- After entering hibernation both in host and device modes saved GPWRDN register. - In handling status change interrupt checking if current mode differs from the mode when entered hibernation. In case when mode is not changed, exiting device hibernation without remote wake up. On the other hand, if there is device hibernation and changed to host, then exiting hibernation for device mode with remote wake up. - Removed workaround for ignore suspend interrupt before enumeration. Signed-off-by: Artur Petrosyan <arturp@xxxxxxxxxxxx> Signed-off-by: Minas Harutyunyan <hminas@xxxxxxxxxxxx> --- drivers/usb/dwc2/core_intr.c | 19 +++++++++---------- drivers/usb/dwc2/hcd.c | 3 +++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 3602aca3316b..47e7dc4100af 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c @@ -491,12 +491,6 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) hsotg->hw_params.power_optimized, hsotg->hw_params.hibernation); - /* Ignore suspend request before enumeration */ - if (!dwc2_is_device_connected(hsotg)) { - dev_dbg(hsotg->dev, - "ignore suspend request before enumeration\n"); - return; - } if (dsts & DSTS_SUSPSTS) { switch (hsotg->params.power_down) { case DWC2_POWER_DOWN_PARAM_PARTIAL: @@ -733,21 +727,26 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg) } } } + if ((gpwrdn & GPWRDN_RST_DET) && (gpwrdn & GPWRDN_RST_DET_MSK)) { dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__); if (!linestate && (gpwrdn & GPWRDN_BSESSVLD)) dwc2_exit_hibernation(hsotg, 0, 1, 0); } + if ((gpwrdn & GPWRDN_STS_CHGINT) && - (gpwrdn & GPWRDN_STS_CHGINT_MSK) && linestate) { + (gpwrdn & GPWRDN_STS_CHGINT_MSK)) { dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__); if (hsotg->hw_params.hibernation && hsotg->hibernated) { - if (gpwrdn & GPWRDN_IDSTS) { + if ((gpwrdn & GPWRDN_IDSTS) & + (hsotg->gr_backup.gpwrdn & GPWRDN_IDSTS) && + linestate) { dwc2_exit_hibernation(hsotg, 0, 0, 0); call_gadget(hsotg, resume); - } else { - dwc2_exit_hibernation(hsotg, 1, 0, 1); + } else if (!(gpwrdn & GPWRDN_IDSTS) && !linestate) { + dwc2_exit_hibernation(hsotg, 1, 0, 0); + call_gadget(hsotg, resume); } } } diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 2bd6e6bfc241..0e29b4c4e87b 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -5582,6 +5582,9 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg) gpwrdn |= GPWRDN_PWRDNSWTCH; dwc2_writel(hsotg, gpwrdn, GPWRDN); + /* Save gpwrdn register for further usage if stschng interrupt */ + hsotg->gr_backup.gpwrdn = dwc2_readl(hsotg, GPWRDN); + hsotg->hibernated = 1; hsotg->bus_suspended = 1; dev_dbg(hsotg->dev, "Host hibernation completed\n"); -- 2.11.0