[PATCH v7 0/8] Rust Abstractions for PWM subsystem with TH1520 PWM driver

Michal Wilczynski
2025-07-02T13:49:56Z

This patch series introduces Rust support for the T-HEAD TH1520 PWM
controller and demonstrates its use for fan control on the Sipeed Lichee
Pi 4A board.

The primary goal of this patch series is to introduce a basic set of
Rust abstractions for the Linux PWM subsystem. As a first user and
practical demonstration of these abstractions, the series also provides
a functional PWM driver for the T-HEAD TH1520 SoC. This allows control
of its PWM channels and ultimately enables temperature controlled fan
support for the Lichee Pi 4A board. This work aims to explore the use of
Rust for PWM drivers and lay a foundation for potential future
Rust based PWM drivers.

The core of this series is a new rust/kernel/pwm.rs module that provides
abstractions for writing PWM chip provider drivers in Rust. This has
been significantly reworked from v1 based on extensive feedback. The key
features of the new abstraction layer include:

- Ownership and Lifetime Management: The pwm::Chip wrapper is managed
by ARef, correctly tying its lifetime to its embedded struct device
reference counter. Chip registration is handled by a pwm::Registration
RAII guard, which guarantees that pwmchip_add is always paired with
pwmchip_remove, preventing resource leaks.

- Modern and Safe API: The PwmOps trait is now based on the modern
waveform API (round_waveform_tohw, write_waveform, etc.) as recommended
by the subsystem maintainer. It is generic over a driver's
hardware specific data structure, moving all unsafe serialization logic
into the abstraction layer and allowing drivers to be written in 100%
safe Rust.

- Ergonomics: The API provides safe, idiomatic wrappers for other PWM
types (State, Args, Device, etc.) and uses standard kernel error
handling patterns.

The series is structured as follows:
- Expose PWM_WFHWSIZE in public header for bindgen.
- Rust PWM Abstractions: The new safe abstraction layer.
- TH1520 PWM Driver: A new Rust driver for the TH1520 SoC, built on
top of the new abstractions.
- Device Tree Bindings & Nodes: The remaining patches add the necessary
DT bindings and nodes for the TH1520 PWM controller, and the PWM fan
configuration for the Lichee Pi 4A board.

Testing:
Tested on the TH1520 SoC. The fan works correctly. The duty/period
calculations are correct. Fan starts slow when the chip is not hot and
gradually increases the speed when PVT reports higher temperatures.

The patches are based on mainline, with some dependencies which are not
merged yet - platform Io support [1].

Reference repository with all the patches together can be found on
github [2].

[1] - https://lore.kernel.org/rust-for-linux/20250509-topics-tyr-platform_iomem-v8-0-e9f1725a40da@collabora.com/
[2] - https://github.com/mwilczy/linux/commits/rust-next-pwm-working-fan-for-sending-v11/

---
Changes in v7:
- Made parent_device function private and moved casts to Device<Bound>
there as well.
- Link to v6: https://lore.kernel.org/r/20250701-rust-next-pwm-working-fan-for-sending-v6-0-2710932f6f6b@samsung.com

Changes in v6:
- Re-based on top of linux-next, dropped two already accepted commits.
- After re-basing the IoMem dependent patchset stopped working,
reworked it to use similar API like the PCI subsystem (I think it
will end up the same). Re-worked the driver for it as well.
- Remove the apply and get_state callbacks, and most of the State as
well, as the old way of implementing drivers should not be possible
in Rust. Left only enabled(), since it's useful for my driver.
- Removed the public set_drvdata() method from pwm::Chip
- Moved WFHWSIZE to the public include/linux/pwm.h header and renamed it
to PWM_WFHWSIZE, allowing bindgen to create safe FFI bindings.
- Corrected the ns_to_cycles integer calculation in the TH1520 driver to
handle overflow correctly.
- Updated the Kconfig entry for the TH1520 driver to select the Rust
abstractions for a better user experience.

- Link to v5: https://lore.kernel.org/r/20250623-rust-next-pwm-working-fan-for-sending-v5-0-0ca23747c23e@samsung.com

Changes in v5:
- Reworked `pwm::Chip` creation to take driver data directly, which
allowed making the `chip.drvdata()` accessor infallible
- added missing `pwm.c` file lost during the commit split (sorry !)
- Link to v4: https://lore.kernel.org/r/20250618-rust-next-pwm-working-fan-for-sending-v4-0-a6a28f2b6d8a@samsung.com

Changes in v4:
- Reworked the pwm::Registration API to use the devres framework,
addressing lifetime issue.
- Corrected the PwmOps trait and its callbacks to use immutable references
(&Chip, &Device) for improved safety.
- Applied various code style and naming cleanups based on feedback

- Link to v3: https://lore.kernel.org/r/20250617-rust-next-pwm-working-fan-for-sending-v3-0-1cca847c6f9f@samsung.com

Changes in v3:
- Addressed feedback from Uwe by making multiple changes to the TH1520
driver and the abstraction layer.
- Split the core PWM abstractions into three focused commits to ease
review per Benno request.
- Confirmed the driver now works correctly with CONFIG_PWM_DEBUG enabled
by implementing the full waveform API, which correctly reads the
hardware state.
- Refactored the Rust code to build cleanly with
CONFIG_RUST_BUILD_ASSERT_ALLOW=n, primarily by using the try_* family of
functions for IoMem access.
- Included several cosmetic changes and cleanups to the abstractions
per Miguel review.

- Link to v2: https://lore.kernel.org/r/20250610-rust-next-pwm-working-fan-for-sending-v2-0-753e2955f110@samsung.com

Changes in v2:
- Reworked the PWM abstraction layer based on extensive feedback.
- Replaced initial devm allocation with a proper ARef<Chip> lifetime model
using AlwaysRefCounted.
- Implemented a Registration RAII guard to ensure safe chip add/remove.
- Migrated the PwmOps trait from the legacy .apply callback to the modern
waveform API.
- Refactored the TH1520 driver to use the new, safer abstractions.
- Added a patch to mark essential bus clocks as CLK_IGNORE_UNUSED to fix
boot hangs when the PWM and thermal sensors are enabled.
- Link to v1: https://lore.kernel.org/r/20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com

---
Michal Wilczynski (8):
pwm: Expose PWM_WFHWSIZE in public header
rust: pwm: Add Kconfig and basic data structures
rust: pwm: Add core 'Device' and 'Chip' object wrappers
rust: pwm: Add driver operations trait and registration support
pwm: Add Rust driver for T-HEAD TH1520 SoC
dt-bindings: pwm: thead: Add T-HEAD TH1520 PWM controller
riscv: dts: thead: Add PWM controller node
riscv: dts: thead: Add PWM fan and thermal control

.../devicetree/bindings/pwm/thead,th1520-pwm.yaml | 48 ++
MAINTAINERS | 8 +
arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts | 67 ++
arch/riscv/boot/dts/thead/th1520.dtsi | 7 +
drivers/pwm/Kconfig | 24 +
drivers/pwm/Makefile | 1 +
drivers/pwm/core.c | 26 +-
drivers/pwm/pwm_th1520.rs | 338 +++++++++
include/linux/pwm.h | 2 +
rust/bindings/bindings_helper.h | 1 +
rust/helpers/helpers.c | 1 +
rust/helpers/pwm.c | 20 +
rust/kernel/lib.rs | 2 +
rust/kernel/pwm.rs | 770 +++++++++++++++++++++
14 files changed, 1301 insertions(+), 14 deletions(-)
---
base-commit: d52ca12c4915f3ee67aeaa5ad9e3597a40e4620e
change-id: 20250524-rust-next-pwm-working-fan-for-sending-552ad2d1b193

Best regards,
--
Michal Wilczynski <m.wilczynski@samsung.com>