[PATCH 07/12] usb: dwc2: Move gadget interrupts to common interrupt handler

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Dinh Nguyen <dinguyen@xxxxxxxxxx>

Update dwc2_handle_common_intr() to handle both hcd and gadget interrupts.

Signed-off-by: Dinh Nguyen <dinguyen@xxxxxxxxxx>
---
 drivers/usb/dwc2/core_intr.c |  116 +++++++++++++++++++++++++-
 drivers/usb/dwc2/gadget.c    |  188 ------------------------------------------
 2 files changed, 114 insertions(+), 190 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index c93918b..7500621 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -337,6 +337,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 		}
 		/* Change to L0 state */
 		hsotg->lx_state = DWC2_L0;
+		call_gadget(hsotg, resume);
 	} else {
 		if (hsotg->lx_state != DWC2_L1) {
 			u32 pcgcctl = readl(hsotg->regs + PCGCTL);
@@ -397,6 +398,8 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
 			"DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n",
 			!!(dsts & DSTS_SUSPSTS),
 			hsotg->hw_params.power_optimized);
+
+		call_gadget(hsotg, suspend);
 	} else {
 		if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
 			dev_dbg(hsotg->dev, "a_peripheral->a_host\n");
@@ -421,6 +424,11 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
 			 GINTSTS_MODEMIS | GINTSTS_DISCONNINT |		\
 			 GINTSTS_USBSUSP | GINTSTS_PRTINT)
 
+/* IRQ flags which will trigger a retry around the IRQ loop */
+#define IRQ_RETRY_MASK (GINTSTS_NPTXFEMP | \
+			GINTSTS_PTXFEMP |  \
+			GINTSTS_RXFLVL)
+
 /*
  * This function returns the Core Interrupt register
  */
@@ -441,7 +449,7 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
 			gintsts, gintmsk);
 
 	if (gahbcfg & GAHBCFG_GLBL_INTR_EN)
-		return gintsts & gintmsk & gintmsk_common;
+		return gintsts & gintmsk;
 	else
 		return 0;
 }
@@ -463,7 +471,8 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
 {
 	struct dwc2_hsotg *hsotg = dev;
 	u32 gintsts;
-	irqreturn_t retval = IRQ_NONE;
+	int retry_count = 8;
+	irqreturn_t retval = IRQ_HANDLED;
 
 	if (!dwc2_is_controller_alive(hsotg)) {
 		dev_warn(hsotg->dev, "Controller is dead\n");
@@ -472,16 +481,90 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
 
 	spin_lock(&hsotg->lock);
 
+irq_retry:
 	gintsts = dwc2_read_common_intr(hsotg);
 	if (gintsts & ~GINTSTS_PRTINT)
 		retval = IRQ_HANDLED;
 
+	if (gintsts & GINTSTS_ENUMDONE) {
+		writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
+		s3c_hsotg_irq_enumdone(hsotg);
+	}
+
 	if (gintsts & GINTSTS_MODEMIS)
 		dwc2_handle_mode_mismatch_intr(hsotg);
 	if (gintsts & GINTSTS_OTGINT)
 		dwc2_handle_otg_intr(hsotg);
 	if (gintsts & GINTSTS_CONIDSTSCHNG)
 		dwc2_handle_conn_id_status_change_intr(hsotg);
+
+	if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {
+		u32 daint = readl(hsotg->regs + DAINT);
+		u32 daint_out = daint >> DAINT_OUTEP_SHIFT;
+		u32 daint_in = daint & ~(daint_out << DAINT_OUTEP_SHIFT);
+		int ep;
+
+		dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint);
+		for (ep = 0; ep < 15 && daint_out; ep++, daint_out >>= 1) {
+			if (daint_out & 1)
+				s3c_hsotg_epint(hsotg, ep, 0);
+		}
+
+		for (ep = 0; ep < 15 && daint_in; ep++, daint_in >>= 1) {
+			if (daint_in & 1)
+				s3c_hsotg_epint(hsotg, ep, 1);
+		}
+	}
+
+	if (gintsts & GINTSTS_USBRST) {
+		u32 usb_status = readl(hsotg->regs + GOTGCTL);
+
+		dev_dbg(hsotg->dev, "%s: USBRST\n", __func__);
+		dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
+			readl(hsotg->regs + GNPTXSTS));
+
+		writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
+
+		if (usb_status & GOTGCTL_BSESVLD) {
+			if (time_after(jiffies, hsotg->s3c_hsotg->last_rst +
+				msecs_to_jiffies(200))) {
+				kill_all_requests(hsotg, &hsotg->eps[0],
+					-ECONNRESET, true);
+				s3c_hsotg_core_init(hsotg);
+				hsotg->s3c_hsotg->last_rst = jiffies;
+			}
+		}
+	}
+
+	if (gintsts & GINTSTS_NPTXFEMP) {
+		dev_dbg(hsotg->dev, "NPTXFEMP\n");
+
+		/*
+		 * Disable the interrupt to stop it happening again
+		 * unless one of these endpoint routines decides that
+		 * it needs re-enabling
+		 */
+		s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTXFEMP);
+		s3c_hsotg_irq_fifoempty(hsotg, false);
+	}
+
+	if (gintsts & GINTSTS_PTXFEMP) {
+		dev_dbg(hsotg->dev, "PTXFEMP\n");
+
+		/* See note in GINTSTS_NPTxFEmp */
+		s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTXFEMP);
+		s3c_hsotg_irq_fifoempty(hsotg, true);
+	}
+
+	if (gintsts & GINTSTS_RXFLVL) {
+		/*
+		 * note, since GINTSTS_RXFLVL doubles as FIFO-not-empty,
+		 * we need to retry s3c_hsotg_handle_rx if this is still
+		 * set.
+		 */
+		s3c_hsotg_handle_rx(hsotg);
+	}
+
 	if (gintsts & GINTSTS_DISCONNINT)
 		dwc2_handle_disconnect_intr(hsotg);
 	if (gintsts & GINTSTS_SESSREQINT)
@@ -491,6 +574,28 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
 	if (gintsts & GINTSTS_USBSUSP)
 		dwc2_handle_usb_suspend_intr(hsotg);
 
+	if (gintsts & GINTSTS_ERLYSUSP) {
+		dev_dbg(hsotg->dev, "GINTSTS_ERLYSUSP\n");
+		writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS);
+	}
+
+	/*
+	 * these next two seem to crop-up occasionally causing the core
+	 * to shutdown the USB transfer, so try clearing them and logging
+	 * the occurrence.
+	 */
+	if (gintsts & GINTSTS_GOUTNAKEFF) {
+		dev_dbg(hsotg->dev, "GOUTNAKEFF triggered\n");
+		writel(DCTL_CGOUTNAK, hsotg->regs + DCTL);
+		s3c_hsotg_dump(hsotg);
+	}
+
+	if (gintsts & GINTSTS_GINNAKEFF) {
+		dev_dbg(hsotg->dev, "GINNAKEFF triggered\n");
+		writel(DCTL_CGNPINNAK, hsotg->regs + DCTL);
+		s3c_hsotg_dump(hsotg);
+	}
+
 	if (gintsts & GINTSTS_PRTINT) {
 		/*
 		 * The port interrupt occurs while in device mode with HPRT0
@@ -504,6 +609,13 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
 		}
 	}
 
+	/*
+	 * if we've had fifo events, we should try and go around the
+	 * loop again to see if there's any point in returning yet.
+	 */
+	if (gintsts & IRQ_RETRY_MASK && --retry_count > 0)
+		goto irq_retry;
+
 	spin_unlock(&hsotg->lock);
 out:
 	return retval;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index b8c466f..aa57d3e 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2231,194 +2231,6 @@ void s3c_hsotg_core_init(struct dwc2_hsotg *dwc2)
 }
 
 /**
- * s3c_hsotg_irq - handle device interrupt
- * @irq: The IRQ number triggered
- * @pw: The pw value when registered the handler.
- */
-static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
-{
-	struct s3c_hsotg *hsotg = pw;
-	int retry_count = 8;
-	u32 gintsts;
-	u32 gintmsk;
-
-	spin_lock(&hsotg->lock);
-irq_retry:
-	gintsts = readl(hsotg->regs + GINTSTS);
-	gintmsk = readl(hsotg->regs + GINTMSK);
-
-	dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n",
-		__func__, gintsts, gintsts & gintmsk, gintmsk, retry_count);
-
-	gintsts &= gintmsk;
-
-	if (gintsts & GINTSTS_OTGINT) {
-		u32 otgint = readl(hsotg->regs + GOTGINT);
-
-		dev_info(hsotg->dev, "OTGInt: %08x\n", otgint);
-
-		writel(otgint, hsotg->regs + GOTGINT);
-	}
-
-	if (gintsts & GINTSTS_SESSREQINT) {
-		dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__);
-		writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
-	}
-
-	if (gintsts & GINTSTS_ENUMDONE) {
-		writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
-
-		s3c_hsotg_irq_enumdone(hsotg);
-	}
-
-	if (gintsts & GINTSTS_CONIDSTSCHNG) {
-		dev_dbg(hsotg->dev, "ConIDStsChg (DSTS=0x%08x, GOTCTL=%08x)\n",
-			readl(hsotg->regs + DSTS),
-			readl(hsotg->regs + GOTGCTL));
-
-		writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
-	}
-
-	if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {
-		u32 daint = readl(hsotg->regs + DAINT);
-		u32 daintmsk = readl(hsotg->regs + DAINTMSK);
-		u32 daint_out, daint_in;
-		int ep;
-
-		daint &= daintmsk;
-		daint_out = daint >> DAINT_OUTEP_SHIFT;
-		daint_in = daint & ~(daint_out << DAINT_OUTEP_SHIFT);
-
-		dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint);
-
-		for (ep = 0; ep < 15 && daint_out; ep++, daint_out >>= 1) {
-			if (daint_out & 1)
-				s3c_hsotg_epint(hsotg, ep, 0);
-		}
-
-		for (ep = 0; ep < 15 && daint_in; ep++, daint_in >>= 1) {
-			if (daint_in & 1)
-				s3c_hsotg_epint(hsotg, ep, 1);
-		}
-	}
-
-	if (gintsts & GINTSTS_USBRST) {
-
-		u32 usb_status = readl(hsotg->regs + GOTGCTL);
-
-		dev_info(hsotg->dev, "%s: USBRst\n", __func__);
-		dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
-			readl(hsotg->regs + GNPTXSTS));
-
-		writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
-
-		if (usb_status & GOTGCTL_BSESVLD) {
-			if (time_after(jiffies, hsotg->last_rst +
-				       msecs_to_jiffies(200))) {
-
-				kill_all_requests(hsotg, &hsotg->eps[0],
-							  -ECONNRESET, true);
-
-				s3c_hsotg_core_init(hsotg);
-				hsotg->last_rst = jiffies;
-			}
-		}
-	}
-
-	/* check both FIFOs */
-
-	if (gintsts & GINTSTS_NPTXFEMP) {
-		dev_dbg(hsotg->dev, "NPTxFEmp\n");
-
-		/*
-		 * Disable the interrupt to stop it happening again
-		 * unless one of these endpoint routines decides that
-		 * it needs re-enabling
-		 */
-
-		s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTXFEMP);
-		s3c_hsotg_irq_fifoempty(hsotg, false);
-	}
-
-	if (gintsts & GINTSTS_PTXFEMP) {
-		dev_dbg(hsotg->dev, "PTxFEmp\n");
-
-		/* See note in GINTSTS_NPTxFEmp */
-
-		s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTXFEMP);
-		s3c_hsotg_irq_fifoempty(hsotg, true);
-	}
-
-	if (gintsts & GINTSTS_RXFLVL) {
-		/*
-		 * note, since GINTSTS_RxFLvl doubles as FIFO-not-empty,
-		 * we need to retry s3c_hsotg_handle_rx if this is still
-		 * set.
-		 */
-
-		s3c_hsotg_handle_rx(hsotg);
-	}
-
-	if (gintsts & GINTSTS_MODEMIS) {
-		dev_warn(hsotg->dev, "warning, mode mismatch triggered\n");
-		writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
-	}
-
-	if (gintsts & GINTSTS_USBSUSP) {
-		dev_info(hsotg->dev, "GINTSTS_USBSusp\n");
-		writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
-
-		call_gadget(hsotg, suspend);
-	}
-
-	if (gintsts & GINTSTS_WKUPINT) {
-		dev_info(hsotg->dev, "GINTSTS_WkUpIn\n");
-		writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
-
-		call_gadget(hsotg, resume);
-	}
-
-	if (gintsts & GINTSTS_ERLYSUSP) {
-		dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n");
-		writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS);
-	}
-
-	/*
-	 * these next two seem to crop-up occasionally causing the core
-	 * to shutdown the USB transfer, so try clearing them and logging
-	 * the occurrence.
-	 */
-
-	if (gintsts & GINTSTS_GOUTNAKEFF) {
-		dev_info(hsotg->dev, "GOUTNakEff triggered\n");
-
-		writel(DCTL_CGOUTNAK, hsotg->regs + DCTL);
-
-		s3c_hsotg_dump(hsotg);
-	}
-
-	if (gintsts & GINTSTS_GINNAKEFF) {
-		dev_info(hsotg->dev, "GINNakEff triggered\n");
-
-		writel(DCTL_CGNPINNAK, hsotg->regs + DCTL);
-
-		s3c_hsotg_dump(hsotg);
-	}
-
-	/*
-	 * if we've had fifo events, we should try and go around the
-	 * loop again to see if there's any point in returning yet.
-	 */
-
-	if (gintsts & IRQ_RETRY_MASK && --retry_count > 0)
-			goto irq_retry;
-
-	spin_unlock(&hsotg->lock);
-
-	return IRQ_HANDLED;
-}
-
-/**
  * s3c_hsotg_ep_enable - enable the given endpoint
  * @ep: The USB endpint to configure
  * @desc: The USB endpoint descriptor to configure with.
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux