@@ -131,11 +131,24 @@ void dwc3_enable_susphy(struct dwc3 *dwc, bool enable)
131131 }
132132}
133133
134- void dwc3_set_prtcap (struct dwc3 * dwc , u32 mode )
134+ void dwc3_set_prtcap (struct dwc3 * dwc , u32 mode , bool ignore_susphy )
135135{
136+ unsigned int hw_mode ;
136137 u32 reg ;
137138
138139 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+
139152 reg &= ~(DWC3_GCTL_PRTCAPDIR (DWC3_GCTL_PRTCAP_OTG ));
140153 reg |= DWC3_GCTL_PRTCAPDIR (mode );
141154 dwc3_writel (dwc -> regs , DWC3_GCTL , reg );
@@ -216,7 +229,7 @@ static void __dwc3_set_mode(struct work_struct *work)
216229
217230 spin_lock_irqsave (& dwc -> lock , flags );
218231
219- dwc3_set_prtcap (dwc , desired_dr_role );
232+ dwc3_set_prtcap (dwc , desired_dr_role , false );
220233
221234 spin_unlock_irqrestore (& dwc -> lock , flags );
222235
@@ -658,16 +671,7 @@ static int dwc3_ss_phy_setup(struct dwc3 *dwc, int index)
658671 */
659672 reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX ;
660673
661- /*
662- * Above DWC_usb3.0 1.94a, it is recommended to set
663- * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration.
664- * So default value will be '0' when the core is reset. Application
665- * needs to set it to '1' after the core initialization is completed.
666- *
667- * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be
668- * cleared after power-on reset, and it can be set after core
669- * initialization.
670- */
674+ /* Ensure the GUSB3PIPECTL.SUSPENDENABLE is cleared prior to phy init. */
671675 reg &= ~DWC3_GUSB3PIPECTL_SUSPHY ;
672676
673677 if (dwc -> u2ss_inp3_quirk )
@@ -747,15 +751,7 @@ static int dwc3_hs_phy_setup(struct dwc3 *dwc, int index)
747751 break ;
748752 }
749753
750- /*
751- * Above DWC_usb3.0 1.94a, it is recommended to set
752- * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration.
753- * So default value will be '0' when the core is reset. Application
754- * needs to set it to '1' after the core initialization is completed.
755- *
756- * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared
757- * after power-on reset, and it can be set after core initialization.
758- */
754+ /* Ensure the GUSB2PHYCFG.SUSPHY is cleared prior to phy init. */
759755 reg &= ~DWC3_GUSB2PHYCFG_SUSPHY ;
760756
761757 if (dwc -> dis_enblslpm_quirk )
@@ -830,6 +826,25 @@ static int dwc3_phy_init(struct dwc3 *dwc)
830826 goto err_exit_usb3_phy ;
831827 }
832828
829+ /*
830+ * Above DWC_usb3.0 1.94a, it is recommended to set
831+ * DWC3_GUSB3PIPECTL_SUSPHY and DWC3_GUSB2PHYCFG_SUSPHY to '0' during
832+ * coreConsultant configuration. So default value will be '0' when the
833+ * core is reset. Application needs to set it to '1' after the core
834+ * initialization is completed.
835+ *
836+ * Certain phy requires to be in P0 power state during initialization.
837+ * Make sure GUSB3PIPECTL.SUSPENDENABLE and GUSB2PHYCFG.SUSPHY are clear
838+ * prior to phy init to maintain in the P0 state.
839+ *
840+ * After phy initialization, some phy operations can only be executed
841+ * while in lower P states. Ensure GUSB3PIPECTL.SUSPENDENABLE and
842+ * GUSB2PHYCFG.SUSPHY are set soon after initialization to avoid
843+ * blocking phy ops.
844+ */
845+ if (!DWC3_VER_IS_WITHIN (DWC3 , ANY , 194 A ))
846+ dwc3_enable_susphy (dwc , true);
847+
833848 return 0 ;
834849
835850err_exit_usb3_phy :
@@ -1588,7 +1603,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
15881603
15891604 switch (dwc -> dr_mode ) {
15901605 case USB_DR_MODE_PERIPHERAL :
1591- dwc3_set_prtcap (dwc , DWC3_GCTL_PRTCAP_DEVICE );
1606+ dwc3_set_prtcap (dwc , DWC3_GCTL_PRTCAP_DEVICE , false );
15921607
15931608 if (dwc -> usb2_phy )
15941609 otg_set_vbus (dwc -> usb2_phy -> otg , false);
@@ -1600,7 +1615,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
16001615 return dev_err_probe (dev , ret , "failed to initialize gadget\n" );
16011616 break ;
16021617 case USB_DR_MODE_HOST :
1603- dwc3_set_prtcap (dwc , DWC3_GCTL_PRTCAP_HOST );
1618+ dwc3_set_prtcap (dwc , DWC3_GCTL_PRTCAP_HOST , false );
16041619
16051620 if (dwc -> usb2_phy )
16061621 otg_set_vbus (dwc -> usb2_phy -> otg , true);
@@ -1645,7 +1660,7 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
16451660 }
16461661
16471662 /* de-assert DRVVBUS for HOST and OTG mode */
1648- dwc3_set_prtcap (dwc , DWC3_GCTL_PRTCAP_DEVICE );
1663+ dwc3_set_prtcap (dwc , DWC3_GCTL_PRTCAP_DEVICE , true );
16491664}
16501665
16511666static void dwc3_get_software_properties (struct dwc3 * dwc )
@@ -2453,15 +2468,15 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
24532468 if (ret )
24542469 return ret ;
24552470
2456- dwc3_set_prtcap (dwc , DWC3_GCTL_PRTCAP_DEVICE );
2471+ dwc3_set_prtcap (dwc , DWC3_GCTL_PRTCAP_DEVICE , true );
24572472 dwc3_gadget_resume (dwc );
24582473 break ;
24592474 case DWC3_GCTL_PRTCAP_HOST :
24602475 if (!PMSG_IS_AUTO (msg ) && !device_may_wakeup (dwc -> dev )) {
24612476 ret = dwc3_core_init_for_resume (dwc );
24622477 if (ret )
24632478 return ret ;
2464- dwc3_set_prtcap (dwc , DWC3_GCTL_PRTCAP_HOST );
2479+ dwc3_set_prtcap (dwc , DWC3_GCTL_PRTCAP_HOST , true );
24652480 break ;
24662481 }
24672482 /* Restore GUSB2PHYCFG bits that were modified in suspend */
@@ -2490,7 +2505,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
24902505 if (ret )
24912506 return ret ;
24922507
2493- dwc3_set_prtcap (dwc , dwc -> current_dr_role );
2508+ dwc3_set_prtcap (dwc , dwc -> current_dr_role , true );
24942509
24952510 dwc3_otg_init (dwc );
24962511 if (dwc -> current_otg_role == DWC3_OTG_ROLE_HOST ) {
0 commit comments