All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tomi Valkeinen <tomi.valkeinen@ti.com>
To: Mike Turquette <mturquette@linaro.org>,
	linux-kernel <linux-kernel@vger.kernel.org>
Cc: "Kristo, Tero" <t-kristo@ti.com>,
	Shawn Guo <shawn.guo@linaro.org>, Paul Walmsley <paul@pwsan.com>
Subject: Re: Rounding issue in drivers/clk/clk-divider.c
Date: Mon, 28 Oct 2013 11:39:01 +0200	[thread overview]
Message-ID: <526E30B5.9080306@ti.com> (raw)
In-Reply-To: <52554F66.5080405@ti.com>

[-- Attachment #1: Type: text/plain, Size: 3894 bytes --]

Hi,

Ping.

 Tomi

On 09/10/13 15:43, Tomi Valkeinen wrote:
> Hi,
> 
> On 08/10/13 16:17, Tomi Valkeinen wrote:
>> Hi,
>>
>> I'm seeing the following issue on omap3 with dpll4_m4 clock. dpll4_m4's
>> parent is a PLL set to 864000000 and dpll4_m4 is a divider, handled by
>> clk-divider.c.
>>
>> Now, if I call clk_round_rate(dpll4_m4, 143999999), I get 123428571
>> which is correct. However, if I call clk_round_rate(dpll4_m4,
>> 123428571), I would presume to get the same answer, 123428571, as that
>> was already "verified" by the previous clk_round_rate() call. However, I
>> get 108000000.
>>
>> So, if I have the following code:
>>
>> rate = clk_round_rate(dpll4_m4, 143999999);
>> /* rate is 123428571 */
>> clk_set_rate(dpll4_m4, rate);
>>
>> the resulting rate is 108000000.
> 
> I continued testing with this, and with the following RFC patch I get
> consistent rates:
> 
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 8d3009e..ba20314 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -115,7 +115,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
>  		return parent_rate;
>  	}
>  
> -	return parent_rate / div;
> +	return DIV_ROUND_UP(parent_rate, div);
>  }
>  
>  /*
> @@ -207,7 +207,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
>  	int div;
>  	div = clk_divider_bestdiv(hw, rate, prate);
>  
> -	return *prate / div;
> +	return DIV_ROUND_UP(*prate, div);
>  }
>  
>  static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
> @@ -218,7 +218,7 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
>  	unsigned long flags = 0;
>  	u32 val;
>  
> -	div = parent_rate / rate;
> +	div = DIV_ROUND_UP(parent_rate, rate);
>  	value = _get_val(divider, div);
>  
>  	if (value > div_mask(divider))
> 
> 
> Now clk_round_rate for this clock returns the following:
> 
> 144000000 -> 144000000
> 143999999 -> 123428572
> 123428572 -> 123428572
> 123428571 -> 108000000
> 
> So now multiple nested calls to clk_round_rate return consistent values, and
> calling clk_set_rate with the rate returned by clk_round_rate will not modify
> the rate.
> 
> I believe the patch is missing pieces, at least for clk_divider_bestdiv() for
> the case when CLK_SET_RATE_PARENT is set. Also, 864000000 / 7 = 123428571.4...,
> so in reality 123428571 would be a better answer than 123428572. But rounding
> to 123428572 makes things work consistently.
> 
> However, even if the patch fixes the issue for me, I'm a bit confused on the
> clock rate rounding. How should it happen? Is it even defined how the rate is
> rounded?
> 
> In my particular use case I want to iterate the possible clock rates, so that I
> can find the best one to use. I do it with this kind of code:
> 
> /* start with the max rate my IP allows */
> rate = max_allowed_fck;
> while (true) {
> 	rate = clk_round_rate(rate);
> 	test_rate(rate);
> 	/* -1, so that the next round will return the next lowest rate */
> 	rate -= 1;
> }
> 
> The code above presumes that the clk_round_rate will round down, but I don't
> see the rounding explicitly specified in any documentation. Is that kind of
> code valid?
> 
> Another use case I have is to set the clock rate to something which is higher
> than what I need. I.e. I know that I need at least 100MHz clock so that the IP
> performs the job quickly enough. If I call clk_round_rate(100M), I'll get a
> lower clock, not higher. So in this case I'd actually like the rounding to be
> up. And if the rate is rounded down, I have no idea what rate should I use to
> get at least 100MHz.
> 
> Am I doing something silly here? =) Should there be multiple clk_round_rate
> versions, for different roundings?
> 
>  Tomi
> 
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

      reply	other threads:[~2013-10-28  9:39 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-08 13:17 Rounding issue in drivers/clk/clk-divider.c Tomi Valkeinen
2013-10-09 12:43 ` Tomi Valkeinen
2013-10-28  9:39   ` Tomi Valkeinen [this message]

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=526E30B5.9080306@ti.com \
    --to=tomi.valkeinen@ti.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mturquette@linaro.org \
    --cc=paul@pwsan.com \
    --cc=shawn.guo@linaro.org \
    --cc=t-kristo@ti.com \
    /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.