aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-07-20 12:05:13 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2011-07-31 17:28:27 -0400
commit88c939770db375244b00ba92e901fa92677a7164 (patch)
tree44295486ea66c6aee832a3602b600e777e5107fc /drivers/mfd
parentb1224cd113d4441edee4a58a1e2e428141247c0d (diff)
mfd: Acknowlege all WM831x IRQs before we handle them
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>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/wm831x-irq.c30
1 files changed, 13 insertions, 17 deletions
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index 6c3408ca2c2d..ada1835a5455 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -449,7 +449,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
449{ 449{
450 struct wm831x *wm831x = data; 450 struct wm831x *wm831x = data;
451 unsigned int i; 451 unsigned int i;
452 int primary; 452 int primary, status_addr;
453 int status_regs[WM831X_NUM_IRQ_REGS] = { 0 }; 453 int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
454 int read[WM831X_NUM_IRQ_REGS] = { 0 }; 454 int read[WM831X_NUM_IRQ_REGS] = { 0 };
455 int *status; 455 int *status;
@@ -484,8 +484,9 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
484 /* Hopefully there should only be one register to read 484 /* Hopefully there should only be one register to read
485 * each time otherwise we ought to do a block read. */ 485 * each time otherwise we ought to do a block read. */
486 if (!read[offset]) { 486 if (!read[offset]) {
487 *status = wm831x_reg_read(wm831x, 487 status_addr = irq_data_to_status_reg(&wm831x_irqs[i]);
488 irq_data_to_status_reg(&wm831x_irqs[i])); 488
489 *status = wm831x_reg_read(wm831x, status_addr);
489 if (*status < 0) { 490 if (*status < 0) {
490 dev_err(wm831x->dev, 491 dev_err(wm831x->dev,
491 "Failed to read IRQ status: %d\n", 492 "Failed to read IRQ status: %d\n",
@@ -494,26 +495,21 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
494 } 495 }
495 496
496 read[offset] = 1; 497 read[offset] = 1;
498
499 /* Ignore any bits that we don't think are masked */
500 *status &= ~wm831x->irq_masks_cur[offset];
501
502 /* Acknowledge now so we don't miss
503 * notifications while we handle.
504 */
505 wm831x_reg_write(wm831x, status_addr, *status);
497 } 506 }
498 507
499 /* Report it if it isn't masked, or forget the status. */ 508 if (*status & wm831x_irqs[i].mask)
500 if ((*status & ~wm831x->irq_masks_cur[offset])
501 & wm831x_irqs[i].mask)
502 handle_nested_irq(wm831x->irq_base + i); 509 handle_nested_irq(wm831x->irq_base + i);
503 else
504 *status &= ~wm831x_irqs[i].mask;
505 } 510 }
506 511
507out: 512out:
508 /* Touchscreen interrupts are handled specially in the driver */
509 status_regs[0] &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);
510
511 for (i = 0; i < ARRAY_SIZE(status_regs); i++) {
512 if (status_regs[i])
513 wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
514 status_regs[i]);
515 }
516
517 return IRQ_HANDLED; 513 return IRQ_HANDLED;
518} 514}
519 515