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: Manu Gautam <mgautam@codeaurora.org>
This commit is contained in:
Manu Gautam 2018-12-03 14:38:23 +05:30
parent 582ce26ce1
commit 7d34ffa6c3

View file

@ -174,6 +174,7 @@ enum plug_orientation {
#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
@ -2214,7 +2215,13 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool hibernation)
}
dev_info(mdwc->dev, "DWC3 in low power mode\n");
/* kick_sm if it is waiting for lpm sequence to finish */
if (test_and_clear_bit(WAIT_FOR_LPM, &mdwc->inputs))
schedule_delayed_work(&mdwc->sm_work, 0);
mutex_unlock(&mdwc->suspend_resume_mutex);
return 0;
}
@ -3724,6 +3731,9 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
if (!mdwc->host_only_mode)
dwc3_post_host_reset_core_init(dwc);
/* wait for LPM, to ensure h/w is reset after stop_host */
set_bit(WAIT_FOR_LPM, &mdwc->inputs);
pm_runtime_mark_last_busy(mdwc->dev);
pm_runtime_put_sync_autosuspend(mdwc->dev);
dbg_event(0xFF, "StopHost psync",
@ -3804,6 +3814,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);
@ -3920,6 +3933,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;