diff mbox series

[RFC,1/2] phy: qcom-snps-femto-v2: properly enable ref clock

Message ID 20230529185638.32376-2-athierry@redhat.com
State Superseded
Headers show
Series Clock fixes for qcom-snps-femto-v2 PHY driver | expand

Commit Message

Adrien Thierry May 29, 2023, 6:56 p.m. UTC
The driver is not enabling the ref clock, which thus gets disabled by
the clk_disable_unused initcall. This leads to the dwc3 controller
failing to initialize if probed after clk_disable_unused is called, for
instance when the driver is built as a module.

To fix this, add calls to clk_prepare_enable/clk_disable_unprepare at
the proper places.

Signed-off-by: Adrien Thierry <athierry@redhat.com>
---
 drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c | 20 +++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

Comments

Bjorn Andersson May 29, 2023, 9:16 p.m. UTC | #1
On Mon, May 29, 2023 at 02:56:36PM -0400, Adrien Thierry wrote:
> The driver is not enabling the ref clock, which thus gets disabled by
> the clk_disable_unused initcall. This leads to the dwc3 controller
> failing to initialize if probed after clk_disable_unused is called, for
> instance when the driver is built as a module.
> 

Good catch!

A side note though, clk_disable_unused() has no way to take kernel
modules into consideration today, and it doesn't handle the case where
clock drivers are built as modules appropriately.
Work has started to address this, but as of todaybooting the system
without clk_ignore_unused is not recommended...

> To fix this, add calls to clk_prepare_enable/clk_disable_unprepare at
> the proper places.
> 

If I parse the downstream kernel correctly the refclock should be
turned off across runtime and system suspend as well.

Regards,
Bjorn

> Signed-off-by: Adrien Thierry <athierry@redhat.com>
> ---
>  drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c | 20 +++++++++++++++++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> index 6c237f3cc66d..8abf482e81a8 100644
> --- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> +++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> @@ -166,6 +166,7 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
>  	}
>  
>  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> +	clk_disable_unprepare(hsphy->ref_clk);
>  	return 0;
>  }
>  
> @@ -181,6 +182,12 @@ static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
>  		return ret;
>  	}
>  
> +	ret = clk_prepare_enable(hsphy->ref_clk);
> +	if (ret) {
> +		dev_err(&hsphy->phy->dev, "failed to enable ref clock\n");
> +		return ret;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -380,10 +387,16 @@ static int qcom_snps_hsphy_init(struct phy *phy)
>  		goto poweroff_phy;
>  	}
>  
> +	ret = clk_prepare_enable(hsphy->ref_clk);
> +	if (ret) {
> +		dev_err(&phy->dev, "failed to enable ref clock, %d\n", ret);
> +		goto disable_ahb_clk;
> +	}
> +
>  	ret = reset_control_assert(hsphy->phy_reset);
>  	if (ret) {
>  		dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
> -		goto disable_ahb_clk;
> +		goto disable_ref_clk;
>  	}
>  
>  	usleep_range(100, 150);
> @@ -391,7 +404,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
>  	ret = reset_control_deassert(hsphy->phy_reset);
>  	if (ret) {
>  		dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
> -		goto disable_ahb_clk;
> +		goto disable_ref_clk;
>  	}
>  
>  	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
> @@ -448,6 +461,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
>  
>  	return 0;
>  
> +disable_ref_clk:
> +	clk_disable_unprepare(hsphy->ref_clk);
>  disable_ahb_clk:
>  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
>  poweroff_phy:
> @@ -462,6 +477,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
>  
>  	reset_control_assert(hsphy->phy_reset);
>  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> +	clk_disable_unprepare(hsphy->ref_clk);
>  	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
>  	hsphy->phy_initialized = false;
>  
> -- 
> 2.40.1
>
Andrew Halaney May 30, 2023, 1:22 p.m. UTC | #2
On Mon, May 29, 2023 at 02:56:36PM -0400, Adrien Thierry wrote:
> The driver is not enabling the ref clock, which thus gets disabled by
> the clk_disable_unused initcall. This leads to the dwc3 controller
> failing to initialize if probed after clk_disable_unused is called, for
> instance when the driver is built as a module.
> 
> To fix this, add calls to clk_prepare_enable/clk_disable_unprepare at
> the proper places.
> 

I'm a sucker for a good paper trail, maybe add:
Link: https://lore.kernel.org/linux-arm-msm/ZEqvy+khHeTkC2hf@fedora/
Fixes: 51e8114f80d0 ("phy: qcom-snps: Add SNPS USB PHY driver for QCOM based SOCs")

good work!

> Signed-off-by: Adrien Thierry <athierry@redhat.com>
> ---
>  drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c | 20 +++++++++++++++++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> index 6c237f3cc66d..8abf482e81a8 100644
> --- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> +++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> @@ -166,6 +166,7 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
>  	}
>  
>  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> +	clk_disable_unprepare(hsphy->ref_clk);
>  	return 0;
>  }
>  
> @@ -181,6 +182,12 @@ static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
>  		return ret;
>  	}
>  
> +	ret = clk_prepare_enable(hsphy->ref_clk);
> +	if (ret) {
> +		dev_err(&hsphy->phy->dev, "failed to enable ref clock\n");
> +		return ret;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -380,10 +387,16 @@ static int qcom_snps_hsphy_init(struct phy *phy)
>  		goto poweroff_phy;
>  	}
>  
> +	ret = clk_prepare_enable(hsphy->ref_clk);
> +	if (ret) {
> +		dev_err(&phy->dev, "failed to enable ref clock, %d\n", ret);
> +		goto disable_ahb_clk;
> +	}
> +
>  	ret = reset_control_assert(hsphy->phy_reset);
>  	if (ret) {
>  		dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
> -		goto disable_ahb_clk;
> +		goto disable_ref_clk;
>  	}
>  
>  	usleep_range(100, 150);
> @@ -391,7 +404,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
>  	ret = reset_control_deassert(hsphy->phy_reset);
>  	if (ret) {
>  		dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
> -		goto disable_ahb_clk;
> +		goto disable_ref_clk;
>  	}
>  
>  	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
> @@ -448,6 +461,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
>  
>  	return 0;
>  
> +disable_ref_clk:
> +	clk_disable_unprepare(hsphy->ref_clk);
>  disable_ahb_clk:
>  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
>  poweroff_phy:
> @@ -462,6 +477,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
>  
>  	reset_control_assert(hsphy->phy_reset);
>  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> +	clk_disable_unprepare(hsphy->ref_clk);
>  	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
>  	hsphy->phy_initialized = false;
>  
> -- 
> 2.40.1
>
Adrien Thierry May 30, 2023, 6:46 p.m. UTC | #3
Hi Bjorn, thanks for your reply!

On Mon, May 29, 2023 at 02:16:29PM -0700, Bjorn Andersson wrote:
> On Mon, May 29, 2023 at 02:56:36PM -0400, Adrien Thierry wrote:
> > The driver is not enabling the ref clock, which thus gets disabled by
> > the clk_disable_unused initcall. This leads to the dwc3 controller
> > failing to initialize if probed after clk_disable_unused is called, for
> > instance when the driver is built as a module.
> > 
> 
> Good catch!
> 
> A side note though, clk_disable_unused() has no way to take kernel
> modules into consideration today, and it doesn't handle the case where
> clock drivers are built as modules appropriately.
> Work has started to address this, but as of todaybooting the system
> without clk_ignore_unused is not recommended...
>

For my understanding, do you have an example of a situation that would
fail with modules when not using clk_ignore_unused?

> > To fix this, add calls to clk_prepare_enable/clk_disable_unprepare at
> > the proper places.
> > 
> 
> If I parse the downstream kernel correctly the refclock should be
> turned off across runtime and system suspend as well.
> 

Which downstream kernel are you using? I'm not seing a system suspend
callback in mine [1]. refclock should be turned off on runtime suspend in
my patch, in qcom_snps_hsphy_suspend, which is called by
qcom_snps_hsphy_runtime_suspend.

[1] https://git.codelinaro.org/clo/la/kernel/ark-5.14/-/blob/kernel.lnx.5.14.r2-rel/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c

> Regards,
> Bjorn
> 
> > Signed-off-by: Adrien Thierry <athierry@redhat.com>
> > ---
> >  drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c | 20 +++++++++++++++++--
> >  1 file changed, 18 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> > index 6c237f3cc66d..8abf482e81a8 100644
> > --- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> > +++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> > @@ -166,6 +166,7 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
> >  	}
> >  
> >  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> > +	clk_disable_unprepare(hsphy->ref_clk);
> >  	return 0;
> >  }
> >  
> > @@ -181,6 +182,12 @@ static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
> >  		return ret;
> >  	}
> >  
> > +	ret = clk_prepare_enable(hsphy->ref_clk);
> > +	if (ret) {
> > +		dev_err(&hsphy->phy->dev, "failed to enable ref clock\n");
> > +		return ret;
> > +	}
> > +
> >  	return 0;
> >  }
> >  
> > @@ -380,10 +387,16 @@ static int qcom_snps_hsphy_init(struct phy *phy)
> >  		goto poweroff_phy;
> >  	}
> >  
> > +	ret = clk_prepare_enable(hsphy->ref_clk);
> > +	if (ret) {
> > +		dev_err(&phy->dev, "failed to enable ref clock, %d\n", ret);
> > +		goto disable_ahb_clk;
> > +	}
> > +
> >  	ret = reset_control_assert(hsphy->phy_reset);
> >  	if (ret) {
> >  		dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
> > -		goto disable_ahb_clk;
> > +		goto disable_ref_clk;
> >  	}
> >  
> >  	usleep_range(100, 150);
> > @@ -391,7 +404,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
> >  	ret = reset_control_deassert(hsphy->phy_reset);
> >  	if (ret) {
> >  		dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
> > -		goto disable_ahb_clk;
> > +		goto disable_ref_clk;
> >  	}
> >  
> >  	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
> > @@ -448,6 +461,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
> >  
> >  	return 0;
> >  
> > +disable_ref_clk:
> > +	clk_disable_unprepare(hsphy->ref_clk);
> >  disable_ahb_clk:
> >  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> >  poweroff_phy:
> > @@ -462,6 +477,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
> >  
> >  	reset_control_assert(hsphy->phy_reset);
> >  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> > +	clk_disable_unprepare(hsphy->ref_clk);
> >  	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
> >  	hsphy->phy_initialized = false;
> >  
> > -- 
> > 2.40.1
> >

Best,
Adrien
Bjorn Andersson May 31, 2023, 2:34 a.m. UTC | #4
On Tue, May 30, 2023 at 02:46:05PM -0400, Adrien Thierry wrote:
> Hi Bjorn, thanks for your reply!
> 
> On Mon, May 29, 2023 at 02:16:29PM -0700, Bjorn Andersson wrote:
> > On Mon, May 29, 2023 at 02:56:36PM -0400, Adrien Thierry wrote:
> > > The driver is not enabling the ref clock, which thus gets disabled by
> > > the clk_disable_unused initcall. This leads to the dwc3 controller
> > > failing to initialize if probed after clk_disable_unused is called, for
> > > instance when the driver is built as a module.
> > > 
> > 
> > Good catch!
> > 
> > A side note though, clk_disable_unused() has no way to take kernel
> > modules into consideration today, and it doesn't handle the case where
> > clock drivers are built as modules appropriately.
> > Work has started to address this, but as of todaybooting the system
> > without clk_ignore_unused is not recommended...
> >
> 
> For my understanding, do you have an example of a situation that would
> fail with modules when not using clk_ignore_unused?
> 

The prime example relates to the display clocks, where the bootloader
typically leave clocks on and at lateinit we haven't yet loaded enough
modules to bring up the display. And to make matters worse, the code
ends up disabling the PLL feeding the clock tree without first disabling
some of the muxes - which has side effects...

Another case, although much less concerning in the short run, is when
you have any of the clock drivers built as modules. clk_disable_unused()
will be invoked before they are loaded, so your expectation that unused
clocks are turned off is just not fulfilled.

> > > To fix this, add calls to clk_prepare_enable/clk_disable_unprepare at
> > > the proper places.
> > > 
> > 
> > If I parse the downstream kernel correctly the refclock should be
> > turned off across runtime and system suspend as well.
> > 
> 
> Which downstream kernel are you using? I'm not seing a system suspend
> callback in mine [1]. refclock should be turned off on runtime suspend in
> my patch, in qcom_snps_hsphy_suspend, which is called by
> qcom_snps_hsphy_runtime_suspend.
> 

Forgive me, but isn't [1] the driver you're modifying?

I'm looking at [2], with set_suspend() being invoked from the runtime
and system suspend/resume handlers.

> [1] https://git.codelinaro.org/clo/la/kernel/ark-5.14/-/blob/kernel.lnx.5.14.r2-rel/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c

[2] https://git.codelinaro.org/clo/la/kernel/msm-5.4/-/blob/LV.AU.1.2.1.r2-05300-gen3meta.0/drivers/usb/phy/phy-msm-snps-hs.c#L908

Regards,
Bjorn

> 
> > Regards,
> > Bjorn
> > 
> > > Signed-off-by: Adrien Thierry <athierry@redhat.com>
> > > ---
> > >  drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c | 20 +++++++++++++++++--
> > >  1 file changed, 18 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> > > index 6c237f3cc66d..8abf482e81a8 100644
> > > --- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> > > +++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> > > @@ -166,6 +166,7 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
> > >  	}
> > >  
> > >  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> > > +	clk_disable_unprepare(hsphy->ref_clk);
> > >  	return 0;
> > >  }
> > >  
> > > @@ -181,6 +182,12 @@ static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
> > >  		return ret;
> > >  	}
> > >  
> > > +	ret = clk_prepare_enable(hsphy->ref_clk);
> > > +	if (ret) {
> > > +		dev_err(&hsphy->phy->dev, "failed to enable ref clock\n");
> > > +		return ret;
> > > +	}
> > > +
> > >  	return 0;
> > >  }
> > >  
> > > @@ -380,10 +387,16 @@ static int qcom_snps_hsphy_init(struct phy *phy)
> > >  		goto poweroff_phy;
> > >  	}
> > >  
> > > +	ret = clk_prepare_enable(hsphy->ref_clk);
> > > +	if (ret) {
> > > +		dev_err(&phy->dev, "failed to enable ref clock, %d\n", ret);
> > > +		goto disable_ahb_clk;
> > > +	}
> > > +
> > >  	ret = reset_control_assert(hsphy->phy_reset);
> > >  	if (ret) {
> > >  		dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
> > > -		goto disable_ahb_clk;
> > > +		goto disable_ref_clk;
> > >  	}
> > >  
> > >  	usleep_range(100, 150);
> > > @@ -391,7 +404,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
> > >  	ret = reset_control_deassert(hsphy->phy_reset);
> > >  	if (ret) {
> > >  		dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
> > > -		goto disable_ahb_clk;
> > > +		goto disable_ref_clk;
> > >  	}
> > >  
> > >  	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
> > > @@ -448,6 +461,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
> > >  
> > >  	return 0;
> > >  
> > > +disable_ref_clk:
> > > +	clk_disable_unprepare(hsphy->ref_clk);
> > >  disable_ahb_clk:
> > >  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> > >  poweroff_phy:
> > > @@ -462,6 +477,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
> > >  
> > >  	reset_control_assert(hsphy->phy_reset);
> > >  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> > > +	clk_disable_unprepare(hsphy->ref_clk);
> > >  	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
> > >  	hsphy->phy_initialized = false;
> > >  
> > > -- 
> > > 2.40.1
> > >
> 
> Best,
> Adrien
>
Adrien Thierry June 1, 2023, 5:09 p.m. UTC | #5
On Tue, May 30, 2023 at 07:34:41PM -0700, Bjorn Andersson wrote:
> On Tue, May 30, 2023 at 02:46:05PM -0400, Adrien Thierry wrote:
> > Hi Bjorn, thanks for your reply!
> > 
> > On Mon, May 29, 2023 at 02:16:29PM -0700, Bjorn Andersson wrote:
> > > On Mon, May 29, 2023 at 02:56:36PM -0400, Adrien Thierry wrote:
> > > > The driver is not enabling the ref clock, which thus gets disabled by
> > > > the clk_disable_unused initcall. This leads to the dwc3 controller
> > > > failing to initialize if probed after clk_disable_unused is called, for
> > > > instance when the driver is built as a module.
> > > > 
> > > 
> > > Good catch!
> > > 
> > > A side note though, clk_disable_unused() has no way to take kernel
> > > modules into consideration today, and it doesn't handle the case where
> > > clock drivers are built as modules appropriately.
> > > Work has started to address this, but as of todaybooting the system
> > > without clk_ignore_unused is not recommended...
> > >
> > 
> > For my understanding, do you have an example of a situation that would
> > fail with modules when not using clk_ignore_unused?
> > 
> 
> The prime example relates to the display clocks, where the bootloader
> typically leave clocks on and at lateinit we haven't yet loaded enough
> modules to bring up the display. And to make matters worse, the code
> ends up disabling the PLL feeding the clock tree without first disabling
> some of the muxes - which has side effects...
> 
> Another case, although much less concerning in the short run, is when
> you have any of the clock drivers built as modules. clk_disable_unused()
> will be invoked before they are loaded, so your expectation that unused
> clocks are turned off is just not fulfilled.
>

Thanks for the explanation!

> > > > To fix this, add calls to clk_prepare_enable/clk_disable_unprepare at
> > > > the proper places.
> > > > 
> > > 
> > > If I parse the downstream kernel correctly the refclock should be
> > > turned off across runtime and system suspend as well.
> > > 
> > 
> > Which downstream kernel are you using? I'm not seing a system suspend
> > callback in mine [1]. refclock should be turned off on runtime suspend in
> > my patch, in qcom_snps_hsphy_suspend, which is called by
> > qcom_snps_hsphy_runtime_suspend.
> > 
> 
> Forgive me, but isn't [1] the driver you're modifying?
> 
> I'm looking at [2], with set_suspend() being invoked from the runtime
> and system suspend/resume handlers.
> 
> > [1] https://git.codelinaro.org/clo/la/kernel/ark-5.14/-/blob/kernel.lnx.5.14.r2-rel/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> 
> [2] https://git.codelinaro.org/clo/la/kernel/msm-5.4/-/blob/LV.AU.1.2.1.r2-05300-gen3meta.0/drivers/usb/phy/phy-msm-snps-hs.c#L908
> 

Thank you. The femto PHY driver is not using set_suspend(), but has
runtime PM ops. Is it ok if I add the system sleep PM ops as well with
SET_SYSTEM_SLEEP_PM_OPS() ?

> Regards,
> Bjorn
> 
> > 
> > > Regards,
> > > Bjorn
> > > 
> > > > Signed-off-by: Adrien Thierry <athierry@redhat.com>
> > > > ---
> > > >  drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c | 20 +++++++++++++++++--
> > > >  1 file changed, 18 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> > > > index 6c237f3cc66d..8abf482e81a8 100644
> > > > --- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> > > > +++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
> > > > @@ -166,6 +166,7 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
> > > >  	}
> > > >  
> > > >  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> > > > +	clk_disable_unprepare(hsphy->ref_clk);
> > > >  	return 0;
> > > >  }
> > > >  
> > > > @@ -181,6 +182,12 @@ static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
> > > >  		return ret;
> > > >  	}
> > > >  
> > > > +	ret = clk_prepare_enable(hsphy->ref_clk);
> > > > +	if (ret) {
> > > > +		dev_err(&hsphy->phy->dev, "failed to enable ref clock\n");
> > > > +		return ret;
> > > > +	}
> > > > +
> > > >  	return 0;
> > > >  }
> > > >  
> > > > @@ -380,10 +387,16 @@ static int qcom_snps_hsphy_init(struct phy *phy)
> > > >  		goto poweroff_phy;
> > > >  	}
> > > >  
> > > > +	ret = clk_prepare_enable(hsphy->ref_clk);
> > > > +	if (ret) {
> > > > +		dev_err(&phy->dev, "failed to enable ref clock, %d\n", ret);
> > > > +		goto disable_ahb_clk;
> > > > +	}
> > > > +
> > > >  	ret = reset_control_assert(hsphy->phy_reset);
> > > >  	if (ret) {
> > > >  		dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
> > > > -		goto disable_ahb_clk;
> > > > +		goto disable_ref_clk;
> > > >  	}
> > > >  
> > > >  	usleep_range(100, 150);
> > > > @@ -391,7 +404,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
> > > >  	ret = reset_control_deassert(hsphy->phy_reset);
> > > >  	if (ret) {
> > > >  		dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
> > > > -		goto disable_ahb_clk;
> > > > +		goto disable_ref_clk;
> > > >  	}
> > > >  
> > > >  	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
> > > > @@ -448,6 +461,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
> > > >  
> > > >  	return 0;
> > > >  
> > > > +disable_ref_clk:
> > > > +	clk_disable_unprepare(hsphy->ref_clk);
> > > >  disable_ahb_clk:
> > > >  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> > > >  poweroff_phy:
> > > > @@ -462,6 +477,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
> > > >  
> > > >  	reset_control_assert(hsphy->phy_reset);
> > > >  	clk_disable_unprepare(hsphy->cfg_ahb_clk);
> > > > +	clk_disable_unprepare(hsphy->ref_clk);
> > > >  	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
> > > >  	hsphy->phy_initialized = false;
> > > >  
> > > > -- 
> > > > 2.40.1
> > > >
> > 
> > Best,
> > Adrien
> >
diff mbox series

Patch

diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
index 6c237f3cc66d..8abf482e81a8 100644
--- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
+++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
@@ -166,6 +166,7 @@  static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
 	}
 
 	clk_disable_unprepare(hsphy->cfg_ahb_clk);
+	clk_disable_unprepare(hsphy->ref_clk);
 	return 0;
 }
 
@@ -181,6 +182,12 @@  static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
 		return ret;
 	}
 
+	ret = clk_prepare_enable(hsphy->ref_clk);
+	if (ret) {
+		dev_err(&hsphy->phy->dev, "failed to enable ref clock\n");
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -380,10 +387,16 @@  static int qcom_snps_hsphy_init(struct phy *phy)
 		goto poweroff_phy;
 	}
 
+	ret = clk_prepare_enable(hsphy->ref_clk);
+	if (ret) {
+		dev_err(&phy->dev, "failed to enable ref clock, %d\n", ret);
+		goto disable_ahb_clk;
+	}
+
 	ret = reset_control_assert(hsphy->phy_reset);
 	if (ret) {
 		dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
-		goto disable_ahb_clk;
+		goto disable_ref_clk;
 	}
 
 	usleep_range(100, 150);
@@ -391,7 +404,7 @@  static int qcom_snps_hsphy_init(struct phy *phy)
 	ret = reset_control_deassert(hsphy->phy_reset);
 	if (ret) {
 		dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
-		goto disable_ahb_clk;
+		goto disable_ref_clk;
 	}
 
 	qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
@@ -448,6 +461,8 @@  static int qcom_snps_hsphy_init(struct phy *phy)
 
 	return 0;
 
+disable_ref_clk:
+	clk_disable_unprepare(hsphy->ref_clk);
 disable_ahb_clk:
 	clk_disable_unprepare(hsphy->cfg_ahb_clk);
 poweroff_phy:
@@ -462,6 +477,7 @@  static int qcom_snps_hsphy_exit(struct phy *phy)
 
 	reset_control_assert(hsphy->phy_reset);
 	clk_disable_unprepare(hsphy->cfg_ahb_clk);
+	clk_disable_unprepare(hsphy->ref_clk);
 	regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
 	hsphy->phy_initialized = false;