mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 02:36:02 +00:00
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>
This commit is contained in:
parent
d44d635635
commit
8002fbeef1
@ -311,29 +311,33 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
static int stm32_pwm_config(struct stm32_pwm *priv, unsigned int ch,
|
||||
u64 duty_ns, u64 period_ns)
|
||||
{
|
||||
unsigned long long prd, div, dty;
|
||||
unsigned int prescaler = 0;
|
||||
unsigned long long prd, dty;
|
||||
unsigned long long prescaler;
|
||||
u32 ccmr, mask, shift;
|
||||
|
||||
/*
|
||||
* .probe() asserted that clk_get_rate() is not bigger than 1 GHz, so
|
||||
* this won't overflow.
|
||||
* the calculations here won't overflow.
|
||||
* First we need to find the minimal value for prescaler such that
|
||||
*
|
||||
* period_ns * clkrate
|
||||
* ------------------------------
|
||||
* NSEC_PER_SEC * (prescaler + 1)
|
||||
*
|
||||
* isn't bigger than max_arr.
|
||||
*/
|
||||
div = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk),
|
||||
NSEC_PER_SEC);
|
||||
prd = div;
|
||||
|
||||
while (div > priv->max_arr) {
|
||||
prescaler++;
|
||||
div = prd;
|
||||
do_div(div, prescaler + 1);
|
||||
}
|
||||
|
||||
prd = div;
|
||||
prescaler = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk),
|
||||
(u64)NSEC_PER_SEC * priv->max_arr);
|
||||
if (prescaler > 0)
|
||||
prescaler -= 1;
|
||||
|
||||
if (prescaler > MAX_TIM_PSC)
|
||||
return -EINVAL;
|
||||
|
||||
prd = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk),
|
||||
(u64)NSEC_PER_SEC * (prescaler + 1));
|
||||
|
||||
/*
|
||||
* All channels share the same prescaler and counter so when two
|
||||
* channels are active at the same time we can't change them
|
||||
|
Loading…
Reference in New Issue
Block a user