From: Sasha Levin <sashal@kernel.org>
To: "Uwe Kleine-König" <ukleinek@kernel.org>
Cc: patches@lists.linux.dev, stable@vger.kernel.org,
Nylon Chen <nylon.chen@sifive.com>, Zong Li <zong.li@sifive.com>,
Vincent Chen <vincent.chen@sifive.com>,
paul.walmsley@sifive.com, samuel.holland@sifive.com,
linux-pwm@vger.kernel.org, linux-riscv@lists.infradead.org
Subject: Re: [PATCH AUTOSEL 6.1 24/51] pwm: sifive: Fix PWM algorithm and clarify inverted compare behavior
Date: Sat, 16 Aug 2025 09:08:19 -0400 [thread overview]
Message-ID: <aKCCwwjndbFXFbIB@lappy> (raw)
In-Reply-To: <52ycm5nf2jrxdmdmcijz57xhm2twspjmmiign6zq6rp3d5wt6t@tq5w47fmiwgg>
On Mon, Aug 04, 2025 at 12:38:15PM +0200, Uwe Kleine-König wrote:
>Hello,
>
>On Sun, Aug 03, 2025 at 08:36:16PM -0400, Sasha Levin wrote:
>> From: Nylon Chen <nylon.chen@sifive.com>
>>
>> [ Upstream commit 7dbc4432ea6bf9d709391eb57f1e9fb44e99845a ]
>>
>> The `frac` variable represents the pulse inactive time, and the result
>> of this algorithm is the pulse active time. Therefore, we must reverse
>> the result.
>>
>> Although the SiFive Reference Manual states "pwms >= pwmcmpX -> HIGH",
>> the hardware behavior is inverted due to a fixed XNOR with 0. As a result,
>> the pwmcmp register actually defines the low (inactive) portion of the pulse.
>>
>> The reference is SiFive FU740-C000 Manual[0]
>>
>> Link: https://sifive.cdn.prismic.io/sifive/1a82e600-1f93-4f41-b2d8-86ed8b16acba_fu740-c000-manual-v1p6.pdf [0]
>>
>> Co-developed-by: Zong Li <zong.li@sifive.com>
>> Signed-off-by: Zong Li <zong.li@sifive.com>
>> Co-developed-by: Vincent Chen <vincent.chen@sifive.com>
>> Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
>> Signed-off-by: Nylon Chen <nylon.chen@sifive.com>
>> Link: https://lore.kernel.org/r/20250529035341.51736-3-nylon.chen@sifive.com
>> Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>
>> Signed-off-by: Sasha Levin <sashal@kernel.org>
>> ---
>>
>> LLM Generated explanations, may be completely bogus:
>>
>> **Backport Status: YES**
>>
>> This commit should be backported to stable kernel trees. Here's my
>> extensive analysis:
>>
>> ## Critical Bug Fix Analysis
>>
>> 1. **The commit fixes a significant functional bug** - The PWM algorithm
>> was fundamentally broken:
>> - The `frac` variable was incorrectly used (lines 158-161 in
>> original, now 168-171)
>> - The driver was writing the duty cycle value directly to PWMCMP
>> register (line 193), but the hardware actually expects the
>> **inactive** (low) time
>> - This results in inverted PWM output behavior where users get the
>> opposite duty cycle from what they request
>>
>> 2. **Hardware behavior discrepancy** - The commit reveals and fixes a
>> critical mismatch between documentation and actual hardware:
>> - The documentation states "pwms >= pwmcmpX -> HIGH"
>> - But the hardware has a hard-tied XNOR with 0 that inverts this
>> behavior
>> - The driver now correctly compensates for this hardware quirk
>>
>> 3. **User-visible impact**:
>> - **In `pwm_sifive_get_state()`**: The driver now correctly inverts
>> the value read from hardware (lines 115->122-126)
>> - **In `pwm_sifive_apply()`**: The driver now inverts the duty cycle
>> before writing to hardware (lines 162->171)
>> - **Polarity change**: Changed from `PWM_POLARITY_INVERSED` to
>> `PWM_POLARITY_NORMAL` (lines 126->137, 142->152)
>> - **Documentation fix**: Updated comment from "cannot generate 100%
>> duty" to "cannot generate 0% duty" (lines 11->27, 160->170)
>>
>> 4. **The fix is relatively small and contained**:
>> - Changes are isolated to the PWM algorithm logic
>> - No architectural changes or new features
>> - Simple mathematical inversion: `duty = (1U << PWM_SIFIVE_CMPWIDTH)
>> - 1 - inactive`
>>
>> 5. **No risky side effects**:
>> - The change is straightforward and mathematically correct
>> - Doesn't affect other subsystems
>> - Maintains the same register interface
>>
>> 6. **Affects all SiFive PWM users**:
>> - Any system using SiFive FU540 or FU740 SoCs would have incorrect
>> PWM output
>> - This includes various RISC-V development boards and embedded
>> systems
>> - Users would get inverted duty cycles, potentially breaking motor
>> controls, LED dimming, etc.
>>
>> 7. **Clear documentation reference**:
>> - The commit references the official SiFive FU740-C000 Manual
>> - Provides clear explanation of the hardware behavior mismatch
>>
>> The bug causes PWM outputs to be inverted from user expectations, which
>> is a significant functional issue that would affect any system relying
>> on proper PWM behavior for motor control, LED dimming, or other PWM-
>> dependent functionality. The fix is clean, minimal, and addresses a
>> clear hardware/software mismatch that exists in production systems.
>
>What your LLM missed is that the device trees using this PWM relied on
>this "bug" and so this commit should be applied either together with
>f4bcf818e5d6 ("riscv: dts: sifive: unleashed/unmatched: Remove PWM
>controlled LED's active-low properties") or not at all.
>
>Given that there might be device trees in use that are not in mainline
>and that break in the same way without a possiblity for us to fix that I
>tend to prefer not to backport this breaking change to stable.
Ack, I'll drop it. Thanks!
--
Thanks,
Sasha
WARNING: multiple messages have this Message-ID (diff)
From: Sasha Levin <sashal@kernel.org>
To: "Uwe Kleine-König" <ukleinek@kernel.org>
Cc: patches@lists.linux.dev, stable@vger.kernel.org,
Nylon Chen <nylon.chen@sifive.com>, Zong Li <zong.li@sifive.com>,
Vincent Chen <vincent.chen@sifive.com>,
paul.walmsley@sifive.com, samuel.holland@sifive.com,
linux-pwm@vger.kernel.org, linux-riscv@lists.infradead.org
Subject: Re: [PATCH AUTOSEL 6.1 24/51] pwm: sifive: Fix PWM algorithm and clarify inverted compare behavior
Date: Sat, 16 Aug 2025 09:08:19 -0400 [thread overview]
Message-ID: <aKCCwwjndbFXFbIB@lappy> (raw)
In-Reply-To: <52ycm5nf2jrxdmdmcijz57xhm2twspjmmiign6zq6rp3d5wt6t@tq5w47fmiwgg>
On Mon, Aug 04, 2025 at 12:38:15PM +0200, Uwe Kleine-König wrote:
>Hello,
>
>On Sun, Aug 03, 2025 at 08:36:16PM -0400, Sasha Levin wrote:
>> From: Nylon Chen <nylon.chen@sifive.com>
>>
>> [ Upstream commit 7dbc4432ea6bf9d709391eb57f1e9fb44e99845a ]
>>
>> The `frac` variable represents the pulse inactive time, and the result
>> of this algorithm is the pulse active time. Therefore, we must reverse
>> the result.
>>
>> Although the SiFive Reference Manual states "pwms >= pwmcmpX -> HIGH",
>> the hardware behavior is inverted due to a fixed XNOR with 0. As a result,
>> the pwmcmp register actually defines the low (inactive) portion of the pulse.
>>
>> The reference is SiFive FU740-C000 Manual[0]
>>
>> Link: https://sifive.cdn.prismic.io/sifive/1a82e600-1f93-4f41-b2d8-86ed8b16acba_fu740-c000-manual-v1p6.pdf [0]
>>
>> Co-developed-by: Zong Li <zong.li@sifive.com>
>> Signed-off-by: Zong Li <zong.li@sifive.com>
>> Co-developed-by: Vincent Chen <vincent.chen@sifive.com>
>> Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
>> Signed-off-by: Nylon Chen <nylon.chen@sifive.com>
>> Link: https://lore.kernel.org/r/20250529035341.51736-3-nylon.chen@sifive.com
>> Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>
>> Signed-off-by: Sasha Levin <sashal@kernel.org>
>> ---
>>
>> LLM Generated explanations, may be completely bogus:
>>
>> **Backport Status: YES**
>>
>> This commit should be backported to stable kernel trees. Here's my
>> extensive analysis:
>>
>> ## Critical Bug Fix Analysis
>>
>> 1. **The commit fixes a significant functional bug** - The PWM algorithm
>> was fundamentally broken:
>> - The `frac` variable was incorrectly used (lines 158-161 in
>> original, now 168-171)
>> - The driver was writing the duty cycle value directly to PWMCMP
>> register (line 193), but the hardware actually expects the
>> **inactive** (low) time
>> - This results in inverted PWM output behavior where users get the
>> opposite duty cycle from what they request
>>
>> 2. **Hardware behavior discrepancy** - The commit reveals and fixes a
>> critical mismatch between documentation and actual hardware:
>> - The documentation states "pwms >= pwmcmpX -> HIGH"
>> - But the hardware has a hard-tied XNOR with 0 that inverts this
>> behavior
>> - The driver now correctly compensates for this hardware quirk
>>
>> 3. **User-visible impact**:
>> - **In `pwm_sifive_get_state()`**: The driver now correctly inverts
>> the value read from hardware (lines 115->122-126)
>> - **In `pwm_sifive_apply()`**: The driver now inverts the duty cycle
>> before writing to hardware (lines 162->171)
>> - **Polarity change**: Changed from `PWM_POLARITY_INVERSED` to
>> `PWM_POLARITY_NORMAL` (lines 126->137, 142->152)
>> - **Documentation fix**: Updated comment from "cannot generate 100%
>> duty" to "cannot generate 0% duty" (lines 11->27, 160->170)
>>
>> 4. **The fix is relatively small and contained**:
>> - Changes are isolated to the PWM algorithm logic
>> - No architectural changes or new features
>> - Simple mathematical inversion: `duty = (1U << PWM_SIFIVE_CMPWIDTH)
>> - 1 - inactive`
>>
>> 5. **No risky side effects**:
>> - The change is straightforward and mathematically correct
>> - Doesn't affect other subsystems
>> - Maintains the same register interface
>>
>> 6. **Affects all SiFive PWM users**:
>> - Any system using SiFive FU540 or FU740 SoCs would have incorrect
>> PWM output
>> - This includes various RISC-V development boards and embedded
>> systems
>> - Users would get inverted duty cycles, potentially breaking motor
>> controls, LED dimming, etc.
>>
>> 7. **Clear documentation reference**:
>> - The commit references the official SiFive FU740-C000 Manual
>> - Provides clear explanation of the hardware behavior mismatch
>>
>> The bug causes PWM outputs to be inverted from user expectations, which
>> is a significant functional issue that would affect any system relying
>> on proper PWM behavior for motor control, LED dimming, or other PWM-
>> dependent functionality. The fix is clean, minimal, and addresses a
>> clear hardware/software mismatch that exists in production systems.
>
>What your LLM missed is that the device trees using this PWM relied on
>this "bug" and so this commit should be applied either together with
>f4bcf818e5d6 ("riscv: dts: sifive: unleashed/unmatched: Remove PWM
>controlled LED's active-low properties") or not at all.
>
>Given that there might be device trees in use that are not in mainline
>and that break in the same way without a possiblity for us to fix that I
>tend to prefer not to backport this breaking change to stable.
Ack, I'll drop it. Thanks!
--
Thanks,
Sasha
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2025-08-16 13:08 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-04 0:35 [PATCH AUTOSEL 6.1 01/51] usb: xhci: print xhci->xhc_state when queue_command failed Sasha Levin
2025-08-04 0:35 ` [PATCH AUTOSEL 6.1 02/51] cpufreq: CPPC: Mark driver with NEED_UPDATE_LIMITS flag Sasha Levin
2025-08-04 0:35 ` [PATCH AUTOSEL 6.1 03/51] selftests/futex: Define SYS_futex on 32-bit architectures with 64-bit time_t Sasha Levin
2025-08-04 0:35 ` Sasha Levin
2025-08-04 0:35 ` [PATCH AUTOSEL 6.1 04/51] usb: typec: ucsi: psy: Set current max to 100mA for BC 1.2 and Default Sasha Levin
2025-08-04 0:35 ` [PATCH AUTOSEL 6.1 05/51] regulator: core: repeat voltage setting request for stepped regulators Sasha Levin
2025-08-04 0:35 ` [PATCH AUTOSEL 6.1 06/51] usb: xhci: Avoid showing warnings for dying controller Sasha Levin
2025-08-04 0:35 ` [PATCH AUTOSEL 6.1 07/51] usb: xhci: Set avg_trb_len = 8 for EP0 during Address Device Command Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 08/51] usb: xhci: Avoid showing errors during surprise removal Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 09/51] remoteproc: imx_rproc: skip clock enable when M-core is managed by the SCU Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 10/51] gpio: wcd934x: check the return value of regmap_update_bits() Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 11/51] cpufreq: Exit governor when failed to start old governor Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 12/51] ARM: rockchip: fix kernel hang during smp initialization Sasha Levin
2025-08-04 0:36 ` Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 13/51] PM / devfreq: governor: Replace sscanf() with kstrtoul() in set_freq_store() Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 14/51] EDAC/synopsys: Clear the ECC counters on init Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 15/51] ASoC: soc-dapm: set bias_level if snd_soc_dapm_set_bias_level() was successed Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 16/51] thermal/drivers/qcom-spmi-temp-alarm: Enable stage 2 shutdown when required Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 17/51] tools/nolibc: define time_t in terms of __kernel_old_time_t Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 18/51] iio: adc: ad_sigma_delta: don't overallocate scan buffer Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 19/51] gpio: tps65912: check the return value of regmap_update_bits() Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 20/51] ARM: tegra: Use I/O memcpy to write to IRAM Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 21/51] tools/build: Fix s390(x) cross-compilation with clang Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 22/51] selftests: tracing: Use mutex_unlock for testing glob filter Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 23/51] ACPI: PRM: Reduce unnecessary printing to avoid user confusion Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 24/51] pwm: sifive: Fix PWM algorithm and clarify inverted compare behavior Sasha Levin
2025-08-04 0:36 ` Sasha Levin
2025-08-04 10:38 ` Uwe Kleine-König
2025-08-04 10:38 ` Uwe Kleine-König
2025-08-16 13:08 ` Sasha Levin [this message]
2025-08-16 13:08 ` Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 25/51] PM: runtime: Clear power.needs_force_resume in pm_runtime_reinit() Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 26/51] thermal: sysfs: Return ENODATA instead of EAGAIN for reads Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 27/51] PM: sleep: console: Fix the black screen issue Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 28/51] ACPI: processor: fix acpi_object initialization Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 29/51] mmc: sdhci-msm: Ensure SD card power isn't ON when card removed Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 30/51] ACPI: APEI: GHES: add TAINT_MACHINE_CHECK on GHES panic path Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 31/51] pps: clients: gpio: fix interrupt handling order in remove path Sasha Levin
2025-08-04 6:56 ` Rodolfo Giometti
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 32/51] reset: brcmstb: Enable reset drivers for ARCH_BCM2835 Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 33/51] mei: bus: Check for still connected devices in mei_cl_bus_dev_release() Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 34/51] mmc: rtsx_usb_sdmmc: Fix error-path in sd_set_power_mode() Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 35/51] ALSA: hda: Handle the jack polling always via a work Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 36/51] ALSA: hda: Disable jack polling at shutdown Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 37/51] x86/bugs: Avoid warning when overriding return thunk Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 38/51] ASoC: hdac_hdmi: Rate limit logging on connection and disconnection Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 39/51] ALSA: intel8x0: Fix incorrect codec index usage in mixer for ICH4 Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 40/51] ASoC: core: Check for rtd == NULL in snd_soc_remove_pcm_runtime() Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 41/51] usb: typec: intel_pmc_mux: Defer probe if SCU IPC isn't present Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 42/51] usb: core: usb_submit_urb: downgrade type check Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 43/51] usb: typec: fusb302: fix scheduling while atomic when using virtio-gpio Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 44/51] pm: cpupower: Fix the snapshot-order of tsc,mperf, clock in mperf_stop() Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 45/51] platform/x86: thinkpad_acpi: Handle KCOV __init vs inline mismatches Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 46/51] platform/chrome: cros_ec_typec: Defer probe on missing EC parent Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 47/51] ALSA: hda/ca0132: Fix buffer overflow in add_tuning_control Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 48/51] ALSA: pcm: Rewrite recalculate_boundary() to avoid costly loop Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 49/51] ALSA: usb-audio: Avoid precedence issues in mixer_quirks macros Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 50/51] iio: adc: ad7768-1: Ensure SYNC_IN pulse minimum timing requirement Sasha Levin
2025-08-04 0:36 ` [PATCH AUTOSEL 6.1 51/51] ASoC: codecs: rt5640: Retry DEVICE_ID verification Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aKCCwwjndbFXFbIB@lappy \
--to=sashal@kernel.org \
--cc=linux-pwm@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=nylon.chen@sifive.com \
--cc=patches@lists.linux.dev \
--cc=paul.walmsley@sifive.com \
--cc=samuel.holland@sifive.com \
--cc=stable@vger.kernel.org \
--cc=ukleinek@kernel.org \
--cc=vincent.chen@sifive.com \
--cc=zong.li@sifive.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.