Skip to content

Commit 8002fbe

Browse files
author
Uwe Kleine-König
committed
pwm: stm32: Calculate prescaler with a division instead of a loop
Instead of looping over increasing values for the prescaler and testing if it's big enough, calculate the value using a single division. Link: https://lore.kernel.org/r/498a44b313a6c0a84ccddd03cd67aadaaaf7daf2.1710711976.git.u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
1 parent d44d635 commit 8002fbe

1 file changed

Lines changed: 17 additions & 13 deletions

File tree

drivers/pwm/pwm-stm32.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -311,29 +311,33 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
311311
static int stm32_pwm_config(struct stm32_pwm *priv, unsigned int ch,
312312
u64 duty_ns, u64 period_ns)
313313
{
314-
unsigned long long prd, div, dty;
315-
unsigned int prescaler = 0;
314+
unsigned long long prd, dty;
315+
unsigned long long prescaler;
316316
u32 ccmr, mask, shift;
317317

318318
/*
319319
* .probe() asserted that clk_get_rate() is not bigger than 1 GHz, so
320-
* this won't overflow.
320+
* the calculations here won't overflow.
321+
* First we need to find the minimal value for prescaler such that
322+
*
323+
* period_ns * clkrate
324+
* ------------------------------
325+
* NSEC_PER_SEC * (prescaler + 1)
326+
*
327+
* isn't bigger than max_arr.
321328
*/
322-
div = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk),
323-
NSEC_PER_SEC);
324-
prd = div;
325-
326-
while (div > priv->max_arr) {
327-
prescaler++;
328-
div = prd;
329-
do_div(div, prescaler + 1);
330-
}
331329

332-
prd = div;
330+
prescaler = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk),
331+
(u64)NSEC_PER_SEC * priv->max_arr);
332+
if (prescaler > 0)
333+
prescaler -= 1;
333334

334335
if (prescaler > MAX_TIM_PSC)
335336
return -EINVAL;
336337

338+
prd = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk),
339+
(u64)NSEC_PER_SEC * (prescaler + 1));
340+
337341
/*
338342
* All channels share the same prescaler and counter so when two
339343
* channels are active at the same time we can't change them

0 commit comments

Comments
 (0)