Skip to content

Commit 9811204

Browse files
Roger QuadrosFelipe Balbi
authored andcommitted
usb: dwc3: core: Fix ULPI PHYs and prevent phy_get/ulpi_init during suspend/resume
In order for ULPI PHYs to work, dwc3_phy_setup() and dwc3_ulpi_init() must be doene before dwc3_core_get_phy(). commit 541768b ("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: 541768b ("usb: dwc3: core: Call dwc3_core_get_phy() before initializing phys") Fixes: f54edb5 ("usb: dwc3: core: initialize ULPI before trying to get the PHY") Cc: linux-stable <[email protected]> # >= v4.13 Signed-off-by: Roger Quadros <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent 8874ae5 commit 9811204

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

drivers/usb/dwc3/core.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,22 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
486486
parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
487487
}
488488

489+
static int dwc3_core_ulpi_init(struct dwc3 *dwc)
490+
{
491+
int intf;
492+
int ret = 0;
493+
494+
intf = DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3);
495+
496+
if (intf == DWC3_GHWPARAMS3_HSPHY_IFC_ULPI ||
497+
(intf == DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI &&
498+
dwc->hsphy_interface &&
499+
!strncmp(dwc->hsphy_interface, "ulpi", 4)))
500+
ret = dwc3_ulpi_init(dwc);
501+
502+
return ret;
503+
}
504+
489505
/**
490506
* dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
491507
* @dwc: Pointer to our controller context structure
@@ -497,7 +513,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
497513
static int dwc3_phy_setup(struct dwc3 *dwc)
498514
{
499515
u32 reg;
500-
int ret;
501516

502517
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
503518

@@ -568,9 +583,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
568583
}
569584
/* FALLTHROUGH */
570585
case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
571-
ret = dwc3_ulpi_init(dwc);
572-
if (ret)
573-
return ret;
574586
/* FALLTHROUGH */
575587
default:
576588
break;
@@ -727,6 +739,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
727739
}
728740

729741
static int dwc3_core_get_phy(struct dwc3 *dwc);
742+
static int dwc3_core_ulpi_init(struct dwc3 *dwc);
730743

731744
/**
732745
* dwc3_core_init - Low-level initialization of DWC3 Core
@@ -758,17 +771,27 @@ static int dwc3_core_init(struct dwc3 *dwc)
758771
dwc->maximum_speed = USB_SPEED_HIGH;
759772
}
760773

761-
ret = dwc3_core_get_phy(dwc);
774+
ret = dwc3_phy_setup(dwc);
762775
if (ret)
763776
goto err0;
764777

765-
ret = dwc3_core_soft_reset(dwc);
766-
if (ret)
767-
goto err0;
778+
if (!dwc->ulpi_ready) {
779+
ret = dwc3_core_ulpi_init(dwc);
780+
if (ret)
781+
goto err0;
782+
dwc->ulpi_ready = true;
783+
}
768784

769-
ret = dwc3_phy_setup(dwc);
785+
if (!dwc->phys_ready) {
786+
ret = dwc3_core_get_phy(dwc);
787+
if (ret)
788+
goto err0a;
789+
dwc->phys_ready = true;
790+
}
791+
792+
ret = dwc3_core_soft_reset(dwc);
770793
if (ret)
771-
goto err0;
794+
goto err0a;
772795

773796
dwc3_core_setup_global_control(dwc);
774797
dwc3_core_num_eps(dwc);
@@ -841,6 +864,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
841864
phy_exit(dwc->usb2_generic_phy);
842865
phy_exit(dwc->usb3_generic_phy);
843866

867+
err0a:
868+
dwc3_ulpi_exit(dwc);
869+
844870
err0:
845871
return ret;
846872
}
@@ -1235,7 +1261,6 @@ static int dwc3_probe(struct platform_device *pdev)
12351261

12361262
err3:
12371263
dwc3_free_event_buffers(dwc);
1238-
dwc3_ulpi_exit(dwc);
12391264

12401265
err2:
12411266
pm_runtime_allow(&pdev->dev);

drivers/usb/dwc3/core.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,9 @@ struct dwc3_scratchpad_array {
797797
* @usb3_phy: pointer to USB3 PHY
798798
* @usb2_generic_phy: pointer to USB2 PHY
799799
* @usb3_generic_phy: pointer to USB3 PHY
800+
* @phys_ready: flag to indicate that PHYs are ready
800801
* @ulpi: pointer to ulpi interface
802+
* @ulpi_ready: flag to indicate that ULPI is initialized
801803
* @u2sel: parameter from Set SEL request.
802804
* @u2pel: parameter from Set SEL request.
803805
* @u1sel: parameter from Set SEL request.
@@ -895,7 +897,10 @@ struct dwc3 {
895897
struct phy *usb2_generic_phy;
896898
struct phy *usb3_generic_phy;
897899

900+
bool phys_ready;
901+
898902
struct ulpi *ulpi;
903+
bool ulpi_ready;
899904

900905
void __iomem *regs;
901906
size_t regs_size;

0 commit comments

Comments
 (0)