aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoger Quadros <rogerq@ti.com>2018-02-12 08:30:08 -0500
committerFelipe Balbi <felipe.balbi@linux.intel.com>2018-02-15 08:28:35 -0500
commit98112041bcca164676367e261c8c1073ef70cb51 (patch)
treed2f247c984ac75e98738cf819d5edf2cba413c20
parent8874ae5f15f3feef3b4a415b9aed51edcf449aa1 (diff)
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 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>
-rw-r--r--drivers/usb/dwc3/core.c47
-rw-r--r--drivers/usb/dwc3/core.h5
2 files changed, 41 insertions, 11 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 59511f2cd3ac..f1d838a4acd6 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)
486 parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 486 parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
487} 487}
488 488
489static 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
489/** 505/**
490 * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 506 * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
491 * @dwc: Pointer to our controller context structure 507 * @dwc: Pointer to our controller context structure
@@ -497,7 +513,6 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
497static int dwc3_phy_setup(struct dwc3 *dwc) 513static int dwc3_phy_setup(struct dwc3 *dwc)
498{ 514{
499 u32 reg; 515 u32 reg;
500 int ret;
501 516
502 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 517 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
503 518
@@ -568,9 +583,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
568 } 583 }
569 /* FALLTHROUGH */ 584 /* FALLTHROUGH */
570 case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 585 case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI:
571 ret = dwc3_ulpi_init(dwc);
572 if (ret)
573 return ret;
574 /* FALLTHROUGH */ 586 /* FALLTHROUGH */
575 default: 587 default:
576 break; 588 break;
@@ -727,6 +739,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
727} 739}
728 740
729static int dwc3_core_get_phy(struct dwc3 *dwc); 741static int dwc3_core_get_phy(struct dwc3 *dwc);
742static int dwc3_core_ulpi_init(struct dwc3 *dwc);
730 743
731/** 744/**
732 * dwc3_core_init - Low-level initialization of DWC3 Core 745 * dwc3_core_init - Low-level initialization of DWC3 Core
@@ -758,17 +771,27 @@ static int dwc3_core_init(struct dwc3 *dwc)
758 dwc->maximum_speed = USB_SPEED_HIGH; 771 dwc->maximum_speed = USB_SPEED_HIGH;
759 } 772 }
760 773
761 ret = dwc3_core_get_phy(dwc); 774 ret = dwc3_phy_setup(dwc);
762 if (ret) 775 if (ret)
763 goto err0; 776 goto err0;
764 777
765 ret = dwc3_core_soft_reset(dwc); 778 if (!dwc->ulpi_ready) {
766 if (ret) 779 ret = dwc3_core_ulpi_init(dwc);
767 goto err0; 780 if (ret)
781 goto err0;
782 dwc->ulpi_ready = true;
783 }
768 784
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);
770 if (ret) 793 if (ret)
771 goto err0; 794 goto err0a;
772 795
773 dwc3_core_setup_global_control(dwc); 796 dwc3_core_setup_global_control(dwc);
774 dwc3_core_num_eps(dwc); 797 dwc3_core_num_eps(dwc);
@@ -841,6 +864,9 @@ err1:
841 phy_exit(dwc->usb2_generic_phy); 864 phy_exit(dwc->usb2_generic_phy);
842 phy_exit(dwc->usb3_generic_phy); 865 phy_exit(dwc->usb3_generic_phy);
843 866
867err0a:
868 dwc3_ulpi_exit(dwc);
869
844err0: 870err0:
845 return ret; 871 return ret;
846} 872}
@@ -1235,7 +1261,6 @@ err4:
1235 1261
1236err3: 1262err3:
1237 dwc3_free_event_buffers(dwc); 1263 dwc3_free_event_buffers(dwc);
1238 dwc3_ulpi_exit(dwc);
1239 1264
1240err2: 1265err2:
1241 pm_runtime_allow(&pdev->dev); 1266 pm_runtime_allow(&pdev->dev);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 185b9603fd98..860d2bc184d1 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -797,7 +797,9 @@ struct dwc3_scratchpad_array {
797 * @usb3_phy: pointer to USB3 PHY 797 * @usb3_phy: pointer to USB3 PHY
798 * @usb2_generic_phy: pointer to USB2 PHY 798 * @usb2_generic_phy: pointer to USB2 PHY
799 * @usb3_generic_phy: pointer to USB3 PHY 799 * @usb3_generic_phy: pointer to USB3 PHY
800 * @phys_ready: flag to indicate that PHYs are ready
800 * @ulpi: pointer to ulpi interface 801 * @ulpi: pointer to ulpi interface
802 * @ulpi_ready: flag to indicate that ULPI is initialized
801 * @u2sel: parameter from Set SEL request. 803 * @u2sel: parameter from Set SEL request.
802 * @u2pel: parameter from Set SEL request. 804 * @u2pel: parameter from Set SEL request.
803 * @u1sel: parameter from Set SEL request. 805 * @u1sel: parameter from Set SEL request.
@@ -895,7 +897,10 @@ struct dwc3 {
895 struct phy *usb2_generic_phy; 897 struct phy *usb2_generic_phy;
896 struct phy *usb3_generic_phy; 898 struct phy *usb3_generic_phy;
897 899
900 bool phys_ready;
901
898 struct ulpi *ulpi; 902 struct ulpi *ulpi;
903 bool ulpi_ready;
899 904
900 void __iomem *regs; 905 void __iomem *regs;
901 size_t regs_size; 906 size_t regs_size;