Skip to content

Commit 1f5c537

Browse files
committed
Merge tag 'pwm/for-6.10-rc5-fixes-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux
Pull pwm fixes from Uwe Kleine-König: "Three fixes for the pwm-stm32 driver. The first patch prevents an integer wrap-around for small periods. In the second patch the calculation of the prescaler is fixed which resulted in values for the ARR register that don't fit into the corresponding register bit field. The last commit improves an error message that was wrongly copied from another error path" * tag 'pwm/for-6.10-rc5-fixes-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux: pwm: stm32: Fix error message to not describe the previous error path pwm: stm32: Fix calculation of prescaler pwm: stm32: Refuse too small period requests
2 parents 56bf733 + f01af30 commit 1f5c537

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

drivers/pwm/pwm-stm32.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -321,22 +321,30 @@ static int stm32_pwm_config(struct stm32_pwm *priv, unsigned int ch,
321321
* First we need to find the minimal value for prescaler such that
322322
*
323323
* period_ns * clkrate
324-
* ------------------------------
324+
* ------------------------------ < max_arr + 1
325325
* NSEC_PER_SEC * (prescaler + 1)
326326
*
327-
* isn't bigger than max_arr.
327+
* This equation is equivalent to
328+
*
329+
* period_ns * clkrate
330+
* ---------------------------- < prescaler + 1
331+
* NSEC_PER_SEC * (max_arr + 1)
332+
*
333+
* Using integer division and knowing that the right hand side is
334+
* integer, this is further equivalent to
335+
*
336+
* (period_ns * clkrate) // (NSEC_PER_SEC * (max_arr + 1)) ≤ prescaler
328337
*/
329338

330339
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;
334-
340+
(u64)NSEC_PER_SEC * ((u64)priv->max_arr + 1));
335341
if (prescaler > MAX_TIM_PSC)
336342
return -EINVAL;
337343

338344
prd = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk),
339345
(u64)NSEC_PER_SEC * (prescaler + 1));
346+
if (!prd)
347+
return -EINVAL;
340348

341349
/*
342350
* All channels share the same prescaler and counter so when two
@@ -673,7 +681,8 @@ static int stm32_pwm_probe(struct platform_device *pdev)
673681
* .apply() won't overflow.
674682
*/
675683
if (clk_get_rate(priv->clk) > 1000000000)
676-
return dev_err_probe(dev, -EINVAL, "Failed to lock clock\n");
684+
return dev_err_probe(dev, -EINVAL, "Clock freq too high (%lu)\n",
685+
clk_get_rate(priv->clk));
677686

678687
chip->ops = &stm32pwm_ops;
679688

0 commit comments

Comments
 (0)