[PATCH 1/5] pwm: dwc: Fix 32 bit overflow when computing duty/period in get_state

From: shao.mingyin

Date: Fri Nov 06 2026 - 11:13:41 EST


From: Shao Mingyin <shao.mingyin@xxxxxxxxxx>

dwc_pwm_get_state() computes duty and period with
"duty = (ld + 1) * dwc->clk_ns". ld and ld2 are u32 and dwc->clk_ns is
an unsigned int, so the multiplication is carried out in 32 bit and wraps
modulo 2^32 before the (already truncated) result is assigned to the u64
duty/period variables. For load counts above ~2^32 / clk_ns the reported
duty cycle and period are wrong.

Cast the load counts to u64 before multiplying.

Fixes: 4aff152d14c14 ("pwm: dwc: add PWM bit unset in get_state call")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
---

diff --git a/drivers/pwm/pwm-dwc-core.c b/drivers/pwm/pwm-dwc-core.c
index 6dabec93a3c6..104393c499f0 100644
--- a/drivers/pwm/pwm-dwc-core.c
+++ b/drivers/pwm/pwm-dwc-core.c
@@ -137,11 +137,11 @@ static int dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
* based on the timer load-count only.
*/
if (ctrl & DWC_TIM_CTRL_PWM) {
- duty = (ld + 1) * dwc->clk_ns;
- period = (ld2 + 1) * dwc->clk_ns;
+ duty = ((u64)ld + 1) * dwc->clk_ns;
+ period = ((u64)ld2 + 1) * dwc->clk_ns;
period += duty;
} else {
- duty = (ld + 1) * dwc->clk_ns;
+ duty = ((u64)ld + 1) * dwc->clk_ns;
period = duty * 2;
}

--
2.47.0