[PATCH v2 RESEND] usb: dwc3: core: Fix ULPI PHYs and prevent phy_get/ulpi_init during suspend/resume

2018-02-12 Thread Roger Quadros
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  # >= v4.13
Signed-off-by: Roger Quadros 
---
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(>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  

[PATCH v2 RESEND] usb: dwc3: core: Fix ULPI PHYs and prevent phy_get/ulpi_init during suspend/resume

2018-02-12 Thread Roger Quadros
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  # >= v4.13
Signed-off-by: Roger Quadros 
---
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(>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