All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Cc: Andy Gross <agross@kernel.org>, Rob Herring <robh+dt@kernel.org>,
	Stephen Boyd <sboyd@kernel.org>, Taniya Das <tdas@codeaurora.org>,
	Jonathan Marek <jonathan@marek.ca>,
	Michael Turquette <mturquette@baylibre.com>,
	linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org,
	linux-clk@vger.kernel.org,
	Bryan O'Donoghue <bryan.odonoghue@linaro.org>,
	Mark Brown <broonie@kernel.org>,
	Ulf Hansson <ulf.hansson@linaro.org>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 4/7] clk: qcom: gdsc: call runtime PM functions for the provider device
Date: Fri, 9 Jul 2021 13:54:20 -0500	[thread overview]
Message-ID: <YOibXCHvnG70ftQ0@yoga> (raw)
In-Reply-To: <20210709173202.667820-5-dmitry.baryshkov@linaro.org>

On Fri 09 Jul 12:31 CDT 2021, Dmitry Baryshkov wrote:

> In order to properly handle runtime PM status of the provider device,
> call pm_runtime_get/pm_runtime_put on the clock controller device.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>  drivers/clk/qcom/gdsc.c | 66 ++++++++++++++++++++++++++++++++++++++---
>  drivers/clk/qcom/gdsc.h |  2 ++
>  2 files changed, 64 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c
> index ccd36617d067..6bec31fccb09 100644
> --- a/drivers/clk/qcom/gdsc.c
> +++ b/drivers/clk/qcom/gdsc.c
> @@ -11,6 +11,7 @@
>  #include <linux/kernel.h>
>  #include <linux/ktime.h>
>  #include <linux/pm_domain.h>
> +#include <linux/pm_runtime.h>
>  #include <linux/regmap.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/reset-controller.h>
> @@ -50,6 +51,30 @@ enum gdsc_status {
>  	GDSC_ON
>  };
>  
> +static int gdsc_pm_runtime_get(struct gdsc *sc)
> +{
> +	int ret;
> +
> +	if (!sc->rpm_dev)
> +		return 0;
> +
> +	ret = pm_runtime_get_sync(sc->rpm_dev);
> +	if (ret < 0) {
> +		pm_runtime_put_noidle(sc->rpm_dev);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int gdsc_pm_runtime_put(struct gdsc *sc)
> +{
> +	if (!sc->rpm_dev)
> +		return 0;
> +
> +	return pm_runtime_put_sync(sc->rpm_dev);
> +}
> +
>  /* Returns 1 if GDSC status is status, 0 if not, and < 0 on error */
>  static int gdsc_check_status(struct gdsc *sc, enum gdsc_status status)
>  {
> @@ -232,9 +257,8 @@ static void gdsc_retain_ff_on(struct gdsc *sc)
>  	regmap_update_bits(sc->regmap, sc->gdscr, mask, mask);
>  }
>  
> -static int gdsc_enable(struct generic_pm_domain *domain)
> +static int _gdsc_enable(struct gdsc *sc)
>  {
> -	struct gdsc *sc = domain_to_gdsc(domain);
>  	int ret;
>  
>  	if (sc->pwrsts == PWRSTS_ON)
> @@ -290,11 +314,28 @@ static int gdsc_enable(struct generic_pm_domain *domain)
>  	return 0;
>  }
>  
> -static int gdsc_disable(struct generic_pm_domain *domain)
> +static int gdsc_enable(struct generic_pm_domain *domain)
>  {
>  	struct gdsc *sc = domain_to_gdsc(domain);
>  	int ret;
>  
> +	ret = gdsc_pm_runtime_get(sc);
> +	if (ret)
> +		return ret;
> +
> +	ret = _gdsc_enable(sc);
> +	if (ret) {
> +		gdsc_pm_runtime_put(sc);

I presume what you do here is to leave the pm_runtime state of dispcc
active if we succeeded in enabling the gdsc. But the gdsc is a subdomain
of the parent domain, so the framework should take case of its
dependency.

So the reason for gdsc_pm_runtime_get()/put() in this code path is so
that you can access the dispcc registers, i.e. I think you should
get()/put() regardless of the return value.

> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int _gdsc_disable(struct gdsc *sc)
> +{
> +	int ret;
> +
>  	if (sc->pwrsts == PWRSTS_ON)
>  		return gdsc_assert_reset(sc);
>  
> @@ -329,6 +370,18 @@ static int gdsc_disable(struct generic_pm_domain *domain)
>  	return 0;
>  }
>  
> +static int gdsc_disable(struct generic_pm_domain *domain)
> +{
> +	struct gdsc *sc = domain_to_gdsc(domain);
> +	int ret;
> +

If the gdsc is found to be on at initialization, the next operation that
will happen is gdsc_disable() and as you didn't activate the pm_runtime
state in gdsc_init() you would in theory get here with registers
unaccessible.

In practice though, the active gdsc should through the being a subdomain
of the parent domain keep power on for you, so you won't notice this
issue.

But as above, I think you should wrap _gdsc_disable() in a get()/put()
pair.

> +	ret = _gdsc_disable(sc);
> +	if (ret)
> +		return ret;
> +
> +	return gdsc_pm_runtime_put(sc);
> +}
> +
>  static int gdsc_init(struct gdsc *sc)
>  {
>  	u32 mask, val;
> @@ -425,6 +478,8 @@ int gdsc_register(struct gdsc_desc *desc,
>  	for (i = 0; i < num; i++) {
>  		if (!scs[i])
>  			continue;
> +		if (pm_runtime_enabled(dev))
> +			scs[i]->rpm_dev = dev;
>  		scs[i]->regmap = regmap;
>  		scs[i]->rcdev = rcdev;
>  		ret = gdsc_init(scs[i]);
> @@ -486,7 +541,10 @@ void gdsc_unregister(struct gdsc_desc *desc)
>   */
>  int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain)
>  {
> +	struct gdsc *sc = domain_to_gdsc(domain);
> +
>  	/* Do nothing but give genpd the impression that we were successful */
> -	return 0;
> +	/* Get the runtime PM device only */
> +	return gdsc_pm_runtime_get(sc);

Per above, if you let the framework deal with the gdsc's dependencies on
the parent domain and you only get()/put() for the sake of dispcc then
you don't need you don't need to do this to keep the subsequent
gdsc_disable() in balance.

>  }
>  EXPORT_SYMBOL_GPL(gdsc_gx_do_nothing_enable);
> diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h
> index 5bb396b344d1..a82982df0a55 100644
> --- a/drivers/clk/qcom/gdsc.h
> +++ b/drivers/clk/qcom/gdsc.h
> @@ -25,6 +25,7 @@ struct reset_controller_dev;
>   * @resets: ids of resets associated with this gdsc
>   * @reset_count: number of @resets
>   * @rcdev: reset controller
> + * @rpm_dev: runtime PM device
>   */
>  struct gdsc {
>  	struct generic_pm_domain	pd;
> @@ -58,6 +59,7 @@ struct gdsc {
>  
>  	const char 			*supply;
>  	struct regulator		*rsupply;
> +	struct device 			*rpm_dev;

This isn't just the "runtime pm device", it's the device this gdsc is
associated with. So "dev" sounds sufficient to me, but that requires
that you have a separate bool rpm_enabled to remember if
pm_runtime_enabled() was true during probe.

So unless we need "dev" for something else this might be sufficient.

Regards,
Bjorn

>  };
>  
>  struct gdsc_desc {
> -- 
> 2.30.2
> 

  reply	other threads:[~2021-07-09 18:54 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-09 17:31 [PATCH v3 0/7] clk: qcom: use power-domain for sm8250's clock controllers Dmitry Baryshkov
2021-07-09 17:31 ` [PATCH v3 1/7] dt-bindings: clock: qcom,dispcc-sm8x50: add mmcx power domain Dmitry Baryshkov
2021-07-09 18:54   ` Bjorn Andersson
2021-07-09 17:31 ` [PATCH v3 2/7] dt-bindings: clock: qcom,videocc: " Dmitry Baryshkov
2021-07-09 18:55   ` Bjorn Andersson
2021-07-09 17:31 ` [PATCH v3 3/7] clk: qcom: gdsc: enable optional power domain support Dmitry Baryshkov
2021-07-09 18:38   ` Bjorn Andersson
2021-07-09 21:28     ` Dmitry Baryshkov
2021-07-10  0:48       ` Bjorn Andersson
2021-07-09 17:31 ` [PATCH v3 4/7] clk: qcom: gdsc: call runtime PM functions for the provider device Dmitry Baryshkov
2021-07-09 18:54   ` Bjorn Andersson [this message]
2021-07-09 22:10     ` Dmitry Baryshkov
2021-07-10  0:53       ` Bjorn Andersson
2021-07-09 17:32 ` [PATCH v3 5/7] arm64: dts: qcom: sm8250: remove mmcx regulator Dmitry Baryshkov
2021-07-09 18:55   ` Bjorn Andersson
2021-07-09 17:32 ` [PATCH v3 6/7] clk: qcom: dispcc-sm8250: stop using " Dmitry Baryshkov
2021-07-09 18:55   ` Bjorn Andersson
2021-07-09 17:32 ` [PATCH v3 7/7] clk: qcom: videocc-sm8250: " Dmitry Baryshkov
2021-07-09 18:55   ` Bjorn Andersson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YOibXCHvnG70ftQ0@yoga \
    --to=bjorn.andersson@linaro.org \
    --cc=agross@kernel.org \
    --cc=broonie@kernel.org \
    --cc=bryan.odonoghue@linaro.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dmitry.baryshkov@linaro.org \
    --cc=jonathan@marek.ca \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mturquette@baylibre.com \
    --cc=robh+dt@kernel.org \
    --cc=sboyd@kernel.org \
    --cc=tdas@codeaurora.org \
    --cc=ulf.hansson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.