aboutsummaryrefslogtreecommitdiff
path: root/drivers/pcmcia
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/Kconfig42
-rw-r--r--drivers/pcmcia/Makefile26
-rw-r--r--drivers/pcmcia/at91_cf.c223
-rw-r--r--drivers/pcmcia/au1000_generic.c548
-rw-r--r--drivers/pcmcia/au1000_generic.h137
-rw-r--r--drivers/pcmcia/au1000_pb1x00.c297
-rw-r--r--drivers/pcmcia/bcm63xx_pcmcia.c14
-rw-r--r--drivers/pcmcia/bfin_cf_pcmcia.c23
-rw-r--r--drivers/pcmcia/cardbus.c28
-rw-r--r--drivers/pcmcia/cistpl.c12
-rw-r--r--drivers/pcmcia/cs.c116
-rw-r--r--drivers/pcmcia/cs_internal.h69
-rw-r--r--drivers/pcmcia/db1xxx_ss.c53
-rw-r--r--drivers/pcmcia/ds.c308
-rw-r--r--drivers/pcmcia/electra_cf.c29
-rw-r--r--drivers/pcmcia/i82092.c32
-rw-r--r--drivers/pcmcia/i82365.c3
-rw-r--r--drivers/pcmcia/m32r_cfc.c3
-rw-r--r--drivers/pcmcia/m32r_cfc.h2
-rw-r--r--drivers/pcmcia/m32r_pcc.c3
-rw-r--r--drivers/pcmcia/m32r_pcc.h2
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c167
-rw-r--r--drivers/pcmcia/o2micro.h4
-rw-r--r--drivers/pcmcia/omap_cf.c4
-rw-r--r--drivers/pcmcia/pcmcia_cis.c118
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c1077
-rw-r--r--drivers/pcmcia/pcmcia_resource.c741
-rw-r--r--drivers/pcmcia/pd6729.c45
-rw-r--r--drivers/pcmcia/pd6729.h2
-rw-r--r--drivers/pcmcia/pxa2xx_balloon3.c140
-rw-r--r--drivers/pcmcia/pxa2xx_base.c89
-rw-r--r--drivers/pcmcia/pxa2xx_base.h1
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x255.c51
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x270.c36
-rw-r--r--drivers/pcmcia/pxa2xx_cm_x2xx.c3
-rw-r--r--drivers/pcmcia/pxa2xx_colibri.c169
-rw-r--r--drivers/pcmcia/pxa2xx_e740.c68
-rw-r--r--drivers/pcmcia/pxa2xx_hx4700.c121
-rw-r--r--drivers/pcmcia/pxa2xx_mainstone.c41
-rw-r--r--drivers/pcmcia/pxa2xx_palmld.c59
-rw-r--r--drivers/pcmcia/pxa2xx_palmtc.c92
-rw-r--r--drivers/pcmcia/pxa2xx_palmtx.c74
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c37
-rw-r--r--drivers/pcmcia/pxa2xx_stargate2.c62
-rw-r--r--drivers/pcmcia/pxa2xx_trizeps4.c68
-rw-r--r--drivers/pcmcia/pxa2xx_viper.c64
-rw-r--r--drivers/pcmcia/pxa2xx_vpac270.c147
-rw-r--r--drivers/pcmcia/rsrc_iodyn.c15
-rw-r--r--drivers/pcmcia/rsrc_mgr.c7
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c34
-rw-r--r--drivers/pcmcia/sa1100_assabet.c65
-rw-r--r--drivers/pcmcia/sa1100_cerf.c54
-rw-r--r--drivers/pcmcia/sa1100_generic.c5
-rw-r--r--drivers/pcmcia/sa1100_generic.h1
-rw-r--r--drivers/pcmcia/sa1100_h3600.c96
-rw-r--r--drivers/pcmcia/sa1100_nanoengine.c133
-rw-r--r--drivers/pcmcia/sa1100_shannon.c59
-rw-r--r--drivers/pcmcia/sa1100_simpad.c66
-rw-r--r--drivers/pcmcia/sa1111_badge4.c (renamed from drivers/pcmcia/sa1100_badge4.c)3
-rw-r--r--drivers/pcmcia/sa1111_generic.c118
-rw-r--r--drivers/pcmcia/sa1111_generic.h1
-rw-r--r--drivers/pcmcia/sa1111_jornada720.c (renamed from drivers/pcmcia/sa1100_jornada720.c)10
-rw-r--r--drivers/pcmcia/sa1111_lubbock.c (renamed from drivers/pcmcia/pxa2xx_lubbock.c)4
-rw-r--r--drivers/pcmcia/sa1111_neponset.c (renamed from drivers/pcmcia/sa1100_neponset.c)18
-rw-r--r--drivers/pcmcia/sa11xx_base.c11
-rw-r--r--drivers/pcmcia/soc_common.c345
-rw-r--r--drivers/pcmcia/soc_common.h28
-rw-r--r--drivers/pcmcia/socket_sysfs.c3
-rw-r--r--drivers/pcmcia/tcic.c3
-rw-r--r--drivers/pcmcia/ti113x.h2
-rw-r--r--drivers/pcmcia/vrc4171_card.c9
-rw-r--r--drivers/pcmcia/vrc4173_cardu.c73
-rw-r--r--drivers/pcmcia/xxs1500_ss.c24
-rw-r--r--drivers/pcmcia/yenta_socket.c78
74 files changed, 2292 insertions, 4423 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index d0f5ad30607..0c657d6af03 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -4,7 +4,6 @@
menuconfig PCCARD
tristate "PCCard (PCMCIA/CardBus) support"
- depends on HOTPLUG
---help---
Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
computer. These are credit-card size devices such as network cards,
@@ -36,8 +35,8 @@ config PCMCIA
If unsure, say Y.
config PCMCIA_LOAD_CIS
- bool "Load CIS updates from userspace (EXPERIMENTAL)"
- depends on PCMCIA && EXPERIMENTAL
+ bool "Load CIS updates from userspace"
+ depends on PCMCIA
select FW_LOADER
default y
help
@@ -69,7 +68,7 @@ comment "PC-card bridges"
config YENTA
tristate "CardBus yenta-compatible bridge support"
depends on PCI
- select CARDBUS if !EMBEDDED
+ select CARDBUS if !EXPERT
select PCCARD_NONSTATIC if PCMCIA != n
---help---
This option enables support for CardBus host bridges. Virtually
@@ -84,27 +83,27 @@ config YENTA
config YENTA_O2
default y
- bool "Special initialization for O2Micro bridges" if EMBEDDED
+ bool "Special initialization for O2Micro bridges" if EXPERT
depends on YENTA
config YENTA_RICOH
default y
- bool "Special initialization for Ricoh bridges" if EMBEDDED
+ bool "Special initialization for Ricoh bridges" if EXPERT
depends on YENTA
config YENTA_TI
default y
- bool "Special initialization for TI and EnE bridges" if EMBEDDED
+ bool "Special initialization for TI and EnE bridges" if EXPERT
depends on YENTA
config YENTA_ENE_TUNE
default y
- bool "Auto-tune EnE bridges for CB cards" if EMBEDDED
+ bool "Auto-tune EnE bridges for CB cards" if EXPERT
depends on YENTA_TI && CARDBUS
config YENTA_TOSHIBA
default y
- bool "Special initialization for Toshiba ToPIC bridges" if EMBEDDED
+ bool "Special initialization for Toshiba ToPIC bridges" if EXPERT
depends on YENTA
config PD6729
@@ -155,18 +154,14 @@ config PCMCIA_M8XX
This driver is also available as a module called m8xx_pcmcia.
-config PCMCIA_AU1X00
- tristate "Au1x00 pcmcia support"
- depends on SOC_AU1X00 && PCMCIA
-
config PCMCIA_ALCHEMY_DEVBOARD
tristate "Alchemy Db/Pb1xxx PCMCIA socket services"
- depends on SOC_AU1X00 && PCMCIA
+ depends on MIPS_ALCHEMY && PCMCIA
select 64BIT_PHYS_ADDR
help
Enable this driver of you want PCMCIA support on your Alchemy
- Db1000, Db/Pb1100, Db/Pb1500, Db/Pb1550, Db/Pb1200 board.
- NOT suitable for the PB1000!
+ Db1000, Db/Pb1100, Db/Pb1500, Db/Pb1550, Db/Pb1200, DB1300
+ board. NOT suitable for the PB1000!
This driver is also available as a module called db1xxx_ss.ko
@@ -187,10 +182,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)/
@@ -200,8 +199,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
@@ -215,7 +215,9 @@ config PCMCIA_PXA2XX
depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
|| MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \
|| ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \
- || MACH_VPAC270)
+ || MACH_VPAC270 || MACH_BALLOON3 || MACH_COLIBRI \
+ || MACH_COLIBRI320 || MACH_H4700)
+ select PCMCIA_SA1111 if ARCH_LUBBOCK && SA1111
select PCMCIA_SOC_COMMON
help
Say Y here to include support for the PXA2xx PCMCIA controller
@@ -240,7 +242,7 @@ config PCMCIA_DEBUG
config PCMCIA_PROBE
bool
- default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X && !PARISC
+ default y if ISA && !ARCH_SA1100 && !PARISC
config M32R_PCC
bool "M32R PCMCIA I/F"
@@ -285,7 +287,7 @@ config BFIN_CFPCMCIA
config AT91_CF
tristate "AT91 CompactFlash Controller"
- depends on PCMCIA && ARCH_AT91RM9200
+ depends on PCMCIA && ARCH_AT91
help
Say Y here to support the CompactFlash controller on AT91 chips.
Or choose M to compile the driver as a module named "at91_cf".
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index d006e8beab9..7745b512a87 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -7,7 +7,6 @@ pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
obj-$(CONFIG_PCCARD) += pcmcia_core.o
pcmcia-y += ds.o pcmcia_resource.o cistpl.o pcmcia_cis.o
-pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o
obj-$(CONFIG_PCMCIA) += pcmcia.o
pcmcia_rsrc-y += rsrc_mgr.o
@@ -26,11 +25,11 @@ 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_AU1X00) += au1x00_ss.o
obj-$(CONFIG_PCMCIA_BCM63XX) += bcm63xx_pcmcia.o
obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o
obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
@@ -40,25 +39,22 @@ obj-$(CONFIG_AT91_CF) += at91_cf.o
obj-$(CONFIG_ELECTRA_CF) += electra_cf.o
obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o
-au1x00_ss-y += au1000_generic.o
-au1x00_ss-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o
-
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_CERF) += sa1100_cerf.o
-sa1100_cs-$(CONFIG_SA1100_COLLIE) += pxa2xx_sharpsl.o
+sa1100_cs-$(CONFIG_SA1100_COLLIE) += pxa2xx_sharpsl.o
sa1100_cs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
+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
@@ -70,6 +66,10 @@ pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o
pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o
pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o
pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o
+pxa2xx-obj-$(CONFIG_MACH_BALLOON3) += pxa2xx_balloon3.o
+pxa2xx-obj-$(CONFIG_MACH_COLIBRI) += pxa2xx_colibri.o
+pxa2xx-obj-$(CONFIG_MACH_COLIBRI320) += pxa2xx_colibri.o
+pxa2xx-obj-$(CONFIG_MACH_H4700) += pxa2xx_hx4700.o
obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y)
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index fb33fa42d24..de24232c519 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -16,16 +16,18 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/platform_data/atmel.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include <pcmcia/ss.h>
-#include <mach/hardware.h>
-#include <asm/io.h>
-#include <asm/sizes.h>
-#include <asm/gpio.h>
-
-#include <mach/board.h>
#include <mach/at91rm9200_mc.h>
+#include <mach/at91_ramc.h>
/*
@@ -40,8 +42,6 @@
/*--------------------------------------------------------------------------*/
-static const char driver_name[] = "at91_cf";
-
struct at91_cf_socket {
struct pcmcia_socket socket;
@@ -69,13 +69,13 @@ static irqreturn_t at91_cf_irq(int irq, void *_cf)
{
struct at91_cf_socket *cf = _cf;
- if (irq == cf->board->det_pin) {
+ if (irq == gpio_to_irq(cf->board->det_pin)) {
unsigned present = at91_cf_present(cf);
/* kick pccard as needed */
if (present != cf->present) {
cf->present = present;
- pr_debug("%s: card %s\n", driver_name,
+ dev_dbg(&cf->pdev->dev, "card %s\n",
present ? "present" : "gone");
pcmcia_parse_events(&cf->socket, SS_DETECT);
}
@@ -95,13 +95,13 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
/* NOTE: CF is always 3VCARD */
if (at91_cf_present(cf)) {
- int rdy = cf->board->irq_pin; /* RDY/nIRQ */
- int vcc = cf->board->vcc_pin;
+ int rdy = gpio_is_valid(cf->board->irq_pin); /* RDY/nIRQ */
+ int vcc = gpio_is_valid(cf->board->vcc_pin);
*sp = SS_DETECT | SS_3VCARD;
- if (!rdy || gpio_get_value(rdy))
+ if (!rdy || gpio_get_value(cf->board->irq_pin))
*sp |= SS_READY;
- if (!vcc || gpio_get_value(vcc))
+ if (!vcc || gpio_get_value(cf->board->vcc_pin))
*sp |= SS_POWERON;
} else
*sp = 0;
@@ -117,24 +117,24 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
cf = container_of(sock, struct at91_cf_socket, socket);
/* switch Vcc if needed and possible */
- if (cf->board->vcc_pin) {
+ if (gpio_is_valid(cf->board->vcc_pin)) {
switch (s->Vcc) {
- case 0:
- gpio_set_value(cf->board->vcc_pin, 0);
- break;
- case 33:
- gpio_set_value(cf->board->vcc_pin, 1);
- break;
- default:
- return -EINVAL;
+ case 0:
+ gpio_set_value(cf->board->vcc_pin, 0);
+ break;
+ case 33:
+ gpio_set_value(cf->board->vcc_pin, 1);
+ break;
+ default:
+ return -EINVAL;
}
}
/* toggle reset if needed */
gpio_set_value(cf->board->rst_pin, s->flags & SS_RESET);
- pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
- driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+ dev_dbg(&cf->pdev->dev, "Vcc %d, io_irq %d, flags %04x csc %04x\n",
+ s->Vcc, s->io_irq, s->flags, s->csc_mask);
return 0;
}
@@ -156,7 +156,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
@@ -170,12 +170,12 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
*/
if (!(io->flags & (MAP_16BIT | MAP_AUTOSZ))) {
csr |= AT91_SMC_DBW_8;
- pr_debug("%s: 8bit i/o bus\n", driver_name);
+ dev_dbg(&cf->pdev->dev, "8bit i/o bus\n");
} else {
csr |= AT91_SMC_DBW_16;
- pr_debug("%s: 16bit i/o bus\n", driver_name);
+ dev_dbg(&cf->pdev->dev, "16bit i/o bus\n");
}
- 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;
@@ -214,21 +214,60 @@ static struct pccard_operations at91_cf_ops = {
/*--------------------------------------------------------------------------*/
-static int __init at91_cf_probe(struct platform_device *pdev)
+#if defined(CONFIG_OF)
+static const struct of_device_id at91_cf_dt_ids[] = {
+ { .compatible = "atmel,at91rm9200-cf" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, at91_cf_dt_ids);
+
+static int at91_cf_dt_init(struct platform_device *pdev)
+{
+ struct at91_cf_data *board;
+
+ board = devm_kzalloc(&pdev->dev, sizeof(*board), GFP_KERNEL);
+ if (!board)
+ return -ENOMEM;
+
+ board->irq_pin = of_get_gpio(pdev->dev.of_node, 0);
+ board->det_pin = of_get_gpio(pdev->dev.of_node, 1);
+ board->vcc_pin = of_get_gpio(pdev->dev.of_node, 2);
+ board->rst_pin = of_get_gpio(pdev->dev.of_node, 3);
+
+ pdev->dev.platform_data = board;
+
+ return 0;
+}
+#else
+static int at91_cf_dt_init(struct platform_device *pdev)
+{
+ return -ENODEV;
+}
+#endif
+
+static int at91_cf_probe(struct platform_device *pdev)
{
struct at91_cf_socket *cf;
struct at91_cf_data *board = pdev->dev.platform_data;
struct resource *io;
int status;
- if (!board || !board->det_pin || !board->rst_pin)
+ if (!board) {
+ status = at91_cf_dt_init(pdev);
+ if (status)
+ return status;
+
+ board = pdev->dev.platform_data;
+ }
+
+ if (!gpio_is_valid(board->det_pin) || !gpio_is_valid(board->rst_pin))
return -ENODEV;
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!io)
return -ENODEV;
- cf = kzalloc(sizeof *cf, GFP_KERNEL);
+ cf = devm_kzalloc(&pdev->dev, sizeof(*cf), GFP_KERNEL);
if (!cf)
return -ENOMEM;
@@ -238,22 +277,25 @@ static int __init at91_cf_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, cf);
/* must be a GPIO; ergo must trigger on both edges */
- status = gpio_request(board->det_pin, "cf_det");
+ status = devm_gpio_request(&pdev->dev, board->det_pin, "cf_det");
if (status < 0)
- goto fail0;
- status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf);
+ return status;
+
+ status = devm_request_irq(&pdev->dev, gpio_to_irq(board->det_pin),
+ at91_cf_irq, 0, "at91_cf detect", cf);
if (status < 0)
- goto fail00;
+ return status;
+
device_init_wakeup(&pdev->dev, 1);
- status = gpio_request(board->rst_pin, "cf_rst");
+ status = devm_gpio_request(&pdev->dev, board->rst_pin, "cf_rst");
if (status < 0)
goto fail0a;
- if (board->vcc_pin) {
- status = gpio_request(board->vcc_pin, "cf_vcc");
+ if (gpio_is_valid(board->vcc_pin)) {
+ status = devm_gpio_request(&pdev->dev, board->vcc_pin, "cf_vcc");
if (status < 0)
- goto fail0b;
+ goto fail0a;
}
/*
@@ -262,35 +304,35 @@ static int __init at91_cf_probe(struct platform_device *pdev)
* unless we report that we handle everything (sigh).
* (Note: DK board doesn't wire the IRQ pin...)
*/
- if (board->irq_pin) {
- status = gpio_request(board->irq_pin, "cf_irq");
+ if (gpio_is_valid(board->irq_pin)) {
+ status = devm_gpio_request(&pdev->dev, board->irq_pin, "cf_irq");
if (status < 0)
- goto fail0c;
- status = request_irq(board->irq_pin, at91_cf_irq,
- IRQF_SHARED, driver_name, cf);
+ goto fail0a;
+
+ status = devm_request_irq(&pdev->dev, gpio_to_irq(board->irq_pin),
+ at91_cf_irq, IRQF_SHARED, "at91_cf", cf);
if (status < 0)
- goto fail0d;
- cf->socket.pci_irq = board->irq_pin;
+ goto fail0a;
+ cf->socket.pci_irq = gpio_to_irq(board->irq_pin);
} else
cf->socket.pci_irq = nr_irqs + 1;
/* pcmcia layer only remaps "real" memory not iospace */
- cf->socket.io_offset = (unsigned long)
- ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
+ cf->socket.io_offset = (unsigned long) devm_ioremap(&pdev->dev,
+ cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
if (!cf->socket.io_offset) {
status = -ENXIO;
- goto fail1;
+ goto fail0a;
}
/* reserve chip-select regions */
- if (!request_mem_region(io->start, io->end + 1 - io->start,
- driver_name)) {
+ if (!devm_request_mem_region(&pdev->dev, io->start, resource_size(io), "at91_cf")) {
status = -ENXIO;
- goto fail1;
+ goto fail0a;
}
- pr_info("%s: irqs det #%d, io #%d\n", driver_name,
- board->det_pin, board->irq_pin);
+ dev_info(&pdev->dev, "irqs det #%d, io #%d\n",
+ gpio_to_irq(board->det_pin), gpio_to_irq(board->irq_pin));
cf->socket.owner = THIS_MODULE;
cf->socket.dev.parent = &pdev->dev;
@@ -303,55 +345,22 @@ static int __init at91_cf_probe(struct platform_device *pdev)
status = pcmcia_register_socket(&cf->socket);
if (status < 0)
- goto fail2;
+ goto fail0a;
return 0;
-fail2:
- release_mem_region(io->start, io->end + 1 - io->start);
-fail1:
- if (cf->socket.io_offset)
- iounmap((void __iomem *) cf->socket.io_offset);
- if (board->irq_pin) {
- free_irq(board->irq_pin, cf);
-fail0d:
- gpio_free(board->irq_pin);
- }
-fail0c:
- if (board->vcc_pin)
- gpio_free(board->vcc_pin);
-fail0b:
- gpio_free(board->rst_pin);
fail0a:
device_init_wakeup(&pdev->dev, 0);
- free_irq(board->det_pin, cf);
-fail00:
- gpio_free(board->det_pin);
-fail0:
- kfree(cf);
return status;
}
-static int __exit at91_cf_remove(struct platform_device *pdev)
+static int at91_cf_remove(struct platform_device *pdev)
{
struct at91_cf_socket *cf = platform_get_drvdata(pdev);
- struct at91_cf_data *board = cf->board;
- struct resource *io = cf->socket.io[0].res;
pcmcia_unregister_socket(&cf->socket);
- release_mem_region(io->start, io->end + 1 - io->start);
- iounmap((void __iomem *) cf->socket.io_offset);
- if (board->irq_pin) {
- free_irq(board->irq_pin, cf);
- gpio_free(board->irq_pin);
- }
- if (board->vcc_pin)
- gpio_free(board->vcc_pin);
- gpio_free(board->rst_pin);
device_init_wakeup(&pdev->dev, 0);
- free_irq(board->det_pin, cf);
- gpio_free(board->det_pin);
- kfree(cf);
+
return 0;
}
@@ -363,9 +372,9 @@ static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
struct at91_cf_data *board = cf->board;
if (device_may_wakeup(&pdev->dev)) {
- enable_irq_wake(board->det_pin);
- if (board->irq_pin)
- enable_irq_wake(board->irq_pin);
+ enable_irq_wake(gpio_to_irq(board->det_pin));
+ if (gpio_is_valid(board->irq_pin))
+ enable_irq_wake(gpio_to_irq(board->irq_pin));
}
return 0;
}
@@ -376,9 +385,9 @@ static int at91_cf_resume(struct platform_device *pdev)
struct at91_cf_data *board = cf->board;
if (device_may_wakeup(&pdev->dev)) {
- disable_irq_wake(board->det_pin);
- if (board->irq_pin)
- disable_irq_wake(board->irq_pin);
+ disable_irq_wake(gpio_to_irq(board->det_pin));
+ if (gpio_is_valid(board->irq_pin))
+ disable_irq_wake(gpio_to_irq(board->irq_pin));
}
return 0;
@@ -391,27 +400,17 @@ static int at91_cf_resume(struct platform_device *pdev)
static struct platform_driver at91_cf_driver = {
.driver = {
- .name = (char *) driver_name,
+ .name = "at91_cf",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(at91_cf_dt_ids),
},
- .remove = __exit_p(at91_cf_remove),
+ .probe = at91_cf_probe,
+ .remove = at91_cf_remove,
.suspend = at91_cf_suspend,
.resume = at91_cf_resume,
};
-/*--------------------------------------------------------------------------*/
-
-static int __init at91_cf_init(void)
-{
- return platform_driver_probe(&at91_cf_driver, at91_cf_probe);
-}
-module_init(at91_cf_init);
-
-static void __exit at91_cf_exit(void)
-{
- platform_driver_unregister(&at91_cf_driver);
-}
-module_exit(at91_cf_exit);
+module_platform_driver(at91_cf_driver);
MODULE_DESCRIPTION("AT91 Compact Flash Driver");
MODULE_AUTHOR("David Brownell");
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
deleted file mode 100644
index 88c4c409878..00000000000
--- a/drivers/pcmcia/au1000_generic.c
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- *
- * Alchemy Semi Au1000 pcmcia driver
- *
- * Copyright 2001-2003 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@embeddedalley.com or source@mvista.com
- *
- * Copyright 2004 Pete Popov, Embedded Alley Solutions, Inc.
- * Updated the driver to 2.6. Followed the sa11xx API and largely
- * copied many of the hardware independent functions.
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * ########################################################################
- *
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/notifier.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#include <asm/mach-au1x00/au1000.h>
-#include "au1000_generic.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Pete Popov <ppopov@embeddedalley.com>");
-MODULE_DESCRIPTION("Linux PCMCIA Card Services: Au1x00 Socket Controller");
-
-#if 0
-#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
-#else
-#define debug(x,args...)
-#endif
-
-#define MAP_SIZE 0x100000
-extern struct au1000_pcmcia_socket au1000_pcmcia_socket[];
-#define PCMCIA_SOCKET(x) (au1000_pcmcia_socket + (x))
-#define to_au1000_socket(x) container_of(x, struct au1000_pcmcia_socket, socket)
-
-/* Some boards like to support CF cards as IDE root devices, so they
- * grab pcmcia sockets directly.
- */
-u32 *pcmcia_base_vaddrs[2];
-extern const unsigned long mips_io_port_base;
-
-static DEFINE_MUTEX(pcmcia_sockets_lock);
-
-static int (*au1x00_pcmcia_hw_init[])(struct device *dev) = {
- au1x_board_init,
-};
-
-static int
-au1x00_pcmcia_skt_state(struct au1000_pcmcia_socket *skt)
-{
- struct pcmcia_state state;
- unsigned int stat;
-
- memset(&state, 0, sizeof(struct pcmcia_state));
-
- skt->ops->socket_state(skt, &state);
-
- stat = state.detect ? SS_DETECT : 0;
- stat |= state.ready ? SS_READY : 0;
- stat |= state.wrprot ? SS_WRPROT : 0;
- stat |= state.vs_3v ? SS_3VCARD : 0;
- stat |= state.vs_Xv ? SS_XVCARD : 0;
- stat |= skt->cs_state.Vcc ? SS_POWERON : 0;
-
- if (skt->cs_state.flags & SS_IOCARD)
- stat |= state.bvd1 ? SS_STSCHG : 0;
- else {
- if (state.bvd1 == 0)
- stat |= SS_BATDEAD;
- else if (state.bvd2 == 0)
- stat |= SS_BATWARN;
- }
- return stat;
-}
-
-/*
- * au100_pcmcia_config_skt
- *
- * Convert PCMCIA socket state to our socket configure structure.
- */
-static int
-au1x00_pcmcia_config_skt(struct au1000_pcmcia_socket *skt, socket_state_t *state)
-{
- int ret;
-
- ret = skt->ops->configure_socket(skt, state);
- if (ret == 0) {
- skt->cs_state = *state;
- }
-
- if (ret < 0)
- debug("unable to configure socket %d\n", skt->nr);
-
- return ret;
-}
-
-/* au1x00_pcmcia_sock_init()
- *
- * (Re-)Initialise the socket, turning on status interrupts
- * and PCMCIA bus. This must wait for power to stabilise
- * so that the card status signals report correctly.
- *
- * Returns: 0
- */
-static int au1x00_pcmcia_sock_init(struct pcmcia_socket *sock)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
-
- debug("initializing socket %u\n", skt->nr);
-
- skt->ops->socket_init(skt);
- return 0;
-}
-
-/*
- * au1x00_pcmcia_suspend()
- *
- * Remove power on the socket, disable IRQs from the card.
- * Turn off status interrupts, and disable the PCMCIA bus.
- *
- * Returns: 0
- */
-static int au1x00_pcmcia_suspend(struct pcmcia_socket *sock)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
-
- debug("suspending socket %u\n", skt->nr);
-
- skt->ops->socket_suspend(skt);
-
- return 0;
-}
-
-static DEFINE_SPINLOCK(status_lock);
-
-/*
- * au1x00_check_status()
- */
-static void au1x00_check_status(struct au1000_pcmcia_socket *skt)
-{
- unsigned int events;
-
- debug("entering PCMCIA monitoring thread\n");
-
- do {
- unsigned int status;
- unsigned long flags;
-
- status = au1x00_pcmcia_skt_state(skt);
-
- spin_lock_irqsave(&status_lock, flags);
- events = (status ^ skt->status) & skt->cs_state.csc_mask;
- skt->status = status;
- spin_unlock_irqrestore(&status_lock, flags);
-
- debug("events: %s%s%s%s%s%s\n",
- events == 0 ? "<NONE>" : "",
- events & SS_DETECT ? "DETECT " : "",
- events & SS_READY ? "READY " : "",
- events & SS_BATDEAD ? "BATDEAD " : "",
- events & SS_BATWARN ? "BATWARN " : "",
- events & SS_STSCHG ? "STSCHG " : "");
-
- if (events)
- pcmcia_parse_events(&skt->socket, events);
- } while (events);
-}
-
-/*
- * au1x00_pcmcia_poll_event()
- * Let's poll for events in addition to IRQs since IRQ only is unreliable...
- */
-static void au1x00_pcmcia_poll_event(unsigned long dummy)
-{
- struct au1000_pcmcia_socket *skt = (struct au1000_pcmcia_socket *)dummy;
- debug("polling for events\n");
-
- mod_timer(&skt->poll_timer, jiffies + AU1000_PCMCIA_POLL_PERIOD);
-
- au1x00_check_status(skt);
-}
-
-/* au1x00_pcmcia_get_status()
- *
- * From the sa11xx_core.c:
- * Implements the get_status() operation for the in-kernel PCMCIA
- * service (formerly SS_GetStatus in Card Services). Essentially just
- * fills in bits in `status' according to internal driver state or
- * the value of the voltage detect chipselect register.
- *
- * As a debugging note, during card startup, the PCMCIA core issues
- * three set_socket() commands in a row the first with RESET deasserted,
- * the second with RESET asserted, and the last with RESET deasserted
- * again. Following the third set_socket(), a get_status() command will
- * be issued. The kernel is looking for the SS_READY flag (see
- * setup_socket(), reset_socket(), and unreset_socket() in cs.c).
- *
- * Returns: 0
- */
-static int
-au1x00_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
-
- skt->status = au1x00_pcmcia_skt_state(skt);
- *status = skt->status;
-
- return 0;
-}
-
-/* au1x00_pcmcia_set_socket()
- * Implements the set_socket() operation for the in-kernel PCMCIA
- * service (formerly SS_SetSocket in Card Services). We more or
- * less punt all of this work and let the kernel handle the details
- * of power configuration, reset, &c. We also record the value of
- * `state' in order to regurgitate it to the PCMCIA core later.
- *
- * Returns: 0
- */
-static int
-au1x00_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
-
- debug("for sock %u\n", skt->nr);
-
- debug("\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n",
- (state->csc_mask==0)?"<NONE>":"",
- (state->csc_mask&SS_DETECT)?"DETECT ":"",
- (state->csc_mask&SS_READY)?"READY ":"",
- (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
- (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
- (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
- (state->flags==0)?"<NONE>":"",
- (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
- (state->flags&SS_IOCARD)?"IOCARD ":"",
- (state->flags&SS_RESET)?"RESET ":"",
- (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
- (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"");
- debug("\tVcc %d Vpp %d irq %d\n",
- state->Vcc, state->Vpp, state->io_irq);
-
- return au1x00_pcmcia_config_skt(skt, state);
-}
-
-int
-au1x00_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
- unsigned int speed;
-
- if(map->map>=MAX_IO_WIN){
- debug("map (%d) out of range\n", map->map);
- return -1;
- }
-
- if(map->flags&MAP_ACTIVE){
- speed=(map->speed>0)?map->speed:AU1000_PCMCIA_IO_SPEED;
- skt->spd_io[map->map] = speed;
- }
-
- map->start=(unsigned int)(u32)skt->virt_io;
- map->stop=map->start+MAP_SIZE;
- return 0;
-
-} /* au1x00_pcmcia_set_io_map() */
-
-
-static int
-au1x00_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
- unsigned short speed = map->speed;
-
- if(map->map>=MAX_WIN){
- debug("map (%d) out of range\n", map->map);
- return -1;
- }
-
- if (map->flags & MAP_ATTRIB) {
- skt->spd_attr[map->map] = speed;
- skt->spd_mem[map->map] = 0;
- } else {
- skt->spd_attr[map->map] = 0;
- skt->spd_mem[map->map] = speed;
- }
-
- if (map->flags & MAP_ATTRIB) {
- map->static_start = skt->phys_attr + map->card_start;
- }
- else {
- map->static_start = skt->phys_mem + map->card_start;
- }
-
- debug("set_mem_map %d start %08lx card_start %08x\n",
- map->map, map->static_start, map->card_start);
- return 0;
-
-} /* au1x00_pcmcia_set_mem_map() */
-
-static struct pccard_operations au1x00_pcmcia_operations = {
- .init = au1x00_pcmcia_sock_init,
- .suspend = au1x00_pcmcia_suspend,
- .get_status = au1x00_pcmcia_get_status,
- .set_socket = au1x00_pcmcia_set_socket,
- .set_io_map = au1x00_pcmcia_set_io_map,
- .set_mem_map = au1x00_pcmcia_set_mem_map,
-};
-
-static const char *skt_names[] = {
- "PCMCIA socket 0",
- "PCMCIA socket 1",
-};
-
-struct skt_dev_info {
- int nskt;
-};
-
-int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
-{
- struct skt_dev_info *sinfo;
- struct au1000_pcmcia_socket *skt;
- int ret, i;
-
- sinfo = kzalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
- if (!sinfo) {
- ret = -ENOMEM;
- goto out;
- }
-
- sinfo->nskt = nr;
-
- /*
- * Initialise the per-socket structure.
- */
- for (i = 0; i < nr; i++) {
- skt = PCMCIA_SOCKET(i);
- memset(skt, 0, sizeof(*skt));
-
- skt->socket.resource_ops = &pccard_static_ops;
- skt->socket.ops = &au1x00_pcmcia_operations;
- skt->socket.owner = ops->owner;
- skt->socket.dev.parent = dev;
-
- init_timer(&skt->poll_timer);
- skt->poll_timer.function = au1x00_pcmcia_poll_event;
- skt->poll_timer.data = (unsigned long)skt;
- skt->poll_timer.expires = jiffies + AU1000_PCMCIA_POLL_PERIOD;
-
- skt->nr = first + i;
- skt->irq = 255;
- skt->dev = dev;
- skt->ops = ops;
-
- skt->res_skt.name = skt_names[skt->nr];
- skt->res_io.name = "io";
- skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- skt->res_mem.name = "memory";
- skt->res_mem.flags = IORESOURCE_MEM;
- skt->res_attr.name = "attribute";
- skt->res_attr.flags = IORESOURCE_MEM;
-
- /*
- * PCMCIA client drivers use the inb/outb macros to access the
- * IO registers. Since mips_io_port_base is added to the
- * access address of the mips implementation of inb/outb,
- * we need to subtract it here because we want to access the
- * I/O or MEM address directly, without going through this
- * "mips_io_port_base" mechanism.
- */
- if (i == 0) {
- skt->virt_io = (void *)
- (ioremap((phys_t)AU1X_SOCK0_IO, 0x1000) -
- (u32)mips_io_port_base);
- skt->phys_attr = AU1X_SOCK0_PHYS_ATTR;
- skt->phys_mem = AU1X_SOCK0_PHYS_MEM;
- }
- else {
- skt->virt_io = (void *)
- (ioremap((phys_t)AU1X_SOCK1_IO, 0x1000) -
- (u32)mips_io_port_base);
- skt->phys_attr = AU1X_SOCK1_PHYS_ATTR;
- skt->phys_mem = AU1X_SOCK1_PHYS_MEM;
- }
- pcmcia_base_vaddrs[i] = (u32 *)skt->virt_io;
- ret = ops->hw_init(skt);
-
- skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
- skt->socket.irq_mask = 0;
- skt->socket.map_size = MAP_SIZE;
- skt->socket.pci_irq = skt->irq;
- skt->socket.io_offset = (unsigned long)skt->virt_io;
-
- skt->status = au1x00_pcmcia_skt_state(skt);
-
- ret = pcmcia_register_socket(&skt->socket);
- if (ret)
- goto out_err;
-
- WARN_ON(skt->socket.sock != i);
-
- add_timer(&skt->poll_timer);
- }
-
- dev_set_drvdata(dev, sinfo);
- return 0;
-
-
-out_err:
- flush_scheduled_work();
- ops->hw_shutdown(skt);
- while (i-- > 0) {
- skt = PCMCIA_SOCKET(i);
-
- del_timer_sync(&skt->poll_timer);
- pcmcia_unregister_socket(&skt->socket);
- flush_scheduled_work();
- if (i == 0) {
- iounmap(skt->virt_io + (u32)mips_io_port_base);
- skt->virt_io = NULL;
- }
-#ifndef CONFIG_MIPS_XXS1500
- else {
- iounmap(skt->virt_io + (u32)mips_io_port_base);
- skt->virt_io = NULL;
- }
-#endif
- ops->hw_shutdown(skt);
-
- }
- kfree(sinfo);
-out:
- return ret;
-}
-
-int au1x00_drv_pcmcia_remove(struct platform_device *dev)
-{
- struct skt_dev_info *sinfo = platform_get_drvdata(dev);
- int i;
-
- mutex_lock(&pcmcia_sockets_lock);
- platform_set_drvdata(dev, NULL);
-
- for (i = 0; i < sinfo->nskt; i++) {
- struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i);
-
- del_timer_sync(&skt->poll_timer);
- pcmcia_unregister_socket(&skt->socket);
- flush_scheduled_work();
- skt->ops->hw_shutdown(skt);
- au1x00_pcmcia_config_skt(skt, &dead_socket);
- iounmap(skt->virt_io + (u32)mips_io_port_base);
- skt->virt_io = NULL;
- }
-
- kfree(sinfo);
- mutex_unlock(&pcmcia_sockets_lock);
- return 0;
-}
-
-
-/*
- * PCMCIA "Driver" API
- */
-
-static int au1x00_drv_pcmcia_probe(struct platform_device *dev)
-{
- int i, ret = -ENODEV;
-
- mutex_lock(&pcmcia_sockets_lock);
- for (i=0; i < ARRAY_SIZE(au1x00_pcmcia_hw_init); i++) {
- ret = au1x00_pcmcia_hw_init[i](&dev->dev);
- if (ret == 0)
- break;
- }
- mutex_unlock(&pcmcia_sockets_lock);
- return ret;
-}
-
-static struct platform_driver au1x00_pcmcia_driver = {
- .driver = {
- .name = "au1x00-pcmcia",
- .owner = THIS_MODULE,
- },
- .probe = au1x00_drv_pcmcia_probe,
- .remove = au1x00_drv_pcmcia_remove,
-};
-
-
-/* au1x00_pcmcia_init()
- *
- * This routine performs low-level PCMCIA initialization and then
- * registers this socket driver with Card Services.
- *
- * Returns: 0 on success, -ve error code on failure
- */
-static int __init au1x00_pcmcia_init(void)
-{
- int error = 0;
- error = platform_driver_register(&au1x00_pcmcia_driver);
- return error;
-}
-
-/* au1x00_pcmcia_exit()
- * Invokes the low-level kernel service to free IRQs associated with this
- * socket controller and reset GPIO edge detection.
- */
-static void __exit au1x00_pcmcia_exit(void)
-{
- platform_driver_unregister(&au1x00_pcmcia_driver);
-}
-
-module_init(au1x00_pcmcia_init);
-module_exit(au1x00_pcmcia_exit);
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h
deleted file mode 100644
index a324d329dea..00000000000
--- a/drivers/pcmcia/au1000_generic.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Alchemy Semi Au1000 pcmcia driver include file
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-#ifndef __ASM_AU1000_PCMCIA_H
-#define __ASM_AU1000_PCMCIA_H
-
-/* include the world */
-
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/ss.h>
-#include <pcmcia/cistpl.h>
-#include "cs_internal.h"
-
-#define AU1000_PCMCIA_POLL_PERIOD (2*HZ)
-#define AU1000_PCMCIA_IO_SPEED (255)
-#define AU1000_PCMCIA_MEM_SPEED (300)
-
-#define AU1X_SOCK0_IO 0xF00000000ULL
-#define AU1X_SOCK0_PHYS_ATTR 0xF40000000ULL
-#define AU1X_SOCK0_PHYS_MEM 0xF80000000ULL
-
-/* pcmcia socket 1 needs external glue logic so the memory map
- * differs from board to board.
- */
-#if defined(CONFIG_MIPS_PB1000)
-#define AU1X_SOCK1_IO 0xF08000000ULL
-#define AU1X_SOCK1_PHYS_ATTR 0xF48000000ULL
-#define AU1X_SOCK1_PHYS_MEM 0xF88000000ULL
-#endif
-
-struct pcmcia_state {
- unsigned detect: 1,
- ready: 1,
- wrprot: 1,
- bvd1: 1,
- bvd2: 1,
- vs_3v: 1,
- vs_Xv: 1;
-};
-
-struct pcmcia_configure {
- unsigned sock: 8,
- vcc: 8,
- vpp: 8,
- output: 1,
- speaker: 1,
- reset: 1;
-};
-
-struct pcmcia_irqs {
- int sock;
- int irq;
- const char *str;
-};
-
-
-struct au1000_pcmcia_socket {
- struct pcmcia_socket socket;
-
- /*
- * Info from low level handler
- */
- struct device *dev;
- unsigned int nr;
- unsigned int irq;
-
- /*
- * Core PCMCIA state
- */
- struct pcmcia_low_level *ops;
-
- unsigned int status;
- socket_state_t cs_state;
-
- unsigned short spd_io[MAX_IO_WIN];
- unsigned short spd_mem[MAX_WIN];
- unsigned short spd_attr[MAX_WIN];
-
- struct resource res_skt;
- struct resource res_io;
- struct resource res_mem;
- struct resource res_attr;
-
- void * virt_io;
- unsigned int phys_io;
- unsigned int phys_attr;
- unsigned int phys_mem;
- unsigned short speed_io, speed_attr, speed_mem;
-
- unsigned int irq_state;
-
- struct timer_list poll_timer;
-};
-
-struct pcmcia_low_level {
- struct module *owner;
-
- int (*hw_init)(struct au1000_pcmcia_socket *);
- void (*hw_shutdown)(struct au1000_pcmcia_socket *);
-
- void (*socket_state)(struct au1000_pcmcia_socket *, struct pcmcia_state *);
- int (*configure_socket)(struct au1000_pcmcia_socket *, struct socket_state_t *);
-
- /*
- * Enable card status IRQs on (re-)initialisation. This can
- * be called at initialisation, power management event, or
- * pcmcia event.
- */
- void (*socket_init)(struct au1000_pcmcia_socket *);
-
- /*
- * Disable card status IRQs and PCMCIA bus on suspend.
- */
- void (*socket_suspend)(struct au1000_pcmcia_socket *);
-};
-
-extern int au1x_board_init(struct device *dev);
-
-#endif /* __ASM_AU1000_PCMCIA_H */
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c
deleted file mode 100644
index 5a979cb8f3e..00000000000
--- a/drivers/pcmcia/au1000_pb1x00.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- *
- * Alchemy Semi Pb1000 boards specific pcmcia routines.
- *
- * Copyright 2002 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * ########################################################################
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/proc_fs.h>
-#include <linux/types.h>
-
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/ss.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/bus_ops.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#include <asm/au1000.h>
-#include <asm/au1000_pcmcia.h>
-
-#define debug(fmt, arg...) do { } while (0)
-
-#include <asm/pb1000.h>
-#define PCMCIA_IRQ AU1000_GPIO_15
-
-static int pb1x00_pcmcia_init(struct pcmcia_init *init)
-{
- u16 pcr;
- pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
-
- au_writel(0x8000, PB1000_MDR); /* clear pcmcia interrupt */
- au_sync_delay(100);
- au_writel(0x4000, PB1000_MDR); /* enable pcmcia interrupt */
- au_sync();
-
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1);
- au_writel(pcr, PB1000_PCR);
- au_sync_delay(20);
-
- return PCMCIA_NUM_SOCKS;
-}
-
-static int pb1x00_pcmcia_shutdown(void)
-{
- u16 pcr;
- pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1);
- au_writel(pcr, PB1000_PCR);
- au_sync_delay(20);
- return 0;
-}
-
-static int
-pb1x00_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state)
-{
- u32 inserted0, inserted1;
- u16 vs0, vs1;
-
- vs0 = vs1 = (u16)au_readl(PB1000_ACR1);
- inserted0 = !(vs0 & (ACR1_SLOT_0_CD1 | ACR1_SLOT_0_CD2));
- inserted1 = !(vs1 & (ACR1_SLOT_1_CD1 | ACR1_SLOT_1_CD2));
- vs0 = (vs0 >> 4) & 0x3;
- vs1 = (vs1 >> 12) & 0x3;
-
- state->ready = 0;
- state->vs_Xv = 0;
- state->vs_3v = 0;
- state->detect = 0;
-
- if (sock == 0) {
- if (inserted0) {
- switch (vs0) {
- case 0:
- case 2:
- state->vs_3v=1;
- break;
- case 3: /* 5V */
- break;
- default:
- /* return without setting 'detect' */
- printk(KERN_ERR "pb1x00 bad VS (%d)\n",
- vs0);
- return 0;
- }
- state->detect = 1;
- }
- }
- else {
- if (inserted1) {
- switch (vs1) {
- case 0:
- case 2:
- state->vs_3v=1;
- break;
- case 3: /* 5V */
- break;
- default:
- /* return without setting 'detect' */
- printk(KERN_ERR "pb1x00 bad VS (%d)\n",
- vs1);
- return 0;
- }
- state->detect = 1;
- }
- }
-
- if (state->detect) {
- state->ready = 1;
- }
-
- state->bvd1=1;
- state->bvd2=1;
- state->wrprot=0;
- return 1;
-}
-
-
-static int pb1x00_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
-{
-
- if(info->sock > PCMCIA_MAX_SOCK) return -1;
-
- /*
- * Even in the case of the Pb1000, both sockets are connected
- * to the same irq line.
- */
- info->irq = PCMCIA_IRQ;
-
- return 0;
-}
-
-
-static int
-pb1x00_pcmcia_configure_socket(const struct pcmcia_configure *configure)
-{
- u16 pcr;
-
- if(configure->sock > PCMCIA_MAX_SOCK) return -1;
-
- pcr = au_readl(PB1000_PCR);
-
- if (configure->sock == 0) {
- pcr &= ~(PCR_SLOT_0_VCC0 | PCR_SLOT_0_VCC1 |
- PCR_SLOT_0_VPP0 | PCR_SLOT_0_VPP1);
- }
- else {
- pcr &= ~(PCR_SLOT_1_VCC0 | PCR_SLOT_1_VCC1 |
- PCR_SLOT_1_VPP0 | PCR_SLOT_1_VPP1);
- }
-
- pcr &= ~PCR_SLOT_0_RST;
- debug("Vcc %dV Vpp %dV, pcr %x\n",
- configure->vcc, configure->vpp, pcr);
- switch(configure->vcc){
- case 0: /* Vcc 0 */
- switch(configure->vpp) {
- case 0:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_GND,
- configure->sock);
- break;
- case 12:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_12V,
- configure->sock);
- break;
- case 50:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_5V,
- configure->sock);
- break;
- case 33:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_3V,
- configure->sock);
- break;
- default:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
- configure->sock);
- printk("%s: bad Vcc/Vpp (%d:%d)\n",
- __func__,
- configure->vcc,
- configure->vpp);
- break;
- }
- break;
- case 50: /* Vcc 5V */
- switch(configure->vpp) {
- case 0:
- pcr |= SET_VCC_VPP(VCC_5V,VPP_GND,
- configure->sock);
- break;
- case 50:
- pcr |= SET_VCC_VPP(VCC_5V,VPP_5V,
- configure->sock);
- break;
- case 12:
- pcr |= SET_VCC_VPP(VCC_5V,VPP_12V,
- configure->sock);
- break;
- case 33:
- pcr |= SET_VCC_VPP(VCC_5V,VPP_3V,
- configure->sock);
- break;
- default:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
- configure->sock);
- printk("%s: bad Vcc/Vpp (%d:%d)\n",
- __func__,
- configure->vcc,
- configure->vpp);
- break;
- }
- break;
- case 33: /* Vcc 3.3V */
- switch(configure->vpp) {
- case 0:
- pcr |= SET_VCC_VPP(VCC_3V,VPP_GND,
- configure->sock);
- break;
- case 50:
- pcr |= SET_VCC_VPP(VCC_3V,VPP_5V,
- configure->sock);
- break;
- case 12:
- pcr |= SET_VCC_VPP(VCC_3V,VPP_12V,
- configure->sock);
- break;
- case 33:
- pcr |= SET_VCC_VPP(VCC_3V,VPP_3V,
- configure->sock);
- break;
- default:
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
- configure->sock);
- printk("%s: bad Vcc/Vpp (%d:%d)\n",
- __func__,
- configure->vcc,
- configure->vpp);
- break;
- }
- break;
- default: /* what's this ? */
- pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,configure->sock);
- printk(KERN_ERR "%s: bad Vcc %d\n",
- __func__, configure->vcc);
- break;
- }
-
- if (configure->sock == 0) {
- pcr &= ~(PCR_SLOT_0_RST);
- if (configure->reset)
- pcr |= PCR_SLOT_0_RST;
- }
- else {
- pcr &= ~(PCR_SLOT_1_RST);
- if (configure->reset)
- pcr |= PCR_SLOT_1_RST;
- }
- au_writel(pcr, PB1000_PCR);
- au_sync_delay(300);
-
- return 0;
-}
-
-
-struct pcmcia_low_level pb1x00_pcmcia_ops = {
- pb1x00_pcmcia_init,
- pb1x00_pcmcia_shutdown,
- pb1x00_pcmcia_socket_state,
- pb1x00_pcmcia_get_irq_info,
- pb1x00_pcmcia_configure_socket
-};
diff --git a/drivers/pcmcia/bcm63xx_pcmcia.c b/drivers/pcmcia/bcm63xx_pcmcia.c
index 693577e0fef..0c6aac1232f 100644
--- a/drivers/pcmcia/bcm63xx_pcmcia.c
+++ b/drivers/pcmcia/bcm63xx_pcmcia.c
@@ -323,7 +323,7 @@ static struct pccard_operations bcm63xx_pcmcia_operations = {
/*
* register pcmcia socket to core
*/
-static int __devinit bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
+static int bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
{
struct bcm63xx_pcmcia_socket *skt;
struct pcmcia_socket *sock;
@@ -436,7 +436,7 @@ err:
return ret;
}
-static int __devexit bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
+static int bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
{
struct bcm63xx_pcmcia_socket *skt;
struct resource *res;
@@ -453,7 +453,7 @@ static int __devexit bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
struct platform_driver bcm63xx_pcmcia_driver = {
.probe = bcm63xx_drv_pcmcia_probe,
- .remove = __devexit_p(bcm63xx_drv_pcmcia_remove),
+ .remove = bcm63xx_drv_pcmcia_remove,
.driver = {
.name = "bcm63xx_pcmcia",
.owner = THIS_MODULE,
@@ -461,7 +461,7 @@ struct platform_driver bcm63xx_pcmcia_driver = {
};
#ifdef CONFIG_CARDBUS
-static int __devinit bcm63xx_cb_probe(struct pci_dev *dev,
+static int bcm63xx_cb_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
/* keep pci device */
@@ -469,13 +469,13 @@ static int __devinit bcm63xx_cb_probe(struct pci_dev *dev,
return platform_driver_register(&bcm63xx_pcmcia_driver);
}
-static void __devexit bcm63xx_cb_exit(struct pci_dev *dev)
+static void bcm63xx_cb_exit(struct pci_dev *dev)
{
platform_driver_unregister(&bcm63xx_pcmcia_driver);
bcm63xx_cb_dev = NULL;
}
-static struct pci_device_id bcm63xx_cb_table[] = {
+static DEFINE_PCI_DEVICE_TABLE(bcm63xx_cb_table) = {
{
.vendor = PCI_VENDOR_ID_BROADCOM,
.device = BCM6348_CPU_ID,
@@ -503,7 +503,7 @@ static struct pci_driver bcm63xx_cardbus_driver = {
.name = "bcm63xx_cardbus",
.id_table = bcm63xx_cb_table,
.probe = bcm63xx_cb_probe,
- .remove = __devexit_p(bcm63xx_cb_exit),
+ .remove = bcm63xx_cb_exit,
};
#endif
diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
index eae9cbe37a3..971991bab97 100644
--- a/drivers/pcmcia/bfin_cf_pcmcia.c
+++ b/drivers/pcmcia/bfin_cf_pcmcia.c
@@ -195,7 +195,7 @@ static struct pccard_operations bfin_cf_ops = {
/*--------------------------------------------------------------------------*/
-static int __devinit bfin_cf_probe(struct platform_device *pdev)
+static int bfin_cf_probe(struct platform_device *pdev)
{
struct bfin_cf_socket *cf;
struct resource *io_mem, *attr_mem;
@@ -235,7 +235,7 @@ static int __devinit bfin_cf_probe(struct platform_device *pdev)
cf->irq = irq;
cf->socket.pci_irq = irq;
- set_irq_type(irq, IRQF_TRIGGER_LOW);
+ irq_set_irq_type(irq, IRQF_TRIGGER_LOW);
io_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
attr_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -286,7 +286,7 @@ fail0:
return status;
}
-static int __devexit bfin_cf_remove(struct platform_device *pdev)
+static int bfin_cf_remove(struct platform_device *pdev)
{
struct bfin_cf_socket *cf = platform_get_drvdata(pdev);
@@ -303,25 +303,14 @@ static int __devexit bfin_cf_remove(struct platform_device *pdev)
static struct platform_driver bfin_cf_driver = {
.driver = {
- .name = (char *)driver_name,
+ .name = driver_name,
.owner = THIS_MODULE,
},
.probe = bfin_cf_probe,
- .remove = __devexit_p(bfin_cf_remove),
+ .remove = bfin_cf_remove,
};
-static int __init bfin_cf_init(void)
-{
- return platform_driver_register(&bfin_cf_driver);
-}
-
-static void __exit bfin_cf_exit(void)
-{
- platform_driver_unregister(&bfin_cf_driver);
-}
-
-module_init(bfin_cf_init);
-module_exit(bfin_cf_exit);
+module_platform_driver(bfin_cf_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("BFIN CF/PCMCIA Driver");
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 9a58862f140..4fe4cc4ae19 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -70,14 +70,15 @@ int __ref cb_alloc(struct pcmcia_socket *s)
struct pci_dev *dev;
unsigned int max, pass;
+ pci_lock_rescan_remove();
+
s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
pci_fixup_cardbus(bus);
- max = bus->secondary;
+ max = bus->busn_res.start;
for (pass = 0; pass < 2; pass++)
list_for_each_entry(dev, &bus->devices, bus_list)
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ if (pci_is_bridge(dev))
max = pci_scan_bridge(bus, dev, max, pass);
/*
@@ -91,9 +92,9 @@ int __ref cb_alloc(struct pcmcia_socket *s)
if (s->tune_bridge)
s->tune_bridge(s, bus);
- pci_enable_bridges(bus);
pci_bus_add_devices(bus);
+ pci_unlock_rescan_remove();
return 0;
}
@@ -105,8 +106,21 @@ int __ref cb_alloc(struct pcmcia_socket *s)
*/
void cb_free(struct pcmcia_socket *s)
{
- struct pci_dev *bridge = s->cb_dev;
+ struct pci_dev *bridge, *dev, *tmp;
+ struct pci_bus *bus;
+
+ bridge = s->cb_dev;
+ if (!bridge)
+ return;
+
+ bus = bridge->subordinate;
+ if (!bus)
+ return;
+
+ pci_lock_rescan_remove();
+
+ list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list)
+ pci_stop_and_remove_bus_device(dev);
- if (bridge)
- pci_remove_behind_bridge(bridge);
+ pci_unlock_rescan_remove();
}
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 8844bc3e311..884a984216f 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -27,9 +27,7 @@
#include <asm/byteorder.h>
#include <asm/unaligned.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
@@ -54,6 +52,9 @@ static const u_int exponent[] = {
/* Upper limit on reasonable # of tuples */
#define MAX_TUPLES 200
+/* Bits in IRQInfo1 field */
+#define IRQ_INFO2_VALID 0x10
+
/* 16-bit CIS? */
static int cis_width;
module_param(cis_width, int, 0444);
@@ -210,7 +211,7 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
* Probably only useful for writing one-byte registers. Must be called
* with ops_mutex held.
*/
-void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
+int pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
u_int len, void *ptr)
{
void __iomem *sys, *end;
@@ -232,7 +233,7 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
((cis_width) ? MAP_16BIT : 0));
if (!sys) {
dev_dbg(&s->dev, "could not map memory\n");
- return; /* FIXME: Error */
+ return -EINVAL;
}
writeb(flags, sys+CISREG_ICTRL0);
@@ -257,7 +258,7 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
sys = set_cis_map(s, card_offset, flags);
if (!sys) {
dev_dbg(&s->dev, "could not map memory\n");
- return; /* FIXME: error */
+ return -EINVAL;
}
end = sys + s->map_size;
@@ -271,6 +272,7 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
addr = 0;
}
}
+ return 0;
}
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 976d80706ea..5292db69c42 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -29,12 +29,9 @@
#include <linux/device.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
-#include <asm/system.h>
#include <asm/irq.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -252,38 +249,6 @@ struct pcmcia_socket *pcmcia_get_socket_by_nr(unsigned int nr)
}
EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
-/*
- * The central event handler. Send_event() sends an event to the
- * 16-bit subsystem, which then calls the relevant device drivers.
- * Parse_events() interprets the event bits from
- * a card status change report. Do_shutdown() handles the high
- * priority stuff associated with a card removal.
- */
-
-/* NOTE: send_event needs to be called with skt->sem held. */
-
-static int send_event(struct pcmcia_socket *s, event_t event, int priority)
-{
- int ret;
-
- if ((s->state & SOCKET_CARDBUS) && (event != CS_EVENT_CARD_REMOVAL))
- return 0;
-
- dev_dbg(&s->dev, "send_event(event %d, pri %d, callback 0x%p)\n",
- event, priority, s->callback);
-
- if (!s->callback)
- return 0;
- if (!try_module_get(s->callback->owner))
- return 0;
-
- ret = s->callback->event(s, event, priority);
-
- module_put(s->callback->owner);
-
- return ret;
-}
-
static int socket_reset(struct pcmcia_socket *skt)
{
int status, i;
@@ -326,7 +291,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
dev_dbg(&s->dev, "shutdown\n");
- send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
+ if (s->callback)
+ s->callback->remove(s);
mutex_lock(&s->ops_mutex);
s->state &= SOCKET_INUSE | SOCKET_PRESENT;
@@ -477,7 +443,8 @@ static int socket_insert(struct pcmcia_socket *skt)
dev_dbg(&skt->dev, "insert done\n");
mutex_unlock(&skt->ops_mutex);
- send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
+ if (!(skt->state & SOCKET_CARDBUS) && (skt->callback))
+ skt->callback->add(skt);
} else {
mutex_unlock(&skt->ops_mutex);
socket_shutdown(skt);
@@ -494,7 +461,6 @@ static int socket_suspend(struct pcmcia_socket *skt)
mutex_lock(&skt->ops_mutex);
skt->suspended_state = skt->state;
- send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
skt->socket = dead_socket;
skt->ops->set_socket(skt, &skt->socket);
if (skt->ops->suspend)
@@ -518,7 +484,7 @@ static int socket_early_resume(struct pcmcia_socket *skt)
static int socket_late_resume(struct pcmcia_socket *skt)
{
- int ret;
+ int ret = 0;
mutex_lock(&skt->ops_mutex);
skt->state &= ~SOCKET_SUSPEND;
@@ -545,19 +511,31 @@ static int socket_late_resume(struct pcmcia_socket *skt)
return socket_insert(skt);
}
+ if (!(skt->state & SOCKET_CARDBUS) && (skt->callback))
+ ret = skt->callback->early_resume(skt);
+ return ret;
+}
+
+/*
+ * Finalize the resume. In case of a cardbus socket, we have
+ * to rebind the devices as we can't be certain that it has been
+ * replaced, or not.
+ */
+static int socket_complete_resume(struct pcmcia_socket *skt)
+{
+ int ret = 0;
#ifdef CONFIG_CARDBUS
if (skt->state & SOCKET_CARDBUS) {
/* We can't be sure the CardBus card is the same
* as the one previously inserted. Therefore, remove
* and re-add... */
cb_free(skt);
- cb_alloc(skt);
- return 0;
+ ret = cb_alloc(skt);
+ if (ret)
+ cb_free(skt);
}
#endif
-
- send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
- return 0;
+ return ret;
}
/*
@@ -567,11 +545,15 @@ static int socket_late_resume(struct pcmcia_socket *skt)
*/
static int socket_resume(struct pcmcia_socket *skt)
{
+ int err;
if (!(skt->state & SOCKET_SUSPEND))
return -EBUSY;
socket_early_resume(skt);
- return socket_late_resume(skt);
+ err = socket_late_resume(skt);
+ if (!err)
+ err = socket_complete_resume(skt);
+ return err;
}
static void socket_remove(struct pcmcia_socket *skt)
@@ -654,16 +636,8 @@ static int pccardd(void *__skt)
spin_unlock_irqrestore(&skt->thread_lock, flags);
mutex_lock(&skt->skt_mutex);
- if (events) {
- if (events & SS_DETECT)
- socket_detect_change(skt);
- if (events & SS_BATDEAD)
- send_event(skt, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW);
- if (events & SS_BATWARN)
- send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);
- if (events & SS_READY)
- send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW);
- }
+ if (events & SS_DETECT)
+ socket_detect_change(skt);
if (sysfs_events) {
if (sysfs_events & PCMCIA_UEVENT_EJECT)
@@ -783,7 +757,7 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
s->callback = c;
if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT)
- send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
+ s->callback->add(s);
} else
s->callback = NULL;
err:
@@ -823,20 +797,13 @@ int pcmcia_reset_card(struct pcmcia_socket *skt)
break;
}
- ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
- if (ret == 0) {
- send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
- if (skt->callback)
- skt->callback->suspend(skt);
- mutex_lock(&skt->ops_mutex);
- ret = socket_reset(skt);
- mutex_unlock(&skt->ops_mutex);
- if (ret == 0) {
- send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
- if (skt->callback)
- skt->callback->resume(skt);
- }
- }
+ if (skt->callback)
+ skt->callback->suspend(skt);
+ mutex_lock(&skt->ops_mutex);
+ ret = socket_reset(skt);
+ mutex_unlock(&skt->ops_mutex);
+ if ((ret == 0) && (skt->callback))
+ skt->callback->resume(skt);
ret = 0;
} while (0);
@@ -892,11 +859,17 @@ static int pcmcia_socket_dev_resume_noirq(struct device *dev)
return __pcmcia_pm_op(dev, socket_early_resume);
}
-static int pcmcia_socket_dev_resume(struct device *dev)
+static int __used pcmcia_socket_dev_resume(struct device *dev)
{
return __pcmcia_pm_op(dev, socket_late_resume);
}
+static void __used pcmcia_socket_dev_complete(struct device *dev)
+{
+ WARN(__pcmcia_pm_op(dev, socket_complete_resume),
+ "failed to complete resume");
+}
+
static const struct dev_pm_ops pcmcia_socket_pm_ops = {
/* dev_resume may be called with IRQs enabled */
SET_SYSTEM_SLEEP_PM_OPS(NULL,
@@ -911,6 +884,7 @@ static const struct dev_pm_ops pcmcia_socket_pm_ops = {
.resume_noirq = pcmcia_socket_dev_resume_noirq,
.thaw_noirq = pcmcia_socket_dev_resume_noirq,
.restore_noirq = pcmcia_socket_dev_resume_noirq,
+ .complete = pcmcia_socket_dev_complete,
};
#define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops)
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 4126a75445e..7f1953f78b1 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -10,7 +10,7 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* (C) 1999 David A. Hinds
- * (C) 2003 - 2008 Dominik Brodowski
+ * (C) 2003 - 2010 Dominik Brodowski
*
*
* This file contains definitions _only_ needed by the PCMCIA core modules.
@@ -26,19 +26,16 @@
/* Flags in client state */
#define CLIENT_WIN_REQ(i) (0x1<<(i))
+/* Flag to access all functions */
+#define BIND_FN_ALL 0xff
+
/* Each card function gets one of these guys */
typedef struct config_t {
struct kref ref;
unsigned int state;
- unsigned int Attributes;
- unsigned int IntType;
- unsigned int ConfigBase;
- unsigned char Status, Pin, Copy, Option, ExtStatus;
- unsigned int CardValues;
- io_req_t io;
- struct {
- u_int Attributes;
- } irq;
+
+ struct resource io[MAX_IO_WIN]; /* io ports */
+ struct resource mem[MAX_WIN]; /* mem areas */
} config_t;
@@ -56,18 +53,11 @@ struct pccard_resource_ops {
unsigned int attr,
unsigned int *base,
unsigned int num,
- unsigned int align);
+ unsigned int align,
+ struct resource **parent);
struct resource* (*find_mem) (unsigned long base, unsigned long num,
unsigned long align, int low,
struct pcmcia_socket *s);
- int (*add_io) (struct pcmcia_socket *s,
- unsigned int action,
- unsigned long r_start,
- unsigned long r_end);
- int (*add_mem) (struct pcmcia_socket *s,
- unsigned int action,
- unsigned long r_start,
- unsigned long r_end);
int (*init) (struct pcmcia_socket *s);
void (*exit) (struct pcmcia_socket *s);
};
@@ -114,11 +104,12 @@ void cb_free(struct pcmcia_socket *s);
struct pcmcia_callback{
struct module *owner;
- int (*event) (struct pcmcia_socket *s,
- event_t event, int priority);
+ int (*add) (struct pcmcia_socket *s);
+ int (*remove) (struct pcmcia_socket *s);
void (*requery) (struct pcmcia_socket *s);
int (*validate) (struct pcmcia_socket *s, unsigned int *i);
int (*suspend) (struct pcmcia_socket *s);
+ int (*early_resume) (struct pcmcia_socket *s);
int (*resume) (struct pcmcia_socket *s);
};
@@ -146,6 +137,8 @@ void pcmcia_put_socket(struct pcmcia_socket *skt);
/* ds.c */
extern struct bus_type pcmcia_bus_type;
+struct pcmcia_device;
+
/* pcmcia_resource.c */
extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
extern int pcmcia_validate_mem(struct pcmcia_socket *s);
@@ -163,8 +156,8 @@ extern struct bin_attribute pccard_cis_attr;
int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr,
u_int addr, u_int len, void *ptr);
-void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr,
- u_int addr, u_int len, void *ptr);
+int pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr,
+ u_int addr, u_int len, void *ptr);
void release_cis_mem(struct pcmcia_socket *s);
void destroy_cis_cache(struct pcmcia_socket *s);
int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
@@ -188,34 +181,4 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function,
int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple);
-
-#ifdef CONFIG_PCMCIA_IOCTL
-/* ds.c */
-extern struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev);
-extern void pcmcia_put_dev(struct pcmcia_device *p_dev);
-
-struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s,
- unsigned int function);
-
-/* pcmcia_ioctl.c */
-extern void __init pcmcia_setup_ioctl(void);
-extern void __exit pcmcia_cleanup_ioctl(void);
-extern void handle_event(struct pcmcia_socket *s, event_t event);
-extern int handle_request(struct pcmcia_socket *s, event_t event);
-
-#else /* CONFIG_PCMCIA_IOCTL */
-
-static inline void __init pcmcia_setup_ioctl(void) { return; }
-static inline void __exit pcmcia_cleanup_ioctl(void) { return; }
-static inline void handle_event(struct pcmcia_socket *s, event_t event)
-{
- return;
-}
-static inline int handle_request(struct pcmcia_socket *s, event_t event)
-{
- return 0;
-}
-
-#endif /* CONFIG_PCMCIA_IOCTL */
-
#endif /* _LINUX_CS_INTERNAL_H */
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
index 0f4cc3f0002..a31e69ea99f 100644
--- a/drivers/pcmcia/db1xxx_ss.c
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -7,7 +7,7 @@
/* This is a fairly generic PCMCIA socket driver suitable for the
* following Alchemy Development boards:
- * Db1000, Db/Pb1500, Db/Pb1100, Db/Pb1550, Db/Pb1200.
+ * Db1000, Db/Pb1500, Db/Pb1100, Db/Pb1550, Db/Pb1200, Db1300
*
* The Db1000 is used as a reference: Per-socket card-, carddetect- and
* statuschange IRQs connected to SoC GPIOs, control and status register
@@ -18,18 +18,19 @@
* - Pb1100/Pb1500: single socket only; voltage key bits VS are
* at STATUS[5:4] (instead of STATUS[1:0]).
* - Au1200-based: additional card-eject irqs, irqs not gpios!
+ * - Db1300: Db1200-like, no pwr ctrl, single socket (#1).
*/
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/resource.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
#include <asm/mach-au1x00/au1000.h>
@@ -59,11 +60,17 @@ struct db1x_pcmcia_sock {
#define BOARD_TYPE_DEFAULT 0 /* most boards */
#define BOARD_TYPE_DB1200 1 /* IRQs aren't gpios */
#define BOARD_TYPE_PB1100 2 /* VS bits slightly different */
+#define BOARD_TYPE_DB1300 3 /* no power control */
int board_type;
};
#define to_db1x_socket(x) container_of(x, struct db1x_pcmcia_sock, socket)
+static int db1300_card_inserted(struct db1x_pcmcia_sock *sock)
+{
+ return bcsr_read(BCSR_SIGSTAT) & (1 << 8);
+}
+
/* DB/PB1200: check CPLD SIGSTATUS register bit 10/12 */
static int db1200_card_inserted(struct db1x_pcmcia_sock *sock)
{
@@ -84,6 +91,8 @@ static int db1x_card_inserted(struct db1x_pcmcia_sock *sock)
switch (sock->board_type) {
case BOARD_TYPE_DB1200:
return db1200_card_inserted(sock);
+ case BOARD_TYPE_DB1300:
+ return db1300_card_inserted(sock);
default:
return db1000_card_inserted(sock);
}
@@ -160,21 +169,22 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)
* ejection handler have been registered and the currently
* active one disabled.
*/
- if (sock->board_type == BOARD_TYPE_DB1200) {
+ if ((sock->board_type == BOARD_TYPE_DB1200) ||
+ (sock->board_type == BOARD_TYPE_DB1300)) {
ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq,
- IRQF_DISABLED, "pcmcia_insert", sock);
+ 0, "pcmcia_insert", sock);
if (ret)
goto out1;
ret = request_irq(sock->eject_irq, db1200_pcmcia_cdirq,
- IRQF_DISABLED, "pcmcia_eject", sock);
+ 0, "pcmcia_eject", sock);
if (ret) {
free_irq(sock->insert_irq, sock);
goto out1;
}
/* enable the currently silent one */
- if (db1200_card_inserted(sock))
+ if (db1x_card_inserted(sock))
enable_irq(sock->eject_irq);
else
enable_irq(sock->insert_irq);
@@ -182,7 +192,7 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)
/* all other (older) Db1x00 boards use a GPIO to show
* card detection status: use both-edge triggers.
*/
- set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH);
+ irq_set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH);
ret = request_irq(sock->insert_irq, db1000_pcmcia_cdirq,
0, "pcmcia_carddetect", sock);
@@ -270,7 +280,8 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
}
/* create new voltage code */
- cr_set |= ((v << 2) | p) << (sock->nr * 8);
+ if (sock->board_type != BOARD_TYPE_DB1300)
+ cr_set |= ((v << 2) | p) << (sock->nr * 8);
changed = state->flags ^ sock->old_flags;
@@ -343,6 +354,10 @@ static int db1x_pcmcia_get_status(struct pcmcia_socket *skt,
/* if Vcc is not zero, we have applied power to a card */
status |= GET_VCC(cr, sock->nr) ? SS_POWERON : 0;
+ /* DB1300: power always on, but don't tell when no card present */
+ if ((sock->board_type == BOARD_TYPE_DB1300) && (status & SS_DETECT))
+ status = SS_POWERON | SS_3VCARD | SS_DETECT;
+
/* reset de-asserted? then we're ready */
status |= (GET_RESET(cr, sock->nr)) ? SS_READY : SS_RESET;
@@ -394,7 +409,7 @@ static struct pccard_operations db1x_pcmcia_operations = {
.set_mem_map = au1x00_pcmcia_set_mem_map,
};
-static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
+static int db1x_pcmcia_socket_probe(struct platform_device *pdev)
{
struct db1x_pcmcia_sock *sock;
struct resource *r;
@@ -419,6 +434,9 @@ static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
case BCSR_WHOAMI_PB1200 ... BCSR_WHOAMI_DB1200:
sock->board_type = BOARD_TYPE_DB1200;
break;
+ case BCSR_WHOAMI_DB1300:
+ sock->board_type = BOARD_TYPE_DB1300;
+ break;
default:
printk(KERN_INFO "db1xxx-ss: unknown board %d!\n", bid);
ret = -ENODEV;
@@ -541,7 +559,7 @@ out0:
return ret;
}
-static int __devexit db1x_pcmcia_socket_remove(struct platform_device *pdev)
+static int db1x_pcmcia_socket_remove(struct platform_device *pdev)
{
struct db1x_pcmcia_sock *sock = platform_get_drvdata(pdev);
@@ -559,21 +577,10 @@ static struct platform_driver db1x_pcmcia_socket_driver = {
.owner = THIS_MODULE,
},
.probe = db1x_pcmcia_socket_probe,
- .remove = __devexit_p(db1x_pcmcia_socket_remove),
+ .remove = db1x_pcmcia_socket_remove,
};
-int __init db1x_pcmcia_socket_load(void)
-{
- return platform_driver_register(&db1x_pcmcia_socket_driver);
-}
-
-void __exit db1x_pcmcia_socket_unload(void)
-{
- platform_driver_unregister(&db1x_pcmcia_socket_driver);
-}
-
-module_init(db1x_pcmcia_socket_load);
-module_exit(db1x_pcmcia_socket_unload);
+module_platform_driver(db1x_pcmcia_socket_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PCMCIA Socket Services for Alchemy Db/Pb1x00 boards");
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index eac961463be..757119b8714 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -10,7 +10,7 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* (C) 1999 David A. Hinds
- * (C) 2003 - 2006 Dominik Brodowski
+ * (C) 2003 - 2010 Dominik Brodowski
*/
#include <linux/kernel.h>
@@ -26,8 +26,6 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/ss.h>
@@ -47,13 +45,13 @@ MODULE_LICENSE("GPL");
static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
{
- struct pcmcia_device_id *did = p_drv->id_table;
+ const struct pcmcia_device_id *did = p_drv->id_table;
unsigned int i;
u32 hash;
if (!p_drv->probe || !p_drv->remove)
printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
- "function\n", p_drv->drv.name);
+ "function\n", p_drv->name);
while (did && did->match_flags) {
for (i = 0; i < 4; i++) {
@@ -66,7 +64,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
printk(KERN_DEBUG "pcmcia: %s: invalid hash for "
"product string \"%s\": is 0x%x, should "
- "be 0x%x\n", p_drv->drv.name, did->prod_id[i],
+ "be 0x%x\n", p_drv->name, did->prod_id[i],
did->prod_id_hash[i], hash);
printk(KERN_DEBUG "pcmcia: see "
"Documentation/pcmcia/devicetable.txt for "
@@ -129,10 +127,7 @@ pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count)
list_add_tail(&dynid->node, &pdrv->dynids.list);
mutex_unlock(&pdrv->dynids.lock);
- if (get_driver(&pdrv->drv)) {
- retval = driver_attach(&pdrv->drv);
- put_driver(&pdrv->drv);
- }
+ retval = driver_attach(&pdrv->drv);
if (retval)
return retval;
@@ -162,6 +157,11 @@ pcmcia_create_newid_file(struct pcmcia_driver *drv)
return error;
}
+static void
+pcmcia_remove_newid_file(struct pcmcia_driver *drv)
+{
+ driver_remove_file(&drv->drv, &driver_attr_new_id);
+}
/**
* pcmcia_register_driver - register a PCMCIA driver with the bus core
@@ -181,10 +181,11 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
/* initialize common fields */
driver->drv.bus = &pcmcia_bus_type;
driver->drv.owner = driver->owner;
+ driver->drv.name = driver->name;
mutex_init(&driver->dynids.lock);
INIT_LIST_HEAD(&driver->dynids.list);
- pr_debug("registering driver %s\n", driver->drv.name);
+ pr_debug("registering driver %s\n", driver->name);
error = driver_register(&driver->drv);
if (error < 0)
@@ -204,7 +205,8 @@ EXPORT_SYMBOL(pcmcia_register_driver);
*/
void pcmcia_unregister_driver(struct pcmcia_driver *driver)
{
- pr_debug("unregistering driver %s\n", driver->drv.name);
+ pr_debug("unregistering driver %s\n", driver->name);
+ pcmcia_remove_newid_file(driver);
driver_unregister(&driver->drv);
pcmcia_free_dynids(driver);
}
@@ -213,7 +215,7 @@ EXPORT_SYMBOL(pcmcia_unregister_driver);
/* pcmcia_device handling */
-struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev)
+static struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev)
{
struct device *tmp_dev;
tmp_dev = get_device(&p_dev->dev);
@@ -222,7 +224,7 @@ struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev)
return to_pcmcia_dev(tmp_dev);
}
-void pcmcia_put_dev(struct pcmcia_device *p_dev)
+static void pcmcia_put_dev(struct pcmcia_device *p_dev)
{
if (p_dev)
put_device(&p_dev->dev);
@@ -265,7 +267,7 @@ static int pcmcia_device_probe(struct device *dev)
p_drv = to_pcmcia_drv(dev->driver);
s = p_dev->socket;
- dev_dbg(dev, "trying to bind to %s\n", p_drv->drv.name);
+ dev_dbg(dev, "trying to bind to %s\n", p_drv->name);
if ((!p_drv->probe) || (!p_dev->function_config) ||
(!try_module_get(p_drv->owner))) {
@@ -277,24 +279,31 @@ static int pcmcia_device_probe(struct device *dev)
ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG,
&cis_config);
if (!ret) {
- p_dev->conf.ConfigBase = cis_config.base;
- p_dev->conf.Present = cis_config.rmask[0];
+ p_dev->config_base = cis_config.base;
+ p_dev->config_regs = cis_config.rmask[0];
+ dev_dbg(dev, "base %x, regs %x", p_dev->config_base,
+ p_dev->config_regs);
} else {
dev_printk(KERN_INFO, dev,
"pcmcia: could not parse base and rmask0 of CIS\n");
- p_dev->conf.ConfigBase = 0;
- p_dev->conf.Present = 0;
+ p_dev->config_base = 0;
+ p_dev->config_regs = 0;
}
ret = p_drv->probe(p_dev);
if (ret) {
dev_dbg(dev, "binding to %s failed with %d\n",
- p_drv->drv.name, ret);
+ p_drv->name, ret);
goto put_module;
}
+ dev_dbg(dev, "%s bound: Vpp %d.%d, idx %x, IRQ %d", p_drv->name,
+ p_dev->vpp/10, p_dev->vpp%10, p_dev->config_index, p_dev->irq);
+ dev_dbg(dev, "resources: ioport %pR %pR iomem %pR %pR %pR",
+ p_dev->resource[0], p_dev->resource[1], p_dev->resource[2],
+ p_dev->resource[3], p_dev->resource[4]);
mutex_lock(&s->ops_mutex);
- if ((s->pcmcia_state.has_pfc) &&
+ if ((s->pcmcia_pfc) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY);
mutex_unlock(&s->ops_mutex);
@@ -359,7 +368,7 @@ static int pcmcia_device_remove(struct device *dev)
* pseudo multi-function card, we need to unbind
* all devices
*/
- if ((p_dev->socket->pcmcia_state.has_pfc) &&
+ if ((p_dev->socket->pcmcia_pfc) &&
(p_dev->socket->device_count > 0) &&
(p_dev->device_no == 0))
pcmcia_card_remove(p_dev->socket, p_dev);
@@ -375,13 +384,13 @@ static int pcmcia_device_remove(struct device *dev)
if (p_dev->_irq || p_dev->_io || p_dev->_locked)
dev_printk(KERN_INFO, dev,
"pcmcia: driver %s did not release config properly\n",
- p_drv->drv.name);
+ p_drv->name);
for (i = 0; i < MAX_WIN; i++)
if (p_dev->_win & CLIENT_WIN_REQ(i))
dev_printk(KERN_INFO, dev,
"pcmcia: driver %s did not release window properly\n",
- p_drv->drv.name);
+ p_drv->name);
/* references from pcmcia_probe_device */
pcmcia_put_dev(p_dev);
@@ -477,7 +486,8 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
}
-struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int function)
+static struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s,
+ unsigned int function)
{
struct pcmcia_device *p_dev, *tmp_dev;
int i;
@@ -531,7 +541,6 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu
list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list)
if (p_dev->func == tmp_dev->func) {
p_dev->function_config = tmp_dev->function_config;
- p_dev->io = tmp_dev->io;
p_dev->irq = tmp_dev->irq;
kref_get(&p_dev->function_config->ref);
}
@@ -544,15 +553,29 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu
"IRQ setup failed -- device might not work\n");
if (!p_dev->function_config) {
+ config_t *c;
dev_dbg(&p_dev->dev, "creating config_t\n");
- p_dev->function_config = kzalloc(sizeof(struct config_t),
- GFP_KERNEL);
- if (!p_dev->function_config) {
+ c = kzalloc(sizeof(struct config_t), GFP_KERNEL);
+ if (!c) {
mutex_unlock(&s->ops_mutex);
goto err_unreg;
}
- kref_init(&p_dev->function_config->ref);
+ p_dev->function_config = c;
+ kref_init(&c->ref);
+ for (i = 0; i < MAX_IO_WIN; i++) {
+ c->io[i].name = p_dev->devname;
+ c->io[i].flags = IORESOURCE_IO;
+ }
+ for (i = 0; i< MAX_WIN; i++) {
+ c->mem[i].name = p_dev->devname;
+ c->mem[i].flags = IORESOURCE_MEM;
+ }
}
+ for (i = 0; i < MAX_IO_WIN; i++)
+ p_dev->resource[i] = &p_dev->function_config->io[i];
+ for (; i < (MAX_IO_WIN + MAX_WIN); i++)
+ p_dev->resource[i] = &p_dev->function_config->mem[i-MAX_IO_WIN];
+
mutex_unlock(&s->ops_mutex);
dev_printk(KERN_NOTICE, &p_dev->dev,
@@ -680,7 +703,7 @@ static void pcmcia_requery(struct pcmcia_socket *s)
* call pcmcia_device_add() -- which will fail if both
* devices are already registered. */
mutex_lock(&s->ops_mutex);
- has_pfc = s->pcmcia_state.has_pfc;
+ has_pfc = s->pcmcia_pfc;
mutex_unlock(&s->ops_mutex);
if (has_pfc)
pcmcia_device_add(s, 0);
@@ -764,7 +787,7 @@ static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filenam
static inline int pcmcia_devmatch(struct pcmcia_device *dev,
- struct pcmcia_device_id *did)
+ const struct pcmcia_device_id *did)
{
if (did->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID) {
if ((!dev->has_manf_id) || (dev->manf_id != did->manf_id))
@@ -812,7 +835,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) {
dev_dbg(&dev->dev, "this is a pseudo-multi-function device\n");
mutex_lock(&dev->socket->ops_mutex);
- dev->socket->pcmcia_state.has_pfc = 1;
+ dev->socket->pcmcia_pfc = 1;
mutex_unlock(&dev->socket->ops_mutex);
if (dev->device_no != did->device_no)
return 0;
@@ -826,7 +849,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
/* if this is a pseudo-multi-function device,
* we need explicit matches */
- if (dev->socket->pcmcia_state.has_pfc)
+ if (dev->socket->pcmcia_pfc)
return 0;
if (dev->device_no)
return 0;
@@ -870,7 +893,7 @@ static int pcmcia_bus_match(struct device *dev, struct device_driver *drv)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
struct pcmcia_driver *p_drv = to_pcmcia_drv(drv);
- struct pcmcia_device_id *did = p_drv->id_table;
+ const struct pcmcia_device_id *did = p_drv->id_table;
struct pcmcia_dynid *dynid;
/* match dynamic devices first */
@@ -885,14 +908,6 @@ static int pcmcia_bus_match(struct device *dev, struct device_driver *drv)
}
mutex_unlock(&p_drv->dynids.lock);
-#ifdef CONFIG_PCMCIA_IOCTL
- /* matching by cardmgr */
- if (p_dev->cardmgr == p_drv) {
- dev_dbg(dev, "cardmgr matched to %s\n", drv->name);
- return 1;
- }
-#endif
-
while (did && did->match_flags) {
dev_dbg(dev, "trying to match to %s\n", drv->name);
if (pcmcia_devmatch(p_dev, did)) {
@@ -905,8 +920,6 @@ static int pcmcia_bus_match(struct device *dev, struct device_driver *drv)
return 0;
}
-#ifdef CONFIG_HOTPLUG
-
static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct pcmcia_device *p_dev;
@@ -947,15 +960,6 @@ static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
-#else
-
-static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- return -ENODEV;
-}
-
-#endif
-
/************************ runtime PM support ***************************/
static int pcmcia_dev_suspend(struct device *dev, pm_message_t state);
@@ -988,16 +992,17 @@ static ssize_t field##_show (struct device *dev, struct device_attribute *attr,
{ \
struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \
return p_dev->test ? sprintf(buf, format, p_dev->field) : -ENODEV; \
-}
+} \
+static DEVICE_ATTR_RO(field);
#define pcmcia_device_stringattr(name, field) \
static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \
return p_dev->field ? sprintf(buf, "%s\n", p_dev->field) : -ENODEV; \
-}
+} \
+static DEVICE_ATTR_RO(name);
-pcmcia_device_attr(func, socket, "0x%02x\n");
pcmcia_device_attr(func_id, has_func_id, "0x%02x\n");
pcmcia_device_attr(manf_id, has_manf_id, "0x%04x\n");
pcmcia_device_attr(card_id, has_card_id, "0x%04x\n");
@@ -1006,8 +1011,29 @@ pcmcia_device_stringattr(prod_id2, prod_id[1]);
pcmcia_device_stringattr(prod_id3, prod_id[2]);
pcmcia_device_stringattr(prod_id4, prod_id[3]);
+static ssize_t function_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ return p_dev->socket ? sprintf(buf, "0x%02x\n", p_dev->func) : -ENODEV;
+}
+static DEVICE_ATTR_RO(function);
-static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t resources_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ char *str = buf;
+ int i;
+
+ for (i = 0; i < PCMCIA_NUM_RESOURCES; i++)
+ str += sprintf(str, "%pr\n", p_dev->resource[i]);
+
+ return str - buf;
+}
+static DEVICE_ATTR_RO(resources);
+
+static ssize_t pm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
@@ -1017,8 +1043,8 @@ static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute
return sprintf(buf, "on\n");
}
-static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t pm_state_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
int ret = 0;
@@ -1033,7 +1059,7 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute
return ret ? ret : count;
}
-
+static DEVICE_ATTR_RW(pm_state);
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -1056,8 +1082,9 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
p_dev->func, p_dev->device_no,
hash[0], hash[1], hash[2], hash[3]);
}
+static DEVICE_ATTR_RO(modalias);
-static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
+static ssize_t allow_func_id_match_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
@@ -1072,21 +1099,24 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
return count;
}
-
-static struct device_attribute pcmcia_dev_attrs[] = {
- __ATTR(function, 0444, func_show, NULL),
- __ATTR(pm_state, 0644, pcmcia_show_pm_state, pcmcia_store_pm_state),
- __ATTR_RO(func_id),
- __ATTR_RO(manf_id),
- __ATTR_RO(card_id),
- __ATTR_RO(prod_id1),
- __ATTR_RO(prod_id2),
- __ATTR_RO(prod_id3),
- __ATTR_RO(prod_id4),
- __ATTR_RO(modalias),
- __ATTR(allow_func_id_match, 0200, NULL, pcmcia_store_allow_func_id_match),
- __ATTR_NULL,
+static DEVICE_ATTR_WO(allow_func_id_match);
+
+static struct attribute *pcmcia_dev_attrs[] = {
+ &dev_attr_resources.attr,
+ &dev_attr_pm_state.attr,
+ &dev_attr_function.attr,
+ &dev_attr_func_id.attr,
+ &dev_attr_manf_id.attr,
+ &dev_attr_card_id.attr,
+ &dev_attr_prod_id1.attr,
+ &dev_attr_prod_id2.attr,
+ &dev_attr_prod_id3.attr,
+ &dev_attr_prod_id4.attr,
+ &dev_attr_modalias.attr,
+ &dev_attr_allow_func_id_match.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(pcmcia_dev);
/* PM support, also needed for reset */
@@ -1118,7 +1148,7 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state)
dev_printk(KERN_ERR, dev,
"pcmcia: device %s (driver %s) did "
"not want to go to sleep (%d)\n",
- p_dev->devname, p_drv->drv.name, ret);
+ p_dev->devname, p_drv->name, ret);
mutex_lock(&p_dev->socket->ops_mutex);
p_dev->suspended = 0;
mutex_unlock(&p_dev->socket->ops_mutex);
@@ -1160,7 +1190,7 @@ static int pcmcia_dev_resume(struct device *dev)
if (p_dev->device_no == p_dev->func) {
dev_dbg(dev, "requesting configuration\n");
- ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+ ret = pcmcia_enable_device(p_dev);
if (ret)
goto out;
}
@@ -1215,86 +1245,55 @@ static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
return 0;
}
+static int pcmcia_bus_remove(struct pcmcia_socket *skt)
+{
+ atomic_set(&skt->present, 0);
+ pcmcia_card_remove(skt, NULL);
-/*======================================================================
+ mutex_lock(&skt->ops_mutex);
+ destroy_cis_cache(skt);
+ pcmcia_cleanup_irq(skt);
+ mutex_unlock(&skt->ops_mutex);
- The card status event handler.
+ return 0;
+}
-======================================================================*/
+static int pcmcia_bus_add(struct pcmcia_socket *skt)
+{
+ atomic_set(&skt->present, 1);
-/* Normally, the event is passed to individual drivers after
- * informing userspace. Only for CS_EVENT_CARD_REMOVAL this
- * is inversed to maintain historic compatibility.
- */
+ mutex_lock(&skt->ops_mutex);
+ skt->pcmcia_pfc = 0;
+ destroy_cis_cache(skt); /* to be on the safe side... */
+ mutex_unlock(&skt->ops_mutex);
-static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
-{
- struct pcmcia_socket *s = pcmcia_get_socket(skt);
+ pcmcia_card_add(skt);
- if (!s) {
- dev_printk(KERN_ERR, &skt->dev,
- "PCMCIA obtaining reference to socket " \
- "failed, event 0x%x lost!\n", event);
- return -ENODEV;
- }
+ return 0;
+}
- dev_dbg(&skt->dev, "ds_event(0x%06x, %d, 0x%p)\n",
- event, priority, skt);
+static int pcmcia_bus_early_resume(struct pcmcia_socket *skt)
+{
+ if (!verify_cis_cache(skt))
+ return 0;
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- atomic_set(&skt->present, 0);
- pcmcia_card_remove(skt, NULL);
- handle_event(skt, event);
- mutex_lock(&s->ops_mutex);
- destroy_cis_cache(s);
- pcmcia_cleanup_irq(s);
- mutex_unlock(&s->ops_mutex);
- break;
+ dev_dbg(&skt->dev, "cis mismatch - different card\n");
- case CS_EVENT_CARD_INSERTION:
- atomic_set(&skt->present, 1);
- mutex_lock(&s->ops_mutex);
- s->pcmcia_state.has_pfc = 0;
- destroy_cis_cache(s); /* to be on the safe side... */
- mutex_unlock(&s->ops_mutex);
- pcmcia_card_add(skt);
- handle_event(skt, event);
- break;
-
- case CS_EVENT_EJECTION_REQUEST:
- break;
-
- case CS_EVENT_PM_RESUME:
- if (verify_cis_cache(skt) != 0) {
- dev_dbg(&skt->dev, "cis mismatch - different card\n");
- /* first, remove the card */
- ds_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
- mutex_lock(&s->ops_mutex);
- destroy_cis_cache(skt);
- kfree(skt->fake_cis);
- skt->fake_cis = NULL;
- s->functions = 0;
- mutex_unlock(&s->ops_mutex);
- /* now, add the new card */
- ds_event(skt, CS_EVENT_CARD_INSERTION,
- CS_EVENT_PRI_LOW);
- }
- handle_event(skt, event);
- break;
+ /* first, remove the card */
+ pcmcia_bus_remove(skt);
- case CS_EVENT_PM_SUSPEND:
- case CS_EVENT_RESET_PHYSICAL:
- case CS_EVENT_CARD_RESET:
- default:
- handle_event(skt, event);
- break;
- }
+ mutex_lock(&skt->ops_mutex);
+ destroy_cis_cache(skt);
+ kfree(skt->fake_cis);
+ skt->fake_cis = NULL;
+ skt->functions = 0;
+ mutex_unlock(&skt->ops_mutex);
- pcmcia_put_socket(s);
+ /* now, add the new card */
+ pcmcia_bus_add(skt);
+ return 0;
+}
- return 0;
-} /* ds_event */
/*
* NOTE: This is racy. There's no guarantee the card will still be
@@ -1323,14 +1322,16 @@ EXPORT_SYMBOL(pcmcia_dev_present);
static struct pcmcia_callback pcmcia_bus_callback = {
.owner = THIS_MODULE,
- .event = ds_event,
+ .add = pcmcia_bus_add,
+ .remove = pcmcia_bus_remove,
.requery = pcmcia_requery,
.validate = pccard_validate_cis,
.suspend = pcmcia_bus_suspend,
+ .early_resume = pcmcia_bus_early_resume,
.resume = pcmcia_bus_resume,
};
-static int __devinit pcmcia_bus_add_socket(struct device *dev,
+static int pcmcia_bus_add_socket(struct device *dev,
struct class_interface *class_intf)
{
struct pcmcia_socket *socket = dev_get_drvdata(dev);
@@ -1350,11 +1351,8 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,
return ret;
}
-#ifdef CONFIG_PCMCIA_IOCTL
- init_waitqueue_head(&socket->queue);
-#endif
INIT_LIST_HEAD(&socket->devices_list);
- memset(&socket->pcmcia_state, 0, sizeof(u8));
+ socket->pcmcia_pfc = 0;
socket->device_count = 0;
atomic_set(&socket->present, 0);
@@ -1404,7 +1402,7 @@ struct bus_type pcmcia_bus_type = {
.name = "pcmcia",
.uevent = pcmcia_bus_uevent,
.match = pcmcia_bus_match,
- .dev_attrs = pcmcia_dev_attrs,
+ .dev_groups = pcmcia_dev_groups,
.probe = pcmcia_device_probe,
.remove = pcmcia_device_remove,
.suspend = pcmcia_dev_suspend,
@@ -1429,8 +1427,6 @@ static int __init init_pcmcia_bus(void)
return ret;
}
- pcmcia_setup_ioctl();
-
return 0;
}
fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that
@@ -1439,8 +1435,6 @@ fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that
static void __exit exit_pcmcia_bus(void)
{
- pcmcia_cleanup_ioctl();
-
class_interface_unregister(&pcmcia_bus_interface);
bus_unregister(&pcmcia_bus_type);
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index f94d8281cfb..5ea64d0f61a 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -30,6 +30,8 @@
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
@@ -44,7 +46,7 @@ struct electra_cf_socket {
unsigned present:1;
unsigned active:1;
- struct of_device *ofdev;
+ struct platform_device *ofdev;
unsigned long mem_phys;
void __iomem * mem_base;
unsigned long mem_size;
@@ -181,8 +183,7 @@ static struct pccard_operations electra_cf_ops = {
.set_mem_map = electra_cf_set_mem_map,
};
-static int __devinit electra_cf_probe(struct of_device *ofdev,
- const struct of_device_id *match)
+static int electra_cf_probe(struct platform_device *ofdev)
{
struct device *device = &ofdev->dev;
struct device_node *np = ofdev->dev.of_node;
@@ -210,9 +211,9 @@ static int __devinit electra_cf_probe(struct of_device *ofdev,
cf->ofdev = ofdev;
cf->mem_phys = mem.start;
- cf->mem_size = PAGE_ALIGN(mem.end - mem.start);
+ cf->mem_size = PAGE_ALIGN(resource_size(&mem));
cf->mem_base = ioremap(cf->mem_phys, cf->mem_size);
- cf->io_size = PAGE_ALIGN(io.end - io.start);
+ cf->io_size = PAGE_ALIGN(resource_size(&io));
area = __get_vm_area(cf->io_size, 0, PHB_IO_BASE, PHB_IO_END);
if (area == NULL)
@@ -325,7 +326,7 @@ fail1:
}
-static int __devexit electra_cf_remove(struct of_device *ofdev)
+static int electra_cf_remove(struct platform_device *ofdev)
{
struct device *device = &ofdev->dev;
struct electra_cf_socket *cf;
@@ -356,9 +357,9 @@ static const struct of_device_id electra_cf_match[] = {
};
MODULE_DEVICE_TABLE(of, electra_cf_match);
-static struct of_platform_driver electra_cf_driver = {
+static struct platform_driver electra_cf_driver = {
.driver = {
- .name = (char *)driver_name,
+ .name = driver_name,
.owner = THIS_MODULE,
.of_match_table = electra_cf_match,
},
@@ -366,17 +367,7 @@ static struct of_platform_driver electra_cf_driver = {
.remove = electra_cf_remove,
};
-static int __init electra_cf_init(void)
-{
- return of_register_platform_driver(&electra_cf_driver);
-}
-module_init(electra_cf_init);
-
-static void __exit electra_cf_exit(void)
-{
- of_unregister_platform_driver(&electra_cf_driver);
-}
-module_exit(electra_cf_exit);
+module_platform_driver(electra_cf_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 3003bb3dfcc..7d47456429a 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -15,11 +15,8 @@
#include <linux/interrupt.h>
#include <linux/device.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
-#include <asm/system.h>
#include <asm/io.h>
#include "i82092aa.h"
@@ -28,14 +25,9 @@
MODULE_LICENSE("GPL");
/* PCI core routines */
-static struct pci_device_id i82092aa_pci_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82092AA_0,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {}
+static DEFINE_PCI_DEVICE_TABLE(i82092aa_pci_ids) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0) },
+ { }
};
MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids);
@@ -43,7 +35,7 @@ static struct pci_driver i82092aa_pci_driver = {
.name = "i82092aa",
.id_table = i82092aa_pci_ids,
.probe = i82092aa_pci_probe,
- .remove = __devexit_p(i82092aa_pci_remove),
+ .remove = i82092aa_pci_remove,
};
@@ -56,7 +48,7 @@ static struct pccard_operations i82092aa_operations = {
.set_mem_map = i82092aa_set_mem_map,
};
-/* The card can do upto 4 sockets, allocate a structure for each of them */
+/* The card can do up to 4 sockets, allocate a structure for each of them */
struct socket_info {
int number;
@@ -75,7 +67,7 @@ static struct socket_info sockets[MAX_SOCKETS];
static int socket_count; /* shortcut */
-static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
unsigned char configbyte;
int i, ret;
@@ -141,8 +133,6 @@ static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_de
goto err_out_free_res;
}
- pci_set_drvdata(dev, &sockets[i].socket);
-
for (i = 0; i<socket_count; i++) {
sockets[i].socket.dev.parent = &dev->dev;
sockets[i].socket.ops = &i82092aa_operations;
@@ -170,16 +160,16 @@ err_out_disable:
return ret;
}
-static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
+static void i82092aa_pci_remove(struct pci_dev *dev)
{
- struct pcmcia_socket *socket = pci_get_drvdata(dev);
+ int i;
enter("i82092aa_pci_remove");
free_irq(dev->irq, i82092aa_interrupt);
- if (socket)
- pcmcia_unregister_socket(socket);
+ for (i = 0; i < socket_count; i++)
+ pcmcia_unregister_socket(&sockets[i].socket);
leave("i82092aa_pci_remove");
}
@@ -618,7 +608,7 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_
enter("i82092aa_set_mem_map");
- pcibios_resource_to_bus(sock_info->dev, &region, mem->res);
+ pcibios_resource_to_bus(sock_info->dev->bus, &region, mem->res);
map = mem->map;
if (map > 4) {
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 9e2a15628de..e6f3d17dd2b 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -48,11 +48,8 @@
#include <linux/bitops.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/system.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <linux/isapnp.h>
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 7e16ed8eb0a..a26f38c6402 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -24,11 +24,8 @@
#include <linux/bitops.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/system.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#undef MAX_IO_WIN /* FIXME */
#define MAX_IO_WIN 1
diff --git a/drivers/pcmcia/m32r_cfc.h b/drivers/pcmcia/m32r_cfc.h
index 8146e3bee2e..f558e1adf95 100644
--- a/drivers/pcmcia/m32r_cfc.h
+++ b/drivers/pcmcia/m32r_cfc.h
@@ -9,7 +9,7 @@
#endif
/*
- * M32R PC Card Controler
+ * M32R PC Card Controller
*/
#define M32R_PCC0_BASE 0x00ef7000
#define M32R_PCC1_BASE 0x00ef7020
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 6c5c3f910d7..296514155cd 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -24,12 +24,9 @@
#include <linux/bitops.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/system.h>
#include <asm/addrspace.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
/* XXX: should be moved into asm/irq.h */
#define PCC0_IRQ 24
diff --git a/drivers/pcmcia/m32r_pcc.h b/drivers/pcmcia/m32r_pcc.h
index e4fffe417ba..f95c58563bc 100644
--- a/drivers/pcmcia/m32r_pcc.h
+++ b/drivers/pcmcia/m32r_pcc.h
@@ -5,7 +5,7 @@
#define M32R_MAX_PCC 2
/*
- * M32R PC Card Controler
+ * M32R PC Card Controller
*/
#define M32R_PCC0_BASE 0x00ef7000
#define M32R_PCC1_BASE 0x00ef7020
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 25e5e30a18a..182034d2ef5 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -48,19 +48,18 @@
#include <linux/interrupt.h>
#include <linux/fsl_devices.h>
#include <linux/bitops.h>
+#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/io.h>
-#include <asm/system.h>
#include <asm/time.h>
#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#include <asm/irq.h>
#include <asm/fs_pd.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
@@ -71,12 +70,6 @@ MODULE_LICENSE("Dual MPL/GPL");
#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
-/* The RPX series use SLOT_B */
-#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
-#define CONFIG_PCMCIA_SLOT_B
-#define CONFIG_BD_IS_MHZ
-#endif
-
/* The ADS board use SLOT_A */
#ifdef CONFIG_ADS
#define CONFIG_PCMCIA_SLOT_A
@@ -256,81 +249,6 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev);
#define PCMCIA_BMT_LIMIT (15*4) /* Bus Monitor Timeout value */
-/* ------------------------------------------------------------------------- */
-/* board specific stuff: */
-/* voltage_set(), hardware_enable() and hardware_disable() */
-/* ------------------------------------------------------------------------- */
-/* RPX Boards from Embedded Planet */
-
-#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
-
-/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks.
- * SYPCR is write once only, therefore must the slowest memory be faster
- * than the bus monitor or we will get a machine check due to the bus timeout.
- */
-
-#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE"
-
-#undef PCMCIA_BMT_LIMIT
-#define PCMCIA_BMT_LIMIT (6*8)
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
- u32 reg = 0;
-
- switch (vcc) {
- case 0:
- break;
- case 33:
- reg |= BCSR1_PCVCTL4;
- break;
- case 50:
- reg |= BCSR1_PCVCTL5;
- break;
- default:
- return 1;
- }
-
- switch (vpp) {
- case 0:
- break;
- case 33:
- case 50:
- if (vcc == vpp)
- reg |= BCSR1_PCVCTL6;
- else
- return 1;
- break;
- case 120:
- reg |= BCSR1_PCVCTL7;
- default:
- return 1;
- }
-
- if (!((vcc == 50) || (vcc == 0)))
- return 1;
-
- /* first, turn off all power */
-
- out_be32(((u32 *) RPX_CSR_ADDR),
- in_be32(((u32 *) RPX_CSR_ADDR)) & ~(BCSR1_PCVCTL4 |
- BCSR1_PCVCTL5 |
- BCSR1_PCVCTL6 |
- BCSR1_PCVCTL7));
-
- /* enable new powersettings */
-
- out_be32(((u32 *) RPX_CSR_ADDR), in_be32(((u32 *) RPX_CSR_ADDR)) | reg);
-
- return 0;
-}
-
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-#define hardware_enable(_slot_) /* No hardware to enable */
-#define hardware_disable(_slot_) /* No hardware to disable */
-
-#endif /* CONFIG_RPXCLASSIC */
-
/* FADS Boards from Motorola */
#if defined(CONFIG_FADS)
@@ -422,65 +340,6 @@ static inline int voltage_set(int slot, int vcc, int vpp)
#endif
-/* ------------------------------------------------------------------------- */
-/* Motorola MBX860 */
-
-#if defined(CONFIG_MBX)
-
-#define PCMCIA_BOARD_MSG "MBX"
-
-static int voltage_set(int slot, int vcc, int vpp)
-{
- u8 reg = 0;
-
- switch (vcc) {
- case 0:
- break;
- case 33:
- reg |= CSR2_VCC_33;
- break;
- case 50:
- reg |= CSR2_VCC_50;
- break;
- default:
- return 1;
- }
-
- switch (vpp) {
- case 0:
- break;
- case 33:
- case 50:
- if (vcc == vpp)
- reg |= CSR2_VPP_VCC;
- else
- return 1;
- break;
- case 120:
- if ((vcc == 33) || (vcc == 50))
- reg |= CSR2_VPP_12;
- else
- return 1;
- default:
- return 1;
- }
-
- /* first, turn off all power */
- out_8((u8 *) MBX_CSR2_ADDR,
- in_8((u8 *) MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
-
- /* enable new powersettings */
- out_8((u8 *) MBX_CSR2_ADDR, in_8((u8 *) MBX_CSR2_ADDR) | reg);
-
- return 0;
-}
-
-#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
-#define hardware_enable(_slot_) /* No hardware to enable */
-#define hardware_disable(_slot_) /* No hardware to disable */
-
-#endif /* CONFIG_MBX */
-
#if defined(CONFIG_PRxK)
#include <asm/cpld.h>
extern volatile fpga_pc_regs *fpga_pc;
@@ -1150,8 +1009,7 @@ static struct pccard_operations m8xx_services = {
.set_mem_map = m8xx_set_mem_map,
};
-static int __init m8xx_probe(struct of_device *ofdev,
- const struct of_device_id *match)
+static int __init m8xx_probe(struct platform_device *ofdev)
{
struct pcmcia_win *w;
unsigned int i, m, hwirq;
@@ -1200,7 +1058,7 @@ static int __init m8xx_probe(struct of_device *ofdev,
out_be32(M8XX_PGCRX(1),
M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16));
- /* intialize the fixed memory windows */
+ /* initialize the fixed memory windows */
for (i = 0; i < PCMCIA_SOCKETS_NO; i++) {
for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
@@ -1250,7 +1108,7 @@ static int __init m8xx_probe(struct of_device *ofdev,
return 0;
}
-static int m8xx_remove(struct of_device *ofdev)
+static int m8xx_remove(struct platform_device *ofdev)
{
u32 m, i;
struct pcmcia_win *w;
@@ -1297,7 +1155,7 @@ static const struct of_device_id m8xx_pcmcia_match[] = {
MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
-static struct of_platform_driver m8xx_pcmcia_driver = {
+static struct platform_driver m8xx_pcmcia_driver = {
.driver = {
.name = driver_name,
.owner = THIS_MODULE,
@@ -1307,15 +1165,4 @@ static struct of_platform_driver m8xx_pcmcia_driver = {
.remove = m8xx_remove,
};
-static int __init m8xx_init(void)
-{
- return of_register_platform_driver(&m8xx_pcmcia_driver);
-}
-
-static void __exit m8xx_exit(void)
-{
- of_unregister_platform_driver(&m8xx_pcmcia_driver);
-}
-
-module_init(m8xx_init);
-module_exit(m8xx_exit);
+module_platform_driver(m8xx_pcmcia_driver);
diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h
index e74bebac269..5096e92c7a4 100644
--- a/drivers/pcmcia/o2micro.h
+++ b/drivers/pcmcia/o2micro.h
@@ -153,14 +153,14 @@ static int o2micro_override(struct yenta_socket *socket)
if (use_speedup) {
dev_info(&socket->dev->dev,
- "O2: enabling read prefetch/write burst\n");
+ "O2: enabling read prefetch/write burst. If you experience problems or performance issues, use the yenta_socket parameter 'o2_speedup=off'\n");
config_writeb(socket, O2_RESERVED1,
a | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST);
config_writeb(socket, O2_RESERVED2,
b | O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST);
} else {
dev_info(&socket->dev->dev,
- "O2: disabling read prefetch/write burst\n");
+ "O2: disabling read prefetch/write burst. If you experience problems or performance issues, use the yenta_socket parameter 'o2_speedup=on'\n");
config_writeb(socket, O2_RESERVED1,
a & ~(O2_RES_READ_PREFETCH | O2_RES_WRITE_BURST));
config_writeb(socket, O2_RESERVED2,
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 0ad06a3bd56..25c4b1993b3 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -24,8 +24,8 @@
#include <asm/io.h>
#include <asm/sizes.h>
-#include <plat/mux.h>
-#include <plat/tc.h>
+#include <mach/mux.h>
+#include <mach/tc.h>
/* NOTE: don't expect this to support many I/O cards. The 16xx chips have
diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c
index 4a65eaf96b0..e2c92415b89 100644
--- a/drivers/pcmcia/pcmcia_cis.c
+++ b/drivers/pcmcia/pcmcia_cis.c
@@ -6,7 +6,7 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Copyright (C) 1999 David A. Hinds
- * Copyright (C) 2004-2009 Dominik Brodowski
+ * Copyright (C) 2004-2010 Dominik Brodowski
*
* 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
@@ -19,11 +19,9 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ds.h>
#include "cs_internal.h"
@@ -127,14 +125,24 @@ next_entry:
return ret;
}
+
+/**
+ * pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter
+ */
+static int pcmcia_io_cfg_data_width(unsigned int flags)
+{
+ if (!(flags & CISTPL_IO_8BIT))
+ return IO_DATA_PATH_WIDTH_16;
+ if (!(flags & CISTPL_IO_16BIT))
+ return IO_DATA_PATH_WIDTH_8;
+ return IO_DATA_PATH_WIDTH_AUTO;
+}
+
+
struct pcmcia_cfg_mem {
struct pcmcia_device *p_dev;
+ int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
void *priv_data;
- int (*conf_check) (struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data);
cisparse_t parse;
cistpl_cftable_entry_t dflt;
};
@@ -148,25 +156,102 @@ struct pcmcia_cfg_mem {
*/
static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
{
- cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
struct pcmcia_cfg_mem *cfg_mem = priv;
+ struct pcmcia_device *p_dev = cfg_mem->p_dev;
+ cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
+ cistpl_cftable_entry_t *dflt = &cfg_mem->dflt;
+ unsigned int flags = p_dev->config_flags;
+ unsigned int vcc = p_dev->socket->socket.Vcc;
+
+ dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n",
+ cfg->index, flags);
/* default values */
- cfg_mem->p_dev->conf.ConfigIndex = cfg->index;
+ cfg_mem->p_dev->config_index = cfg->index;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
cfg_mem->dflt = *cfg;
- return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt,
- cfg_mem->p_dev->socket->socket.Vcc,
- cfg_mem->priv_data);
+ /* check for matching Vcc? */
+ if (flags & CONF_AUTO_CHECK_VCC) {
+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+ return -ENODEV;
+ } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+ return -ENODEV;
+ }
+ }
+
+ /* set Vpp? */
+ if (flags & CONF_AUTO_SET_VPP) {
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->vpp =
+ dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ }
+
+ /* enable audio? */
+ if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
+ p_dev->config_flags |= CONF_ENABLE_SPKR;
+
+
+ /* IO window settings? */
+ if (flags & CONF_AUTO_SET_IO) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ int i = 0;
+
+ p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
+ p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
+ if (io->nwin == 0)
+ return -ENODEV;
+
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ p_dev->resource[0]->flags |=
+ pcmcia_io_cfg_data_width(io->flags);
+ if (io->nwin > 1) {
+ /* For multifunction cards, by convention, we
+ * configure the network function with window 0,
+ * and serial with window 1 */
+ i = (io->win[1].len > io->win[0].len);
+ p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+ p_dev->resource[1]->start = io->win[1-i].base;
+ p_dev->resource[1]->end = io->win[1-i].len;
+ }
+ p_dev->resource[0]->start = io->win[i].base;
+ p_dev->resource[0]->end = io->win[i].len;
+ p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+ }
+
+ /* MEM window settings? */
+ if (flags & CONF_AUTO_SET_IOMEM) {
+ /* so far, we only set one memory window */
+ cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+
+ p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
+ if (mem->nwin == 0)
+ return -ENODEV;
+
+ p_dev->resource[2]->start = mem->win[0].host_addr;
+ p_dev->resource[2]->end = mem->win[0].len;
+ if (p_dev->resource[2]->end < 0x1000)
+ p_dev->resource[2]->end = 0x1000;
+ p_dev->card_addr = mem->win[0].card_addr;
+ }
+
+ dev_dbg(&p_dev->dev,
+ "checking configuration %x: %pr %pr %pr (%d lines)\n",
+ p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
+ p_dev->resource[2], p_dev->io_lines);
+
+ return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
}
/**
* pcmcia_loop_config() - loop over configuration options
* @p_dev: the struct pcmcia_device which we need to loop for.
* @conf_check: function to call for each configuration option.
- * It gets passed the struct pcmcia_device, the CIS data
- * describing the configuration option, and private data
+ * It gets passed the struct pcmcia_device and private data
* being passed to pcmcia_loop_config()
* @priv_data: private data to be passed to the conf_check function.
*
@@ -176,9 +261,6 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
*/
int pcmcia_loop_config(struct pcmcia_device *p_dev,
int (*conf_check) (struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
void *priv_data),
void *priv_data)
{
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
deleted file mode 100644
index d007a2a0383..00000000000
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ /dev/null
@@ -1,1077 +0,0 @@
-/*
- * pcmcia_ioctl.c -- ioctl interface for cardmgr and cardctl
- *
- * 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.
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * (C) 1999 David A. Hinds
- * (C) 2003 - 2004 Dominik Brodowski
- */
-
-/*
- * This file will go away soon.
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/errno.h>
-#include <linux/ioctl.h>
-#include <linux/proc_fs.h>
-#include <linux/poll.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/seq_file.h>
-#include <linux/smp_lock.h>
-#include <linux/workqueue.h>
-
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/cistpl.h>
-#include <pcmcia/cisreg.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/ss.h>
-
-#include "cs_internal.h"
-
-static int major_dev = -1;
-
-
-/* Device user information */
-#define MAX_EVENTS 32
-#define USER_MAGIC 0x7ea4
-#define CHECK_USER(u) \
- (((u) == NULL) || ((u)->user_magic != USER_MAGIC))
-
-typedef struct user_info_t {
- u_int user_magic;
- int event_head, event_tail;
- event_t event[MAX_EVENTS];
- struct user_info_t *next;
- struct pcmcia_socket *socket;
-} user_info_t;
-
-
-static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s,
- unsigned int function)
-{
- struct pcmcia_device *p_dev = NULL;
-
- mutex_lock(&s->ops_mutex);
- list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
- if (p_dev->func == function) {
- mutex_unlock(&s->ops_mutex);
- return pcmcia_get_dev(p_dev);
- }
- }
- mutex_unlock(&s->ops_mutex);
- return NULL;
-}
-
-/* backwards-compatible accessing of driver --- by name! */
-
-static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info)
-{
- struct device_driver *drv;
- struct pcmcia_driver *p_drv;
-
- drv = driver_find((char *) dev_info, &pcmcia_bus_type);
- if (!drv)
- return NULL;
-
- p_drv = container_of(drv, struct pcmcia_driver, drv);
-
- return p_drv;
-}
-
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *proc_pccard;
-
-static int proc_read_drivers_callback(struct device_driver *driver, void *_m)
-{
- struct seq_file *m = _m;
- struct pcmcia_driver *p_drv = container_of(driver,
- struct pcmcia_driver, drv);
-
- seq_printf(m, "%-24.24s 1 %d\n", p_drv->drv.name,
-#ifdef CONFIG_MODULE_UNLOAD
- (p_drv->owner) ? module_refcount(p_drv->owner) : 1
-#else
- 1
-#endif
- );
- return 0;
-}
-
-static int pccard_drivers_proc_show(struct seq_file *m, void *v)
-{
- return bus_for_each_drv(&pcmcia_bus_type, NULL,
- m, proc_read_drivers_callback);
-}
-
-static int pccard_drivers_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, pccard_drivers_proc_show, NULL);
-}
-
-static const struct file_operations pccard_drivers_proc_fops = {
- .owner = THIS_MODULE,
- .open = pccard_drivers_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-#endif
-
-
-#ifdef CONFIG_PCMCIA_PROBE
-
-static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
-{
- int irq;
- u32 mask;
-
- irq = adj->resource.irq.IRQ;
- if ((irq < 0) || (irq > 15))
- return -EINVAL;
-
- if (adj->Action != REMOVE_MANAGED_RESOURCE)
- return 0;
-
- mask = 1 << irq;
-
- if (!(s->irq_mask & mask))
- return 0;
-
- s->irq_mask &= ~mask;
-
- return 0;
-}
-
-#else
-
-static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
-{
- return 0;
-}
-
-#endif
-
-static int pcmcia_adjust_resource_info(adjust_t *adj)
-{
- struct pcmcia_socket *s;
- int ret = -ENOSYS;
-
- down_read(&pcmcia_socket_list_rwsem);
- list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
-
- if (adj->Resource == RES_IRQ)
- ret = adjust_irq(s, adj);
-
- else if (s->resource_ops->add_io) {
- unsigned long begin, end;
-
- /* you can't use the old interface if the new
- * one was used before */
- mutex_lock(&s->ops_mutex);
- if ((s->resource_setup_new) &&
- !(s->resource_setup_old)) {
- mutex_unlock(&s->ops_mutex);
- continue;
- } else if (!(s->resource_setup_old))
- s->resource_setup_old = 1;
-
- switch (adj->Resource) {
- case RES_MEMORY_RANGE:
- begin = adj->resource.memory.Base;
- end = adj->resource.memory.Base + adj->resource.memory.Size - 1;
- if (s->resource_ops->add_mem)
- ret = s->resource_ops->add_mem(s, adj->Action, begin, end);
- case RES_IO_RANGE:
- begin = adj->resource.io.BasePort;
- end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1;
- if (s->resource_ops->add_io)
- ret = s->resource_ops->add_io(s, adj->Action, begin, end);
- }
- if (!ret) {
- /* as there's no way we know this is the
- * last call to adjust_resource_info, we
- * always need to assume this is the latest
- * one... */
- s->resource_setup_done = 1;
- }
- mutex_unlock(&s->ops_mutex);
- }
- }
- up_read(&pcmcia_socket_list_rwsem);
-
- return ret;
-}
-
-
-/** pcmcia_get_window
- */
-static int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *wh_out,
- window_handle_t wh, win_req_t *req)
-{
- pccard_mem_map *win;
- window_handle_t w;
-
- wh--;
- if (!s || !(s->state & SOCKET_PRESENT))
- return -ENODEV;
- if (wh >= MAX_WIN)
- return -EINVAL;
- for (w = wh; w < MAX_WIN; w++)
- if (s->state & SOCKET_WIN_REQ(w))
- break;
- if (w == MAX_WIN)
- return -EINVAL;
- win = &s->win[w];
- req->Base = win->res->start;
- req->Size = win->res->end - win->res->start + 1;
- req->AccessSpeed = win->speed;
- req->Attributes = 0;
- if (win->flags & MAP_ATTRIB)
- req->Attributes |= WIN_MEMORY_TYPE_AM;
- if (win->flags & MAP_ACTIVE)
- req->Attributes |= WIN_ENABLE;
- if (win->flags & MAP_16BIT)
- req->Attributes |= WIN_DATA_WIDTH_16;
- if (win->flags & MAP_USE_WAIT)
- req->Attributes |= WIN_USE_WAIT;
-
- *wh_out = w + 1;
- return 0;
-} /* pcmcia_get_window */
-
-
-/** pcmcia_get_mem_page
- *
- * Change the card address of an already open memory window.
- */
-static int pcmcia_get_mem_page(struct pcmcia_socket *skt, window_handle_t wh,
- memreq_t *req)
-{
- wh--;
- if (wh >= MAX_WIN)
- return -EINVAL;
-
- req->Page = 0;
- req->CardOffset = skt->win[wh].card_start;
- return 0;
-} /* pcmcia_get_mem_page */
-
-
-/** pccard_get_status
- *
- * Get the current socket state bits. We don't support the latched
- * SocketState yet: I haven't seen any point for it.
- */
-
-static int pccard_get_status(struct pcmcia_socket *s,
- struct pcmcia_device *p_dev,
- cs_status_t *status)
-{
- config_t *c;
- int val;
-
- s->ops->get_status(s, &val);
- status->CardState = status->SocketState = 0;
- status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
- status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
- status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0;
- status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0;
- if (s->state & SOCKET_SUSPEND)
- status->CardState |= CS_EVENT_PM_SUSPEND;
- if (!(s->state & SOCKET_PRESENT))
- return -ENODEV;
-
- c = (p_dev) ? p_dev->function_config : NULL;
-
- if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
- (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
- u_char reg;
- if (c->CardValues & PRESENT_PIN_REPLACE) {
- mutex_lock(&s->ops_mutex);
- pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
- mutex_unlock(&s->ops_mutex);
- status->CardState |=
- (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
- status->CardState |=
- (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0;
- status->CardState |=
- (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0;
- status->CardState |=
- (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0;
- } else {
- /* No PRR? Then assume we're always ready */
- status->CardState |= CS_EVENT_READY_CHANGE;
- }
- if (c->CardValues & PRESENT_EXT_STATUS) {
- mutex_lock(&s->ops_mutex);
- pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
- mutex_unlock(&s->ops_mutex);
- status->CardState |=
- (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
- }
- return 0;
- }
- status->CardState |=
- (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
- status->CardState |=
- (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0;
- status->CardState |=
- (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
- status->CardState |=
- (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
- return 0;
-} /* pccard_get_status */
-
-static int pccard_get_configuration_info(struct pcmcia_socket *s,
- struct pcmcia_device *p_dev,
- config_info_t *config)
-{
- config_t *c;
-
- if (!(s->state & SOCKET_PRESENT))
- return -ENODEV;
-
-
-#ifdef CONFIG_CARDBUS
- if (s->state & SOCKET_CARDBUS) {
- memset(config, 0, sizeof(config_info_t));
- config->Vcc = s->socket.Vcc;
- config->Vpp1 = config->Vpp2 = s->socket.Vpp;
- config->Option = s->cb_dev->subordinate->number;
- if (s->state & SOCKET_CARDBUS_CONFIG) {
- config->Attributes = CONF_VALID_CLIENT;
- config->IntType = INT_CARDBUS;
- config->AssignedIRQ = s->pcmcia_irq;
- if (config->AssignedIRQ)
- config->Attributes |= CONF_ENABLE_IRQ;
- if (s->io[0].res) {
- config->BasePort1 = s->io[0].res->start;
- config->NumPorts1 = s->io[0].res->end -
- config->BasePort1 + 1;
- }
- }
- return 0;
- }
-#endif
-
- if (p_dev) {
- c = p_dev->function_config;
- config->Function = p_dev->func;
- } else {
- c = NULL;
- config->Function = 0;
- }
-
- if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
- config->Attributes = 0;
- config->Vcc = s->socket.Vcc;
- config->Vpp1 = config->Vpp2 = s->socket.Vpp;
- return 0;
- }
-
- config->Attributes = c->Attributes | CONF_VALID_CLIENT;
- config->Vcc = s->socket.Vcc;
- config->Vpp1 = config->Vpp2 = s->socket.Vpp;
- config->IntType = c->IntType;
- config->ConfigBase = c->ConfigBase;
- config->Status = c->Status;
- config->Pin = c->Pin;
- config->Copy = c->Copy;
- config->Option = c->Option;
- config->ExtStatus = c->ExtStatus;
- config->Present = config->CardValues = c->CardValues;
- config->IRQAttributes = c->irq.Attributes;
- config->AssignedIRQ = s->pcmcia_irq;
- config->BasePort1 = c->io.BasePort1;
- config->NumPorts1 = c->io.NumPorts1;
- config->Attributes1 = c->io.Attributes1;
- config->BasePort2 = c->io.BasePort2;
- config->NumPorts2 = c->io.NumPorts2;
- config->Attributes2 = c->io.Attributes2;
- config->IOAddrLines = c->io.IOAddrLines;
-
- return 0;
-} /* pccard_get_configuration_info */
-
-
-/*======================================================================
-
- These manage a ring buffer of events pending for one user process
-
-======================================================================*/
-
-
-static int queue_empty(user_info_t *user)
-{
- return (user->event_head == user->event_tail);
-}
-
-static event_t get_queued_event(user_info_t *user)
-{
- user->event_tail = (user->event_tail+1) % MAX_EVENTS;
- return user->event[user->event_tail];
-}
-
-static void queue_event(user_info_t *user, event_t event)
-{
- user->event_head = (user->event_head+1) % MAX_EVENTS;
- if (user->event_head == user->event_tail)
- user->event_tail = (user->event_tail+1) % MAX_EVENTS;
- user->event[user->event_head] = event;
-}
-
-void handle_event(struct pcmcia_socket *s, event_t event)
-{
- user_info_t *user;
- for (user = s->user; user; user = user->next)
- queue_event(user, event);
- wake_up_interruptible(&s->queue);
-}
-
-
-/*======================================================================
-
- bind_request() and bind_device() are merged by now. Register_client()
- is called right at the end of bind_request(), during the driver's
- ->attach() call. Individual descriptions:
-
- bind_request() connects a socket to a particular client driver.
- It looks up the specified device ID in the list of registered
- drivers, binds it to the socket, and tries to create an instance
- of the device. unbind_request() deletes a driver instance.
-
- Bind_device() associates a device driver with a particular socket.
- It is normally called by Driver Services after it has identified
- a newly inserted card. An instance of that driver will then be
- eligible to register as a client of this socket.
-
- Register_client() uses the dev_info_t handle to match the
- caller with a socket. The driver must have already been bound
- to a socket with bind_device() -- in fact, bind_device()
- allocates the client structure that will be used.
-
-======================================================================*/
-
-static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info)
-{
- struct pcmcia_driver *p_drv;
- struct pcmcia_device *p_dev;
- int ret = 0;
-
- s = pcmcia_get_socket(s);
- if (!s)
- return -EINVAL;
-
- pr_debug("bind_request(%d, '%s')\n", s->sock,
- (char *)bind_info->dev_info);
-
- p_drv = get_pcmcia_driver(&bind_info->dev_info);
- if (!p_drv) {
- ret = -EINVAL;
- goto err_put;
- }
-
- if (!try_module_get(p_drv->owner)) {
- ret = -EINVAL;
- goto err_put_driver;
- }
-
- mutex_lock(&s->ops_mutex);
- list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
- if (p_dev->func == bind_info->function) {
- if ((p_dev->dev.driver == &p_drv->drv)) {
- if (p_dev->cardmgr) {
- /* if there's already a device
- * registered, and it was registered
- * by userspace before, we need to
- * return the "instance". */
- mutex_unlock(&s->ops_mutex);
- bind_info->instance = p_dev;
- ret = -EBUSY;
- goto err_put_module;
- } else {
- /* the correct driver managed to bind
- * itself magically to the correct
- * device. */
- mutex_unlock(&s->ops_mutex);
- p_dev->cardmgr = p_drv;
- ret = 0;
- goto err_put_module;
- }
- } else if (!p_dev->dev.driver) {
- /* there's already a device available where
- * no device has been bound to yet. So we don't
- * need to register a device! */
- mutex_unlock(&s->ops_mutex);
- goto rescan;
- }
- }
- }
- mutex_unlock(&s->ops_mutex);
-
- p_dev = pcmcia_device_add(s, bind_info->function);
- if (!p_dev) {
- ret = -EIO;
- goto err_put_module;
- }
-
-rescan:
- p_dev->cardmgr = p_drv;
-
- /* if a driver is already running, we can abort */
- if (p_dev->dev.driver)
- goto err_put_module;
-
- /*
- * Prevent this racing with a card insertion.
- */
- mutex_lock(&s->skt_mutex);
- ret = bus_rescan_devices(&pcmcia_bus_type);
- mutex_unlock(&s->skt_mutex);
- if (ret)
- goto err_put_module;
-
- /* check whether the driver indeed matched. I don't care if this
- * is racy or not, because it can only happen on cardmgr access
- * paths...
- */
- if (!(p_dev->dev.driver == &p_drv->drv))
- p_dev->cardmgr = NULL;
-
- err_put_module:
- module_put(p_drv->owner);
- err_put_driver:
- put_driver(&p_drv->drv);
- err_put:
- pcmcia_put_socket(s);
-
- return ret;
-} /* bind_request */
-
-#ifdef CONFIG_CARDBUS
-
-static struct pci_bus *pcmcia_lookup_bus(struct pcmcia_socket *s)
-{
- if (!s || !(s->state & SOCKET_CARDBUS))
- return NULL;
-
- return s->cb_dev->subordinate;
-}
-#endif
-
-static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int first)
-{
- struct pcmcia_device *p_dev;
- struct pcmcia_driver *p_drv;
- int ret = 0;
-
-#ifdef CONFIG_CARDBUS
- /*
- * Some unbelievably ugly code to associate the PCI cardbus
- * device and its driver with the PCMCIA "bind" information.
- */
- {
- struct pci_bus *bus;
-
- bus = pcmcia_lookup_bus(s);
- if (bus) {
- struct list_head *list;
- struct pci_dev *dev = NULL;
-
- list = bus->devices.next;
- while (list != &bus->devices) {
- struct pci_dev *pdev = pci_dev_b(list);
- list = list->next;
-
- if (first) {
- dev = pdev;
- break;
- }
-
- /* Try to handle "next" here some way? */
- }
- if (dev && dev->driver) {
- strlcpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
- bind_info->major = 0;
- bind_info->minor = 0;
- bind_info->next = NULL;
- return 0;
- }
- }
- }
-#endif
-
- mutex_lock(&s->ops_mutex);
- list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
- if (p_dev->func == bind_info->function) {
- p_dev = pcmcia_get_dev(p_dev);
- if (!p_dev)
- continue;
- goto found;
- }
- }
- mutex_unlock(&s->ops_mutex);
- return -ENODEV;
-
- found:
- mutex_unlock(&s->ops_mutex);
-
- p_drv = to_pcmcia_drv(p_dev->dev.driver);
- if (p_drv && !p_dev->_locked) {
- ret = -EAGAIN;
- goto err_put;
- }
-
- if (!first) {
- ret = -ENODEV;
- goto err_put;
- }
-
- strlcpy(bind_info->name, dev_name(&p_dev->dev), DEV_NAME_LEN);
- bind_info->next = NULL;
-
- err_put:
- pcmcia_put_dev(p_dev);
- return ret;
-} /* get_device_info */
-
-
-static int ds_open(struct inode *inode, struct file *file)
-{
- socket_t i = iminor(inode);
- struct pcmcia_socket *s;
- user_info_t *user;
- static int warning_printed;
- int ret = 0;
-
- pr_debug("ds_open(socket %d)\n", i);
-
- lock_kernel();
- s = pcmcia_get_socket_by_nr(i);
- if (!s) {
- ret = -ENODEV;
- goto out;
- }
- s = pcmcia_get_socket(s);
- if (!s) {
- ret = -ENODEV;
- goto out;
- }
-
- if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
- if (s->pcmcia_state.busy) {
- pcmcia_put_socket(s);
- ret = -EBUSY;
- goto out;
- }
- else
- s->pcmcia_state.busy = 1;
- }
-
- user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
- if (!user) {
- pcmcia_put_socket(s);
- ret = -ENOMEM;
- goto out;
- }
- user->event_tail = user->event_head = 0;
- user->next = s->user;
- user->user_magic = USER_MAGIC;
- user->socket = s;
- s->user = user;
- file->private_data = user;
-
- if (!warning_printed) {
- printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl "
- "usage from process: %s.\n", current->comm);
- printk(KERN_INFO "pcmcia: This interface will soon be removed from "
- "the kernel; please expect breakage unless you upgrade "
- "to new tools.\n");
- printk(KERN_INFO "pcmcia: see http://www.kernel.org/pub/linux/"
- "utils/kernel/pcmcia/pcmcia.html for details.\n");
- warning_printed = 1;
- }
-
- if (atomic_read(&s->present))
- queue_event(user, CS_EVENT_CARD_INSERTION);
-out:
- unlock_kernel();
- return ret;
-} /* ds_open */
-
-/*====================================================================*/
-
-static int ds_release(struct inode *inode, struct file *file)
-{
- struct pcmcia_socket *s;
- user_info_t *user, **link;
-
- pr_debug("ds_release(socket %d)\n", iminor(inode));
-
- user = file->private_data;
- if (CHECK_USER(user))
- goto out;
-
- s = user->socket;
-
- /* Unlink user data structure */
- if ((file->f_flags & O_ACCMODE) != O_RDONLY)
- s->pcmcia_state.busy = 0;
-
- file->private_data = NULL;
- for (link = &s->user; *link; link = &(*link)->next)
- if (*link == user)
- break;
- if (link == NULL)
- goto out;
- *link = user->next;
- user->user_magic = 0;
- kfree(user);
- pcmcia_put_socket(s);
-out:
- return 0;
-} /* ds_release */
-
-/*====================================================================*/
-
-static ssize_t ds_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct pcmcia_socket *s;
- user_info_t *user;
- int ret;
-
- pr_debug("ds_read(socket %d)\n", iminor(file->f_path.dentry->d_inode));
-
- if (count < 4)
- return -EINVAL;
-
- user = file->private_data;
- if (CHECK_USER(user))
- return -EIO;
-
- s = user->socket;
- ret = wait_event_interruptible(s->queue, !queue_empty(user));
- if (ret == 0)
- ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4;
-
- return ret;
-} /* ds_read */
-
-/*====================================================================*/
-
-static ssize_t ds_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- pr_debug("ds_write(socket %d)\n", iminor(file->f_path.dentry->d_inode));
-
- if (count != 4)
- return -EINVAL;
- if ((file->f_flags & O_ACCMODE) == O_RDONLY)
- return -EBADF;
-
- return -EIO;
-} /* ds_write */
-
-/*====================================================================*/
-
-/* No kernel lock - fine */
-static u_int ds_poll(struct file *file, poll_table *wait)
-{
- struct pcmcia_socket *s;
- user_info_t *user;
-
- pr_debug("ds_poll(socket %d)\n", iminor(file->f_path.dentry->d_inode));
-
- user = file->private_data;
- if (CHECK_USER(user))
- return POLLERR;
- s = user->socket;
- /*
- * We don't check for a dead socket here since that
- * will send cardmgr into an endless spin.
- */
- poll_wait(file, &s->queue, wait);
- if (!queue_empty(user))
- return POLLIN | POLLRDNORM;
- return 0;
-} /* ds_poll */
-
-/*====================================================================*/
-
-static int ds_ioctl(struct file *file, u_int cmd, u_long arg)
-{
- struct pcmcia_socket *s;
- void __user *uarg = (char __user *)arg;
- u_int size;
- int ret, err;
- ds_ioctl_arg_t *buf;
- user_info_t *user;
-
- pr_debug("ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);
-
- user = file->private_data;
- if (CHECK_USER(user))
- return -EIO;
-
- s = user->socket;
-
- size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
- if (size > sizeof(ds_ioctl_arg_t))
- return -EINVAL;
-
- /* Permission check */
- if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (cmd & IOC_IN) {
- if (!access_ok(VERIFY_READ, uarg, size)) {
- pr_debug("ds_ioctl(): verify_read = %d\n", -EFAULT);
- return -EFAULT;
- }
- }
- if (cmd & IOC_OUT) {
- if (!access_ok(VERIFY_WRITE, uarg, size)) {
- pr_debug("ds_ioctl(): verify_write = %d\n", -EFAULT);
- return -EFAULT;
- }
- }
- buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- err = ret = 0;
-
- if (cmd & IOC_IN) {
- if (__copy_from_user((char *)buf, uarg, size)) {
- err = -EFAULT;
- goto free_out;
- }
- }
-
- switch (cmd) {
- case DS_ADJUST_RESOURCE_INFO:
- ret = pcmcia_adjust_resource_info(&buf->adjust);
- break;
- case DS_GET_CONFIGURATION_INFO:
- if (buf->config.Function &&
- (buf->config.Function >= s->functions))
- ret = -EINVAL;
- else {
- struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
- ret = pccard_get_configuration_info(s, p_dev, &buf->config);
- pcmcia_put_dev(p_dev);
- }
- break;
- case DS_GET_FIRST_TUPLE:
- mutex_lock(&s->skt_mutex);
- pcmcia_validate_mem(s);
- mutex_unlock(&s->skt_mutex);
- ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple);
- break;
- case DS_GET_NEXT_TUPLE:
- ret = pccard_get_next_tuple(s, BIND_FN_ALL, &buf->tuple);
- break;
- case DS_GET_TUPLE_DATA:
- buf->tuple.TupleData = buf->tuple_parse.data;
- buf->tuple.TupleDataMax = sizeof(buf->tuple_parse.data);
- ret = pccard_get_tuple_data(s, &buf->tuple);
- break;
- case DS_PARSE_TUPLE:
- buf->tuple.TupleData = buf->tuple_parse.data;
- ret = pcmcia_parse_tuple(&buf->tuple, &buf->tuple_parse.parse);
- break;
- case DS_RESET_CARD:
- ret = pcmcia_reset_card(s);
- break;
- case DS_GET_STATUS:
- if (buf->status.Function &&
- (buf->status.Function >= s->functions))
- ret = -EINVAL;
- else {
- struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
- ret = pccard_get_status(s, p_dev, &buf->status);
- pcmcia_put_dev(p_dev);
- }
- break;
- case DS_VALIDATE_CIS:
- mutex_lock(&s->skt_mutex);
- pcmcia_validate_mem(s);
- mutex_unlock(&s->skt_mutex);
- ret = pccard_validate_cis(s, &buf->cisinfo.Chains);
- break;
- case DS_SUSPEND_CARD:
- pcmcia_parse_uevents(s, PCMCIA_UEVENT_SUSPEND);
- break;
- case DS_RESUME_CARD:
- pcmcia_parse_uevents(s, PCMCIA_UEVENT_RESUME);
- break;
- case DS_EJECT_CARD:
- pcmcia_parse_uevents(s, PCMCIA_UEVENT_EJECT);
- break;
- case DS_INSERT_CARD:
- pcmcia_parse_uevents(s, PCMCIA_UEVENT_INSERT);
- break;
- case DS_ACCESS_CONFIGURATION_REGISTER:
- if ((buf->conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) {
- err = -EPERM;
- goto free_out;
- }
-
- ret = -EINVAL;
-
- if (!(buf->conf_reg.Function &&
- (buf->conf_reg.Function >= s->functions))) {
- struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function);
- if (p_dev) {
- ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg);
- pcmcia_put_dev(p_dev);
- }
- }
- break;
- case DS_GET_FIRST_REGION:
- case DS_GET_NEXT_REGION:
- case DS_BIND_MTD:
- if (!capable(CAP_SYS_ADMIN)) {
- err = -EPERM;
- goto free_out;
- } else {
- printk_once(KERN_WARNING
- "2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special\n");
- printk_once(KERN_WARNING "MTD handling any more.\n");
- }
- err = -EINVAL;
- goto free_out;
- break;
- case DS_GET_FIRST_WINDOW:
- ret = pcmcia_get_window(s, &buf->win_info.handle, 1,
- &buf->win_info.window);
- break;
- case DS_GET_NEXT_WINDOW:
- ret = pcmcia_get_window(s, &buf->win_info.handle,
- buf->win_info.handle + 1, &buf->win_info.window);
- break;
- case DS_GET_MEM_PAGE:
- ret = pcmcia_get_mem_page(s, buf->win_info.handle,
- &buf->win_info.map);
- break;
- case DS_REPLACE_CIS:
- ret = pcmcia_replace_cis(s, buf->cisdump.Data, buf->cisdump.Length);
- break;
- case DS_BIND_REQUEST:
- if (!capable(CAP_SYS_ADMIN)) {
- err = -EPERM;
- goto free_out;
- }
- err = bind_request(s, &buf->bind_info);
- break;
- case DS_GET_DEVICE_INFO:
- err = get_device_info(s, &buf->bind_info, 1);
- break;
- case DS_GET_NEXT_DEVICE:
- err = get_device_info(s, &buf->bind_info, 0);
- break;
- case DS_UNBIND_REQUEST:
- err = 0;
- break;
- default:
- err = -EINVAL;
- }
-
- if ((err == 0) && (ret != 0)) {
- pr_debug("ds_ioctl: ret = %d\n", ret);
- switch (ret) {
- case -ENODEV:
- case -EINVAL:
- case -EBUSY:
- case -ENOSYS:
- err = ret;
- break;
- case -ENOMEM:
- err = -ENOSPC; break;
- case -ENOSPC:
- err = -ENODATA; break;
- default:
- err = -EIO; break;
- }
- }
-
- if (cmd & IOC_OUT) {
- if (__copy_to_user(uarg, (char *)buf, size))
- err = -EFAULT;
- }
-
-free_out:
- kfree(buf);
- return err;
-} /* ds_ioctl */
-
-static long ds_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- int ret;
-
- lock_kernel();
- ret = ds_ioctl(file, cmd, arg);
- unlock_kernel();
-
- return ret;
-}
-
-
-/*====================================================================*/
-
-static const struct file_operations ds_fops = {
- .owner = THIS_MODULE,
- .open = ds_open,
- .release = ds_release,
- .unlocked_ioctl = ds_unlocked_ioctl,
- .read = ds_read,
- .write = ds_write,
- .poll = ds_poll,
-};
-
-void __init pcmcia_setup_ioctl(void)
-{
- int i;
-
- /* Set up character device for user mode clients */
- i = register_chrdev(0, "pcmcia", &ds_fops);
- if (i < 0)
- printk(KERN_NOTICE "unable to find a free device # for "
- "Driver Services (error=%d)\n", i);
- else
- major_dev = i;
-
-#ifdef CONFIG_PROC_FS
- proc_pccard = proc_mkdir("bus/pccard", NULL);
- if (proc_pccard)
- proc_create("drivers", 0, proc_pccard, &pccard_drivers_proc_fops);
-#endif
-}
-
-
-void __exit pcmcia_cleanup_ioctl(void)
-{
-#ifdef CONFIG_PROC_FS
- if (proc_pccard) {
- remove_proc_entry("drivers", proc_pccard);
- remove_proc_entry("bus/pccard", NULL);
- }
-#endif
- if (major_dev != -1)
- unregister_chrdev(major_dev, "pcmcia");
-}
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index a4cd9adfcbc..e8c19def1b0 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -6,7 +6,7 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Copyright (C) 1999 David A. Hinds
- * Copyright (C) 2004-2005 Dominik Brodowski
+ * Copyright (C) 2004-2010 Dominik Brodowski
*
* 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
@@ -25,9 +25,7 @@
#include <asm/irq.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -57,220 +55,298 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
}
-/** alloc_io_space
+/**
+ * release_io_space() - release IO ports allocated with alloc_io_space()
+ * @s: pcmcia socket
+ * @res: resource to release
*
- * Special stuff for managing IO windows, because they are scarce
*/
+static void release_io_space(struct pcmcia_socket *s, struct resource *res)
+{
+ resource_size_t num = resource_size(res);
+ int i;
+
+ dev_dbg(&s->dev, "release_io_space for %pR\n", res);
+
+ for (i = 0; i < MAX_IO_WIN; i++) {
+ if (!s->io[i].res)
+ continue;
+ if ((s->io[i].res->start <= res->start) &&
+ (s->io[i].res->end >= res->end)) {
+ s->io[i].InUse -= num;
+ if (res->parent)
+ release_resource(res);
+ res->start = res->end = 0;
+ res->flags = IORESOURCE_IO;
+ /* Free the window if no one else is using it */
+ if (s->io[i].InUse == 0) {
+ release_resource(s->io[i].res);
+ kfree(s->io[i].res);
+ s->io[i].res = NULL;
+ }
+ }
+ }
+}
+
-static int alloc_io_space(struct pcmcia_socket *s, u_int attr,
- unsigned int *base, unsigned int num, u_int lines)
+/**
+ * alloc_io_space() - allocate IO ports for use by a PCMCIA device
+ * @s: pcmcia socket
+ * @res: resource to allocate (begin: begin, end: size)
+ * @lines: number of IO lines decoded by the PCMCIA card
+ *
+ * Special stuff for managing IO windows, because they are scarce
+ */
+static int alloc_io_space(struct pcmcia_socket *s, struct resource *res,
+ unsigned int lines)
{
unsigned int align;
+ unsigned int base = res->start;
+ unsigned int num = res->end;
+ int ret;
+
+ res->flags |= IORESOURCE_IO;
+
+ dev_dbg(&s->dev, "alloc_io_space request for %pR, %d lines\n",
+ res, lines);
- align = (*base) ? (lines ? 1<<lines : 0) : 1;
+ align = base ? (lines ? 1<<lines : 0) : 1;
if (align && (align < num)) {
- if (*base) {
- dev_dbg(&s->dev, "odd IO request: num %#x align %#x\n",
- num, align);
+ if (base) {
+ dev_dbg(&s->dev, "odd IO request\n");
align = 0;
} else
while (align && (align < num))
align <<= 1;
}
- if (*base & ~(align-1)) {
- dev_dbg(&s->dev, "odd IO request: base %#x align %#x\n",
- *base, align);
+ if (base & ~(align-1)) {
+ dev_dbg(&s->dev, "odd IO request\n");
align = 0;
}
- return s->resource_ops->find_io(s, attr, base, num, align);
-} /* alloc_io_space */
-
+ ret = s->resource_ops->find_io(s, res->flags, &base, num, align,
+ &res->parent);
+ if (ret) {
+ dev_dbg(&s->dev, "alloc_io_space request failed (%d)\n", ret);
+ return -EINVAL;
+ }
-static void release_io_space(struct pcmcia_socket *s, unsigned int base,
- unsigned int num)
-{
- int i;
+ res->start = base;
+ res->end = res->start + num - 1;
- for (i = 0; i < MAX_IO_WIN; i++) {
- if (!s->io[i].res)
- continue;
- if ((s->io[i].res->start <= base) &&
- (s->io[i].res->end >= base+num-1)) {
- s->io[i].InUse -= num;
- /* Free the window if no one else is using it */
- if (s->io[i].InUse == 0) {
- release_resource(s->io[i].res);
- kfree(s->io[i].res);
- s->io[i].res = NULL;
- }
+ if (res->parent) {
+ ret = request_resource(res->parent, res);
+ if (ret) {
+ dev_warn(&s->dev,
+ "request_resource %pR failed: %d\n", res, ret);
+ res->parent = NULL;
+ release_io_space(s, res);
}
}
-} /* release_io_space */
+ dev_dbg(&s->dev, "alloc_io_space request result %d: %pR\n", ret, res);
+ return ret;
+}
-/** pccard_access_configuration_register
+/**
+ * pcmcia_access_config() - read or write card configuration registers
*
- * Access_configuration_register() reads and writes configuration
- * registers in attribute memory. Memory window 0 is reserved for
- * this and the tuple reading services.
+ * pcmcia_access_config() reads and writes configuration registers in
+ * attribute memory. Memory window 0 is reserved for this and the tuple
+ * reading services. Drivers must use pcmcia_read_config_byte() or
+ * pcmcia_write_config_byte().
*/
-
-int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
- conf_reg_t *reg)
+static int pcmcia_access_config(struct pcmcia_device *p_dev,
+ off_t where, u8 *val,
+ int (*accessf) (struct pcmcia_socket *s,
+ int attr, unsigned int addr,
+ unsigned int len, void *ptr))
{
struct pcmcia_socket *s;
config_t *c;
int addr;
- u_char val;
int ret = 0;
- if (!p_dev || !p_dev->function_config)
- return -EINVAL;
-
s = p_dev->socket;
mutex_lock(&s->ops_mutex);
c = p_dev->function_config;
if (!(c->state & CONFIG_LOCKED)) {
- dev_dbg(&s->dev, "Configuration isnt't locked\n");
+ dev_dbg(&p_dev->dev, "Configuration isn't locked\n");
mutex_unlock(&s->ops_mutex);
return -EACCES;
}
- addr = (c->ConfigBase + reg->Offset) >> 1;
+ addr = (p_dev->config_base + where) >> 1;
+
+ ret = accessf(s, 1, addr, 1, val);
- switch (reg->Action) {
- case CS_READ:
- ret = pcmcia_read_cis_mem(s, 1, addr, 1, &val);
- reg->Value = val;
- break;
- case CS_WRITE:
- val = reg->Value;
- pcmcia_write_cis_mem(s, 1, addr, 1, &val);
- break;
- default:
- dev_dbg(&s->dev, "Invalid conf register request\n");
- ret = -EINVAL;
- break;
- }
mutex_unlock(&s->ops_mutex);
+
return ret;
-} /* pcmcia_access_configuration_register */
-EXPORT_SYMBOL(pcmcia_access_configuration_register);
+}
-int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
- memreq_t *req)
+/**
+ * pcmcia_read_config_byte() - read a byte from a card configuration register
+ *
+ * pcmcia_read_config_byte() reads a byte from a configuration register in
+ * attribute memory.
+ */
+int pcmcia_read_config_byte(struct pcmcia_device *p_dev, off_t where, u8 *val)
+{
+ return pcmcia_access_config(p_dev, where, val, pcmcia_read_cis_mem);
+}
+EXPORT_SYMBOL(pcmcia_read_config_byte);
+
+
+/**
+ * pcmcia_write_config_byte() - write a byte to a card configuration register
+ *
+ * pcmcia_write_config_byte() writes a byte to a configuration register in
+ * attribute memory.
+ */
+int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val)
+{
+ return pcmcia_access_config(p_dev, where, &val, pcmcia_write_cis_mem);
+}
+EXPORT_SYMBOL(pcmcia_write_config_byte);
+
+
+/**
+ * pcmcia_map_mem_page() - modify iomem window to point to a different offset
+ * @p_dev: pcmcia device
+ * @res: iomem resource already enabled by pcmcia_request_window()
+ * @offset: card_offset to map
+ *
+ * pcmcia_map_mem_page() modifies what can be read and written by accessing
+ * an iomem range previously enabled by pcmcia_request_window(), by setting
+ * the card_offset value to @offset.
+ */
+int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
+ unsigned int offset)
{
struct pcmcia_socket *s = p_dev->socket;
+ unsigned int w;
int ret;
- wh--;
- if (wh >= MAX_WIN)
- return -EINVAL;
- if (req->Page != 0) {
- dev_dbg(&s->dev, "failure: requested page is zero\n");
+ w = ((res->flags & IORESOURCE_BITS & WIN_FLAGS_REQ) >> 2) - 1;
+ if (w >= MAX_WIN)
return -EINVAL;
- }
+
mutex_lock(&s->ops_mutex);
- s->win[wh].card_start = req->CardOffset;
- ret = s->ops->set_mem_map(s, &s->win[wh]);
+ s->win[w].card_start = offset;
+ ret = s->ops->set_mem_map(s, &s->win[w]);
if (ret)
- dev_warn(&s->dev, "failed to set_mem_map\n");
+ dev_warn(&p_dev->dev, "failed to set_mem_map\n");
mutex_unlock(&s->ops_mutex);
return ret;
-} /* pcmcia_map_mem_page */
+}
EXPORT_SYMBOL(pcmcia_map_mem_page);
-/** pcmcia_modify_configuration
+/**
+ * pcmcia_fixup_iowidth() - reduce io width to 8bit
+ * @p_dev: pcmcia device
*
- * Modify a locked socket configuration
+ * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the
+ * IO width to 8bit after having called pcmcia_enable_device()
+ * previously.
*/
-int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
- modconf_t *mod)
+int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev)
{
- struct pcmcia_socket *s;
- config_t *c;
- int ret;
-
- s = p_dev->socket;
+ struct pcmcia_socket *s = p_dev->socket;
+ pccard_io_map io_off = { 0, 0, 0, 0, 1 };
+ pccard_io_map io_on;
+ int i, ret = 0;
mutex_lock(&s->ops_mutex);
- c = p_dev->function_config;
- if (!(s->state & SOCKET_PRESENT)) {
- dev_dbg(&s->dev, "No card present\n");
- ret = -ENODEV;
- goto unlock;
- }
- if (!(c->state & CONFIG_LOCKED)) {
- dev_dbg(&s->dev, "Configuration isnt't locked\n");
+ dev_dbg(&p_dev->dev, "fixup iowidth to 8bit\n");
+
+ if (!(s->state & SOCKET_PRESENT) ||
+ !(p_dev->function_config->state & CONFIG_LOCKED)) {
+ dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
ret = -EACCES;
goto unlock;
}
- if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) {
- dev_dbg(&s->dev,
- "changing Vcc or IRQ is not allowed at this time\n");
- ret = -EINVAL;
- goto unlock;
- }
+ io_on.speed = io_speed;
+ for (i = 0; i < MAX_IO_WIN; i++) {
+ if (!s->io[i].res)
+ continue;
+ io_off.map = i;
+ io_on.map = i;
- /* We only allow changing Vpp1 and Vpp2 to the same value */
- if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
- (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
- if (mod->Vpp1 != mod->Vpp2) {
- dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");
- ret = -EINVAL;
- goto unlock;
- }
- s->socket.Vpp = mod->Vpp1;
- if (s->ops->set_socket(s, &s->socket)) {
- dev_printk(KERN_WARNING, &s->dev,
- "Unable to set VPP\n");
- ret = -EIO;
- goto unlock;
- }
- } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
- (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
- dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");
- ret = -EINVAL;
- goto unlock;
+ io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
+ io_on.start = s->io[i].res->start;
+ io_on.stop = s->io[i].res->end;
+
+ s->ops->set_io_map(s, &io_off);
+ mdelay(40);
+ s->ops->set_io_map(s, &io_on);
}
+unlock:
+ mutex_unlock(&s->ops_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(pcmcia_fixup_iowidth);
+
- if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
- pccard_io_map io_off = { 0, 0, 0, 0, 1 };
- pccard_io_map io_on;
- int i;
+/**
+ * pcmcia_fixup_vpp() - set Vpp to a new voltage level
+ * @p_dev: pcmcia device
+ * @new_vpp: new Vpp voltage
+ *
+ * pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to
+ * a new voltage level between calls to pcmcia_enable_device()
+ * and pcmcia_disable_device().
+ */
+int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp)
+{
+ struct pcmcia_socket *s = p_dev->socket;
+ int ret = 0;
- io_on.speed = io_speed;
- for (i = 0; i < MAX_IO_WIN; i++) {
- if (!s->io[i].res)
- continue;
- io_off.map = i;
- io_on.map = i;
+ mutex_lock(&s->ops_mutex);
- io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
- io_on.start = s->io[i].res->start;
- io_on.stop = s->io[i].res->end;
+ dev_dbg(&p_dev->dev, "fixup Vpp to %d\n", new_vpp);
- s->ops->set_io_map(s, &io_off);
- mdelay(40);
- s->ops->set_io_map(s, &io_on);
- }
+ if (!(s->state & SOCKET_PRESENT) ||
+ !(p_dev->function_config->state & CONFIG_LOCKED)) {
+ dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
+ ret = -EACCES;
+ goto unlock;
}
- ret = 0;
+
+ s->socket.Vpp = new_vpp;
+ if (s->ops->set_socket(s, &s->socket)) {
+ dev_warn(&p_dev->dev, "Unable to set VPP\n");
+ ret = -EIO;
+ goto unlock;
+ }
+ p_dev->vpp = new_vpp;
+
unlock:
mutex_unlock(&s->ops_mutex);
return ret;
-} /* modify_configuration */
-EXPORT_SYMBOL(pcmcia_modify_configuration);
+}
+EXPORT_SYMBOL(pcmcia_fixup_vpp);
+/**
+ * pcmcia_release_configuration() - physically disable a PCMCIA device
+ * @p_dev: pcmcia device
+ *
+ * pcmcia_release_configuration() is the 1:1 counterpart to
+ * pcmcia_enable_device(): If a PCMCIA device is no longer used by any
+ * driver, the Vpp voltage is set to 0, IRQs will no longer be generated,
+ * and I/O ranges will be disabled. As pcmcia_release_io() and
+ * pcmcia_release_window() still need to be called, device drivers are
+ * expected to call pcmcia_disable_device() instead.
+ */
int pcmcia_release_configuration(struct pcmcia_device *p_dev)
{
pccard_io_map io = { 0, 0, 0, 0, 1 };
@@ -283,7 +359,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
if (p_dev->_locked) {
p_dev->_locked = 0;
if (--(s->lock_count) == 0) {
- s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
+ s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
s->socket.Vpp = 0;
s->socket.io_irq = 0;
s->ops->set_socket(s, &s->socket);
@@ -305,42 +381,38 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
mutex_unlock(&s->ops_mutex);
return 0;
-} /* pcmcia_release_configuration */
+}
-/** pcmcia_release_io
+/**
+ * pcmcia_release_io() - release I/O allocated by a PCMCIA device
+ * @p_dev: pcmcia device
*
- * Release_io() releases the I/O ranges allocated by a client. This
- * may be invoked some time after a card ejection has already dumped
- * the actual socket configuration, so if the client is "stale", we
- * don't bother checking the port ranges against the current socket
- * values.
+ * pcmcia_release_io() releases the I/O ranges allocated by a PCMCIA
+ * device. This may be invoked some time after a card ejection has
+ * already dumped the actual socket configuration, so if the client is
+ * "stale", we don't bother checking the port ranges against the
+ * current socket values.
*/
-static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
+static int pcmcia_release_io(struct pcmcia_device *p_dev)
{
struct pcmcia_socket *s = p_dev->socket;
int ret = -EINVAL;
config_t *c;
mutex_lock(&s->ops_mutex);
- c = p_dev->function_config;
-
if (!p_dev->_io)
goto out;
- p_dev->_io = 0;
+ c = p_dev->function_config;
- if ((c->io.BasePort1 != req->BasePort1) ||
- (c->io.NumPorts1 != req->NumPorts1) ||
- (c->io.BasePort2 != req->BasePort2) ||
- (c->io.NumPorts2 != req->NumPorts2))
- goto out;
+ release_io_space(s, &c->io[0]);
- c->state &= ~CONFIG_IO_REQ;
+ if (c->io[1].end)
+ release_io_space(s, &c->io[1]);
- release_io_space(s, req->BasePort1, req->NumPorts1);
- if (req->NumPorts2)
- release_io_space(s, req->BasePort2, req->NumPorts2);
+ p_dev->_io = 0;
+ c->state &= ~CONFIG_IO_REQ;
out:
mutex_unlock(&s->ops_mutex);
@@ -349,20 +421,31 @@ out:
} /* pcmcia_release_io */
-int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
+/**
+ * pcmcia_release_window() - release reserved iomem for PCMCIA devices
+ * @p_dev: pcmcia device
+ * @res: iomem resource to release
+ *
+ * pcmcia_release_window() releases &struct resource *res which was
+ * previously reserved by calling pcmcia_request_window().
+ */
+int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
{
struct pcmcia_socket *s = p_dev->socket;
pccard_mem_map *win;
+ unsigned int w;
+
+ dev_dbg(&p_dev->dev, "releasing window %pR\n", res);
- wh--;
- if (wh >= MAX_WIN)
+ w = ((res->flags & IORESOURCE_BITS & WIN_FLAGS_REQ) >> 2) - 1;
+ if (w >= MAX_WIN)
return -EINVAL;
mutex_lock(&s->ops_mutex);
- win = &s->win[wh];
+ win = &s->win[w];
- if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) {
- dev_dbg(&s->dev, "not releasing unknown window\n");
+ if (!(p_dev->_win & CLIENT_WIN_REQ(w))) {
+ dev_dbg(&p_dev->dev, "not releasing unknown window\n");
mutex_unlock(&s->ops_mutex);
return -EINVAL;
}
@@ -370,15 +453,18 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
/* Shut down memory window */
win->flags &= ~MAP_ACTIVE;
s->ops->set_mem_map(s, win);
- s->state &= ~SOCKET_WIN_REQ(wh);
+ s->state &= ~SOCKET_WIN_REQ(w);
/* Release system memory */
if (win->res) {
+ release_resource(res);
release_resource(win->res);
kfree(win->res);
win->res = NULL;
}
- p_dev->_win &= ~CLIENT_WIN_REQ(wh);
+ res->start = res->end = 0;
+ res->flags = IORESOURCE_MEM;
+ p_dev->_win &= ~CLIENT_WIN_REQ(w);
mutex_unlock(&s->ops_mutex);
return 0;
@@ -386,100 +472,119 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
EXPORT_SYMBOL(pcmcia_release_window);
-int pcmcia_request_configuration(struct pcmcia_device *p_dev,
- config_req_t *req)
+/**
+ * pcmcia_enable_device() - set up and activate a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ *
+ * pcmcia_enable_device() physically enables a PCMCIA device. It parses
+ * the flags passed to in @flags and stored in @p_dev->flags and sets up
+ * the Vpp voltage, enables the speaker line, I/O ports and store proper
+ * values to configuration registers.
+ */
+int pcmcia_enable_device(struct pcmcia_device *p_dev)
{
int i;
- u_int base;
+ unsigned int base;
struct pcmcia_socket *s = p_dev->socket;
config_t *c;
pccard_io_map iomap;
+ unsigned char status = 0;
+ unsigned char ext_status = 0;
+ unsigned char option = 0;
+ unsigned int flags = p_dev->config_flags;
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
- if (req->IntType & INT_CARDBUS) {
- dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n");
- return -EINVAL;
- }
-
mutex_lock(&s->ops_mutex);
c = p_dev->function_config;
if (c->state & CONFIG_LOCKED) {
mutex_unlock(&s->ops_mutex);
- dev_dbg(&s->dev, "Configuration is locked\n");
+ dev_dbg(&p_dev->dev, "Configuration is locked\n");
return -EACCES;
}
/* Do power control. We don't allow changes in Vcc. */
- s->socket.Vpp = req->Vpp;
+ s->socket.Vpp = p_dev->vpp;
if (s->ops->set_socket(s, &s->socket)) {
mutex_unlock(&s->ops_mutex);
- dev_printk(KERN_WARNING, &s->dev,
+ dev_printk(KERN_WARNING, &p_dev->dev,
"Unable to set socket state\n");
return -EINVAL;
}
/* Pick memory or I/O card, DMA mode, interrupt */
- c->IntType = req->IntType;
- c->Attributes = req->Attributes;
- if (req->IntType & INT_MEMORY_AND_IO)
+ if (p_dev->_io || flags & CONF_ENABLE_IRQ)
+ flags |= CONF_ENABLE_IOCARD;
+ if (flags & CONF_ENABLE_IOCARD)
s->socket.flags |= SS_IOCARD;
- if (req->IntType & INT_ZOOMED_VIDEO)
+ if (flags & CONF_ENABLE_ZVCARD)
s->socket.flags |= SS_ZVCARD | SS_IOCARD;
- if (req->Attributes & CONF_ENABLE_DMA)
- s->socket.flags |= SS_DMA_MODE;
- if (req->Attributes & CONF_ENABLE_SPKR)
+ if (flags & CONF_ENABLE_SPKR) {
s->socket.flags |= SS_SPKR_ENA;
- if (req->Attributes & CONF_ENABLE_IRQ)
+ status = CCSR_AUDIO_ENA;
+ if (!(p_dev->config_regs & PRESENT_STATUS))
+ dev_warn(&p_dev->dev, "speaker requested, but "
+ "PRESENT_STATUS not set!\n");
+ }
+ if (flags & CONF_ENABLE_IRQ)
s->socket.io_irq = s->pcmcia_irq;
else
s->socket.io_irq = 0;
+ if (flags & CONF_ENABLE_ESR) {
+ p_dev->config_regs |= PRESENT_EXT_STATUS;
+ ext_status = ESR_REQ_ATTN_ENA;
+ }
s->ops->set_socket(s, &s->socket);
s->lock_count++;
+ dev_dbg(&p_dev->dev,
+ "enable_device: V %d, flags %x, base %x, regs %x, idx %x\n",
+ p_dev->vpp, flags, p_dev->config_base, p_dev->config_regs,
+ p_dev->config_index);
+
/* Set up CIS configuration registers */
- base = c->ConfigBase = req->ConfigBase;
- c->CardValues = req->Present;
- if (req->Present & PRESENT_COPY) {
- c->Copy = req->Copy;
- pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
- }
- if (req->Present & PRESENT_OPTION) {
+ base = p_dev->config_base;
+ if (p_dev->config_regs & PRESENT_COPY) {
+ u16 tmp = 0;
+ dev_dbg(&p_dev->dev, "clearing CISREG_SCR\n");
+ pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &tmp);
+ }
+ if (p_dev->config_regs & PRESENT_PIN_REPLACE) {
+ u16 tmp = 0;
+ dev_dbg(&p_dev->dev, "clearing CISREG_PRR\n");
+ pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &tmp);
+ }
+ if (p_dev->config_regs & PRESENT_OPTION) {
if (s->functions == 1) {
- c->Option = req->ConfigIndex & COR_CONFIG_MASK;
+ option = p_dev->config_index & COR_CONFIG_MASK;
} else {
- c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
- c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
- if (req->Present & PRESENT_IOBASE_0)
- c->Option |= COR_ADDR_DECODE;
+ option = p_dev->config_index & COR_MFC_CONFIG_MASK;
+ option |= COR_FUNC_ENA|COR_IREQ_ENA;
+ if (p_dev->config_regs & PRESENT_IOBASE_0)
+ option |= COR_ADDR_DECODE;
}
- if ((req->Attributes & CONF_ENABLE_IRQ) &&
- !(req->Attributes & CONF_ENABLE_PULSE_IRQ))
- c->Option |= COR_LEVEL_REQ;
- pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
+ if ((flags & CONF_ENABLE_IRQ) &&
+ !(flags & CONF_ENABLE_PULSE_IRQ))
+ option |= COR_LEVEL_REQ;
+ pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &option);
mdelay(40);
}
- if (req->Present & PRESENT_STATUS) {
- c->Status = req->Status;
- pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
- }
- if (req->Present & PRESENT_PIN_REPLACE) {
- c->Pin = req->Pin;
- pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin);
- }
- if (req->Present & PRESENT_EXT_STATUS) {
- c->ExtStatus = req->ExtStatus;
- pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
- }
- if (req->Present & PRESENT_IOBASE_0) {
- u_char b = c->io.BasePort1 & 0xff;
+ if (p_dev->config_regs & PRESENT_STATUS)
+ pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &status);
+
+ if (p_dev->config_regs & PRESENT_EXT_STATUS)
+ pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1,
+ &ext_status);
+
+ if (p_dev->config_regs & PRESENT_IOBASE_0) {
+ u8 b = c->io[0].start & 0xff;
pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
- b = (c->io.BasePort1 >> 8) & 0xff;
+ b = (c->io[0].start >> 8) & 0xff;
pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
}
- if (req->Present & PRESENT_IOSIZE) {
- u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
+ if (p_dev->config_regs & PRESENT_IOSIZE) {
+ u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1;
pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
}
@@ -509,74 +614,68 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
p_dev->_locked = 1;
mutex_unlock(&s->ops_mutex);
return 0;
-} /* pcmcia_request_configuration */
-EXPORT_SYMBOL(pcmcia_request_configuration);
+} /* pcmcia_enable_device */
+EXPORT_SYMBOL(pcmcia_enable_device);
-/** pcmcia_request_io
+/**
+ * pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices
+ * @p_dev: the associated PCMCIA device
*
- * Request_io() reserves ranges of port addresses for a socket.
- * I have not implemented range sharing or alias addressing.
+ * pcmcia_request_io() attempts to reserve the IO port ranges specified in
+ * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The
+ * "start" value is the requested start of the IO port resource; "end"
+ * reflects the number of ports requested. The number of IO lines requested
+ * is specified in &struct pcmcia_device @p_dev->io_lines.
*/
-int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
+int pcmcia_request_io(struct pcmcia_device *p_dev)
{
struct pcmcia_socket *s = p_dev->socket;
- config_t *c;
+ config_t *c = p_dev->function_config;
int ret = -EINVAL;
mutex_lock(&s->ops_mutex);
+ dev_dbg(&p_dev->dev, "pcmcia_request_io: %pR , %pR",
+ &c->io[0], &c->io[1]);
if (!(s->state & SOCKET_PRESENT)) {
- dev_dbg(&s->dev, "No card present\n");
+ dev_dbg(&p_dev->dev, "pcmcia_request_io: No card present\n");
goto out;
}
- if (!req)
- goto out;
-
- c = p_dev->function_config;
if (c->state & CONFIG_LOCKED) {
- dev_dbg(&s->dev, "Configuration is locked\n");
+ dev_dbg(&p_dev->dev, "Configuration is locked\n");
goto out;
}
if (c->state & CONFIG_IO_REQ) {
- dev_dbg(&s->dev, "IO already configured\n");
- goto out;
- }
- if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) {
- dev_dbg(&s->dev, "bad attribute setting for IO region 1\n");
- goto out;
- }
- if ((req->NumPorts2 > 0) &&
- (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) {
- dev_dbg(&s->dev, "bad attribute setting for IO region 2\n");
+ dev_dbg(&p_dev->dev, "IO already configured\n");
goto out;
}
- dev_dbg(&s->dev, "trying to allocate resource 1\n");
- ret = alloc_io_space(s, req->Attributes1, &req->BasePort1,
- req->NumPorts1, req->IOAddrLines);
- if (ret) {
- dev_dbg(&s->dev, "allocation of resource 1 failed\n");
+ ret = alloc_io_space(s, &c->io[0], p_dev->io_lines);
+ if (ret)
goto out;
- }
- if (req->NumPorts2) {
- dev_dbg(&s->dev, "trying to allocate resource 2\n");
- ret = alloc_io_space(s, req->Attributes2, &req->BasePort2,
- req->NumPorts2, req->IOAddrLines);
+ if (c->io[1].end) {
+ ret = alloc_io_space(s, &c->io[1], p_dev->io_lines);
if (ret) {
- dev_dbg(&s->dev, "allocation of resource 2 failed\n");
- release_io_space(s, req->BasePort1, req->NumPorts1);
+ struct resource tmp = c->io[0];
+ /* release the previously allocated resource */
+ release_io_space(s, &c->io[0]);
+ /* but preserve the settings, for they worked... */
+ c->io[0].end = resource_size(&tmp);
+ c->io[0].start = tmp.start;
+ c->io[0].flags = tmp.flags;
goto out;
}
- }
+ } else
+ c->io[1].start = 0;
- c->io = *req;
c->state |= CONFIG_IO_REQ;
p_dev->_io = 1;
- dev_dbg(&s->dev, "allocating resources succeeded: %d\n", ret);
+ dev_dbg(&p_dev->dev, "pcmcia_request_io succeeded: %pR , %pR",
+ &c->io[0], &c->io[1]);
out:
mutex_unlock(&s->ops_mutex);
@@ -587,11 +686,13 @@ EXPORT_SYMBOL(pcmcia_request_io);
/**
* pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ * @handler: IRQ handler to register
*
- * pcmcia_request_irq() is a wrapper around request_irq which will allow
+ * pcmcia_request_irq() is a wrapper around request_irq() which allows
* the PCMCIA core to clean up the registration in pcmcia_disable_device().
* Drivers are free to use request_irq() directly, but then they need to
- * call free_irq themselfves, too. Also, only IRQF_SHARED capable IRQ
+ * call free_irq() themselfves, too. Also, only %IRQF_SHARED capable IRQ
* handlers are allowed.
*/
int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
@@ -614,12 +715,14 @@ EXPORT_SYMBOL(pcmcia_request_irq);
/**
* pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first
+ * @p_dev: the associated PCMCIA device
+ * @handler: IRQ handler to register
*
- * pcmcia_request_exclusive_irq() is a wrapper around request_irq which
+ * pcmcia_request_exclusive_irq() is a wrapper around request_irq() which
* attempts first to request an exclusive IRQ. If it fails, it also accepts
* a shared IRQ, but prints out a warning. PCMCIA drivers should allow for
* IRQ sharing and either use request_irq directly (then they need to call
- * free_irq themselves, too), or the pcmcia_request_irq() function.
+ * free_irq() themselves, too), or the pcmcia_request_irq() function.
*/
int __must_check
__pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
@@ -651,7 +754,7 @@ EXPORT_SYMBOL(__pcmcia_request_exclusive_irq);
#ifdef CONFIG_PCMCIA_PROBE
/* mask of IRQs already reserved by other cards, we should avoid using them */
-static u8 pcmcia_used_irq[NR_IRQS];
+static u8 pcmcia_used_irq[32];
static irqreturn_t test_action(int cpl, void *dev_id)
{
@@ -674,6 +777,9 @@ static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type)
for (try = 0; try < 64; try++) {
irq = try % 32;
+ if (irq > NR_IRQS)
+ continue;
+
/* marked as available by driver, not blocked by userspace? */
if (!((mask >> irq) & 1))
continue;
@@ -757,62 +863,67 @@ int pcmcia_setup_irq(struct pcmcia_device *p_dev)
}
-/** pcmcia_request_window
+/**
+ * pcmcia_request_window() - attempt to reserve iomem for PCMCIA devices
+ * @p_dev: the associated PCMCIA device
+ * @res: &struct resource pointing to p_dev->resource[2..5]
+ * @speed: access speed
*
- * Request_window() establishes a mapping between card memory space
- * and system memory space.
+ * pcmcia_request_window() attepts to reserve an iomem ranges specified in
+ * &struct resource @res pointing to one of the entries in
+ * &struct pcmcia_device @p_dev->resource[2..5]. The "start" value is the
+ * requested start of the IO mem resource; "end" reflects the size
+ * requested.
*/
-int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh)
+int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
+ unsigned int speed)
{
struct pcmcia_socket *s = p_dev->socket;
pccard_mem_map *win;
u_long align;
int w;
+ dev_dbg(&p_dev->dev, "request_window %pR %d\n", res, speed);
+
if (!(s->state & SOCKET_PRESENT)) {
- dev_dbg(&s->dev, "No card present\n");
+ dev_dbg(&p_dev->dev, "No card present\n");
return -ENODEV;
}
- if (req->Attributes & (WIN_PAGED | WIN_SHARED)) {
- dev_dbg(&s->dev, "bad attribute setting for iomem region\n");
- return -EINVAL;
- }
/* Window size defaults to smallest available */
- if (req->Size == 0)
- req->Size = s->map_size;
- align = (((s->features & SS_CAP_MEM_ALIGN) ||
- (req->Attributes & WIN_STRICT_ALIGN)) ?
- req->Size : s->map_size);
- if (req->Size & (s->map_size-1)) {
- dev_dbg(&s->dev, "invalid map size\n");
+ if (res->end == 0)
+ res->end = s->map_size;
+ align = (s->features & SS_CAP_MEM_ALIGN) ? res->end : s->map_size;
+ if (res->end & (s->map_size-1)) {
+ dev_dbg(&p_dev->dev, "invalid map size\n");
return -EINVAL;
}
- if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
- (req->Base & (align-1))) {
- dev_dbg(&s->dev, "invalid base address\n");
+ if ((res->start && (s->features & SS_CAP_STATIC_MAP)) ||
+ (res->start & (align-1))) {
+ dev_dbg(&p_dev->dev, "invalid base address\n");
return -EINVAL;
}
- if (req->Base)
+ if (res->start)
align = 0;
/* Allocate system memory window */
+ mutex_lock(&s->ops_mutex);
for (w = 0; w < MAX_WIN; w++)
if (!(s->state & SOCKET_WIN_REQ(w)))
break;
if (w == MAX_WIN) {
- dev_dbg(&s->dev, "all windows are used already\n");
+ dev_dbg(&p_dev->dev, "all windows are used already\n");
+ mutex_unlock(&s->ops_mutex);
return -EINVAL;
}
- mutex_lock(&s->ops_mutex);
win = &s->win[w];
if (!(s->features & SS_CAP_STATIC_MAP)) {
- win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
- (req->Attributes & WIN_MAP_BELOW_1MB), s);
+ win->res = pcmcia_find_mem_region(res->start, res->end, align,
+ 0, s);
if (!win->res) {
- dev_dbg(&s->dev, "allocating mem region failed\n");
+ dev_dbg(&p_dev->dev, "allocating mem region failed\n");
mutex_unlock(&s->ops_mutex);
return -EINVAL;
}
@@ -821,20 +932,12 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
/* Configure the socket controller */
win->map = w+1;
- win->flags = 0;
- win->speed = req->AccessSpeed;
- if (req->Attributes & WIN_MEMORY_TYPE)
- win->flags |= MAP_ATTRIB;
- if (req->Attributes & WIN_ENABLE)
- win->flags |= MAP_ACTIVE;
- if (req->Attributes & WIN_DATA_WIDTH_16)
- win->flags |= MAP_16BIT;
- if (req->Attributes & WIN_USE_WAIT)
- win->flags |= MAP_USE_WAIT;
+ win->flags = res->flags & WIN_FLAGS_MAP;
+ win->speed = speed;
win->card_start = 0;
if (s->ops->set_mem_map(s, win) != 0) {
- dev_dbg(&s->dev, "failed to set memory mapping\n");
+ dev_dbg(&p_dev->dev, "failed to set memory mapping\n");
mutex_unlock(&s->ops_mutex);
return -EIO;
}
@@ -842,26 +945,56 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
/* Return window handle */
if (s->features & SS_CAP_STATIC_MAP)
- req->Base = win->static_start;
+ res->start = win->static_start;
else
- req->Base = win->res->start;
+ res->start = win->res->start;
+
+ /* convert to new-style resources */
+ res->end += res->start - 1;
+ res->flags &= ~WIN_FLAGS_REQ;
+ res->flags |= (win->map << 2) | IORESOURCE_MEM;
+ res->parent = win->res;
+ if (win->res)
+ request_resource(&iomem_resource, res);
+
+ dev_dbg(&p_dev->dev, "request_window results in %pR\n", res);
mutex_unlock(&s->ops_mutex);
- *wh = w + 1;
return 0;
} /* pcmcia_request_window */
EXPORT_SYMBOL(pcmcia_request_window);
+
+/**
+ * pcmcia_disable_device() - disable and clean up a PCMCIA device
+ * @p_dev: the associated PCMCIA device
+ *
+ * pcmcia_disable_device() is the driver-callable counterpart to
+ * pcmcia_enable_device(): If a PCMCIA device is no longer used,
+ * drivers are expected to clean up and disable the device by calling
+ * this function. Any I/O ranges (iomem and ioports) will be released,
+ * the Vpp voltage will be set to 0, and IRQs will no longer be
+ * generated -- at least if there is no other card function (of
+ * multifunction devices) being used.
+ */
void pcmcia_disable_device(struct pcmcia_device *p_dev)
{
+ int i;
+
+ dev_dbg(&p_dev->dev, "disabling device\n");
+
+ for (i = 0; i < MAX_WIN; i++) {
+ struct resource *res = p_dev->resource[MAX_IO_WIN + i];
+ if (res->flags & WIN_FLAGS_REQ)
+ pcmcia_release_window(p_dev, res);
+ }
+
pcmcia_release_configuration(p_dev);
- pcmcia_release_io(p_dev, &p_dev->io);
+ pcmcia_release_io(p_dev);
if (p_dev->_irq) {
free_irq(p_dev->irq, p_dev->priv);
p_dev->_irq = 0;
}
- if (p_dev->win)
- pcmcia_release_window(p_dev, p_dev->win);
}
EXPORT_SYMBOL(pcmcia_disable_device);
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index b61a13663a0..622dd6fe734 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -17,11 +17,8 @@
#include <linux/device.h>
#include <linux/io.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
-#include <asm/system.h>
#include "pd6729.h"
#include "i82365.h"
@@ -592,7 +589,7 @@ static int pd6729_check_irq(int irq)
return 0;
}
-static u_int __devinit pd6729_isa_scan(void)
+static u_int pd6729_isa_scan(void)
{
u_int mask0, mask = 0;
int i;
@@ -623,7 +620,7 @@ static u_int __devinit pd6729_isa_scan(void)
return mask;
}
-static int __devinit pd6729_pci_probe(struct pci_dev *dev,
+static int pd6729_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
int i, j, ret;
@@ -647,7 +644,8 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
if (!pci_resource_start(dev, 0)) {
dev_warn(&dev->dev, "refusing to load the driver as the "
"io_base is NULL.\n");
- goto err_out_free_mem;
+ ret = -ENOMEM;
+ goto err_out_disable;
}
dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx "
@@ -676,6 +674,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
mask = pd6729_isa_scan();
if (irq_mode == 0 && mask == 0) {
dev_warn(&dev->dev, "no ISA interrupt is available.\n");
+ ret = -ENODEV;
goto err_out_free_res;
}
@@ -727,22 +726,22 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
return 0;
- err_out_free_res2:
+err_out_free_res2:
if (irq_mode == 1)
free_irq(dev->irq, socket);
else
del_timer_sync(&socket->poll_timer);
- err_out_free_res:
+err_out_free_res:
pci_release_regions(dev);
- err_out_disable:
+err_out_disable:
pci_disable_device(dev);
- err_out_free_mem:
+err_out_free_mem:
kfree(socket);
return ret;
}
-static void __devexit pd6729_pci_remove(struct pci_dev *dev)
+static void pd6729_pci_remove(struct pci_dev *dev)
{
int i;
struct pd6729_socket *socket = pci_get_drvdata(dev);
@@ -765,13 +764,8 @@ static void __devexit pd6729_pci_remove(struct pci_dev *dev)
kfree(socket);
}
-static struct pci_device_id pd6729_pci_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_CIRRUS,
- .device = PCI_DEVICE_ID_CIRRUS_6729,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+static DEFINE_PCI_DEVICE_TABLE(pd6729_pci_ids) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729) },
{ }
};
MODULE_DEVICE_TABLE(pci, pd6729_pci_ids);
@@ -780,18 +774,7 @@ static struct pci_driver pd6729_pci_driver = {
.name = "pd6729",
.id_table = pd6729_pci_ids,
.probe = pd6729_pci_probe,
- .remove = __devexit_p(pd6729_pci_remove),
+ .remove = pd6729_pci_remove,
};
-static int pd6729_module_init(void)
-{
- return pci_register_driver(&pd6729_pci_driver);
-}
-
-static void pd6729_module_exit(void)
-{
- pci_unregister_driver(&pd6729_pci_driver);
-}
-
-module_init(pd6729_module_init);
-module_exit(pd6729_module_exit);
+module_pci_driver(pd6729_pci_driver);
diff --git a/drivers/pcmcia/pd6729.h b/drivers/pcmcia/pd6729.h
index 41418d394c5..c8e84bdece3 100644
--- a/drivers/pcmcia/pd6729.h
+++ b/drivers/pcmcia/pd6729.h
@@ -15,7 +15,7 @@
struct pd6729_socket {
int number;
int card_irq;
- unsigned long io_base; /* base io address of the socket */
+ unsigned long io_base; /* base io address of the socket */
struct pcmcia_socket socket;
struct timer_list poll_timer;
};
diff --git a/drivers/pcmcia/pxa2xx_balloon3.c b/drivers/pcmcia/pxa2xx_balloon3.c
new file mode 100644
index 00000000000..2ef576c5b69
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_balloon3.c
@@ -0,0 +1,140 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_balloon3.c
+ *
+ * Balloon3 PCMCIA specific routines.
+ *
+ * Author: Nick Bane
+ * Created: June, 2006
+ * Copyright: Toby Churchill Ltd
+ * Derived from pxa2xx_mainstone.c, by Nico Pitre
+ *
+ * Various modification by Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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/gpio.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/balloon3.h>
+
+#include <asm/mach-types.h>
+
+#include "soc_common.h"
+
+static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ uint16_t ver;
+
+ ver = __raw_readw(BALLOON3_FPGA_VER);
+ if (ver < 0x4f08)
+ pr_warn("The FPGA code, version 0x%04x, is too old. "
+ "PCMCIA/CF support might be broken in this version!",
+ ver);
+
+ skt->socket.pci_irq = BALLOON3_BP_CF_NRDY_IRQ;
+ 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";
+
+ return 0;
+}
+
+static unsigned long balloon3_pcmcia_status[2] = {
+ BALLOON3_CF_nSTSCHG_BVD1,
+ BALLOON3_CF_nSTSCHG_BVD1
+};
+
+static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+ uint16_t status;
+ int flip;
+
+ /* This actually reads the STATUS register */
+ status = __raw_readw(BALLOON3_CF_STATUS_REG);
+ flip = (status ^ balloon3_pcmcia_status[skt->nr])
+ & BALLOON3_CF_nSTSCHG_BVD1;
+ /*
+ * Workaround for STSCHG which can't be deasserted:
+ * We therefore disable/enable corresponding IRQs
+ * as needed to avoid IRQ locks.
+ */
+ if (flip) {
+ balloon3_pcmcia_status[skt->nr] = status;
+ if (status & BALLOON3_CF_nSTSCHG_BVD1)
+ enable_irq(BALLOON3_BP_NSTSCHG_IRQ);
+ else
+ disable_irq(BALLOON3_BP_NSTSCHG_IRQ);
+ }
+
+ state->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 */
+}
+
+static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ __raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG +
+ ((state->flags & SS_RESET) ?
+ BALLOON3_FPGA_SETnCLR : 0));
+ return 0;
+}
+
+static struct pcmcia_low_level balloon3_pcmcia_ops = {
+ .owner = THIS_MODULE,
+ .hw_init = balloon3_pcmcia_hw_init,
+ .socket_state = balloon3_pcmcia_socket_state,
+ .configure_socket = balloon3_pcmcia_configure_socket,
+ .first = 0,
+ .nr = 1,
+};
+
+static struct platform_device *balloon3_pcmcia_device;
+
+static int __init balloon3_pcmcia_init(void)
+{
+ int ret;
+
+ if (!machine_is_balloon3())
+ return -ENODEV;
+
+ balloon3_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+ if (!balloon3_pcmcia_device)
+ return -ENOMEM;
+
+ ret = platform_device_add_data(balloon3_pcmcia_device,
+ &balloon3_pcmcia_ops, sizeof(balloon3_pcmcia_ops));
+
+ if (!ret)
+ ret = platform_device_add(balloon3_pcmcia_device);
+
+ if (ret)
+ platform_device_put(balloon3_pcmcia_device);
+
+ return ret;
+}
+
+static void __exit balloon3_pcmcia_exit(void)
+{
+ platform_device_unregister(balloon3_pcmcia_device);
+}
+
+module_init(balloon3_pcmcia_init);
+module_exit(balloon3_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nick Bane <nick@cecomputing.co.uk>");
+MODULE_ALIAS("platform:pxa2xx-pcmcia");
+MODULE_DESCRIPTION("Balloon3 board CF/PCMCIA driver");
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index df4532e91b1..cfec9dd18ff 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -26,13 +26,12 @@
#include <linux/platform_device.h>
#include <mach/hardware.h>
+#include <mach/smemc.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/system.h>
#include <mach/pxa2xx-regs.h>
#include <asm/mach-types.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
@@ -117,37 +116,49 @@ static inline u_int pxa2xx_pcmcia_cmd_time(u_int mem_clk_10khz,
static int pxa2xx_pcmcia_set_mcmem( int sock, int speed, int clock )
{
- MCMEM(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+ uint32_t val;
+
+ val = ((pxa2xx_mcxx_setup(speed, clock)
& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
| ((pxa2xx_mcxx_asst(speed, clock)
& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
| ((pxa2xx_mcxx_hold(speed, clock)
& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+ __raw_writel(val, MCMEM(sock));
+
return 0;
}
static int pxa2xx_pcmcia_set_mcio( int sock, int speed, int clock )
{
- MCIO(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+ uint32_t val;
+
+ val = ((pxa2xx_mcxx_setup(speed, clock)
& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
| ((pxa2xx_mcxx_asst(speed, clock)
& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
| ((pxa2xx_mcxx_hold(speed, clock)
& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+ __raw_writel(val, MCIO(sock));
+
return 0;
}
static int pxa2xx_pcmcia_set_mcatt( int sock, int speed, int clock )
{
- MCATT(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+ uint32_t val;
+
+ val = ((pxa2xx_mcxx_setup(speed, clock)
& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
| ((pxa2xx_mcxx_asst(speed, clock)
& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
| ((pxa2xx_mcxx_hold(speed, clock)
& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+ __raw_writel(val, MCATT(sock));
+
return 0;
}
@@ -167,8 +178,8 @@ static int pxa2xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int cl
static int pxa2xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
{
- unsigned int clk = get_memclk_frequency_10khz();
- return pxa2xx_pcmcia_set_mcxx(skt, clk);
+ unsigned long clk = clk_get_rate(skt->clk);
+ return pxa2xx_pcmcia_set_mcxx(skt, clk / 10000);
}
#ifdef CONFIG_CPU_FREQ
@@ -178,7 +189,6 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
unsigned long val,
struct cpufreq_freqs *freqs)
{
-#warning "it's not clear if this is right since the core CPU (N) clock has no effect on the memory (L) clock"
switch (val) {
case CPUFREQ_PRECHANGE:
if (freqs->new > freqs->old) {
@@ -186,7 +196,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
"pre-updating\n",
freqs->new / 1000, (freqs->new / 100) % 10,
freqs->old / 1000, (freqs->old / 100) % 10);
- pxa2xx_pcmcia_set_mcxx(skt, freqs->new);
+ pxa2xx_pcmcia_set_timing(skt);
}
break;
@@ -196,7 +206,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
"post-updating\n",
freqs->new / 1000, (freqs->new / 100) % 10,
freqs->old / 1000, (freqs->old / 100) % 10);
- pxa2xx_pcmcia_set_mcxx(skt, freqs->new);
+ pxa2xx_pcmcia_set_timing(skt);
}
break;
}
@@ -204,23 +214,23 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
}
#endif
-static void pxa2xx_configure_sockets(struct device *dev)
+void pxa2xx_configure_sockets(struct device *dev)
{
struct pcmcia_low_level *ops = dev->platform_data;
-
/*
* We have at least one socket, so set MECR:CIT
* (Card Is There)
*/
- MECR |= MECR_CIT;
+ uint32_t mecr = MECR_CIT;
/* Set MECR:NOS (Number Of Sockets) */
if ((ops->first + ops->nr) > 1 ||
machine_is_viper() || machine_is_arcom_zeus())
- MECR |= MECR_NOS;
- else
- MECR &= ~MECR_NOS;
+ mecr |= MECR_NOS;
+
+ __raw_writel(mecr, MECR);
}
+EXPORT_SYMBOL(pxa2xx_configure_sockets);
static const char *skt_names[] = {
"PCMCIA socket 0",
@@ -272,43 +282,59 @@ static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)
struct pcmcia_low_level *ops;
struct skt_dev_info *sinfo;
struct soc_pcmcia_socket *skt;
+ struct clk *clk;
ops = (struct pcmcia_low_level *)dev->dev.platform_data;
- if (!ops)
+ if (!ops) {
+ ret = -ENODEV;
+ goto err0;
+ }
+
+ if (cpu_is_pxa320() && ops->nr > 1) {
+ dev_err(&dev->dev, "pxa320 supports only one pcmcia slot");
+ ret = -EINVAL;
+ goto err0;
+ }
+
+ clk = clk_get(&dev->dev, NULL);
+ if (IS_ERR(clk))
return -ENODEV;
pxa2xx_drv_pcmcia_ops(ops);
sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL);
- if (!sinfo)
+ if (!sinfo) {
+ clk_put(clk);
return -ENOMEM;
+ }
sinfo->nskt = ops->nr;
+ sinfo->clk = clk;
/* Initialize processor specific parameters */
for (i = 0; i < ops->nr; i++) {
skt = &sinfo->skt[i];
skt->nr = ops->first + i;
- skt->ops = ops;
- skt->socket.owner = ops->owner;
- skt->socket.dev.parent = &dev->dev;
- skt->socket.pci_irq = NO_IRQ;
+ skt->clk = clk;
+ soc_pcmcia_init_one(skt, ops, &dev->dev);
ret = pxa2xx_drv_pcmcia_add_one(skt);
if (ret)
- break;
+ goto err1;
}
- if (ret) {
- while (--i >= 0)
- soc_pcmcia_remove_one(&sinfo->skt[i]);
- kfree(sinfo);
- } else {
- pxa2xx_configure_sockets(&dev->dev);
- dev_set_drvdata(&dev->dev, sinfo);
- }
+ pxa2xx_configure_sockets(&dev->dev);
+ dev_set_drvdata(&dev->dev, sinfo);
+ return 0;
+
+err1:
+ while (--i >= 0)
+ soc_pcmcia_remove_one(&sinfo->skt[i]);
+ clk_put(clk);
+ kfree(sinfo);
+err0:
return ret;
}
@@ -322,6 +348,7 @@ static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)
for (i = 0; i < sinfo->nskt; i++)
soc_pcmcia_remove_one(&sinfo->skt[i]);
+ clk_put(sinfo->clk);
kfree(sinfo);
return 0;
}
diff --git a/drivers/pcmcia/pxa2xx_base.h b/drivers/pcmcia/pxa2xx_base.h
index bb62ea87b8f..b609b45469e 100644
--- a/drivers/pcmcia/pxa2xx_base.h
+++ b/drivers/pcmcia/pxa2xx_base.h
@@ -1,3 +1,4 @@
int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt);
void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops);
+void pxa2xx_configure_sockets(struct device *dev);
diff --git a/drivers/pcmcia/pxa2xx_cm_x255.c b/drivers/pcmcia/pxa2xx_cm_x255.c
index 05913d0bbdb..da40908b29d 100644
--- a/drivers/pcmcia/pxa2xx_cm_x255.c
+++ b/drivers/pcmcia/pxa2xx_cm_x255.c
@@ -14,8 +14,7 @@
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
+#include <linux/export.h>
#include "soc_common.h"
@@ -26,17 +25,6 @@
#define GPIO_PCMCIA_S1_RDYINT (8)
#define GPIO_PCMCIA_RESET (9)
-#define PCMCIA_S0_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID)
-#define PCMCIA_S1_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S1_CD_VALID)
-#define PCMCIA_S0_RDYINT IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT)
-#define PCMCIA_S1_RDYINT IRQ_GPIO(GPIO_PCMCIA_S1_RDYINT)
-
-
-static struct pcmcia_irqs irqs[] = {
- { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" },
- { 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" },
-};
-
static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset");
@@ -44,17 +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;
- 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);
}
@@ -62,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 */
}
@@ -102,23 +88,12 @@ static int cmx255_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void cmx255_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void cmx255_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
-
static struct pcmcia_low_level cmx255_pcmcia_ops __initdata = {
.owner = THIS_MODULE,
.hw_init = cmx255_pcmcia_hw_init,
.hw_shutdown = cmx255_pcmcia_shutdown,
.socket_state = cmx255_pcmcia_socket_state,
.configure_socket = cmx255_pcmcia_configure_socket,
- .socket_init = cmx255_pcmcia_socket_init,
- .socket_suspend = cmx255_pcmcia_socket_suspend,
.nr = 1,
};
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
index 5662646b84d..f59223f2307 100644
--- a/drivers/pcmcia/pxa2xx_cm_x270.c
+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
@@ -14,8 +14,7 @@
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
+#include <linux/export.h>
#include "soc_common.h"
@@ -23,14 +22,6 @@
#define GPIO_PCMCIA_S0_RDYINT (82)
#define GPIO_PCMCIA_RESET (53)
-#define PCMCIA_S0_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID)
-#define PCMCIA_S0_RDYINT IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT)
-
-
-static struct pcmcia_irqs irqs[] = {
- { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" },
-};
-
static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset");
@@ -38,17 +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;
- 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 */
}
@@ -82,23 +67,12 @@ static int cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void cmx270_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void cmx270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
-
static struct pcmcia_low_level cmx270_pcmcia_ops __initdata = {
.owner = THIS_MODULE,
.hw_init = cmx270_pcmcia_hw_init,
.hw_shutdown = cmx270_pcmcia_shutdown,
.socket_state = cmx270_pcmcia_socket_state,
.configure_socket = cmx270_pcmcia_configure_socket,
- .socket_init = cmx270_pcmcia_socket_init,
- .socket_suspend = cmx270_pcmcia_socket_suspend,
.nr = 1,
};
diff --git a/drivers/pcmcia/pxa2xx_cm_x2xx.c b/drivers/pcmcia/pxa2xx_cm_x2xx.c
index 4f09506ad8d..6e7dcfd22ed 100644
--- a/drivers/pcmcia/pxa2xx_cm_x2xx.c
+++ b/drivers/pcmcia/pxa2xx_cm_x2xx.c
@@ -12,9 +12,8 @@
#include <linux/module.h>
-#include <asm/system.h>
#include <asm/mach-types.h>
-#include <mach/system.h>
+#include <mach/hardware.h>
int cmx255_pcmcia_init(void);
int cmx270_pcmcia_init(void);
diff --git a/drivers/pcmcia/pxa2xx_colibri.c b/drivers/pcmcia/pxa2xx_colibri.c
new file mode 100644
index 00000000000..4dee7b2a803
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_colibri.c
@@ -0,0 +1,169 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_colibri.c
+ *
+ * Driver for Toradex Colibri PXA270 CF socket
+ *
+ * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * 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/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+
+#include "soc_common.h"
+
+#define COLIBRI270_RESET_GPIO 53
+#define COLIBRI270_PPEN_GPIO 107
+#define COLIBRI270_BVD1_GPIO 83
+#define COLIBRI270_BVD2_GPIO 82
+#define COLIBRI270_DETECT_GPIO 84
+#define COLIBRI270_READY_GPIO 1
+
+#define COLIBRI320_RESET_GPIO 77
+#define COLIBRI320_PPEN_GPIO 57
+#define COLIBRI320_BVD1_GPIO 53
+#define COLIBRI320_BVD2_GPIO 79
+#define COLIBRI320_DETECT_GPIO 81
+#define COLIBRI320_READY_GPIO 29
+
+enum {
+ DETECT = 0,
+ READY = 1,
+ BVD1 = 2,
+ BVD2 = 3,
+ PPEN = 4,
+ RESET = 5,
+};
+
+/* Contents of this array are configured on-the-fly in init function */
+static struct gpio colibri_pcmcia_gpios[] = {
+ { 0, GPIOF_IN, "PCMCIA Detect" },
+ { 0, GPIOF_IN, "PCMCIA Ready" },
+ { 0, GPIOF_IN, "PCMCIA BVD1" },
+ { 0, GPIOF_IN, "PCMCIA BVD2" },
+ { 0, GPIOF_INIT_LOW, "PCMCIA PPEN" },
+ { 0, GPIOF_INIT_HIGH,"PCMCIA Reset" },
+};
+
+static int colibri_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ int ret;
+
+ ret = gpio_request_array(colibri_pcmcia_gpios,
+ ARRAY_SIZE(colibri_pcmcia_gpios));
+ if (ret)
+ goto err1;
+
+ 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";
+
+err1:
+ return ret;
+}
+
+static void colibri_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+ gpio_free_array(colibri_pcmcia_gpios,
+ ARRAY_SIZE(colibri_pcmcia_gpios));
+}
+
+static void colibri_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+
+ state->detect = !!gpio_get_value(colibri_pcmcia_gpios[DETECT].gpio);
+ 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->vs_3v = 1;
+ state->vs_Xv = 0;
+}
+
+static int
+colibri_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ gpio_set_value(colibri_pcmcia_gpios[PPEN].gpio,
+ !(state->Vcc == 33 && state->Vpp < 50));
+ gpio_set_value(colibri_pcmcia_gpios[RESET].gpio,
+ state->flags & SS_RESET);
+ return 0;
+}
+
+static struct pcmcia_low_level colibri_pcmcia_ops = {
+ .owner = THIS_MODULE,
+
+ .first = 0,
+ .nr = 1,
+
+ .hw_init = colibri_pcmcia_hw_init,
+ .hw_shutdown = colibri_pcmcia_hw_shutdown,
+
+ .socket_state = colibri_pcmcia_socket_state,
+ .configure_socket = colibri_pcmcia_configure_socket,
+};
+
+static struct platform_device *colibri_pcmcia_device;
+
+static int __init colibri_pcmcia_init(void)
+{
+ int ret;
+
+ if (!machine_is_colibri() && !machine_is_colibri320())
+ return -ENODEV;
+
+ colibri_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+ if (!colibri_pcmcia_device)
+ return -ENOMEM;
+
+ /* Colibri PXA270 */
+ if (machine_is_colibri()) {
+ colibri_pcmcia_gpios[RESET].gpio = COLIBRI270_RESET_GPIO;
+ colibri_pcmcia_gpios[PPEN].gpio = COLIBRI270_PPEN_GPIO;
+ colibri_pcmcia_gpios[BVD1].gpio = COLIBRI270_BVD1_GPIO;
+ colibri_pcmcia_gpios[BVD2].gpio = COLIBRI270_BVD2_GPIO;
+ colibri_pcmcia_gpios[DETECT].gpio = COLIBRI270_DETECT_GPIO;
+ colibri_pcmcia_gpios[READY].gpio = COLIBRI270_READY_GPIO;
+ /* Colibri PXA320 */
+ } else if (machine_is_colibri320()) {
+ colibri_pcmcia_gpios[RESET].gpio = COLIBRI320_RESET_GPIO;
+ colibri_pcmcia_gpios[PPEN].gpio = COLIBRI320_PPEN_GPIO;
+ colibri_pcmcia_gpios[BVD1].gpio = COLIBRI320_BVD1_GPIO;
+ colibri_pcmcia_gpios[BVD2].gpio = COLIBRI320_BVD2_GPIO;
+ colibri_pcmcia_gpios[DETECT].gpio = COLIBRI320_DETECT_GPIO;
+ colibri_pcmcia_gpios[READY].gpio = COLIBRI320_READY_GPIO;
+ }
+
+ ret = platform_device_add_data(colibri_pcmcia_device,
+ &colibri_pcmcia_ops, sizeof(colibri_pcmcia_ops));
+
+ if (!ret)
+ ret = platform_device_add(colibri_pcmcia_device);
+
+ if (ret)
+ platform_device_put(colibri_pcmcia_device);
+
+ return ret;
+}
+
+static void __exit colibri_pcmcia_exit(void)
+{
+ platform_device_unregister(colibri_pcmcia_device);
+}
+
+module_init(colibri_pcmcia_init);
+module_exit(colibri_pcmcia_exit);
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("PCMCIA support for Toradex Colibri PXA270/PXA320");
+MODULE_ALIAS("platform:pxa2xx-pcmcia");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/pxa2xx_e740.c b/drivers/pcmcia/pxa2xx_e740.c
index 8bfbd4dca13..8751a323b44 100644
--- a/drivers/pcmcia/pxa2xx_e740.c
+++ b/drivers/pcmcia/pxa2xx_e740.c
@@ -23,50 +23,27 @@
#include "soc_common.h"
-static struct pcmcia_irqs cd_irqs[] = {
- {
- .sock = 0,
- .irq = IRQ_GPIO(GPIO_E740_PCMCIA_CD0),
- .str = "CF card detect"
- },
- {
- .sock = 1,
- .irq = IRQ_GPIO(GPIO_E740_PCMCIA_CD1),
- .str = "Wifi switch"
- },
-};
-
static int e740_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
- skt->socket.pci_irq = skt->nr == 0 ? IRQ_GPIO(GPIO_E740_PCMCIA_RDY0) :
- IRQ_GPIO(GPIO_E740_PCMCIA_RDY1);
-
- 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;
}
@@ -106,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_hx4700.c b/drivers/pcmcia/pxa2xx_hx4700.c
new file mode 100644
index 00000000000..7dfef3ee5b5
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_hx4700.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 Paul Parsons <lost.distance@yahoo.com>
+ *
+ * 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/platform_device.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <mach/hx4700.h>
+
+#include "soc_common.h"
+
+static struct gpio gpios[] = {
+ { GPIO114_HX4700_CF_RESET, GPIOF_OUT_INIT_LOW, "CF reset" },
+ { EGPIO4_CF_3V3_ON, GPIOF_OUT_INIT_LOW, "CF 3.3V enable" },
+};
+
+static int hx4700_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ int ret;
+
+ ret = gpio_request_array(gpios, ARRAY_SIZE(gpios));
+ if (ret)
+ goto out;
+
+ /*
+ * IRQ type must be set before soc_pcmcia_hw_init() calls request_irq().
+ * The asic3 default IRQ type is level trigger low level detect, exactly
+ * the the signal present on GPIOD4_CF_nCD when a CF card is inserted.
+ * If the IRQ type is not changed, the asic3 interrupt handler will loop
+ * repeatedly because it is unable to clear the level trigger interrupt.
+ */
+ irq_set_irq_type(gpio_to_irq(GPIOD4_CF_nCD), IRQ_TYPE_EDGE_BOTH);
+
+ skt->stat[SOC_STAT_CD].gpio = GPIOD4_CF_nCD;
+ skt->stat[SOC_STAT_CD].name = "PCMCIA CD";
+ skt->stat[SOC_STAT_RDY].gpio = GPIO60_HX4700_CF_RNB;
+ skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready";
+
+out:
+ return ret;
+}
+
+static void hx4700_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+ gpio_free_array(gpios, ARRAY_SIZE(gpios));
+}
+
+static void hx4700_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+ struct pcmcia_state *state)
+{
+ state->vs_3v = 1;
+ state->vs_Xv = 0;
+}
+
+static int hx4700_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+ const socket_state_t *state)
+{
+ switch (state->Vcc) {
+ case 0:
+ gpio_set_value(EGPIO4_CF_3V3_ON, 0);
+ break;
+ case 33:
+ gpio_set_value(EGPIO4_CF_3V3_ON, 1);
+ break;
+ default:
+ printk(KERN_ERR "pcmcia: Unsupported Vcc: %d\n", state->Vcc);
+ return -EINVAL;
+ }
+
+ gpio_set_value(GPIO114_HX4700_CF_RESET, (state->flags & SS_RESET) != 0);
+
+ return 0;
+}
+
+static struct pcmcia_low_level hx4700_pcmcia_ops = {
+ .owner = THIS_MODULE,
+ .nr = 1,
+ .hw_init = hx4700_pcmcia_hw_init,
+ .hw_shutdown = hx4700_pcmcia_hw_shutdown,
+ .socket_state = hx4700_pcmcia_socket_state,
+ .configure_socket = hx4700_pcmcia_configure_socket,
+};
+
+static struct platform_device *hx4700_pcmcia_device;
+
+static int __init hx4700_pcmcia_init(void)
+{
+ struct platform_device *pdev;
+
+ if (!machine_is_h4700())
+ return -ENODEV;
+
+ pdev = platform_device_register_data(NULL, "pxa2xx-pcmcia", -1,
+ &hx4700_pcmcia_ops, sizeof(hx4700_pcmcia_ops));
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ hx4700_pcmcia_device = pdev;
+
+ return 0;
+}
+
+static void __exit hx4700_pcmcia_exit(void)
+{
+ platform_device_unregister(hx4700_pcmcia_device);
+}
+
+module_init(hx4700_pcmcia_init);
+module_exit(hx4700_pcmcia_exit);
+
+MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>");
+MODULE_DESCRIPTION("HP iPAQ hx4700 PCMCIA driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 92016fe932b..7e32e25cdcb 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,
@@ -128,22 +126,11 @@ static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return ret;
}
-static void mst_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void mst_pcmcia_socket_suspend(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,
- .socket_init = mst_pcmcia_socket_init,
- .socket_suspend = mst_pcmcia_socket_suspend,
.nr = 2,
};
diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c
index 6fb6f7f0672..ed7d4dbc39f 100644
--- a/drivers/pcmcia/pxa2xx_palmld.c
+++ b/drivers/pcmcia/pxa2xx_palmld.c
@@ -4,7 +4,7 @@
* Driver for Palm LifeDrive PCMCIA
*
* Copyright (C) 2006 Alex Osborne <ato@meshy.org>
- * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2007-2011 Marek Vasut <marek.vasut@gmail.com>
*
* 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
@@ -20,59 +20,33 @@
#include <mach/palmld.h>
#include "soc_common.h"
+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" },
+};
+
static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
int ret;
- ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_POWER, "PCMCIA PWR");
- if (ret)
- goto err1;
- ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_POWER, 0);
- if (ret)
- goto err2;
-
- ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_RESET, "PCMCIA RST");
- if (ret)
- goto err2;
- ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_RESET, 1);
- if (ret)
- goto err3;
-
- ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_READY, "PCMCIA RDY");
- if (ret)
- goto err3;
- ret = gpio_direction_input(GPIO_NR_PALMLD_PCMCIA_READY);
- if (ret)
- goto err4;
+ ret = gpio_request_array(palmld_pcmcia_gpios,
+ ARRAY_SIZE(palmld_pcmcia_gpios));
- skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY);
- return 0;
+ skt->stat[SOC_STAT_RDY].gpio = GPIO_NR_PALMLD_PCMCIA_READY;
+ skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready";
-err4:
- gpio_free(GPIO_NR_PALMLD_PCMCIA_READY);
-err3:
- gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET);
-err2:
- gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER);
-err1:
return ret;
}
static void palmld_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
{
- gpio_free(GPIO_NR_PALMLD_PCMCIA_READY);
- gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET);
- gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER);
+ gpio_free_array(palmld_pcmcia_gpios, ARRAY_SIZE(palmld_pcmcia_gpios));
}
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;
}
@@ -87,14 +61,6 @@ static int palmld_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void palmld_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void palmld_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level palmld_pcmcia_ops = {
.owner = THIS_MODULE,
@@ -106,9 +72,6 @@ static struct pcmcia_low_level palmld_pcmcia_ops = {
.socket_state = palmld_pcmcia_socket_state,
.configure_socket = palmld_pcmcia_configure_socket,
-
- .socket_init = palmld_pcmcia_socket_init,
- .socket_suspend = palmld_pcmcia_socket_suspend,
};
static struct platform_device *palmld_pcmcia_device;
diff --git a/drivers/pcmcia/pxa2xx_palmtc.c b/drivers/pcmcia/pxa2xx_palmtc.c
index 459a232d66b..81225a7a8cb 100644
--- a/drivers/pcmcia/pxa2xx_palmtc.c
+++ b/drivers/pcmcia/pxa2xx_palmtc.c
@@ -4,7 +4,7 @@
* Driver for Palm Tungsten|C PCMCIA
*
* Copyright (C) 2008 Alex Osborne <ato@meshy.org>
- * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2009-2011 Marek Vasut <marek.vasut@gmail.com>
*
* 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
@@ -21,89 +21,36 @@
#include <mach/palmtc.h>
#include "soc_common.h"
+static struct gpio palmtc_pcmcia_gpios[] = {
+ { GPIO_NR_PALMTC_PCMCIA_POWER1, GPIOF_INIT_LOW, "PCMCIA Power 1" },
+ { 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_PWRREADY, GPIOF_IN, "PCMCIA Power Ready" },
+};
+
static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
int ret;
- ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER1, "PCMCIA PWR1");
- if (ret)
- goto err1;
- ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER1, 0);
- if (ret)
- goto err2;
-
- ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER2, "PCMCIA PWR2");
- if (ret)
- goto err2;
- ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER2, 0);
- if (ret)
- goto err3;
-
- ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER3, "PCMCIA PWR3");
- if (ret)
- goto err3;
- ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER3, 0);
- if (ret)
- goto err4;
+ ret = gpio_request_array(palmtc_pcmcia_gpios,
+ ARRAY_SIZE(palmtc_pcmcia_gpios));
- ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_RESET, "PCMCIA RST");
- if (ret)
- goto err4;
- ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_RESET, 1);
- if (ret)
- goto err5;
+ skt->stat[SOC_STAT_RDY].gpio = GPIO_NR_PALMTC_PCMCIA_READY;
+ skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready";
- ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_READY, "PCMCIA RDY");
- if (ret)
- goto err5;
- ret = gpio_direction_input(GPIO_NR_PALMTC_PCMCIA_READY);
- if (ret)
- goto err6;
-
- ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_PWRREADY, "PCMCIA PWRRDY");
- if (ret)
- goto err6;
- ret = gpio_direction_input(GPIO_NR_PALMTC_PCMCIA_PWRREADY);
- if (ret)
- goto err7;
-
- skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY);
- return 0;
-
-err7:
- gpio_free(GPIO_NR_PALMTC_PCMCIA_PWRREADY);
-err6:
- gpio_free(GPIO_NR_PALMTC_PCMCIA_READY);
-err5:
- gpio_free(GPIO_NR_PALMTC_PCMCIA_RESET);
-err4:
- gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER3);
-err3:
- gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER2);
-err2:
- gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER1);
-err1:
return ret;
}
static void palmtc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
{
- gpio_free(GPIO_NR_PALMTC_PCMCIA_PWRREADY);
- gpio_free(GPIO_NR_PALMTC_PCMCIA_READY);
- gpio_free(GPIO_NR_PALMTC_PCMCIA_RESET);
- gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER3);
- gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER2);
- gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER1);
+ gpio_free_array(palmtc_pcmcia_gpios, ARRAY_SIZE(palmtc_pcmcia_gpios));
}
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;
}
@@ -166,14 +113,6 @@ static int palmtc_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return ret;
}
-static void palmtc_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void palmtc_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level palmtc_pcmcia_ops = {
.owner = THIS_MODULE,
@@ -185,9 +124,6 @@ static struct pcmcia_low_level palmtc_pcmcia_ops = {
.socket_state = palmtc_pcmcia_socket_state,
.configure_socket = palmtc_pcmcia_configure_socket,
-
- .socket_init = palmtc_pcmcia_socket_init,
- .socket_suspend = palmtc_pcmcia_socket_suspend,
};
static struct platform_device *palmtc_pcmcia_device;
diff --git a/drivers/pcmcia/pxa2xx_palmtx.c b/drivers/pcmcia/pxa2xx_palmtx.c
index b07b247a399..069b6bbcf31 100644
--- a/drivers/pcmcia/pxa2xx_palmtx.c
+++ b/drivers/pcmcia/pxa2xx_palmtx.c
@@ -3,7 +3,7 @@
*
* Driver for Palm T|X PCMCIA
*
- * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2007-2011 Marek Vasut <marek.vasut@gmail.com>
*
* 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
@@ -13,77 +13,40 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/gpio.h>
#include <asm/mach-types.h>
-
-#include <mach/gpio.h>
#include <mach/palmtx.h>
-
#include "soc_common.h"
+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" },
+};
+
static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
int ret;
- ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER1, "PCMCIA PWR1");
- if (ret)
- goto err1;
- ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER1, 0);
- if (ret)
- goto err2;
-
- ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER2, "PCMCIA PWR2");
- if (ret)
- goto err2;
- ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER2, 0);
- if (ret)
- goto err3;
+ ret = gpio_request_array(palmtx_pcmcia_gpios,
+ ARRAY_SIZE(palmtx_pcmcia_gpios));
- ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_RESET, "PCMCIA RST");
- if (ret)
- goto err3;
- ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_RESET, 1);
- if (ret)
- goto err4;
+ skt->stat[SOC_STAT_RDY].gpio = GPIO_NR_PALMTX_PCMCIA_READY;
+ skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready";
- ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_READY, "PCMCIA RDY");
- if (ret)
- goto err4;
- ret = gpio_direction_input(GPIO_NR_PALMTX_PCMCIA_READY);
- if (ret)
- goto err5;
-
- skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMTX_PCMCIA_READY);
- return 0;
-
-err5:
- gpio_free(GPIO_NR_PALMTX_PCMCIA_READY);
-err4:
- gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET);
-err3:
- gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2);
-err2:
- gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1);
-err1:
return ret;
}
static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
{
- gpio_free(GPIO_NR_PALMTX_PCMCIA_READY);
- gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET);
- gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2);
- gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1);
+ gpio_free_array(palmtx_pcmcia_gpios, ARRAY_SIZE(palmtx_pcmcia_gpios));
}
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;
}
@@ -100,14 +63,6 @@ palmtx_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void palmtx_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void palmtx_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level palmtx_pcmcia_ops = {
.owner = THIS_MODULE,
@@ -119,9 +74,6 @@ static struct pcmcia_low_level palmtx_pcmcia_ops = {
.socket_state = palmtx_pcmcia_socket_state,
.configure_socket = palmtx_pcmcia_configure_socket,
-
- .socket_init = palmtx_pcmcia_socket_init,
- .socket_suspend = palmtx_pcmcia_socket_suspend,
};
static struct platform_device *palmtx_pcmcia_device;
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 0ea3b29440e..89ebd8c7663 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -46,24 +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;
-
- if (platform_scoop_config->pcmcia_init)
- platform_scoop_config->pcmcia_init();
-
- /* 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;
@@ -71,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,10 +194,9 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
sharpsl_pcmcia_init_reset(skt);
}
-static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = {
+static struct pcmcia_low_level sharpsl_pcmcia_ops = {
.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,
@@ -237,7 +208,7 @@ static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = {
#ifdef CONFIG_SA1100_COLLIE
#include "sa11xx_base.h"
-int __init pcmcia_collie_init(struct device *dev)
+int pcmcia_collie_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/pxa2xx_stargate2.c b/drivers/pcmcia/pxa2xx_stargate2.c
index d08802fe35f..1d73c4401fd 100644
--- a/drivers/pcmcia/pxa2xx_stargate2.c
+++ b/drivers/pcmcia/pxa2xx_stargate2.c
@@ -28,37 +28,32 @@
#include "soc_common.h"
-#define SG2_S0_BUFF_CTL 120
#define SG2_S0_POWER_CTL 108
#define SG2_S0_GPIO_RESET 82
#define SG2_S0_GPIO_DETECT 53
#define SG2_S0_GPIO_READY 81
-static struct pcmcia_irqs irqs[] = {
- { 0, IRQ_GPIO(SG2_S0_GPIO_DETECT), "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 = IRQ_GPIO(SG2_S0_GPIO_READY);
- 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,
@@ -88,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,
};
@@ -122,37 +104,23 @@ static int __init sg2_pcmcia_init(void)
if (!sg2_pcmcia_device)
return -ENOMEM;
- ret = gpio_request(SG2_S0_BUFF_CTL, "SG2 CF buff ctl");
+ ret = gpio_request_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
if (ret)
goto error_put_platform_device;
- ret = gpio_request(SG2_S0_POWER_CTL, "SG2 CF power ctl");
- if (ret)
- goto error_free_gpio_buff_ctl;
- ret = gpio_request(SG2_S0_GPIO_RESET, "SG2 CF reset");
- if (ret)
- goto error_free_gpio_power_ctl;
- /* Set gpio directions */
- gpio_direction_output(SG2_S0_BUFF_CTL, 0);
- gpio_direction_output(SG2_S0_POWER_CTL, 1);
- gpio_direction_output(SG2_S0_GPIO_RESET, 1);
ret = platform_device_add_data(sg2_pcmcia_device,
&sg2_pcmcia_ops,
sizeof(sg2_pcmcia_ops));
if (ret)
- goto error_free_gpio_reset;
+ goto error_free_gpios;
ret = platform_device_add(sg2_pcmcia_device);
if (ret)
- goto error_free_gpio_reset;
+ goto error_free_gpios;
return 0;
-error_free_gpio_reset:
- gpio_free(SG2_S0_GPIO_RESET);
-error_free_gpio_power_ctl:
- gpio_free(SG2_S0_POWER_CTL);
-error_free_gpio_buff_ctl:
- gpio_free(SG2_S0_BUFF_CTL);
+error_free_gpios:
+ gpio_free_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
error_put_platform_device:
platform_device_put(sg2_pcmcia_device);
@@ -162,9 +130,7 @@ error_put_platform_device:
static void __exit sg2_pcmcia_exit(void)
{
platform_device_unregister(sg2_pcmcia_device);
- gpio_free(SG2_S0_BUFF_CTL);
- gpio_free(SG2_S0_POWER_CTL);
- gpio_free(SG2_S0_GPIO_RESET);
+ gpio_free_array(sg2_pcmcia_gpios, ARRAY_SIZE(sg2_pcmcia_gpios));
}
fs_initcall(sg2_pcmcia_init);
diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c
index b7e596620db..d326ba1fa1c 100644
--- a/drivers/pcmcia/pxa2xx_trizeps4.c
+++ b/drivers/pcmcia/pxa2xx_trizeps4.c
@@ -29,75 +29,25 @@
extern void board_pcmcia_power(int power);
-static struct pcmcia_irqs irqs[] = {
- { 0, IRQ_GPIO(GPIO_PCD), "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 = IRQ_GPIO(GPIO_PRDY);
+ 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;
-
-#ifndef CONFIG_MACH_TRIZEPS_CONXS
- case 1:
-#endif
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];
@@ -121,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
@@ -139,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
@@ -207,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,
@@ -226,6 +171,9 @@ static int __init trizeps_pcmcia_init(void)
{
int ret;
+ if (!machine_is_trizeps4() && !machine_is_trizeps4wl())
+ return -ENODEV;
+
trizeps_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
if (!trizeps_pcmcia_device)
return -ENOMEM;
diff --git a/drivers/pcmcia/pxa2xx_viper.c b/drivers/pcmcia/pxa2xx_viper.c
index a51f2077644..a76f495953a 100644
--- a/drivers/pcmcia/pxa2xx_viper.c
+++ b/drivers/pcmcia/pxa2xx_viper.c
@@ -25,20 +25,13 @@
#include <asm/irq.h>
-#include <mach/arcom-pcmcia.h>
+#include <linux/platform_data/pcmcia-pxa2xx_viper.h>
#include "soc_common.h"
#include "pxa2xx_base.h"
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;
}
@@ -136,22 +109,12 @@ static int viper_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
return 0;
}
-static void viper_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
-{
-}
-
-static void viper_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
-{
-}
-
static struct pcmcia_low_level viper_pcmcia_ops = {
.owner = THIS_MODULE,
.hw_init = viper_pcmcia_hw_init,
.hw_shutdown = viper_pcmcia_hw_shutdown,
.socket_state = viper_pcmcia_socket_state,
.configure_socket = viper_pcmcia_configure_socket,
- .socket_init = viper_pcmcia_socket_init,
- .socket_suspend = viper_pcmcia_socket_suspend,
.nr = 1,
};
@@ -214,18 +177,7 @@ static struct platform_driver viper_pcmcia_driver = {
.id_table = viper_pcmcia_id_table,
};
-static int __init viper_pcmcia_init(void)
-{
- return platform_driver_register(&viper_pcmcia_driver);
-}
-
-static void __exit viper_pcmcia_exit(void)
-{
- return platform_driver_unregister(&viper_pcmcia_driver);
-}
-
-module_init(viper_pcmcia_init);
-module_exit(viper_pcmcia_exit);
+module_platform_driver(viper_pcmcia_driver);
MODULE_DEVICE_TABLE(platform, viper_pcmcia_id_table);
MODULE_LICENSE("GPL");
diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c
index 55627eccee8..a47dcd24a26 100644
--- a/drivers/pcmcia/pxa2xx_vpac270.c
+++ b/drivers/pcmcia/pxa2xx_vpac270.c
@@ -3,8 +3,7 @@
*
* Driver for Voipac PXA270 PCMCIA and CF sockets
*
- * Copyright (C) 2010
- * Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2010-2011 Marek Vasut <marek.vasut@gmail.com>
*
* 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
@@ -12,27 +11,24 @@
*
*/
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <asm/mach-types.h>
-#include <mach/gpio.h>
+#include <asm/gpio.h>
#include <mach/vpac270.h>
#include "soc_common.h"
-static struct pcmcia_irqs cd_irqs[] = {
- {
- .sock = 0,
- .irq = IRQ_GPIO(GPIO84_VPAC270_PCMCIA_CD),
- .str = "PCMCIA CD"
- },
- {
- .sock = 1,
- .irq = IRQ_GPIO(GPIO17_VPAC270_CF_CD),
- .str = "CF CD"
- },
+static struct gpio vpac270_pcmcia_gpios[] = {
+ { GPIO107_VPAC270_PCMCIA_PPEN, GPIOF_INIT_LOW, "PCMCIA PPEN" },
+ { GPIO11_VPAC270_PCMCIA_RESET, GPIOF_INIT_LOW, "PCMCIA Reset" },
+};
+
+static struct gpio vpac270_cf_gpios[] = {
+ { GPIO16_VPAC270_CF_RESET, GPIOF_INIT_LOW, "CF Reset" },
};
static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
@@ -40,111 +36,39 @@ static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
int ret;
if (skt->nr == 0) {
- ret = gpio_request(GPIO84_VPAC270_PCMCIA_CD, "PCMCIA CD");
- if (ret)
- goto err1;
- ret = gpio_direction_input(GPIO84_VPAC270_PCMCIA_CD);
- if (ret)
- goto err2;
-
- ret = gpio_request(GPIO35_VPAC270_PCMCIA_RDY, "PCMCIA RDY");
- if (ret)
- goto err2;
- ret = gpio_direction_input(GPIO35_VPAC270_PCMCIA_RDY);
- if (ret)
- goto err3;
-
- ret = gpio_request(GPIO107_VPAC270_PCMCIA_PPEN, "PCMCIA PPEN");
- if (ret)
- goto err3;
- ret = gpio_direction_output(GPIO107_VPAC270_PCMCIA_PPEN, 0);
- if (ret)
- goto err4;
-
- ret = gpio_request(GPIO11_VPAC270_PCMCIA_RESET, "PCMCIA RESET");
- if (ret)
- goto err4;
- ret = gpio_direction_output(GPIO11_VPAC270_PCMCIA_RESET, 0);
- if (ret)
- goto err5;
-
- skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY);
-
- return soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1);
-
-err5:
- gpio_free(GPIO11_VPAC270_PCMCIA_RESET);
-err4:
- gpio_free(GPIO107_VPAC270_PCMCIA_PPEN);
-err3:
- gpio_free(GPIO35_VPAC270_PCMCIA_RDY);
-err2:
- gpio_free(GPIO84_VPAC270_PCMCIA_CD);
-err1:
- return ret;
+ ret = gpio_request_array(vpac270_pcmcia_gpios,
+ ARRAY_SIZE(vpac270_pcmcia_gpios));
+ 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(GPIO17_VPAC270_CF_CD, "CF CD");
- if (ret)
- goto err6;
- ret = gpio_direction_input(GPIO17_VPAC270_CF_CD);
- if (ret)
- goto err7;
-
- ret = gpio_request(GPIO12_VPAC270_CF_RDY, "CF RDY");
- if (ret)
- goto err7;
- ret = gpio_direction_input(GPIO12_VPAC270_CF_RDY);
- if (ret)
- goto err8;
-
- ret = gpio_request(GPIO16_VPAC270_CF_RESET, "CF RESET");
- if (ret)
- goto err8;
- ret = gpio_direction_output(GPIO16_VPAC270_CF_RESET, 0);
- if (ret)
- goto err9;
-
- skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY);
-
- return soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1);
-
-err9:
- gpio_free(GPIO16_VPAC270_CF_RESET);
-err8:
- gpio_free(GPIO12_VPAC270_CF_RDY);
-err7:
- gpio_free(GPIO17_VPAC270_CF_CD);
-err6:
- return ret;
+ ret = gpio_request_array(vpac270_cf_gpios,
+ ARRAY_SIZE(vpac270_cf_gpios));
+ 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_hw_shutdown(struct soc_pcmcia_socket *skt)
{
- gpio_free(GPIO11_VPAC270_PCMCIA_RESET);
- gpio_free(GPIO107_VPAC270_PCMCIA_PPEN);
- gpio_free(GPIO35_VPAC270_PCMCIA_RDY);
- gpio_free(GPIO84_VPAC270_PCMCIA_CD);
- gpio_free(GPIO16_VPAC270_CF_RESET);
- gpio_free(GPIO12_VPAC270_CF_RDY);
- gpio_free(GPIO17_VPAC270_CF_CD);
+ if (skt->nr == 0)
+ gpio_free_array(vpac270_pcmcia_gpios,
+ ARRAY_SIZE(vpac270_pcmcia_gpios));
+ else
+ gpio_free_array(vpac270_cf_gpios,
+ ARRAY_SIZE(vpac270_cf_gpios));
}
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;
}
@@ -166,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,
@@ -185,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/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c
index d0bf3502106..f53c237bda2 100644
--- a/drivers/pcmcia/rsrc_iodyn.c
+++ b/drivers/pcmcia/rsrc_iodyn.c
@@ -16,9 +16,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
@@ -88,7 +86,7 @@ static struct resource *__iodyn_find_io_region(struct pcmcia_socket *s,
static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
unsigned int *base, unsigned int num,
- unsigned int align)
+ unsigned int align, struct resource **parent)
{
int i, ret = 0;
@@ -129,6 +127,7 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
((res->flags & ~IORESOURCE_BITS) |
(attr & IORESOURCE_BITS));
s->io[i].InUse = num;
+ *parent = res;
return 0;
}
@@ -136,10 +135,11 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
try = res->end + 1;
if ((*base == 0) || (*base == try)) {
if (adjust_resource(s->io[i].res, res->start,
- res->end - res->start + num + 1))
+ resource_size(res) + num))
continue;
*base = try;
s->io[i].InUse += num;
+ *parent = res;
return 0;
}
@@ -147,11 +147,12 @@ static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
try = res->start - num;
if ((*base == 0) || (*base == try)) {
if (adjust_resource(s->io[i].res,
- res->start - num,
- res->end - res->start + num + 1))
+ res->start - num,
+ resource_size(res) + num))
continue;
*base = try;
s->io[i].InUse += num;
+ *parent = res;
return 0;
}
}
@@ -164,8 +165,6 @@ struct pccard_resource_ops pccard_iodyn_ops = {
.validate_mem = NULL,
.find_io = iodyn_find_io,
.find_mem = NULL,
- .add_io = NULL,
- .add_mem = NULL,
.init = static_init,
.exit = NULL,
};
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 142efac3c38..aa628ed0e9f 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -16,9 +16,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
@@ -48,11 +46,12 @@ struct resource *pcmcia_make_resource(unsigned long start, unsigned long end,
static int static_find_io(struct pcmcia_socket *s, unsigned int attr,
unsigned int *base, unsigned int num,
- unsigned int align)
+ unsigned int align, struct resource **parent)
{
if (!s->io_offset)
return -EINVAL;
*base = s->io_offset | (*base & 0x0fff);
+ *parent = NULL;
return 0;
}
@@ -62,8 +61,6 @@ struct pccard_resource_ops pccard_static_ops = {
.validate_mem = NULL,
.find_io = static_find_io,
.find_mem = NULL,
- .add_io = NULL,
- .add_mem = NULL,
.init = static_init,
.exit = NULL,
};
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index dcd1a4ad3d6..065704c605d 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -28,9 +28,7 @@
#include <asm/irq.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
@@ -64,6 +62,9 @@ struct socket_data {
#define MEM_PROBE_LOW (1 << 0)
#define MEM_PROBE_HIGH (1 << 1)
+/* Action field */
+#define REMOVE_MANAGED_RESOURCE 1
+#define ADD_MANAGED_RESOURCE 2
/*======================================================================
@@ -368,12 +369,12 @@ static int do_validate_mem(struct pcmcia_socket *s,
}
}
- free_region(res2);
- free_region(res1);
-
dev_dbg(&s->dev, "cs: memory probe 0x%06lx-0x%06lx: %p %p %u %u %u",
base, base+size-1, res1, res2, ret, info1, info2);
+ free_region(res2);
+ free_region(res1);
+
if ((ret) || (info1 != info2) || (info1 == 0))
return -EINVAL;
@@ -716,7 +717,7 @@ static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s,
static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
unsigned int *base, unsigned int num,
- unsigned int align)
+ unsigned int align, struct resource **parent)
{
int i, ret = 0;
@@ -758,6 +759,7 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
((res->flags & ~IORESOURCE_BITS) |
(attr & IORESOURCE_BITS));
s->io[i].InUse = num;
+ *parent = res;
return 0;
}
@@ -768,11 +770,12 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
res->end + num);
if (!ret) {
ret = adjust_resource(s->io[i].res, res->start,
- res->end - res->start + num + 1);
+ resource_size(res) + num);
if (ret)
continue;
*base = try;
s->io[i].InUse += num;
+ *parent = res;
return 0;
}
}
@@ -785,12 +788,13 @@ static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
res->end);
if (!ret) {
ret = adjust_resource(s->io[i].res,
- res->start - num,
- res->end - res->start + num + 1);
+ res->start - num,
+ resource_size(res) + num);
if (ret)
continue;
*base = try;
s->io[i].InUse += num;
+ *parent = res;
return 0;
}
}
@@ -1055,8 +1059,6 @@ struct pccard_resource_ops pccard_nonstatic_ops = {
.validate_mem = pcmcia_nonstatic_validate_mem,
.find_io = nonstatic_find_io,
.find_mem = nonstatic_find_mem_region,
- .add_io = adjust_io,
- .add_mem = adjust_memory,
.init = nonstatic_init,
.exit = nonstatic_release_resource_db,
};
@@ -1115,8 +1117,6 @@ static ssize_t store_io_db(struct device *dev,
mutex_lock(&s->ops_mutex);
ret = adjust_io(s, add, start_addr, end_addr);
- if (!ret)
- s->resource_setup_new = 1;
mutex_unlock(&s->ops_mutex);
return ret ? ret : count;
@@ -1183,8 +1183,6 @@ static ssize_t store_mem_db(struct device *dev,
mutex_lock(&s->ops_mutex);
ret = adjust_memory(s, add, start_addr, end_addr);
- if (!ret)
- s->resource_setup_new = 1;
mutex_unlock(&s->ops_mutex);
return ret ? ret : count;
@@ -1201,7 +1199,7 @@ static const struct attribute_group rsrc_attributes = {
.attrs = pccard_rsrc_attributes,
};
-static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
+static int pccard_sysfs_add_rsrc(struct device *dev,
struct class_interface *class_intf)
{
struct pcmcia_socket *s = dev_get_drvdata(dev);
@@ -1211,7 +1209,7 @@ static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
return sysfs_create_group(&dev->kobj, &rsrc_attributes);
}
-static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
+static void pccard_sysfs_remove_rsrc(struct device *dev,
struct class_interface *class_intf)
{
struct pcmcia_socket *s = dev_get_drvdata(dev);
@@ -1224,7 +1222,7 @@ static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
static struct class_interface pccard_rsrc_interface __refdata = {
.class = &pcmcia_socket_class,
.add_dev = &pccard_sysfs_add_rsrc,
- .remove_dev = __devexit_p(&pccard_sysfs_remove_rsrc),
+ .remove_dev = &pccard_sysfs_remove_rsrc,
};
static int __init nonstatic_sysfs_init(void)
diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c
index fd013a1ef47..44cfc4416e5 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 9bf088b1727..b3774e5d039 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,37 +68,20 @@ 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 __init pcmcia_cerf_init(struct device *dev)
+int pcmcia_cerf_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index edbd8c47262..ff8a027a4af 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -35,8 +35,6 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include <asm/hardware/scoop.h>
@@ -55,6 +53,9 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
#if defined(CONFIG_SA1100_H3100) || defined(CONFIG_SA1100_H3600)
pcmcia_h3600_init,
#endif
+#ifdef CONFIG_SA1100_NANOENGINE
+ pcmcia_nanoengine_init,
+#endif
#ifdef CONFIG_SA1100_SHANNON
pcmcia_shannon_init,
#endif
diff --git a/drivers/pcmcia/sa1100_generic.h b/drivers/pcmcia/sa1100_generic.h
index 794f96a35bb..adb08dbc723 100644
--- a/drivers/pcmcia/sa1100_generic.h
+++ b/drivers/pcmcia/sa1100_generic.h
@@ -13,6 +13,7 @@ extern int pcmcia_freebird_init(struct device *);
extern int pcmcia_gcplus_init(struct device *);
extern int pcmcia_graphicsmaster_init(struct device *);
extern int pcmcia_h3600_init(struct device *);
+extern int pcmcia_nanoengine_init(struct device *);
extern int pcmcia_pangolin_init(struct device *);
extern int pcmcia_pfs168_init(struct device *);
extern int pcmcia_shannon_init(struct device *);
diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c
index 56329ad575a..431d8b07cba 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
@@ -219,7 +153,7 @@ struct pcmcia_low_level h3600_pcmcia_ops = {
.socket_suspend = h3600_pcmcia_socket_suspend,
};
-int __init pcmcia_h3600_init(struct device *dev)
+int pcmcia_h3600_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1100_nanoengine.c b/drivers/pcmcia/sa1100_nanoengine.c
new file mode 100644
index 00000000000..35c30ff41e8
--- /dev/null
+++ b/drivers/pcmcia/sa1100_nanoengine.c
@@ -0,0 +1,133 @@
+/*
+ * drivers/pcmcia/sa1100_nanoengine.c
+ *
+ * PCMCIA implementation routines for BSI nanoEngine.
+ *
+ * In order to have a fully functional pcmcia subsystem in a BSE nanoEngine
+ * board you should carefully read this:
+ * http://cambuca.ldhs.cetuc.puc-rio.br/nanoengine/
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * Based on original work for kernel 2.4 by
+ * Miguel Freitas <miguel@cpti.cetuc.puc-rio.br>
+ *
+ * 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/device.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/nanoengine.h>
+
+#include "sa1100_generic.h"
+
+struct nanoengine_pins {
+ unsigned output_pins;
+ unsigned clear_outputs;
+ int gpio_rst;
+ int gpio_cd;
+ int gpio_rdy;
+};
+
+static struct nanoengine_pins nano_skts[] = {
+ {
+ .gpio_rst = GPIO_PC_RESET0,
+ .gpio_cd = GPIO_PC_CD0,
+ .gpio_rdy = GPIO_PC_READY0,
+ }, {
+ .gpio_rst = GPIO_PC_RESET1,
+ .gpio_cd = GPIO_PC_CD1,
+ .gpio_rdy = GPIO_PC_READY1,
+ }
+};
+
+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;
+
+ 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 0;
+}
+
+static void nanoengine_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+ 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 i = skt->nr;
+
+ if (i >= num_nano_pcmcia_sockets)
+ return -ENXIO;
+
+ 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 i = skt->nr;
+
+ if (i >= num_nano_pcmcia_sockets)
+ return;
+
+ state->bvd1 = 1;
+ state->bvd2 = 1;
+ state->vs_3v = 1; /* Can only apply 3.3V */
+ state->vs_Xv = 0;
+}
+
+static struct pcmcia_low_level nanoengine_pcmcia_ops = {
+ .owner = THIS_MODULE,
+
+ .hw_init = nanoengine_pcmcia_hw_init,
+ .hw_shutdown = nanoengine_pcmcia_hw_shutdown,
+
+ .configure_socket = nanoengine_pcmcia_configure_socket,
+ .socket_state = nanoengine_pcmcia_socket_state,
+};
+
+int pcmcia_nanoengine_init(struct device *dev)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_nanoengine())
+ ret = sa11xx_drv_pcmcia_probe(
+ dev, &nanoengine_pcmcia_ops, 0, 2);
+
+ return ret;
+}
+
diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c
index c4d51867a05..b07a2dc3296 100644
--- a/drivers/pcmcia/sa1100_shannon.c
+++ b/drivers/pcmcia/sa1100_shannon.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -15,40 +16,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 +52,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,28 +85,14 @@ 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 __init pcmcia_shannon_init(struct device *dev)
+int pcmcia_shannon_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index 05bd504e6f1..73fd37968b6 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -15,47 +15,40 @@
#include <mach/simpad.h>
#include "sa1100_generic.h"
-extern long get_cs3_shadow(void);
-extern void set_cs3_bit(int value);
-extern void clear_cs3_bit(int value);
-
-static struct pcmcia_irqs irqs[] = {
- { 1, IRQ_GPIO_CF_CD, "CF_CD" },
-};
-
static int simpad_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+ 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: */
- //set_cs3_bit(PCMCIA_BUFF_DIS);
- clear_cs3_bit(PCMCIA_RESET);
+ /*simpad_set_cs3_bit(PCMCIA_BUFF_DIS);*/
+ simpad_clear_cs3_bit(PCMCIA_RESET);
}
static void
simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
struct pcmcia_state *state)
{
- unsigned long levels = GPLR;
- long cs3reg = get_cs3_shadow();
-
- state->detect=((levels & GPIO_CF_CD)==0)?1:0;
- state->ready=(levels & GPIO_CF_IRQ)?1:0;
- state->bvd1=1; /* Not available on Simpad. */
- state->bvd2=1; /* Not available on Simpad. */
- state->wrprot=0; /* Not available on Simpad. */
-
- if((cs3reg & 0x0c) == 0x0c) {
+ long cs3reg = simpad_get_cs3_ro();
+
+ /* 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 */
+
+ if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) ==
+ (PCMCIA_VS1|PCMCIA_VS2)) {
state->vs_3v=0;
state->vs_Xv=0;
} else {
@@ -75,23 +68,23 @@ simpad_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
/* Murphy: see table of MIC2562a-1 */
switch (state->Vcc) {
case 0:
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+ simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
break;
case 33:
- clear_cs3_bit(VCC_3V_EN|EN1);
- set_cs3_bit(VCC_5V_EN|EN0);
+ simpad_clear_cs3_bit(VCC_3V_EN|EN1);
+ simpad_set_cs3_bit(VCC_5V_EN|EN0);
break;
case 50:
- clear_cs3_bit(VCC_5V_EN|EN1);
- set_cs3_bit(VCC_3V_EN|EN0);
+ simpad_clear_cs3_bit(VCC_5V_EN|EN1);
+ simpad_set_cs3_bit(VCC_3V_EN|EN0);
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
__func__, state->Vcc);
- clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+ simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
local_irq_restore(flags);
return -1;
}
@@ -102,15 +95,9 @@ 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));
- set_cs3_bit(PCMCIA_RESET);
+ simpad_set_cs3_bit(PCMCIA_RESET);
}
static struct pcmcia_low_level simpad_pcmcia_ops = {
@@ -119,11 +106,10 @@ 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,
};
-int __init pcmcia_simpad_init(struct device *dev)
+int pcmcia_simpad_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1111_badge4.c
index 1ce53f493be..4d206f4dd67 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 59866905ea3..65b02c3e14c 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);
@@ -199,18 +211,20 @@ static int pcmcia_probe(struct sa1111_dev *dev)
return 0;
}
-static int __devexit pcmcia_remove(struct sa1111_dev *dev)
+static int pcmcia_remove(struct sa1111_dev *dev)
{
struct sa1111_pcmcia_socket *next, *s = dev_get_drvdata(&dev->dev);
dev_set_drvdata(&dev->dev, NULL);
- for (; next = s->next, s; s = next) {
+ for (; s; s = next) {
+ next = s->next;
soc_pcmcia_remove_one(&s->soc);
kfree(s);
}
release_mem_region(dev->res.start, 512);
+ sa1111_disable_device(dev);
return 0;
}
@@ -220,7 +234,7 @@ static struct sa1111_driver pcmcia_driver = {
},
.devid = SA1111_DEVID_PCMCIA,
.probe = pcmcia_probe,
- .remove = __devexit_p(pcmcia_remove),
+ .remove = pcmcia_remove,
};
static int __init sa1111_drv_pcmcia_init(void)
diff --git a/drivers/pcmcia/sa1111_generic.h b/drivers/pcmcia/sa1111_generic.h
index 02dc8577cda..f6376e34a7e 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 6bcabee6bde..3baa3ef0968 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,12 +87,11 @@ 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,
};
-int __devinit pcmcia_jornada720_init(struct device *dev)
+int pcmcia_jornada720_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/sa1111_lubbock.c
index b9f8c8fb42b..c5caf579045 100644
--- a/drivers/pcmcia/pxa2xx_lubbock.c
+++ b/drivers/pcmcia/sa1111_lubbock.c
@@ -187,7 +187,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
* 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
- * avaliable in the seat pocket in front of you!
+ * available in the seat pocket in front of you!
*/
((socket_state_t *)state)->Vcc = 50;
((socket_state_t *)state)->Vpp = 50;
@@ -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,
};
@@ -226,6 +225,7 @@ int pcmcia_lubbock_init(struct sa1111_dev *sadev)
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);
}
diff --git a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1111_neponset.c
index c95639b5f2a..1d78739c4c0 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 fa28d8911b0..54d3089d157 100644
--- a/drivers/pcmcia/sa11xx_base.c
+++ b/drivers/pcmcia/sa11xx_base.c
@@ -41,7 +41,6 @@
#include <mach/hardware.h>
#include <asm/irq.h>
-#include <asm/system.h>
#include "soc_common.h"
#include "sa11xx_base.h"
@@ -126,9 +125,6 @@ sa1100_pcmcia_frequency_change(struct soc_pcmcia_socket *skt,
if (freqs->new < freqs->old)
sa1100_pcmcia_set_mecr(skt, freqs->new);
break;
- case CPUFREQ_RESUMECHANGE:
- sa1100_pcmcia_set_mecr(skt, freqs->new);
- break;
}
return 0;
@@ -231,15 +227,12 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops,
sinfo->nskt = nr;
- /* Initiliaze processor specific parameters */
+ /* Initialize processor specific parameters */
for (i = 0; i < nr; i++) {
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 6f1a86b43c6..a2bc6ee1702 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -31,24 +31,26 @@
======================================================================*/
-#include <linux/module.h>
-#include <linux/moduleparam.h>
+#include <linux/cpufreq.h>
+#include <linux/gpio.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/spinlock.h>
-#include <linux/cpufreq.h>
+#include <linux/timer.h>
#include <mach/hardware.h>
-#include <asm/io.h>
-#include <asm/system.h>
#include "soc_common.h"
+static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev);
+
#ifdef CONFIG_PCMCIA_DEBUG
static int pc_debug;
@@ -57,18 +59,25 @@ module_param(pc_debug, int, 0644);
void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func,
int lvl, const char *fmt, ...)
{
+ struct va_format vaf;
va_list args;
if (pc_debug > lvl) {
- printk(KERN_DEBUG "skt%u: %s: ", skt->nr, func);
va_start(args, fmt);
- vprintk(fmt, args);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_DEBUG "skt%u: %s: %pV", skt->nr, func, &vaf);
+
va_end(args);
}
}
+EXPORT_SYMBOL(soc_pcmcia_debug);
#endif
-#define to_soc_pcmcia_socket(x) container_of(x, struct soc_pcmcia_socket, socket)
+#define to_soc_pcmcia_socket(x) \
+ container_of(x, struct soc_pcmcia_socket, socket)
static unsigned short
calc_speed(unsigned short *spds, int num, unsigned short dflt)
@@ -85,14 +94,105 @@ calc_speed(unsigned short *spds, int num, unsigned short dflt)
return speed;
}
-void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing)
+void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt,
+ struct soc_pcmcia_timing *timing)
{
- timing->io = calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
- timing->mem = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
- timing->attr = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+ timing->io =
+ calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
+ timing->mem =
+ calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+ timing->attr =
+ calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
}
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;
@@ -100,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;
@@ -131,8 +247,8 @@ static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
*
* Convert PCMCIA socket state to our socket configure structure.
*/
-static int
-soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state)
+static int soc_common_pcmcia_config_skt(
+ struct soc_pcmcia_socket *skt, socket_state_t *state)
{
int ret;
@@ -144,10 +260,11 @@ soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *stat
*/
if (skt->irq_state != 1 && state->io_irq) {
skt->irq_state = 1;
- set_irq_type(skt->socket.pci_irq, IRQ_TYPE_EDGE_FALLING);
+ irq_set_irq_type(skt->socket.pci_irq,
+ IRQ_TYPE_EDGE_FALLING);
} else if (skt->irq_state == 1 && state->io_irq == 0) {
skt->irq_state = 0;
- set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
+ irq_set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
}
skt->cs_state = *state;
@@ -174,8 +291,9 @@ static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock)
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
debug(skt, 2, "initializing socket\n");
-
- skt->ops->socket_init(skt);
+ if (skt->ops->socket_init)
+ skt->ops->socket_init(skt);
+ soc_pcmcia_hw_enable(skt);
return 0;
}
@@ -195,7 +313,9 @@ static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock)
debug(skt, 2, "suspending socket\n");
- skt->ops->socket_suspend(skt);
+ soc_pcmcia_hw_disable(skt);
+ if (skt->ops->socket_suspend)
+ skt->ops->socket_suspend(skt);
return 0;
}
@@ -298,24 +418,24 @@ soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
* of power configuration, reset, &c. We also record the value of
* `state' in order to regurgitate it to the PCMCIA core later.
*/
-static int
-soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+static int soc_common_pcmcia_set_socket(
+ struct pcmcia_socket *sock, socket_state_t *state)
{
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
- debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
- (state->csc_mask==0)?"<NONE> ":"",
- (state->csc_mask&SS_DETECT)?"DETECT ":"",
- (state->csc_mask&SS_READY)?"READY ":"",
- (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
- (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
- (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
- (state->flags==0)?"<NONE> ":"",
- (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
- (state->flags&SS_IOCARD)?"IOCARD ":"",
- (state->flags&SS_RESET)?"RESET ":"",
- (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
- (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
+ debug(skt, 2, "mask: %s%s%s%s%s%s flags: %s%s%s%s%s%s Vcc %d Vpp %d irq %d\n",
+ (state->csc_mask == 0) ? "<NONE> " : "",
+ (state->csc_mask & SS_DETECT) ? "DETECT " : "",
+ (state->csc_mask & SS_READY) ? "READY " : "",
+ (state->csc_mask & SS_BATDEAD) ? "BATDEAD " : "",
+ (state->csc_mask & SS_BATWARN) ? "BATWARN " : "",
+ (state->csc_mask & SS_STSCHG) ? "STSCHG " : "",
+ (state->flags == 0) ? "<NONE> " : "",
+ (state->flags & SS_PWR_AUTO) ? "PWR_AUTO " : "",
+ (state->flags & SS_IOCARD) ? "IOCARD " : "",
+ (state->flags & SS_RESET) ? "RESET " : "",
+ (state->flags & SS_SPKR_ENA) ? "SPKR_ENA " : "",
+ (state->flags & SS_OUTPUT_ENA) ? "OUTPUT_ENA " : "",
state->Vcc, state->Vpp, state->io_irq);
return soc_common_pcmcia_config_skt(skt, state);
@@ -330,8 +450,8 @@ soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
*
* Returns: 0 on success, -1 on error
*/
-static int
-soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
+static int soc_common_pcmcia_set_io_map(
+ struct pcmcia_socket *sock, struct pccard_io_map *map)
{
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
unsigned short speed = map->speed;
@@ -340,14 +460,14 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
map->map, map->speed, (unsigned long long)map->start,
(unsigned long long)map->stop);
debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
- (map->flags==0)?"<NONE>":"",
- (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
- (map->flags&MAP_16BIT)?"16BIT ":"",
- (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
- (map->flags&MAP_0WS)?"0WS ":"",
- (map->flags&MAP_WRPROT)?"WRPROT ":"",
- (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
- (map->flags&MAP_PREFETCH)?"PREFETCH ":"");
+ (map->flags == 0) ? "<NONE>" : "",
+ (map->flags & MAP_ACTIVE) ? "ACTIVE " : "",
+ (map->flags & MAP_16BIT) ? "16BIT " : "",
+ (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "",
+ (map->flags & MAP_0WS) ? "0WS " : "",
+ (map->flags & MAP_WRPROT) ? "WRPROT " : "",
+ (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "",
+ (map->flags & MAP_PREFETCH) ? "PREFETCH " : "");
if (map->map >= MAX_IO_WIN) {
printk(KERN_ERR "%s(): map (%d) out of range\n", __func__,
@@ -384,8 +504,8 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
*
* Returns: 0 on success, -ERRNO on error
*/
-static int
-soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
+static int soc_common_pcmcia_set_mem_map(
+ struct pcmcia_socket *sock, struct pccard_mem_map *map)
{
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
struct resource *res;
@@ -394,14 +514,14 @@ soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
debug(skt, 2, "map %u speed %u card_start %08x\n",
map->map, map->speed, map->card_start);
debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
- (map->flags==0)?"<NONE>":"",
- (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
- (map->flags&MAP_16BIT)?"16BIT ":"",
- (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
- (map->flags&MAP_0WS)?"0WS ":"",
- (map->flags&MAP_WRPROT)?"WRPROT ":"",
- (map->flags&MAP_ATTRIB)?"ATTRIB ":"",
- (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
+ (map->flags == 0) ? "<NONE>" : "",
+ (map->flags & MAP_ACTIVE) ? "ACTIVE " : "",
+ (map->flags & MAP_16BIT) ? "16BIT " : "",
+ (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "",
+ (map->flags & MAP_0WS) ? "0WS " : "",
+ (map->flags & MAP_WRPROT) ? "WRPROT " : "",
+ (map->flags & MAP_ATTRIB) ? "ATTRIB " : "",
+ (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "");
if (map->map >= MAX_WIN)
return -EINVAL;
@@ -456,8 +576,8 @@ static struct bittbl conf_bits[] = {
{ SS_OUTPUT_ENA, "SS_OUTPUT_ENA" },
};
-static void
-dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, int sz)
+static void dump_bits(char **p, const char *prefix,
+ unsigned int val, struct bittbl *bits, int sz)
{
char *b = *p;
int i;
@@ -475,13 +595,14 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i
*
* Returns: the number of characters added to the buffer
*/
-static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_status(
+ struct device *dev, struct device_attribute *attr, char *buf)
{
struct soc_pcmcia_socket *skt =
container_of(dev, struct soc_pcmcia_socket, socket.dev);
char *p = buf;
- p+=sprintf(p, "slot : %d\n", skt->nr);
+ p += sprintf(p, "slot : %d\n", skt->nr);
dump_bits(&p, "status", skt->status,
status_bits, ARRAY_SIZE(status_bits));
@@ -490,12 +611,12 @@ static ssize_t show_status(struct device *dev, struct device_attribute *attr, ch
dump_bits(&p, "cs_flags", skt->cs_state.flags,
conf_bits, ARRAY_SIZE(conf_bits));
- p+=sprintf(p, "Vcc : %d\n", skt->cs_state.Vcc);
- p+=sprintf(p, "Vpp : %d\n", skt->cs_state.Vpp);
- p+=sprintf(p, "IRQ : %d (%d)\n", skt->cs_state.io_irq,
+ p += sprintf(p, "Vcc : %d\n", skt->cs_state.Vcc);
+ p += sprintf(p, "Vpp : %d\n", skt->cs_state.Vpp);
+ p += sprintf(p, "IRQ : %d (%d)\n", skt->cs_state.io_irq,
skt->socket.pci_irq);
if (skt->ops->show_timing)
- p+=skt->ops->show_timing(skt, p);
+ p += skt->ops->show_timing(skt, p);
return p-buf;
}
@@ -512,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;
- 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)
- 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) {
- set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_RISING);
- 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);
@@ -588,7 +646,7 @@ soc_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
mutex_lock(&soc_pcmcia_sockets_lock);
list_for_each_entry(skt, &soc_pcmcia_sockets, node)
- if ( skt->ops->frequency_change )
+ if (skt->ops->frequency_change)
ret += skt->ops->frequency_change(skt, val, freqs);
mutex_unlock(&soc_pcmcia_sockets_lock);
@@ -614,12 +672,28 @@ fs_initcall(soc_pcmcia_cpufreq_register);
static void soc_pcmcia_cpufreq_unregister(void)
{
- cpufreq_unregister_notifier(&soc_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+ cpufreq_unregister_notifier(&soc_pcmcia_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
}
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);
@@ -627,10 +701,9 @@ void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
pcmcia_unregister_socket(&skt->socket);
- flush_scheduled_work();
-
- 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);
@@ -687,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;
@@ -720,9 +793,7 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
pcmcia_unregister_socket(&skt->socket);
out_err_7:
- flush_scheduled_work();
-
- 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 e40824ce6b0..e6fcbea5b68 100644
--- a/drivers/pcmcia/soc_common.h
+++ b/drivers/pcmcia/soc_common.h
@@ -10,9 +10,8 @@
#define _ASM_ARCH_PCMCIA
/* include the world */
+#include <linux/clk.h>
#include <linux/cpufreq.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
@@ -31,6 +30,7 @@ struct soc_pcmcia_socket {
* Info from low level handler
*/
unsigned int nr;
+ struct clk *clk;
/*
* Core PCMCIA state
@@ -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;
@@ -58,6 +68,7 @@ struct soc_pcmcia_socket {
struct skt_dev_info {
int nskt;
+ struct clk *clk;
struct soc_pcmcia_socket skt[0];
};
@@ -114,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);
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 80e36bc407d..d6881514d38 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -23,12 +23,9 @@
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/mutex.h>
-#include <asm/system.h>
#include <asm/irq.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 56004a1b5bb..cbe15fc3741 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -47,10 +47,7 @@
#include <linux/bitops.h>
#include <asm/io.h>
-#include <asm/system.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include "tcic.h"
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index 9ffa97d0b16..a71789486cd 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -691,7 +691,7 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
/*
* those are either single or dual slot CB with additional functions
* like 1394, smartcard reader, etc. check the TIEALL flag for them
- * the TIEALL flag binds the IRQ of all functions toghether.
+ * the TIEALL flag binds the IRQ of all functions together.
* we catch the single slot variants later.
*/
sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 86e4a1a3c64..d98a0861249 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -246,6 +246,7 @@ static int pccard_init(struct pcmcia_socket *sock)
socket = &vrc4171_sockets[slot];
socket->csc_irq = search_nonuse_irq();
socket->io_irq = search_nonuse_irq();
+ spin_lock_init(&socket->lock);
return 0;
}
@@ -564,7 +565,7 @@ static inline void reserve_using_irq(int slot)
vrc4171_irq_mask &= ~(1 << irq);
}
-static int __devinit vrc4171_add_sockets(void)
+static int vrc4171_add_sockets(void)
{
vrc4171_socket_t *socket;
int slot, retval;
@@ -631,7 +632,7 @@ static void vrc4171_remove_sockets(void)
}
}
-static int __devinit vrc4171_card_setup(char *options)
+static int vrc4171_card_setup(char *options)
{
if (options == NULL || *options == '\0')
return 1;
@@ -712,7 +713,7 @@ static struct platform_driver vrc4171_card_driver = {
},
};
-static int __devinit vrc4171_card_init(void)
+static int vrc4171_card_init(void)
{
int retval;
@@ -746,7 +747,7 @@ static int __devinit vrc4171_card_init(void)
return 0;
}
-static void __devexit vrc4171_card_exit(void)
+static void vrc4171_card_exit(void)
{
free_irq(vrc4171_irq, vrc4171_sockets);
vrc4171_remove_sockets();
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index 9b3c15827e5..d92692056e2 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -456,12 +456,12 @@ static void cardu_interrupt(int irq, void *dev_id)
}
}
-static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
+static int vrc4173_cardu_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
vrc4173_socket_t *socket;
unsigned long start, len, flags;
- int slot, err;
+ int slot, err, ret;
slot = vrc4173_cardu_slots++;
socket = &cardu_sockets[slot];
@@ -474,46 +474,66 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
return err;
start = pci_resource_start(dev, 0);
- if (start == 0)
- return -ENODEV;
+ if (start == 0) {
+ ret = -ENODEV;
+ goto disable;
+ }
len = pci_resource_len(dev, 0);
- if (len == 0)
- return -ENODEV;
+ if (len == 0) {
+ ret = -ENODEV;
+ goto disable;
+ }
- if (((flags = pci_resource_flags(dev, 0)) & IORESOURCE_MEM) == 0)
- return -EBUSY;
+ flags = pci_resource_flags(dev, 0);
+ if ((flags & IORESOURCE_MEM) == 0) {
+ ret = -EBUSY;
+ goto disable;
+ }
- if ((err = pci_request_regions(dev, socket->name)) < 0)
- return err;
+ err = pci_request_regions(dev, socket->name);
+ if (err < 0) {
+ ret = err;
+ goto disable;
+ }
socket->base = ioremap(start, len);
- if (socket->base == NULL)
- return -ENODEV;
+ if (socket->base == NULL) {
+ ret = -ENODEV;
+ goto release;
+ }
socket->dev = dev;
socket->pcmcia_socket = pcmcia_register_socket(slot, &cardu_operations, 1);
if (socket->pcmcia_socket == NULL) {
- iounmap(socket->base);
- socket->base = NULL;
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto unmap;
}
if (request_irq(dev->irq, cardu_interrupt, IRQF_SHARED, socket->name, socket) < 0) {
- pcmcia_unregister_socket(socket->pcmcia_socket);
- socket->pcmcia_socket = NULL;
- iounmap(socket->base);
- socket->base = NULL;
- return -EBUSY;
+ ret = -EBUSY;
+ goto unregister;
}
printk(KERN_INFO "%s at %#08lx, IRQ %d\n", socket->name, start, dev->irq);
return 0;
+
+unregister:
+ pcmcia_unregister_socket(socket->pcmcia_socket);
+ socket->pcmcia_socket = NULL;
+unmap:
+ iounmap(socket->base);
+ socket->base = NULL;
+release:
+ pci_release_regions(dev);
+disable:
+ pci_disable_device(dev);
+ return ret;
}
-static int __devinit vrc4173_cardu_setup(char *options)
+static int vrc4173_cardu_setup(char *options)
{
if (options == NULL || *options == '\0')
return 1;
@@ -543,11 +563,8 @@ static int __devinit vrc4173_cardu_setup(char *options)
__setup("vrc4173_cardu=", vrc4173_cardu_setup);
-static struct pci_device_id vrc4173_cardu_id_table[] __devinitdata = {
- { .vendor = PCI_VENDOR_ID_NEC,
- .device = PCI_DEVICE_ID_NEC_NAPCCARD,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID, },
+static DEFINE_PCI_DEVICE_TABLE(vrc4173_cardu_id_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NAPCCARD) },
{0, }
};
@@ -557,14 +574,14 @@ static struct pci_driver vrc4173_cardu_driver = {
.id_table = vrc4173_cardu_id_table,
};
-static int __devinit vrc4173_cardu_init(void)
+static int vrc4173_cardu_init(void)
{
vrc4173_cardu_slots = 0;
return pci_register_driver(&vrc4173_cardu_driver);
}
-static void __devexit vrc4173_cardu_exit(void)
+static void vrc4173_cardu_exit(void)
{
pci_unregister_driver(&vrc4173_cardu_driver);
}
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
index 201ccfa1e97..95f5b270ad4 100644
--- a/drivers/pcmcia/xxs1500_ss.c
+++ b/drivers/pcmcia/xxs1500_ss.c
@@ -17,13 +17,10 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
#include <asm/irq.h>
-#include <asm/system.h>
#include <asm/mach-au1x00/au1000.h>
#define MEM_MAP_SIZE 0x400000
@@ -207,7 +204,7 @@ static struct pccard_operations xxs1500_pcmcia_operations = {
.set_mem_map = au1x00_pcmcia_set_mem_map,
};
-static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev)
+static int xxs1500_pcmcia_probe(struct platform_device *pdev)
{
struct xxs1500_pcmcia_sock *sock;
struct resource *r;
@@ -276,7 +273,7 @@ static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev)
* edge detector.
*/
irq = gpio_to_irq(GPIO_CDA);
- set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
+ irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
ret = request_irq(irq, cdirq, 0, "pcmcia_carddetect", sock);
if (ret) {
dev_err(&pdev->dev, "cannot setup cd irq\n");
@@ -302,7 +299,7 @@ out0:
return ret;
}
-static int __devexit xxs1500_pcmcia_remove(struct platform_device *pdev)
+static int xxs1500_pcmcia_remove(struct platform_device *pdev)
{
struct xxs1500_pcmcia_sock *sock = platform_get_drvdata(pdev);
@@ -320,21 +317,10 @@ static struct platform_driver xxs1500_pcmcia_socket_driver = {
.owner = THIS_MODULE,
},
.probe = xxs1500_pcmcia_probe,
- .remove = __devexit_p(xxs1500_pcmcia_remove),
+ .remove = xxs1500_pcmcia_remove,
};
-int __init xxs1500_pcmcia_socket_load(void)
-{
- return platform_driver_register(&xxs1500_pcmcia_socket_driver);
-}
-
-void __exit xxs1500_pcmcia_socket_unload(void)
-{
- platform_driver_unregister(&xxs1500_pcmcia_socket_driver);
-}
-
-module_init(xxs1500_pcmcia_socket_load);
-module_exit(xxs1500_pcmcia_socket_unload);
+module_platform_driver(xxs1500_pcmcia_socket_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PCMCIA Socket Services for MyCable XXS1500 systems");
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index f1d41374eea..946f90ef602 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -19,22 +19,20 @@
#include <linux/io.h>
#include <linux/slab.h>
-#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
#include "yenta_socket.h"
#include "i82365.h"
-static int disable_clkrun;
+static bool disable_clkrun;
module_param(disable_clkrun, bool, 0444);
MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option");
-static int isa_probe = 1;
+static bool isa_probe = 1;
module_param(isa_probe, bool, 0444);
MODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing");
-static int pwr_irqs_off;
+static bool pwr_irqs_off;
module_param(pwr_irqs_off, bool, 0644);
MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!");
@@ -447,7 +445,7 @@ static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *
unsigned int start, stop, card_start;
unsigned short word;
- pcibios_resource_to_bus(socket->dev, &region, mem->res);
+ pcibios_resource_to_bus(socket->dev->bus, &region, mem->res);
map = mem->map;
start = region.start;
@@ -711,7 +709,7 @@ static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type
region.start = config_readl(socket, addr_start) & mask;
region.end = config_readl(socket, addr_end) | ~mask;
if (region.start && region.end > region.start && !override_bios) {
- pcibios_bus_to_resource(dev, res, &region);
+ pcibios_bus_to_resource(dev->bus, res, &region);
if (pci_claim_resource(dev, PCI_BRIDGE_RESOURCES + nr) == 0)
return 0;
dev_printk(KERN_INFO, &dev->dev,
@@ -785,7 +783,7 @@ static void yenta_free_resources(struct yenta_socket *socket)
/*
* Close it down - release our resources and go home..
*/
-static void __devexit yenta_close(struct pci_dev *dev)
+static void yenta_close(struct pci_dev *dev)
{
struct yenta_socket *sock = pci_get_drvdata(dev);
@@ -1035,7 +1033,7 @@ static void yenta_config_init(struct yenta_socket *socket)
struct pci_dev *dev = socket->dev;
struct pci_bus_region region;
- pcibios_resource_to_bus(socket->dev, &region, &dev->resource[0]);
+ pcibios_resource_to_bus(socket->dev->bus, &region, &dev->resource[0]);
config_writel(socket, CB_LEGACY_MODE_BASE, 0);
config_writel(socket, PCI_BASE_ADDRESS_0, region.start);
@@ -1050,8 +1048,8 @@ static void yenta_config_init(struct yenta_socket *socket)
config_writeb(socket, PCI_LATENCY_TIMER, 168);
config_writel(socket, PCI_PRIMARY_BUS,
(176 << 24) | /* sec. latency timer */
- (dev->subordinate->subordinate << 16) | /* subordinate bus */
- (dev->subordinate->secondary << 8) | /* secondary bus */
+ ((unsigned int)dev->subordinate->busn_res.end << 16) | /* subordinate bus */
+ ((unsigned int)dev->subordinate->busn_res.start << 8) | /* secondary bus */
dev->subordinate->primary); /* primary bus */
/*
@@ -1074,11 +1072,11 @@ static void yenta_config_init(struct yenta_socket *socket)
* invisible during PCI scans because of a misconfigured subordinate number
* of the parent brige - some BIOSes seem to be too lazy to set it right.
* Does the fixup carefully by checking how far it can go without conflicts.
- * See http\://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information.
+ * See http://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information.
*/
static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
{
- struct list_head *tmp;
+ struct pci_bus *sibling;
unsigned char upper_limit;
/*
* We only check and fix the parent bridge: All systems which need
@@ -1088,54 +1086,54 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
struct pci_bus *bridge_to_fix = cardbus_bridge->parent;
/* Check bus numbers are already set up correctly: */
- if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate)
+ if (bridge_to_fix->busn_res.end >= cardbus_bridge->busn_res.end)
return; /* The subordinate number is ok, nothing to do */
if (!bridge_to_fix->parent)
return; /* Root bridges are ok */
/* stay within the limits of the bus range of the parent: */
- upper_limit = bridge_to_fix->parent->subordinate;
+ upper_limit = bridge_to_fix->parent->busn_res.end;
- /* check the bus ranges of all silbling bridges to prevent overlap */
- list_for_each(tmp, &bridge_to_fix->parent->children) {
- struct pci_bus *silbling = pci_bus_b(tmp);
+ /* check the bus ranges of all sibling bridges to prevent overlap */
+ list_for_each_entry(sibling, &bridge_to_fix->parent->children,
+ node) {
/*
- * If the silbling has a higher secondary bus number
+ * If the sibling has a higher secondary bus number
* and it's secondary is equal or smaller than our
* current upper limit, set the new upper limit to
- * the bus number below the silbling's range:
+ * the bus number below the sibling's range:
*/
- if (silbling->secondary > bridge_to_fix->subordinate
- && silbling->secondary <= upper_limit)
- upper_limit = silbling->secondary - 1;
+ if (sibling->busn_res.start > bridge_to_fix->busn_res.end
+ && sibling->busn_res.start <= upper_limit)
+ upper_limit = sibling->busn_res.start - 1;
}
/* Show that the wanted subordinate number is not possible: */
- if (cardbus_bridge->subordinate > upper_limit)
+ if (cardbus_bridge->busn_res.end > upper_limit)
dev_printk(KERN_WARNING, &cardbus_bridge->dev,
"Upper limit for fixing this "
"bridge's parent bridge: #%02x\n", upper_limit);
/* If we have room to increase the bridge's subordinate number, */
- if (bridge_to_fix->subordinate < upper_limit) {
+ if (bridge_to_fix->busn_res.end < upper_limit) {
/* use the highest number of the hidden bus, within limits */
unsigned char subordinate_to_assign =
- min(cardbus_bridge->subordinate, upper_limit);
+ min_t(int, cardbus_bridge->busn_res.end, upper_limit);
dev_printk(KERN_INFO, &bridge_to_fix->dev,
"Raising subordinate bus# of parent "
"bus (#%02x) from #%02x to #%02x\n",
bridge_to_fix->number,
- bridge_to_fix->subordinate, subordinate_to_assign);
+ (int)bridge_to_fix->busn_res.end, subordinate_to_assign);
/* Save the new subordinate in the bus struct of the bridge */
- bridge_to_fix->subordinate = subordinate_to_assign;
+ bridge_to_fix->busn_res.end = subordinate_to_assign;
/* and update the PCI config space with the new subordinate */
pci_write_config_byte(bridge_to_fix->self,
- PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate);
+ PCI_SUBORDINATE_BUS, bridge_to_fix->busn_res.end);
}
}
@@ -1144,7 +1142,7 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
* interrupt, and that we can map the cardbus area. Fill in the
* socket information structure..
*/
-static int __devinit yenta_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct yenta_socket *socket;
int ret;
@@ -1354,7 +1352,7 @@ static const struct dev_pm_ops yenta_pm_ops = {
.driver_data = CARDBUS_TYPE_##type, \
}
-static struct pci_device_id yenta_table[] = {
+static DEFINE_PCI_DEVICE_TABLE(yenta_table) = {
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1031, TI),
/*
@@ -1437,24 +1435,10 @@ static struct pci_driver yenta_cardbus_driver = {
.name = "yenta_cardbus",
.id_table = yenta_table,
.probe = yenta_probe,
- .remove = __devexit_p(yenta_close),
+ .remove = yenta_close,
.driver.pm = YENTA_PM_OPS,
};
-
-static int __init yenta_socket_init(void)
-{
- return pci_register_driver(&yenta_cardbus_driver);
-}
-
-
-static void __exit yenta_socket_exit(void)
-{
- pci_unregister_driver(&yenta_cardbus_driver);
-}
-
-
-module_init(yenta_socket_init);
-module_exit(yenta_socket_exit);
+module_pci_driver(yenta_cardbus_driver);
MODULE_LICENSE("GPL");