aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/spmi
diff options
context:
space:
mode:
authorAshay Jaiswal <ashayj@codeaurora.org>2022-09-29 17:50:15 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-30 14:33:23 +0200
commit4df88fe5b631bb9e381880b4cca73e91750afffe (patch)
tree76367d910e5836c619f38fa3578749493a45ecad /drivers/spmi
parentspmi: pmic-arb: check apid against limits before calling irq handler (diff)
downloadwireguard-linux-4df88fe5b631bb9e381880b4cca73e91750afffe.tar.xz
wireguard-linux-4df88fe5b631bb9e381880b4cca73e91750afffe.zip
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')
-rw-r--r--drivers/spmi/spmi-pmic-arb.c29
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);