From: Stephen Boyd <sboyd@codeaurora.org>
To: Dong Aisheng <aisheng.dong@nxp.com>
Cc: linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, mturquette@baylibre.com,
dongas86@gmail.com, shawnguo@kernel.org, Anson.Huang@nxp.com,
ping.bai@nxp.com
Subject: Re: [PATCH V2 01/10] clk: clk-divider: add CLK_DIVIDER_ZERO_GATE clk support
Date: Thu, 2 Nov 2017 00:50:39 -0700 [thread overview]
Message-ID: <20171102075039.GU30645@codeaurora.org> (raw)
In-Reply-To: <1499946435-7177-2-git-send-email-aisheng.dong@nxp.com>
On 07/13, Dong Aisheng wrote:
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 9bb472c..55f8c41 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -123,6 +123,9 @@ unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
> struct clk_divider *divider = to_clk_divider(hw);
> unsigned int div;
>
> + if (flags & CLK_DIVIDER_ZERO_GATE && !val)
> + return 0;
> +
> div = _get_div(table, val, flags, divider->width);
> if (!div) {
> WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO),
> @@ -141,8 +144,13 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
> struct clk_divider *divider = to_clk_divider(hw);
> unsigned int val;
>
> - val = clk_readl(divider->reg) >> divider->shift;
> - val &= div_mask(divider->width);
> + if ((divider->flags & CLK_DIVIDER_ZERO_GATE) &&
> + !clk_hw_is_enabled(hw)) {
This seems racy. Are we holding the register lock here?
> + val = divider->cached_val;
> + } else {
> + val = clk_readl(divider->reg) >> divider->shift;
> + val &= div_mask(divider->width);
> + }
>
> return divider_recalc_rate(hw, parent_rate, val, divider->table,
> divider->flags);
> @@ -392,6 +400,12 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
> value = divider_get_val(rate, parent_rate, divider->table,
> divider->width, divider->flags);
>
> + if ((divider->flags & CLK_DIVIDER_ZERO_GATE) &&
> + !clk_hw_is_enabled(hw)) {
Same racy comment here.
> + divider->cached_val = value;
> + return 0;
> + }
> +
> if (divider->lock)
> spin_lock_irqsave(divider->lock, flags);
> else
> @@ -414,10 +428,85 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
> return 0;
> }
>
> +static int clk_divider_enable(struct clk_hw *hw)
> +{
> + struct clk_divider *divider = to_clk_divider(hw);
> + unsigned long flags = 0;
> + u32 val;
> +
> + if (!(divider->flags & CLK_DIVIDER_ZERO_GATE))
> + return 0;
This is not good. We will always jump to these functions on
enable/disable for a divider although 99.9% of all dividers that
exist won't need to run this code at all.
Can you please move this logic into your own divider
implementation? The flag can be added to the generic layer if
necessary but I'd prefer to see this logic kept in the driver
that uses it. If we get more than one driver doing the cached
divider thing then we can think about moving it to the more
generic place like here, but for now we should be able to keep
this contained away from the basic types and handled by the
quirky driver that needs it.
> +
> + if (!divider->cached_val) {
> + pr_err("%s: no valid preset rate\n", clk_hw_get_name(hw));
> + return -EINVAL;
> + }
> +
> + if (divider->lock)
> + spin_lock_irqsave(divider->lock, flags);
> + else
> + __acquire(divider->lock);
> +
> + /* restore div val */
> + val = clk_readl(divider->reg);
> + val |= divider->cached_val << divider->shift;
> + clk_writel(val, divider->reg);
> +
> + if (divider->lock)
> + spin_unlock_irqrestore(divider->lock, flags);
> + else
> + __release(divider->lock);
> +
> + return 0;
> +}
> +
> +static void clk_divider_disable(struct clk_hw *hw)
> +{
> + struct clk_divider *divider = to_clk_divider(hw);
> + unsigned long flags = 0;
> + u32 val;
> +
> + if (!(divider->flags & CLK_DIVIDER_ZERO_GATE))
> + return;
> +
> + if (divider->lock)
> + spin_lock_irqsave(divider->lock, flags);
> + else
> + __acquire(divider->lock);
> +
> + /* store the current div val */
> + val = clk_readl(divider->reg) >> divider->shift;
> + val &= div_mask(divider->width);
> + divider->cached_val = val;
> + clk_writel(0, divider->reg);
> +
> + if (divider->lock)
> + spin_unlock_irqrestore(divider->lock, flags);
> + else
> + __release(divider->lock);
> +}
> +
> +static int clk_divider_is_enabled(struct clk_hw *hw)
> +{
> + struct clk_divider *divider = to_clk_divider(hw);
> + u32 val;
> +
> + if (!(divider->flags & CLK_DIVIDER_ZERO_GATE))
> + return __clk_get_enable_count(hw->clk);
The plan was to delete this API once OMAP stopped using it.
clk_hw_is_enabled() doesn't work?
> +
> + val = clk_readl(divider->reg) >> divider->shift;
> + val &= div_mask(divider->width);
> +
> + return val ? 1 : 0;
> +}
> +
> const struct clk_ops clk_divider_ops = {
> .recalc_rate = clk_divider_recalc_rate,
> .round_rate = clk_divider_round_rate,
> .set_rate = clk_divider_set_rate,
> + .enable = clk_divider_enable,
> + .disable = clk_divider_disable,
> + .is_enabled = clk_divider_is_enabled,
> };
> EXPORT_SYMBOL_GPL(clk_divider_ops);
>
> @@ -436,6 +525,7 @@ static struct clk_hw *_register_divider(struct device *dev, const char *name,
> struct clk_divider *div;
> struct clk_hw *hw;
> struct clk_init_data init;
> + u32 val;
> int ret;
>
> if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
> @@ -468,6 +558,12 @@ static struct clk_hw *_register_divider(struct device *dev, const char *name,
> div->hw.init = &init;
> div->table = table;
>
> + if (div->flags & CLK_DIVIDER_ZERO_GATE) {
> + val = clk_readl(reg) >> shift;
> + val &= div_mask(width);
> + div->cached_val = val;
> + }
What if it isn't on? Setting cached_val to 0 is ok?
> +
> /* register the clock */
> hw = &div->hw;
> ret = clk_hw_register(dev, hw);
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
next prev parent reply other threads:[~2017-11-02 7:50 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-07-13 11:47 [PATCH V2 00/10] clk: add imx7ulp clk support Dong Aisheng
2017-07-13 11:47 ` [PATCH V2 01/10] clk: clk-divider: add CLK_DIVIDER_ZERO_GATE " Dong Aisheng
2017-11-02 7:50 ` Stephen Boyd [this message]
2017-12-20 14:27 ` Dong Aisheng
2017-12-22 1:24 ` Stephen Boyd
2017-12-22 3:42 ` Dong Aisheng
2018-01-17 3:00 ` Dong Aisheng
2017-07-13 11:47 ` [PATCH V2 02/10] clk: reparent orphans after critical clocks enabled Dong Aisheng
2017-11-02 7:36 ` Stephen Boyd
2017-12-20 14:33 ` Dong Aisheng
2017-12-21 18:32 ` Stephen Boyd
2017-12-22 1:55 ` Stephen Boyd
2017-12-22 2:54 ` Dong Aisheng
2017-07-13 11:47 ` [PATCH V2 03/10] clk: fractional-divider: add CLK_FRAC_DIVIDER_ZERO_BASED flag support Dong Aisheng
2017-07-13 11:47 ` [PATCH V2 04/10] clk: imx: add pllv4 support Dong Aisheng
2017-07-13 11:47 ` [PATCH V2 05/10] clk: imx: add pfdv2 support Dong Aisheng
2017-07-13 11:47 ` [PATCH V2 06/10] clk: imx: add composite clk support Dong Aisheng
2017-07-13 11:47 ` [PATCH V2 07/10] dt-bindings: clock: add imx7ulp clock binding doc Dong Aisheng
2017-07-13 11:47 ` [PATCH V2 08/10] clk: imx: make mux parent strings const Dong Aisheng
2017-07-13 11:47 ` [PATCH V2 09/10] clk: imx: implement new clk_hw based APIs Dong Aisheng
2017-07-13 11:47 ` [PATCH V2 10/10] clk: imx: add imx7ulp clk driver Dong Aisheng
2017-07-26 2:57 ` [PATCH V2 00/10] clk: add imx7ulp clk support A.s. Dong
2017-08-24 7:05 ` A.s. Dong
2017-09-11 7:25 ` Dong Aisheng
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=20171102075039.GU30645@codeaurora.org \
--to=sboyd@codeaurora.org \
--cc=Anson.Huang@nxp.com \
--cc=aisheng.dong@nxp.com \
--cc=dongas86@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mturquette@baylibre.com \
--cc=ping.bai@nxp.com \
--cc=shawnguo@kernel.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).