diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2016-06-10 08:43:21 -0400 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2016-07-11 06:07:24 -0400 |
commit | ab248b603960a4b6effaa9e16fc1ea84a33210c7 (patch) | |
tree | 116a0ba4981a5e54960d934e0b5339809f089b99 /drivers/pwm/pwm-lpss.c | |
parent | e5ca42458b6278b7d5866e08dae7c45349af2157 (diff) |
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/pwm-lpss.c')
-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, | |||
91 | int duty_ns, int period_ns) | 91 | int duty_ns, int period_ns) |
92 | { | 92 | { |
93 | struct pwm_lpss_chip *lpwm = to_lpwm(chip); | 93 | struct pwm_lpss_chip *lpwm = to_lpwm(chip); |
94 | u8 on_time_div; | 94 | unsigned long long on_time_div; |
95 | unsigned long c, base_unit_range; | 95 | unsigned long c, base_unit_range; |
96 | unsigned long long base_unit, freq = NSEC_PER_SEC; | 96 | unsigned long long base_unit, freq = NSEC_PER_SEC; |
97 | u32 ctrl; | 97 | u32 ctrl; |
@@ -113,7 +113,9 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
113 | 113 | ||
114 | if (duty_ns <= 0) | 114 | if (duty_ns <= 0) |
115 | duty_ns = 1; | 115 | duty_ns = 1; |
116 | on_time_div = 255 - (255 * duty_ns / period_ns); | 116 | on_time_div = 255ULL * duty_ns; |
117 | do_div(on_time_div, period_ns); | ||
118 | on_time_div = 255ULL - on_time_div; | ||
117 | 119 | ||
118 | pm_runtime_get_sync(chip->dev); | 120 | pm_runtime_get_sync(chip->dev); |
119 | 121 | ||