Commit 5e4301f1 authored by Russell King's avatar Russell King

[PCMCIA] Reorganise SA11xx PCMCIA support.

The SA1100 PCMCIA structure didn't lend itself well to the device
model.  With this reorganisation, we end up with a reasonable
structure which fits better with the driver model.  It is now
obvious that SA11x0-based socket drivers are separate from
SA1111-based socket drivers, and are treated as two separate drivers
by the driver model.
parent 18e4786e
...@@ -82,10 +82,22 @@ config HD64465_PCMCIA ...@@ -82,10 +82,22 @@ config HD64465_PCMCIA
config PCMCIA_SA1100 config PCMCIA_SA1100
tristate "SA1100 support" tristate "SA1100 support"
depends on ARM && ARCH_SA1100 && PCMCIA depends on ARM && ARCH_SA1100 && PCMCIA
help
Say Y here to include support for SA11x0-based PCMCIA or CF
sockets, found on HP iPAQs, Yopy, and other StrongARM(R)/
Xscale(R) embedded machines.
This driver is also available as a module called sa1100_cs.
config PCMCIA_SA1111 config PCMCIA_SA1111
tristate "SA1111 support" tristate "SA1111 support"
depends on PCMCIA_SA1100 && SA1111 depends on ARM && ARCH_SA1100 && SA1111 && PCMCIA
help
Say Y here to include support for SA1111-based PCMCIA or CF
sockets, found on the Jornada 720, Graphicsmaster and other
StrongARM(R)/Xscale(R) embedded machines.
This driver is also available as a module called sa1111_cs.
config PCMCIA_PROBE config PCMCIA_PROBE
bool bool
......
...@@ -11,8 +11,8 @@ obj-$(CONFIG_I82365) += i82365.o ...@@ -11,8 +11,8 @@ obj-$(CONFIG_I82365) += i82365.o
obj-$(CONFIG_I82092) += i82092.o obj-$(CONFIG_I82092) += i82092.o
obj-$(CONFIG_TCIC) += tcic.o obj-$(CONFIG_TCIC) += tcic.o
obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o
obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o
yenta_socket-y += pci_socket.o yenta.o yenta_socket-y += pci_socket.o yenta.o
......
...@@ -152,36 +152,6 @@ static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz, ...@@ -152,36 +152,6 @@ static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz,
struct pcmcia_low_level; struct pcmcia_low_level;
/* This structure encapsulates per-socket state which we might need to
* use when responding to a Card Services query of some kind.
*/
struct sa1100_pcmcia_socket {
/*
* Core PCMCIA state
*/
int nr;
struct resource res;
socket_state_t cs_state;
pccard_io_map io_map[MAX_IO_WIN];
pccard_mem_map pc_mem_map[MAX_WIN];
void (*handler)(void *, unsigned int);
void *handler_info;
struct pcmcia_state k_state;
ioaddr_t phys_attr, phys_mem;
void *virt_io;
unsigned short speed_io, speed_attr, speed_mem;
/*
* Info from low level handler
*/
unsigned int irq;
unsigned int irq_state;
struct pcmcia_low_level *ops;
};
/* I/O pins replacing memory pins /* I/O pins replacing memory pins
* (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75) * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75)
* *
...@@ -191,59 +161,4 @@ struct sa1100_pcmcia_socket { ...@@ -191,59 +161,4 @@ struct sa1100_pcmcia_socket {
#define iostschg bvd1 #define iostschg bvd1
#define iospkr bvd2 #define iospkr bvd2
/*
* Declaration for all machine specific init/exit functions.
*/
extern int pcmcia_adsbitsy_init(struct device *);
extern void pcmcia_adsbitsy_exit(struct device *);
extern int pcmcia_assabet_init(struct device *);
extern void pcmcia_assabet_exit(struct device *);
extern int pcmcia_badge4_init(struct device *);
extern void pcmcia_badge4_exit(struct device *);
extern int pcmcia_cerf_init(struct device *);
extern void pcmcia_cerf_exit(struct device *);
extern int pcmcia_flexanet_init(struct device *);
extern void pcmcia_flexanet_exit(struct device *);
extern int pcmcia_freebird_init(struct device *);
extern void pcmcia_freebird_exit(struct device *);
extern int pcmcia_gcplus_init(struct device *);
extern void pcmcia_gcplus_exit(struct device *);
extern int pcmcia_graphicsmaster_init(struct device *);
extern void pcmcia_graphicsmaster_exit(struct device *);
extern int pcmcia_pangolin_init(struct device *);
extern void pcmcia_pangolin_exit(struct device *);
extern int pcmcia_pfs168_init(struct device *);
extern void pcmcia_pfs168_exit(struct device *);
extern int pcmcia_shannon_init(struct device *);
extern void pcmcia_shannon_exit(struct device *);
extern int pcmcia_simpad_init(struct device *);
extern void pcmcia_simpad_exit(struct device *);
extern int pcmcia_stork_init(struct device *);
extern void pcmcia_stork_exit(struct device *);
extern int pcmcia_system3_init(struct device *);
extern void pcmcia_system3_exit(struct device *);
extern int pcmcia_trizeps_init(struct device *);
extern void pcmcia_trizeps_exit(struct device *);
extern int pcmcia_xp860_init(struct device *);
extern void pcmcia_xp860_exit(struct device *);
extern int pcmcia_yopy_init(struct device *);
extern void pcmcia_yopy_exit(struct device *);
#endif /* !defined(_PCMCIA_SA1100_H) */ #endif /* !defined(_PCMCIA_SA1100_H) */
...@@ -18,93 +18,86 @@ ...@@ -18,93 +18,86 @@
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
static int adsbitsy_pcmcia_init(struct pcmcia_init *init) static int adsbitsy_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
/* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */ /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3); PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
/* Disable Power 3.3V/5V for PCMCIA/CF */ /* Disable Power 3.3V/5V for PCMCIA/CF */
PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3; PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
/* Why? */ /* Why? */
MECR = 0x09430943; MECR = 0x09430943;
return sa1111_pcmcia_init(init); return sa1111_pcmcia_init(skt);
} }
static int static int
adsbitsy_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) adsbitsy_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
{ {
unsigned int pa_dwr_mask, pa_dwr_set; unsigned int pa_dwr_mask, pa_dwr_set;
int ret; int ret;
switch (sock) { switch (skt->nr) {
case 0: case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1; pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
switch (conf->vcc) { switch (state->Vcc) {
default: default:
case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break; case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
case 33: pa_dwr_set = GPIO_GPIO1; break; case 33: pa_dwr_set = GPIO_GPIO1; break;
case 50: pa_dwr_set = GPIO_GPIO0; break; case 50: pa_dwr_set = GPIO_GPIO0; break;
} }
break; break;
case 1: case 1:
pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3; pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
switch (conf->vcc) { switch (state->Vcc) {
default: default:
case 0: pa_dwr_set = 0; break; case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO2; break; case 33: pa_dwr_set = GPIO_GPIO2; break;
case 50: pa_dwr_set = GPIO_GPIO3; break; case 50: pa_dwr_set = GPIO_GPIO3; break;
} }
default: default:
return -1; return -1;
} }
if (conf->vpp != conf->vcc && conf->vpp != 0) { if (state->Vpp != state->Vcc && state->Vpp != 0) {
printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n", printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
__FUNCTION__, conf->vpp); __FUNCTION__, state->Vpp);
return -1; return -1;
} }
ret = sa1111_pcmcia_configure_socket(sock, conf); ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) { if (ret == 0) {
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set; PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
local_irq_restore(flags); local_irq_restore(flags);
} }
return ret; return ret;
} }
static struct pcmcia_low_level adsbitsy_pcmcia_ops = { static struct pcmcia_low_level adsbitsy_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = adsbitsy_pcmcia_init, .hw_init = adsbitsy_pcmcia_hw_init,
.shutdown = sa1111_pcmcia_shutdown, .hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state, .socket_state = sa1111_pcmcia_socket_state,
.configure_socket = adsbitsy_pcmcia_configure_socket, .configure_socket = adsbitsy_pcmcia_configure_socket,
.socket_init = sa1111_pcmcia_socket_init,
.socket_init = sa1111_pcmcia_socket_init, .socket_suspend = sa1111_pcmcia_socket_suspend,
.socket_suspend = sa1111_pcmcia_socket_suspend,
}; };
int __init pcmcia_adsbitsy_init(struct device *dev) int __init pcmcia_adsbitsy_init(struct device *dev)
{ {
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_adsbitsy()) if (machine_is_adsbitsy())
ret = sa1100_register_pcmcia(&adsbitsy_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &adsbitsy_pcmcia_ops, 0, 2);
return ret; return ret;
} }
void __exit pcmcia_adsbitsy_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&adsbitsy_pcmcia_ops, dev);
}
...@@ -20,85 +20,47 @@ ...@@ -20,85 +20,47 @@
#include "sa1100_generic.h" #include "sa1100_generic.h"
static struct irqs { static struct pcmcia_irqs irqs[] = {
int irq; { 1, ASSABET_IRQ_GPIO_CF_CD, "CF CD" },
const char *str; { 1, ASSABET_IRQ_GPIO_CF_BVD2, "CF BVD2" },
} irqs[] = { { 1, ASSABET_IRQ_GPIO_CF_BVD1, "CF BVD1" },
{ ASSABET_IRQ_GPIO_CF_CD, "CF_CD" },
{ ASSABET_IRQ_GPIO_CF_BVD2, "CF_BVD2" },
{ ASSABET_IRQ_GPIO_CF_BVD1, "CF_BVD1" },
}; };
static int assabet_pcmcia_init(struct pcmcia_init *init) static int assabet_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
int i, res; skt->irq = ASSABET_IRQ_GPIO_CF_IRQ;
/* Register interrupts */
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
res = request_irq(irqs[i].irq, sa1100_pcmcia_interrupt,
SA_INTERRUPT, irqs[i].str, NULL);
if (res)
goto irq_err;
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
}
init->socket_irq[0] = NO_IRQ;
init->socket_irq[1] = ASSABET_IRQ_GPIO_CF_IRQ;
/* There's only one slot, but it's "Slot 1": */
return 2;
irq_err:
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irqs[i].irq, res);
while (i--) return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
free_irq(irqs[i].irq, NULL);
return res;
} }
/* /*
* Release all resources. * Release all resources.
*/ */
static int assabet_pcmcia_shutdown(void) static void assabet_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
} }
static void static void
assabet_pcmcia_socket_state(int sock, struct pcmcia_state *state) assabet_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
{ {
unsigned long levels = GPLR; unsigned long levels = GPLR;
if (sock == 1) { state->detect = (levels & ASSABET_GPIO_CF_CD) ? 0 : 1;
state->detect = (levels & ASSABET_GPIO_CF_CD) ? 0 : 1; state->ready = (levels & ASSABET_GPIO_CF_IRQ) ? 1 : 0;
state->ready = (levels & ASSABET_GPIO_CF_IRQ) ? 1 : 0; state->bvd1 = (levels & ASSABET_GPIO_CF_BVD1) ? 1 : 0;
state->bvd1 = (levels & ASSABET_GPIO_CF_BVD1) ? 1 : 0; state->bvd2 = (levels & ASSABET_GPIO_CF_BVD2) ? 1 : 0;
state->bvd2 = (levels & ASSABET_GPIO_CF_BVD2) ? 1 : 0; state->wrprot = 0; /* Not available on Assabet. */
state->wrprot = 0; /* Not available on Assabet. */ state->vs_3v = 1; /* Can only apply 3.3V on Assabet. */
state->vs_3v = 1; /* Can only apply 3.3V on Assabet. */ state->vs_Xv = 0;
state->vs_Xv = 0;
}
} }
static int static int
assabet_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configure) assabet_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
{ {
unsigned int mask; unsigned int mask;
if (sock > 1) switch (state->Vcc) {
return -1;
if (sock == 0)
return 0;
switch (configure->vcc) {
case 0: case 0:
mask = 0; mask = 0;
break; break;
...@@ -113,13 +75,13 @@ assabet_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configu ...@@ -113,13 +75,13 @@ assabet_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configu
default: default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc); state->Vcc);
return -1; return -1;
} }
/* Silently ignore Vpp, output enable, speaker enable. */ /* Silently ignore Vpp, output enable, speaker enable. */
if (configure->reset) if (state->flags & SS_RESET)
mask |= ASSABET_BCR_CF_RST; mask |= ASSABET_BCR_CF_RST;
ASSABET_BCR_frob(ASSABET_BCR_CF_RST | ASSABET_BCR_CF_PWR, mask); ASSABET_BCR_frob(ASSABET_BCR_CF_RST | ASSABET_BCR_CF_PWR, mask);
...@@ -132,48 +94,36 @@ assabet_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configu ...@@ -132,48 +94,36 @@ assabet_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configu
* be called at initialisation, power management event, or * be called at initialisation, power management event, or
* pcmcia event. * pcmcia event.
*/ */
static int assabet_pcmcia_socket_init(int sock) static void assabet_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
int i; /*
* Enable CF bus
if (sock == 1) { */
/* ASSABET_BCR_clear(ASSABET_BCR_CF_BUS_OFF);
* Enable CF bus
*/
ASSABET_BCR_clear(ASSABET_BCR_CF_BUS_OFF);
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
}
return 0; sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
} }
/* /*
* Disable card status IRQs on suspend. * Disable card status IRQs on suspend.
*/ */
static int assabet_pcmcia_socket_suspend(int sock) static void assabet_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
if (sock == 1) {
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
/*
* Tristate the CF bus signals. Also assert CF
* reset as per user guide page 4-11.
*/
ASSABET_BCR_set(ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_CF_RST);
}
return 0; /*
* Tristate the CF bus signals. Also assert CF
* reset as per user guide page 4-11.
*/
ASSABET_BCR_set(ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_CF_RST);
} }
static struct pcmcia_low_level assabet_pcmcia_ops = { static struct pcmcia_low_level assabet_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = assabet_pcmcia_init,
.shutdown = assabet_pcmcia_shutdown, .hw_init = assabet_pcmcia_hw_init,
.hw_shutdown = assabet_pcmcia_hw_shutdown,
.socket_state = assabet_pcmcia_socket_state, .socket_state = assabet_pcmcia_socket_state,
.configure_socket = assabet_pcmcia_configure_socket, .configure_socket = assabet_pcmcia_configure_socket,
...@@ -185,20 +135,8 @@ int __init pcmcia_assabet_init(struct device *dev) ...@@ -185,20 +135,8 @@ int __init pcmcia_assabet_init(struct device *dev)
{ {
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_assabet()) { if (machine_is_assabet() && !machine_has_neponset())
if (!machine_has_neponset()) ret = sa11xx_drv_pcmcia_probe(dev, &assabet_pcmcia_ops, 1, 1);
ret = sa1100_register_pcmcia(&assabet_pcmcia_ops, dev);
#ifndef CONFIG_ASSABET_NEPONSET
else
printk(KERN_ERR "Card Services disabled: missing "
"Neponset support\n");
#endif
}
return ret;
}
void __exit pcmcia_assabet_exit(struct device *dev) return ret;
{
sa1100_unregister_pcmcia(&assabet_pcmcia_ops, dev);
} }
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <asm/arch/badge4.h> #include <asm/arch/badge4.h>
#include <asm/hardware/sa1111.h> #include <asm/hardware/sa1111.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
/* /*
...@@ -62,27 +61,6 @@ static int badge4_pcmvcc = 50; /* pins 3 and 5 jumpered on JP6 */ ...@@ -62,27 +61,6 @@ static int badge4_pcmvcc = 50; /* pins 3 and 5 jumpered on JP6 */
static int badge4_pcmvpp = 50; /* pins 2 and 4 jumpered on JP6 */ static int badge4_pcmvpp = 50; /* pins 2 and 4 jumpered on JP6 */
static int badge4_cfvcc = 33; /* pins 1 and 2 jumpered on JP10 */ static int badge4_cfvcc = 33; /* pins 1 and 2 jumpered on JP10 */
static int badge4_pcmcia_init(struct pcmcia_init *init)
{
printk(KERN_INFO
"%s: badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n",
__FUNCTION__,
badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc);
return sa1111_pcmcia_init(init);
}
static int badge4_pcmcia_shutdown(void)
{
int rc = sa1111_pcmcia_shutdown();
/* be sure to disable 5v0 use */
badge4_set_5V(BADGE4_5V_PCMCIA_SOCK0, 0);
badge4_set_5V(BADGE4_5V_PCMCIA_SOCK1, 0);
return rc;
}
static void complain_about_jumpering(const char *whom, static void complain_about_jumpering(const char *whom,
const char *supply, const char *supply,
int given, int wanted) int given, int wanted)
...@@ -97,32 +75,32 @@ static void complain_about_jumpering(const char *whom, ...@@ -97,32 +75,32 @@ static void complain_about_jumpering(const char *whom,
} }
static int static int
badge4_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) badge4_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
{ {
int ret; int ret;
switch (sock) { switch (skt->nr) {
case 0: case 0:
if ((conf->vcc != 0) && if ((state->Vcc != 0) &&
(conf->vcc != badge4_pcmvcc)) { (state->Vcc != badge4_pcmvcc)) {
complain_about_jumpering(__FUNCTION__, "pcmvcc", complain_about_jumpering(__FUNCTION__, "pcmvcc",
badge4_pcmvcc, conf->vcc); badge4_pcmvcc, state->Vcc);
// Apply power regardless of the jumpering. // Apply power regardless of the jumpering.
// return -1; // return -1;
} }
if ((conf->vpp != 0) && if ((state->Vpp != 0) &&
(conf->vpp != badge4_pcmvpp)) { (state->Vpp != badge4_pcmvpp)) {
complain_about_jumpering(__FUNCTION__, "pcmvpp", complain_about_jumpering(__FUNCTION__, "pcmvpp",
badge4_pcmvpp, conf->vpp); badge4_pcmvpp, state->Vpp);
return -1; return -1;
} }
break; break;
case 1: case 1:
if ((conf->vcc != 0) && if ((state->Vcc != 0) &&
(conf->vcc != badge4_cfvcc)) { (state->Vcc != badge4_cfvcc)) {
complain_about_jumpering(__FUNCTION__, "cfvcc", complain_about_jumpering(__FUNCTION__, "cfvcc",
badge4_cfvcc, conf->vcc); badge4_cfvcc, state->Vcc);
return -1; return -1;
} }
break; break;
...@@ -131,16 +109,16 @@ badge4_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -131,16 +109,16 @@ badge4_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
return -1; return -1;
} }
ret = sa1111_pcmcia_configure_socket(sock, conf); ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) { if (ret == 0) {
unsigned long flags; unsigned long flags;
int need5V; int need5V;
local_irq_save(flags); local_irq_save(flags);
need5V = ((conf->vcc == 50) || (conf->vpp == 50)); need5V = ((state->Vcc == 50) || (state->Vpp == 50));
badge4_set_5V(BADGE4_5V_PCMCIA_SOCK(conf->sock), need5V); badge4_set_5V(BADGE4_5V_PCMCIA_SOCK(skt->nr), need5V);
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -150,8 +128,8 @@ badge4_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -150,8 +128,8 @@ badge4_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
static struct pcmcia_low_level badge4_pcmcia_ops = { static struct pcmcia_low_level badge4_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = badge4_pcmcia_init, .init = sa1111_pcmcia_hw_init,
.shutdown = badge4_pcmcia_shutdown, .shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state, .socket_state = sa1111_pcmcia_socket_state,
.configure_socket = badge4_pcmcia_configure_socket, .configure_socket = badge4_pcmcia_configure_socket,
...@@ -163,15 +141,16 @@ int pcmcia_badge4_init(struct device *dev) ...@@ -163,15 +141,16 @@ int pcmcia_badge4_init(struct device *dev)
{ {
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_badge4()) if (machine_is_badge4()) {
ret = sa1100_register_pcmcia(&badge4_pcmcia_ops, dev); printk(KERN_INFO
"%s: badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n",
__FUNCTION__,
badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc);
return ret; ret = sa11xx_drv_pcmcia_probe(dev, &badge4_pcmcia_ops, 0, 2);
} }
void __devexit pcmcia_badge4_exit(struct device *dev) return ret;
{
sa1100_unregister_pcmcia(&badge4_pcmcia_ops, dev);
} }
static int __init pcmv_setup(char *s) static int __init pcmv_setup(char *s)
......
...@@ -23,139 +23,91 @@ ...@@ -23,139 +23,91 @@
#define CERF_SOCKET 1 #define CERF_SOCKET 1
#endif #endif
static struct irqs { static struct pcmcia_irqs irqs[] = {
int irq; { CERF_SOCKET, IRQ_GPIO_CF_CD, "CF_CD" },
const char *str; { CERF_SOCKET, IRQ_GPIO_CF_BVD2, "CF_BVD2" },
} irqs[] = { { CERF_SOCKET, IRQ_GPIO_CF_BVD1, "CF_BVD1" }
{ IRQ_GPIO_CF_CD, "CF_CD" },
{ IRQ_GPIO_CF_BVD2, "CF_BVD2" },
{ IRQ_GPIO_CF_BVD1, "CF_BVD1" }
}; };
static int cerf_pcmcia_init(struct pcmcia_init *init) static int cerf_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
int i, res; skt->irq = IRQ_GPIO_CF_IRQ;
for (i = 0; i < ARRAY_SIZE(irqs); i++) { return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
res = request_irq(irqs[i].irq, sa1100_pcmcia_interrupt, SA_INTERRUPT,
irqs[i].str, NULL);
if (res)
goto irq_err;
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
}
init->socket_irq[CERF_SOCKET] = IRQ_GPIO_CF_IRQ;
return 2;
irq_err:
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irqs[i].irq, res);
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
} }
static int cerf_pcmcia_shutdown(void) static void cerf_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
} }
static void cerf_pcmcia_socket_state(int sock, struct pcmcia_state *state) static void
cerf_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
{ {
unsigned long levels=GPLR; unsigned long levels = GPLR;
if (sock == CERF_SOCKET) { state->detect=((levels & GPIO_CF_CD)==0)?1:0;
state->detect=((levels & GPIO_CF_CD)==0)?1:0; state->ready=(levels & GPIO_CF_IRQ)?1:0;
state->ready=(levels & GPIO_CF_IRQ)?1:0; state->bvd1=(levels & GPIO_CF_BVD1)?1:0;
state->bvd1=(levels & GPIO_CF_BVD1)?1:0; state->bvd2=(levels & GPIO_CF_BVD2)?1:0;
state->bvd2=(levels & GPIO_CF_BVD2)?1:0; state->wrprot=0;
state->wrprot=0; state->vs_3v=1;
state->vs_3v=1; state->vs_Xv=0;
state->vs_Xv=0;
}
} }
static int cerf_pcmcia_configure_socket(int sock, const struct pcmcia_configure static int
*configure) cerf_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
if (sock>1) switch (state->Vcc) {
return -1; case 0:
break;
if (sock != CERF_SOCKET)
return 0;
switch(configure->vcc){ case 50:
case 0: case 33:
break;
case 50:
case 33:
#ifdef CONFIG_SA1100_CERF_CPLD #ifdef CONFIG_SA1100_CERF_CPLD
GPCR = GPIO_PWR_SHUTDOWN; GPCR = GPIO_PWR_SHUTDOWN;
#endif #endif
break; break;
default: default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
configure->vcc); __FUNCTION__, state->Vcc);
return -1; return -1;
} }
if(configure->reset) if (state->flags & SS_RESET) {
{
#ifdef CONFIG_SA1100_CERF_CPLD #ifdef CONFIG_SA1100_CERF_CPLD
GPSR = GPIO_CF_RESET; GPSR = GPIO_CF_RESET;
#endif #endif
} } else {
else
{
#ifdef CONFIG_SA1100_CERF_CPLD #ifdef CONFIG_SA1100_CERF_CPLD
GPCR = GPIO_CF_RESET; GPCR = GPIO_CF_RESET;
#endif #endif
} }
return 0; return 0;
} }
static int cerf_pcmcia_socket_init(int sock) static void cerf_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
if (sock == CERF_SOCKET)
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
return 0;
} }
static int cerf_pcmcia_socket_suspend(int sock) static void cerf_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
if (sock == CERF_SOCKET)
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
return 0;
} }
static struct pcmcia_low_level cerf_pcmcia_ops = { static struct pcmcia_low_level cerf_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = cerf_pcmcia_init, .init = cerf_pcmcia_hw_init,
.shutdown = cerf_pcmcia_shutdown, .shutdown = cerf_pcmcia_hw_shutdown,
.socket_state = cerf_pcmcia_socket_state, .socket_state = cerf_pcmcia_socket_state,
.configure_socket = cerf_pcmcia_configure_socket, .configure_socket = cerf_pcmcia_configure_socket,
.socket_init = cerf_pcmcia_socket_init, .socket_init = cerf_pcmcia_socket_init,
.socket_suspend = cerf_pcmcia_socket_suspend, .socket_suspend = cerf_pcmcia_socket_suspend,
}; };
int __init pcmcia_cerf_init(struct device *dev) int __init pcmcia_cerf_init(struct device *dev)
...@@ -163,12 +115,7 @@ int __init pcmcia_cerf_init(struct device *dev) ...@@ -163,12 +115,7 @@ int __init pcmcia_cerf_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_cerf()) if (machine_is_cerf())
ret = sa1100_register_pcmcia(&cerf_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &cerf_pcmcia_ops, CERF_SOCKET, 1);
return ret; return ret;
} }
void __exit pcmcia_cerf_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&cerf_pcmcia_ops, dev);
}
...@@ -16,69 +16,32 @@ ...@@ -16,69 +16,32 @@
#include <asm/irq.h> #include <asm/irq.h>
#include "sa1100_generic.h" #include "sa1100_generic.h"
static struct { static struct pcmcia_irqs irqs[] = {
int irq; { 0, IRQ_GPIO_CF1_CD, "CF1_CD" },
const char *name; { 0, IRQ_GPIO_CF1_BVD1, "CF1_BVD1" },
} irqs[] = { { 1, IRQ_GPIO_CF2_CD, "CF2_CD" },
{ IRQ_GPIO_CF1_CD, "CF1_CD" }, { 1, IRQ_GPIO_CF2_BVD1, "CF2_BVD1" }
{ IRQ_GPIO_CF1_BVD1, "CF1_BVD1" },
{ IRQ_GPIO_CF2_CD, "CF2_CD" },
{ IRQ_GPIO_CF2_BVD1, "CF2_BVD1" }
}; };
/* /*
* Socket initialization. * Socket initialization.
* *
* Called by sa1100_pcmcia_driver_init on startup. * Called by sa1100_pcmcia_driver_init on startup.
* Must return the number of slots.
*
*/ */
static int flexanet_pcmcia_init(struct pcmcia_init *init) static int flexanet_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
int i, res; skt->irq = skt->nr ? IRQ_GPIO_CF2_IRQ : IRQ_GPIO_CF1_IRQ;
/* Configure the GPIOs as inputs (BVD2 is not implemented) */ return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
GPDR &= ~(GPIO_CF1_NCD | GPIO_CF1_BVD1 | GPIO_CF1_IRQ |
GPIO_CF2_NCD | GPIO_CF2_BVD1 | GPIO_CF2_IRQ );
/* Register the socket interrupts (not the card interrupts) */
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
res = request_irq(irqs[i].irq, sa1100_pcmcia_interrupt, SA_INTERRUPT,
irqs[i].name, NULL);
if (res < 0)
break;
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
}
init->socket_irq[0] = IRQ_GPIO_CF1_IRQ;
init->socket_irq[1] = IRQ_GPIO_CF2_IRQ;
/* If we failed, then free all interrupts requested thus far. */
if (res < 0) {
printk(KERN_ERR "%s: request for IRQ%d failed: %d\n",
__FUNCTION__, irqs[i].irq, res);
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
}
return 2;
} }
/* /*
* Socket shutdown * Socket shutdown
*
*/ */
static int flexanet_pcmcia_shutdown(void) static void flexanet_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
} }
...@@ -88,109 +51,96 @@ static int flexanet_pcmcia_shutdown(void) ...@@ -88,109 +51,96 @@ static int flexanet_pcmcia_shutdown(void)
* Sockets in Flexanet are 3.3V only, without BVD2. * Sockets in Flexanet are 3.3V only, without BVD2.
* *
*/ */
static void flexanet_pcmcia_socket_state(int sock, struct pcmcia_state *state) static void
flexanet_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
struct pcmcia_state *state)
{ {
unsigned long levels = GPLR; /* Sense the GPIOs, asynchronously */ unsigned long levels = GPLR; /* Sense the GPIOs, asynchronously */
switch (sock) { switch (skt->nr) {
case 0: /* Socket 0 */ ase 0: /* Socket 0 */
state->detect = ((levels & GPIO_CF1_NCD)==0)?1:0; state->detect = ((levels & GPIO_CF1_NCD)==0)?1:0;
state->ready = (levels & GPIO_CF1_IRQ)?1:0; state->ready = (levels & GPIO_CF1_IRQ)?1:0;
state->bvd1 = (levels & GPIO_CF1_BVD1)?1:0; state->bvd1 = (levels & GPIO_CF1_BVD1)?1:0;
state->bvd2 = 1; state->bvd2 = 1;
state->wrprot = 0; state->wrprot = 0;
state->vs_3v = 1; state->vs_3v = 1;
state->vs_Xv = 0; state->vs_Xv = 0;
break; break;
case 1: /* Socket 1 */ case 1: /* Socket 1 */
state->detect = ((levels & GPIO_CF2_NCD)==0)?1:0; state->detect = ((levels & GPIO_CF2_NCD)==0)?1:0;
state->ready = (levels & GPIO_CF2_IRQ)?1:0; state->ready = (levels & GPIO_CF2_IRQ)?1:0;
state->bvd1 = (levels & GPIO_CF2_BVD1)?1:0; state->bvd1 = (levels & GPIO_CF2_BVD1)?1:0;
state->bvd2 = 1; state->bvd2 = 1;
state->wrprot = 0; state->wrprot = 0;
state->vs_3v = 1; state->vs_3v = 1;
state->vs_Xv = 0; state->vs_Xv = 0;
break; break;
} }
} }
/* /*
* *
*/ */
static int flexanet_pcmcia_configure_socket(int sock, const struct pcmcia_configure static int
*configure) flexanet_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
unsigned long value, flags, mask; unsigned long value, flags, mask;
if (sock > 1) /* Ignore the VCC level since it is 3.3V and always on */
return -1; switch (state->Vcc) {
case 0:
printk(KERN_WARNING "%s(): CS asked to power off.\n",
__FUNCTION__);
break;
/* Ignore the VCC level since it is 3.3V and always on */ case 50:
switch (configure->vcc) printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
{ __FUNCTION__);
case 0:
printk(KERN_WARNING "%s(): CS asked to power off.\n", __FUNCTION__);
break;
case 50: case 33:
printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n", break;
__FUNCTION__);
case 33: default:
break; printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
state->Vcc);
return -1;
}
default: /* Reset the slot(s) using the controls in the BCR */
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, mask = 0;
configure->vcc);
return -1;
}
/* Reset the slot(s) using the controls in the BCR */ switch (skt->nr) {
mask = 0; case 0:
mask = FHH_BCR_CF1_RST;
break;
case 1:
mask = FHH_BCR_CF2_RST;
break;
}
switch (sock) local_irq_save(flags);
{
case 0 : mask = FHH_BCR_CF1_RST; break;
case 1 : mask = FHH_BCR_CF2_RST; break;
}
local_irq_save(flags); value = flexanet_BCR;
value = (state->flags & SS_RESET) ? (value | mask) : (value & ~mask);
FHH_BCR = flexanet_BCR = value;
value = flexanet_BCR; local_irq_restore(flags);
value = (configure->reset) ? (value | mask) : (value & ~mask);
FHH_BCR = flexanet_BCR = value;
local_irq_restore(flags); return 0;
return 0;
} }
static int flexanet_pcmcia_socket_init(int sock) static void flexanet_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
if (sock == 0) { sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
set_irq_type(IRQ_GPIO_CF1_CD, IRQT_BOTHEDGE);
set_irq_type(IRQ_GPIO_CF1_BVD1, IRQT_BOTHEDGE);
} else if (sock == 1) {
set_irq_type(IRQ_GPIO_CF2_CD, IRQT_BOTHEDGE);
set_irq_type(IRQ_GPIO_CF2_BVD1, IRQT_BOTHEDGE);
}
return 0;
} }
static int flexanet_pcmcia_socket_suspend(int sock) static void flexanet_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
if (sock == 0) { sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
set_irq_type(IRQ_GPIO_CF1_CD, IRQT_NOEDGE);
set_irq_type(IRQ_GPIO_CF1_BVD1, IRQT_NOEDGE);
} else if (sock == 1) {
set_irq_type(IRQ_GPIO_CF2_CD, IRQT_NOEDGE);
set_irq_type(IRQ_GPIO_CF2_BVD1, IRQT_NOEDGE);
}
return 0;
} }
/* /*
...@@ -198,14 +148,13 @@ static int flexanet_pcmcia_socket_suspend(int sock) ...@@ -198,14 +148,13 @@ static int flexanet_pcmcia_socket_suspend(int sock)
* *
*/ */
static struct pcmcia_low_level flexanet_pcmcia_ops = { static struct pcmcia_low_level flexanet_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = flexanet_pcmcia_init, .hw_init = flexanet_pcmcia_hw_init,
.shutdown = flexanet_pcmcia_shutdown, .hw_shutdown = flexanet_pcmcia_hw_shutdown,
.socket_state = flexanet_pcmcia_socket_state, .socket_state = flexanet_pcmcia_socket_state,
.configure_socket = flexanet_pcmcia_configure_socket, .configure_socket = flexanet_pcmcia_configure_socket,
.socket_init = flexanet_pcmcia_socket_init,
.socket_init = flexanet_pcmcia_socket_init, .socket_suspend = flexanet_pcmcia_socket_suspend,
.socket_suspend = flexanet_pcmcia_socket_suspend,
}; };
int __init pcmcia_flexanet_init(struct device *dev) int __init pcmcia_flexanet_init(struct device *dev)
...@@ -213,13 +162,7 @@ int __init pcmcia_flexanet_init(struct device *dev) ...@@ -213,13 +162,7 @@ int __init pcmcia_flexanet_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_flexanet()) if (machine_is_flexanet())
ret = sa1100_register_pcmcia(&flexanet_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &flexanet_pcmcia_ops, 0, 2);
return ret; return ret;
} }
void __exit pcmcia_flexanet_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&flexanet_pcmcia_ops, dev);
}
...@@ -15,155 +15,113 @@ ...@@ -15,155 +15,113 @@
#include <asm/irq.h> #include <asm/irq.h>
#include "sa1100_generic.h" #include "sa1100_generic.h"
static struct irqs { static struct pcmcia_irqs irqs[] = {
int irq; { 0, IRQ_GPIO_FREEBIRD_CF_CD, "CF_CD" },
const char *str; { 0, IRQ_GPIO_FREEBIRD_CF_BVD, "CF_BVD1" },
} irqs[] = {
{ IRQ_GPIO_FREEBIRD_CF_CD, "CF_CD" },
{ IRQ_GPIO_FREEBIRD_CF_BVD, "CF_BVD1" },
}; };
static int freebird_pcmcia_init(struct pcmcia_init *init){ static int freebird_pcmcia_init(struct sa1100_pcmcia_socket *skt)
int i, res; {
/* Enable Linkup CF card */
/* Enable Linkup CF card */ LINKUP_PRC = 0xc0;
LINKUP_PRC = 0xc0; mdelay(100);
mdelay(100); LINKUP_PRC = 0xc1;
LINKUP_PRC = 0xc1; mdelay(100);
mdelay(100); LINKUP_PRC = 0xd1;
LINKUP_PRC = 0xd1; mdelay(100);
mdelay(100); LINKUP_PRC = 0xd1;
LINKUP_PRC = 0xd1; mdelay(100);
mdelay(100); LINKUP_PRC = 0xc0;
LINKUP_PRC = 0xc0;
skt->irq = IRQ_GPIO_FREEBIRD_CF_IRQ;
/* Register interrupts */
for (i = 0; i < ARRAY_SIZE(irqs); i++) { return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
res = request_irq(irqs[i].irq, sa1100_pcmcia_interrupt, SA_INTERRUPT,
irqs[i].str, NULL);
if (res)
goto irq_err;
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
}
init->socket_irq[0] = IRQ_GPIO_FREEBIRD_CF_IRQ;
/* There's only one slot, but it's "Slot 1": */
return 2;
irq_err:
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irqs[i].irq, res);
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
} }
static int freebird_pcmcia_shutdown(void) static void freebird_pcmcia_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs);
/* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
/* Disable CF card */
LINKUP_PRC = 0x40; /* SSP=1 SOE=0 */
mdelay(100);
return 0; /* Disable CF card */
LINKUP_PRC = 0x40; /* SSP=1 SOE=0 */
mdelay(100);
} }
static void freebird_pcmcia_socket_state(int sock, struct pcmcia_state *state) static void
freebird_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
{ {
unsigned long levels = LINKUP_PRS; unsigned long levels = LINKUP_PRS;
//printk("LINKUP_PRS=%x\n",levels); // printk("LINKUP_PRS=%x\n",levels);
if (sock == 0) { state->detect = ((levels & (LINKUP_CD1 | LINKUP_CD2))==0)?1:0;
state->detect = ((levels & (LINKUP_CD1 | LINKUP_CD2))==0)?1:0; state->ready = (levels & LINKUP_RDY)?1:0;
state->ready = (levels & LINKUP_RDY)?1:0; state->bvd1 = (levels & LINKUP_BVD1)?1:0;
state->bvd1 = (levels & LINKUP_BVD1)?1:0; state->bvd2 = (levels & LINKUP_BVD2)?1:0;
state->bvd2 = (levels & LINKUP_BVD2)?1:0; state->wrprot = 0; /* Not available on Assabet. */
state->wrprot = 0; /* Not available on Assabet. */ state->vs_3v = 1; /* Can only apply 3.3V on Assabet. */
state->vs_3v = 1; /* Can only apply 3.3V on Assabet. */ state->vs_Xv = 0;
state->vs_Xv = 0;
}
} }
static int freebird_pcmcia_configure_socket(int sock, const struct pcmcia_configure static int
*configure) freebird_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
socket_state_t *state)
{ {
unsigned long value, flags; unsigned long value, flags;
if(sock>1) return -1;
if(sock==1) return 0;
local_irq_save(flags); local_irq_save(flags);
value = 0xc0; /* SSP=1 SOE=1 CFE=1 */ value = 0xc0; /* SSP=1 SOE=1 CFE=1 */
switch(configure->vcc){ switch (state->Vcc) {
case 0: case 0:
break;
break; case 50:
printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
__FUNCTION__);
case 50: case 33: /* Can only apply 3.3V to the CF slot. */
printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n", value |= LINKUP_S1;
__FUNCTION__); break;
case 33: /* Can only apply 3.3V to the CF slot. */ default:
value |= LINKUP_S1; printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
break; __FUNCTION__, state->Vcc);
local_irq_restore(flags);
return -1;
}
default: if (state->flags & SS_RESET)
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, value |= LINKUP_RESET;
configure->vcc);
local_irq_restore(flags);
return -1;
}
if (configure->reset) /* Silently ignore Vpp, output enable, speaker enable. */
value = (configure->reset) ? (value | LINKUP_RESET) : (value & ~LINKUP_RESET);
/* Silently ignore Vpp, output enable, speaker enable. */ LINKUP_PRC = value;
// printk("LINKUP_PRC=%x\n",value);
local_irq_restore(flags);
LINKUP_PRC = value; return 0;
//printk("LINKUP_PRC=%x\n",value);
local_irq_restore(flags);
return 0;
} }
static int freebird_pcmcia_socket_init(int sock) static void freebird_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
if (sock == 1) { sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
set_irq_type(IRQ_GPIO_FREEBIRD_CF_CD, IRQT_BOTHEDGE);
set_irq_type(IRQ_GPIO_FREEBIRD_CF_BVD, IRQT_BOTHEDGE);
}
return 0;
} }
static int freebird_pcmcia_socket_suspend(int sock) static void freebird_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
if (sock == 1) { sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
set_irq_type(IRQ_GPIO_FREEBIRD_CF_CD, IRQT_NOEDGE);
set_irq_type(IRQ_GPIO_FREEBIRD_CF_BVD, IRQT_NOEDGE);
}
return 0;
} }
static struct pcmcia_low_level freebird_pcmcia_ops = { static struct pcmcia_low_level freebird_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = freebird_pcmcia_init, .hw_init = freebird_pcmcia_hw_init,
.shutdown = freebird_pcmcia_shutdown, .hw_shutdown = freebird_pcmcia_hw_shutdown,
.socket_state = freebird_pcmcia_socket_state, .socket_state = freebird_pcmcia_socket_state,
.configure_socket = freebird_pcmcia_configure_socket, .configure_socket = freebird_pcmcia_configure_socket,
.socket_init = freebird_pcmcia_socket_init, .socket_init = freebird_pcmcia_socket_init,
.socket_suspend = freebird_pcmcia_socket_suspend, .socket_suspend = freebird_pcmcia_socket_suspend,
}; };
int __init pcmcia_freebird_init(struct device *dev) int __init pcmcia_freebird_init(struct device *dev)
...@@ -171,12 +129,7 @@ int __init pcmcia_freebird_init(struct device *dev) ...@@ -171,12 +129,7 @@ int __init pcmcia_freebird_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_freebird()) if (machine_is_freebird())
ret = sa1100_register_pcmcia(&freebird_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &freebird_pcmcia_ops, 0, 1);
return ret; return ret;
} }
void __exit pcmcia_freebird_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&freebird_pcmcia_ops, dev);
}
This diff is collapsed.
/* #include "sa11xx_core.h"
* linux/include/asm/arch/pcmcia.h
*
* Copyright (C) 2000 John G Dorsey <john+@cs.cmu.edu>
*
* This file contains definitions for the low-level SA-1100 kernel PCMCIA
* interface. Please see linux/Documentation/arm/SA1100/PCMCIA for details.
*/
#ifndef _ASM_ARCH_PCMCIA
#define _ASM_ARCH_PCMCIA
/* Ideally, we'd support up to MAX_SOCK sockets, but the SA-1100 only /*
* has support for two. This shows up in lots of hardwired ways, such * Declaration for all machine specific init/exit functions.
* as the fact that MECR only has enough bits to configure two sockets.
* Since it's so entrenched in the hardware, limiting the software
* in this way doesn't seem too terrible.
*/ */
#define SA1100_PCMCIA_MAX_SOCK (2) extern int pcmcia_adsbitsy_init(struct device *);
extern int pcmcia_assabet_init(struct device *);
struct pcmcia_init { extern int pcmcia_badge4_init(struct device *);
int socket_irq[SA1100_PCMCIA_MAX_SOCK]; extern int pcmcia_cerf_init(struct device *);
}; extern int pcmcia_flexanet_init(struct device *);
extern int pcmcia_freebird_init(struct device *);
struct pcmcia_state { extern int pcmcia_gcplus_init(struct device *);
unsigned detect: 1, extern int pcmcia_graphicsmaster_init(struct device *);
ready: 1, extern int pcmcia_h3600_init(struct device *);
bvd1: 1, extern int pcmcia_pangolin_init(struct device *);
bvd2: 1, extern int pcmcia_pfs168_init(struct device *);
wrprot: 1, extern int pcmcia_shannon_init(struct device *);
vs_3v: 1, extern int pcmcia_simpad_init(struct device *);
vs_Xv: 1; extern int pcmcia_stork_init(struct device *);
}; extern int pcmcia_system3_init(struct device *);
extern int pcmcia_trizeps_init(struct device *);
struct pcmcia_configure { extern int pcmcia_xp860_init(struct device *);
unsigned vcc: 8, extern int pcmcia_yopy_init(struct device *);
vpp: 8,
output: 1,
speaker: 1,
reset: 1,
irq: 1;
};
struct pcmcia_low_level {
struct module *owner;
int (*init)(struct pcmcia_init *);
int (*shutdown)(void);
void (*socket_state)(int sock, struct pcmcia_state *);
int (*configure_socket)(int sock, const struct pcmcia_configure *);
/*
* Enable card status IRQs on (re-)initialisation. This can
* be called at initialisation, power management event, or
* pcmcia event.
*/
int (*socket_init)(int sock);
/*
* Disable card status IRQs and PCMCIA bus on suspend.
*/
int (*socket_suspend)(int sock);
/*
* Calculate MECR timing clock wait states
*/
unsigned int (*socket_get_timing)(unsigned int sock,
unsigned int cpu_speed, unsigned int cmd_time);
};
extern int sa1100_register_pcmcia(struct pcmcia_low_level *, struct device *);
extern void sa1100_unregister_pcmcia(struct pcmcia_low_level *, struct device *);
extern void sa1100_pcmcia_interrupt(int, void *, struct pt_regs *);
#endif
...@@ -34,126 +34,113 @@ static volatile unsigned long *PCMCIA_Status = ...@@ -34,126 +34,113 @@ static volatile unsigned long *PCMCIA_Status =
static volatile unsigned long *PCMCIA_Power = static volatile unsigned long *PCMCIA_Power =
((volatile unsigned long *) ADS_p2v(_ADS_CS_PR)); ((volatile unsigned long *) ADS_p2v(_ADS_CS_PR));
static int gcplus_pcmcia_init(struct pcmcia_init *init) static struct pcmcia_irqs irqs[] = {
{ { 0, S0_CD_IRQ, "PCMCIA 0 CD" },
int irq, res; };
// Reset PCMCIA
// Reset Timing for CPLD(U2) version 8001E or later
*PCMCIA_Power &= ~ ADS_CS_PR_A_RESET;
udelay(12); // 12 uSec
*PCMCIA_Power |= ADS_CS_PR_A_RESET; static int gcplus_pcmcia_init(struct sa1100_pcmcia_socket *skt)
mdelay(30); // 30 mSec {
// Reset PCMCIA
// Reset Timing for CPLD(U2) version 8001E or later
*PCMCIA_Power &= ~ ADS_CS_PR_A_RESET;
udelay(12); // 12 uSec
// Turn off 5V *PCMCIA_Power |= ADS_CS_PR_A_RESET;
*PCMCIA_Power &= ~0x03; mdelay(30); // 30 mSec
/* Register interrupts */ // Turn off 5V
irq = S0_CD_IRQ; *PCMCIA_Power &= ~0x03;
res = request_irq(irq, sa1100_pcmcia_interrupt, SA_INTERRUPT, "PCMCIA 0 CD", NULL);
if (res < 0) {
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irq, res);
return res;
}
init->socket_irq[0] = S0_STS_IRQ; skt->irq = S0_STS_IRQ;
return 1; // 1 PCMCIA Slot /* Register interrupts */
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
} }
static int gcplus_pcmcia_shutdown(void) static void gcplus_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
/* disable IRQs */ /* disable IRQs */
free_irq( S0_CD_IRQ, NULL); free_irq(S0_CD_IRQ, skt);
/* Shutdown PCMCIA power */ /* Shutdown PCMCIA power */
mdelay(2); // 2msec mdelay(2); // 2msec
*PCMCIA_Power &= ~0x03; *PCMCIA_Power &= ~0x03;
return 0;
} }
static void gcplus_pcmcia_socket_state(int sock, struct pcmcia_state *state_array) static void
gcplus_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
{ {
unsigned long levels = *PCMCIA_Status; unsigned long levels = *PCMCIA_Status;
if (sock == 0) { state->detect=(levels & ADS_CS_ST_A_CD)?1:0;
state->detect=(levels & ADS_CS_ST_A_CD)?1:0; state->ready=(levels & ADS_CS_ST_A_READY)?1:0;
state->ready=(levels & ADS_CS_ST_A_READY)?1:0; state->bvd1= 0;
state->bvd1= 0; state->bvd2= 0;
state->bvd2= 0; state->wrprot=0;
state->wrprot=0; state->vs_3v=0;
state->vs_3v=0; state->vs_Xv=0;
state->vs_Xv=0;
}
} }
static int gcplus_pcmcia_configure_socket(int sock, const struct pcmcia_configure static int
*configure) gcplus_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
unsigned long flags; unsigned long flags;
if(sock>1) return -1; local_irq_save(flags);
local_irq_save(flags); switch (state->Vcc) {
case 0:
*PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER);
break;
switch (configure->vcc) { case 50:
case 0: *PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER);
*PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER); *PCMCIA_Power |= ADS_CS_PR_A_5V_POWER;
break; break;
case 50: case 33:
*PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER); *PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER);
*PCMCIA_Power |= ADS_CS_PR_A_5V_POWER; *PCMCIA_Power |= ADS_CS_PR_A_3V_POWER;
break; break;
case 33: default:
*PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER); printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
*PCMCIA_Power |= ADS_CS_PR_A_3V_POWER; __FUNCTION__, state->Vcc);
break; local_irq_restore(flags);
return -1;
}
default: /* Silently ignore Vpp, output enable, speaker enable. */
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
local_irq_restore(flags);
return -1;
}
/* Silently ignore Vpp, output enable, speaker enable. */ // Reset PCMCIA
*PCMCIA_Power &= ~ ADS_CS_PR_A_RESET;
udelay(12);
// Reset PCMCIA *PCMCIA_Power |= ADS_CS_PR_A_RESET;
*PCMCIA_Power &= ~ ADS_CS_PR_A_RESET; mdelay(30);
udelay(12);
*PCMCIA_Power |= ADS_CS_PR_A_RESET; local_irq_restore(flags);
mdelay(30);
local_irq_restore(flags); return 0;
return 0;
} }
static int gcplus_pcmcia_socket_init(int sock) static void gcplus_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
return 0;
} }
static int gcplus_pcmcia_socket_suspend(int sock) static void gcplus_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
return 0;
} }
static struct pcmcia_low_level gcplus_pcmcia_ops = { static struct pcmcia_low_level gcplus_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = gcplus_pcmcia_init, .hw_init = gcplus_pcmcia_hw_init,
.shutdown = gcplus_pcmcia_shutdown, .hw_shutdown = gcplus_pcmcia_hw_shutdown,
.socket_state = gcplus_pcmcia_socket_state, .socket_state = gcplus_pcmcia_socket_state,
.configure_socket = gcplus_pcmcia_configure_socket, .configure_socket = gcplus_pcmcia_configure_socket,
.socket_init = gcplus_pcmcia_socket_init,
.socket_init = gcplus_pcmcia_socket_init, .socket_suspend = gcplus_pcmcia_socket_suspend,
.socket_suspend = gcplus_pcmcia_socket_suspend,
}; };
int __init pcmcia_gcplus_init(struct device *dev) int __init pcmcia_gcplus_init(struct device *dev)
...@@ -161,13 +148,7 @@ int __init pcmcia_gcplus_init(struct device *dev) ...@@ -161,13 +148,7 @@ int __init pcmcia_gcplus_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_gcplus()) if (machine_is_gcplus())
ret = sa1100_register_pcmcia(&gcplus_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &gcplus_pcmcia_ops, 0, 1);
return ret; return ret;
} }
void __exit pcmcia_gcplus_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&gcplus_pcmcia_ops, dev);
}
...@@ -17,10 +17,9 @@ ...@@ -17,10 +17,9 @@
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
static int graphicsmaster_pcmcia_init(struct pcmcia_init *init) static int graphicsmaster_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
int return_val=0; int return_val=0;
...@@ -33,65 +32,67 @@ static int graphicsmaster_pcmcia_init(struct pcmcia_init *init) ...@@ -33,65 +32,67 @@ static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
/* why? */ /* why? */
MECR = 0x09430943; MECR = 0x09430943;
return sa1111_pcmcia_init(init); return sa1111_pcmcia_hwinit(skt);
} }
static int static int
graphicsmaster_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) graphicsmaster_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
unsigned int pa_dwr_mask, pa_dwr_set; unsigned int pa_dwr_mask, pa_dwr_set;
int ret; int ret;
switch (sock) { switch (skt->nr) {
case 0: case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1; pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
switch (conf->vcc) { switch (state->Vcc) {
default: default:
case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break; case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
case 33: pa_dwr_set = GPIO_GPIO1; break; case 33: pa_dwr_set = GPIO_GPIO1; break;
case 50: pa_dwr_set = GPIO_GPIO0; break; case 50: pa_dwr_set = GPIO_GPIO0; break;
} }
break; break;
case 1: case 1:
pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3; pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
switch (conf->vcc) { switch (state->Vcc) {
default: default:
case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break; case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
case 33: pa_dwr_set = GPIO_GPIO3; break; case 33: pa_dwr_set = GPIO_GPIO3; break;
case 50: pa_dwr_set = GPIO_GPIO2; break; case 50: pa_dwr_set = GPIO_GPIO2; break;
} }
} break;
}
if (conf->vpp != conf->vcc && conf->vpp != 0) {
printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__, if (state->Vpp != state->Vcc && state->Vpp != 0) {
conf->vpp); printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
return -1; __FUNCTION__, state->Vpp);
} return -1;
}
ret = sa1111_pcmcia_configure_socket(sock, conf);
if (ret == 0) { ret = sa1111_pcmcia_configure_socket(skt, state);
unsigned long flags; if (ret == 0) {
unsigned long flags;
local_irq_save(flags);
PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set; local_irq_save(flags);
local_irq_restore(flags); PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
} local_irq_restore(flags);
}
return ret;
return ret;
} }
static struct pcmcia_low_level graphicsmaster_pcmcia_ops = { static struct pcmcia_low_level graphicsmaster_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = graphicsmaster_pcmcia_init, .hw_init = graphicsmaster_pcmcia_init,
.shutdown = sa1111_pcmcia_shutdown, .hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state, .socket_state = sa1111_pcmcia_socket_state,
.configure_socket = graphicsmaster_pcmcia_configure_socket, .configure_socket = graphicsmaster_pcmcia_configure_socket,
.socket_init = sa1111_pcmcia_socket_init, .socket_init = sa1111_pcmcia_socket_init,
.socket_suspend = sa1111_pcmcia_socket_suspend, .socket_suspend = sa1111_pcmcia_socket_suspend,
}; };
int __init pcmcia_graphicsmaster_init(struct device *dev) int __init pcmcia_graphicsmaster_init(struct device *dev)
...@@ -99,13 +100,7 @@ int __init pcmcia_graphicsmaster_init(struct device *dev) ...@@ -99,13 +100,7 @@ int __init pcmcia_graphicsmaster_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_graphicsmaster()) if (machine_is_graphicsmaster())
ret = sa1100_register_pcmcia(&graphicsmaster_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &graphicsmaster_pcmcia_ops, 0, 2);
return ret; return ret;
} }
void __exit pcmcia_graphicsmaster_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&graphicsmaster_pcmcia_ops, dev);
}
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/hardware.h> #include <asm/hardware.h>
...@@ -17,65 +18,36 @@ ...@@ -17,65 +18,36 @@
#include "sa1100_generic.h" #include "sa1100_generic.h"
static struct irqs { static struct pcmcia_irqs irqs[] = {
int irq; { 0, IRQ_GPIO_H3600_PCMCIA_CD0, "PCMCIA CD0" },
const char *str; { 1, IRQ_GPIO_H3600_PCMCIA_CD1, "PCMCIA CD1" }
} irqs[] = {
{ IRQ_GPIO_H3600_PCMCIA_CD0, "PCMCIA CD0" },
{ IRQ_GPIO_H3600_PCMCIA_CD1, "PCMCIA CD1" }
}; };
static int h3600_pcmcia_init(struct pcmcia_init *init) static int h3600_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
int i, res; skt->irq = skt->nr ? IRQ_GPIO_H3600_PCMCIA_IRQ1
: IRQ_GPIO_H3600_PCMCIA_IRQ0;
/*
* Register interrupts
*/
for (i = res = 0; i < ARRAY_SIZE(irqs); i++) {
res = request_irq(irqs[i].irq, sa1100_pcmcia_interrupt,
SA_INTERRUPT, irqs[i].str, NULL);
if (res)
break;
}
if (res) {
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irqs[i].irq, res);
while (i--) return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
free_irq(irqs[i].irq, NULL);
}
init->socket_irq[0] = IRQ_GPIO_H3600_PCMCIA_IRQ0;
init->socket_irq[1] = IRQ_GPIO_H3600_PCMCIA_IRQ1;
return res ? res : 2;
} }
static int h3600_pcmcia_shutdown(void) static void h3600_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/*
* disable IRQs
*/
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
/* Disable CF bus: */ /* Disable CF bus: */
clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON); clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
clr_h3600_egpio(IPAQ_EGPIO_OPT_ON); clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
set_h3600_egpio(IPAQ_EGPIO_OPT_RESET); set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
return 0;
} }
static void h3600_pcmcia_socket_state(int sock, struct pcmcia_state *state) static void
h3600_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
{ {
unsigned long levels = GPLR; unsigned long levels = GPLR;
switch (sock) { switch (skt->nr) {
case 0: case 0:
state->detect = levels & GPIO_H3600_PCMCIA_CD0 ? 0 : 1; state->detect = levels & GPIO_H3600_PCMCIA_CD0 ? 0 : 1;
state->ready = levels & GPIO_H3600_PCMCIA_IRQ0 ? 1 : 0; state->ready = levels & GPIO_H3600_PCMCIA_IRQ0 ? 1 : 0;
...@@ -99,18 +71,15 @@ static void h3600_pcmcia_socket_state(int sock, struct pcmcia_state *state) ...@@ -99,18 +71,15 @@ static void h3600_pcmcia_socket_state(int sock, struct pcmcia_state *state)
} }
static int static int
h3600_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) h3600_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
{ {
if (sock > 1) if (state->Vcc != 0 && state->Vcc != 33 && state->Vcc != 50) {
return -1;
if (conf->vcc != 0 && conf->vcc != 33 && conf->vcc != 50) {
printk(KERN_ERR "h3600_pcmcia: unrecognized Vcc %u.%uV\n", printk(KERN_ERR "h3600_pcmcia: unrecognized Vcc %u.%uV\n",
conf->vcc / 10, conf->vcc % 10); state->Vcc / 10, state->Vcc % 10);
return -1; return -1;
} }
if (conf->reset) if (state->flags & SS_RESET)
set_h3600_egpio(IPAQ_EGPIO_CARD_RESET); set_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
else else
clr_h3600_egpio(IPAQ_EGPIO_CARD_RESET); clr_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
...@@ -120,7 +89,7 @@ h3600_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -120,7 +89,7 @@ h3600_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
return 0; return 0;
} }
static int h3600_pcmcia_socket_init(int sock) static void h3600_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
/* Enable CF bus: */ /* Enable CF bus: */
set_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON); set_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
...@@ -130,28 +99,12 @@ static int h3600_pcmcia_socket_init(int sock) ...@@ -130,28 +99,12 @@ static int h3600_pcmcia_socket_init(int sock)
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(10*HZ / 1000); schedule_timeout(10*HZ / 1000);
switch (sock) { sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
case 0:
set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD0, IRQT_BOTHEDGE);
break;
case 1:
set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD1, IRQT_BOTHEDGE);
break;
}
return 0;
} }
static int h3600_pcmcia_socket_suspend(int sock) static void h3600_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
switch (sock) { sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
case 0:
set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD0, IRQT_NOEDGE);
break;
case 1:
set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD1, IRQT_NOEDGE);
break;
}
/* /*
* FIXME: This doesn't fit well. We don't have the mechanism in * FIXME: This doesn't fit well. We don't have the mechanism in
...@@ -159,20 +112,18 @@ static int h3600_pcmcia_socket_suspend(int sock) ...@@ -159,20 +112,18 @@ static int h3600_pcmcia_socket_suspend(int sock)
* on one bus. We rely on the cs.c behaviour shutting down * on one bus. We rely on the cs.c behaviour shutting down
* socket 0 then socket 1. * socket 0 then socket 1.
*/ */
if (sock == 1) { if (skt->nr == 1) {
clr_h3600_egpio(IPAQ_EGPIO_OPT_ON); clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON); clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
/* hmm, does this suck power? */ /* hmm, does this suck power? */
set_h3600_egpio(IPAQ_EGPIO_OPT_RESET); set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
} }
return 0;
} }
struct pcmcia_low_level h3600_pcmcia_ops = { struct pcmcia_low_level h3600_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = h3600_pcmcia_init, .hw_init = h3600_pcmcia_hw_init,
.shutdown = h3600_pcmcia_shutdown, .hw_shutdown = h3600_pcmcia_hw_shutdown,
.socket_state = h3600_pcmcia_socket_state, .socket_state = h3600_pcmcia_socket_state,
.configure_socket = h3600_pcmcia_configure_socket, .configure_socket = h3600_pcmcia_configure_socket,
...@@ -185,12 +136,7 @@ int __init pcmcia_h3600_init(struct device *dev) ...@@ -185,12 +136,7 @@ int __init pcmcia_h3600_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_h3600()) if (machine_is_h3600())
ret = sa1100_register_pcmcia(&h3600_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &h3600_pcmcia_ops, 0, 2);
return ret; return ret;
} }
void __exit pcmcia_h3600_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&h3600_pcmcia_ops, dev);
}
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <asm/hardware/sa1111.h> #include <asm/hardware/sa1111.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
#define SOCKET0_POWER GPIO_GPIO0 #define SOCKET0_POWER GPIO_GPIO0
...@@ -24,7 +23,7 @@ ...@@ -24,7 +23,7 @@
#warning *** Does SOCKET1_3V actually do anything? #warning *** Does SOCKET1_3V actually do anything?
#define SOCKET1_3V GPIO_GPIO3 #define SOCKET1_3V GPIO_GPIO3
static int jornada720_pcmcia_init(struct pcmcia_init *init) static int jornada720_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
/* /*
* What is all this crap for? * What is all this crap for?
...@@ -46,23 +45,23 @@ static int jornada720_pcmcia_init(struct pcmcia_init *init) ...@@ -46,23 +45,23 @@ static int jornada720_pcmcia_init(struct pcmcia_init *init)
PC_SDR = 0; PC_SDR = 0;
PC_SSR = 0; PC_SSR = 0;
return sa1111_pcmcia_init(init); return sa1111_pcmcia_hw_init(skt);
} }
static int static int
jornada720_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) jornada720_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
{ {
unsigned int pa_dwr_mask, pa_dwr_set; unsigned int pa_dwr_mask, pa_dwr_set;
int ret; int ret;
printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__, printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__,
sock, conf->vcc, conf->vpp); skt->nr, state->Vcc, state->Vpp);
switch (sock) { switch (skt->nr) {
case 0: case 0:
pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V; pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V;
switch (conf->vcc) { switch (state->Vcc) {
default: default:
case 0: pa_dwr_set = 0; break; case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = SOCKET0_POWER | SOCKET0_3V; break; case 33: pa_dwr_set = SOCKET0_POWER | SOCKET0_3V; break;
...@@ -73,7 +72,7 @@ printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__, ...@@ -73,7 +72,7 @@ printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__,
case 1: case 1:
pa_dwr_mask = SOCKET1_POWER; pa_dwr_mask = SOCKET1_POWER;
switch (conf->vcc) { switch (state->Vcc) {
default: default:
case 0: pa_dwr_set = 0; break; case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = SOCKET1_POWER; break; case 33: pa_dwr_set = SOCKET1_POWER; break;
...@@ -85,13 +84,13 @@ printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__, ...@@ -85,13 +84,13 @@ printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__,
return -1; return -1;
} }
if (conf->vpp != conf->vcc && conf->vpp != 0) { if (state->Vpp != state->Vcc && state->Vpp != 0) {
printk(KERN_ERR "%s(): slot cannot support VPP %u\n", printk(KERN_ERR "%s(): slot cannot support VPP %u\n",
__FUNCTION__, conf->vpp); __FUNCTION__, state->Vpp);
return -1; return -1;
} }
ret = sa1111_pcmcia_configure_socket(sock, conf); ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) { if (ret == 0) {
unsigned long flags; unsigned long flags;
...@@ -105,8 +104,8 @@ printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__, ...@@ -105,8 +104,8 @@ printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__,
static struct pcmcia_low_level jornada720_pcmcia_ops = { static struct pcmcia_low_level jornada720_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = jornada720_pcmcia_init, .hw_init = jornada720_pcmcia_hw_init,
.shutdown = sa1111_pcmcia_shutdown, .hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state, .socket_state = sa1111_pcmcia_socket_state,
.configure_socket = jornada720_pcmcia_configure_socket, .configure_socket = jornada720_pcmcia_configure_socket,
...@@ -119,12 +118,7 @@ int __init pcmcia_jornada720_init(struct device *dev) ...@@ -119,12 +118,7 @@ int __init pcmcia_jornada720_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_jornada720()) if (machine_is_jornada720())
ret = sa1100_register_pcmcia(&jornada720_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &jornada720_pcmcia_ops, 0, 2);
return ret; return ret;
} }
void __devexit pcmcia_jornada720_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&jornada720_pcmcia_ops, dev);
}
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <asm/arch/neponset.h> #include <asm/arch/neponset.h>
#include <asm/hardware/sa1111.h> #include <asm/hardware/sa1111.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
/* /*
...@@ -42,52 +41,27 @@ ...@@ -42,52 +41,27 @@
* the corresponding truth table. * the corresponding truth table.
*/ */
static int neponset_pcmcia_init(struct pcmcia_init *init)
{
NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP);
/*
* Set GPIO_A<3:0> to be outputs for the MAX1600,
* and switch to standby mode.
*/
PA_DDR = 0;
PA_SDR = 0;
PA_DWR = 0;
PA_SSR = 0;
return sa1111_pcmcia_init(init);
}
static int static int
neponset_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) neponset_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
{ {
unsigned int ncr_mask, pa_dwr_mask; unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set;
unsigned int ncr_set, pa_dwr_set;
int ret; int ret;
switch (sock) { switch (skt->nr) {
case 0: case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1; pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
ncr_mask = NCR_A0VPP | NCR_A1VPP; ncr_mask = NCR_A0VPP | NCR_A1VPP;
switch (conf->vcc) { if (state->Vpp == 0)
default: ncr_set = 0;
case 0: pa_dwr_set = 0; break; else if (state->Vpp == 120)
case 33: pa_dwr_set = GPIO_GPIO1; break; ncr_set = NCR_A1VPP;
case 50: pa_dwr_set = GPIO_GPIO0; break; else if (state->Vpp == state->Vcc)
} ncr_set = NCR_A0VPP;
else {
switch (conf->vpp) { printk(KERN_ERR "%s(): unrecognized VPP %u\n",
case 0: ncr_set = 0; break; __FUNCTION__, state->Vpp);
case 120: ncr_set = NCR_A1VPP; break; return -1;
default:
if (conf->vpp == conf->vcc)
ncr_set = NCR_A0VPP;
else {
printk(KERN_ERR "%s(): unrecognized VPP %u\n",
__FUNCTION__, conf->vpp);
return -1;
}
} }
break; break;
...@@ -96,16 +70,9 @@ neponset_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -96,16 +70,9 @@ neponset_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
ncr_mask = 0; ncr_mask = 0;
ncr_set = 0; ncr_set = 0;
switch (conf->vcc) { if (state->Vpp != state->Vcc && state->Vpp != 0) {
default:
case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO2; break;
case 50: pa_dwr_set = GPIO_GPIO3; break;
}
if (conf->vpp != conf->vcc && conf->vpp != 0) {
printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n", printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
__FUNCTION__, conf->vpp); __FUNCTION__, state->Vpp);
return -1; return -1;
} }
break; break;
...@@ -114,41 +81,64 @@ neponset_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -114,41 +81,64 @@ neponset_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
return -1; return -1;
} }
ret = sa1111_pcmcia_configure_socket(sock, conf); /*
* pa_dwr_set is the mask for selecting Vcc on both sockets.
* pa_dwr_mask selects which bits (and therefore socket) we change.
*/
switch (state->Vcc) {
default:
case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO1|GPIO_GPIO2; break;
case 50: pa_dwr_set = GPIO_GPIO0|GPIO_GPIO3; break;
}
ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) { if (ret == 0) {
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set; NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set;
PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
PA_DWR = (PA_DWR & ~pa_dwr_mask) | (pa_dwr_set & pa_dwr_mask);
local_irq_restore(flags); local_irq_restore(flags);
} }
return 0; return 0;
} }
static void neponset_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{
if (skt->nr == 0)
NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP);
sa1111_pcmcia_socket_init(skt);
}
static struct pcmcia_low_level neponset_pcmcia_ops = { static struct pcmcia_low_level neponset_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = neponset_pcmcia_init, .hw_init = sa1111_pcmcia_hw_init,
.shutdown = sa1111_pcmcia_shutdown, .hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state, .socket_state = sa1111_pcmcia_socket_state,
.configure_socket = neponset_pcmcia_configure_socket, .configure_socket = neponset_pcmcia_configure_socket,
.socket_init = neponset_pcmcia_socket_init,
.socket_init = sa1111_pcmcia_socket_init, .socket_suspend = sa1111_pcmcia_socket_suspend,
.socket_suspend = sa1111_pcmcia_socket_suspend,
}; };
int __init pcmcia_neponset_init(struct device *dev) int __init pcmcia_neponset_init(struct device *dev)
{ {
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_assabet()) if (machine_is_assabet()) {
ret = sa1100_register_pcmcia(&neponset_pcmcia_ops, dev); /*
* Set GPIO_A<3:0> to be outputs for the MAX1600,
* and switch to standby mode.
*/
PA_DDR = 0;
PA_DWR = 0;
PA_SDR = 0;
PA_SSR = 0;
ret = sa11xx_drv_pcmcia_probe(dev, &neponset_pcmcia_ops, 0, 2);
}
return ret; return ret;
} }
void __devexit pcmcia_neponset_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&neponset_pcmcia_ops, dev);
}
...@@ -22,134 +22,118 @@ ...@@ -22,134 +22,118 @@
#define PANGOLIN_SOCK 0 #define PANGOLIN_SOCK 0
#endif #endif
static int pangolin_pcmcia_init(struct pcmcia_init *init){ static struct pcmcia_irqs irqs[] = {
int res; { PANGOLIN_SOCK, IRQ_PCMCIA_CD, "PCMCIA CD" },
};
static int pangolin_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{
int res;
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
/* Enable PCMCIA bus: */ /* Enable PCMCIA bus: */
GPCR = GPIO_PCMCIA_BUS_ON; GPCR = GPIO_PCMCIA_BUS_ON;
#endif #endif
init->socket_irq[PANGOLIN_SOCK] = IRQ_PCMCIA_IRQ; skt->irq = IRQ_PCMCIA_IRQ;
/* Set transition detect */
set_irq_type(IRQ_PCMCIA_CD, IRQT_NOEDGE);
set_irq_type(IRQ_PCMCIA_IRQ, IRQT_FALLING);
/* Register interrupts */ return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
res = request_irq(IRQ_PCMCIA_CD, sa1100_pcmcia_interrupt, SA_INTERRUPT,
"PCMCIA_CD", NULL);
if (res >= 0)
/* There's only one slot, but it's "Slot 1": */
return 2;
irq_err:
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, IRQ_PCMCIA_CD, res);
return res;
} }
static int pangolin_pcmcia_shutdown(void) static void pangolin_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
/* disable IRQs */ sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
free_irq(IRQ_PCMCIA_CD, NULL);
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
/* Disable PCMCIA bus: */ /* Disable PCMCIA bus: */
GPSR = GPIO_PCMCIA_BUS_ON; GPSR = GPIO_PCMCIA_BUS_ON;
#endif #endif
return 0;
} }
static void pangolin_pcmcia_socket_state(int sock, struct pcmcia_state *state) static void
pangolin_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
struct pcmcia_state *state)
{ {
unsigned long levels = GPLR;; unsigned long levels = GPLR;;
if (sock == PANGOLIN_SOCK) { state->detect=((levels & GPIO_PCMCIA_CD)==0)?1:0;
state->detect=((levels & GPIO_PCMCIA_CD)==0)?1:0; state->ready=(levels & GPIO_PCMCIA_IRQ)?1:0;
state->ready=(levels & GPIO_PCMCIA_IRQ)?1:0; state->bvd1=1; /* Not available on Pangolin. */
state->bvd1=1; /* Not available on Pangolin. */ state->bvd2=1; /* Not available on Pangolin. */
state->bvd2=1; /* Not available on Pangolin. */ state->wrprot=0; /* Not available on Pangolin. */
state->wrprot=0; /* Not available on Pangolin. */ state->vs_3v=1; /* Can only apply 3.3V on Pangolin. */
state->vs_3v=1; /* Can only apply 3.3V on Pangolin. */ state->vs_Xv=0;
state->vs_Xv=0;
}
} }
static int pangolin_pcmcia_configure_socket(int sock, const struct pcmcia_configure static int
*configure) pangolin_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
unsigned long value, flags; unsigned long value, flags;
if(sock>1) return -1; local_irq_save(flags);
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
if(sock==0) return 0;
#endif
local_irq_save(flags);
/* Murphy: BUS_ON different from POWER ? */ /* Murphy: BUS_ON different from POWER ? */
switch(configure->vcc){ switch (state->Vcc) {
case 0: case 0:
break; break;
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
case 50: case 50:
printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n", printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
__FUNCTION__); __FUNCTION__);
case 33: /* Can only apply 3.3V to the CF slot. */ case 33: /* Can only apply 3.3V to the CF slot. */
break; break;
#else #else
case 50: case 50:
printk(KERN_WARNING "%s(): CS asked for 5V, determinded by jumper setting...\n", __FUNCTION__); printk(KERN_WARNING "%s(): CS asked for 5V, determinded by "
break; "jumper setting...\n", __FUNCTION__);
case 33: break;
printk(KERN_WARNING "%s(): CS asked for 3.3V, determined by jumper setting...\n", __FUNCTION__); case 33:
break; printk(KERN_WARNING "%s(): CS asked for 3.3V, determined by "
"jumper setting...\n", __FUNCTION__);
break;
#endif #endif
default: default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
configure->vcc); __FUNCTION__, state->Vcc);
local_irq_restore(flags); local_irq_restore(flags);
return -1; return -1;
} }
#ifdef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE #ifdef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
/* reset & unreset request */ /* reset & unreset request */
if(sock==0) { if (skt->nr == 0) {
if(configure->reset) { if (state->flags & SS_RESET) {
GPSR |= GPIO_PCMCIA_RESET; GPSR = GPIO_PCMCIA_RESET;
} else { } else {
GPCR |= GPIO_PCMCIA_RESET; GPCR = GPIO_PCMCIA_RESET;
}
} }
}
#endif #endif
/* Silently ignore Vpp, output enable, speaker enable. */ /* Silently ignore Vpp, output enable, speaker enable. */
local_irq_restore(flags); local_irq_restore(flags);
return 0; return 0;
} }
static int pangolin_pcmcia_socket_init(int sock) static void pangolin_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
if (sock == 1) sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
set_irq_type(IRQ_PCMCIA_CD, IRQT_BOTHEDGE);
return 0;
} }
static int pangolin_pcmcia_socket_suspend(int sock) static void pangolin_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
if (sock == 1) sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
set_irq_type(IRQ_PCMCIA_CD, IRQT_NOEDGE);
return 0;
} }
static struct pcmcia_low_level pangolin_pcmcia_ops = { static struct pcmcia_low_level pangolin_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = pangolin_pcmcia_init, .hw_init = pangolin_pcmcia_hw_init,
.shutdown = pangolin_pcmcia_shutdown, .hw_shutdown = pangolin_pcmcia_hw_shutdown,
.socket_state = pangolin_pcmcia_socket_state, .socket_state = pangolin_pcmcia_socket_state,
.configure_socket = pangolin_pcmcia_configure_socket, .configure_socket = pangolin_pcmcia_configure_socket,
.socket_init = pangolin_pcmcia_socket_init, .socket_init = pangolin_pcmcia_socket_init,
.socket_suspend = pangolin_pcmcia_socket_suspend, .socket_suspend = pangolin_pcmcia_socket_suspend,
}; };
int __init pcmcia_pangolin_init(struct device *dev) int __init pcmcia_pangolin_init(struct device *dev)
...@@ -157,13 +141,7 @@ int __init pcmcia_pangolin_init(struct device *dev) ...@@ -157,13 +141,7 @@ int __init pcmcia_pangolin_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_pangolin()) if (machine_is_pangolin())
ret = sa1100_register_pcmcia(&pangolin_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &pangolin_pcmcia_ops, PANGOLIN_SOCK, 1);
return ret; return ret;
} }
void __exit pcmcia_pangolin_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&pangolin_pcmcia_ops, dev);
}
...@@ -16,10 +16,9 @@ ...@@ -16,10 +16,9 @@
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/irq.h> #include <asm/irq.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
static int pfs168_pcmcia_init(struct pcmcia_init *init) static int pfs168_pcmcia_init(struct sa1100_pcmcia_socket *skt)
{ {
/* TPS2211 to standby mode: */ /* TPS2211 to standby mode: */
PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3); PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
...@@ -27,11 +26,12 @@ static int pfs168_pcmcia_init(struct pcmcia_init *init) ...@@ -27,11 +26,12 @@ static int pfs168_pcmcia_init(struct pcmcia_init *init)
/* Set GPIO_A<3:0> to be outputs for PCMCIA (socket 0) power controller: */ /* Set GPIO_A<3:0> to be outputs for PCMCIA (socket 0) power controller: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3); PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
return sa1111_pcmcia_init(init); return sa1111_pcmcia_init(skt);
} }
static int static int
pfs168_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) pfs168_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
unsigned int pa_dwr_mask = 0, pa_dwr_set = 0; unsigned int pa_dwr_mask = 0, pa_dwr_set = 0;
int ret; int ret;
...@@ -48,33 +48,33 @@ pfs168_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -48,33 +48,33 @@ pfs168_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
* *
*/ */
switch (sock) { switch (skt->nr) {
case 0: case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3; pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
switch (conf->vcc) { switch (state->Vcc) {
default: default:
case 0: pa_dwr_set = 0; break; case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO0; break; case 33: pa_dwr_set = GPIO_GPIO0; break;
case 50: pa_dwr_set = GPIO_GPIO1; break; case 50: pa_dwr_set = GPIO_GPIO1; break;
} }
switch (conf->vpp) { switch (state->Vpp) {
case 0: case 0:
break; break;
case 120: case 120:
printk(KERN_ERR "%s(): PFS-168 does not support VPP %uV\n", printk(KERN_ERR "%s(): PFS-168 does not support VPP %uV\n",
__FUNCTION__, conf->vpp / 10); __FUNCTION__, state->Vpp / 10);
return -1; return -1;
break; break;
default: default:
if (conf->vpp == conf->vcc) if (state->Vpp == state->Vcc)
pa_dwr_set |= GPIO_GPIO3; pa_dwr_set |= GPIO_GPIO3;
else { else {
printk(KERN_ERR "%s(): unrecognized VPP %u\n", __FUNCTION__, printk(KERN_ERR "%s(): unrecognized VPP %u\n", __FUNCTION__,
conf->vpp); state->Vpp);
return -1; return -1;
} }
} }
...@@ -91,24 +91,24 @@ pfs168_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -91,24 +91,24 @@ pfs168_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
case 50: case 50:
printk(KERN_ERR "%s(): PFS-168 CompactFlash socket does not support VCC %uV\n", printk(KERN_ERR "%s(): PFS-168 CompactFlash socket does not support VCC %uV\n",
__FUNCTION__, conf->vcc / 10); __FUNCTION__, state->Vcc / 10);
return -1; return -1;
default: default:
printk(KERN_ERR "%s(): unrecognized VCC %u\n", __FUNCTION__, printk(KERN_ERR "%s(): unrecognized VCC %u\n", __FUNCTION__,
conf->vcc); state->Vcc);
return -1; return -1;
} }
if (conf->vpp != conf->vcc && conf->vpp != 0) { if (state->Vpp != state->Vcc && state->Vpp != 0) {
printk(KERN_ERR "%s(): CompactFlash socket does not support VPP %uV\n" printk(KERN_ERR "%s(): CompactFlash socket does not support VPP %uV\n"
__FUNCTION__, conf->vpp / 10); __FUNCTION__, state->Vpp / 10);
return -1; return -1;
} }
break; break;
} }
ret = sa1111_pcmcia_configure_socket(sock, conf); ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) { if (ret == 0) {
unsigned long flags; unsigned long flags;
...@@ -121,14 +121,13 @@ pfs168_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -121,14 +121,13 @@ pfs168_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
} }
static struct pcmcia_low_level pfs168_pcmcia_ops = { static struct pcmcia_low_level pfs168_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = pfs168_pcmcia_init, .hw_init = pfs168_pcmcia_hw_init,
.shutdown = sa1111_pcmcia_shutdown, .hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state, .socket_state = sa1111_pcmcia_socket_state,
.configure_socket = pfs168_pcmcia_configure_socket, .configure_socket = pfs168_pcmcia_configure_socket,
.socket_init = sa1111_pcmcia_socket_init,
.socket_init = sa1111_pcmcia_socket_init, .socket_suspend = sa1111_pcmcia_socket_suspend,
.socket_suspend = sa1111_pcmcia_socket_suspend,
}; };
int __init pcmcia_pfs168_init(struct device *dev) int __init pcmcia_pfs168_init(struct device *dev)
...@@ -136,12 +135,7 @@ int __init pcmcia_pfs168_init(struct device *dev) ...@@ -136,12 +135,7 @@ int __init pcmcia_pfs168_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_pfs168()) if (machine_is_pfs168())
ret = sa1100_register_pcmcia(&pfs168_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &pfs168_pcmcia_ops, 0, 2);
return ret; return ret;
} }
void __exit pcmcia_pfs168_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&pfs168_pcmcia_ops, dev);
}
...@@ -16,64 +16,36 @@ ...@@ -16,64 +16,36 @@
#include <asm/irq.h> #include <asm/irq.h>
#include "sa1100_generic.h" #include "sa1100_generic.h"
static struct irqs { static struct pcmcia_irqs irqs[] = {
int irq; { 0, SHANNON_IRQ_GPIO_EJECT_0, "PCMCIA_CD_0" },
const char *str; { 1, SHANNON_IRQ_GPIO_EJECT_1, "PCMCIA_CD_1" },
} irqs[] = {
{ SHANNON_IRQ_GPIO_EJECT_0, "PCMCIA_CD_0" },
{ SHANNON_IRQ_GPIO_EJECT_1, "PCMCIA_CD_1" },
}; };
static int shannon_pcmcia_init(struct pcmcia_init *init) static int shannon_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
int i, res;
/* All those are inputs */ /* All those are inputs */
GPDR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 | GPDR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 |
SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1); SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1);
GAFR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 | GAFR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 |
SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1); SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1);
init->socket_irq[0] = SHANNON_IRQ_GPIO_RDY_0; skt->irq = skt->nr ? SHANNON_IRQ_GPIO_RDY_1 : SHANNON_IRQ_GPIO_RDY_0;
init->socket_irq[1] = SHANNON_IRQ_GPIO_RDY_1;
/* Register interrupts */
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
res = request_irq(irqs[i].irq, sa1100_pcmcia_interrupt,
SA_INTERRUPT, irqs[i].str, NULL);
if (res)
goto irq_err;
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
}
return 2;
irq_err: return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irqs[i].irq, res);
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
} }
static int shannon_pcmcia_shutdown(void) static void shannon_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
} }
static void shannon_pcmcia_socket_state(int sock, struct pcmcia_state *state) static void
shannon_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
struct pcmcia_state *state)
{ {
unsigned long levels = GPLR; unsigned long levels = GPLR;
switch (sock) { switch (skt->nr) {
case 0: case 0:
state->detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1; state->detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1;
state->ready = (levels & SHANNON_GPIO_RDY_0) ? 1 : 0; state->ready = (levels & SHANNON_GPIO_RDY_0) ? 1 : 0;
...@@ -96,9 +68,11 @@ static void shannon_pcmcia_socket_state(int sock, struct pcmcia_state *state) ...@@ -96,9 +68,11 @@ static void shannon_pcmcia_socket_state(int sock, struct pcmcia_state *state)
} }
} }
static int shannon_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configure) static int
shannon_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
switch (configure->vcc) { switch (state->Vcc) {
case 0: /* power off */ case 0: /* power off */
printk(KERN_WARNING __FUNCTION__"(): CS asked for 0V, still applying 3.3V..\n"); printk(KERN_WARNING __FUNCTION__"(): CS asked for 0V, still applying 3.3V..\n");
break; break;
...@@ -108,7 +82,7 @@ static int shannon_pcmcia_configure_socket(int sock, const struct pcmcia_configu ...@@ -108,7 +82,7 @@ static int shannon_pcmcia_configure_socket(int sock, const struct pcmcia_configu
break; break;
default: default:
printk(KERN_ERR __FUNCTION__"(): unrecognized Vcc %u\n", printk(KERN_ERR __FUNCTION__"(): unrecognized Vcc %u\n",
configure->vcc); state->Vcc);
return -1; return -1;
} }
...@@ -119,30 +93,20 @@ static int shannon_pcmcia_configure_socket(int sock, const struct pcmcia_configu ...@@ -119,30 +93,20 @@ static int shannon_pcmcia_configure_socket(int sock, const struct pcmcia_configu
return 0; return 0;
} }
static int shannon_pcmcia_socket_init(int sock) static void shannon_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
if (sock == 0) sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
set_irq_type(SHANNON_IRQ_GPIO_EJECT_0, IRQT_BOTHEDGE);
else if (sock == 1)
set_irq_Type(SHANNON_IRQ_GPIO_EJECT_1, IRQT_BOTHEDGE);
return 0;
} }
static int shannon_pcmcia_socket_suspend(int sock) static void shannon_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
if (sock == 0) sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
set_irq_type(SHANNON_IRQ_GPIO_EJECT_0, IRQT_NOEDGE);
else if (sock == 1)
set_irq_type(SHANNON_IRQ_GPIO_EJECT_1, IRQT_NOEDGE);
return 0;
} }
static struct pcmcia_low_level shannon_pcmcia_ops = { static struct pcmcia_low_level shannon_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = shannon_pcmcia_init, .hw_init = shannon_pcmcia_hw_init,
.shutdown = shannon_pcmcia_shutdown, .hw_shutdown = shannon_pcmcia_hw_shutdown,
.socket_state = shannon_pcmcia_socket_state, .socket_state = shannon_pcmcia_socket_state,
.configure_socket = shannon_pcmcia_configure_socket, .configure_socket = shannon_pcmcia_configure_socket,
...@@ -155,12 +119,7 @@ int __init pcmcia_shannon_init(struct device *dev) ...@@ -155,12 +119,7 @@ int __init pcmcia_shannon_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_shannon()) if (machine_is_shannon())
ret = sa1100_register_pcmcia(&shannon_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &shannon_pcmcia_ops, 0, 2);
return ret; return ret;
} }
void __exit pcmcia_shannon_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&shannon_pcmcia_ops, dev);
}
...@@ -19,134 +19,110 @@ extern long get_cs3_shadow(void); ...@@ -19,134 +19,110 @@ extern long get_cs3_shadow(void);
extern void set_cs3_bit(int value); extern void set_cs3_bit(int value);
extern void clear_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_init(struct pcmcia_init *init){ static int simpad_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
int irq, res; {
set_cs3_bit(PCMCIA_RESET);
set_cs3_bit(PCMCIA_RESET); clear_cs3_bit(PCMCIA_BUFF_DIS);
clear_cs3_bit(PCMCIA_BUFF_DIS); clear_cs3_bit(PCMCIA_RESET);
clear_cs3_bit(PCMCIA_RESET);
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
init->socket_irq[1] = IRQ_GPIO_CF_IRQ;
/* Register interrupts */
irq = IRQ_GPIO_CF_CD;
res = request_irq(irq, sa1100_pcmcia_interrupt, SA_INTERRUPT,
"CF_CD", NULL );
if( res < 0 ) goto irq_err;
set_irq_type( IRQ_GPIO_CF_CD, IRQT_NOEDGE ); clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
/* There's only one slot, but it's "Slot 1": */ skt->irq = IRQ_GPIO_CF_IRQ;
return 2;
irq_err: return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
printk( KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irq, res);
return res;
} }
static int simpad_pcmcia_shutdown(void) static void simpad_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
/* disable IRQs */ sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
free_irq( IRQ_GPIO_CF_CD, NULL );
/* Disable CF bus: */
/* Disable CF bus: */ //set_cs3_bit(PCMCIA_BUFF_DIS);
clear_cs3_bit(PCMCIA_RESET);
//set_cs3_bit(PCMCIA_BUFF_DIS);
clear_cs3_bit(PCMCIA_RESET);
return 0;
} }
static void simpad_pcmcia_socket_state(int sock, struct pcmcia_state *state) static void
simpad_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
struct pcmcia_state *state)
{ {
if (sock == 1) { unsigned long levels = GPLR;
unsigned long levels = GPLR; unsigned long *cs3reg = CS3_BASE;
unsigned long *cs3reg = CS3_BASE;
state->detect=((levels & GPIO_CF_CD)==0)?1:0;
state->detect=((levels & GPIO_CF_CD)==0)?1:0; state->ready=(levels & GPIO_CF_IRQ)?1:0;
state->ready=(levels & GPIO_CF_IRQ)?1:0; state->bvd1=1; /* Not available on Simpad. */
state->bvd1=1; /* Not available on Simpad. */ state->bvd2=1; /* Not available on Simpad. */
state->bvd2=1; /* Not available on Simpad. */ state->wrprot=0; /* Not available on Simpad. */
state->wrprot=0; /* Not available on Simpad. */
if((*cs3reg & 0x0c) == 0x0c) { if((*cs3reg & 0x0c) == 0x0c) {
state->vs_3v=0; state->vs_3v=0;
state->vs_Xv=0; state->vs_Xv=0;
} else { } else {
state->vs_3v=1; state->vs_3v=1;
state->vs_Xv=0; state->vs_Xv=0;
} }
}
} }
static int simpad_pcmcia_configure_socket(int sock, const struct pcmcia_configure static int
*configure) simpad_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
unsigned long value, flags; unsigned long value, flags;
if(sock>1) return -1; local_irq_save(flags);
if(sock==0) return 0; /* Murphy: see table of MIC2562a-1 */
switch (state->Vcc) {
local_irq_save(flags); case 0:
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
/* Murphy: see table of MIC2562a-1 */ break;
switch(configure->vcc){ case 33:
case 0: clear_cs3_bit(VCC_3V_EN|EN0);
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1); set_cs3_bit(VCC_5V_EN|EN1);
break; break;
case 33: case 50:
clear_cs3_bit(VCC_3V_EN|EN0); clear_cs3_bit(VCC_5V_EN|EN1);
set_cs3_bit(VCC_5V_EN|EN1); set_cs3_bit(VCC_3V_EN|EN0);
break; break;
case 50: default:
clear_cs3_bit(VCC_5V_EN|EN1); printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
set_cs3_bit(VCC_3V_EN|EN0); __FUNCTION__, state->Vcc);
break; clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
local_irq_restore(flags);
default: return -1;
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, }
configure->vcc);
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1); /* Silently ignore Vpp, output enable, speaker enable. */
local_irq_restore(flags); local_irq_restore(flags);
return -1;
} return 0;
/* Silently ignore Vpp, output enable, speaker enable. */
local_irq_restore(flags);
return 0;
} }
static int simpad_pcmcia_socket_init(int sock) static void simpad_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
set_irq_type(IRQ_GPIO_CF_CD, IRQT_BOTHEDGE); sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
return 0;
} }
static int simpad_pcmcia_socket_suspend(int sock) static void simpad_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
set_irq_type(IRQ_GPIO_CF_CD, IRQT_NOEDGE); sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
return 0;
} }
static struct pcmcia_low_level simpad_pcmcia_ops = { static struct pcmcia_low_level simpad_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = simpad_pcmcia_init, .hw_init = simpad_pcmcia_hw_init,
.shutdown = simpad_pcmcia_shutdown, .hw_shutdown = simpad_pcmcia_hw_shutdown,
.socket_state = simpad_pcmcia_socket_state, .socket_state = simpad_pcmcia_socket_state,
.configure_socket = simpad_pcmcia_configure_socket, .configure_socket = simpad_pcmcia_configure_socket,
.socket_init = simpad_pcmcia_socket_init,
.socket_init = simpad_pcmcia_socket_init, .socket_suspend = simpad_pcmcia_socket_suspend,
.socket_suspend = simpad_pcmcia_socket_suspend,
}; };
int __init pcmcia_simpad_init(struct device *dev) int __init pcmcia_simpad_init(struct device *dev)
...@@ -154,12 +130,7 @@ int __init pcmcia_simpad_init(struct device *dev) ...@@ -154,12 +130,7 @@ int __init pcmcia_simpad_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_simpad()) if (machine_is_simpad())
ret = sa1100_register_pcmcia(&simpad_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &simpad_pcmcia_ops, 1, 1);
return ret; return ret;
} }
void __exit pcmcia_simpad_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&simpad_pcmcia_ops, dev);
}
...@@ -32,62 +32,39 @@ ...@@ -32,62 +32,39 @@
static int debug = 0; static int debug = 0;
static struct irqs { static struct pcmcia_irqs irqs[] = {
int irq; { 0, IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, "PCMCIA_CD0" },
const char *str; { 1, IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, "PCMCIA_CD1" },
} irqs[] = {
{ IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, "PCMCIA_CD0" },
{ IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, "PCMCIA_CD1" },
}; };
static int stork_pcmcia_init(struct pcmcia_init *init) static int stork_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
int irq, res;
printk("in stork_pcmcia_init\n"); printk("in stork_pcmcia_init\n");
init->socket_irq[0] = IRQ_GPIO_STORK_PCMCIA_A_RDY; skt->irq = skt->nr ? IRQ_GPIO_STORK_PCMCIA_B_RDY
init->socket_irq[1] = IRQ_GPIO_STORK_PCMCIA_B_RDY; : IRQ_GPIO_STORK_PCMCIA_A_RDY;
/* Register interrupts */
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
res = request_irq(irqs[i].irq, sa1100_pcmcia_interrupt,
SA_INTERRUPT, irqs[i].str, NULL);
if (res)
goto irq_err;
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
}
return 2;
irq_err:
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irq, res);
while (i--) return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
free_irq(irqs[i].irq, NULL);
return res;
} }
static int stork_pcmcia_shutdown(void) static void stork_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
int i; int i;
printk(__FUNCTION__ "\n"); printk(__FUNCTION__ "\n");
/* disable IRQs */ /* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++) sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
free_irq(irqs[i].irq, NULL);
/* Disable CF bus: */ /* Disable CF bus: */
storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON); storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
storkClearLatchA(STORK_PCMCIA_A_POWER_ON); storkClearLatchA(STORK_PCMCIA_A_POWER_ON);
storkClearLatchA(STORK_PCMCIA_B_POWER_ON); storkClearLatchA(STORK_PCMCIA_B_POWER_ON);
return 0;
} }
static void stork_pcmcia_socket_state(int sock, struct pcmcia_state *state) static void
stork_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
struct pcmcia_state *state)
{ {
unsigned long levels = GPLR; unsigned long levels = GPLR;
...@@ -95,7 +72,7 @@ static void stork_pcmcia_socket_state(int sock, struct pcmcia_state *state) ...@@ -95,7 +72,7 @@ static void stork_pcmcia_socket_state(int sock, struct pcmcia_state *state)
printk(__FUNCTION__ " GPLR=%x IRQ[1:0]=%x\n", levels, printk(__FUNCTION__ " GPLR=%x IRQ[1:0]=%x\n", levels,
(levels & (GPIO_STORK_PCMCIA_A_RDY|GPIO_STORK_PCMCIA_B_RDY))); (levels & (GPIO_STORK_PCMCIA_A_RDY|GPIO_STORK_PCMCIA_B_RDY)));
switch (sock) { switch (skt->nr) {
case 0: case 0:
state->detect=((levels & GPIO_STORK_PCMCIA_A_CARD_DETECT)==0)?1:0; state->detect=((levels & GPIO_STORK_PCMCIA_A_CARD_DETECT)==0)?1:0;
state->ready=(levels & GPIO_STORK_PCMCIA_A_RDY)?1:0; state->ready=(levels & GPIO_STORK_PCMCIA_A_RDY)?1:0;
...@@ -118,20 +95,19 @@ static void stork_pcmcia_socket_state(int sock, struct pcmcia_state *state) ...@@ -118,20 +95,19 @@ static void stork_pcmcia_socket_state(int sock, struct pcmcia_state *state)
} }
} }
static int stork_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configure) static int
stork_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
unsigned long flags; unsigned long flags;
int DETECT, RDY, POWER, RESET; int DETECT, RDY, POWER, RESET;
if (sock > 1) return -1; printk("%s: socket=%d vcc=%d vpp=%d reset=%d\n", __FUNCTION__,
skt->nr, state->Vcc, state->Vpp, state->flags & SS_RESET ? 1 : 0);
printk(__FUNCTION__ ": socket=%d vcc=%d vpp=%d reset=%d\n",
sock, configure->vcc, configure->vpp, configure->reset);
local_irq_save(flags); local_irq_save(flags);
if (sock == 0) { if (skt->nr == 0) {
DETECT = GPIO_STORK_PCMCIA_A_CARD_DETECT; DETECT = GPIO_STORK_PCMCIA_A_CARD_DETECT;
RDY = GPIO_STORK_PCMCIA_A_RDY; RDY = GPIO_STORK_PCMCIA_A_RDY;
POWER = STORK_PCMCIA_A_POWER_ON; POWER = STORK_PCMCIA_A_POWER_ON;
...@@ -148,7 +124,7 @@ static int stork_pcmcia_configure_socket(int sock, const struct pcmcia_configure ...@@ -148,7 +124,7 @@ static int stork_pcmcia_configure_socket(int sock, const struct pcmcia_configure
printk("no card detected - but resetting anyway\r\n"); printk("no card detected - but resetting anyway\r\n");
} }
*/ */
switch (configure->vcc) { switch (state->Vcc) {
case 0: case 0:
/* storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON); */ /* storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON); */
storkClearLatchA(POWER); storkClearLatchA(POWER);
...@@ -162,12 +138,12 @@ static int stork_pcmcia_configure_socket(int sock, const struct pcmcia_configure ...@@ -162,12 +138,12 @@ static int stork_pcmcia_configure_socket(int sock, const struct pcmcia_configure
default: default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc); state->Vcc);
local_irq_restore(flags); local_irq_restore(flags);
return -1; return -1;
} }
if (configure->reset) if (state->flags & SS_RESET)
storkSetLatchB(RESET); storkSetLatchB(RESET);
else else
storkClearLatchB(RESET); storkClearLatchB(RESET);
...@@ -176,43 +152,35 @@ static int stork_pcmcia_configure_socket(int sock, const struct pcmcia_configure ...@@ -176,43 +152,35 @@ static int stork_pcmcia_configure_socket(int sock, const struct pcmcia_configure
/* silently ignore vpp and speaker enables. */ /* silently ignore vpp and speaker enables. */
printk(__FUNCTION__ ": finished\n"); printk("%s: finished\n", __FUNCTION__);
return 0; return 0;
} }
static int stork_pcmcia_socket_init(int sock) static void stork_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON); storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
if (sock == 0) sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
set_irq_type(IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, IRQT_BOTHEDGE);
else if (sock == 1)
set_irq_type(IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, IRQT_BOTHEDGE);
return 0;
} }
static int stork_pcmcia_socket_suspend(int sock) static void stork_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
if (sock == 0) sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
set_irq_type(IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, IRQT_NOEDGE);
else if (sock == 1) { /*
set_irq_type(IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, IRQT_NOEDGE); * Hack!
*/
/* if (skt->nr == 1)
* Hack!
*/
storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON); storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
}
return 0; return 0;
} }
static struct pcmcia_low_level stork_pcmcia_ops = { static struct pcmcia_low_level stork_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = stork_pcmcia_init, .hw_init = stork_pcmcia_hw_init,
.shutdown = stork_pcmcia_shutdown, .hw_shutdown = stork_pcmcia_hw_shutdown,
.socket_state = stork_pcmcia_socket_state, .socket_state = stork_pcmcia_socket_state,
.configure_socket = stork_pcmcia_configure_socket, .configure_socket = stork_pcmcia_configure_socket,
...@@ -225,13 +193,7 @@ int __init pcmcia_stork_init(struct device *dev) ...@@ -225,13 +193,7 @@ int __init pcmcia_stork_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_stork()) if (machine_is_stork())
ret = sa1100_register_pcmcia(&stork_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &stork_pcmcia_ops, 0, 2);
return ret; return ret;
} }
void __exit pcmcia_stork_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&stork_pcmcia_ops, dev);
}
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/hardware/sa1111.h> #include <asm/hardware/sa1111.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
#define DEBUG 0 #define DEBUG 0
...@@ -48,34 +47,24 @@ ...@@ -48,34 +47,24 @@
# define DPRINTK( x, args... ) /* nix */ # define DPRINTK( x, args... ) /* nix */
#endif #endif
int system3_pcmcia_init(struct pcmcia_init *init) static int system3_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
init->socket_irq[0] = IRQ_S0_READY_NINT; skt->irq = skt->nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT;
init->socket_irq[1] = IRQ_S1_READY_NINT;
/* Don't need no CD and BVD* interrupts */ /* Don't need no CD and BVD* interrupts */
return 2;
}
int system3_pcmcia_shutdown(void)
{
return 0; return 0;
} }
int system3_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) void system3_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
/* only CF ATM */
if (sock == 0)
return -1;
return sa1111_pcmcia_configure_socket(sock, conf);
} }
static void system3_pcmcia_socket_state(int sock, struct pcmcia_state *state) static void
system3_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
{ {
unsigned long status = PCSR; unsigned long status = PCSR;
switch (sock) { switch (skt->nr) {
#if 0 /* PCMCIA socket not yet connected */ #if 0 /* PCMCIA socket not yet connected */
case 0: case 0:
state->detect = status & PCSR_S0_DETECT ? 0 : 1; state->detect = status & PCSR_S0_DETECT ? 0 : 1;
...@@ -100,15 +89,15 @@ static void system3_pcmcia_socket_state(int sock, struct pcmcia_state *state) ...@@ -100,15 +89,15 @@ static void system3_pcmcia_socket_state(int sock, struct pcmcia_state *state)
} }
DPRINTK("Sock %d PCSR=0x%08lx, Sx_RDY_nIREQ=%d\n", DPRINTK("Sock %d PCSR=0x%08lx, Sx_RDY_nIREQ=%d\n",
sock, status, state->ready); skt->nr, status, state->ready);
} }
struct pcmcia_low_level system3_pcmcia_ops = { struct pcmcia_low_level system3_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = system3_pcmcia_init, .init = system3_pcmcia_hw_init,
.shutdown = system3_pcmcia_shutdown, .shutdown = system3_pcmcia_hw_shutdown,
.socket_state = system3_pcmcia_socket_state, .socket_state = system3_pcmcia_socket_state,
.configure_socket = system3_pcmcia_configure_socket, .configure_socket = sa1111_pcmcia_configure_socket,
.socket_init = sa1111_pcmcia_socket_init, .socket_init = sa1111_pcmcia_socket_init,
.socket_suspend = sa1111_pcmcia_socket_suspend, .socket_suspend = sa1111_pcmcia_socket_suspend,
...@@ -119,12 +108,8 @@ int __init pcmcia_system3_init(struct device *dev) ...@@ -119,12 +108,8 @@ int __init pcmcia_system3_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_pt_system3()) if (machine_is_pt_system3())
ret = sa1100_register_pcmcia(&system3_pcmcia_ops, dev); /* only CF ATM */
ret = sa11xx_drv_pcmcia_probe(dev, &system3_pcmcia_ops, 1, 1);
return ret; return ret;
} }
void __exit pcmcia_system3_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&system3_pcmcia_ops, dev);
}
...@@ -23,15 +23,18 @@ ...@@ -23,15 +23,18 @@
#include "sa1100_generic.h" #include "sa1100_generic.h"
#define NUMBER_OF_TRIZEPS_PCMCIA_SLOTS 1 #define NUMBER_OF_TRIZEPS_PCMCIA_SLOTS 1
static struct pcmcia_irqs irqs[] = {
{ 0, TRIZEPS_IRQ_PCMCIA_CD0, "PCMCIA_CD0" },
};
/** /**
* *
* *
******************************************************/ ******************************************************/
static int trizeps_pcmcia_init(struct pcmcia_init *init) static int trizeps_pcmcia_init(struct sa1100_pcmcia_socket *skt)
{ {
int res; skt->irq = TRIZEPS_IRQ_PCMCIA_IRQ0;
init->socket_irq[0] = TRIZEPS_IRQ_PCMCIA_IRQ0;
/* Enable CF bus: */ /* Enable CF bus: */
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_nPCM_ENA_REG); TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_nPCM_ENA_REG);
...@@ -40,74 +43,54 @@ static int trizeps_pcmcia_init(struct pcmcia_init *init) ...@@ -40,74 +43,54 @@ static int trizeps_pcmcia_init(struct pcmcia_init *init)
GPDR &= ~((GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_CD0)) GPDR &= ~((GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_CD0))
| (GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_IRQ0))); | (GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_IRQ0)));
/* Register SOCKET interrupts */ return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* WHY? */
res = request_irq(TRIZEPS_IRQ_PCMCIA_CD0, sa1100_pcmcia_interrupt,
SA_INTERRUPT, "PCMCIA_CD0", NULL );
if( res < 0 ) goto irq_err;
set_irq_type(TRIZEPS_IRQ_PCMCIA_CD0, IRQT_NOEDGE);
//MECR = 0x00060006; // Initialised on trizeps init
// return=sa1100_pcmcia_socket_count (sa1100_generic.c)
// -> number of PCMCIA Slots
// Slot 0 -> Trizeps PCMCIA
// Slot 1 -> Trizeps ISA-Bus
return NUMBER_OF_TRIZEPS_PCMCIA_SLOTS;
irq_err:
printk( KERN_ERR "%s(): PCMCIA Request for IRQ %u failed\n", __FUNCTION__, TRIZEPS_IRQ_PCMCIA_CD0 );
return -1;
} }
/** /**
* *
* *
******************************************************/ ******************************************************/
static int trizeps_pcmcia_shutdown(void) static void trizeps_pcmcia_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
printk(">>>>>PCMCIA TRIZEPS shutdown\n"); printk(">>>>>PCMCIA TRIZEPS shutdown\n");
/* disable IRQs */
free_irq(TRIZEPS_IRQ_PCMCIA_CD0, NULL ); sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* Disable CF bus: */ /* Disable CF bus: */
TRIZEPS_BCR_set(TRIZEPS_BCR1, TRIZEPS_nPCM_ENA_REG); TRIZEPS_BCR_set(TRIZEPS_BCR1, TRIZEPS_nPCM_ENA_REG);
return 0;
} }
/** /**
* *
******************************************************/ ******************************************************/
static void trizeps_pcmcia_socket_state(int sock, struct pcmcia_state *state_array) static void
trizeps_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
struct pcmcia_state *state_array)
{ {
unsigned long levels = GPLR; unsigned long levels = GPLR;
if (sock == 0) { state->detect = ((levels & GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_CD0)) == 0) ? 1 : 0;
state->detect = ((levels & GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_CD0)) == 0) ? 1 : 0; state->ready = ((levels & GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_IRQ0)) != 0) ? 1 : 0;
state->ready = ((levels & GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_IRQ0)) != 0) ? 1 : 0; state->bvd1 = ((TRIZEPS_BCR1 & TRIZEPS_PCM_BVD1) !=0 ) ? 1 : 0;
state->bvd1 = ((TRIZEPS_BCR1 & TRIZEPS_PCM_BVD1) !=0 ) ? 1 : 0; state->bvd2 = ((TRIZEPS_BCR1 & TRIZEPS_PCM_BVD2) != 0) ? 1 : 0;
state->bvd2 = ((TRIZEPS_BCR1 & TRIZEPS_PCM_BVD2) != 0) ? 1 : 0; state->wrprot = 0; // not write protected
state->wrprot = 0; // not write protected state->vs_3v = ((TRIZEPS_BCR1 & TRIZEPS_nPCM_VS1) == 0) ? 1 : 0; //VS1=0 -> vs_3v=1
state->vs_3v = ((TRIZEPS_BCR1 & TRIZEPS_nPCM_VS1) == 0) ? 1 : 0; //VS1=0 -> vs_3v=1 state->vs_Xv = ((TRIZEPS_BCR1 & TRIZEPS_nPCM_VS2) == 0) ? 1 : 0; //VS2=0 -> vs_Xv=1
state->vs_Xv = ((TRIZEPS_BCR1 & TRIZEPS_nPCM_VS2) == 0) ? 1 : 0; //VS2=0 -> vs_Xv=1
}
} }
/** /**
* *
* *
******************************************************/ ******************************************************/
static int trizeps_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configure) static int
trizeps_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
unsigned long flags; unsigned long flags;
if(sock>1) return -1;
local_irq_save(flags); local_irq_save(flags);
switch (configure->vcc) { switch (state->Vcc) {
case 0: case 0:
printk(">>> PCMCIA Power off\n"); printk(">>> PCMCIA Power off\n");
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_PCM_V3_EN_REG); TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_PCM_V3_EN_REG);
...@@ -126,19 +109,19 @@ static int trizeps_pcmcia_configure_socket(int sock, const struct pcmcia_configu ...@@ -126,19 +109,19 @@ static int trizeps_pcmcia_configure_socket(int sock, const struct pcmcia_configu
break; break;
default: default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc); state->Vcc);
local_irq_restore(flags); local_irq_restore(flags);
return -1; return -1;
} }
if (configure->reset) if (state->flags & SS_RESET)
TRIZEPS_BCR_set(TRIZEPS_BCR1, TRIZEPS_nPCM_RESET_DISABLE); // Reset TRIZEPS_BCR_set(TRIZEPS_BCR1, TRIZEPS_nPCM_RESET_DISABLE); // Reset
else else
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_nPCM_RESET_DISABLE); // no Reset TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_nPCM_RESET_DISABLE); // no Reset
/* /*
printk(" vcc=%u vpp=%u -->reset=%i\n", printk(" vcc=%u vpp=%u -->reset=%i\n",
configure->vcc, state->Vcc,
configure->vpp, state->Vpp,
((BCR_read(1) & nPCM_RESET_DISABLE)? 1:0)); ((BCR_read(1) & nPCM_RESET_DISABLE)? 1:0));
*/ */
local_irq_restore(flags); local_irq_restore(flags);
...@@ -146,16 +129,14 @@ static int trizeps_pcmcia_configure_socket(int sock, const struct pcmcia_configu ...@@ -146,16 +129,14 @@ static int trizeps_pcmcia_configure_socket(int sock, const struct pcmcia_configu
return 0; return 0;
} }
static int trizeps_pcmcia_socket_init(int sock) static void trizeps_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
set_irq_type(TRIZEPS_IRQ_PCMCIA_CD0, IRQT_BOTHEDGE); sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
return 0;
} }
static int trizeps_pcmcia_socket_suspend(int sock) static void trizeps_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
set_irq_type(TRIZEPS_IRQ_PCMCIA_CD0, IRQT_NOEDGE); sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
return 0;
} }
/** /**
...@@ -164,8 +145,8 @@ static int trizeps_pcmcia_socket_suspend(int sock) ...@@ -164,8 +145,8 @@ static int trizeps_pcmcia_socket_suspend(int sock)
******************************************************/ ******************************************************/
struct pcmcia_low_level trizeps_pcmcia_ops = { struct pcmcia_low_level trizeps_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = trizeps_pcmcia_init, .hw_init = trizeps_pcmcia_hw_init,
.shutdown = trizeps_pcmcia_shutdown, .hw_shutdown = trizeps_pcmcia_hw_shutdown,
.socket_state = trizeps_pcmcia_socket_state, .socket_state = trizeps_pcmcia_socket_state,
.configure_socket = trizeps_pcmcia_configure_socket, .configure_socket = trizeps_pcmcia_configure_socket,
.socket_init = trizeps_pcmcia_socket_init, .socket_init = trizeps_pcmcia_socket_init,
...@@ -174,13 +155,11 @@ struct pcmcia_low_level trizeps_pcmcia_ops = { ...@@ -174,13 +155,11 @@ struct pcmcia_low_level trizeps_pcmcia_ops = {
int __init pcmcia_trizeps_init(struct device *dev) int __init pcmcia_trizeps_init(struct device *dev)
{ {
if (machine_is_trizeps()) { int ret = -ENODEV;
return sa1100_register_pcmcia(&trizeps_pcmcia_ops, dev);
}
return -ENODEV;
}
void __exit pcmcia_trizeps_exit(struct device *dev) if (machine_is_trizeps())
{ ret = sa11xx_drv_pcmcia_probe(dev, &trizeps_pcmcia_ops, 0,
sa1100_unregister_pcmcia(&trizeps_pcmcia_ops, dev); NUMBER_OF_TRIZEPS_PCMCIA_SLOTS);
return ret;
} }
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#define NCR_A0VPP (1<<16) #define NCR_A0VPP (1<<16)
#define NCR_A1VPP (1<<17) #define NCR_A1VPP (1<<17)
static int xp860_pcmcia_init(struct pcmcia_init *init) static int xp860_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
/* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */ /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3); PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
...@@ -38,11 +38,11 @@ static int xp860_pcmcia_init(struct pcmcia_init *init) ...@@ -38,11 +38,11 @@ static int xp860_pcmcia_init(struct pcmcia_init *init)
GPDR |= (NCR_A0VPP | NCR_A1VPP); GPDR |= (NCR_A0VPP | NCR_A1VPP);
GPCR &= ~(NCR_A0VPP | NCR_A1VPP); GPCR &= ~(NCR_A0VPP | NCR_A1VPP);
return sa1111_pcmcia_init(init); return sa1111_pcmcia_hw_init(skt);
} }
static int static int
xp860_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) xp860_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
{ {
unsigned int gpio_mask, pa_dwr_mask; unsigned int gpio_mask, pa_dwr_mask;
unsigned int gpio_set, pa_dwr_set; unsigned int gpio_set, pa_dwr_set;
...@@ -72,28 +72,28 @@ xp860_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -72,28 +72,28 @@ xp860_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
* the corresponding truth table. * the corresponding truth table.
*/ */
switch (sock) { switch (skt->nr) {
case 0: case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1; pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
gpio_mask = NCR_A0VPP | NCR_A1VPP; gpio_mask = NCR_A0VPP | NCR_A1VPP;
switch (conf->vcc) { switch (state->Vcc) {
default: default:
case 0: pa_dwr_set = 0; break; case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO1; break; case 33: pa_dwr_set = GPIO_GPIO1; break;
case 50: pa_dwr_set = GPIO_GPIO0; break; case 50: pa_dwr_set = GPIO_GPIO0; break;
} }
switch (conf->vpp) { switch (state->Vpp) {
case 0: gpio_set = 0; break; case 0: gpio_set = 0; break;
case 120: gpio_set = NCR_A1VPP; break; case 120: gpio_set = NCR_A1VPP; break;
default: default:
if (conf->vpp == conf->vcc) if (state->Vpp == state->Vcc)
gpio_set = NCR_A0VPP; gpio_set = NCR_A0VPP;
else { else {
printk(KERN_ERR "%s(): unrecognized Vpp %u\n", printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
__FUNCTION__, conf->vpp); __FUNCTION__, state->Vpp);
return -1; return -1;
} }
} }
...@@ -104,22 +104,22 @@ xp860_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -104,22 +104,22 @@ xp860_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
gpio_mask = 0; gpio_mask = 0;
gpio_set = 0; gpio_set = 0;
switch (conf->vcc) { switch (state->Vcc) {
default: default:
case 0: pa_dwr_set = 0; break; case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO2; break; case 33: pa_dwr_set = GPIO_GPIO2; break;
case 50: pa_dwr_set = GPIO_GPIO3; break; case 50: pa_dwr_set = GPIO_GPIO3; break;
} }
if (conf->vpp != conf->vcc && conf->vpp != 0) { if (state->Vpp != state->Vcc && state->Vpp != 0) {
printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
__FUNCTION__, conf->vpp); __FUNCTION__, state->Vpp);
return -1; return -1;
} }
break; break;
} }
ret = sa1111_pcmcia_configure_socket(sock, conf); ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) { if (ret == 0) {
unsigned long flags; unsigned long flags;
...@@ -134,14 +134,13 @@ xp860_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf) ...@@ -134,14 +134,13 @@ xp860_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
} }
static struct pcmcia_low_level xp860_pcmcia_ops = { static struct pcmcia_low_level xp860_pcmcia_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = xp860_pcmcia_init, .hw_init = xp860_pcmcia_hw_init,
.shutdown = sa1111_pcmcia_shutdown, .hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state, .socket_state = sa1111_pcmcia_socket_state,
.configure_socket = xp860_pcmcia_configure_socket, .configure_socket = xp860_pcmcia_configure_socket,
.socket_init = sa1111_pcmcia_socket_init,
.socket_init = sa1111_pcmcia_socket_init, .socket_suspend = sa1111_pcmcia_socket_suspend,
.socket_suspend = sa1111_pcmcia_socket_suspend,
}; };
int __init pcmcia_xp860_init(struct device *dev) int __init pcmcia_xp860_init(struct device *dev)
...@@ -149,13 +148,7 @@ int __init pcmcia_xp860_init(struct device *dev) ...@@ -149,13 +148,7 @@ int __init pcmcia_xp860_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_xp860()) if (machine_is_xp860())
ret = sa1100_register_pcmcia(&xp860_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &xp860_pcmcia_ops, 0, 2);
return ret; return ret;
} }
void __exit pcmcia_xp860_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&xp860_pcmcia_ops, dev);
}
...@@ -27,81 +27,51 @@ static inline void pcmcia_reset(int reset) ...@@ -27,81 +27,51 @@ static inline void pcmcia_reset(int reset)
yopy_gpio_set(GPIO_CF_RESET, reset); yopy_gpio_set(GPIO_CF_RESET, reset);
} }
static struct irqs { static struct pcmcia_irqs irqs[] = {
int irq; { 0, IRQ_CF_CD, "CF_CD" },
const char *str; { 0, IRQ_CF_BVD2, "CF_BVD2" },
} irqs[] = { { 0, IRQ_CF_BVD1, "CF_BVD1" },
{ IRQ_CF_CD, "CF_CD" },
{ IRQ_CF_BVD2, "CF_BVD2" },
{ IRQ_CF_BVD1, "CF_BVD1" },
}; };
static int yopy_pcmcia_init(struct pcmcia_init *init) static int yopy_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{ {
int i, res; skt->irq = IRQ_CF_IREQ;
init->socket_irq[0] = IRQ_CF_IREQ;
pcmcia_power(0); pcmcia_power(0);
pcmcia_reset(1); pcmcia_reset(1);
/* Register interrupts */ return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
res = request_irq(irqs[i].irq, sa1100_pcmcia_interrupt,
SA_INTERRUPT, irqs[i].str, NULL);
if (res)
goto irq_err;
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
}
return 1;
irq_err:
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irqs[i].irq, res);
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
} }
static int yopy_pcmcia_shutdown(void) static void yopy_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
/* Disable CF */ /* Disable CF */
pcmcia_reset(1); pcmcia_reset(1);
pcmcia_power(0); pcmcia_power(0);
return 0;
} }
static void yopy_pcmcia_socket_state(int sock, struct pcmcia_state_array *state) static void
yopy_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
struct pcmcia_state_array *state)
{ {
unsigned long levels = GPLR; unsigned long levels = GPLR;
if (sock == 0) { state->detect = (levels & GPIO_CF_CD) ? 0 : 1;
state->detect = (levels & GPIO_CF_CD) ? 0 : 1; state->ready = (levels & GPIO_CF_READY) ? 1 : 0;
state->ready = (levels & GPIO_CF_READY) ? 1 : 0; state->bvd1 = (levels & GPIO_CF_BVD1) ? 1 : 0;
state->bvd1 = (levels & GPIO_CF_BVD1) ? 1 : 0; state->bvd2 = (levels & GPIO_CF_BVD2) ? 1 : 0;
state->bvd2 = (levels & GPIO_CF_BVD2) ? 1 : 0; state->wrprot = 0; /* Not available on Yopy. */
state->wrprot = 0; /* Not available on Yopy. */ state->vs_3v = 0; /* FIXME Can only apply 3.3V on Yopy. */
state->vs_3v = 0; /* FIXME Can only apply 3.3V on Yopy. */ state->vs_Xv = 0;
state->vs_Xv = 0;
}
} }
static int yopy_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configure) static int
yopy_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{ {
if (sock != 0) switch (state->Vcc) {
return -1;
switch (configure->vcc) {
case 0: /* power off */ case 0: /* power off */
pcmcia_power(0); pcmcia_power(0);
break; break;
...@@ -112,35 +82,25 @@ static int yopy_pcmcia_configure_socket(int sock, const struct pcmcia_configure ...@@ -112,35 +82,25 @@ static int yopy_pcmcia_configure_socket(int sock, const struct pcmcia_configure
break; break;
default: default:
printk(KERN_ERR __FUNCTION__"(): unrecognized Vcc %u\n", printk(KERN_ERR __FUNCTION__"(): unrecognized Vcc %u\n",
configure->vcc); state->Vcc);
return -1; return -1;
} }
pcmcia_reset(configure->reset); pcmcia_reset(state->flags & SS_RESET ? 1 : 0);
/* Silently ignore Vpp, output enable, speaker enable. */ /* Silently ignore Vpp, output enable, speaker enable. */
return 0; return 0;
} }
static int yopy_pcmcia_socket_init(int sock) static void yopy_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
return 0;
} }
static int yopy_pcmcia_socket_suspend(int sock) static void yopy_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{ {
int i; sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
return 0;
} }
static struct pcmcia_low_level yopy_pcmcia_ops = { static struct pcmcia_low_level yopy_pcmcia_ops = {
...@@ -159,13 +119,7 @@ int __init pcmcia_yopy_init(struct device *dev) ...@@ -159,13 +119,7 @@ int __init pcmcia_yopy_init(struct device *dev)
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_yopy()) if (machine_is_yopy())
ret = sa1100_register_pcmcia(&yopy_pcmcia_ops, dev); ret = sa11xx_drv_pcmcia_probe(dev, &yopy_pcmcia_ops, 0, 1);
return ret; return ret;
} }
void __exit pcmcia_yopy_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&yopy_pcmcia_ops, dev);
}
This diff is collapsed.
extern int sa1111_pcmcia_init(struct pcmcia_init *); #include "sa11xx_core.h"
extern int sa1111_pcmcia_shutdown(void);
extern void sa1111_pcmcia_socket_state(int sock, struct pcmcia_state *);
extern int sa1111_pcmcia_configure_socket(int sock, const struct pcmcia_configure *);
extern int sa1111_pcmcia_socket_init(int);
extern int sa1111_pcmcia_socket_suspend(int);
extern int sa1111_pcmcia_hw_init(struct sa1100_pcmcia_socket *);
extern void sa1111_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *);
extern void sa1111_pcmcia_socket_state(struct sa1100_pcmcia_socket *, struct pcmcia_state *);
extern int sa1111_pcmcia_configure_socket(struct sa1100_pcmcia_socket *, const socket_state_t *);
extern void sa1111_pcmcia_socket_init(struct sa1100_pcmcia_socket *);
extern void sa1111_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *);
extern int pcmcia_jornada720_init(struct device *); extern int pcmcia_jornada720_init(struct device *);
extern void pcmcia_jornada720_exit(struct device *);
extern int pcmcia_neponset_init(struct device *); extern int pcmcia_neponset_init(struct device *);
extern void pcmcia_neponset_exit(struct device *);
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment