usb: dwc3: core: Fix ULPI PHYs and prevent phy_get/ulpi_init during suspend/resume
commit 98112041bcca164676367e261c8c1073ef70cb51 upstream. 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> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
44e5d0b6ce
commit
685a452ce3
@ -511,6 +511,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
|
||||
@ -522,7 +538,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));
|
||||
|
||||
@ -593,9 +608,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;
|
||||
@ -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_ulpi_init(struct dwc3 *dwc);
|
||||
|
||||
/**
|
||||
* dwc3_core_init - Low-level initialization of DWC3 Core
|
||||
@ -783,18 +796,28 @@ static int dwc3_core_init(struct dwc3 *dwc)
|
||||
dwc->maximum_speed = USB_SPEED_HIGH;
|
||||
}
|
||||
|
||||
ret = dwc3_core_get_phy(dwc);
|
||||
if (ret)
|
||||
goto err0;
|
||||
|
||||
ret = dwc3_core_soft_reset(dwc);
|
||||
if (ret)
|
||||
goto err0;
|
||||
|
||||
ret = dwc3_phy_setup(dwc);
|
||||
if (ret)
|
||||
goto err0;
|
||||
|
||||
if (!dwc->ulpi_ready) {
|
||||
ret = dwc3_core_ulpi_init(dwc);
|
||||
if (ret)
|
||||
goto err0;
|
||||
dwc->ulpi_ready = true;
|
||||
}
|
||||
|
||||
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 err0a;
|
||||
|
||||
dwc3_core_setup_global_control(dwc);
|
||||
dwc3_core_num_eps(dwc);
|
||||
|
||||
@ -866,6 +889,9 @@ err1:
|
||||
phy_exit(dwc->usb2_generic_phy);
|
||||
phy_exit(dwc->usb3_generic_phy);
|
||||
|
||||
err0a:
|
||||
dwc3_ulpi_exit(dwc);
|
||||
|
||||
err0:
|
||||
return ret;
|
||||
}
|
||||
@ -1256,7 +1282,6 @@ err4:
|
||||
|
||||
err3:
|
||||
dwc3_free_event_buffers(dwc);
|
||||
dwc3_ulpi_exit(dwc);
|
||||
|
||||
err2:
|
||||
pm_runtime_allow(&pdev->dev);
|
||||
|
@ -805,7 +805,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
|
||||
* @isoch_delay: wValue from Set Isochronous Delay request;
|
||||
* @u2sel: parameter from Set SEL request.
|
||||
* @u2pel: parameter from Set SEL request.
|
||||
@ -903,7 +905,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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user