diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2022-04-25 15:22:44 +0200 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2022-05-20 16:20:07 +0200 |
commit | 8c193f4714df136a6747fb66f4218134771092be (patch) | |
tree | ba5b8775351c61737f6485913a7ef0e3764128d3 /net/ife | |
parent | 615f4e84461b71e5fed01d9f6d9d98ef3dd1d452 (diff) | |
download | linux-stable-8c193f4714df136a6747fb66f4218134771092be.tar.gz linux-stable-8c193f4714df136a6747fb66f4218134771092be.tar.bz2 linux-stable-8c193f4714df136a6747fb66f4218134771092be.zip |
pwm: tegra: Optimize period calculation
Dividing by the result of a division looses precision because the result is
rounded twice. E.g. with clk_rate = 48000000 and period = 32760033 the
following numbers result:
rate = pc->clk_rate >> PWM_DUTY_WIDTH = 187500
hz = DIV_ROUND_CLOSEST_ULL(100ULL * NSEC_PER_SEC, period_ns) = 3052
rate = DIV_ROUND_CLOSEST_ULL(100ULL * rate, hz) = 6144
The exact result would be 6142.5061875 and (apart from rounding) this is
found by using a single division. As a side effect is also a tad
cheaper to calculate.
Also using clk_rate >> PWM_DUTY_WIDTH looses precision. Consider for
example clk_rate = 47999999 and period = 106667:
mul_u64_u64_div_u64(pc->clk_rate >> PWM_DUTY_WIDTH, period_ns,
NSEC_PER_SEC) = 19
mul_u64_u64_div_u64(pc->clk_rate, period_ns,
NSEC_PER_SEC << PWM_DUTY_WIDTH) = 20
(The exact result is 20.000062083332033.)
With this optimizations also switch from round-closest to round-down for
the period calculation. Given that the calculations were non-optimal for
quite some time now with variations in both directions which nobody
reported as a problem, this is the opportunity to align the driver's
behavior to the requirements of new drivers. This has several upsides:
- Implementation is easier as there are no round-nearest variants of
mul_u64_u64_div_u64().
- Requests for too small periods are now consistently refused. This was
kind of arbitrary before, where period_ns < min_period_ns was
refused, but in some cases min_period_ns isn't actually implementable
and then values between min_period_ns and the actual minimum were
rounded up to the actual minimum.
Note that the duty_cycle calculation isn't using the usual round-down
approach yet.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'net/ife')
0 files changed, 0 insertions, 0 deletions