Skip to content

Commit e9945b2

Browse files
HoratiuVulturlinusw
authored andcommitted
pinctrl: ocelot: Fix incorrect trigger of the interrupt.
The interrupt controller can detect only link changes. So in case an external device generated a level based interrupt, then the interrupt controller detected correctly the first edge. But the problem was that the interrupt controller was detecting also the edge when the interrupt was cleared. So it would generate another interrupt. The fix for this is to clear the second interrupt but still check the interrupt line status. Fixes: c297561 ("pinctrl: ocelot: Fix interrupt controller") Signed-off-by: Horatiu Vultur <[email protected]> Tested-by: Michael Walle <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Linus Walleij <[email protected]>
1 parent ff83560 commit e9945b2

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

drivers/pinctrl/pinctrl-ocelot.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,19 +1864,28 @@ static void ocelot_irq_unmask_level(struct irq_data *data)
18641864
if (val & bit)
18651865
ack = true;
18661866

1867+
/* Try to clear any rising edges */
1868+
if (!active && ack)
1869+
regmap_write_bits(info->map, REG(OCELOT_GPIO_INTR, info, gpio),
1870+
bit, bit);
1871+
18671872
/* Enable the interrupt now */
18681873
gpiochip_enable_irq(chip, gpio);
18691874
regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio),
18701875
bit, bit);
18711876

18721877
/*
1873-
* In case the interrupt line is still active and the interrupt
1874-
* controller has not seen any changes in the interrupt line, then it
1875-
* means that there happen another interrupt while the line was active.
1878+
* In case the interrupt line is still active then it means that
1879+
* there happen another interrupt while the line was active.
18761880
* So we missed that one, so we need to kick the interrupt again
18771881
* handler.
18781882
*/
1879-
if (active && !ack) {
1883+
regmap_read(info->map, REG(OCELOT_GPIO_IN, info, gpio), &val);
1884+
if ((!(val & bit) && trigger_level == IRQ_TYPE_LEVEL_LOW) ||
1885+
(val & bit && trigger_level == IRQ_TYPE_LEVEL_HIGH))
1886+
active = true;
1887+
1888+
if (active) {
18801889
struct ocelot_irq_work *work;
18811890

18821891
work = kmalloc(sizeof(*work), GFP_ATOMIC);

0 commit comments

Comments
 (0)