linux-samsung-soc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ulf Hansson <ulf.hansson@linaro.org>
To: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: linux-clk <linux-clk@vger.kernel.org>,
	"linux-pm@vger.kernel.org" <linux-pm@vger.kernel.org>,
	linux-samsung-soc <linux-samsung-soc@vger.kernel.org>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	Stephen Boyd <sboyd@codeaurora.org>,
	Michael Turquette <mturquette@baylibre.com>,
	Sylwester Nawrocki <s.nawrocki@samsung.com>,
	Chanwoo Choi <cw00.choi@samsung.com>,
	Inki Dae <inki.dae@samsung.com>,
	Krzysztof Kozlowski <krzk@kernel.org>,
	Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Subject: Re: [PATCH v5 1/4] clk: Add support for runtime PM
Date: Mon, 13 Mar 2017 13:20:14 +0100	[thread overview]
Message-ID: <CAPDyKFpe1ujO+ZMJ=pYG+NupxSAgY6WjgDkybkUhD1g6YpEfkg@mail.gmail.com> (raw)
In-Reply-To: <1485345194-3196-2-git-send-email-m.szyprowski@samsung.com>

On 25 January 2017 at 12:53, Marek Szyprowski <m.szyprowski@samsung.com> wrote:
> Registers for some clocks might be located in the SOC area, which are under the
> power domain. To enable access to those registers respective domain has to be
> turned on. Additionally, registers for such clocks will usually loose its
> contents when power domain is turned off, so additional saving and restoring of
> them might be needed in the clock controller driver.
>
> This patch adds basic infrastructure in the clocks core to allow implementing
> driver for such clocks under power domains. Clock provider can supply a
> struct device pointer, which is the used by clock core for tracking and managing
> clock's controller runtime pm state. Each clk_prepare() operation
> will first call pm_runtime_get_sync() on the supplied device, while
> clk_unprepare() will do pm_runtime_put() at the end.
>
> Additional calls to pm_runtime_get/put functions are required to ensure that any
> register access (like calculating/changing clock rates and unpreparing/disabling
> unused clocks on boot) will be done with clock controller in runtime resumend
> state.
>
> When one wants to register clock controller, which make use of this feature, he
> has to:
> 1. Provide a struct device to the core when registering the provider.
> 2. Ensure to enable runtime PM for that device before registering clocks.
> 3. Make sure that the runtime PM status of the controller device reflects
>    the HW state.
>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/clk/clk.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 117 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 0fb39fe217d1..5b9d52c8185b 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -21,6 +21,7 @@
>  #include <linux/of.h>
>  #include <linux/device.h>
>  #include <linux/init.h>
> +#include <linux/pm_runtime.h>
>  #include <linux/sched.h>
>  #include <linux/clkdev.h>
>
> @@ -46,6 +47,7 @@ struct clk_core {
>         const struct clk_ops    *ops;
>         struct clk_hw           *hw;
>         struct module           *owner;
> +       struct device           *dev;
>         struct clk_core         *parent;
>         const char              **parent_names;
>         struct clk_core         **parents;
> @@ -87,6 +89,26 @@ struct clk {
>         struct hlist_node clks_node;
>  };
>
> +/***           runtime pm          ***/
> +static int clk_pm_runtime_get(struct clk_core *core)
> +{
> +       int ret = 0;
> +
> +       if (!core->dev)
> +               return 0;
> +
> +       ret = pm_runtime_get_sync(core->dev);
> +       return ret < 0 ? ret : 0;
> +}
> +
> +static void clk_pm_runtime_put(struct clk_core *core)
> +{
> +       if (!core->dev)
> +               return;
> +
> +       pm_runtime_put(core->dev);

I would rather change this to a pm_runtime_put_sync().

The reason is that users of clocks (drivers being clock consumers),
which has runtime PM support deployed, often performs clock
gating/ungating from their runtime PM callbacks.

In other words, using async or sync runtime PM APIs, is better decided
by the user of the clock itself.


> +}
> +
>  /***           locking             ***/
>  static void clk_prepare_lock(void)
>  {
> @@ -150,6 +172,8 @@ static void clk_enable_unlock(unsigned long flags)
>
>  static bool clk_core_is_prepared(struct clk_core *core)
>  {
> +       bool status;
> +
>         /*
>          * .is_prepared is optional for clocks that can prepare
>          * fall back to software usage counter if it is missing
> @@ -157,11 +181,20 @@ static bool clk_core_is_prepared(struct clk_core *core)
>         if (!core->ops->is_prepared)
>                 return core->prepare_count;
>
> -       return core->ops->is_prepared(core->hw);
> +       if (clk_pm_runtime_get(core) == 0) {
> +               status = core->ops->is_prepared(core->hw);
> +               clk_pm_runtime_put(core);
> +       } else {
> +               status = false;

To simplify this, you could assign status to false when defining it.
Perhaps also rename it from "status" to "ret", as that name is more
commonly used, I think.

> +       }
> +
> +       return status;
>  }
>
>  static bool clk_core_is_enabled(struct clk_core *core)
>  {
> +       bool status;

Maybe name the variable ret instead, to be more consistent.

> +
>         /*
>          * .is_enabled is only mandatory for clocks that gate
>          * fall back to software usage counter if .is_enabled is missing
> @@ -169,7 +202,30 @@ static bool clk_core_is_enabled(struct clk_core *core)
>         if (!core->ops->is_enabled)
>                 return core->enable_count;
>
> -       return core->ops->is_enabled(core->hw);
> +       /*
> +        * Check if clock controller's device is runtime active before
> +        * calling .is_enabled callback. If not, assume that clock is
> +        * disabled, because we might be called from atomic context, from
> +        * which pm_runtime_get() is not allowed.
> +        * This function is called mainly from clk_disable_unused_subtree,
> +        * which ensures proper runtime pm activation of controller before
> +        * taking enable spinlock, but the below check is needed if one tries
> +        * to call it from other places.
> +        */
> +       if (core->dev) {
> +               pm_runtime_get_noresume(core->dev);
> +               if (!pm_runtime_active(core->dev)) {
> +                       status = false;
> +                       goto done;
> +               }
> +       }
> +
> +       status = core->ops->is_enabled(core->hw);
> +done:
> +       if (core->dev)
> +               pm_runtime_put(core->dev);

Let's use clk_pm_runtime_put() here instead.

> +
> +       return status;
>  }
>

[...]

> @@ -1036,9 +1111,13 @@ long clk_get_accuracy(struct clk *clk)
>  static unsigned long clk_recalc(struct clk_core *core,
>                                 unsigned long parent_rate)
>  {
> -       if (core->ops->recalc_rate)
> -               return core->ops->recalc_rate(core->hw, parent_rate);
> -       return parent_rate;
> +       unsigned long rate = parent_rate;
> +
> +       if (core->ops->recalc_rate && clk_pm_runtime_get(core) == 0) {

To be consistent, let's not check against "== 0", but instead just use
a "!" before the expression.

> +               rate = core->ops->recalc_rate(core->hw, parent_rate);
> +               clk_pm_runtime_put(core);
> +       }
> +       return rate;
>  }
>

[...]

Overall, this looks good to me. So with the minor changes suggested
above, feel free to add my reviewed-by tag.

Kind regards
Uffe

  reply	other threads:[~2017-03-13 12:20 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20170125115327eucas1p172866fa87417f59f1dea60185d6d8b60@eucas1p1.samsung.com>
2017-01-25 11:53 ` [PATCH v5 0/4] Add runtime PM support for clocks (on Exynos SoC example) Marek Szyprowski
     [not found]   ` <CGME20170125115328eucas1p1d97fac29286805b58039f8aec2b9bfe6@eucas1p1.samsung.com>
2017-01-25 11:53     ` [PATCH v5 1/4] clk: Add support for runtime PM Marek Szyprowski
2017-03-13 12:20       ` Ulf Hansson [this message]
     [not found]   ` <CGME20170125115329eucas1p1fc59d9be3421bc763d16aa331375b9f6@eucas1p1.samsung.com>
2017-01-25 11:53     ` [PATCH v5 2/4] clk: samsung: " Marek Szyprowski
2017-03-13 13:34       ` Ulf Hansson
     [not found]   ` <CGME20170125115329eucas1p1f42bbb54d5973b6192e964dc8b3a8081@eucas1p1.samsung.com>
2017-01-25 11:53     ` [PATCH v5 3/4] clk: samsung: exynos5433: Add runtime PM support Marek Szyprowski
2017-03-13 13:31       ` Ulf Hansson
2017-03-22  8:26         ` Marek Szyprowski
     [not found]   ` <CGME20170125115330eucas1p16f9de097e0966bc9d9901bc27caa085c@eucas1p1.samsung.com>
2017-01-25 11:53     ` [PATCH v5 4/4] clk: samsung: exynos-audss: Use runtime PM Marek Szyprowski
2017-01-26  1:28       ` kbuild test robot

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='CAPDyKFpe1ujO+ZMJ=pYG+NupxSAgY6WjgDkybkUhD1g6YpEfkg@mail.gmail.com' \
    --to=ulf.hansson@linaro.org \
    --cc=b.zolnierkie@samsung.com \
    --cc=cw00.choi@samsung.com \
    --cc=inki.dae@samsung.com \
    --cc=krzk@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=mturquette@baylibre.com \
    --cc=s.nawrocki@samsung.com \
    --cc=sboyd@codeaurora.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).