On 4/8/2021 1:45 PM, Artur Petrosyan wrote: > 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. > > Signed-off-by: Artur Petrosyan <Arthur.Petrosyan@xxxxxxxxxxxx> Acked-by: Minas Harutyunyan <Minas.Harutyunyan@xxxxxxxxxxxx> > --- > Changes in v3: > - None > Changes in v2: > - None > > drivers/usb/dwc2/core.h | 5 ++-- > drivers/usb/dwc2/hcd.c | 61 ++++++++++++++++++++++++++--------------- > 2 files changed, 42 insertions(+), 24 deletions(-) > > diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h > index 76807abd753b..5a7850482e57 100644 > --- a/drivers/usb/dwc2/core.h > +++ b/drivers/usb/dwc2/core.h > @@ -1471,7 +1471,7 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force); > void dwc2_hcd_start(struct dwc2_hsotg *hsotg); > int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup); > int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex); > -void dwc2_port_resume(struct dwc2_hsotg *hsotg); > +int dwc2_port_resume(struct dwc2_hsotg *hsotg); > int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg); > int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg); > int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg); > @@ -1497,7 +1497,8 @@ static inline int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup) > { return 0; } > static inline int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) > { return 0; } > -static inline void dwc2_port_resume(struct dwc2_hsotg *hsotg) {} > +static inline int dwc2_port_resume(struct dwc2_hsotg *hsotg) > +{ return 0; } > static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg) > { return 0; } > static inline int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) > 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 */ >