lkml.org 
[lkml]   [2021]   [Mar]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.11 533/775] pwm: iqs620a: Fix overflow and optimize calculations
    Date
    From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

    [ Upstream commit 72d6b2459dbd539c1369149e501fdc3dc8ddef16 ]

    If state->duty_cycle is 0x100000000000000, the previous calculation of
    duty_scale overflows and yields a duty cycle ratio of 0% instead of
    100%. Fix this by clamping the requested duty cycle to the maximal
    possible duty cycle first. This way it is possible to use a native
    integer division instead of a (depending on the architecture) more
    expensive 64bit division.

    With this change in place duty_scale cannot be bigger than 256 which
    allows to simplify the calculation of duty_val.

    Fixes: 6f0841a8197b ("pwm: Add support for Azoteq IQS620A PWM generator")
    Tested-by: Jeff LaBundy <jeff@labundy.com>
    Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
    Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/pwm/pwm-iqs620a.c | 8 +++++---
    1 file changed, 5 insertions(+), 3 deletions(-)

    diff --git a/drivers/pwm/pwm-iqs620a.c b/drivers/pwm/pwm-iqs620a.c
    index 5ede8255926ef..14b18fb4f5274 100644
    --- a/drivers/pwm/pwm-iqs620a.c
    +++ b/drivers/pwm/pwm-iqs620a.c
    @@ -46,7 +46,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
    {
    struct iqs620_pwm_private *iqs620_pwm;
    struct iqs62x_core *iqs62x;
    - u64 duty_scale;
    + unsigned int duty_cycle;
    + unsigned int duty_scale;
    int ret;

    if (state->polarity != PWM_POLARITY_NORMAL)
    @@ -70,7 +71,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
    * For lower duty cycles (e.g. 0), the PWM output is simply disabled to
    * allow an external pull-down resistor to hold the GPIO3/LTX pin low.
    */
    - duty_scale = div_u64(state->duty_cycle * 256, IQS620_PWM_PERIOD_NS);
    + duty_cycle = min_t(u64, state->duty_cycle, IQS620_PWM_PERIOD_NS);
    + duty_scale = duty_cycle * 256 / IQS620_PWM_PERIOD_NS;

    mutex_lock(&iqs620_pwm->lock);

    @@ -82,7 +84,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
    }

    if (duty_scale) {
    - u8 duty_val = min_t(u64, duty_scale - 1, 0xff);
    + u8 duty_val = duty_scale - 1;

    ret = regmap_write(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE,
    duty_val);
    --
    2.27.0


    \
     
     \ /
      Last update: 2021-03-02 14:40    [W:4.025 / U:0.668 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site