From: Boris BREZILLON <boris.brezillon@free-electrons.com>
To: Soren Brinkmann <soren.brinkmann@xilinx.com>
Cc: "Mike Turquette" <mturquette@linaro.org>,
"Rafael J. Wysocki" <rjw@rjwysocki.net>,
"Viresh Kumar" <viresh.kumar@linaro.org>,
"Russell King" <linux@arm.linux.org.uk>,
linux-pm@vger.kernel.org,
"Nicolas Ferre" <nicolas.ferre@atmel.com>,
"Michal Simek" <michal.simek@xilinx.com>,
cpufreq@vger.kernel.org, linux-kernel@vger.kernel.org,
"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 1/4] clk: Introduce 'clk_find_nearest_rate()'
Date: Mon, 30 Jun 2014 21:27:07 +0200 [thread overview]
Message-ID: <20140630212707.1eb44db6@bbrezillon> (raw)
In-Reply-To: <1404147396-8041-2-git-send-email-soren.brinkmann@xilinx.com>
Hello Soren,
On Mon, 30 Jun 2014 09:56:33 -0700
Soren Brinkmann <soren.brinkmann@xilinx.com> wrote:
> Introduce a new API function to find the rate a clock can provide
> which is closest to a given rate.
>
> clk_round_rate() leaves it to the clock driver how rounding is done.
> Commonly implementations round down due to use-cases that have a
> certain frequency maximum that must not be exceeded.
I had the same concern (how could a driver decide whether it should
round up, down or to the closest value), but had a slightly different
approach in mind.
AFAIU, you're assuming the clock is always a power of two (which is
true most of the time, but some clock implementation might differ,
i.e. a PLL accept any kind of multiplier not necessarily a power of 2).
How about improving the clk_ops interface instead by adding a new method
long (*round_rate_with_constraint)(struct clk_hw *hw,
unsigned long requested_rate,
unsigned long *parent_rate,
enum clk_round_type type);
with
enum clk_round_type {
CLK_ROUND_DOWN,
CLK_ROUND_UP,
CLK_ROUND_CLOSEST,
};
or just adding these 3 methods:
long (*round_rate_up)(struct clk_hw *hw,
unsigned long requested_rate,
unsigned long *parent_rate);
long (*round_rate_down)(struct clk_hw *hw,
unsigned long requested_rate,
unsigned long *parent_rate);
long (*round_rate_closest)(struct clk_hw *hw,
unsigned long requested_rate,
unsigned long *parent_rate);
and let the round_rate method implement the default behaviour.
This way you could add 3 functions to the API:
clk_round_closest (or clk_find_nearest_rate as you called it),
clk_round_up and clk_round_down, and let the clk driver implementation
return the appropriate rate.
These are just some thoughts...
Best Regards,
Boris
>
> The new API call enables use-cases where accuracy is preferred. E.g.
> Ethernet clocks.
>
> Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
> ---
>
> drivers/clk/clk.c | 57
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/clk.h | 9 +++++++++ 2 files changed, 66 insertions(+)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 8b73edef151d..fce1165cd879 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1030,6 +1030,63 @@ long clk_round_rate(struct clk *clk, unsigned
> long rate) EXPORT_SYMBOL_GPL(clk_round_rate);
>
> /**
> + * clk_find_nearest_rate - round the given rate for a clk
> + * @clk: the clk for which we are rounding a rate
> + * @rate: the rate which is to be rounded
> + *
> + * Takes in a rate as input and finds the closest rate that the clk
> + * can actually use which is then returned.
> + * Note: This function relies on the clock's clk_round_rate()
> implementation.
> + * For cases clk_round_rate() rounds up, not the closest but the
> rounded up
> + * rate is found.
> + */
> +long clk_find_nearest_rate(struct clk *clk, unsigned long rate)
> +{
> + long ret, lower, upper;
> + unsigned long tmp;
> +
> + clk_prepare_lock();
> +
> + lower = __clk_round_rate(clk, rate);
> + if (lower >= rate || lower < 0) {
> + ret = lower;
> + goto unlock;
> + }
> +
> + tmp = rate + (rate - lower) - 1;
> + if (tmp > LONG_MAX)
> + upper = LONG_MAX;
> + else
> + upper = tmp;
> +
> + upper = __clk_round_rate(clk, upper);
> + if (upper <= lower || upper < 0) {
> + ret = lower;
> + goto unlock;
> + }
> +
> + lower = rate + 1;
> + while (lower < upper) {
> + long rounded, mid;
> +
> + mid = lower + ((upper - lower) >> 1);
> + rounded = __clk_round_rate(clk, mid);
> + if (rounded < lower)
> + lower = mid + 1;
> + else
> + upper = rounded;
> + }
> +
> + ret = upper;
> +
> +unlock:
> + clk_prepare_unlock();
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_find_nearest_rate);
> +
> +/**
> * __clk_notify - call clk notifier chain
> * @clk: struct clk * that is changing rate
> * @msg: clk notifier type (see include/linux/clk.h)
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index fb5e097d8f72..f8b53c515483 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -264,6 +264,15 @@ void devm_clk_put(struct device *dev, struct clk
> *clk); long clk_round_rate(struct clk *clk, unsigned long rate);
>
> /**
> + * clk_find_nearest_rate - Find nearest rate to the exact rate a
> clock can provide
> + * @clk: the clk for which we are rounding a rate
> + * @rate: the rate which is to be rounded
> + *
> + * Returns the rate closest to @rate the clock can provide.
> + */
> +long clk_find_nearest_rate(struct clk *clk, unsigned long rate);
> +
> +/**
> * clk_set_rate - set the clock rate for a clock source
> * @clk: clock source
> * @rate: desired clock rate in Hz
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
WARNING: multiple messages have this Message-ID (diff)
From: boris.brezillon@free-electrons.com (Boris BREZILLON)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/4] clk: Introduce 'clk_find_nearest_rate()'
Date: Mon, 30 Jun 2014 21:27:07 +0200 [thread overview]
Message-ID: <20140630212707.1eb44db6@bbrezillon> (raw)
In-Reply-To: <1404147396-8041-2-git-send-email-soren.brinkmann@xilinx.com>
Hello Soren,
On Mon, 30 Jun 2014 09:56:33 -0700
Soren Brinkmann <soren.brinkmann@xilinx.com> wrote:
> Introduce a new API function to find the rate a clock can provide
> which is closest to a given rate.
>
> clk_round_rate() leaves it to the clock driver how rounding is done.
> Commonly implementations round down due to use-cases that have a
> certain frequency maximum that must not be exceeded.
I had the same concern (how could a driver decide whether it should
round up, down or to the closest value), but had a slightly different
approach in mind.
AFAIU, you're assuming the clock is always a power of two (which is
true most of the time, but some clock implementation might differ,
i.e. a PLL accept any kind of multiplier not necessarily a power of 2).
How about improving the clk_ops interface instead by adding a new method
long (*round_rate_with_constraint)(struct clk_hw *hw,
unsigned long requested_rate,
unsigned long *parent_rate,
enum clk_round_type type);
with
enum clk_round_type {
CLK_ROUND_DOWN,
CLK_ROUND_UP,
CLK_ROUND_CLOSEST,
};
or just adding these 3 methods:
long (*round_rate_up)(struct clk_hw *hw,
unsigned long requested_rate,
unsigned long *parent_rate);
long (*round_rate_down)(struct clk_hw *hw,
unsigned long requested_rate,
unsigned long *parent_rate);
long (*round_rate_closest)(struct clk_hw *hw,
unsigned long requested_rate,
unsigned long *parent_rate);
and let the round_rate method implement the default behaviour.
This way you could add 3 functions to the API:
clk_round_closest (or clk_find_nearest_rate as you called it),
clk_round_up and clk_round_down, and let the clk driver implementation
return the appropriate rate.
These are just some thoughts...
Best Regards,
Boris
>
> The new API call enables use-cases where accuracy is preferred. E.g.
> Ethernet clocks.
>
> Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
> ---
>
> drivers/clk/clk.c | 57
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/clk.h | 9 +++++++++ 2 files changed, 66 insertions(+)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 8b73edef151d..fce1165cd879 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1030,6 +1030,63 @@ long clk_round_rate(struct clk *clk, unsigned
> long rate) EXPORT_SYMBOL_GPL(clk_round_rate);
>
> /**
> + * clk_find_nearest_rate - round the given rate for a clk
> + * @clk: the clk for which we are rounding a rate
> + * @rate: the rate which is to be rounded
> + *
> + * Takes in a rate as input and finds the closest rate that the clk
> + * can actually use which is then returned.
> + * Note: This function relies on the clock's clk_round_rate()
> implementation.
> + * For cases clk_round_rate() rounds up, not the closest but the
> rounded up
> + * rate is found.
> + */
> +long clk_find_nearest_rate(struct clk *clk, unsigned long rate)
> +{
> + long ret, lower, upper;
> + unsigned long tmp;
> +
> + clk_prepare_lock();
> +
> + lower = __clk_round_rate(clk, rate);
> + if (lower >= rate || lower < 0) {
> + ret = lower;
> + goto unlock;
> + }
> +
> + tmp = rate + (rate - lower) - 1;
> + if (tmp > LONG_MAX)
> + upper = LONG_MAX;
> + else
> + upper = tmp;
> +
> + upper = __clk_round_rate(clk, upper);
> + if (upper <= lower || upper < 0) {
> + ret = lower;
> + goto unlock;
> + }
> +
> + lower = rate + 1;
> + while (lower < upper) {
> + long rounded, mid;
> +
> + mid = lower + ((upper - lower) >> 1);
> + rounded = __clk_round_rate(clk, mid);
> + if (rounded < lower)
> + lower = mid + 1;
> + else
> + upper = rounded;
> + }
> +
> + ret = upper;
> +
> +unlock:
> + clk_prepare_unlock();
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_find_nearest_rate);
> +
> +/**
> * __clk_notify - call clk notifier chain
> * @clk: struct clk * that is changing rate
> * @msg: clk notifier type (see include/linux/clk.h)
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index fb5e097d8f72..f8b53c515483 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -264,6 +264,15 @@ void devm_clk_put(struct device *dev, struct clk
> *clk); long clk_round_rate(struct clk *clk, unsigned long rate);
>
> /**
> + * clk_find_nearest_rate - Find nearest rate to the exact rate a
> clock can provide
> + * @clk: the clk for which we are rounding a rate
> + * @rate: the rate which is to be rounded
> + *
> + * Returns the rate closest to @rate the clock can provide.
> + */
> +long clk_find_nearest_rate(struct clk *clk, unsigned long rate);
> +
> +/**
> * clk_set_rate - set the clock rate for a clock source
> * @clk: clock source
> * @rate: desired clock rate in Hz
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
next prev parent reply other threads:[~2014-06-30 19:27 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-30 16:56 [PATCH 0/4] Introduce clk_find_nearest_rate() Soren Brinkmann
2014-06-30 16:56 ` Soren Brinkmann
2014-06-30 16:56 ` Soren Brinkmann
2014-06-30 16:56 ` Soren Brinkmann
2014-06-30 16:56 ` [PATCH 1/4] clk: Introduce 'clk_find_nearest_rate()' Soren Brinkmann
2014-06-30 16:56 ` Soren Brinkmann
2014-06-30 16:56 ` Soren Brinkmann
2014-06-30 19:27 ` Boris BREZILLON [this message]
2014-06-30 19:27 ` Boris BREZILLON
2014-07-01 0:12 ` Sören Brinkmann
2014-07-01 0:12 ` Sören Brinkmann
2014-07-01 0:12 ` Sören Brinkmann
2014-07-01 6:32 ` Boris BREZILLON
2014-07-01 6:32 ` Boris BREZILLON
2014-07-01 7:18 ` Boris BREZILLON
2014-07-01 7:18 ` Boris BREZILLON
2014-07-01 8:23 ` Uwe Kleine-König
2014-07-01 8:23 ` Uwe Kleine-König
2014-07-01 17:52 ` Sören Brinkmann
2014-07-01 17:52 ` Sören Brinkmann
2014-07-01 17:52 ` Sören Brinkmann
2014-06-30 16:56 ` [PATCH 2/4] cpufreq: cpu0: Use clk_find_nearest_rate() Soren Brinkmann
2014-06-30 16:56 ` Soren Brinkmann
2014-06-30 16:56 ` [PATCH 3/4] net: macb: Use clk_find_nearest_rate() API Soren Brinkmann
2014-06-30 16:56 ` Soren Brinkmann
2014-06-30 16:56 ` [PATCH 4/4] ARM: zynq: dt: Use properly rounded frequencies in OPPs Soren Brinkmann
2014-06-30 16:56 ` Soren Brinkmann
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=20140630212707.1eb44db6@bbrezillon \
--to=boris.brezillon@free-electrons.com \
--cc=cpufreq@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux@arm.linux.org.uk \
--cc=michal.simek@xilinx.com \
--cc=mturquette@linaro.org \
--cc=nicolas.ferre@atmel.com \
--cc=rjw@rjwysocki.net \
--cc=soren.brinkmann@xilinx.com \
--cc=u.kleine-koenig@pengutronix.de \
--cc=viresh.kumar@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.