From d418b9a1df7e92e22646f72fd2f3b7515b4316ea Mon Sep 17 00:00:00 2001 From: Ajay Agarwal Date: Fri, 30 Aug 2019 14:11:00 +0530 Subject: [PATCH] usb: dwc3-msm: Try core reset and reinit if PHY PLL lock fails Add support for retrying core reset and re-initialization in host mode if the PHY PLL lock failure is seen. Also, increase the lock timeout to 50 msec. Change-Id: I8c8db60dcd73b7cf05598538d0c519b1b1e2417f Signed-off-by: Ajay Agarwal --- drivers/usb/dwc3/dwc3-msm.c | 22 +++++++++++++++++++++- drivers/usb/phy/phy-msm-qusb.c | 3 ++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 0650f0b69de7..7fec7b8e4dd9 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -276,6 +276,8 @@ struct dwc3_msm { struct mutex suspend_resume_mutex; enum usb_device_speed override_usb_speed; + + bool core_init_failed; }; #define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ @@ -1953,12 +1955,20 @@ static void dwc3_msm_power_collapse_por(struct dwc3_msm *mdwc) ret = dwc3_core_pre_init(dwc); if (ret) { dev_err(mdwc->dev, "dwc3_core_pre_init failed\n"); + mdwc->core_init_failed = true; return; } mdwc->init = true; } - dwc3_core_init(dwc); + ret = dwc3_core_init(dwc); + if (ret) { + dev_err(mdwc->dev, "dwc3_core_init failed\n"); + mdwc->core_init_failed = true; + return; + } + + mdwc->core_init_failed = false; /* Re-configure event buffers */ dwc3_event_buffers_setup(dwc); @@ -3602,6 +3612,12 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on) dev_dbg(mdwc->dev, "%s: turn on host\n", __func__); pm_runtime_get_sync(mdwc->dev); + if (mdwc->core_init_failed) { + dev_err(mdwc->dev, "%s: Core init failed\n", __func__); + pm_runtime_put_sync_suspend(mdwc->dev); + return -EAGAIN; + } + mdwc->hs_phy->flags |= PHY_HOST_MODE; if (dwc->maximum_speed == USB_SPEED_SUPER) { mdwc->ss_phy->flags |= PHY_HOST_MODE; @@ -4076,6 +4092,10 @@ static void dwc3_otg_sm_work(struct work_struct *w) delay = VBUS_REG_CHECK_DELAY; work = 1; mdwc->vbus_retry_count++; + } else if (ret == -EAGAIN) { + mdwc->drd_state = DRD_STATE_HOST_IDLE; + dev_dbg(mdwc->dev, "Core init failed. Retrying...\n"); + work = 1; } else if (ret) { dev_err(mdwc->dev, "unable to start host\n"); mdwc->drd_state = DRD_STATE_HOST_IDLE; diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c index ae72ec6b3d19..1b09c028d098 100644 --- a/drivers/usb/phy/phy-msm-qusb.c +++ b/drivers/usb/phy/phy-msm-qusb.c @@ -862,7 +862,7 @@ static int qusb_phy_init(struct usb_phy *phy) wmb(); /* Required to get PHY PLL lock successfully */ - usleep_range(100, 110); + usleep_range(50000, 51000); } if (qphy->major_rev < 2) { @@ -881,6 +881,7 @@ static int qusb_phy_init(struct usb_phy *phy) if (pll_lock_fail) { dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg); WARN_ON(1); + return -ETIMEDOUT; } return 0;