Commit 685a452c authored by Roger Quadros's avatar Roger Quadros Committed by Greg Kroah-Hartman

usb: dwc3: core: Fix ULPI PHYs and prevent phy_get/ulpi_init during suspend/resume

commit 98112041 upstream.

In order for ULPI PHYs to work, dwc3_phy_setup() and dwc3_ulpi_init()
must be doene before dwc3_core_get_phy().

commit 541768b0 ("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: 541768b0 ("usb: dwc3: core: Call dwc3_core_get_phy() before initializing phys")
Fixes: f54edb53 ("usb: dwc3: core: initialize ULPI before trying to get the PHY")
Cc: linux-stable <stable@vger.kernel.org> # >= v4.13
Signed-off-by: default avatarRoger Quadros <rogerq@ti.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
Signed-off-by: default avatarSudip Mukherjee <sudipm.mukherjee@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 44e5d0b6
...@@ -511,6 +511,22 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) ...@@ -511,6 +511,22 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 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 * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
* @dwc: Pointer to our controller context structure * @dwc: Pointer to our controller context structure
...@@ -522,7 +538,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) ...@@ -522,7 +538,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
static int dwc3_phy_setup(struct dwc3 *dwc) static int dwc3_phy_setup(struct dwc3 *dwc)
{ {
u32 reg; u32 reg;
int ret;
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
...@@ -593,9 +608,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc) ...@@ -593,9 +608,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
ret = dwc3_ulpi_init(dwc);
if (ret)
return ret;
/* FALLTHROUGH */ /* FALLTHROUGH */
default: default:
break; break;
...@@ -752,6 +764,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) ...@@ -752,6 +764,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
} }
static int dwc3_core_get_phy(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 * dwc3_core_init - Low-level initialization of DWC3 Core
...@@ -783,17 +796,27 @@ static int dwc3_core_init(struct dwc3 *dwc) ...@@ -783,17 +796,27 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc->maximum_speed = USB_SPEED_HIGH; dwc->maximum_speed = USB_SPEED_HIGH;
} }
ret = dwc3_core_get_phy(dwc); ret = dwc3_phy_setup(dwc);
if (ret) if (ret)
goto err0; goto err0;
ret = dwc3_core_soft_reset(dwc); if (!dwc->ulpi_ready) {
if (ret) ret = dwc3_core_ulpi_init(dwc);
goto err0; 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) if (ret)
goto err0; goto err0a;
dwc3_core_setup_global_control(dwc); dwc3_core_setup_global_control(dwc);
dwc3_core_num_eps(dwc); dwc3_core_num_eps(dwc);
...@@ -866,6 +889,9 @@ static int dwc3_core_init(struct dwc3 *dwc) ...@@ -866,6 +889,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb2_generic_phy);
phy_exit(dwc->usb3_generic_phy); phy_exit(dwc->usb3_generic_phy);
err0a:
dwc3_ulpi_exit(dwc);
err0: err0:
return ret; return ret;
} }
...@@ -1256,7 +1282,6 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -1256,7 +1282,6 @@ static int dwc3_probe(struct platform_device *pdev)
err3: err3:
dwc3_free_event_buffers(dwc); dwc3_free_event_buffers(dwc);
dwc3_ulpi_exit(dwc);
err2: err2:
pm_runtime_allow(&pdev->dev); pm_runtime_allow(&pdev->dev);
......
...@@ -805,7 +805,9 @@ struct dwc3_scratchpad_array { ...@@ -805,7 +805,9 @@ struct dwc3_scratchpad_array {
* @usb3_phy: pointer to USB3 PHY * @usb3_phy: pointer to USB3 PHY
* @usb2_generic_phy: pointer to USB2 PHY * @usb2_generic_phy: pointer to USB2 PHY
* @usb3_generic_phy: pointer to USB3 PHY * @usb3_generic_phy: pointer to USB3 PHY
* @phys_ready: flag to indicate that PHYs are ready
* @ulpi: pointer to ulpi interface * @ulpi: pointer to ulpi interface
* @ulpi_ready: flag to indicate that ULPI is initialized
* @isoch_delay: wValue from Set Isochronous Delay request; * @isoch_delay: wValue from Set Isochronous Delay request;
* @u2sel: parameter from Set SEL request. * @u2sel: parameter from Set SEL request.
* @u2pel: parameter from Set SEL request. * @u2pel: parameter from Set SEL request.
...@@ -903,7 +905,10 @@ struct dwc3 { ...@@ -903,7 +905,10 @@ struct dwc3 {
struct phy *usb2_generic_phy; struct phy *usb2_generic_phy;
struct phy *usb3_generic_phy; struct phy *usb3_generic_phy;
bool phys_ready;
struct ulpi *ulpi; struct ulpi *ulpi;
bool ulpi_ready;
void __iomem *regs; void __iomem *regs;
size_t regs_size; size_t regs_size;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment