diff options
author | Ashay Jaiswal <ashayj@codeaurora.org> | 2022-09-29 17:50:15 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-09-30 14:33:23 +0200 |
commit | 4df88fe5b631bb9e381880b4cca73e91750afffe (patch) | |
tree | 76367d910e5836c619f38fa3578749493a45ecad /drivers/spmi/spmi-pmic-arb.c | |
parent | 191adbdd26f1a26c9302369b2701bfddf8c0780e (diff) |
spmi: pmic-arb: add support to dispatch interrupt based on IRQ status
Current implementation of SPMI arbiter dispatches interrupt based on the
Arbiter's accumulator status, in some cases the accumulator status may
remain zero and the interrupt remains un-handled. Add logic to dispatch
interrupts based Arbiter's IRQ status if the accumulator status is zero.
Signed-off-by: Ashay Jaiswal <ashayj@codeaurora.org>
Signed-off-by: David Collins <collinsd@codeaurora.org>
Signed-off-by: Fenglin Wu <quic_fenglinw@quicinc.com>
Link: https://lore.kernel.org/r/1655004286-11493-6-git-send-email-quic_fenglinw@quicinc.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Link: https://lore.kernel.org/r/20220930005019.2663064-7-sboyd@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/spmi/spmi-pmic-arb.c')
-rw-r--r-- | drivers/spmi/spmi-pmic-arb.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c index e19eaec30aa5..56f22941d570 100644 --- a/drivers/spmi/spmi-pmic-arb.c +++ b/drivers/spmi/spmi-pmic-arb.c @@ -630,12 +630,18 @@ static void pmic_arb_chained_irq(struct irq_desc *desc) u8 ee = pmic_arb->ee; u32 status, enable, handled = 0; int i, id, apid; + /* status based dispatch */ + bool acc_valid = false; + u32 irq_status = 0; chained_irq_enter(chip, desc); for (i = first >> 5; i <= last >> 5; ++i) { status = readl_relaxed( ver_ops->owner_acc_status(pmic_arb, ee, i)); + if (status) + acc_valid = true; + while (status) { id = ffs(status) - 1; status &= ~BIT(id); @@ -653,6 +659,29 @@ static void pmic_arb_chained_irq(struct irq_desc *desc) } } + /* ACC_STATUS is empty but IRQ fired check IRQ_STATUS */ + if (!acc_valid) { + for (i = first; i <= last; i++) { + /* skip if APPS is not irq owner */ + if (pmic_arb->apid_data[i].irq_ee != pmic_arb->ee) + continue; + + irq_status = readl_relaxed( + ver_ops->irq_status(pmic_arb, i)); + if (irq_status) { + enable = readl_relaxed( + ver_ops->acc_enable(pmic_arb, i)); + if (enable & SPMI_PIC_ACC_ENABLE_BIT) { + dev_dbg(&pmic_arb->spmic->dev, + "Dispatching IRQ for apid=%d status=%x\n", + i, irq_status); + if (periph_interrupt(pmic_arb, i) != 0) + handled++; + } + } + } + } + if (handled == 0) handle_bad_irq(desc); |