Message ID | ee73347b-e996-4052-6a9d-dd94edd4a61a@ti.com |
---|---|
State | Accepted |
Commit | 98112041bcca164676367e261c8c1073ef70cb51 |
Headers | show |
Series | [v2,RESEND] usb: dwc3: core: Fix ULPI PHYs and prevent phy_get/ulpi_init during suspend/resume | expand |
Hello, After I apply this patch on 4.14 (or receive it with 4.14.70) I see a regression with the Qualcomm QUSB2 phy driver. I'm testing on a Dragonboard 820c. In boot log I get: [ 4.525502] phy phy-7412000.phy.6: QUSB2PHY pll lock failed: status reg = 0 [ 4.529232] phy phy-7412000.phy.6: phy init failed --> -16 [ 4.536170] dwc3 7600000.dwc3: failed to initialize core [ 4.541743] dwc3: probe of 7600000.dwc3 failed with error -16 [ 4.549979] phy phy-7411000.phy.5: QUSB2PHY pll lock failed: status reg = 0 [ 4.552843] phy phy-7411000.phy.5: phy init failed --> -16 [ 4.559606] dwc3 6a00000.dwc3: failed to initialize core [ 4.565181] dwc3: probe of 6a00000.dwc3 failed with error -16 I can provide a full log if needed. Best regards, Todor On 12.02.2018 15:30, Roger Quadros wrote: > In order for ULPI PHYs to work, dwc3_phy_setup() and dwc3_ulpi_init() > must be doene before dwc3_core_get_phy(). > > commit 541768b08a40 ("usb: dwc3: core: Call dwc3_core_get_phy() before initializing phys") > broke this. > > The other issue is that dwc3_core_get_phy() and dwc3_ulpi_init() should > be called only once during the life cycle of the driver. However, > as dwc3_core_init() is called during system suspend/resume it will > result in multiple calls to dwc3_core_get_phy() and dwc3_ulpi_init() > which is wrong. > > Fix this by moving dwc3_ulpi_init() out of dwc3_phy_setup() > into dwc3_core_ulpi_init(). Use a flag 'ulpi_ready' to ensure that > dwc3_core_ulpi_init() is called only once from dwc3_core_init(). > > Use another flag 'phys_ready' to call dwc3_core_get_phy() only once from > dwc3_core_init(). > > Fixes: 541768b08a40 ("usb: dwc3: core: Call dwc3_core_get_phy() before initializing phys") > Fixes: f54edb539c11 ("usb: dwc3: core: initialize ULPI before trying to get the PHY") > Cc: linux-stable <stable@vger.kernel.org> # >= v4.13 > Signed-off-by: Roger Quadros <rogerq@ti.com> > --- > Rebased on Felipe's testing/fixes branch. > > drivers/usb/dwc3/core.c | 47 ++++++++++++++++++++++++++++++++++++----------- > drivers/usb/dwc3/core.h | 5 +++++ > 2 files changed, 41 insertions(+), 11 deletions(-) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > index 59511f2..f1d838a 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -486,6 +486,22 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) > parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); > } > > +static int dwc3_core_ulpi_init(struct dwc3 *dwc) > +{ > + int intf; > + int ret = 0; > + > + intf = DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3); > + > + if (intf == DWC3_GHWPARAMS3_HSPHY_IFC_ULPI || > + (intf == DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI && > + dwc->hsphy_interface && > + !strncmp(dwc->hsphy_interface, "ulpi", 4))) > + ret = dwc3_ulpi_init(dwc); > + > + return ret; > +} > + > /** > * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core > * @dwc: Pointer to our controller context structure > @@ -497,7 +513,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) > static int dwc3_phy_setup(struct dwc3 *dwc) > { > u32 reg; > - int ret; > > reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); > > @@ -568,9 +583,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc) > } > /* FALLTHROUGH */ > case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: > - ret = dwc3_ulpi_init(dwc); > - if (ret) > - return ret; > /* FALLTHROUGH */ > default: > break; > @@ -727,6 +739,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) > } > > static int dwc3_core_get_phy(struct dwc3 *dwc); > +static int dwc3_core_ulpi_init(struct dwc3 *dwc); > > /** > * dwc3_core_init - Low-level initialization of DWC3 Core > @@ -758,17 +771,27 @@ static int dwc3_core_init(struct dwc3 *dwc) > dwc->maximum_speed = USB_SPEED_HIGH; > } > > - ret = dwc3_core_get_phy(dwc); > + ret = dwc3_phy_setup(dwc); > if (ret) > goto err0; > > - ret = dwc3_core_soft_reset(dwc); > - if (ret) > - goto err0; > + if (!dwc->ulpi_ready) { > + ret = dwc3_core_ulpi_init(dwc); > + if (ret) > + goto err0; > + dwc->ulpi_ready = true; > + } > > - ret = dwc3_phy_setup(dwc); > + if (!dwc->phys_ready) { > + ret = dwc3_core_get_phy(dwc); > + if (ret) > + goto err0a; > + dwc->phys_ready = true; > + } > + > + ret = dwc3_core_soft_reset(dwc); > if (ret) > - goto err0; > + goto err0a; > > dwc3_core_setup_global_control(dwc); > dwc3_core_num_eps(dwc); > @@ -841,6 +864,9 @@ static int dwc3_core_init(struct dwc3 *dwc) > phy_exit(dwc->usb2_generic_phy); > phy_exit(dwc->usb3_generic_phy); > > +err0a: > + dwc3_ulpi_exit(dwc); > + > err0: > return ret; > } > @@ -1235,7 +1261,6 @@ static int dwc3_probe(struct platform_device *pdev) > > err3: > dwc3_free_event_buffers(dwc); > - dwc3_ulpi_exit(dwc); > > err2: > pm_runtime_allow(&pdev->dev); > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h > index 185b960..860d2bc 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -797,7 +797,9 @@ struct dwc3_scratchpad_array { > * @usb3_phy: pointer to USB3 PHY > * @usb2_generic_phy: pointer to USB2 PHY > * @usb3_generic_phy: pointer to USB3 PHY > + * @phys_ready: flag to indicate that PHYs are ready > * @ulpi: pointer to ulpi interface > + * @ulpi_ready: flag to indicate that ULPI is initialized > * @u2sel: parameter from Set SEL request. > * @u2pel: parameter from Set SEL request. > * @u1sel: parameter from Set SEL request. > @@ -895,7 +897,10 @@ struct dwc3 { > struct phy *usb2_generic_phy; > struct phy *usb3_generic_phy; > > + bool phys_ready; > + > struct ulpi *ulpi; > + bool ulpi_ready; > > void __iomem *regs; > size_t regs_size; >
Hi, On 15.11.2018 10:09, Felipe Balbi wrote: > > Hi, > > Todor Tomov <todor.tomov@linaro.org> writes: > >> Hello, >> >> After I apply this patch on 4.14 (or receive it with 4.14.70) I see a regression with >> the Qualcomm QUSB2 phy driver. I'm testing on a Dragonboard 820c. >> In boot log I get: >> >> [ 4.525502] phy phy-7412000.phy.6: QUSB2PHY pll lock failed: status reg = 0 >> [ 4.529232] phy phy-7412000.phy.6: phy init failed --> -16 >> [ 4.536170] dwc3 7600000.dwc3: failed to initialize core >> [ 4.541743] dwc3: probe of 7600000.dwc3 failed with error -16 >> [ 4.549979] phy phy-7411000.phy.5: QUSB2PHY pll lock failed: status reg = 0 >> [ 4.552843] phy phy-7411000.phy.5: phy init failed --> -16 >> [ 4.559606] dwc3 6a00000.dwc3: failed to initialize core >> [ 4.565181] dwc3: probe of 6a00000.dwc3 failed with error -16 >> >> I can provide a full log if needed. > > please do. Also, try mainline and let us know if the problem This is the full log on 4.14.69 + this patch: https://paste.ubuntu.com/p/N5WdHw47QC/ I also managed to get a log from 4.20.0-rc2 and I see the same error: https://paste.ubuntu.com/p/jz6fvYyZh6/ > persists. Why do you get -EBUSY from the PHY driver? Maybe I could have proposed a fix if I knew but I don't know. Best regards, Todor > > - > balbi >
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 59511f2..f1d838a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -486,6 +486,22 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); } +static int dwc3_core_ulpi_init(struct dwc3 *dwc) +{ + int intf; + int ret = 0; + + intf = DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3); + + if (intf == DWC3_GHWPARAMS3_HSPHY_IFC_ULPI || + (intf == DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI && + dwc->hsphy_interface && + !strncmp(dwc->hsphy_interface, "ulpi", 4))) + ret = dwc3_ulpi_init(dwc); + + return ret; +} + /** * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core * @dwc: Pointer to our controller context structure @@ -497,7 +513,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) static int dwc3_phy_setup(struct dwc3 *dwc) { u32 reg; - int ret; reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); @@ -568,9 +583,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc) } /* FALLTHROUGH */ case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: - ret = dwc3_ulpi_init(dwc); - if (ret) - return ret; /* FALLTHROUGH */ default: break; @@ -727,6 +739,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) } static int dwc3_core_get_phy(struct dwc3 *dwc); +static int dwc3_core_ulpi_init(struct dwc3 *dwc); /** * dwc3_core_init - Low-level initialization of DWC3 Core @@ -758,17 +771,27 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc->maximum_speed = USB_SPEED_HIGH; } - ret = dwc3_core_get_phy(dwc); + ret = dwc3_phy_setup(dwc); if (ret) goto err0; - ret = dwc3_core_soft_reset(dwc); - if (ret) - goto err0; + if (!dwc->ulpi_ready) { + ret = dwc3_core_ulpi_init(dwc); + if (ret) + goto err0; + dwc->ulpi_ready = true; + } - ret = dwc3_phy_setup(dwc); + if (!dwc->phys_ready) { + ret = dwc3_core_get_phy(dwc); + if (ret) + goto err0a; + dwc->phys_ready = true; + } + + ret = dwc3_core_soft_reset(dwc); if (ret) - goto err0; + goto err0a; dwc3_core_setup_global_control(dwc); dwc3_core_num_eps(dwc); @@ -841,6 +864,9 @@ static int dwc3_core_init(struct dwc3 *dwc) phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb3_generic_phy); +err0a: + dwc3_ulpi_exit(dwc); + err0: return ret; } @@ -1235,7 +1261,6 @@ static int dwc3_probe(struct platform_device *pdev) err3: dwc3_free_event_buffers(dwc); - dwc3_ulpi_exit(dwc); err2: pm_runtime_allow(&pdev->dev); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 185b960..860d2bc 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -797,7 +797,9 @@ struct dwc3_scratchpad_array { * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY * @usb3_generic_phy: pointer to USB3 PHY + * @phys_ready: flag to indicate that PHYs are ready * @ulpi: pointer to ulpi interface + * @ulpi_ready: flag to indicate that ULPI is initialized * @u2sel: parameter from Set SEL request. * @u2pel: parameter from Set SEL request. * @u1sel: parameter from Set SEL request. @@ -895,7 +897,10 @@ struct dwc3 { struct phy *usb2_generic_phy; struct phy *usb3_generic_phy; + bool phys_ready; + struct ulpi *ulpi; + bool ulpi_ready; void __iomem *regs; size_t regs_size;
In order for ULPI PHYs to work, dwc3_phy_setup() and dwc3_ulpi_init() must be doene before dwc3_core_get_phy(). commit 541768b08a40 ("usb: dwc3: core: Call dwc3_core_get_phy() before initializing phys") broke this. The other issue is that dwc3_core_get_phy() and dwc3_ulpi_init() should be called only once during the life cycle of the driver. However, as dwc3_core_init() is called during system suspend/resume it will result in multiple calls to dwc3_core_get_phy() and dwc3_ulpi_init() which is wrong. Fix this by moving dwc3_ulpi_init() out of dwc3_phy_setup() into dwc3_core_ulpi_init(). Use a flag 'ulpi_ready' to ensure that dwc3_core_ulpi_init() is called only once from dwc3_core_init(). Use another flag 'phys_ready' to call dwc3_core_get_phy() only once from dwc3_core_init(). Fixes: 541768b08a40 ("usb: dwc3: core: Call dwc3_core_get_phy() before initializing phys") Fixes: f54edb539c11 ("usb: dwc3: core: initialize ULPI before trying to get the PHY") Cc: linux-stable <stable@vger.kernel.org> # >= v4.13 Signed-off-by: Roger Quadros <rogerq@ti.com> --- Rebased on Felipe's testing/fixes branch. drivers/usb/dwc3/core.c | 47 ++++++++++++++++++++++++++++++++++++----------- drivers/usb/dwc3/core.h | 5 +++++ 2 files changed, 41 insertions(+), 11 deletions(-) -- cheers, -roger Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki