diff options
author | Uwe Kleine-König <uwe@kleine-koenig.org> | 2019-08-24 02:10:38 +0200 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2020-01-08 13:43:39 +0100 |
commit | 2101c878f767fc6341ce0057e3b53d6129e76d99 (patch) | |
tree | c26d5ea2989b9d27f49bfab18b6db7b27836cd32 /drivers/pwm | |
parent | pwm: atmel: Use a constant for maximum prescale value (diff) | |
download | linux-2101c878f767fc6341ce0057e3b53d6129e76d99.tar.xz linux-2101c878f767fc6341ce0057e3b53d6129e76d99.zip |
pwm: atmel: Replace loop in prescale calculation by ad-hoc calculation
The calculated values are the same with the modified algorithm. The only
difference is that the calculation is a bit more efficient.
Acked-by: Claudiu Beznea <claudiu.beznea@microchip.com>
Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm')
-rw-r--r-- | drivers/pwm/pwm-atmel.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index 199255b26aaa..c9fdf1671bb3 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -60,7 +60,7 @@ struct atmel_pwm_registers { }; struct atmel_pwm_config { - u32 max_period; + u32 period_bits; }; struct atmel_pwm_data { @@ -119,17 +119,27 @@ static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip, { struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip); unsigned long long cycles = state->period; + int shift; /* Calculate the period cycles and prescale value */ cycles *= clk_get_rate(atmel_pwm->clk); do_div(cycles, NSEC_PER_SEC); - for (*pres = 0; cycles > atmel_pwm->data->cfg.max_period; cycles >>= 1) - (*pres)++; + /* + * The register for the period length is cfg.period_bits bits wide. + * So for each bit the number of clock cycles is wider divide the input + * clock frequency by two using pres and shift cprd accordingly. + */ + shift = fls(cycles) - atmel_pwm->data->cfg.period_bits; - if (*pres > PWM_MAX_PRES) { + if (shift > PWM_MAX_PRES) { dev_err(chip->dev, "pres exceeds the maximum value\n"); return -EINVAL; + } else if (shift > 0) { + *pres = shift; + cycles >>= *pres; + } else { + *pres = 0; } *cprd = cycles; @@ -289,7 +299,7 @@ static const struct atmel_pwm_data atmel_sam9rl_pwm_data = { }, .cfg = { /* 16 bits to keep period and duty. */ - .max_period = 0xffff, + .period_bits = 16, }, }; @@ -302,7 +312,7 @@ static const struct atmel_pwm_data atmel_sama5_pwm_data = { }, .cfg = { /* 16 bits to keep period and duty. */ - .max_period = 0xffff, + .period_bits = 16, }, }; @@ -315,7 +325,7 @@ static const struct atmel_pwm_data mchp_sam9x60_pwm_data = { }, .cfg = { /* 32 bits to keep period and duty. */ - .max_period = 0xffffffff, + .period_bits = 32, }, }; |