public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
From: heiko@sntech.de (Heiko Stübner)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 01/11] clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent
Date: Mon, 26 May 2014 12:27:08 +0200	[thread overview]
Message-ID: <27477814.I92OqiDuKt@phil> (raw)
In-Reply-To: <5383085C.1060804@free-electrons.com>

Am Montag, 26. Mai 2014, 11:24:44 schrieb Boris BREZILLON:
> Hello Heiko,
> 
> On 23/05/2014 21:33, Heiko St?bner wrote:
> > From: Boris BREZILLON <b.brezillon@overkiz.com>
> > 
> > In case the rate_hw does not implement determine_rate, but only round_rate
> > we fallback to best_parent selection if mux_hw is present and support
> > reparenting.
> > 
> > Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
> > 
> > This also fixes a rate calculation problem when using the standard div and
> > mux ops, as in this case currently only the mux->determine_rate is used
> > in the composite rate calculation.
> > [fixed the output to actually return a rate instead of the diff]
> 
> Sorry for the delay and thanks for fixing this.
> 
> Anyway, when I first proposed this patch, Emilio (added in Cc) told me
> this should not be automatically done by the composite clk driver, and
> the driver should instead provide the determine_rate function.

Just to point out, as I'm not sure if it comes across correctly from my 
description above, it looks like the composite behaviour is currently broken 
when using the standard mux and div ops for it.

As only mux_ops provides a determine rate callback, it will always only run
	mux_ops->determine_rate
thus returning the parent rate as the target rate.

So when the parents are 600 and 891 MHz and you want 75MHz [which the divider 
can provide], the clock would always be set to 600MHz, which may be way out of 
spec - as seen on my rk3188 clock tree.


When looking at the other composite users, only st/clkgen-mux.c uses the same 
pattern with both the standard mux and div operations. I've added Gabriel, 
maybe he can check what happens on his arch, when an affected clock is changed.


> Mike, any opinion on this patch ?
> 
> Best Regards,
> 
> Boris
> 
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> > 
> >  drivers/clk/clk-composite.c | 51
> >  ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50
> >  insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
> > index 57a078e..0a4cd21 100644
> > --- a/drivers/clk/clk-composite.c
> > +++ b/drivers/clk/clk-composite.c
> > @@ -64,11 +64,59 @@ static long clk_composite_determine_rate(struct clk_hw
> > *hw, unsigned long rate,> 
> >  	const struct clk_ops *mux_ops = composite->mux_ops;
> >  	struct clk_hw *rate_hw = composite->rate_hw;
> >  	struct clk_hw *mux_hw = composite->mux_hw;
> > 
> > +	struct clk *parent;
> > +	unsigned long parent_rate;
> > +	long tmp_rate, best_rate;
> > +	unsigned long rate_diff;
> > +	unsigned long best_rate_diff = ULONG_MAX;
> > +	int i;
> > 
> >  	if (rate_hw && rate_ops && rate_ops->determine_rate) {
> >  	
> >  		rate_hw->clk = hw->clk;
> >  		return rate_ops->determine_rate(rate_hw, rate, 
best_parent_rate,
> >  		
> >  						best_parent_p);
> > 
> > +	} else if (rate_hw && rate_ops && rate_ops->round_rate &&
> > +		   mux_hw && mux_ops && mux_ops->set_parent) {
> > +		*best_parent_p = NULL;
> > +
> > +		if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
> > +			*best_parent_p = clk_get_parent(mux_hw->clk);
> > +			*best_parent_rate = __clk_get_rate(*best_parent_p);
> > +
> > +			return rate_ops->round_rate(rate_hw, rate,
> > +						    best_parent_rate);
> > +		}
> > +
> > +		for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
> > +			parent = clk_get_parent_by_index(mux_hw->clk, i);
> > +			if (!parent)
> > +				continue;
> > +
> > +			parent_rate = __clk_get_rate(parent);
> > +
> > +			tmp_rate = rate_ops->round_rate(rate_hw, rate,
> > +							&parent_rate);
> > +			if (tmp_rate < 0)
> > +				continue;
> > +
> > +			if (tmp_rate < rate)
> > +				rate_diff = rate - tmp_rate;
> > +			else
> > +				rate_diff = tmp_rate - rate;
> > +
> > +			if (!rate_diff || !*best_parent_p
> > +				       || best_rate_diff > rate_diff) {
> > +				*best_parent_p = parent;
> > +				*best_parent_rate = parent_rate;
> > +				best_rate_diff = rate_diff;
> > +				best_rate = tmp_rate;
> > +			}
> > +
> > +			if (!rate_diff)
> > +				return rate;
> > +		}
> > +
> > +		return best_rate;
> > 
> >  	} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
> >  	
> >  		mux_hw->clk = hw->clk;
> >  		return mux_ops->determine_rate(mux_hw, rate, best_parent_rate,
> > 
> > @@ -196,7 +244,8 @@ struct clk *clk_register_composite(struct device *dev,
> > const char *name,> 
> >  		composite->rate_hw = rate_hw;
> >  		composite->rate_ops = rate_ops;
> >  		clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
> > 
> > -		if (rate_ops->determine_rate)
> > +		if (rate_ops->determine_rate ||
> > +		    (rate_ops->round_rate && clk_composite_ops->set_parent))
> > 
> >  			clk_composite_ops->determine_rate = 
clk_composite_determine_rate;
> >  	
> >  	}

  reply	other threads:[~2014-05-26 10:27 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-05-23 19:32 [PATCH v3 00/11] Add real clock support for Rockchip's RK3188 Heiko Stübner
2014-05-23 19:33 ` [PATCH v3 01/11] clk: composite: support determine_rate using rate_ops->round_rate + mux_ops->set_parent Heiko Stübner
2014-05-26  9:24   ` Boris BREZILLON
2014-05-26 10:27     ` Heiko Stübner [this message]
2014-05-28 11:07       ` Gabriel Fernandez
2014-05-23 19:34 ` [PATCH v3 02/11] clk: composite: allow read-only clocks Heiko Stübner
2014-05-23 19:34 ` [PATCH v3 03/11] clk: rockchip: add basic infrastructure for clock branches Heiko Stübner
2014-05-23 19:35 ` [PATCH v3 04/11] clk: rockchip: add clock type for pll clocks and pll used on rk3066 Heiko Stübner
2014-05-23 19:36 ` [PATCH v3 05/11] clk: rockchip: add reset controller Heiko Stübner
2014-05-23 19:36 ` [PATCH v3 06/11] dt-bindings: add documentation for rk3188 clock and reset unit Heiko Stübner
2014-05-23 19:37 ` [PATCH v3 07/11] clk: rockchip: add clock driver for rk3188 clocks Heiko Stübner
2014-05-23 19:37 ` [PATCH v3 08/11] ARM: rockchip: Select ARCH_HAS_RESET_CONTROLLER Heiko Stübner
2014-05-23 19:38 ` [PATCH v3 09/11] ARM: dts: rk3188: add cru node and update device clocks to use it Heiko Stübner
2014-05-23 19:38 ` [PATCH v3 10/11] ARM: dts: rockchip: move rk3188 core input clocks into main dtsi Heiko Stübner
2014-05-23 19:39 ` [PATCH v3 11/11] ARM: dts: rockchip: remove the now obsolete rk3188-clocks.dtsi Heiko Stübner

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=27477814.I92OqiDuKt@phil \
    --to=heiko@sntech.de \
    --cc=linux-arm-kernel@lists.infradead.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