From: Maxime Ripard <maxime.ripard@free-electrons.com>
To: Stephen Boyd <sboyd@codeaurora.org>
Cc: Mike Turquette <mturquette@baylibre.com>,
Emilio Lopez <emilio@elopez.com.ar>,
linux-arm-kernel@lists.infradead.org,
Chen-Yu Tsai <wens@csie.org>, Hans de Goede <hdegoede@redhat.com>,
linux-clk@vger.kernel.org, linux-sunxi@googlegroups.com
Subject: Re: [PATCH v3 1/5] clk: Add a basic multiplier clock
Date: Mon, 5 Oct 2015 12:19:32 +0200 [thread overview]
Message-ID: <20151005101932.GH2696@lukather> (raw)
In-Reply-To: <20151002204308.GY12338@codeaurora.org>
[-- Attachment #1: Type: text/plain, Size: 5454 bytes --]
Hi,
On Fri, Oct 02, 2015 at 01:43:08PM -0700, Stephen Boyd wrote:
> On 09/29, Maxime Ripard wrote:
> > diff --git a/drivers/clk/clk-multiplier.c b/drivers/clk/clk-multiplier.c
> > new file mode 100644
> > index 000000000000..61097e365d55
> > --- /dev/null
> > +++ b/drivers/clk/clk-multiplier.c
> > @@ -0,0 +1,176 @@
> > +/*
> > + * Copyright (C) 2015 Maxime Ripard <maxime.ripard@free-electrons.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + */
> > +#include <linux/module.h>
>
> Maybe export.h is more appropriate?
Indeed.
> > +#include <linux/clk-provider.h>
> > +#include <linux/slab.h>
> > +#include <linux/err.h>
> > +#include <linux/of.h>
> > +
> > +#define to_clk_multiplier(_hw) container_of(_hw, struct clk_multiplier, hw)
> > +
> > +static unsigned long __get_mult(struct clk_multiplier *mult,
> > + unsigned long rate,
> > + unsigned long parent_rate)
> > +{
> > + if (mult->flags & CLK_MULTIPLIER_ROUND_CLOSEST)
> > + return DIV_ROUND_CLOSEST(rate, parent_rate);
>
> We should include kernel.h for this macro.
Ack.
> > +
> > + return rate / parent_rate;
> > +}
> > +
> > +static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw,
> > + unsigned long parent_rate)
> > +{
> > + struct clk_multiplier *mult = to_clk_multiplier(hw);
> > + unsigned long val;
> > +
> > + val = clk_readl(mult->reg) >> mult->shift;
> > + val &= GENMASK(mult->width, 0);
>
> and bitops.h for GENMASK
Ack.
> > +
> > + if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS)
> > + val = 1;
> > +
> > + return parent_rate * val;
> > +}
> > +
> > +static bool __is_best_rate(unsigned long rate, unsigned long new,
> > + unsigned long best, unsigned long flags)
> > +{
> > + if (flags & CLK_MULTIPLIER_ROUND_CLOSEST)
>
> Is the only difference in this function vs the divider one that
> flag? Maybe we should make this function generic to the framework
> and pass a flag indicating closest or not.
Actually, the logic is also reversed.
The divider driver will always try to find some rate that is higher
than the one we already have, without going above than the one
requested.
Here, we're tring to be lower than the best rate, without going below
the requested rate.
>
> > + return abs(rate - new) < abs(rate - best);
> > +
> > + return new >= rate && new < best;
> > +}
> > +
> > +static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
> > + unsigned long *best_parent_rate,
> > + u8 width, unsigned long flags)
> > +{
> > + unsigned long orig_parent_rate = *best_parent_rate;
> > + unsigned long parent_rate, current_rate, best_rate = ~0;
> > + unsigned int i, bestmult = 0;
> > +
> > + if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT))
>
> Please use clk_hw_get_flags. I'd *really* like to kill
> __clk_get_flags() but we still have one user in omap code.
Ack.
>
> > + return rate / *best_parent_rate;
> > +
> > + for (i = 1; i < ((1 << width) - 1); i++) {
> > + if (rate * i == orig_parent_rate) {
> > + /*
> > + * This is the best case for us if we have a
> > + * perfect match without changing the parent
> > + * rate.
> > + */
> > + *best_parent_rate = orig_parent_rate;
> > + return i;
> > + }
> > +
> > + parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
> > + rate / i);
> > + current_rate = parent_rate * i;
> > +
> > + if (__is_best_rate(rate, current_rate, best_rate, flags)) {
> > + bestmult = i;
> > + best_rate = current_rate;
> > + *best_parent_rate = parent_rate;
> > + }
> > + }
> > +
> > + return bestmult;
> > +}
> > +
> > +static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate,
> > + unsigned long parent_rate)
> > +{
> > + struct clk_multiplier *mult = to_clk_multiplier(hw);
> > + unsigned long factor = __get_mult(mult, rate, parent_rate);
> > + unsigned long uninitialized_var(flags);
>
> hmmm ok. We set it to 0 in other drivers.
I'll change it then.
>
> > + unsigned long val;
> > +
> > + if (mult->lock)
> > + spin_lock_irqsave(mult->lock, flags);
>
> This needs the same "trick" that we did in the generic clock
> types to avoid sparse warnings.
The __acquire call ?
> > +
> > + val = clk_readl(mult->reg);
> > + val &= ~GENMASK(mult->width + mult->shift, mult->shift);
> > + val |= factor << mult->shift;
> > + clk_writel(val, mult->reg);
> > +
> > + if (mult->lock)
> > + spin_unlock_irqrestore(mult->lock, flags);
> > +
> > + return 0;
> > +}
> > +
> > +struct clk *clk_register_multiplier(struct device *dev, const char *name,
> > + const char *parent_name,
> > + unsigned long flags,
> > + void __iomem *reg, u8 shift, u8 width,
> > + u8 clk_mult_flags, spinlock_t *lock)
> > +{
> > + struct clk_init_data init;
> > + struct clk_multiplier *mult;
> > + struct clk *clk;
> > +
> > + mult = kmalloc(sizeof(*mult), GFP_KERNEL);
> > + if (!mult) {
> > + pr_err("%s: could not allocate multiplier clk\n", __func__);
>
> We don't need allocation error messages.
Ack.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
next prev parent reply other threads:[~2015-10-05 10:19 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-29 7:39 [PATCH v3 0/5] clk: sunxi: Add support for the Audio PLL Maxime Ripard
2015-09-29 7:39 ` [PATCH v3 1/5] clk: Add a basic multiplier clock Maxime Ripard
2015-10-02 20:43 ` Stephen Boyd
2015-10-05 10:19 ` Maxime Ripard [this message]
2015-10-05 18:09 ` Stephen Boyd
2015-10-07 11:04 ` Maxime Ripard
2015-10-07 19:17 ` Stephen Boyd
2015-09-29 7:39 ` [PATCH v3 2/5] clk: sunxi: Add a driver for the PLL2 Maxime Ripard
2015-09-29 7:39 ` [PATCH v3 3/5] clk: sunxi: pll2: Add A13 support Maxime Ripard
2015-09-29 7:39 ` [PATCH v3 4/5] clk: sunxi: codec clock support Maxime Ripard
2015-10-02 20:44 ` Stephen Boyd
2015-10-05 9:05 ` Maxime Ripard
2015-09-29 7:39 ` [PATCH v3 5/5] clk: sunxi: mod1 " Maxime Ripard
2015-10-02 20:45 ` Stephen Boyd
2015-10-05 9:44 ` Maxime Ripard
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=20151005101932.GH2696@lukather \
--to=maxime.ripard@free-electrons.com \
--cc=emilio@elopez.com.ar \
--cc=hdegoede@redhat.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-sunxi@googlegroups.com \
--cc=mturquette@baylibre.com \
--cc=sboyd@codeaurora.org \
--cc=wens@csie.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).