From: Chuanhong Guo <gch981213@gmail.com>
Date: Tue, 10 Sep 2024 09:10:27 +0800
Subject: [PATCH 12/20] usb: dwc2: handle OTG interrupt regardless of GINTSTS

The DWC OTG 3.30a found on Siflower SF19A2890 has battery charger
support enabled. It triggers MultVallpChng interrupt (bit 20 of
GOTGINT) but doesn't set OTGInt in GINTSTS. As a result, this
interrupt is never handled, and linux disables USB interrupt
because "nobody cares".

Handle OTG interrupt in IRQ handler regardless of whether the
OTGInt bit in GINTSTS is set or not.

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
---
 drivers/usb/dwc2/core_intr.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -79,7 +79,7 @@ static void dwc2_handle_mode_mismatch_in
  *
  * @hsotg: Programming view of DWC_otg controller
  */
-static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
+static irqreturn_t dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
 {
 	u32 gotgint;
 	u32 gotgctl;
@@ -88,6 +88,10 @@ static void dwc2_handle_otg_intr(struct
 
 	gotgint = dwc2_readl(hsotg, GOTGINT);
 	gotgctl = dwc2_readl(hsotg, GOTGCTL);
+
+	if (!gotgint)
+		return IRQ_NONE;
+
 	dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
 		dwc2_op_state_str(hsotg));
 
@@ -244,6 +248,7 @@ static void dwc2_handle_otg_intr(struct
 
 	/* Clear GOTGINT */
 	dwc2_writel(hsotg, gotgint, GOTGINT);
+	return IRQ_HANDLED;
 }
 
 /**
@@ -862,6 +867,8 @@ irqreturn_t dwc2_handle_common_intr(int
 		hsotg->frame_number = (dwc2_readl(hsotg, HFNUM)
 				       & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT;
 
+	retval = dwc2_handle_otg_intr(hsotg);
+
 	gintsts = dwc2_read_common_intr(hsotg);
 	if (gintsts & ~GINTSTS_PRTINT)
 		retval = IRQ_HANDLED;
@@ -875,8 +882,6 @@ irqreturn_t dwc2_handle_common_intr(int
 
 	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_DISCONNINT)
