diff options
author | Roger Quadros <rogerq@ti.com> | 2018-02-12 08:30:08 -0500 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2018-02-15 08:28:35 -0500 |
commit | 98112041bcca164676367e261c8c1073ef70cb51 (patch) | |
tree | d2f247c984ac75e98738cf819d5edf2cba413c20 | |
parent | 8874ae5f15f3feef3b4a415b9aed51edcf449aa1 (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.c | 47 | ||||
-rw-r--r-- | 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 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 | ||
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 | |||
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) | |||
497 | static int dwc3_phy_setup(struct dwc3 *dwc) | 513 | static 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 | ||
729 | static int dwc3_core_get_phy(struct dwc3 *dwc); | 741 | static int dwc3_core_get_phy(struct dwc3 *dwc); |
742 | static 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 | ||
867 | err0a: | ||
868 | dwc3_ulpi_exit(dwc); | ||
869 | |||
844 | err0: | 870 | err0: |
845 | return ret; | 871 | return ret; |
846 | } | 872 | } |
@@ -1235,7 +1261,6 @@ err4: | |||
1235 | 1261 | ||
1236 | err3: | 1262 | err3: |
1237 | dwc3_free_event_buffers(dwc); | 1263 | dwc3_free_event_buffers(dwc); |
1238 | dwc3_ulpi_exit(dwc); | ||
1239 | 1264 | ||
1240 | err2: | 1265 | err2: |
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; |