aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeung-Woo Kim <sw0312.kim@samsung.com>2016-08-16 10:22:01 -0400
committerThierry Reding <thierry.reding@gmail.com>2016-09-06 04:48:55 -0400
commit04d68dea26b0a409d44e87ea573a131b6dc67e78 (patch)
tree30fe469fa845ba655d55396ca503ccd2a57bc5a5
parent549c50af251969ecc8de1f773921c2a861fd240b (diff)
pwm: samsung: Fix to use lowest div for large enough modulation bits
From pwm_samsung_calc_tin(), there is routine to find the lowest divider possible to generate lower frequency than requested one. But it is always possible to generate requested frequency with large enough modulation bits except on s3c24xx, so this patch fixes to use lowest div for the case. This patch removes following UBSAN warning: UBSAN: Undefined behaviour in drivers/pwm/pwm-samsung.c:197:13 shift exponent 32 is too large for 32-bit type 'long unsigned int' [...] [<c0670248>] (ubsan_epilogue) from [<c06707b4>] (__ubsan_handle_shift_out_of_bounds+0xd8/0x120) [<c06707b4>] (__ubsan_handle_shift_out_of_bounds) from [<c0694b28>] (pwm_samsung_config+0x508/0x6a4) [<c0694b28>] (pwm_samsung_config) from [<c069286c>] (pwm_apply_state+0x174/0x40c) [<c069286c>] (pwm_apply_state) from [<c0b2e070>] (pwm_fan_probe+0xc8/0x488) [<c0b2e070>] (pwm_fan_probe) from [<c07ba8b0>] (platform_drv_probe+0x70/0x150) [...] Cc: Tomasz Figa <tomasz.figa@gmail.com> Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com> Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
-rw-r--r--drivers/pwm/pwm-samsung.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index ada2d326dc3e..f113cda47032 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -193,9 +193,18 @@ static unsigned long pwm_samsung_calc_tin(struct samsung_pwm_chip *chip,
193 * divider settings and choose the lowest divisor that can generate 193 * divider settings and choose the lowest divisor that can generate
194 * frequencies lower than requested. 194 * frequencies lower than requested.
195 */ 195 */
196 for (div = variant->div_base; div < 4; ++div) 196 if (variant->bits < 32) {
197 if ((rate >> (variant->bits + div)) < freq) 197 /* Only for s3c24xx */
198 break; 198 for (div = variant->div_base; div < 4; ++div)
199 if ((rate >> (variant->bits + div)) < freq)
200 break;
201 } else {
202 /*
203 * Other variants have enough counter bits to generate any
204 * requested rate, so no need to check higher divisors.
205 */
206 div = variant->div_base;
207 }
199 208
200 pwm_samsung_set_divisor(chip, chan, BIT(div)); 209 pwm_samsung_set_divisor(chip, chan, BIT(div));
201 210