arch/arm/rp23xx: Fix PWM frequency, duty cycle and API migration.#18947
Merged
Conversation
Fixed three bugs in the RP23XX PWM driver: * setup_period: The previous divisor calculation used integer arithmetic that caused overflow and loss of precision. The divider is now computed as a 16-bit fixed-point value (div16) using 64-bit arithmetic, and clamped to the valid hardware range (0x10 to 0xFFF). * setup_pulse: The compare value was incorrectly scaled by TOP instead of 65535, producing wrong duty cycles. The formula is now corrected to ((duty * (top + 1)) / 65535) with an overflow guard. * pwm_start: The driver was not updated as part of the breaking change introduced in commit 4df80e1 ("!drivers/pwm: remove PWM_MULTICHAN option"). Access to single channel API is now info->channels[0].duty instead of info[0].duty. Signed-off-by: Brunocor26 <bruno.correia@ubi.pt>
xiaoxiang781216
approved these changes
May 24, 2026
lupyuen
approved these changes
May 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix three bugs in the RP23XX PWM driver that produced incorrect frequency, duty cycle output, and build failure on real hardware:
setup_period: The previous divisor calculation used integer arithmetic that caused overflow and loss of precision. The divider is now computed using 64-bit arithmetic and clamped to the valid hardware range (0x10 to 0xFFF).setup_pulse: The compare value was incorrectly scaled by TOP instead of 65535, producing wrong duty cycles for all values. The corrected formula is:compare = (duty * (top + 1)) / 65535, with an overflow guard.pwm_start: The driver was not updated as part of the breaking change introduced in commit 4df80e1 ("!drivers/pwm: remove PWM_MULTICHAN option"), which migrated the single-channel API frominfo->XXXtoinfo->channels[0].XXX. This caused the driver to fail to compilewith CONFIG_PWM=y and CONFIG_PWM_NCHANNELS=1.
The fix was derived from the RP2350 PWM formula as per the RP2350 datasheet
(section 12.5.2.6, "Configuring PWM period"):
f_pwm = f_sys / ((TOP + 1) * (CSR_PH_CORRECT + 1) * (DIV_INT + DIV_FRAC / 16))
Reference: https://pip-assets.raspberrypi.com/categories/1214-rp2350/documents/RP-008373-DS-2-rp2350-datasheet.pdf
Impact
NO. Bug fix only.
NO. The fix corrects silent hardware misconfiguration.
YES. The driver previously failed to compile with CONFIG_PWM=y and CONFIG_PWM_NCHANNELS=1 due to missing API migration from commit 4df80e1.
YES. Affects all RP23XX boards using the PWM driver.
NO.
NO.
NO.
Testing
I confirm that changes are verified on local setup and works as intended:
Verification at 25 kHz (f_sys = 150 MHz):
Expected: TOP = 5999, DIV = 16 (1.0), f_pwm = 150e6 / (6000 * 1.0) = 25 kHz
Testing logs before change (original driver, f_sys=150MHz, f_pwm=25kHz):
Duty 10%:
Duty 50%:
Duty 100%:
The original code produces incorrect results:
Testing logs after change:
Duty 10% (duty=0x1999=6553, compare expected=0x0257=599):
nsh> pwm -d 10 pwm_start: PWM3 setup_period: PWM3 freq=25000 top=5999 div=16 setup_pulse: PWM3 compare=0x00000257 flags=0x00000000Duty 50% (duty=0x7fff=32767, compare expected=0x0BB7=2999):
nsh> pwm -d 50 pwm_start: PWM3 setup_period: PWM3 freq=25000 top=5999 div=16 setup_pulse: PWM3 compare=0x00000bb7 flags=0x00000000Duty 100% (duty=0xffff=65535, compare expected=0x176F=5999):
nsh> pwm -d 100 pwm_start: PWM3 setup_period: PWM3 freq=25000 top=5999 div=16 setup_pulse: PWM3 compare=0x0000176f flags=0x00000000All compare values match the expected hardware calculations.
PR verification Self-Check