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
config PCMCIA_SA1100
tristate "SA1100 support"
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
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
bool
......
......@@ -11,8 +11,8 @@ obj-$(CONFIG_I82365) += i82365.o
obj-$(CONFIG_I82092) += i82092.o
obj-$(CONFIG_TCIC) += tcic.o
obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o
obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o
obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.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,
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
* (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75)
*
......@@ -191,59 +161,4 @@ struct sa1100_pcmcia_socket {
#define iostschg bvd1
#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) */
......@@ -18,10 +18,9 @@
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include "sa1100_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: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
......@@ -32,20 +31,20 @@ static int adsbitsy_pcmcia_init(struct pcmcia_init *init)
/* Why? */
MECR = 0x09430943;
return sa1111_pcmcia_init(init);
return sa1111_pcmcia_init(skt);
}
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;
int ret;
switch (sock) {
switch (skt->nr) {
case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
switch (conf->vcc) {
switch (state->Vcc) {
default:
case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
case 33: pa_dwr_set = GPIO_GPIO1; break;
......@@ -56,7 +55,7 @@ adsbitsy_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
case 1:
pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
switch (conf->vcc) {
switch (state->Vcc) {
default:
case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO2; break;
......@@ -67,13 +66,13 @@ adsbitsy_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
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",
__FUNCTION__, conf->vpp);
__FUNCTION__, state->Vpp);
return -1;
}
ret = sa1111_pcmcia_configure_socket(sock, conf);
ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) {
unsigned long flags;
......@@ -87,11 +86,10 @@ adsbitsy_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
static struct pcmcia_low_level adsbitsy_pcmcia_ops = {
.owner = THIS_MODULE,
.init = adsbitsy_pcmcia_init,
.shutdown = sa1111_pcmcia_shutdown,
.hw_init = adsbitsy_pcmcia_hw_init,
.hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state,
.configure_socket = adsbitsy_pcmcia_configure_socket,
.socket_init = sa1111_pcmcia_socket_init,
.socket_suspend = sa1111_pcmcia_socket_suspend,
};
......@@ -100,11 +98,6 @@ int __init pcmcia_adsbitsy_init(struct device *dev)
{
int ret = -ENODEV;
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;
}
void __exit pcmcia_adsbitsy_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&adsbitsy_pcmcia_ops, dev);
}
......@@ -20,63 +20,32 @@
#include "sa1100_generic.h"
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ ASSABET_IRQ_GPIO_CF_CD, "CF_CD" },
{ ASSABET_IRQ_GPIO_CF_BVD2, "CF_BVD2" },
{ ASSABET_IRQ_GPIO_CF_BVD1, "CF_BVD1" },
static struct pcmcia_irqs irqs[] = {
{ 1, ASSABET_IRQ_GPIO_CF_CD, "CF CD" },
{ 1, ASSABET_IRQ_GPIO_CF_BVD2, "CF BVD2" },
{ 1, ASSABET_IRQ_GPIO_CF_BVD1, "CF BVD1" },
};
static int assabet_pcmcia_init(struct pcmcia_init *init)
static int assabet_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{
int i, res;
/* 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);
skt->irq = ASSABET_IRQ_GPIO_CF_IRQ;
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
/*
* Release all resources.
*/
static int assabet_pcmcia_shutdown(void)
static void assabet_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{
int i;
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
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;
if (sock == 1) {
state->detect = (levels & ASSABET_GPIO_CF_CD) ? 0 : 1;
state->ready = (levels & ASSABET_GPIO_CF_IRQ) ? 1 : 0;
state->bvd1 = (levels & ASSABET_GPIO_CF_BVD1) ? 1 : 0;
......@@ -84,21 +53,14 @@ assabet_pcmcia_socket_state(int sock, struct pcmcia_state *state)
state->wrprot = 0; /* Not available on Assabet. */
state->vs_3v = 1; /* Can only apply 3.3V on Assabet. */
state->vs_Xv = 0;
}
}
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;
if (sock > 1)
return -1;
if (sock == 0)
return 0;
switch (configure->vcc) {
switch (state->Vcc) {
case 0:
mask = 0;
break;
......@@ -113,13 +75,13 @@ assabet_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configu
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
state->Vcc);
return -1;
}
/* Silently ignore Vpp, output enable, speaker enable. */
if (configure->reset)
if (state->flags & SS_RESET)
mask |= ASSABET_BCR_CF_RST;
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
* be called at initialisation, power management event, or
* pcmcia event.
*/
static int assabet_pcmcia_socket_init(int sock)
static void assabet_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{
int i;
if (sock == 1) {
/*
* 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.
*/
static int assabet_pcmcia_socket_suspend(int sock)
static void assabet_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{
int i;
if (sock == 1) {
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
/*
* 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;
}
static struct pcmcia_low_level assabet_pcmcia_ops = {
.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,
.configure_socket = assabet_pcmcia_configure_socket,
......@@ -185,20 +135,8 @@ int __init pcmcia_assabet_init(struct device *dev)
{
int ret = -ENODEV;
if (machine_is_assabet()) {
if (!machine_has_neponset())
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;
}
if (machine_is_assabet() && !machine_has_neponset())
ret = sa11xx_drv_pcmcia_probe(dev, &assabet_pcmcia_ops, 1, 1);
void __exit pcmcia_assabet_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&assabet_pcmcia_ops, dev);
return ret;
}
......@@ -24,7 +24,6 @@
#include <asm/arch/badge4.h>
#include <asm/hardware/sa1111.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
/*
......@@ -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_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,
const char *supply,
int given, int wanted)
......@@ -97,32 +75,32 @@ static void complain_about_jumpering(const char *whom,
}
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;
switch (sock) {
switch (skt->nr) {
case 0:
if ((conf->vcc != 0) &&
(conf->vcc != badge4_pcmvcc)) {
if ((state->Vcc != 0) &&
(state->Vcc != badge4_pcmvcc)) {
complain_about_jumpering(__FUNCTION__, "pcmvcc",
badge4_pcmvcc, conf->vcc);
badge4_pcmvcc, state->Vcc);
// Apply power regardless of the jumpering.
// return -1;
}
if ((conf->vpp != 0) &&
(conf->vpp != badge4_pcmvpp)) {
if ((state->Vpp != 0) &&
(state->Vpp != badge4_pcmvpp)) {
complain_about_jumpering(__FUNCTION__, "pcmvpp",
badge4_pcmvpp, conf->vpp);
badge4_pcmvpp, state->Vpp);
return -1;
}
break;
case 1:
if ((conf->vcc != 0) &&
(conf->vcc != badge4_cfvcc)) {
if ((state->Vcc != 0) &&
(state->Vcc != badge4_cfvcc)) {
complain_about_jumpering(__FUNCTION__, "cfvcc",
badge4_cfvcc, conf->vcc);
badge4_cfvcc, state->Vcc);
return -1;
}
break;
......@@ -131,16 +109,16 @@ badge4_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
return -1;
}
ret = sa1111_pcmcia_configure_socket(sock, conf);
ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) {
unsigned long flags;
int need5V;
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);
}
......@@ -150,8 +128,8 @@ badge4_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
static struct pcmcia_low_level badge4_pcmcia_ops = {
.owner = THIS_MODULE,
.init = badge4_pcmcia_init,
.shutdown = badge4_pcmcia_shutdown,
.init = sa1111_pcmcia_hw_init,
.shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state,
.configure_socket = badge4_pcmcia_configure_socket,
......@@ -163,15 +141,16 @@ int pcmcia_badge4_init(struct device *dev)
{
int ret = -ENODEV;
if (machine_is_badge4())
ret = sa1100_register_pcmcia(&badge4_pcmcia_ops, dev);
if (machine_is_badge4()) {
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)
{
sa1100_unregister_pcmcia(&badge4_pcmcia_ops, dev);
return ret;
}
static int __init pcmv_setup(char *s)
......
......@@ -23,56 +23,29 @@
#define CERF_SOCKET 1
#endif
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ IRQ_GPIO_CF_CD, "CF_CD" },
{ IRQ_GPIO_CF_BVD2, "CF_BVD2" },
{ IRQ_GPIO_CF_BVD1, "CF_BVD1" }
static struct pcmcia_irqs irqs[] = {
{ CERF_SOCKET, IRQ_GPIO_CF_CD, "CF_CD" },
{ CERF_SOCKET, IRQ_GPIO_CF_BVD2, "CF_BVD2" },
{ CERF_SOCKET, 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;
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[CERF_SOCKET] = IRQ_GPIO_CF_IRQ;
return 2;
skt->irq = IRQ_GPIO_CF_IRQ;
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;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int cerf_pcmcia_shutdown(void)
static void cerf_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{
int i;
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
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->ready=(levels & GPIO_CF_IRQ)?1:0;
state->bvd1=(levels & GPIO_CF_BVD1)?1:0;
......@@ -80,19 +53,13 @@ static void cerf_pcmcia_socket_state(int sock, struct pcmcia_state *state)
state->wrprot=0;
state->vs_3v=1;
state->vs_Xv=0;
}
}
static int cerf_pcmcia_configure_socket(int sock, const struct pcmcia_configure
*configure)
static int
cerf_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{
if (sock>1)
return -1;
if (sock != CERF_SOCKET)
return 0;
switch(configure->vcc){
switch (state->Vcc) {
case 0:
break;
......@@ -104,19 +71,16 @@ static int cerf_pcmcia_configure_socket(int sock, const struct pcmcia_configure
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
__FUNCTION__, state->Vcc);
return -1;
}
if(configure->reset)
{
if (state->flags & SS_RESET) {
#ifdef CONFIG_SA1100_CERF_CPLD
GPSR = GPIO_CF_RESET;
#endif
}
else
{
} else {
#ifdef CONFIG_SA1100_CERF_CPLD
GPCR = GPIO_CF_RESET;
#endif
......@@ -125,32 +89,20 @@ static int cerf_pcmcia_configure_socket(int sock, const struct pcmcia_configure
return 0;
}
static int cerf_pcmcia_socket_init(int sock)
static void cerf_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{
int i;
if (sock == CERF_SOCKET)
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));
}
static int cerf_pcmcia_socket_suspend(int sock)
static void cerf_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{
int i;
if (sock == CERF_SOCKET)
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
return 0;
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static struct pcmcia_low_level cerf_pcmcia_ops = {
.owner = THIS_MODULE,
.init = cerf_pcmcia_init,
.shutdown = cerf_pcmcia_shutdown,
.init = cerf_pcmcia_hw_init,
.shutdown = cerf_pcmcia_hw_shutdown,
.socket_state = cerf_pcmcia_socket_state,
.configure_socket = cerf_pcmcia_configure_socket,
......@@ -163,12 +115,7 @@ int __init pcmcia_cerf_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_cerf_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&cerf_pcmcia_ops, dev);
}
......@@ -16,69 +16,32 @@
#include <asm/irq.h>
#include "sa1100_generic.h"
static struct {
int irq;
const char *name;
} irqs[] = {
{ IRQ_GPIO_CF1_CD, "CF1_CD" },
{ IRQ_GPIO_CF1_BVD1, "CF1_BVD1" },
{ IRQ_GPIO_CF2_CD, "CF2_CD" },
{ IRQ_GPIO_CF2_BVD1, "CF2_BVD1" }
static struct pcmcia_irqs irqs[] = {
{ 0, IRQ_GPIO_CF1_CD, "CF1_CD" },
{ 0, IRQ_GPIO_CF1_BVD1, "CF1_BVD1" },
{ 1, IRQ_GPIO_CF2_CD, "CF2_CD" },
{ 1, IRQ_GPIO_CF2_BVD1, "CF2_BVD1" }
};
/*
* Socket initialization.
*
* 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;
/* Configure the GPIOs as inputs (BVD2 is not implemented) */
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;
}
skt->irq = skt->nr ? IRQ_GPIO_CF2_IRQ : IRQ_GPIO_CF1_IRQ;
return 2;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
/*
* Socket shutdown
*
*/
static int flexanet_pcmcia_shutdown(void)
static void flexanet_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{
int i;
/* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
......@@ -88,12 +51,14 @@ static int flexanet_pcmcia_shutdown(void)
* 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 */
switch (sock) {
case 0: /* Socket 0 */
switch (skt->nr) {
ase 0: /* Socket 0 */
state->detect = ((levels & GPIO_CF1_NCD)==0)?1:0;
state->ready = (levels & GPIO_CF1_IRQ)?1:0;
state->bvd1 = (levels & GPIO_CF1_BVD1)?1:0;
......@@ -119,19 +84,17 @@ static void flexanet_pcmcia_socket_state(int sock, struct pcmcia_state *state)
/*
*
*/
static int flexanet_pcmcia_configure_socket(int sock, const struct pcmcia_configure
*configure)
static int
flexanet_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{
unsigned long value, flags, mask;
if (sock > 1)
return -1;
/* Ignore the VCC level since it is 3.3V and always on */
switch (configure->vcc)
{
switch (state->Vcc) {
case 0:
printk(KERN_WARNING "%s(): CS asked to power off.\n", __FUNCTION__);
printk(KERN_WARNING "%s(): CS asked to power off.\n",
__FUNCTION__);
break;
case 50:
......@@ -143,23 +106,26 @@ static int flexanet_pcmcia_configure_socket(int sock, const struct pcmcia_config
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
state->Vcc);
return -1;
}
/* Reset the slot(s) using the controls in the BCR */
mask = 0;
switch (sock)
{
case 0 : mask = FHH_BCR_CF1_RST; break;
case 1 : mask = FHH_BCR_CF2_RST; break;
switch (skt->nr) {
case 0:
mask = FHH_BCR_CF1_RST;
break;
case 1:
mask = FHH_BCR_CF2_RST;
break;
}
local_irq_save(flags);
value = flexanet_BCR;
value = (configure->reset) ? (value | mask) : (value & ~mask);
value = (state->flags & SS_RESET) ? (value | mask) : (value & ~mask);
FHH_BCR = flexanet_BCR = value;
local_irq_restore(flags);
......@@ -167,30 +133,14 @@ static int flexanet_pcmcia_configure_socket(int sock, const struct pcmcia_config
return 0;
}
static int flexanet_pcmcia_socket_init(int sock)
static void flexanet_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{
if (sock == 0) {
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;
sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int flexanet_pcmcia_socket_suspend(int sock)
static void flexanet_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{
if (sock == 0) {
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;
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
/*
......@@ -199,11 +149,10 @@ static int flexanet_pcmcia_socket_suspend(int sock)
*/
static struct pcmcia_low_level flexanet_pcmcia_ops = {
.owner = THIS_MODULE,
.init = flexanet_pcmcia_init,
.shutdown = flexanet_pcmcia_shutdown,
.hw_init = flexanet_pcmcia_hw_init,
.hw_shutdown = flexanet_pcmcia_hw_shutdown,
.socket_state = flexanet_pcmcia_socket_state,
.configure_socket = flexanet_pcmcia_configure_socket,
.socket_init = flexanet_pcmcia_socket_init,
.socket_suspend = flexanet_pcmcia_socket_suspend,
};
......@@ -213,13 +162,7 @@ int __init pcmcia_flexanet_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_flexanet_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&flexanet_pcmcia_ops, dev);
}
......@@ -15,17 +15,13 @@
#include <asm/irq.h>
#include "sa1100_generic.h"
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ IRQ_GPIO_FREEBIRD_CF_CD, "CF_CD" },
{ IRQ_GPIO_FREEBIRD_CF_BVD, "CF_BVD1" },
static struct pcmcia_irqs irqs[] = {
{ 0, IRQ_GPIO_FREEBIRD_CF_CD, "CF_CD" },
{ 0, IRQ_GPIO_FREEBIRD_CF_BVD, "CF_BVD1" },
};
static int freebird_pcmcia_init(struct pcmcia_init *init){
int i, res;
static int freebird_pcmcia_init(struct sa1100_pcmcia_socket *skt)
{
/* Enable Linkup CF card */
LINKUP_PRC = 0xc0;
mdelay(100);
......@@ -37,51 +33,26 @@ static int freebird_pcmcia_init(struct pcmcia_init *init){
mdelay(100);
LINKUP_PRC = 0xc0;
/* 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] = 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);
skt->irq = IRQ_GPIO_FREEBIRD_CF_IRQ;
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int freebird_pcmcia_shutdown(void)
static void freebird_pcmcia_shutdown(struct sa1100_pcmcia_socket *skt)
{
int i;
/* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs);
/* Disable CF card */
LINKUP_PRC = 0x40; /* SSP=1 SOE=0 */
mdelay(100);
return 0;
}
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;
//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->ready = (levels & LINKUP_RDY)?1:0;
state->bvd1 = (levels & LINKUP_BVD1)?1:0;
......@@ -89,25 +60,20 @@ static void freebird_pcmcia_socket_state(int sock, struct pcmcia_state *state)
state->wrprot = 0; /* Not available on Assabet. */
state->vs_3v = 1; /* Can only apply 3.3V on Assabet. */
state->vs_Xv = 0;
}
}
static int freebird_pcmcia_configure_socket(int sock, const struct pcmcia_configure
*configure)
static int
freebird_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
socket_state_t *state)
{
unsigned long value, flags;
if(sock>1) return -1;
if(sock==1) return 0;
local_irq_save(flags);
value = 0xc0; /* SSP=1 SOE=1 CFE=1 */
switch(configure->vcc){
switch (state->Vcc) {
case 0:
break;
case 50:
......@@ -119,46 +85,38 @@ static int freebird_pcmcia_configure_socket(int sock, const struct pcmcia_config
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
__FUNCTION__, state->Vcc);
local_irq_restore(flags);
return -1;
}
if (configure->reset)
value = (configure->reset) ? (value | LINKUP_RESET) : (value & ~LINKUP_RESET);
if (state->flags & SS_RESET)
value |= LINKUP_RESET;
/* Silently ignore Vpp, output enable, speaker enable. */
LINKUP_PRC = value;
//printk("LINKUP_PRC=%x\n",value);
// 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) {
set_irq_type(IRQ_GPIO_FREEBIRD_CF_CD, IRQT_BOTHEDGE);
set_irq_type(IRQ_GPIO_FREEBIRD_CF_BVD, IRQT_BOTHEDGE);
}
return 0;
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int freebird_pcmcia_socket_suspend(int sock)
static void freebird_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{
if (sock == 1) {
set_irq_type(IRQ_GPIO_FREEBIRD_CF_CD, IRQT_NOEDGE);
set_irq_type(IRQ_GPIO_FREEBIRD_CF_BVD, IRQT_NOEDGE);
}
return 0;
sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static struct pcmcia_low_level freebird_pcmcia_ops = {
.owner = THIS_MODULE,
.init = freebird_pcmcia_init,
.shutdown = freebird_pcmcia_shutdown,
.hw_init = freebird_pcmcia_hw_init,
.hw_shutdown = freebird_pcmcia_hw_shutdown,
.socket_state = freebird_pcmcia_socket_state,
.configure_socket = freebird_pcmcia_configure_socket,
......@@ -171,12 +129,7 @@ int __init pcmcia_freebird_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_freebird_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&freebird_pcmcia_ops, dev);
}
This diff is collapsed.
/*
* 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
* 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)
struct pcmcia_init {
int socket_irq[SA1100_PCMCIA_MAX_SOCK];
};
struct pcmcia_state {
unsigned detect: 1,
ready: 1,
bvd1: 1,
bvd2: 1,
wrprot: 1,
vs_3v: 1,
vs_Xv: 1;
};
struct pcmcia_configure {
unsigned vcc: 8,
vpp: 8,
output: 1,
speaker: 1,
reset: 1,
irq: 1;
};
struct pcmcia_low_level {
struct module *owner;
#include "sa11xx_core.h"
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
/*
* Declaration for all machine specific init/exit functions.
*/
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
extern int pcmcia_adsbitsy_init(struct device *);
extern int pcmcia_assabet_init(struct device *);
extern int pcmcia_badge4_init(struct device *);
extern int pcmcia_cerf_init(struct device *);
extern int pcmcia_flexanet_init(struct device *);
extern int pcmcia_freebird_init(struct device *);
extern int pcmcia_gcplus_init(struct device *);
extern int pcmcia_graphicsmaster_init(struct device *);
extern int pcmcia_h3600_init(struct device *);
extern int pcmcia_pangolin_init(struct device *);
extern int pcmcia_pfs168_init(struct device *);
extern int pcmcia_shannon_init(struct device *);
extern int pcmcia_simpad_init(struct device *);
extern int pcmcia_stork_init(struct device *);
extern int pcmcia_system3_init(struct device *);
extern int pcmcia_trizeps_init(struct device *);
extern int pcmcia_xp860_init(struct device *);
extern int pcmcia_yopy_init(struct device *);
......@@ -34,10 +34,12 @@ static volatile unsigned long *PCMCIA_Status =
static volatile unsigned long *PCMCIA_Power =
((volatile unsigned long *) ADS_p2v(_ADS_CS_PR));
static int gcplus_pcmcia_init(struct pcmcia_init *init)
{
int irq, res;
static struct pcmcia_irqs irqs[] = {
{ 0, S0_CD_IRQ, "PCMCIA 0 CD" },
};
static int gcplus_pcmcia_init(struct sa1100_pcmcia_socket *skt)
{
// Reset PCMCIA
// Reset Timing for CPLD(U2) version 8001E or later
*PCMCIA_Power &= ~ ADS_CS_PR_A_RESET;
......@@ -49,37 +51,27 @@ static int gcplus_pcmcia_init(struct pcmcia_init *init)
// Turn off 5V
*PCMCIA_Power &= ~0x03;
/* Register interrupts */
irq = S0_CD_IRQ;
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;
}
skt->irq = S0_STS_IRQ;
init->socket_irq[0] = 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 */
free_irq( S0_CD_IRQ, NULL);
free_irq(S0_CD_IRQ, skt);
/* Shutdown PCMCIA power */
mdelay(2); // 2msec
*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;
if (sock == 0) {
state->detect=(levels & ADS_CS_ST_A_CD)?1:0;
state->ready=(levels & ADS_CS_ST_A_READY)?1:0;
state->bvd1= 0;
......@@ -87,19 +79,17 @@ static void gcplus_pcmcia_socket_state(int sock, struct pcmcia_state *state_arra
state->wrprot=0;
state->vs_3v=0;
state->vs_Xv=0;
}
}
static int gcplus_pcmcia_configure_socket(int sock, const struct pcmcia_configure
*configure)
static int
gcplus_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{
unsigned long flags;
if(sock>1) return -1;
local_irq_save(flags);
switch (configure->vcc) {
switch (state->Vcc) {
case 0:
*PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER);
break;
......@@ -115,8 +105,8 @@ static int gcplus_pcmcia_configure_socket(int sock, const struct pcmcia_configur
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
__FUNCTION__, state->Vcc);
local_irq_restore(flags);
return -1;
}
......@@ -135,23 +125,20 @@ static int gcplus_pcmcia_configure_socket(int sock, const struct pcmcia_configur
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 = {
.owner = THIS_MODULE,
.init = gcplus_pcmcia_init,
.shutdown = gcplus_pcmcia_shutdown,
.hw_init = gcplus_pcmcia_hw_init,
.hw_shutdown = gcplus_pcmcia_hw_shutdown,
.socket_state = gcplus_pcmcia_socket_state,
.configure_socket = gcplus_pcmcia_configure_socket,
.socket_init = gcplus_pcmcia_socket_init,
.socket_suspend = gcplus_pcmcia_socket_suspend,
};
......@@ -161,13 +148,7 @@ int __init pcmcia_gcplus_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_gcplus_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&gcplus_pcmcia_ops, dev);
}
......@@ -17,10 +17,9 @@
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include "sa1100_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;
......@@ -33,20 +32,21 @@ static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
/* why? */
MECR = 0x09430943;
return sa1111_pcmcia_init(init);
return sa1111_pcmcia_hwinit(skt);
}
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;
int ret;
switch (sock) {
switch (skt->nr) {
case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
switch (conf->vcc) {
switch (state->Vcc) {
default:
case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
case 33: pa_dwr_set = GPIO_GPIO1; break;
......@@ -57,21 +57,22 @@ graphicsmaster_pcmcia_configure_socket(int sock, const struct pcmcia_configure *
case 1:
pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
switch (conf->vcc) {
switch (state->Vcc) {
default:
case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
case 33: pa_dwr_set = GPIO_GPIO3; 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__,
conf->vpp);
if (state->Vpp != state->Vcc && state->Vpp != 0) {
printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
__FUNCTION__, state->Vpp);
return -1;
}
ret = sa1111_pcmcia_configure_socket(sock, conf);
ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) {
unsigned long flags;
......@@ -85,8 +86,8 @@ graphicsmaster_pcmcia_configure_socket(int sock, const struct pcmcia_configure *
static struct pcmcia_low_level graphicsmaster_pcmcia_ops = {
.owner = THIS_MODULE,
.init = graphicsmaster_pcmcia_init,
.shutdown = sa1111_pcmcia_shutdown,
.hw_init = graphicsmaster_pcmcia_init,
.hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state,
.configure_socket = graphicsmaster_pcmcia_configure_socket,
......@@ -99,13 +100,7 @@ int __init pcmcia_graphicsmaster_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_graphicsmaster_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&graphicsmaster_pcmcia_ops, dev);
}
......@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <asm/hardware.h>
......@@ -17,65 +18,36 @@
#include "sa1100_generic.h"
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ IRQ_GPIO_H3600_PCMCIA_CD0, "PCMCIA CD0" },
{ IRQ_GPIO_H3600_PCMCIA_CD1, "PCMCIA CD1" }
static struct pcmcia_irqs irqs[] = {
{ 0, IRQ_GPIO_H3600_PCMCIA_CD0, "PCMCIA CD0" },
{ 1, 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--)
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;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int h3600_pcmcia_shutdown(void)
static void h3600_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{
int i;
/*
* disable IRQs
*/
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* Disable CF bus: */
clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
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;
switch (sock) {
switch (skt->nr) {
case 0:
state->detect = levels & GPIO_H3600_PCMCIA_CD0 ? 0 : 1;
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)
}
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)
return -1;
if (conf->vcc != 0 && conf->vcc != 33 && conf->vcc != 50) {
if (state->Vcc != 0 && state->Vcc != 33 && state->Vcc != 50) {
printk(KERN_ERR "h3600_pcmcia: unrecognized Vcc %u.%uV\n",
conf->vcc / 10, conf->vcc % 10);
state->Vcc / 10, state->Vcc % 10);
return -1;
}
if (conf->reset)
if (state->flags & SS_RESET)
set_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
else
clr_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
......@@ -120,7 +89,7 @@ h3600_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
return 0;
}
static int h3600_pcmcia_socket_init(int sock)
static void h3600_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{
/* Enable CF bus: */
set_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
......@@ -130,28 +99,12 @@ static int h3600_pcmcia_socket_init(int sock)
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(10*HZ / 1000);
switch (sock) {
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;
sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int h3600_pcmcia_socket_suspend(int sock)
static void h3600_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{
switch (sock) {
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;
}
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
/*
* 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)
* on one bus. We rely on the cs.c behaviour shutting down
* 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_NVRAM_ON);
/* hmm, does this suck power? */
set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
}
return 0;
}
struct pcmcia_low_level h3600_pcmcia_ops = {
.owner = THIS_MODULE,
.init = h3600_pcmcia_init,
.shutdown = h3600_pcmcia_shutdown,
.hw_init = h3600_pcmcia_hw_init,
.hw_shutdown = h3600_pcmcia_hw_shutdown,
.socket_state = h3600_pcmcia_socket_state,
.configure_socket = h3600_pcmcia_configure_socket,
......@@ -185,12 +136,7 @@ int __init pcmcia_h3600_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_h3600_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&h3600_pcmcia_ops, dev);
}
......@@ -15,7 +15,6 @@
#include <asm/hardware/sa1111.h>
#include <asm/mach-types.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
#define SOCKET0_POWER GPIO_GPIO0
......@@ -24,7 +23,7 @@
#warning *** Does SOCKET1_3V actually do anything?
#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?
......@@ -46,23 +45,23 @@ static int jornada720_pcmcia_init(struct pcmcia_init *init)
PC_SDR = 0;
PC_SSR = 0;
return sa1111_pcmcia_init(init);
return sa1111_pcmcia_hw_init(skt);
}
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;
int ret;
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:
pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V;
switch (conf->vcc) {
switch (state->Vcc) {
default:
case 0: pa_dwr_set = 0; 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__,
case 1:
pa_dwr_mask = SOCKET1_POWER;
switch (conf->vcc) {
switch (state->Vcc) {
default:
case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = SOCKET1_POWER; break;
......@@ -85,13 +84,13 @@ printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__,
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",
__FUNCTION__, conf->vpp);
__FUNCTION__, state->Vpp);
return -1;
}
ret = sa1111_pcmcia_configure_socket(sock, conf);
ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) {
unsigned long flags;
......@@ -105,8 +104,8 @@ printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__,
static struct pcmcia_low_level jornada720_pcmcia_ops = {
.owner = THIS_MODULE,
.init = jornada720_pcmcia_init,
.shutdown = sa1111_pcmcia_shutdown,
.hw_init = jornada720_pcmcia_hw_init,
.hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state,
.configure_socket = jornada720_pcmcia_configure_socket,
......@@ -119,12 +118,7 @@ int __init pcmcia_jornada720_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __devexit pcmcia_jornada720_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&jornada720_pcmcia_ops, dev);
}
......@@ -15,7 +15,6 @@
#include <asm/arch/neponset.h>
#include <asm/hardware/sa1111.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
/*
......@@ -42,53 +41,28 @@
* 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
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_set, pa_dwr_set;
unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set;
int ret;
switch (sock) {
switch (skt->nr) {
case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
ncr_mask = NCR_A0VPP | NCR_A1VPP;
switch (conf->vcc) {
default:
case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO1; break;
case 50: pa_dwr_set = GPIO_GPIO0; break;
}
switch (conf->vpp) {
case 0: ncr_set = 0; break;
case 120: ncr_set = NCR_A1VPP; break;
default:
if (conf->vpp == conf->vcc)
if (state->Vpp == 0)
ncr_set = 0;
else if (state->Vpp == 120)
ncr_set = NCR_A1VPP;
else if (state->Vpp == state->Vcc)
ncr_set = NCR_A0VPP;
else {
printk(KERN_ERR "%s(): unrecognized VPP %u\n",
__FUNCTION__, conf->vpp);
__FUNCTION__, state->Vpp);
return -1;
}
}
break;
case 1:
......@@ -96,16 +70,9 @@ neponset_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
ncr_mask = 0;
ncr_set = 0;
switch (conf->vcc) {
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) {
if (state->Vpp != state->Vcc && state->Vpp != 0) {
printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
__FUNCTION__, conf->vpp);
__FUNCTION__, state->Vpp);
return -1;
}
break;
......@@ -114,27 +81,46 @@ neponset_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
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) {
unsigned long flags;
local_irq_save(flags);
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);
}
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 = {
.owner = THIS_MODULE,
.init = neponset_pcmcia_init,
.shutdown = sa1111_pcmcia_shutdown,
.hw_init = sa1111_pcmcia_hw_init,
.hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state,
.configure_socket = neponset_pcmcia_configure_socket,
.socket_init = sa1111_pcmcia_socket_init,
.socket_init = neponset_pcmcia_socket_init,
.socket_suspend = sa1111_pcmcia_socket_suspend,
};
......@@ -142,13 +128,17 @@ int __init pcmcia_neponset_init(struct device *dev)
{
int ret = -ENODEV;
if (machine_is_assabet())
ret = sa1100_register_pcmcia(&neponset_pcmcia_ops, dev);
if (machine_is_assabet()) {
/*
* 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;
}
void __devexit pcmcia_neponset_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&neponset_pcmcia_ops, dev);
}
......@@ -22,7 +22,12 @@
#define PANGOLIN_SOCK 0
#endif
static int pangolin_pcmcia_init(struct pcmcia_init *init){
static struct pcmcia_irqs irqs[] = {
{ 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
......@@ -30,42 +35,27 @@ static int pangolin_pcmcia_init(struct pcmcia_init *init){
GPCR = GPIO_PCMCIA_BUS_ON;
#endif
init->socket_irq[PANGOLIN_SOCK] = IRQ_PCMCIA_IRQ;
/* Set transition detect */
set_irq_type(IRQ_PCMCIA_CD, IRQT_NOEDGE);
set_irq_type(IRQ_PCMCIA_IRQ, IRQT_FALLING);
/* Register interrupts */
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;
skt->irq = IRQ_PCMCIA_IRQ;
irq_err:
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, IRQ_PCMCIA_CD, res);
return res;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int pangolin_pcmcia_shutdown(void)
static void pangolin_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{
/* disable IRQs */
free_irq(IRQ_PCMCIA_CD, NULL);
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
/* Disable PCMCIA bus: */
GPSR = GPIO_PCMCIA_BUS_ON;
#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;;
if (sock == PANGOLIN_SOCK) {
state->detect=((levels & GPIO_PCMCIA_CD)==0)?1:0;
state->ready=(levels & GPIO_PCMCIA_IRQ)?1:0;
state->bvd1=1; /* Not available on Pangolin. */
......@@ -73,23 +63,19 @@ static void pangolin_pcmcia_socket_state(int sock, struct pcmcia_state *state)
state->wrprot=0; /* Not available on Pangolin. */
state->vs_3v=1; /* Can only apply 3.3V on Pangolin. */
state->vs_Xv=0;
}
}
static int pangolin_pcmcia_configure_socket(int sock, const struct pcmcia_configure
*configure)
static int
pangolin_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{
unsigned long value, flags;
if(sock>1) return -1;
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
if(sock==0) return 0;
#endif
local_irq_save(flags);
/* Murphy: BUS_ON different from POWER ? */
switch(configure->vcc){
switch (state->Vcc) {
case 0:
break;
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
......@@ -100,25 +86,27 @@ static int pangolin_pcmcia_configure_socket(int sock, const struct pcmcia_config
break;
#else
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 "
"jumper setting...\n", __FUNCTION__);
break;
case 33:
printk(KERN_WARNING "%s(): CS asked for 3.3V, determined by jumper setting...\n", __FUNCTION__);
printk(KERN_WARNING "%s(): CS asked for 3.3V, determined by "
"jumper setting...\n", __FUNCTION__);
break;
#endif
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
__FUNCTION__, state->Vcc);
local_irq_restore(flags);
return -1;
}
#ifdef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
/* reset & unreset request */
if(sock==0) {
if(configure->reset) {
GPSR |= GPIO_PCMCIA_RESET;
if (skt->nr == 0) {
if (state->flags & SS_RESET) {
GPSR = GPIO_PCMCIA_RESET;
} else {
GPCR |= GPIO_PCMCIA_RESET;
GPCR = GPIO_PCMCIA_RESET;
}
}
#endif
......@@ -127,24 +115,20 @@ static int pangolin_pcmcia_configure_socket(int sock, const struct pcmcia_config
return 0;
}
static int pangolin_pcmcia_socket_init(int sock)
static void pangolin_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{
if (sock == 1)
set_irq_type(IRQ_PCMCIA_CD, IRQT_BOTHEDGE);
return 0;
sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int pangolin_pcmcia_socket_suspend(int sock)
static void pangolin_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{
if (sock == 1)
set_irq_type(IRQ_PCMCIA_CD, IRQT_NOEDGE);
return 0;
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static struct pcmcia_low_level pangolin_pcmcia_ops = {
.owner = THIS_MODULE,
.init = pangolin_pcmcia_init,
.shutdown = pangolin_pcmcia_shutdown,
.hw_init = pangolin_pcmcia_hw_init,
.hw_shutdown = pangolin_pcmcia_hw_shutdown,
.socket_state = pangolin_pcmcia_socket_state,
.configure_socket = pangolin_pcmcia_configure_socket,
......@@ -157,13 +141,7 @@ int __init pcmcia_pangolin_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_pangolin_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&pangolin_pcmcia_ops, dev);
}
......@@ -16,10 +16,9 @@
#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_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: */
PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
......@@ -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: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
return sa1111_pcmcia_init(init);
return sa1111_pcmcia_init(skt);
}
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;
int ret;
......@@ -48,33 +48,33 @@ pfs168_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
*
*/
switch (sock) {
switch (skt->nr) {
case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
switch (conf->vcc) {
switch (state->Vcc) {
default:
case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO0; break;
case 50: pa_dwr_set = GPIO_GPIO1; break;
}
switch (conf->vpp) {
switch (state->Vpp) {
case 0:
break;
case 120:
printk(KERN_ERR "%s(): PFS-168 does not support VPP %uV\n",
__FUNCTION__, conf->vpp / 10);
__FUNCTION__, state->Vpp / 10);
return -1;
break;
default:
if (conf->vpp == conf->vcc)
if (state->Vpp == state->Vcc)
pa_dwr_set |= GPIO_GPIO3;
else {
printk(KERN_ERR "%s(): unrecognized VPP %u\n", __FUNCTION__,
conf->vpp);
state->Vpp);
return -1;
}
}
......@@ -91,24 +91,24 @@ pfs168_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
case 50:
printk(KERN_ERR "%s(): PFS-168 CompactFlash socket does not support VCC %uV\n",
__FUNCTION__, conf->vcc / 10);
__FUNCTION__, state->Vcc / 10);
return -1;
default:
printk(KERN_ERR "%s(): unrecognized VCC %u\n", __FUNCTION__,
conf->vcc);
state->Vcc);
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"
__FUNCTION__, conf->vpp / 10);
__FUNCTION__, state->Vpp / 10);
return -1;
}
break;
}
ret = sa1111_pcmcia_configure_socket(sock, conf);
ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) {
unsigned long flags;
......@@ -122,11 +122,10 @@ pfs168_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
static struct pcmcia_low_level pfs168_pcmcia_ops = {
.owner = THIS_MODULE,
.init = pfs168_pcmcia_init,
.shutdown = sa1111_pcmcia_shutdown,
.hw_init = pfs168_pcmcia_hw_init,
.hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state,
.configure_socket = pfs168_pcmcia_configure_socket,
.socket_init = sa1111_pcmcia_socket_init,
.socket_suspend = sa1111_pcmcia_socket_suspend,
};
......@@ -136,12 +135,7 @@ int __init pcmcia_pfs168_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_pfs168_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&pfs168_pcmcia_ops, dev);
}
......@@ -16,64 +16,36 @@
#include <asm/irq.h>
#include "sa1100_generic.h"
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ SHANNON_IRQ_GPIO_EJECT_0, "PCMCIA_CD_0" },
{ SHANNON_IRQ_GPIO_EJECT_1, "PCMCIA_CD_1" },
static struct pcmcia_irqs irqs[] = {
{ 0, SHANNON_IRQ_GPIO_EJECT_0, "PCMCIA_CD_0" },
{ 1, SHANNON_IRQ_GPIO_EJECT_1, "PCMCIA_CD_1" },
};
static int shannon_pcmcia_init(struct pcmcia_init *init)
static int shannon_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{
int i, res;
/* All those are inputs */
GPDR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 |
SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1);
GAFR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 |
SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1);
init->socket_irq[0] = 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;
skt->irq = skt->nr ? SHANNON_IRQ_GPIO_RDY_1 : SHANNON_IRQ_GPIO_RDY_0;
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;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int shannon_pcmcia_shutdown(void)
static void shannon_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{
int i;
/* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
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;
switch (sock) {
switch (skt->nr) {
case 0:
state->detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1;
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)
}
}
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 */
printk(KERN_WARNING __FUNCTION__"(): CS asked for 0V, still applying 3.3V..\n");
break;
......@@ -108,7 +82,7 @@ static int shannon_pcmcia_configure_socket(int sock, const struct pcmcia_configu
break;
default:
printk(KERN_ERR __FUNCTION__"(): unrecognized Vcc %u\n",
configure->vcc);
state->Vcc);
return -1;
}
......@@ -119,30 +93,20 @@ static int shannon_pcmcia_configure_socket(int sock, const struct pcmcia_configu
return 0;
}
static int shannon_pcmcia_socket_init(int sock)
static void shannon_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{
if (sock == 0)
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;
sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int shannon_pcmcia_socket_suspend(int sock)
static void shannon_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{
if (sock == 0)
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;
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static struct pcmcia_low_level shannon_pcmcia_ops = {
.owner = THIS_MODULE,
.init = shannon_pcmcia_init,
.shutdown = shannon_pcmcia_shutdown,
.hw_init = shannon_pcmcia_hw_init,
.hw_shutdown = shannon_pcmcia_hw_shutdown,
.socket_state = shannon_pcmcia_socket_state,
.configure_socket = shannon_pcmcia_configure_socket,
......@@ -155,12 +119,7 @@ int __init pcmcia_shannon_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_shannon_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&shannon_pcmcia_ops, dev);
}
......@@ -19,51 +19,36 @@ extern long get_cs3_shadow(void);
extern void set_cs3_bit(int value);
extern void clear_cs3_bit(int value);
static struct pcmcia_irqs irqs[] = {
{ 1, IRQ_GPIO_CF_CD, "CF_CD" },
};
static int simpad_pcmcia_init(struct pcmcia_init *init){
int irq, res;
static int simpad_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{
set_cs3_bit(PCMCIA_RESET);
clear_cs3_bit(PCMCIA_BUFF_DIS);
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 );
skt->irq = 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__, irq, res);
return res;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int simpad_pcmcia_shutdown(void)
static void simpad_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{
/* disable IRQs */
free_irq( IRQ_GPIO_CF_CD, NULL );
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* Disable CF bus: */
//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 *cs3reg = CS3_BASE;
......@@ -80,23 +65,18 @@ static void simpad_pcmcia_socket_state(int sock, struct pcmcia_state *state)
state->vs_3v=1;
state->vs_Xv=0;
}
}
}
static int simpad_pcmcia_configure_socket(int sock, const struct pcmcia_configure
*configure)
static int
simpad_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
const socket_state_t *state)
{
unsigned long value, flags;
if(sock>1) return -1;
if(sock==0) return 0;
local_irq_save(flags);
/* Murphy: see table of MIC2562a-1 */
switch(configure->vcc){
switch (state->Vcc) {
case 0:
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
break;
......@@ -112,39 +92,35 @@ static int simpad_pcmcia_configure_socket(int sock, const struct pcmcia_configur
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
__FUNCTION__, state->Vcc);
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
local_irq_restore(flags);
return -1;
}
/* 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);
return 0;
sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
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);
return 0;
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static struct pcmcia_low_level simpad_pcmcia_ops = {
.owner = THIS_MODULE,
.init = simpad_pcmcia_init,
.shutdown = simpad_pcmcia_shutdown,
.hw_init = simpad_pcmcia_hw_init,
.hw_shutdown = simpad_pcmcia_hw_shutdown,
.socket_state = simpad_pcmcia_socket_state,
.configure_socket = simpad_pcmcia_configure_socket,
.socket_init = simpad_pcmcia_socket_init,
.socket_suspend = simpad_pcmcia_socket_suspend,
};
......@@ -154,12 +130,7 @@ int __init pcmcia_simpad_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_simpad_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&simpad_pcmcia_ops, dev);
}
......@@ -32,62 +32,39 @@
static int debug = 0;
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, "PCMCIA_CD0" },
{ IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, "PCMCIA_CD1" },
static struct pcmcia_irqs irqs[] = {
{ 0, IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, "PCMCIA_CD0" },
{ 1, 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");
init->socket_irq[0] = IRQ_GPIO_STORK_PCMCIA_A_RDY;
init->socket_irq[1] = IRQ_GPIO_STORK_PCMCIA_B_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;
skt->irq = skt->nr ? IRQ_GPIO_STORK_PCMCIA_B_RDY
: IRQ_GPIO_STORK_PCMCIA_A_RDY;
irq_err:
printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
__FUNCTION__, irq, res);
while (i--)
free_irq(irqs[i].irq, NULL);
return res;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int stork_pcmcia_shutdown(void)
static void stork_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{
int i;
printk(__FUNCTION__ "\n");
/* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* Disable CF bus: */
storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
storkClearLatchA(STORK_PCMCIA_A_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;
......@@ -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,
(levels & (GPIO_STORK_PCMCIA_A_RDY|GPIO_STORK_PCMCIA_B_RDY)));
switch (sock) {
switch (skt->nr) {
case 0:
state->detect=((levels & GPIO_STORK_PCMCIA_A_CARD_DETECT)==0)?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)
}
}
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;
int DETECT, RDY, POWER, RESET;
if (sock > 1) return -1;
printk(__FUNCTION__ ": socket=%d vcc=%d vpp=%d reset=%d\n",
sock, configure->vcc, configure->vpp, configure->reset);
printk("%s: socket=%d vcc=%d vpp=%d reset=%d\n", __FUNCTION__,
skt->nr, state->Vcc, state->Vpp, state->flags & SS_RESET ? 1 : 0);
local_irq_save(flags);
if (sock == 0) {
if (skt->nr == 0) {
DETECT = GPIO_STORK_PCMCIA_A_CARD_DETECT;
RDY = GPIO_STORK_PCMCIA_A_RDY;
POWER = STORK_PCMCIA_A_POWER_ON;
......@@ -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");
}
*/
switch (configure->vcc) {
switch (state->Vcc) {
case 0:
/* storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON); */
storkClearLatchA(POWER);
......@@ -162,12 +138,12 @@ static int stork_pcmcia_configure_socket(int sock, const struct pcmcia_configure
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
state->Vcc);
local_irq_restore(flags);
return -1;
}
if (configure->reset)
if (state->flags & SS_RESET)
storkSetLatchB(RESET);
else
storkClearLatchB(RESET);
......@@ -176,43 +152,35 @@ static int stork_pcmcia_configure_socket(int sock, const struct pcmcia_configure
/* silently ignore vpp and speaker enables. */
printk(__FUNCTION__ ": finished\n");
printk("%s: finished\n", __FUNCTION__);
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);
if (sock == 0)
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;
sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int stork_pcmcia_socket_suspend(int sock)
static void stork_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{
if (sock == 0)
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);
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
/*
* Hack!
*/
if (skt->nr == 1)
storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
}
return 0;
}
static struct pcmcia_low_level stork_pcmcia_ops = {
.owner = THIS_MODULE,
.init = stork_pcmcia_init,
.shutdown = stork_pcmcia_shutdown,
.hw_init = stork_pcmcia_hw_init,
.hw_shutdown = stork_pcmcia_hw_shutdown,
.socket_state = stork_pcmcia_socket_state,
.configure_socket = stork_pcmcia_configure_socket,
......@@ -225,13 +193,7 @@ int __init pcmcia_stork_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_stork_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&stork_pcmcia_ops, dev);
}
......@@ -37,7 +37,6 @@
#include <asm/irq.h>
#include <asm/hardware/sa1111.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
#define DEBUG 0
......@@ -48,34 +47,24 @@
# define DPRINTK( x, args... ) /* nix */
#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;
init->socket_irq[1] = IRQ_S1_READY_NINT;
skt->irq = skt->nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT;
/* Don't need no CD and BVD* interrupts */
return 2;
}
int system3_pcmcia_shutdown(void)
{
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;
switch (sock) {
switch (skt->nr) {
#if 0 /* PCMCIA socket not yet connected */
case 0:
state->detect = status & PCSR_S0_DETECT ? 0 : 1;
......@@ -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",
sock, status, state->ready);
skt->nr, status, state->ready);
}
struct pcmcia_low_level system3_pcmcia_ops = {
.owner = THIS_MODULE,
.init = system3_pcmcia_init,
.shutdown = system3_pcmcia_shutdown,
.init = system3_pcmcia_hw_init,
.shutdown = system3_pcmcia_hw_shutdown,
.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_suspend = sa1111_pcmcia_socket_suspend,
......@@ -119,12 +108,8 @@ int __init pcmcia_system3_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_system3_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&system3_pcmcia_ops, dev);
}
......@@ -23,15 +23,18 @@
#include "sa1100_generic.h"
#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;
init->socket_irq[0] = TRIZEPS_IRQ_PCMCIA_IRQ0;
skt->irq = TRIZEPS_IRQ_PCMCIA_IRQ0;
/* Enable CF bus: */
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_nPCM_ENA_REG);
......@@ -40,51 +43,32 @@ static int trizeps_pcmcia_init(struct pcmcia_init *init)
GPDR &= ~((GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_CD0))
| (GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_IRQ0)));
/* Register SOCKET interrupts */
/* 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;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
/**
*
*
******************************************************/
static int trizeps_pcmcia_shutdown(void)
static void trizeps_pcmcia_shutdown(struct sa1100_pcmcia_socket *skt)
{
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: */
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;
if (sock == 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->bvd1 = ((TRIZEPS_BCR1 & TRIZEPS_PCM_BVD1) !=0 ) ? 1 : 0;
......@@ -92,22 +76,21 @@ static void trizeps_pcmcia_socket_state(int sock, struct pcmcia_state *state_arr
state->wrprot = 0; // not write protected
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
}
}
/**
*
*
******************************************************/
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;
if(sock>1) return -1;
local_irq_save(flags);
switch (configure->vcc) {
switch (state->Vcc) {
case 0:
printk(">>> PCMCIA Power off\n");
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
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
state->Vcc);
local_irq_restore(flags);
return -1;
}
if (configure->reset)
if (state->flags & SS_RESET)
TRIZEPS_BCR_set(TRIZEPS_BCR1, TRIZEPS_nPCM_RESET_DISABLE); // Reset
else
TRIZEPS_BCR_clear(TRIZEPS_BCR1, TRIZEPS_nPCM_RESET_DISABLE); // no Reset
/*
printk(" vcc=%u vpp=%u -->reset=%i\n",
configure->vcc,
configure->vpp,
state->Vcc,
state->Vpp,
((BCR_read(1) & nPCM_RESET_DISABLE)? 1:0));
*/
local_irq_restore(flags);
......@@ -146,16 +129,14 @@ static int trizeps_pcmcia_configure_socket(int sock, const struct pcmcia_configu
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);
return 0;
sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
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);
return 0;
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
/**
......@@ -164,8 +145,8 @@ static int trizeps_pcmcia_socket_suspend(int sock)
******************************************************/
struct pcmcia_low_level trizeps_pcmcia_ops = {
.owner = THIS_MODULE,
.init = trizeps_pcmcia_init,
.shutdown = trizeps_pcmcia_shutdown,
.hw_init = trizeps_pcmcia_hw_init,
.hw_shutdown = trizeps_pcmcia_hw_shutdown,
.socket_state = trizeps_pcmcia_socket_state,
.configure_socket = trizeps_pcmcia_configure_socket,
.socket_init = trizeps_pcmcia_socket_init,
......@@ -174,13 +155,11 @@ struct pcmcia_low_level trizeps_pcmcia_ops = {
int __init pcmcia_trizeps_init(struct device *dev)
{
if (machine_is_trizeps()) {
return sa1100_register_pcmcia(&trizeps_pcmcia_ops, dev);
}
return -ENODEV;
}
int ret = -ENODEV;
void __exit pcmcia_trizeps_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&trizeps_pcmcia_ops, dev);
if (machine_is_trizeps())
ret = sa11xx_drv_pcmcia_probe(dev, &trizeps_pcmcia_ops, 0,
NUMBER_OF_TRIZEPS_PCMCIA_SLOTS);
return ret;
}
......@@ -19,7 +19,7 @@
#define NCR_A0VPP (1<<16)
#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: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
......@@ -38,11 +38,11 @@ static int xp860_pcmcia_init(struct pcmcia_init *init)
GPDR |= (NCR_A0VPP | NCR_A1VPP);
GPCR &= ~(NCR_A0VPP | NCR_A1VPP);
return sa1111_pcmcia_init(init);
return sa1111_pcmcia_hw_init(skt);
}
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_set, pa_dwr_set;
......@@ -72,28 +72,28 @@ xp860_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
* the corresponding truth table.
*/
switch (sock) {
switch (skt->nr) {
case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
gpio_mask = NCR_A0VPP | NCR_A1VPP;
switch (conf->vcc) {
switch (state->Vcc) {
default:
case 0: pa_dwr_set = 0; break;
case 33: pa_dwr_set = GPIO_GPIO1; break;
case 50: pa_dwr_set = GPIO_GPIO0; break;
}
switch (conf->vpp) {
switch (state->Vpp) {
case 0: gpio_set = 0; break;
case 120: gpio_set = NCR_A1VPP; break;
default:
if (conf->vpp == conf->vcc)
if (state->Vpp == state->Vcc)
gpio_set = NCR_A0VPP;
else {
printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
__FUNCTION__, conf->vpp);
__FUNCTION__, state->Vpp);
return -1;
}
}
......@@ -104,22 +104,22 @@ xp860_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
gpio_mask = 0;
gpio_set = 0;
switch (conf->vcc) {
switch (state->Vcc) {
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) {
if (state->Vpp != state->Vcc && state->Vpp != 0) {
printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
__FUNCTION__, conf->vpp);
__FUNCTION__, state->Vpp);
return -1;
}
break;
}
ret = sa1111_pcmcia_configure_socket(sock, conf);
ret = sa1111_pcmcia_configure_socket(skt, state);
if (ret == 0) {
unsigned long flags;
......@@ -135,11 +135,10 @@ xp860_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
static struct pcmcia_low_level xp860_pcmcia_ops = {
.owner = THIS_MODULE,
.init = xp860_pcmcia_init,
.shutdown = sa1111_pcmcia_shutdown,
.hw_init = xp860_pcmcia_hw_init,
.hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state,
.configure_socket = xp860_pcmcia_configure_socket,
.socket_init = sa1111_pcmcia_socket_init,
.socket_suspend = sa1111_pcmcia_socket_suspend,
};
......@@ -149,13 +148,7 @@ int __init pcmcia_xp860_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_xp860_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&xp860_pcmcia_ops, dev);
}
......@@ -27,65 +27,37 @@ static inline void pcmcia_reset(int reset)
yopy_gpio_set(GPIO_CF_RESET, reset);
}
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ IRQ_CF_CD, "CF_CD" },
{ IRQ_CF_BVD2, "CF_BVD2" },
{ IRQ_CF_BVD1, "CF_BVD1" },
static struct pcmcia_irqs irqs[] = {
{ 0, IRQ_CF_CD, "CF_CD" },
{ 0, IRQ_CF_BVD2, "CF_BVD2" },
{ 0, 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;
init->socket_irq[0] = IRQ_CF_IREQ;
skt->irq = IRQ_CF_IREQ;
pcmcia_power(0);
pcmcia_reset(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 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;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int yopy_pcmcia_shutdown(void)
static void yopy_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{
int i;
/* disable IRQs */
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
/* Disable CF */
pcmcia_reset(1);
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;
if (sock == 0) {
state->detect = (levels & GPIO_CF_CD) ? 0 : 1;
state->ready = (levels & GPIO_CF_READY) ? 1 : 0;
state->bvd1 = (levels & GPIO_CF_BVD1) ? 1 : 0;
......@@ -93,15 +65,13 @@ static void yopy_pcmcia_socket_state(int sock, struct pcmcia_state_array *state)
state->wrprot = 0; /* Not available on Yopy. */
state->vs_3v = 0; /* FIXME Can only apply 3.3V on Yopy. */
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)
return -1;
switch (configure->vcc) {
switch (state->Vcc) {
case 0: /* power off */
pcmcia_power(0);
break;
......@@ -112,35 +82,25 @@ static int yopy_pcmcia_configure_socket(int sock, const struct pcmcia_configure
break;
default:
printk(KERN_ERR __FUNCTION__"(): unrecognized Vcc %u\n",
configure->vcc);
state->Vcc);
return -1;
}
pcmcia_reset(configure->reset);
pcmcia_reset(state->flags & SS_RESET ? 1 : 0);
/* Silently ignore Vpp, output enable, speaker enable. */
return 0;
}
static int yopy_pcmcia_socket_init(int sock)
static void yopy_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{
int i;
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));
}
static int yopy_pcmcia_socket_suspend(int sock)
static void yopy_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{
int i;
for (i = 0; i < ARRAY_SIZE(irqs); i++)
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
return 0;
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static struct pcmcia_low_level yopy_pcmcia_ops = {
......@@ -159,13 +119,7 @@ int __init pcmcia_yopy_init(struct device *dev)
int ret = -ENODEV;
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;
}
void __exit pcmcia_yopy_exit(struct device *dev)
{
sa1100_unregister_pcmcia(&yopy_pcmcia_ops, dev);
}
/*
* linux/drivers/pcmcia/sa1100_sa1111.c
* linux/drivers/pcmcia/sa1111_generic.c
*
* We implement the generic parts of a SA1111 PCMCIA driver. This
* basically means we handle everything except controlling the
......@@ -19,63 +19,34 @@
#include <asm/hardware/sa1111.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
#include "sa1111_generic.h"
static struct irqs {
int irq;
const char *str;
} irqs[] = {
{ IRQ_S0_CD_VALID, "SA1111 PCMCIA card detect" },
{ IRQ_S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
{ IRQ_S1_CD_VALID, "SA1111 CF card detect" },
{ IRQ_S1_BVD1_STSCHG, "SA1111 CF BVD1" },
static struct pcmcia_irqs irqs[] = {
{ 0, IRQ_S0_CD_VALID, "SA1111 PCMCIA card detect" },
{ 0, IRQ_S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
{ 1, IRQ_S1_CD_VALID, "SA1111 CF card detect" },
{ 1, IRQ_S1_BVD1_STSCHG, "SA1111 CF BVD1" },
};
static struct sa1111_dev *pcmcia;
int sa1111_pcmcia_init(struct pcmcia_init *init)
int sa1111_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
{
int i, ret;
if (init->socket_irq[0] == NO_IRQ)
init->socket_irq[0] = IRQ_S0_READY_NINT;
if (init->socket_irq[1] == NO_IRQ)
init->socket_irq[1] = IRQ_S1_READY_NINT;
for (i = ret = 0; i < ARRAY_SIZE(irqs); i++) {
ret = request_irq(irqs[i].irq, sa1100_pcmcia_interrupt,
SA_INTERRUPT, irqs[i].str, NULL);
if (ret)
break;
set_irq_type(irqs[i].irq, IRQT_FALLING);
}
if (i < ARRAY_SIZE(irqs)) {
printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
irqs[i].irq, ret);
while (i--)
free_irq(irqs[i].irq, NULL);
}
if (skt->irq == NO_IRQ)
skt->irq = skt->nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT;
return ret ? -1 : 2;
return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
int sa1111_pcmcia_shutdown(void)
void sa1111_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
{
int i;
for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL);
return 0;
sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
void sa1111_pcmcia_socket_state(int sock, struct pcmcia_state *state)
void sa1111_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
{
unsigned long status = sa1111_readl(pcmcia->mapbase + SA1111_PCSR);
struct sa1111_dev *sadev = SA1111_DEV(skt->dev);
unsigned long status = sa1111_readl(sadev->mapbase + SA1111_PCSR);
switch (sock) {
switch (skt->nr) {
case 0:
state->detect = status & PCSR_S0_DETECT ? 0 : 1;
state->ready = status & PCSR_S0_READY ? 1 : 0;
......@@ -98,91 +69,61 @@ void sa1111_pcmcia_socket_state(int sock, struct pcmcia_state *state)
}
}
int sa1111_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf)
int sa1111_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
{
unsigned int rst, flt, wait, pse, irq, pccr_mask, val;
struct sa1111_dev *sadev = SA1111_DEV(skt->dev);
unsigned int pccr_skt_mask, pccr_set_mask, val;
unsigned long flags;
switch (sock) {
switch (skt->nr) {
case 0:
rst = PCCR_S0_RST;
flt = PCCR_S0_FLT;
wait = PCCR_S0_PWAITEN;
pse = PCCR_S0_PSE;
irq = IRQ_S0_READY_NINT;
pccr_skt_mask = PCCR_S0_RST|PCCR_S0_FLT|PCCR_S0_PWAITEN|PCCR_S0_PSE;
break;
case 1:
rst = PCCR_S1_RST;
flt = PCCR_S1_FLT;
wait = PCCR_S1_PWAITEN;
pse = PCCR_S1_PSE;
irq = IRQ_S1_READY_NINT;
pccr_skt_mask = PCCR_S1_RST|PCCR_S1_FLT|PCCR_S1_PWAITEN|PCCR_S1_PSE;
break;
default:
return -1;
}
switch (conf->vcc) {
case 0:
pccr_mask = 0;
break;
pccr_set_mask = 0;
case 33:
pccr_mask = wait;
break;
case 50:
pccr_mask = pse | wait;
break;
default:
printk(KERN_ERR "sa1111_pcmcia: unrecognised VCC %u\n",
conf->vcc);
return -1;
}
if (conf->reset)
pccr_mask |= rst;
if (conf->output)
pccr_mask |= flt;
if (state->Vcc != 0)
pccr_set_mask |= PCCR_S0_PWAITEN|PCCR_S1_PWAITEN;
if (state->Vcc == 50)
pccr_set_mask |= PCCR_S0_PSE|PCCR_S1_PSE;
if (state->flags & SS_RESET)
pccr_set_mask |= PCCR_S0_RST|PCCR_S1_RST;
if (state->flags & SS_OUTPUT_ENA)
pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT;
local_irq_save(flags);
val = sa1111_readl(pcmcia->mapbase + SA1111_PCCR);
val = (val & ~(pse | flt | wait | rst)) | pccr_mask;
sa1111_writel(val, pcmcia->mapbase + SA1111_PCCR);
val = sa1111_readl(sadev->mapbase + SA1111_PCCR);
val &= ~pccr_skt_mask;
val |= pccr_set_mask & pccr_skt_mask;
sa1111_writel(val, sadev->mapbase + SA1111_PCCR);
local_irq_restore(flags);
return 0;
}
int sa1111_pcmcia_socket_init(int sock)
void sa1111_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
{
return 0;
sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
int sa1111_pcmcia_socket_suspend(int sock)
void sa1111_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
{
return 0;
sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
}
static int pcmcia_probe(struct device *dev)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
unsigned long flags;
char *base;
local_irq_save(flags);
if (pcmcia) {
local_irq_restore(flags);
return -EBUSY;
}
pcmcia = sadev;
local_irq_restore(flags);
if (!request_mem_region(sadev->res.start, 512,
SA1111_DRIVER_NAME(sadev)))
return -EBUSY;
......@@ -226,34 +167,8 @@ static int __devexit pcmcia_remove(struct device *dev)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
#ifdef CONFIG_SA1100_ADSBITSY
pcmcia_adsbitsy_exit(dev);
#endif
#ifdef CONFIG_SA1100_BADGE4
pcmcia_badge4_exit(dev);
#endif
#ifdef CONFIG_SA1100_GRAPHICSMASTER
pcmcia_graphicsmaster_exit(dev);
#endif
#ifdef CONFIG_SA1100_JORNADA720
pcmcia_jornada720_exit(dev);
#endif
#ifdef CONFIG_ASSABET_NEPONSET
pcmcia_neponset_exit(dev);
#endif
#ifdef CONFIG_SA1100_PFS168
pcmcia_pfs_exit(dev);
#endif
#ifdef CONFIG_SA1100_PT_SYSTEM3
pcmcia_system3_exit(dev);
#endif
#ifdef CONFIG_SA1100_XP860
pcmcia_xp860_exit(dev);
#endif
sa11xx_drv_pcmcia_remove(dev);
release_mem_region(sadev->res.start, 512);
pcmcia = NULL;
return 0;
}
......
extern int sa1111_pcmcia_init(struct pcmcia_init *);
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);
#include "sa11xx_core.h"
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 void pcmcia_jornada720_exit(struct device *);
extern int pcmcia_neponset_init(struct device *);
extern void pcmcia_neponset_exit(struct device *);
This diff is collapsed.
/*
* 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
#include <linux/proc_fs.h>
/* include the world */
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
struct device;
/* 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
* 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)
struct pcmcia_state {
unsigned detect: 1,
ready: 1,
bvd1: 1,
bvd2: 1,
wrprot: 1,
vs_3v: 1,
vs_Xv: 1;
};
/*
* 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 {
/*
* Info from low level handler
*/
struct device *dev;
unsigned int nr;
unsigned int irq;
/*
* Core PCMCIA state
*/
struct pcmcia_low_level *ops;
unsigned int status;
socket_state_t cs_state;
void (*handler)(void *, unsigned int);
void *handler_info;
unsigned short spd_io[MAX_IO_WIN];
unsigned short spd_mem[MAX_WIN];
unsigned short spd_attr[MAX_WIN];
struct resource res_skt;
struct resource res_io;
struct resource res_mem;
struct resource res_attr;
void *virt_io;
unsigned int irq_state;
struct timer_list poll_timer;
struct work_struct work;
};
struct pcmcia_low_level {
struct module *owner;
int (*hw_init)(struct sa1100_pcmcia_socket *);
void (*hw_shutdown)(struct sa1100_pcmcia_socket *);
void (*socket_state)(struct sa1100_pcmcia_socket *, struct pcmcia_state *);
int (*configure_socket)(struct sa1100_pcmcia_socket *, const socket_state_t *);
/*
* Enable card status IRQs on (re-)initialisation. This can
* be called at initialisation, power management event, or
* pcmcia event.
*/
void (*socket_init)(struct sa1100_pcmcia_socket *);
/*
* Disable card status IRQs and PCMCIA bus on suspend.
*/
void (*socket_suspend)(struct sa1100_pcmcia_socket *);
/*
* Calculate MECR timing clock wait states
*/
unsigned int (*socket_get_timing)(struct sa1100_pcmcia_socket *,
unsigned int cpu_speed, unsigned int cmd_time);
};
struct pcmcia_irqs {
int sock;
int irq;
const char *str;
};
int sa11xx_request_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr);
void sa11xx_free_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr);
void sa11xx_disable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr);
void sa11xx_enable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr);
extern int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr);
extern int sa11xx_drv_pcmcia_remove(struct device *dev);
#endif
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