pwm: mtk-disp: Fix overflow in period and duty calculation
authorJitao Shi <jitao.shi@mediatek.com>
Sun, 8 Aug 2021 13:24:32 +0000 (21:24 +0800)
committerThierry Reding <thierry.reding@gmail.com>
Thu, 2 Sep 2021 20:27:44 +0000 (22:27 +0200)
Current calculation for period and high_width may have 64-bit overflow.
state->period and rate are u64. rate * state->period will overflow.

clk_div = div_u64(rate * state->period, NSEC_PER_SEC)
period = div64_u64(rate * state->period, div);
high_width = div64_u64(rate * state->duty_cycle, div);

This patch is to resolve it by using mul_u64_u64_div_u64().

Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
drivers/pwm/pwm-mtk-disp.c

index caabcb3..73f8103 100644 (file)
@@ -119,7 +119,7 @@ static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
         * high_width = (PWM_CLK_RATE * duty_ns) / (10^9 * (clk_div + 1))
         */
        rate = clk_get_rate(mdp->clk_main);
-       clk_div = div_u64(rate * state->period, NSEC_PER_SEC) >>
+       clk_div = mul_u64_u64_div_u64(state->period, rate, NSEC_PER_SEC) >>
                          PWM_PERIOD_BIT_WIDTH;
        if (clk_div > PWM_CLKDIV_MAX) {
                if (!mdp->enabled) {
@@ -130,11 +130,11 @@ static int mtk_disp_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
        }
 
        div = NSEC_PER_SEC * (clk_div + 1);
-       period = div64_u64(rate * state->period, div);
+       period = mul_u64_u64_div_u64(state->period, rate, div);
        if (period > 0)
                period--;
 
-       high_width = div64_u64(rate * state->duty_cycle, div);
+       high_width = mul_u64_u64_div_u64(state->duty_cycle, rate, div);
        value = period | (high_width << PWM_HIGH_WIDTH_SHIFT);
 
        mtk_disp_pwm_update_bits(mdp, mdp->data->con0,