summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2014-09-26 13:50:12 +0200
committerLinus Walleij <linus.walleij@linaro.org>2014-09-26 14:35:54 +0200
commit83141a771975f4e54402ab05e5cbbc3c56f45bdd (patch)
tree219158fd8726c5c50605508962554281509120d6 /drivers/gpio/gpiolib.c
parente3893386b90500d7f26fec3170bf96f67d3e557e (diff)
downloadlwn-83141a771975f4e54402ab05e5cbbc3c56f45bdd.tar.gz
lwn-83141a771975f4e54402ab05e5cbbc3c56f45bdd.zip
gpio: set parent irq on chained handlers
If the IRQ from the parent is nested the IRQ may need to be resent under certain conditions. Currently the chained IRQ handler in gpiolib does not handle connecting nested IRQs but it is conceptually correct to indicate the actual parent IRQ. Reported-by: Grygorii Strashko <grygorii.strashko@ti.com> Reported-by: Lothar Waßmann <LW@karo-electronics.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 550e575c6ffb..9362b5b817af 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -398,17 +398,30 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
int parent_irq,
irq_flow_handler_t parent_handler)
{
+ unsigned int offset;
+
if (gpiochip->can_sleep) {
chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");
return;
}
+ if (!gpiochip->irqdomain) {
+ chip_err(gpiochip, "called %s before setting up irqchip\n",
+ __func__);
+ return;
+ }
irq_set_chained_handler(parent_irq, parent_handler);
+
/*
* The parent irqchip is already using the chip_data for this
* irqchip, so our callbacks simply use the handler_data.
*/
irq_set_handler_data(parent_irq, gpiochip);
+
+ /* Set the parent IRQ for all affected IRQs */
+ for (offset = 0; offset < gpiochip->ngpio; offset++)
+ irq_set_parent(irq_find_mapping(gpiochip->irqdomain, offset),
+ parent_irq);
}
EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);