summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc2/hcd.c
diff options
context:
space:
mode:
authorArtur Petrosyan <Arthur.Petrosyan@synopsys.com>2021-04-08 13:45:17 +0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-04-09 15:16:38 +0200
commit1e0890ebaa3fe868c3ea4651f05fa86d72740993 (patch)
tree2b093ee7f7ac07a05aebde7c321be0813b6cfc00 /drivers/usb/dwc2/hcd.c
parent22ff0c8e529ed3c3385f9807ec8efacf440c4c8e (diff)
usb: dwc2: Add exit partial power down when port is resumed
Added flow of exiting Partial Power Down in "dwc2_port_resume()" function when core receives resume. NOTE: Switch case statement is used for hibernation partial power down and clock gating mode determination. In this patch only Partial Power Down is implemented the Hibernation and clock gating implementations are planned to be added. Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com> Signed-off-by: Artur Petrosyan <Arthur.Petrosyan@synopsys.com> Link: https://lore.kernel.org/r/20210408094518.6DA1DA022E@mailhost.synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/dwc2/hcd.c')
-rw-r--r--drivers/usb/dwc2/hcd.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index e7fb0d5940bc..720354df014b 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3353,44 +3353,61 @@ int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
*
* @hsotg: Programming view of the DWC_otg controller
*
+ * Return: non-zero if failed to exit suspend mode for host.
+ *
* This function is for exiting Host mode suspend.
* Must NOT be called with interrupt disabled or spinlock held.
*/
-void dwc2_port_resume(struct dwc2_hsotg *hsotg)
+int dwc2_port_resume(struct dwc2_hsotg *hsotg)
{
unsigned long flags;
u32 hprt0;
u32 pcgctl;
+ int ret = 0;
spin_lock_irqsave(&hsotg->lock, flags);
- /*
- * If power_down is supported, Phy clock is already resumed
- * after registers restore.
- */
- if (!hsotg->params.power_down) {
- pcgctl = dwc2_readl(hsotg, PCGCTL);
- pcgctl &= ~PCGCTL_STOPPCLK;
- dwc2_writel(hsotg, pcgctl, PCGCTL);
+ switch (hsotg->params.power_down) {
+ case DWC2_POWER_DOWN_PARAM_PARTIAL:
+ ret = dwc2_exit_partial_power_down(hsotg, 0, true);
+ if (ret)
+ dev_err(hsotg->dev,
+ "exit partial_power_down failed.\n");
+ break;
+ case DWC2_POWER_DOWN_PARAM_HIBERNATION:
+ case DWC2_POWER_DOWN_PARAM_NONE:
+ default:
+ /*
+ * If power_down is supported, Phy clock is already resumed
+ * after registers restore.
+ */
+ if (!hsotg->params.power_down) {
+ pcgctl = dwc2_readl(hsotg, PCGCTL);
+ pcgctl &= ~PCGCTL_STOPPCLK;
+ dwc2_writel(hsotg, pcgctl, PCGCTL);
+ spin_unlock_irqrestore(&hsotg->lock, flags);
+ msleep(20);
+ spin_lock_irqsave(&hsotg->lock, flags);
+ }
+
+ hprt0 = dwc2_read_hprt0(hsotg);
+ hprt0 |= HPRT0_RES;
+ hprt0 &= ~HPRT0_SUSP;
+ dwc2_writel(hsotg, hprt0, HPRT0);
spin_unlock_irqrestore(&hsotg->lock, flags);
- msleep(20);
+
+ msleep(USB_RESUME_TIMEOUT);
+
spin_lock_irqsave(&hsotg->lock, flags);
+ hprt0 = dwc2_read_hprt0(hsotg);
+ hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
+ dwc2_writel(hsotg, hprt0, HPRT0);
+ hsotg->bus_suspended = false;
}
- hprt0 = dwc2_read_hprt0(hsotg);
- hprt0 |= HPRT0_RES;
- hprt0 &= ~HPRT0_SUSP;
- dwc2_writel(hsotg, hprt0, HPRT0);
spin_unlock_irqrestore(&hsotg->lock, flags);
- msleep(USB_RESUME_TIMEOUT);
-
- spin_lock_irqsave(&hsotg->lock, flags);
- hprt0 = dwc2_read_hprt0(hsotg);
- hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
- dwc2_writel(hsotg, hprt0, HPRT0);
- hsotg->bus_suspended = false;
- spin_unlock_irqrestore(&hsotg->lock, flags);
+ return ret;
}
/* Handles hub class-specific requests */