From 62d6d76b8171ec5afc699bd0f5e2e14f74d429e1 Mon Sep 17 00:00:00 2001 From: Ramprasad Katkam Date: Thu, 20 Sep 2018 17:50:28 +0530 Subject: [PATCH] soc: swr-mstr: Add logic to recursively trigger slave irq handler Soundwire slave interrupt is only edge type, so any pending slave side interrupts could not cause a new slave interrupt, if they are triggered before clearing of existing interrupts. Recursively trigger slave irq until there are no pending slave interrupts to handle this issue. Change-Id: I254f2467f09172490796114b48f1f0feb604ad17 Signed-off-by: Ramprasad Katkam --- include/soc/soundwire.h | 1 + soc/swr-mstr-ctrl.c | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/include/soc/soundwire.h b/include/soc/soundwire.h index 279642816072..3bc3332af4c1 100644 --- a/include/soc/soundwire.h +++ b/include/soc/soundwire.h @@ -208,6 +208,7 @@ struct swr_device { unsigned long addr; u8 group_id; struct irq_domain *slave_irq; + bool slave_irq_pending; }; static inline struct swr_device *to_swr_device(struct device *dev) diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 7232fe83caa8..0a1c2520c397 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -1237,20 +1237,26 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev) spurious interrupt\n"); return ret; } - list_for_each_entry(swr_dev, &mstr->devices, dev_list) { - if (swr_dev->dev_num != devnum) - continue; - if (swr_dev->slave_irq) - handle_nested_irq( - irq_find_mapping( - swr_dev->slave_irq, 0)); - } swrm_cmd_fifo_rd_cmd(swrm, &temp, devnum, 0x0, SWRS_SCP_INT_STATUS_CLEAR_1, 1); swrm_cmd_fifo_wr_cmd(swrm, 0x4, devnum, 0x0, SWRS_SCP_INT_STATUS_CLEAR_1); swrm_cmd_fifo_wr_cmd(swrm, 0x0, devnum, 0x0, SWRS_SCP_INT_STATUS_CLEAR_1); + + + list_for_each_entry(swr_dev, &mstr->devices, dev_list) { + if (swr_dev->dev_num != devnum) + continue; + if (swr_dev->slave_irq) { + do { + handle_nested_irq( + irq_find_mapping( + swr_dev->slave_irq, 0)); + } while (swr_dev->slave_irq_pending); + } + + } break; case SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED: dev_dbg(swrm->dev, "SWR new slave attached\n"); @@ -1465,9 +1471,9 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) reg[len] = SWRM_MCP_BUS_CTRL_ADDR; value[len++] = 0x2; - /* Set IRQ to PULSE */ + /* Set IRQ to LEVEL */ reg[len] = SWRM_COMP_CFG_ADDR; - value[len++] = 0x03; + value[len++] = 0x01; reg[len] = SWRM_INTERRUPT_CLEAR; value[len++] = 0xFFFFFFFF; @@ -1722,7 +1728,7 @@ static int swrm_probe(struct platform_device *pdev) ret = request_threaded_irq(swrm->irq, NULL, swr_mstr_interrupt, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "swr_master_irq", swrm); if (ret) { dev_err(swrm->dev, "%s: Failed to request irq %d\n",