usb: dwc3: Set SUSPENDENABLE soon after phy init

After phy initialization, some phy operations can only be executed while
in lower P states. Ensure GUSB3PIPECTL.SUSPENDENABLE and
GUSB2PHYCFG.SUSPHY are set soon after initialization to avoid blocking
phy ops.

Previously the SUSPENDENABLE bits are only set after the controller
initialization, which may not happen right away if there's no gadget
driver or xhci driver bound. Revise this to clear SUSPENDENABLE bits
only when there's mode switching (change in GCTL.PRTCAPDIR).

Fixes: 6d735722063a ("usb: dwc3: core: Prevent phy suspend during init")
Cc: stable <stable@kernel.org>
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/633aef0afee7d56d2316f7cc3e1b2a6d518a8cc9.1738280911.git.Thinh.Nguyen@synopsys.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by Thinh Nguyen and committed by Greg Kroah-Hartman cc5bfc4e 2b66ef84

+45 -30
+42 -27
drivers/usb/dwc3/core.c
··· 131 131 } 132 132 } 133 133 134 - void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) 134 + void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy) 135 135 { 136 + unsigned int hw_mode; 136 137 u32 reg; 137 138 138 139 reg = dwc3_readl(dwc->regs, DWC3_GCTL); 140 + 141 + /* 142 + * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE and 143 + * GUSB2PHYCFG.SUSPHY should be cleared during mode switching, 144 + * and they can be set after core initialization. 145 + */ 146 + hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); 147 + if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD && !ignore_susphy) { 148 + if (DWC3_GCTL_PRTCAP(reg) != mode) 149 + dwc3_enable_susphy(dwc, false); 150 + } 151 + 139 152 reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 140 153 reg |= DWC3_GCTL_PRTCAPDIR(mode); 141 154 dwc3_writel(dwc->regs, DWC3_GCTL, reg); ··· 229 216 230 217 spin_lock_irqsave(&dwc->lock, flags); 231 218 232 - dwc3_set_prtcap(dwc, desired_dr_role); 219 + dwc3_set_prtcap(dwc, desired_dr_role, false); 233 220 234 221 spin_unlock_irqrestore(&dwc->lock, flags); 235 222 ··· 671 658 */ 672 659 reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; 673 660 674 - /* 675 - * Above DWC_usb3.0 1.94a, it is recommended to set 676 - * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration. 677 - * So default value will be '0' when the core is reset. Application 678 - * needs to set it to '1' after the core initialization is completed. 679 - * 680 - * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be 681 - * cleared after power-on reset, and it can be set after core 682 - * initialization. 683 - */ 661 + /* Ensure the GUSB3PIPECTL.SUSPENDENABLE is cleared prior to phy init. */ 684 662 reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 685 663 686 664 if (dwc->u2ss_inp3_quirk) ··· 751 747 break; 752 748 } 753 749 754 - /* 755 - * Above DWC_usb3.0 1.94a, it is recommended to set 756 - * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration. 757 - * So default value will be '0' when the core is reset. Application 758 - * needs to set it to '1' after the core initialization is completed. 759 - * 760 - * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared 761 - * after power-on reset, and it can be set after core initialization. 762 - */ 750 + /* Ensure the GUSB2PHYCFG.SUSPHY is cleared prior to phy init. */ 763 751 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 764 752 765 753 if (dwc->dis_enblslpm_quirk) ··· 825 829 if (ret < 0) 826 830 goto err_exit_usb3_phy; 827 831 } 832 + 833 + /* 834 + * Above DWC_usb3.0 1.94a, it is recommended to set 835 + * DWC3_GUSB3PIPECTL_SUSPHY and DWC3_GUSB2PHYCFG_SUSPHY to '0' during 836 + * coreConsultant configuration. So default value will be '0' when the 837 + * core is reset. Application needs to set it to '1' after the core 838 + * initialization is completed. 839 + * 840 + * Certain phy requires to be in P0 power state during initialization. 841 + * Make sure GUSB3PIPECTL.SUSPENDENABLE and GUSB2PHYCFG.SUSPHY are clear 842 + * prior to phy init to maintain in the P0 state. 843 + * 844 + * After phy initialization, some phy operations can only be executed 845 + * while in lower P states. Ensure GUSB3PIPECTL.SUSPENDENABLE and 846 + * GUSB2PHYCFG.SUSPHY are set soon after initialization to avoid 847 + * blocking phy ops. 848 + */ 849 + if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) 850 + dwc3_enable_susphy(dwc, true); 828 851 829 852 return 0; 830 853 ··· 1603 1588 1604 1589 switch (dwc->dr_mode) { 1605 1590 case USB_DR_MODE_PERIPHERAL: 1606 - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); 1591 + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE, false); 1607 1592 1608 1593 if (dwc->usb2_phy) 1609 1594 otg_set_vbus(dwc->usb2_phy->otg, false); ··· 1615 1600 return dev_err_probe(dev, ret, "failed to initialize gadget\n"); 1616 1601 break; 1617 1602 case USB_DR_MODE_HOST: 1618 - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); 1603 + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST, false); 1619 1604 1620 1605 if (dwc->usb2_phy) 1621 1606 otg_set_vbus(dwc->usb2_phy->otg, true); ··· 1660 1645 } 1661 1646 1662 1647 /* de-assert DRVVBUS for HOST and OTG mode */ 1663 - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); 1648 + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE, true); 1664 1649 } 1665 1650 1666 1651 static void dwc3_get_software_properties(struct dwc3 *dwc) ··· 2468 2453 if (ret) 2469 2454 return ret; 2470 2455 2471 - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); 2456 + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE, true); 2472 2457 dwc3_gadget_resume(dwc); 2473 2458 break; 2474 2459 case DWC3_GCTL_PRTCAP_HOST: ··· 2476 2461 ret = dwc3_core_init_for_resume(dwc); 2477 2462 if (ret) 2478 2463 return ret; 2479 - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); 2464 + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST, true); 2480 2465 break; 2481 2466 } 2482 2467 /* Restore GUSB2PHYCFG bits that were modified in suspend */ ··· 2505 2490 if (ret) 2506 2491 return ret; 2507 2492 2508 - dwc3_set_prtcap(dwc, dwc->current_dr_role); 2493 + dwc3_set_prtcap(dwc, dwc->current_dr_role, true); 2509 2494 2510 2495 dwc3_otg_init(dwc); 2511 2496 if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) {
+1 -1
drivers/usb/dwc3/core.h
··· 1558 1558 #define DWC3_HAS_OTG BIT(3) 1559 1559 1560 1560 /* prototypes */ 1561 - void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode); 1561 + void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy); 1562 1562 void dwc3_set_mode(struct dwc3 *dwc, u32 mode); 1563 1563 u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type); 1564 1564
+2 -2
drivers/usb/dwc3/drd.c
··· 173 173 * block "Initialize GCTL for OTG operation". 174 174 */ 175 175 /* GCTL.PrtCapDir=2'b11 */ 176 - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG); 176 + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG, true); 177 177 /* GUSB2PHYCFG0.SusPHY=0 */ 178 178 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 179 179 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; ··· 556 556 557 557 dwc3_drd_update(dwc); 558 558 } else { 559 - dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG); 559 + dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG, true); 560 560 561 561 /* use OTG block to get ID event */ 562 562 irq = dwc3_otg_get_irq(dwc);