Browse Source

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 <[email protected]>
Ramprasad Katkam 6 years ago
parent
commit
62d6d76b81
2 changed files with 18 additions and 11 deletions
  1. 1 0
      include/soc/soundwire.h
  2. 17 11
      soc/swr-mstr-ctrl.c

+ 1 - 0
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)

+ 17 - 11
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",