In host mode port power must be turned on when wakeup detected or session request interrupt is detected. Because, otherwise core wouldn't exit form partial power down. - Turned on the port power by setting HPRT0_PWR bit. - Called dwc2_hcd_connect() function after enabling the power of the port. Signed-off-by: Artur Petrosyan <arturp@xxxxxxxxxxxx> --- drivers/usb/dwc2/core_intr.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 19ae2595f1c3..06f8022b1bdb 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -312,6 +312,7 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg) static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) { int ret; + u32 hprt0; /* Clear interrupt */ dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS); @@ -320,7 +321,9 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) hsotg->lx_state); if (dwc2_is_device_mode(hsotg)) { - if (hsotg->lx_state == DWC2_L2) { + if (hsotg->lx_state == DWC2_L2 && + hsotg->params.power_down == + DWC2_POWER_DOWN_PARAM_PARTIAL) { ret = dwc2_exit_partial_power_down(hsotg, true); if (ret && (ret != -ENOTSUPP)) dev_err(hsotg->dev, @@ -332,6 +335,14 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg) * established */ dwc2_hsotg_disconnect(hsotg); + } else { + /* Turn on the port power bit. */ + hprt0 = dwc2_read_hprt0(hsotg); + hprt0 |= HPRT0_PWR; + dwc2_writel(hsotg, hprt0, HPRT0); + + /* Connect hcd after port power is set. */ + dwc2_hcd_connect(hsotg); } } @@ -396,6 +407,7 @@ static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg) static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) { int ret; + u32 hprt0; /* Clear interrupt */ dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS); @@ -426,8 +438,6 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) /* Change to L0 state */ hsotg->lx_state = DWC2_L0; } else { - if (hsotg->params.power_down) - return; if (hsotg->lx_state != DWC2_L1) { u32 pcgcctl = dwc2_readl(hsotg, PCGCTL); @@ -435,6 +445,15 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg) /* Restart the Phy Clock */ pcgcctl &= ~PCGCTL_STOPPCLK; dwc2_writel(hsotg, pcgcctl, PCGCTL); + + /* Turn on the port power bit. */ + hprt0 = dwc2_read_hprt0(hsotg); + hprt0 |= HPRT0_PWR; + dwc2_writel(hsotg, hprt0, HPRT0); + + /* Connect hcd. */ + dwc2_hcd_connect(hsotg); + mod_timer(&hsotg->wkp_timer, jiffies + msecs_to_jiffies(71)); } else { -- 2.11.0