mfd: fix pcap irq bottom handler
Mask interrupts before servicing them and loop while pcap asserts the interrupt line. Signed-off-by: Daniel Ribeiro <drwyrm@gmail.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
ecd78cbdb9
commit
b1148fd46c
|
@ -17,6 +17,7 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/mfd/ezx-pcap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#define PCAP_ADC_MAXQ 8
|
||||
struct pcap_adc_request {
|
||||
|
@ -155,34 +156,38 @@ static void pcap_isr_work(struct work_struct *work)
|
|||
u32 msr, isr, int_sel, service;
|
||||
int irq;
|
||||
|
||||
ezx_pcap_read(pcap, PCAP_REG_MSR, &msr);
|
||||
ezx_pcap_read(pcap, PCAP_REG_ISR, &isr);
|
||||
do {
|
||||
ezx_pcap_read(pcap, PCAP_REG_MSR, &msr);
|
||||
ezx_pcap_read(pcap, PCAP_REG_ISR, &isr);
|
||||
|
||||
/* We cant service/ack irqs that are assigned to port 2 */
|
||||
if (!(pdata->config & PCAP_SECOND_PORT)) {
|
||||
ezx_pcap_read(pcap, PCAP_REG_INT_SEL, &int_sel);
|
||||
isr &= ~int_sel;
|
||||
}
|
||||
ezx_pcap_write(pcap, PCAP_REG_ISR, isr);
|
||||
|
||||
local_irq_disable();
|
||||
service = isr & ~msr;
|
||||
|
||||
for (irq = pcap->irq_base; service; service >>= 1, irq++) {
|
||||
if (service & 1) {
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
|
||||
if (WARN(!desc, KERN_WARNING
|
||||
"Invalid PCAP IRQ %d\n", irq))
|
||||
break;
|
||||
|
||||
if (desc->status & IRQ_DISABLED)
|
||||
note_interrupt(irq, desc, IRQ_NONE);
|
||||
else
|
||||
desc->handle_irq(irq, desc);
|
||||
/* We cant service/ack irqs that are assigned to port 2 */
|
||||
if (!(pdata->config & PCAP_SECOND_PORT)) {
|
||||
ezx_pcap_read(pcap, PCAP_REG_INT_SEL, &int_sel);
|
||||
isr &= ~int_sel;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
|
||||
ezx_pcap_write(pcap, PCAP_REG_MSR, isr | msr);
|
||||
ezx_pcap_write(pcap, PCAP_REG_ISR, isr);
|
||||
|
||||
local_irq_disable();
|
||||
service = isr & ~msr;
|
||||
for (irq = pcap->irq_base; service; service >>= 1, irq++) {
|
||||
if (service & 1) {
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
|
||||
if (WARN(!desc, KERN_WARNING
|
||||
"Invalid PCAP IRQ %d\n", irq))
|
||||
break;
|
||||
|
||||
if (desc->status & IRQ_DISABLED)
|
||||
note_interrupt(irq, desc, IRQ_NONE);
|
||||
else
|
||||
desc->handle_irq(irq, desc);
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
|
||||
} while (gpio_get_value(irq_to_gpio(pcap->spi->irq)));
|
||||
}
|
||||
|
||||
static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
|
|
Loading…
Reference in New Issue