[PATCH 3/5] pwm: adp5585: Clamp on/off counters to the 16 bit register range
From: shao.mingyin
Date: Fri Nov 06 2026 - 11:13:44 EST
From: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
pwm_adp5585_apply() computes the on and off counter values as u32 and
writes them through cpu_to_le16() into 16 bit registers. The period is
only clamped to ADP5585_PWM_MAX_PERIOD_NS which is 2 * 0xffff oscillator
ticks, so for duty cycles close to a full period the on counter can
exceed 0xffff and is silently truncated by cpu_to_le16(), programming a
wrong duty cycle.
Clamp both counters to the representable range before writing them.
This is a saturation, not an exact mapping: when the on counter is
clamped the programmed period can be shorter than the requested one.
Fixes: e9b503879fd2 ("pwm: adp5585: Add Analog Devices ADP5585 support")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
---
diff --git a/drivers/pwm/pwm-adp5585.c b/drivers/pwm/pwm-adp5585.c
index 9a1dbba75bc1..da83fcd35e1d 100644
--- a/drivers/pwm/pwm-adp5585.c
+++ b/drivers/pwm/pwm-adp5585.c
@@ -96,6 +96,13 @@ static int pwm_adp5585_apply(struct pwm_chip *chip,
on = div_u64(duty_cycle, NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ);
off = div_u64(period, NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ) - on;
+ /*
+ * The on/off registers are 16 bits wide, clamp the counter values so
+ * that cpu_to_le16() below can't silently truncate them.
+ */
+ on = min_t(u32, on, 0xffff);
+ off = min_t(u32, off, 0xffff);
+
val = cpu_to_le16(off);
ret = regmap_bulk_write(regmap, info->pwm_offt_low, &val, 2);
if (ret)
--
2.47.0