Skip to content

Commit

Permalink
pinctrl: qcom: Move clearing pending IRQ to .irq_request_resources ca…
Browse files Browse the repository at this point in the history
…llback

When GPIOs that are routed to PDC are used as output they can still latch
the IRQ pending at GIC. As a result the spurious IRQ was handled when the
client driver change the direction to input to starts using it as IRQ.

Currently such erroneous latched IRQ are cleared with .irq_enable callback
however if the driver continue to use GPIO as interrupt and invokes
disable_irq() followed by enable_irq() then everytime during enable_irq()
previously latched interrupt gets cleared.

This can make edge IRQs not seen after enable_irq() if they had arrived
after the driver has invoked disable_irq() and were pending at GIC.

Move clearing erroneous IRQ to .irq_request_resources callback as this is
the place where GPIO direction is changed as input and its locked as IRQ.

While at this add a missing check to invoke msm_gpio_irq_clear_unmask()
from .irq_enable callback only when GPIO is not routed to PDC.

Fixes: e35a6ae ("pinctrl/msm: Setup GPIO chip in hierarchy")
Signed-off-by: Maulik Shah <mkshah@codeaurora.org>
Link: https://lore.kernel.org/r/1604561884-10166-1-git-send-email-mkshah@codeaurora.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
mkshahc authored and linusw committed Nov 10, 2020
1 parent c64a6a0 commit 71266d9
Showing 1 changed file with 19 additions and 13 deletions.
32 changes: 19 additions & 13 deletions drivers/pinctrl/qcom/pinctrl-msm.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,21 +815,14 @@ static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear)

static void msm_gpio_irq_enable(struct irq_data *d)
{
/*
* Clear the interrupt that may be pending before we enable
* the line.
* This is especially a problem with the GPIOs routed to the
* PDC. These GPIOs are direct-connect interrupts to the GIC.
* Disabling the interrupt line at the PDC does not prevent
* the interrupt from being latched at the GIC. The state at
* GIC needs to be cleared before enabling.
*/
if (d->parent_data) {
irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, 0);
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct msm_pinctrl *pctrl = gpiochip_get_data(gc);

if (d->parent_data)
irq_chip_enable_parent(d);
}

msm_gpio_irq_clear_unmask(d, true);
if (!test_bit(d->hwirq, pctrl->skip_wake_irqs))
msm_gpio_irq_clear_unmask(d, true);
}

static void msm_gpio_irq_disable(struct irq_data *d)
Expand Down Expand Up @@ -1104,6 +1097,19 @@ static int msm_gpio_irq_reqres(struct irq_data *d)
ret = -EINVAL;
goto out;
}

/*
* Clear the interrupt that may be pending before we enable
* the line.
* This is especially a problem with the GPIOs routed to the
* PDC. These GPIOs are direct-connect interrupts to the GIC.
* Disabling the interrupt line at the PDC does not prevent
* the interrupt from being latched at the GIC. The state at
* GIC needs to be cleared before enabling.
*/
if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs))
irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, 0);

return 0;
out:
module_put(gc->owner);
Expand Down

0 comments on commit 71266d9

Please sign in to comment.