summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeung-Woo Kim <sw0312.kim@samsung.com>2016-08-16 23:22:01 +0900
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-12-14 13:54:36 +0900
commit86c2eab44e82335fa823efd57ec38895929ffd35 (patch)
tree14ed70a2f3fdc9026ad5d05f020a57da02201283
parent0e82e9072af96d58e85122296c074a37085879e7 (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> [Backport from mainline to remove UBSAN warning] Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com> Change-Id: Idf20ea7ccb2d20d0317e5c82498dd1e7fa3656cc
-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 ff201e1b9219..0ec05489d8ed 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,
* divider settings and choose the lowest divisor that can generate
* frequencies lower than requested.
*/
- for (div = variant->div_base; div < 4; ++div)
- if ((rate >> (variant->bits + div)) < freq)
- break;
+ if (variant->bits < 32) {
+ /* Only for s3c24xx */
+ for (div = variant->div_base; div < 4; ++div)
+ if ((rate >> (variant->bits + div)) < freq)
+ break;
+ } else {
+ /*
+ * Other variants have enough counter bits to generate any
+ * requested rate, so no need to check higher divisors.
+ */
+ div = variant->div_base;
+ }
pwm_samsung_set_divisor(chip, chan, BIT(div));