summaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ab8500-core.c
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2012-12-20 11:23:42 +0000
committerLinus Walleij <linus.walleij@linaro.org>2013-02-08 14:25:30 +0100
commit9c677b9b74d4314ed7f222bf802d6d1e7585eb65 (patch)
tree48962275455bc67551f3bd28585638ada958da02 /drivers/mfd/ab8500-core.c
parent88b62b915b0b7e25870eb0604ed9a92ba4bfc9f7 (diff)
downloadlinux-9c677b9b74d4314ed7f222bf802d6d1e7585eb65.tar.gz
linux-9c677b9b74d4314ed7f222bf802d6d1e7585eb65.tar.bz2
linux-9c677b9b74d4314ed7f222bf802d6d1e7585eb65.zip
mfd: ab8500: prepare to handle AB8500 GPIO's IRQs correctly
In an upcoming patch, the gpio-ab8500 driver will relinquish all IRQ handling capability and pass it back into the AB8500 core driver. This will aid in reducing massive code duplication within the kernel. Also, most of the functionality is already in the AB8500 core driver, as the GPIO IRQs are actually sandwiched between lots of other IRQs which the core driver already handles. All we're doing here is providing the core driver with knowledge that each GPIO has two IRQs assigned to it; one for rising and a separate one for falling. Cc: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/mfd/ab8500-core.c')
-rw-r--r--drivers/mfd/ab8500-core.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 4778bb124efe..3d5da51b6a94 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -368,16 +368,40 @@ static void ab8500_irq_mask(struct irq_data *data)
int mask = 1 << (offset % 8);
ab8500->mask[index] |= mask;
+
+ /* The AB8500 GPIOs have two interrupts each (rising & falling). */
+ if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
+ ab8500->mask[index + 2] |= mask;
+ if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
+ ab8500->mask[index + 1] |= mask;
+ if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
+ ab8500->mask[index] |= (mask >> 1);
}
static void ab8500_irq_unmask(struct irq_data *data)
{
struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
+ unsigned int type = irqd_get_trigger_type(data);
int offset = data->hwirq;
int index = offset / 8;
int mask = 1 << (offset % 8);
- ab8500->mask[index] &= ~mask;
+ if (type & IRQ_TYPE_EDGE_RISING)
+ ab8500->mask[index] &= ~mask;
+
+ /* The AB8500 GPIOs have two interrupts each (rising & falling). */
+ if (type & IRQ_TYPE_EDGE_FALLING) {
+ if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
+ ab8500->mask[index + 2] &= ~mask;
+ else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
+ ab8500->mask[index + 1] &= ~mask;
+ else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
+ ab8500->mask[index] &= ~(mask >> 1);
+ else
+ ab8500->mask[index] &= ~mask;
+ } else
+ /* Satisfies the case where type is not set. */
+ ab8500->mask[index] &= ~mask;
}
static struct irq_chip ab8500_irq_chip = {