linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Paul Cercueil <paul@crapouillou.net>
To: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
Cc: Thierry Reding <thierry.reding@gmail.com>,
	od@zcrc.me, linux-pwm@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Mathieu Malaterre <malat@debian.org>,
	Artur Rojek <contact@artur-rojek.eu>
Subject: Re: [PATCH 4/7] pwm: jz4740: Improve algorithm of clock calculation
Date: Fri, 09 Aug 2019 19:14:45 +0200	[thread overview]
Message-ID: <1565370885.2091.2@crapouillou.net> (raw)
In-Reply-To: <20190809170551.u4ybilf5ay2rsvnn@pengutronix.de>



Le ven. 9 août 2019 à 19:05, Uwe =?iso-8859-1?q?Kleine-K=F6nig?= 
<u.kleine-koenig@pengutronix.de> a écrit :
> On Fri, Aug 09, 2019 at 02:30:28PM +0200, Paul Cercueil wrote:
>>  The previous algorithm hardcoded details about how the TCU clocks 
>> work.
>>  The new algorithm will use clk_round_rate to find the perfect clock 
>> rate
>>  for the PWM channel.
>> 
>>  Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>>  Tested-by: Mathieu Malaterre <malat@debian.org>
>>  Tested-by: Artur Rojek <contact@artur-rojek.eu>
>>  ---
>>   drivers/pwm/pwm-jz4740.c | 60 
>> +++++++++++++++++++++++++++++-----------
>>   1 file changed, 44 insertions(+), 16 deletions(-)
>> 
>>  diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
>>  index 6ec8794d3b99..f20dc2e19240 100644
>>  --- a/drivers/pwm/pwm-jz4740.c
>>  +++ b/drivers/pwm/pwm-jz4740.c
>>  @@ -110,24 +110,56 @@ static int jz4740_pwm_apply(struct pwm_chip 
>> *chip, struct pwm_device *pwm,
>>   	struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
>>   	struct clk *clk = pwm_get_chip_data(pwm),
>>   		   *parent_clk = clk_get_parent(clk);
>>  -	unsigned long rate, period, duty;
>>  +	unsigned long rate, parent_rate, period, duty;
>>   	unsigned long long tmp;
>>  -	unsigned int prescaler = 0;
>>  +	int ret;
>> 
>>  -	rate = clk_get_rate(parent_clk);
>>  -	tmp = (unsigned long long)rate * state->period;
>>  -	do_div(tmp, 1000000000);
>>  -	period = tmp;
>>  +	parent_rate = clk_get_rate(parent_clk);
>>  +
>>  +	jz4740_pwm_disable(chip, pwm);
>> 
>>  -	while (period > 0xffff && prescaler < 6) {
>>  -		period >>= 2;
>>  -		rate >>= 2;
>>  -		++prescaler;
>>  +	/* Reset the clock to the maximum rate, and we'll reduce it if 
>> needed */
>>  +	ret = clk_set_max_rate(clk, parent_rate);
> 
> What is the purpose of this call? IIUC this limits the allowed range 
> of
> rates for clk. I assume the idea is to prevent other consumers to 
> change
> the rate in a way that makes it unsuitable for this pwm. But this only
> makes sense if you had a notifier for clk changes, doesn't it? I'm
> confused.

Nothing like that. The second call to clk_set_max_rate() might have set
a maximum clock rate that's lower than the parent's rate, and we want to
undo that.


> I think this doesn't match the commit log, you didn't even introduced 
> a
> call to clk_round_rate().

Right, I'll edit the commit message.


>>  +	if (ret) {
>>  +		dev_err(chip->dev, "Unable to set max rate: %d\n", ret);
>>  +		return ret;
>>   	}
>> 
>>  -	if (prescaler == 6)
>>  -		return -EINVAL;
>>  +	ret = clk_set_rate(clk, parent_rate);
>>  +	if (ret) {
>>  +		dev_err(chip->dev, "Unable to reset to parent rate (%lu Hz)",
>>  +			parent_rate);
>>  +		return ret;
>>  +	}
>>  +
>>  +	/*
>>  +	 * Limit the clock to a maximum rate that still gives us a period 
>> value
>>  +	 * which fits in 16 bits.
>>  +	 */
>>  +	tmp = 0xffffull * NSEC_PER_SEC;
>>  +	do_div(tmp, state->period);
>> 
>>  +	ret = clk_set_max_rate(clk, tmp);
> 
> And now you change the maximal rate again?

Basically, we start from the maximum clock rate we can get for that PWM
- which is the rate of the parent clk - and from that compute the 
maximum
clock rate that we can support that still gives us < 16-bits hardware
values for the period and duty.

We then pass that computed maximum clock rate to clk_set_max_rate(), 
which
may or may not update the current PWM clock's rate to match the new 
limits.
Finally we read back the PWM clock's rate and compute the period and 
duty
from that.


>>  +	if (ret) {
>>  +		dev_err(chip->dev, "Unable to set max rate: %d\n", ret);
>>  +		return ret;
>>  +	}
>>  +
>>  +	/*
>>  +	 * Read back the clock rate, as it may have been modified by
>>  +	 * clk_set_max_rate()
>>  +	 */
>>  +	rate = clk_get_rate(clk);
>>  +
>>  +	if (rate != parent_rate)
>>  +		dev_dbg(chip->dev, "PWM clock updated to %lu Hz\n", rate);
>>  +
>>  +	/* Calculate period value */
>>  +	tmp = (unsigned long long)rate * state->period;
>>  +	do_div(tmp, NSEC_PER_SEC);
>>  +	period = (unsigned long)tmp;
>>  +
>>  +	/* Calculate duty value */
>>   	tmp = (unsigned long long)period * state->duty_cycle;
>>   	do_div(tmp, state->period);
>>   	duty = period - tmp;
>>  @@ -135,14 +167,10 @@ static int jz4740_pwm_apply(struct pwm_chip 
>> *chip, struct pwm_device *pwm,
>>   	if (duty >= period)
>>   		duty = period - 1;
>> 
>>  -	jz4740_pwm_disable(chip, pwm);
>>  -
>>   	/* Set abrupt shutdown */
>>   	regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm),
>>   			   TCU_TCSR_PWM_SD, TCU_TCSR_PWM_SD);
>> 
>>  -	clk_set_rate(clk, rate);
>>  -
> 
> It's not obvious to me why removing these two lines belong in the
> current patch.

They're not removed, they're both moved up in the function.


> Best regards
> Uwe
> 
> --
> Pengutronix e.K.                           | Uwe Kleine-König        
>     |
> Industrial Linux Solutions                 | 
> http://www.pengutronix.de/  |



  reply	other threads:[~2019-08-09 17:14 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-09 12:30 [PATCH 0/7] pwm: jz4740: Driver update Paul Cercueil
2019-08-09 12:30 ` [PATCH 1/7] pwm: jz4740: Obtain regmap from parent node Paul Cercueil
2019-08-09 16:51   ` Uwe Kleine-König
2019-08-09 17:04     ` Paul Cercueil
2019-08-12  6:18       ` Uwe Kleine-König
2019-08-09 12:30 ` [PATCH 2/7] pwm: jz4740: Use clocks from TCU driver Paul Cercueil
2019-08-09 16:55   ` Uwe Kleine-König
2019-08-09 12:30 ` [PATCH 3/7] pwm: jz4740: Drop dependency on MACH_INGENIC Paul Cercueil
2019-08-09 16:41   ` Uwe Kleine-König
2019-08-09 21:40     ` Paul Cercueil
2019-08-12  6:09       ` Uwe Kleine-König
2019-08-09 12:30 ` [PATCH 4/7] pwm: jz4740: Improve algorithm of clock calculation Paul Cercueil
2019-08-09 17:05   ` Uwe Kleine-König
2019-08-09 17:14     ` Paul Cercueil [this message]
2019-08-12  6:15       ` Uwe Kleine-König
2019-08-12 20:43         ` Paul Cercueil
2019-08-12 21:48           ` Uwe Kleine-König
2019-08-12 22:25             ` Paul Cercueil
     [not found]             ` <1565648183.2007.3@crapouillou.net>
2019-08-13  5:27               ` Uwe Kleine-König
2019-08-13 11:01                 ` Paul Cercueil
2019-08-13 12:33                   ` Uwe Kleine-König
2019-08-13 12:47                     ` Paul Cercueil
2019-08-13 14:09                       ` Uwe Kleine-König
2019-08-14 16:10                         ` Paul Cercueil
2019-08-14 17:32                           ` Uwe Kleine-König
2019-10-21 12:47                             ` Paul Cercueil
2020-02-12  7:29                               ` About rounding in the clk framework [Was: Re: [PATCH 4/7] pwm: jz4740: Improve algorithm of clock calculation] Uwe Kleine-König
2020-04-14  9:24                                 ` Uwe Kleine-König
2020-12-21 13:57                                   ` Uwe Kleine-König
2019-08-09 12:30 ` [PATCH 5/7] pwm: jz4740: Allow selection of PWM channels 0 and 1 Paul Cercueil
2019-08-09 12:30 ` [PATCH 6/7] pwm: jz4740: Make PWM start with the active part Paul Cercueil
2019-08-09 17:10   ` Uwe Kleine-König
2019-08-09 17:33     ` Paul Cercueil
2019-08-12  5:55       ` Uwe Kleine-König
2019-08-12 20:50         ` Paul Cercueil
2019-08-12 21:58           ` Uwe Kleine-König
2019-09-20 22:52             ` Thierry Reding
2019-08-09 12:30 ` [PATCH 7/7] pwm: jz4740: document known limitations Paul Cercueil

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=1565370885.2091.2@crapouillou.net \
    --to=paul@crapouillou.net \
    --cc=contact@artur-rojek.eu \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=malat@debian.org \
    --cc=od@zcrc.me \
    --cc=thierry.reding@gmail.com \
    --cc=u.kleine-koenig@pengutronix.de \
    /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).