Commit af02a9d3 authored by Russell King's avatar Russell King

[ARM] SA11x0 PCMCIA 6

Sanitise our pcmcia interrupt handling.  Make sure we only use
set_irq_type after the interrupt has been registered.

Register the socket handling interrupts using the function name
rather than some pointer passed by the generic code.

Let the generic sa11x0 code handle the cards interrupt masking.
parent 657922c7
......@@ -175,6 +175,8 @@ struct sa1100_pcmcia_socket {
* Info from low level handler
*/
unsigned int irq;
unsigned int irq_state;
struct pcmcia_low_level *ops;
};
......
......@@ -33,16 +33,13 @@ static int assabet_pcmcia_init(struct pcmcia_init *init)
{
int i, res;
/* Set transition detect */
set_irq_type(ASSABET_IRQ_GPIO_CF_IRQ, IRQT_FALLING);
/* Register interrupts */
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
irqs[i].str, NULL);
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;
......@@ -127,15 +124,6 @@ assabet_pcmcia_configure_socket(int sock, const struct pcmcia_configure *configu
ASSABET_BCR_frob(ASSABET_BCR_CF_RST | ASSABET_BCR_CF_PWR, mask);
/*
* Handle suspend mode properly. This prevents a
* flood of IRQs from the CF device.
*/
if (configure->irq)
enable_irq(ASSABET_IRQ_GPIO_CF_IRQ);
else
disable_irq(ASSABET_IRQ_GPIO_CF_IRQ);
return 0;
}
......
......@@ -36,14 +36,12 @@ static int cerf_pcmcia_init(struct pcmcia_init *init)
{
int i, res;
set_irq_type(IRQ_GPIO_CF_IRQ, IRQT_FALLING);
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
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;
......
......@@ -41,17 +41,13 @@ static int flexanet_pcmcia_init(struct pcmcia_init *init)
GPDR &= ~(GPIO_CF1_NCD | GPIO_CF1_BVD1 | GPIO_CF1_IRQ |
GPIO_CF2_NCD | GPIO_CF2_BVD1 | GPIO_CF2_IRQ );
/* Set IRQ edge */
set_irq_type(IRQ_GPIO_CF1_IRQ, IRQT_FALLING);
set_irq_type(IRQ_GPIO_CF2_IRQ, IRQT_FALLING);
/* Register the socket interrupts (not the card interrupts) */
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
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;
......
......@@ -37,16 +37,13 @@ static int freebird_pcmcia_init(struct pcmcia_init *init){
mdelay(100);
LINKUP_PRC = 0xc0;
/* Set transition detect */
set_irq_type(IRQ_GPIO_FREEBIRD_CF_IRQ, IRQT_FALLING);
/* Register interrupts */
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
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;
......
......@@ -155,7 +155,6 @@ sa1100_pcmcia_config_skt(struct sa1100_pcmcia_socket *skt, socket_state_t *state
conf.output = state->flags & SS_OUTPUT_ENA ? 1 : 0;
conf.speaker = state->flags & SS_SPKR_ENA ? 1 : 0;
conf.reset = state->flags & SS_RESET ? 1 : 0;
conf.irq = state->io_irq != 0;
ret = skt->ops->configure_socket(skt->nr, &conf);
if (ret == 0) {
......@@ -350,7 +349,7 @@ static void sa1100_pcmcia_poll_event(unsigned long dummy)
* handling code performs scheduling operations which cannot be
* executed from within an interrupt context.
*/
static void sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
void sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
{
DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
schedule_work(&sa1100_pcmcia_task);
......@@ -944,7 +943,6 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops, struct device *dev)
if (!ops->socket_get_timing)
ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing;
pcmcia_init.handler = sa1100_pcmcia_interrupt;
pcmcia_init.socket_irq[0] = NO_IRQ;
pcmcia_init.socket_irq[1] = NO_IRQ;
ret = ops->init(&pcmcia_init);
......@@ -973,6 +971,7 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops, struct device *dev)
skt->nr = i;
skt->ops = ops;
skt->irq = pcmcia_init.socket_irq[i];
skt->irq_state = 0;
skt->speed_io = SA1100_PCMCIA_IO_ACCESS;
skt->speed_attr = SA1100_PCMCIA_5V_MEM_ACCESS;
skt->speed_mem = SA1100_PCMCIA_5V_MEM_ACCESS;
......
......@@ -18,7 +18,6 @@
#define SA1100_PCMCIA_MAX_SOCK (2)
struct pcmcia_init {
void (*handler)(int irq, void *dev, struct pt_regs *regs);
int socket_irq[SA1100_PCMCIA_MAX_SOCK];
};
......@@ -70,5 +69,6 @@ struct pcmcia_low_level {
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
......@@ -51,7 +51,7 @@ static int gcplus_pcmcia_init(struct pcmcia_init *init)
/* Register interrupts */
irq = S0_CD_IRQ;
res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA 0 CD", NULL);
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);
......
......@@ -29,18 +29,12 @@ static int h3600_pcmcia_init(struct pcmcia_init *init)
{
int i, res;
/*
* Set transition detect
*/
set_irq_type(IRQ_GPIO_H3600_PCMCIA_IRQ0, IRQT_FALLING);
set_irq_type(IRQ_GPIO_H3600_PCMCIA_IRQ1, IRQT_FALLING);
/*
* Register interrupts
*/
for (i = res = 0; i < ARRAY_SIZE(irqs); i++) {
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
irqs[i].str, NULL);
res = request_irq(irqs[i].irq, sa1100_pcmcia_interrupt,
SA_INTERRUPT, irqs[i].str, NULL);
if (res)
break;
}
......
......@@ -37,7 +37,7 @@ static int pangolin_pcmcia_init(struct pcmcia_init *init){
set_irq_type(IRQ_PCMCIA_IRQ, IRQT_FALLING);
/* Register interrupts */
res = request_irq(IRQ_PCMCIA_CD, init->handler, SA_INTERRUPT,
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": */
......@@ -130,14 +130,14 @@ static int pangolin_pcmcia_configure_socket(int sock, const struct pcmcia_config
static int pangolin_pcmcia_socket_init(int sock)
{
if (sock == 1)
set_irq_type(IRQ_PCmCIA_CD, IRQT_BOTHEDGE);
set_irq_type(IRQ_PCMCIA_CD, IRQT_BOTHEDGE);
return 0;
}
static int pangolin_pcmcia_socket_suspend(int sock)
{
if (sock == 1)
set_irq_type(IRQ_PCmCIA_CD, IRQT_NOEDGE);
set_irq_type(IRQ_PCMCIA_CD, IRQT_NOEDGE);
return 0;
}
......
......@@ -34,16 +34,13 @@ static int shannon_pcmcia_init(struct pcmcia_init *init)
GAFR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 |
SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1);
/* Set transition detect */
set_irq_type(SHANNON_IRQ_GPIO_RDY_0, IRQT_FALLING);
set_irq_type(SHANNON_IRQ_GPIO_RDY_1, IRQT_FALLING);
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, init->handler, SA_INTERRUPT,
irqs[i].str, NULL);
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);
......
......@@ -29,14 +29,12 @@ static int simpad_pcmcia_init(struct pcmcia_init *init){
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
/* Set transition detect */
set_irq_type( IRQ_GPIO_CF_CD, IRQT_NOEDGE );
set_irq_type( IRQ_GPIO_CF_IRQ, IRQT_FALLING );
init->socket_irq[1] = IRQ_GPIO_CF_IRQ;
/* Register interrupts */
irq = IRQ_GPIO_CF_CD;
res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
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 );
......
......@@ -46,16 +46,13 @@ static int stork_pcmcia_init(struct pcmcia_init *init)
printk("in stork_pcmcia_init\n");
/* Set transition detect */
set_irq_type(IRQ_GPIO_STORK_PCMCIA_A_RDY, IRQT_FALLING);
set_irq_type(IRQ_GPIO_STORK_PCMCIA_B_RDY, IRQT_FALLING);
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, init->handler, SA_INTERRUPT,
irqs[i].str, NULL);
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);
......
......@@ -40,15 +40,12 @@ static int trizeps_pcmcia_init(struct pcmcia_init *init)
GPDR &= ~((GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_CD0))
| (GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_IRQ0)));
/* Set transition detect */
// set_irq_type(SA1100_GPIO_TO_IRQ(GPIO_TRIZEPS_PCMCIA_CD0), IRQT_BOTHEDGE);
set_irq_type(TRIZEPS_IRQ_PCMCIA_IRQ0, IRQT_FALLING);
/* Register SOCKET interrupts */
/* WHY? */
set_irq_type(TRIZEPS_IRQ_PCMCIA_CD0, IRQT_NOEDGE);
res = request_irq( TRIZEPS_IRQ_PCMCIA_CD0, init->handler, SA_INTERRUPT, "PCMCIA_CD0", NULL );
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
......@@ -146,24 +143,18 @@ static int trizeps_pcmcia_configure_socket(int sock, const struct pcmcia_configu
*/
local_irq_restore(flags);
if (configure->irq) {
enable_irq(TRIZEPS_IRQ_PCMCIA_CD0);
enable_irq(TRIZEPS_IRQ_PCMCIA_IRQ0);
} else {
disable_irq(TRIZEPS_IRQ_PCMCIA_IRQ0);
disable_irq(TRIZEPS_IRQ_PCMCIA_CD0);
}
return 0;
}
static int trizeps_pcmcia_socket_init(int sock)
{
set_irq_type(TRIZEPS_IRQ_PCMCIA_CD0, IRQT_BOTHEDGE);
return 0;
}
static int trizeps_pcmcia_socket_suspend(int sock)
{
set_irq_type(TRIZEPS_IRQ_PCMCIA_CD0, IRQT_NOEDGE);
return 0;
}
......
......@@ -45,16 +45,13 @@ static int yopy_pcmcia_init(struct pcmcia_init *init)
pcmcia_power(0);
pcmcia_reset(1);
/* Set transition detect */
set_irq_type(IRQ_CF_IREQ, IRQT_FALLING);
/* Register interrupts */
for (i = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
irqs[i].str, NULL);
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;
......
......@@ -44,8 +44,8 @@ int sa1111_pcmcia_init(struct pcmcia_init *init)
init->socket_irq[1] = IRQ_S1_READY_NINT;
for (i = ret = 0; i < ARRAY_SIZE(irqs); i++) {
ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
irqs[i].str, NULL);
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);
......@@ -155,11 +155,6 @@ int sa1111_pcmcia_configure_socket(int sock, const struct pcmcia_configure *conf
sa1111_writel(val, pcmcia->mapbase + SA1111_PCCR);
local_irq_restore(flags);
if (conf->irq)
enable_irq(irq);
else
disable_irq(irq);
return 0;
}
......
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