Skip to content
  • Abhijeet Dharmapurikar's avatar
    spmi: pmic-arb: clear the latched status of the interrupt · cee0fad7
    Abhijeet Dharmapurikar authored
    
    
    PMIC interrupts each have an internal latched status bit which is
    not visible from any register.  This status bit is set as soon as
    the conditions specified in the interrupt type and polarity
    registers are met even if the interrupt is not enabled.  When it
    is set, nothing else changes within the PMIC and no interrupt
    notification packets are sent.  If the internal latched status
    bit is set when an interrupt is enabled, then the value is
    immediately propagated into the interrupt latched status register
    and an interrupt notification packet is sent out from the PMIC
    over SPMI.
    
    This PMIC hardware behavior can lead to a situation where the
    handler for a level triggered interrupt is called immediately
    after enable_irq() is called even though the interrupt physically
    triggered while it was disabled within the genirq framework.
    This situation takes place if the the interrupt fires twice after
    calling disable_irq().  The first time it fires, the level flow
    handler will mask and disregard it.  Unfortunately, the second
    time it fires, the internal latched status bit is set within the
    PMIC and no further notification is received.  When enable_irq()
    is called later, the interrupt is unmasked (enabled in the PMIC)
    which results in the PMIC immediately sending an interrupt
    notification packet out over SPMI.  This breaks the semantics
    of level triggered interrupts within the genirq framework since
    they should be completely ignored while disabled.
    
    The PMIC internal latched status behavior also affects how
    interrupts are treated during suspend.  While entering suspend,
    all interrupts not specified as wakeup mode are masked.  Upon
    resume, these interrupts are unmasked.  Thus if any of the
    non-wakeup PMIC interrupts fired while the system was suspended,
    then the PMIC will send interrupt notification packets out via
    SPMI as soon as they are unmasked during resume.  This behavior
    violates genirq semantics as well since non-wakeup interrupts
    should be completely ignored during suspend.
    
    Modify the qpnpint_irq_unmask() function so that the interrupt
    latched status clear register is written immediately before the
    interrupt enable register.  This clears the internal latched
    status bit of the interrupt so that it cannot trigger spuriously
    immediately upon being enabled.
    
    Also, while resuming an irq, an unmask could be called even if it
    was not previously masked.  So, before writing these registers,
    check if the interrupt is already enabled within the PMIC. If it
    is, then no further register writes are required.  This
    condition check ensures that a valid latched status register bit
    is not cleared until it is properly handled.
    
    Signed-off-by: default avatarAbhijeet Dharmapurikar <adharmap@codeaurora.org>
    Signed-off-by: default avatarKiran Gunda <kgunda@codeaurora.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    cee0fad7