From 67ad13e13f336b970a43e0c728b822916e3a7b4b Mon Sep 17 00:00:00 2001 From: Johnny Liu Date: Mon, 21 Jul 2025 04:18:07 +0000 Subject: [PATCH] pwm: tegra: Fix types of input arguments Given the structure of pwm_state struct pwm_state { u64 period; u64 duty_cycle; ... }; Correct the types of input arguments of tegra_pwm_config to avoid loss of precision or quantization error. Bug 5308986 Signed-off-by: Johnny Liu Signed-off-by: Robert Lin Change-Id: I3362bda20b9a96476176fbfede5f87d7a125ad7e Reviewed-on: https://git-master.nvidia.com/r/c/3rdparty/canonical/linux-noble/+/3455750 GVS: buildbot_gerritrpt Reviewed-by: Bibek Basu --- drivers/pwm/pwm-tegra.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index 2e6a8c74e6bd..0b3409b8f109 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -77,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -147,7 +148,7 @@ static inline void pwm_writel_mask32(struct tegra_pwm_chip *pc, } static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) + u64 duty_ns, u64 period_ns) { struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); unsigned long channel_o = pc->soc->channel_offset; @@ -157,6 +158,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, unsigned long scale_s = pc->soc->scale_shift; unsigned long required_clk_rate; u32 pwm_f, pfm_f; + u64 val; int err; /* @@ -170,8 +172,11 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * per (1 + pc->pwm_depth) cycles and make sure to round to the * nearest integer during division. */ - pwm_f = (u32)DIV_ROUND_CLOSEST_ULL(duty_ns * (1 + pc->pwm_depth), - period_ns); + val = mul_u64_u64_div_u64(duty_ns, 1 + pc->pwm_depth, period_ns); + if (val > U32_MAX) + return -EINVAL; + + pwm_f = (u32)val; /* Avoid overflow on 100% duty cycle */ if (pwm_f == 1 + pc->pwm_depth) @@ -182,8 +187,11 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * required_clk_rate is a reference rate for source clock and * it is derived based on user requested period. */ - required_clk_rate = DIV_ROUND_UP_ULL( - (u64)NSEC_PER_SEC * (1 + pc->pwm_depth), period_ns); + val = mul_u64_u64_div_u64(NSEC_PER_SEC, 1 + pc->pwm_depth, period_ns); + if (val > U32_MAX) + return -EINVAL; + + required_clk_rate = (u32)val; pc->clk_rate = clk_get_rate(pc->clk); if (pc->clk_rate < required_clk_rate) return -EINVAL;