From af02a9d3027e85d589d2e112cd5d1a745b117c24 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 2 Mar 2003 20:48:47 +0000 Subject: [PATCH] [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. --- drivers/pcmcia/sa1100.h | 2 ++ drivers/pcmcia/sa1100_assabet.c | 18 +++--------------- drivers/pcmcia/sa1100_cerf.c | 6 ++---- drivers/pcmcia/sa1100_flexanet.c | 8 ++------ drivers/pcmcia/sa1100_freebird.c | 7 ++----- drivers/pcmcia/sa1100_generic.c | 5 ++--- drivers/pcmcia/sa1100_generic.h | 2 +- drivers/pcmcia/sa1100_graphicsclient.c | 2 +- drivers/pcmcia/sa1100_h3600.c | 10 ++-------- drivers/pcmcia/sa1100_pangolin.c | 6 +++--- drivers/pcmcia/sa1100_shannon.c | 7 ++----- drivers/pcmcia/sa1100_simpad.c | 6 ++---- drivers/pcmcia/sa1100_stork.c | 7 ++----- drivers/pcmcia/sa1100_trizeps.c | 19 +++++-------------- drivers/pcmcia/sa1100_yopy.c | 9 +++------ drivers/pcmcia/sa1111_generic.c | 9 ++------- 16 files changed, 36 insertions(+), 87 deletions(-) diff --git a/drivers/pcmcia/sa1100.h b/drivers/pcmcia/sa1100.h index 839d9fa34084f..02e156c5031b1 100644 --- a/drivers/pcmcia/sa1100.h +++ b/drivers/pcmcia/sa1100.h @@ -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; }; diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c index b10994165e358..acf86535d9ff3 100644 --- a/drivers/pcmcia/sa1100_assabet.c +++ b/drivers/pcmcia/sa1100_assabet.c @@ -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; } diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c index f4b2a6a4bb1bc..7485a31fd74e0 100644 --- a/drivers/pcmcia/sa1100_cerf.c +++ b/drivers/pcmcia/sa1100_cerf.c @@ -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; diff --git a/drivers/pcmcia/sa1100_flexanet.c b/drivers/pcmcia/sa1100_flexanet.c index 4f2fd029e84a1..c64e961eff509 100644 --- a/drivers/pcmcia/sa1100_flexanet.c +++ b/drivers/pcmcia/sa1100_flexanet.c @@ -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; diff --git a/drivers/pcmcia/sa1100_freebird.c b/drivers/pcmcia/sa1100_freebird.c index e510c0955fee2..37ac401f52f41 100644 --- a/drivers/pcmcia/sa1100_freebird.c +++ b/drivers/pcmcia/sa1100_freebird.c @@ -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; diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index 39e786563827a..d840ccb9a7b7e 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -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; diff --git a/drivers/pcmcia/sa1100_generic.h b/drivers/pcmcia/sa1100_generic.h index e572d12c262dd..91fbea86d6826 100644 --- a/drivers/pcmcia/sa1100_generic.h +++ b/drivers/pcmcia/sa1100_generic.h @@ -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 diff --git a/drivers/pcmcia/sa1100_graphicsclient.c b/drivers/pcmcia/sa1100_graphicsclient.c index c989019a5cf56..2bd36b4c576c0 100644 --- a/drivers/pcmcia/sa1100_graphicsclient.c +++ b/drivers/pcmcia/sa1100_graphicsclient.c @@ -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); diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c index c07d0912d95cb..69509df2e1777 100644 --- a/drivers/pcmcia/sa1100_h3600.c +++ b/drivers/pcmcia/sa1100_h3600.c @@ -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; } diff --git a/drivers/pcmcia/sa1100_pangolin.c b/drivers/pcmcia/sa1100_pangolin.c index 05ca1fcb43491..54827bc585d52 100644 --- a/drivers/pcmcia/sa1100_pangolin.c +++ b/drivers/pcmcia/sa1100_pangolin.c @@ -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; } diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c index 5b16217b53622..4995bd420a577 100644 --- a/drivers/pcmcia/sa1100_shannon.c +++ b/drivers/pcmcia/sa1100_shannon.c @@ -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); diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c index 6d0cf82acea5f..a4e5138932314 100644 --- a/drivers/pcmcia/sa1100_simpad.c +++ b/drivers/pcmcia/sa1100_simpad.c @@ -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 ); diff --git a/drivers/pcmcia/sa1100_stork.c b/drivers/pcmcia/sa1100_stork.c index ab021efbd1c3f..504f8b4ac392c 100644 --- a/drivers/pcmcia/sa1100_stork.c +++ b/drivers/pcmcia/sa1100_stork.c @@ -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); diff --git a/drivers/pcmcia/sa1100_trizeps.c b/drivers/pcmcia/sa1100_trizeps.c index a6a285bc0838c..77de63b6973ab 100644 --- a/drivers/pcmcia/sa1100_trizeps.c +++ b/drivers/pcmcia/sa1100_trizeps.c @@ -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; } diff --git a/drivers/pcmcia/sa1100_yopy.c b/drivers/pcmcia/sa1100_yopy.c index d88cdd37d674a..261aa7040a2a0 100644 --- a/drivers/pcmcia/sa1100_yopy.c +++ b/drivers/pcmcia/sa1100_yopy.c @@ -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; diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index 98a3adc9e5802..eab5a1be6ed67 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -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; } -- 2.53.0