diff -drupN a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c --- a/drivers/usb/dwc2/hcd.c 2017-10-21 18:09:07.000000000 +0300 +++ b/drivers/usb/dwc2/hcd.c 2022-06-09 05:02:34.000000000 +0300 @@ -302,6 +302,7 @@ void dwc2_hcd_disconnect(struct dwc2_hso if (hsotg->op_state != OTG_STATE_A_SUSPEND) { dev_dbg(hsotg->dev, "Disconnect: PortPower off\n"); dwc2_writel(0, hsotg->regs + HPRT0); + usb_phy_vbus_off(hsotg->uphy); } dwc2_disable_host_interrupts(hsotg); @@ -356,6 +357,7 @@ void dwc2_hcd_stop(struct dwc2_hsotg *hs /* Turn off the vbus power */ dev_dbg(hsotg->dev, "PortPower off\n"); dwc2_writel(0, hsotg->regs + HPRT0); + usb_phy_vbus_off(hsotg->uphy); } /* Caller must hold driver lock */ @@ -1367,6 +1369,7 @@ static void dwc2_conn_id_status_change(s /* B-Device connector (Device Mode) */ if (gotgctl & GOTGCTL_CONID_B) { + usb_phy_vbus_off(hsotg->uphy); /* Wait for switch to device mode */ dev_dbg(hsotg->dev, "connId B\n"); while (!dwc2_is_device_mode(hsotg)) { @@ -1382,12 +1385,18 @@ static void dwc2_conn_id_status_change(s dev_err(hsotg->dev, "Connection id status change timed out\n"); hsotg->op_state = OTG_STATE_B_PERIPHERAL; - dwc2_core_init(hsotg, false, -1); + dwc2_core_init(hsotg, false, -1, false); dwc2_enable_global_interrupts(hsotg); spin_lock_irqsave(&hsotg->lock, flags); - dwc2_hsotg_core_init_disconnected(hsotg, false); - spin_unlock_irqrestore(&hsotg->lock, flags); - dwc2_hsotg_core_connect(hsotg); +#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) + if(hsotg->enabled){ + dwc2_hsotg_core_init_disconnected(hsotg, false); + spin_unlock_irqrestore(&hsotg->lock, flags); + dwc2_hsotg_core_connect(hsotg); + }else{ + spin_unlock_irqrestore(&hsotg->lock, flags); + } +#endif } else { /* A-Device connector (Host Mode) */ dev_dbg(hsotg->dev, "connId A\n"); @@ -1405,7 +1414,7 @@ static void dwc2_conn_id_status_change(s hsotg->op_state = OTG_STATE_A_HOST; /* Initialize the Core for Host mode */ - dwc2_core_init(hsotg, false, -1); + dwc2_core_init(hsotg, false, -1, false); dwc2_enable_global_interrupts(hsotg); dwc2_hcd_start(hsotg); } @@ -2378,11 +2387,14 @@ static void _dwc2_hcd_stop(struct usb_hc static int _dwc2_hcd_suspend(struct usb_hcd *hcd) { + int ret = 0; struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); unsigned long flags; - int ret = 0; u32 hprt0; + if(!dwc2_is_host_mode(hsotg)) + return ret; + spin_lock_irqsave(&hsotg->lock, flags); if (hsotg->lx_state != DWC2_L0) @@ -2403,6 +2415,7 @@ static int _dwc2_hcd_suspend(struct usb_ hprt0 |= HPRT0_SUSP; hprt0 &= ~HPRT0_PWR; dwc2_writel(hprt0, hsotg->regs + HPRT0); + usb_phy_vbus_off(hsotg->uphy); } /* Enter hibernation */ @@ -2428,18 +2441,20 @@ skip_power_saving: hsotg->lx_state = DWC2_L2; unlock: spin_unlock_irqrestore(&hsotg->lock, flags); - return ret; } static int _dwc2_hcd_resume(struct usb_hcd *hcd) { + + int ret = 0; struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); unsigned long flags; - int ret = 0; - spin_lock_irqsave(&hsotg->lock, flags); + if(!dwc2_is_host_mode(hsotg)) + return ret; + spin_lock_irqsave(&hsotg->lock, flags); if (hsotg->lx_state != DWC2_L2) goto unlock; @@ -2487,6 +2502,7 @@ static int _dwc2_hcd_resume(struct usb_h * Clear Port Enable and Port Status changes. * Enable Port Power. */ + usb_phy_vbus_on(hsotg->uphy); dwc2_writel(HPRT0_PWR | HPRT0_CONNDET | HPRT0_ENACHG, hsotg->regs + HPRT0); /* Wait for controller to detect Port Connect */ @@ -2496,7 +2512,6 @@ static int _dwc2_hcd_resume(struct usb_h return ret; unlock: spin_unlock_irqrestore(&hsotg->lock, flags); - return ret; } @@ -3054,7 +3069,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso dwc2_disable_global_interrupts(hsotg); /* Initialize the DWC_otg core, and select the Phy type */ - retval = dwc2_core_init(hsotg, true, irq); + retval = dwc2_core_init(hsotg, true, irq, true); if (retval) goto error2;