Skip to content

Commit

Permalink
mfd: Acknowlege all WM831x IRQs before we handle them
Browse files Browse the repository at this point in the history
Ensure that we never have a window where we've handled an interrupt (and
therefore need to be notified of new events) but haven't yet told the
interrupt controller that this is the case (so any new events will be
discarded).

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Mark Brown authored and Samuel Ortiz committed Jul 31, 2011
1 parent b1224cd commit 88c9397
Showing 1 changed file with 13 additions and 17 deletions.
30 changes: 13 additions & 17 deletions drivers/mfd/wm831x-irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
{
struct wm831x *wm831x = data;
unsigned int i;
int primary;
int primary, status_addr;
int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
int read[WM831X_NUM_IRQ_REGS] = { 0 };
int *status;
Expand Down Expand Up @@ -484,8 +484,9 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
/* Hopefully there should only be one register to read
* each time otherwise we ought to do a block read. */
if (!read[offset]) {
*status = wm831x_reg_read(wm831x,
irq_data_to_status_reg(&wm831x_irqs[i]));
status_addr = irq_data_to_status_reg(&wm831x_irqs[i]);

*status = wm831x_reg_read(wm831x, status_addr);
if (*status < 0) {
dev_err(wm831x->dev,
"Failed to read IRQ status: %d\n",
Expand All @@ -494,26 +495,21 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
}

read[offset] = 1;

/* Ignore any bits that we don't think are masked */
*status &= ~wm831x->irq_masks_cur[offset];

/* Acknowledge now so we don't miss
* notifications while we handle.
*/
wm831x_reg_write(wm831x, status_addr, *status);
}

/* Report it if it isn't masked, or forget the status. */
if ((*status & ~wm831x->irq_masks_cur[offset])
& wm831x_irqs[i].mask)
if (*status & wm831x_irqs[i].mask)
handle_nested_irq(wm831x->irq_base + i);
else
*status &= ~wm831x_irqs[i].mask;
}

out:
/* Touchscreen interrupts are handled specially in the driver */
status_regs[0] &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);

for (i = 0; i < ARRAY_SIZE(status_regs); i++) {
if (status_regs[i])
wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
status_regs[i]);
}

return IRQ_HANDLED;
}

Expand Down

0 comments on commit 88c9397

Please sign in to comment.