Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49c45e0b authored by Jack Pham's avatar Jack Pham
Browse files

usb: dwc3: gadget: Clear pending events when stopping controller



Just prior to stopping the controller, we may have issued stop
transfer commands to any endpoints with any pending transfers.
This will result in EP Command Complete events being generated.
However, as per the Databook, the controller will not assert the
halt status bit after clearing the run/stop bit if there are any
pending events in the GEVNTCOUNT(n) registers, so this results
in a timeout error. Fix this by simply clearing GEVNTCOUNT(n)
by reading and writing back the counts.

Change-Id: I2fd0b161b08048072aa7fcea8c636662bcd76bd4
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 46a8ee9f
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -855,8 +855,9 @@ struct dwc3_scratchpad_array {
#define DWC3_GSI_EVT_BUF_ALLOC			10
#define DWC3_GSI_EVT_BUF_SETUP			11
#define DWC3_GSI_EVT_BUF_CLEANUP		12
#define DWC3_GSI_EVT_BUF_FREE			13
#define DWC3_CONTROLLER_NOTIFY_CLEAR_DB		14
#define DWC3_GSI_EVT_BUF_CLEAR			13
#define DWC3_GSI_EVT_BUF_FREE			14
#define DWC3_CONTROLLER_NOTIFY_CLEAR_DB		15

#define MAX_INTR_STATS				10

+9 −0
Original line number Diff line number Diff line
@@ -2002,6 +2002,15 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), 0);
		}
		break;
	case DWC3_GSI_EVT_BUF_CLEAR:
		dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_CLEAR\n");
		for (i = 0; i < mdwc->num_gsi_event_buffers; i++) {
			reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT((i+1)));
			reg &= DWC3_GEVNTCOUNT_MASK;
			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), reg);
			dbg_log_string("remaining EVNTCOUNT(%d)=%d", i+1, reg);
		}
		break;
	case DWC3_GSI_EVT_BUF_FREE:
		dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_FREE\n");
		if (!mdwc->gsi_ev_buff)
+10 −0
Original line number Diff line number Diff line
@@ -2098,6 +2098,16 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
		 */
		dwc3_stop_active_transfers(dwc);

		/*
		 * Clear out any pending events (i.e. End Transfer Command
		 * Complete) before clearing run/stop
		 */
		reg1 = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
		reg1 &= DWC3_GEVNTCOUNT_MASK;
		dbg_log_string("remaining EVNTCOUNT(0)=%d", reg1);
		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg1);
		dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEAR, 0);

		reg &= ~DWC3_DCTL_RUN_STOP;

		if (dwc->has_hibernation && !suspend)