Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: mvebu: use chained_irq_{enter,exit} for GIC compatibility

On currently supported SoCs, the GPIO block used on Marvell EBU SoCs
is always connected to the Marvell MPIC. However, we are going to
introduce the support for newer Marvell EBU SoCs that use the
Cortex-A9 core, and therefore use the GIC as their main interrupt
controller, to which the GPIO block controlled by the gpio-mvebu
driver is connected.

The GIC interrupt controller driver uses the fasteoi flow handler. In
order to ensure that the eoi hook of the GIC driver gets called, the
GPIO driver should call chained_irq_enter() and chained_irq_exit() in
its handler. Without this, the first GPIO interrupt locks up the
system because it doesn't get acked at the GIC level.

This change is similar to for example commit
0d978eb7349941139241a99acf05de6dd49b78d1 ("gpio: davinci: use
chained_irq_enter/chained_irq_exit API").

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Thomas Petazzoni and committed by
Linus Walleij
01ca59f1 ff2ed049

+7
+7
drivers/gpio/gpio-mvebu.c
··· 44 44 #include <linux/of_device.h> 45 45 #include <linux/clk.h> 46 46 #include <linux/pinctrl/consumer.h> 47 + #include <linux/irqchip/chained_irq.h> 47 48 48 49 /* 49 50 * GPIO unit register offsets. ··· 439 438 static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 440 439 { 441 440 struct mvebu_gpio_chip *mvchip = irq_get_handler_data(irq); 441 + struct irq_chip *chip = irq_desc_get_chip(desc); 442 442 u32 cause, type; 443 443 int i; 444 444 445 445 if (mvchip == NULL) 446 446 return; 447 + 448 + chained_irq_enter(chip, desc); 447 449 448 450 cause = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) & 449 451 readl_relaxed(mvebu_gpioreg_level_mask(mvchip)); ··· 470 466 polarity ^= 1 << i; 471 467 writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip)); 472 468 } 469 + 473 470 generic_handle_irq(irq); 474 471 } 472 + 473 + chained_irq_exit(chip, desc); 475 474 } 476 475 477 476 #ifdef CONFIG_DEBUG_FS