[lkml]   [2019]   [Apr]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Patch in this message
    Subject[PATCH 4.9 12/91] gpio: gpio-omap: fix level interrupt idling
    4.9-stable review patch.  If anyone has any objections, please let me know.


    [ Upstream commit d01849f7deba81f4959fd9e51bf20dbf46987d1c ]

    Tony notes that the GPIO module does not idle when level interrupts are
    in use, as the wakeup appears to get stuck.

    After extensive investigation, it appears that the wakeup will only be
    cleared if the interrupt status register is cleared while the interrupt
    is enabled. However, we are currently clearing it with the interrupt
    disabled for level-based interrupts.

    It is acknowledged that this observed behaviour conflicts with a
    statement in the TRM:

    After servicing the interrupt, the status bit in the interrupt status
    register (GPIOi.GPIO_IRQSTATUS_0 or GPIOi.GPIO_IRQSTATUS_1) must be
    reset and the interrupt line released (by setting the corresponding
    bit of the interrupt status register to 1) before enabling an
    interrupt for the GPIO channel in the interrupt-enable register
    the occurrence of unexpected interrupts when enabling an interrupt
    for the GPIO channel.

    However, this does not appear to be a practical problem.

    Further, as reported by Grygorii Strashko <>,
    the TI Android kernel tree has an earlier similar patch as "GPIO: OMAP:
    Fix the sequence to clear the IRQ status" saying:

    if the status is cleared after disabling the IRQ then sWAKEUP will not
    be cleared and gates the module transition

    When we unmask the level interrupt after the interrupt has been handled,
    enable the interrupt and only then clear the interrupt. If the interrupt
    is still pending, the hardware will re-assert the interrupt status.

    Should the caution note in the TRM prove to be a problem, we could
    use a clear-enable-clear sequence instead.

    Cc: Aaro Koskinen <>
    Cc: Keerthy <>
    Cc: Peter Ujfalusi <>
    Signed-off-by: Russell King <>
    [ updated comments based on an earlier TI patch]
    Signed-off-by: Tony Lindgren <>
    Acked-by: Grygorii Strashko <>
    Signed-off-by: Linus Walleij <>
    Signed-off-by: Sasha Levin <>
    drivers/gpio/gpio-omap.c | 14 ++++++++------
    1 file changed, 8 insertions(+), 6 deletions(-)

    diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
    index 6f9c9ac6ee70..75f30a0c418a 100644
    --- a/drivers/gpio/gpio-omap.c
    +++ b/drivers/gpio/gpio-omap.c
    @@ -837,14 +837,16 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
    if (trigger)
    omap_set_gpio_triggering(bank, offset, trigger);

    - /* For level-triggered GPIOs, the clearing must be done after
    - * the HW source is cleared, thus after the handler has run */
    - if (bank->level_mask & BIT(offset)) {
    - omap_set_gpio_irqenable(bank, offset, 0);
    + omap_set_gpio_irqenable(bank, offset, 1);
    + /*
    + * For level-triggered GPIOs, clearing must be done after the source
    + * is cleared, thus after the handler has run. OMAP4 needs this done
    + * after enabing the interrupt to clear the wakeup status.
    + */
    + if (bank->level_mask & BIT(offset))
    omap_clear_gpio_irqstatus(bank, offset);
    - }

    - omap_set_gpio_irqenable(bank, offset, 1);
    raw_spin_unlock_irqrestore(&bank->lock, flags);


     \ /
      Last update: 2019-04-04 11:58    [W:2.494 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site