diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2016-06-10 14:43:21 +0200 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2016-07-11 12:07:24 +0200 |
commit | ab248b603960a4b6effaa9e16fc1ea84a33210c7 (patch) | |
tree | 116a0ba4981a5e54960d934e0b5339809f089b99 /drivers/pwm | |
parent | pwm: lpss: Fix base_unit calculation for PWM frequency (diff) | |
download | linux-ab248b603960a4b6effaa9e16fc1ea84a33210c7.tar.xz linux-ab248b603960a4b6effaa9e16fc1ea84a33210c7.zip |
pwm: lpss: Prevent on_time_div overflow on lower frequencies
If duty_ns is large enough multiplying it by 255 overflows and results
wrong duty cycle value being programmed. For example with 10ms duty when
period is 20ms (50%) we get
255 * 10000000 / 20000000 = -87
because 255 * 10000000 overlows int. Whereas correct value should be
255 * 10000000 / 20000000 = 127
Fix this by using unsigned long long as type for on_time_div and changing
integer literals to use proper type annotation.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm')
-rw-r--r-- | drivers/pwm/pwm-lpss.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 98dc8b80b79d..be4658b42882 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -91,7 +91,7 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns) { struct pwm_lpss_chip *lpwm = to_lpwm(chip); - u8 on_time_div; + unsigned long long on_time_div; unsigned long c, base_unit_range; unsigned long long base_unit, freq = NSEC_PER_SEC; u32 ctrl; @@ -113,7 +113,9 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm, if (duty_ns <= 0) duty_ns = 1; - on_time_div = 255 - (255 * duty_ns / period_ns); + on_time_div = 255ULL * duty_ns; + do_div(on_time_div, period_ns); + on_time_div = 255ULL - on_time_div; pm_runtime_get_sync(chip->dev); |