• Stephen Boyd's avatar
    pinctrl: msm: Really mask level interrupts to prevent latching · b55326dc
    Stephen Boyd authored
    The interrupt controller hardware in this pin controller has two status
    enable bits. The first "normal" status enable bit enables or disables
    the summary interrupt line being raised when a gpio interrupt triggers
    and the "raw" status enable bit allows or prevents the hardware from
    latching an interrupt into the status register for a gpio interrupt.
    Currently we just toggle the "normal" status enable bit in the mask and
    unmask ops so that the summary irq interrupt going to the CPU's
    interrupt controller doesn't trigger for the masked gpio interrupt.
    
    For a level triggered interrupt, the flow would be as follows: the pin
    controller sees the interrupt, latches the status into the status
    register, raises the summary irq to the CPU, summary irq handler runs
    and calls handle_level_irq(), handle_level_irq() masks and acks the gpio
    interrupt, the interrupt handler runs, and finally unmask the interrupt.
    When the interrupt handler completes, we expect that the interrupt line
    level will go back to the deasserted state so the genirq code can unmask
    the interrupt without it triggering again.
    
    If we only mask the interrupt by clearing the "normal" status enable bit
    then we'll ack the interrupt but it will continue to show up as pending
    in the status register because the raw status bit is enabled, the
    hardware hasn't deasserted the line, and thus the asserted state latches
    into the status register again. When the hardware deasserts the
    interrupt the pin controller still thinks there is a pending unserviced
    level interrupt because it latched it earlier. This behavior causes
    software to see an extra interrupt for level type interrupts each time
    the interrupt is handled.
    
    Let's fix this by clearing the raw status enable bit for level type
    interrupts so that the hardware stops latching the status of the
    interrupt after we ack it. We don't do this for edge type interrupts
    because it seems that toggling the raw status enable bit for edge type
    interrupts causes spurious edge interrupts.
    Signed-off-by: default avatarStephen Boyd <swboyd@chromium.org>
    Reviewed-by: default avatarDouglas Anderson <dianders@chromium.org>
    Reviewed-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
    Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
    b55326dc
pinctrl-msm.c 27.5 KB