Skip to content

Commit 685a452

Browse files
Roger Quadrosgregkh
authored andcommitted
usb: dwc3: core: Fix ULPI PHYs and prevent phy_get/ulpi_init during suspend/resume
commit 9811204 upstream. 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]> Signed-off-by: Sudip Mukherjee <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 44e5d0b commit 685a452

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
@@ -511,6 +511,22 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
511511
parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
512512
}
513513

514+
static int dwc3_core_ulpi_init(struct dwc3 *dwc)
515+
{
516+
int intf;
517+
int ret = 0;
518+
519+
intf = DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3);
520+
521+
if (intf == DWC3_GHWPARAMS3_HSPHY_IFC_ULPI ||
522+
(intf == DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI &&
523+
dwc->hsphy_interface &&
524+
!strncmp(dwc->hsphy_interface, "ulpi", 4)))
525+
ret = dwc3_ulpi_init(dwc);
526+
527+
return ret;
528+
}
529+
514530
/**
515531
* dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
516532
* @dwc: Pointer to our controller context structure
@@ -522,7 +538,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
522538
static int dwc3_phy_setup(struct dwc3 *dwc)
523539
{
524540
u32 reg;
525-
int ret;
526541

527542
reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
528543

@@ -593,9 +608,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
593608
}
594609
/* FALLTHROUGH */
595610
case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
596-
ret = dwc3_ulpi_init(dwc);
597-
if (ret)
598-
return ret;
599611
/* FALLTHROUGH */
600612
default:
601613
break;
@@ -752,6 +764,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
752764
}
753765

754766
static int dwc3_core_get_phy(struct dwc3 *dwc);
767+
static int dwc3_core_ulpi_init(struct dwc3 *dwc);
755768

756769
/**
757770
* dwc3_core_init - Low-level initialization of DWC3 Core
@@ -783,17 +796,27 @@ static int dwc3_core_init(struct dwc3 *dwc)
783796
dwc->maximum_speed = USB_SPEED_HIGH;
784797
}
785798

786-
ret = dwc3_core_get_phy(dwc);
799+
ret = dwc3_phy_setup(dwc);
787800
if (ret)
788801
goto err0;
789802

790-
ret = dwc3_core_soft_reset(dwc);
791-
if (ret)
792-
goto err0;
803+
if (!dwc->ulpi_ready) {
804+
ret = dwc3_core_ulpi_init(dwc);
805+
if (ret)
806+
goto err0;
807+
dwc->ulpi_ready = true;
808+
}
793809

794-
ret = dwc3_phy_setup(dwc);
810+
if (!dwc->phys_ready) {
811+
ret = dwc3_core_get_phy(dwc);
812+
if (ret)
813+
goto err0a;
814+
dwc->phys_ready = true;
815+
}
816+
817+
ret = dwc3_core_soft_reset(dwc);
795818
if (ret)
796-
goto err0;
819+
goto err0a;
797820

798821
dwc3_core_setup_global_control(dwc);
799822
dwc3_core_num_eps(dwc);
@@ -866,6 +889,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
866889
phy_exit(dwc->usb2_generic_phy);
867890
phy_exit(dwc->usb3_generic_phy);
868891

892+
err0a:
893+
dwc3_ulpi_exit(dwc);
894+
869895
err0:
870896
return ret;
871897
}
@@ -1256,7 +1282,6 @@ static int dwc3_probe(struct platform_device *pdev)
12561282

12571283
err3:
12581284
dwc3_free_event_buffers(dwc);
1259-
dwc3_ulpi_exit(dwc);
12601285

12611286
err2:
12621287
pm_runtime_allow(&pdev->dev);

drivers/usb/dwc3/core.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,9 @@ struct dwc3_scratchpad_array {
805805
* @usb3_phy: pointer to USB3 PHY
806806
* @usb2_generic_phy: pointer to USB2 PHY
807807
* @usb3_generic_phy: pointer to USB3 PHY
808+
* @phys_ready: flag to indicate that PHYs are ready
808809
* @ulpi: pointer to ulpi interface
810+
* @ulpi_ready: flag to indicate that ULPI is initialized
809811
* @isoch_delay: wValue from Set Isochronous Delay request;
810812
* @u2sel: parameter from Set SEL request.
811813
* @u2pel: parameter from Set SEL request.
@@ -903,7 +905,10 @@ struct dwc3 {
903905
struct phy *usb2_generic_phy;
904906
struct phy *usb3_generic_phy;
905907

908+
bool phys_ready;
909+
906910
struct ulpi *ulpi;
911+
bool ulpi_ready;
907912

908913
void __iomem *regs;
909914
size_t regs_size;

0 commit comments

Comments
 (0)