On 4/8/2021 1:45 PM, Artur Petrosyan wrote: > Adds flow of entering Partial Power Down in > "dwc2_port_suspend()" function when core receives suspend. > > 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 | 48 ++++++++++++++++++++++++++--------------- > 2 files changed, 34 insertions(+), 19 deletions(-) > > diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h > index b7d99cf9e84c..76807abd753b 100644 > --- a/drivers/usb/dwc2/core.h > +++ b/drivers/usb/dwc2/core.h > @@ -1470,7 +1470,7 @@ void dwc2_hcd_connect(struct dwc2_hsotg *hsotg); > 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); > -void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex); > +int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex); > void 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); > @@ -1495,7 +1495,8 @@ static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {} > static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {} > static inline int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup) > { return 0; } > -static inline void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) {} > +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_hcd_init(struct dwc2_hsotg *hsotg) > { return 0; } > diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c > index f4247a66c2b2..e7fb0d5940bc 100644 > --- a/drivers/usb/dwc2/hcd.c > +++ b/drivers/usb/dwc2/hcd.c > @@ -3281,15 +3281,18 @@ static int dwc2_host_is_b_hnp_enabled(struct dwc2_hsotg *hsotg) > * @hsotg: Programming view of the DWC_otg controller > * @windex: The control request wIndex field > * > + * Return: non-zero if failed to enter suspend mode for host. > + * > * This function is for entering Host mode suspend. > * Must NOT be called with interrupt disabled or spinlock held. > */ > -void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) > +int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) > { > unsigned long flags; > u32 hprt0; > u32 pcgctl; > u32 gotgctl; > + int ret = 0; > > dev_dbg(hsotg->dev, "%s()\n", __func__); > > @@ -3302,22 +3305,31 @@ void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) > hsotg->op_state = OTG_STATE_A_SUSPEND; > } > > - hprt0 = dwc2_read_hprt0(hsotg); > - hprt0 |= HPRT0_SUSP; > - dwc2_writel(hsotg, hprt0, HPRT0); > - > - hsotg->bus_suspended = true; > - > - /* > - * If power_down is supported, Phy clock will be suspended > - * after registers are backuped. > - */ > - if (!hsotg->params.power_down) { > - /* Suspend the Phy Clock */ > - pcgctl = dwc2_readl(hsotg, PCGCTL); > - pcgctl |= PCGCTL_STOPPCLK; > - dwc2_writel(hsotg, pcgctl, PCGCTL); > - udelay(10); > + switch (hsotg->params.power_down) { > + case DWC2_POWER_DOWN_PARAM_PARTIAL: > + ret = dwc2_enter_partial_power_down(hsotg); > + if (ret) > + dev_err(hsotg->dev, > + "enter partial_power_down failed.\n"); > + break; > + case DWC2_POWER_DOWN_PARAM_HIBERNATION: > + case DWC2_POWER_DOWN_PARAM_NONE: > + default: > + hprt0 = dwc2_read_hprt0(hsotg); > + hprt0 |= HPRT0_SUSP; > + dwc2_writel(hsotg, hprt0, HPRT0); > + hsotg->bus_suspended = true; > + /* > + * If power_down is supported, Phy clock will be suspended > + * after registers are backuped. > + */ > + if (!hsotg->params.power_down) { > + /* Suspend the Phy Clock */ > + pcgctl = dwc2_readl(hsotg, PCGCTL); > + pcgctl |= PCGCTL_STOPPCLK; > + dwc2_writel(hsotg, pcgctl, PCGCTL); > + udelay(10); > + } > } > > /* For HNP the bus must be suspended for at least 200ms */ > @@ -3332,6 +3344,8 @@ void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) > } else { > spin_unlock_irqrestore(&hsotg->lock, flags); > } > + > + return ret; > } > > /** >