Re: [PATCH] pwm: meson: compute cnt register value in proper way
From: Uwe Kleine-König
Date: Tue Jun 06 2023 - 04:14:29 EST
On Mon, Jun 05, 2023 at 11:01:40PM +0200, Heiner Kallweit wrote:
> On 05.06.2023 09:11, George Stark wrote:
> > On 6/2/23 23:52, Heiner Kallweit wrote:
> >> On 02.06.2023 12:32, George Stark wrote:
> >>> According to the datasheet, the PWM high and low clock count values
> >>> should be set to at least one. Therefore, setting the clock count
> >>> register to 0 actually means 1 clock count.
> >>>
> >>> Signed-off-by: George Stark <GNStark@xxxxxxxxxxxxxx>
> >>> Signed-off-by: Dmitry Rokosov <ddrokosov@xxxxxxxxxxxxxx>
> >>> ---
> >>> This patch is based on currently unmerged patch by Heiner Kallweit
> >>> https://lore.kernel.org/linux-amlogic/23fe625e-dc23-4db8-3dce-83167cd3b206@xxxxxxxxx
> >>> ---
> >>> diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
> >>> index 834acd7..57e7d9c 100644
> >>> --- a/drivers/pwm/pwm-meson.c
> >>> +++ b/drivers/pwm/pwm-meson.c
> >>> @@ -206,6 +206,11 @@
> >>> channel->pre_div = pre_div;
> >>> channel->hi = duty_cnt;
> >>> channel->lo = cnt - duty_cnt;
> >>> +
> >>> + if (channel->hi)
> >>> + channel->hi--;
> >>> + if (channel->lo)
> >>> + channel->lo--;
> > Hello Heiner
> >
> > Thanks for review
> >> I'm not sure whether we should do this. duty_cnt and cnt are results
> >> of an integer division and therefore potentially rounded down.
> >> The chip-internal increment may help to compensate such rounding
> >> errors, so to say. With the proposed change we may end up with the
> >> effective period being shorter than the requested one.
> > Although chip-internal increment sometimes may help accidentally
> > there are cases when the increment ruins precise calculation in unexpected way.
> >
> > Here's our experience on meson a113l (meson-a1) with pwm driver based on ccf:
> > we need to get pwm period as close as possible to 32768hz.
> > config pwm to period 1/32768 = 30517ns, duty 15258n
> > How driver calculates hi\lo regs:
> > rate = NSEC_PER_SEC * 0xffff / 30517 = ~2147Mhz
> > rate = clk_round_rate(rate) clk_round_rate selects fastest parent clock which is 64Mhz in our case then calculating hi\lo at last: period= mul_u64_u64_div_u64(rate, state->period, NSEC_PER_SEC); // 1953
> > duty= mul_u64_u64_div_u64(rate, state->duty_cycle, NSEC_PER_SEC); // 976
> > channel->hi= duty;
> > channel->lo= period- duty;
> > with the internal increment we'll have real output (1953-976 + 1 + 976 + 1) * 1 / 64Mhz = 32736.57Hz but we should have (1953-976 + 976) * 1 / 64Mhz = 32770.09Hz
>
> Supposedly, depending on the prior rounding errors, something incrementing,
> and sometimes not incrementing may provide the more precise result.
> Another source of error is shown your example, the duty cycle isn't 50%
> due to the rounding.
> Not sure however where there's any use case where such small deviations
> would cause problems. Therefore I don't have a strong opinion.
My strong opinion here is: .apply should implement the the best
round-down setting. That is it should pick the maximal period that isn't
bigger than the requested one, and for that period pick the maximal
duty_cycle that isn't bigger than the requested one.
I have some implementation ideas to allow consumers to want different
rounding, but for that to work the .apply functions should all round the
same way.
> > | And IIRC this should not happen.
> > Could you please explain why or point out doc/description where it's stated?
> > If so we can add explicit check to prevent such a case
>
> I think I got this wrong. When checking where I got this information from
> I found the following in pwm_apply_state_debug():
>
> if (state->enabled && state->period < s2.period)
> dev_warn(chip->dev,
> ".apply is supposed to round down period (requested: %llu, applied: %llu)\n",
> state->period, s2.period);
pwm_apply_state_debug() also checks the above sketched rule.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | https://www.pengutronix.de/ |
Attachment:
signature.asc
Description: PGP signature