summaryrefslogtreecommitdiff
path: root/drivers/spmi
diff options
context:
space:
mode:
authorAbhijeet Dharmapurikar <adharmap@codeaurora.org>2016-01-08 10:50:19 -0800
committerRohit Vaswani <rvaswani@codeaurora.org>2016-03-01 12:22:47 -0800
commite4955de860441189c8359bcd7a44331ec708a36a (patch)
tree224e8148754e1e7275308587ce3c38e6232319f8 /drivers/spmi
parent4b3416b34d67b6b799aebd6346fd8e319f9a015c (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.c35
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);
}
}