Hi Marek, On 7/16/2021 9:01 AM, Marek Szyprowski wrote: > Commit 0112b7ce68ea ("usb: dwc2: Update dwc2_handle_usb_suspend_intr > function.") changed the way the driver handles power down modes in a such > way that it uses clock gating when no other power down mode is available. > > This however doesn't work well on the DWC2 implementation used on the > Samsung SoCs. When a clock gating is enabled, system hangs. It looks that > the proper clock gating requires some additional glue code in the shared > USB2 PHY and/or Samsung glue code for the DWC2. To restore driver > operation on the Samsung SoCs simply skip enabling clock gating mode > until one finds what is really needed to make it working reliably. > > Fixes: 0112b7ce68ea ("usb: dwc2: Update dwc2_handle_usb_suspend_intr function.") > Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> > --- > drivers/usb/dwc2/core.h | 4 ++++ > drivers/usb/dwc2/core_intr.c | 3 ++- > drivers/usb/dwc2/hcd.c | 6 ++++-- > drivers/usb/dwc2/params.c | 1 + > 4 files changed, 11 insertions(+), 3 deletions(-) > > diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h > index ab6b815e0089..483de2bbfaab 100644 > --- a/drivers/usb/dwc2/core.h > +++ b/drivers/usb/dwc2/core.h > @@ -383,6 +383,9 @@ enum dwc2_ep0_state { > * 0 - No (default) > * 1 - Partial power down > * 2 - Hibernation > + * @no_clock_gating: Specifies whether to avoid clock gating feature. > + * 0 - No (use clock gating) > + * 1 - Yes (avoid it) > * @lpm: Enable LPM support. > * 0 - No > * 1 - Yes > @@ -480,6 +483,7 @@ struct dwc2_core_params { > #define DWC2_POWER_DOWN_PARAM_NONE 0 > #define DWC2_POWER_DOWN_PARAM_PARTIAL 1 > #define DWC2_POWER_DOWN_PARAM_HIBERNATION 2 > + bool no_clock_gating; > > bool lpm; > bool lpm_clock_gating; > diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c > index a5ab03808da6..a5c52b237e72 100644 > --- a/drivers/usb/dwc2/core_intr.c > +++ b/drivers/usb/dwc2/core_intr.c > @@ -556,7 +556,8 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) > * If neither hibernation nor partial power down are supported, > * clock gating is used to save power. > */ > - dwc2_gadget_enter_clock_gating(hsotg); > + if (!hsotg->params.no_clock_gating) > + dwc2_gadget_enter_clock_gating(hsotg); > } > > /* > diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c > index 035d4911a3c3..2a7828971d05 100644 > --- a/drivers/usb/dwc2/hcd.c > +++ b/drivers/usb/dwc2/hcd.c > @@ -3338,7 +3338,8 @@ int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) > * If not hibernation nor partial power down are supported, > * clock gating is used to save power. > */ > - dwc2_host_enter_clock_gating(hsotg); > + if (!hsotg->params.no_clock_gating) > + dwc2_host_enter_clock_gating(hsotg); > break; > } > > @@ -4402,7 +4403,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd) > * If not hibernation nor partial power down are supported, > * clock gating is used to save power. > */ > - dwc2_host_enter_clock_gating(hsotg); > + if (!hsotg->params.no_clock_gating) > + dwc2_host_enter_clock_gating(hsotg); > > /* After entering suspend, hardware is not accessible */ > clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); > diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c > index 67c5eb140232..59e119345994 100644 > --- a/drivers/usb/dwc2/params.c > +++ b/drivers/usb/dwc2/params.c > @@ -76,6 +76,7 @@ static void dwc2_set_s3c6400_params(struct dwc2_hsotg *hsotg) > struct dwc2_core_params *p = &hsotg->params; > > p->power_down = DWC2_POWER_DOWN_PARAM_NONE; > + p->no_clock_gating = true; > p->phy_utmi_width = 8; > } > > In which mode host/device you see the issue? What is your core version? Please provide GHWCFG1-4 registers values. Is the issue seen because of programming PCGCTL.PCGCTL_GATEHCLK bit only? To check it, could you please comment this bit setting/resetting in clock gating functions: dwc2_host_exit_clock_gating() dwc2_host_enter_clock_gating() dwc2_gadget_exit_clock_gating() dwc2_gadget_enter_clock_gating() Thanks, Minas