aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@stericsson.com>2013-02-06 15:54:34 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-02-08 08:25:32 -0500
commite2ddf46ab4ab40a657a1808cf4e358c46ae1ba68 (patch)
tree542563712b202faa18aefaff44c94feab5b312e4 /drivers/mfd
parent9c677b9b74d4314ed7f222bf802d6d1e7585eb65 (diff)
mfd: ab8500: actually handle the AB8500 GPIO IRQs correctly
The patch: "mfd: ab8500: prepare to handle AB8500 GPIO's IRQs correctly" altered the AB8500 IRQ mask/unmask functions such that they would handle masking on/off the falling edge IRQ if this was requested by the consumer. However the bit mask for hwirqs 43 and 44 was shifting the bit mask incorrectly, resulting in the wrong IRQ being mased/unmasked. Further while the patch would mask/unmask the correct line, when the interrupt actually came in, it would still be treated as a valid hwirq. The offsetting applied when masking/unmasking was not applied when handling the IRQ, i.e. the falling edge lines were not routed back to the rising edge lines. This fixes both cases. The end result has been tested with the SIM detect IRQ, GPIO12, hwirq 46 and 62. Cc: Samuel Ortiz <sameo@linux.intel.com> Cc: Lee Jones <lee.jones@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/ab8500-core.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 3d5da51b6a94..6d6666b0f1b2 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -375,7 +375,8 @@ static void ab8500_irq_mask(struct irq_data *data)
375 if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 375 if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
376 ab8500->mask[index + 1] |= mask; 376 ab8500->mask[index + 1] |= mask;
377 if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 377 if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
378 ab8500->mask[index] |= (mask >> 1); 378 /* Here the falling IRQ is one bit lower */
379 ab8500->mask[index] |= (mask << 1);
379} 380}
380 381
381static void ab8500_irq_unmask(struct irq_data *data) 382static void ab8500_irq_unmask(struct irq_data *data)
@@ -396,12 +397,14 @@ static void ab8500_irq_unmask(struct irq_data *data)
396 else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 397 else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
397 ab8500->mask[index + 1] &= ~mask; 398 ab8500->mask[index + 1] &= ~mask;
398 else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 399 else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
399 ab8500->mask[index] &= ~(mask >> 1); 400 /* Here the falling IRQ is one bit lower */
401 ab8500->mask[index] &= ~(mask << 1);
400 else 402 else
401 ab8500->mask[index] &= ~mask; 403 ab8500->mask[index] &= ~mask;
402 } else 404 } else {
403 /* Satisfies the case where type is not set. */ 405 /* Satisfies the case where type is not set. */
404 ab8500->mask[index] &= ~mask; 406 ab8500->mask[index] &= ~mask;
407 }
405} 408}
406 409
407static struct irq_chip ab8500_irq_chip = { 410static struct irq_chip ab8500_irq_chip = {
@@ -435,6 +438,19 @@ static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
435 line = (i << 3) + int_bit; 438 line = (i << 3) + int_bit;
436 latch_val &= ~(1 << int_bit); 439 latch_val &= ~(1 << int_bit);
437 440
441 /*
442 * This handles the falling edge hwirqs from the GPIO
443 * lines. Route them back to the line registered for the
444 * rising IRQ, as this is merely a flag for the same IRQ
445 * in linux terms.
446 */
447 if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F)
448 line -= 16;
449 if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F)
450 line -= 8;
451 if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
452 line += 1;
453
438 handle_nested_irq(ab8500->irq_base + line); 454 handle_nested_irq(ab8500->irq_base + line);
439 } while (latch_val); 455 } while (latch_val);
440 456