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

Commit ec396ea6 authored by Manu Gautam's avatar Manu Gautam Committed by Hemant Kumar
Browse files

usb: dwc3-msm: Ensure hardware is reset during role change



Introduce additional WAIT_FOR_LPM input flag to ensure USB
enters low power mode after stop_peripheral or stop_host.
This makes sure that USB hardware is reset after LPM for
cases where quick transition to host mode happens while
its child was still preventing dwc3 to enter low power mode.
In the absence of h/w reset after stop_peripheral, host mode
doesn't work.

Change-Id: I67e4fcdc11a3337e3e90b4ca8f461e328a6e8ecf
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
parent 532c8014
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -223,6 +223,7 @@ struct extcon_nb {
#define ID			0
#define B_SESS_VLD		1
#define B_SUSPEND		2
#define WAIT_FOR_LPM		3

#define PM_QOS_SAMPLE_SEC	2
#define PM_QOS_THRESHOLD	400
@@ -2477,7 +2478,13 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse)

	dev_info(mdwc->dev, "DWC3 in low power mode\n");
	dbg_event(0xFF, "Ctl Sus", atomic_read(&dwc->in_lpm));

	/* kick_sm if it is waiting for lpm sequence to finish */
	if (test_and_clear_bit(WAIT_FOR_LPM, &mdwc->inputs))
		queue_delayed_work(mdwc->sm_usb_wq, &mdwc->sm_work, 0);

	mutex_unlock(&mdwc->suspend_resume_mutex);

	return 0;
}

@@ -4023,6 +4030,9 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
		dwc3_usb3_phy_suspend(dwc, false);
		mdwc->in_host_mode = false;

		/* wait for LPM, to ensure h/w is reset after stop_host */
		set_bit(WAIT_FOR_LPM, &mdwc->inputs);

		pm_runtime_put_sync_suspend(mdwc->dev);
		dbg_event(0xFF, "StopHost psync",
			atomic_read(&mdwc->dev->power.usage_count));
@@ -4119,6 +4129,9 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
		usb_phy_notify_disconnect(mdwc->ss_phy, USB_SPEED_SUPER);
		dwc3_override_vbus_status(mdwc, false);
		dwc3_usb3_phy_suspend(dwc, false);

		/* wait for LPM, to ensure h/w is reset after stop_peripheral */
		set_bit(WAIT_FOR_LPM, &mdwc->inputs);
	}

	pm_runtime_put_sync(mdwc->dev);
@@ -4278,6 +4291,11 @@ static void dwc3_otg_sm_work(struct work_struct *w)
		pm_runtime_enable(mdwc->dev);
		/* fall-through */
	case DRD_STATE_IDLE:
		if (test_bit(WAIT_FOR_LPM, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "still not in lpm, wait.\n");
			break;
		}

		if (!test_bit(ID, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "!id\n");
			mdwc->drd_state = DRD_STATE_HOST_IDLE;