[PATCH] pwm: imx27: Fix variable truncation in .apply()

Frank Li Frank.li at nxp.com
Thu May 21 11:56:48 PDT 2026


On Wed, May 20, 2026 at 09:00:54PM -0300, Ronaldo Nunez wrote:
> This patch fixes a variable truncation when calculating period in

Remove "This Patch" just

Fix a variable 'tmp' truncation when calculating period in

> microseconds as part of the solution for the ERR051198 in .apply()
> callback.
>
> The problem was identified when reducing the duty cycle through sysfs,
> with enable set to 1. The condition to fix errata ERR051198 for period
> smaller than 2us is always being met, due to a truncation on tmp,
> variable from .apply() callback, caused by the multiplication of
> NSEC_PER_SEC, PWMPR (period register) and the prescaler which can easily
> overflow u32.

It'd better provide actual example value for PWMPR and prescaler when
overflow happen.

> Declaring tmp as u64 makes it large enough to accommodate
> larger multiplication results.
>
> Testing:
> - Hardware: Udoo Neo Extended with iMX6SoloX SoC
> - Tools: Verified with a logic analyzer

needn't this part.

Frank
>
> Signed-off-by: Ronaldo Nunez <rnunez at baylibre.com>
> ---
>  drivers/pwm/pwm-imx27.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
> index 3d34cdc4a3a5..c8b801fcb525 100644
> --- a/drivers/pwm/pwm-imx27.c
> +++ b/drivers/pwm/pwm-imx27.c
> @@ -200,7 +200,7 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
>  static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
>  			   const struct pwm_state *state)
>  {
> -	unsigned long period_cycles, duty_cycles, prescale, period_us, tmp;
> +	unsigned long period_cycles, duty_cycles, prescale, period_us;
>  	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
>  	unsigned long long c;
>  	unsigned long long clkrate;
> @@ -208,6 +208,7 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
>  	int val;
>  	int ret;
>  	u32 cr;
> +	u64 tmp;
>
>  	clkrate = clk_get_rate(imx->clks[PWM_IMX27_PER].clk);
>  	c = clkrate * state->period;
> @@ -249,6 +250,11 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
>  	val = readl(imx->mmio_base + MX3_PWMPR);
>  	val = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val;
>  	cr = readl(imx->mmio_base + MX3_PWMCR);
> +
> +	/*
> +	 * tmp stores period in nanoseconds. Result fits in u64 since
> +	 * val <= 0xfffe and prescaler in [1, 0x1000].
> +	 */
>  	tmp = NSEC_PER_SEC * (u64)(val + 2) * MX3_PWMCR_PRESCALER_GET(cr);
>  	tmp = DIV_ROUND_UP_ULL(tmp, clkrate);
>  	period_us = DIV_ROUND_UP_ULL(tmp, 1000);
> --
> 2.53.0
>



More information about the linux-arm-kernel mailing list