diff options
| author | Abhijeet Dharmapurikar <adharmap@codeaurora.org> | 2016-01-08 10:50:19 -0800 |
|---|---|---|
| committer | Rohit Vaswani <rvaswani@codeaurora.org> | 2016-03-01 12:22:47 -0800 |
| commit | e4955de860441189c8359bcd7a44331ec708a36a (patch) | |
| tree | 224e8148754e1e7275308587ce3c38e6232319f8 /drivers/spmi | |
| parent | 4b3416b34d67b6b799aebd6346fd8e319f9a015c (diff) | |
spmi: pmic-arb: cleanup unrequested irqs
We see a unmapped irqs trigger right around bootup. This could
likely be because the bootloader exited leaving the interrupts
in an unknown or unhandled state. Ack and mask the interrupt
if one is found. A request_irq later will unmask it and also
setup proper mapping structures.
Change-Id: Icc2fc4f1bd9b3333e5856fce2daa5ba2b69e9a87
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Diffstat (limited to 'drivers/spmi')
| -rw-r--r-- | drivers/spmi/spmi-pmic-arb.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index 2d8057d2dba6..d0ddc59019b3 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -486,6 +486,37 @@ static void qpnpint_spmi_read(struct irq_data *d, u8 reg, void *buf, size_t len) d->irq); } +static void cleanup_irq(struct spmi_pmic_arb *pa, u8 apid, int id) +{ + u32 status; + u16 ppid = pa->apid_data[apid].ppid; + u8 sid = ppid >> 8; + u8 per = ppid & 0xFF; + unsigned long flags; + u8 irq_mask = BIT(id); + + raw_spin_lock_irqsave(&pa->lock, flags); + writel_relaxed(irq_mask, pa->intr + pa->ver_ops->irq_clear(apid)); + if (pa->apid_data[apid].enabled_irq_mask == 0) { + status = readl_relaxed(pa->intr + pa->ver_ops->acc_enable(apid)); + status = status & ~SPMI_PIC_ACC_ENABLE_BIT; + writel_relaxed(status, pa->intr + pa->ver_ops->acc_enable(apid)); + } + raw_spin_unlock_irqrestore(&pa->lock, flags); + + if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid, + (per << 8) + QPNPINT_REG_LATCHED_CLR, &irq_mask, 1)) + dev_err_ratelimited(&pa->spmic->dev, + "failed to ack irq_mask = 0x%x for ppid = %x\n", + irq_mask, ppid); + + if (pmic_arb_write_cmd(pa->spmic, SPMI_CMD_EXT_WRITEL, sid, + (per << 8) + QPNPINT_REG_EN_CLR, &irq_mask, 1)) + dev_err_ratelimited(&pa->spmic->dev, + "failed to ack irq_mask = 0x%x for ppid = %x\n", + irq_mask, ppid); +} + static void periph_interrupt(struct spmi_pmic_arb *pa, u8 apid) { unsigned int irq; @@ -500,6 +531,10 @@ static void periph_interrupt(struct spmi_pmic_arb *pa, u8 apid) pa->apid_data[apid].ppid << 16 | id << 8 | apid); + if (irq == 0) { + cleanup_irq(pa, apid, id); + continue; + } generic_handle_irq(irq); } } |
