Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: pwm: Add Kconfig and basic data structures

Introduce the foundational support for PWM abstractions in Rust.

This commit adds the `RUST_PWM_ABSTRACTIONS` Kconfig option to enable
the feature, along with the necessary build-system support and C
helpers.

It also introduces the first set of safe wrappers for the PWM
subsystem, covering the basic data carrying C structs and enums:
- `Polarity`: A safe wrapper for `enum pwm_polarity`.
- `Waveform`: A wrapper for `struct pwm_waveform`.
- `State`: A wrapper for `struct pwm_state`.

These types provide memory safe, idiomatic Rust representations of the
core PWM data structures and form the building blocks for the
abstractions that will follow.

Tested-by: Drew Fustini <fustini@kernel.org>
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
Reviewed-by: Elle Rhumsaa <elle@weathered-steel.dev>
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
Link: https://patch.msgid.link/20251016-rust-next-pwm-working-fan-for-sending-v16-2-a5df2405d2bd@samsung.com
Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>

authored by

Michal Wilczynski and committed by
Uwe Kleine-König
7b3dce81 ce284f88

+146
+8
MAINTAINERS
··· 20763 20763 F: include/linux/pwm_backlight.h 20764 20764 K: pwm_(config|apply_might_sleep|apply_atomic|ops) 20765 20765 20766 + PWM SUBSYSTEM BINDINGS [RUST] 20767 + M: Michal Wilczynski <m.wilczynski@samsung.com> 20768 + L: linux-pwm@vger.kernel.org 20769 + L: rust-for-linux@vger.kernel.org 20770 + S: Maintained 20771 + F: rust/helpers/pwm.c 20772 + F: rust/kernel/pwm.rs 20773 + 20766 20774 PXA GPIO DRIVER 20767 20775 M: Robert Jarzmik <robert.jarzmik@free.fr> 20768 20776 L: linux-gpio@vger.kernel.org
+12
drivers/pwm/Kconfig
··· 819 819 To compile this driver as a module, choose M here: the module 820 820 will be called pwm-xilinx. 821 821 822 + config RUST_PWM_ABSTRACTIONS 823 + bool 824 + depends on RUST 825 + help 826 + This option enables the safe Rust abstraction layer for the PWM 827 + subsystem. It provides idiomatic wrappers and traits necessary for 828 + writing PWM controller drivers in Rust. 829 + 830 + The abstractions handle resource management (like memory and reference 831 + counting) and provide safe interfaces to the underlying C core, 832 + allowing driver logic to be written in safe Rust. 833 + 822 834 endif
+1
rust/bindings/bindings_helper.h
··· 72 72 #include <linux/pm_opp.h> 73 73 #include <linux/poll.h> 74 74 #include <linux/property.h> 75 + #include <linux/pwm.h> 75 76 #include <linux/random.h> 76 77 #include <linux/refcount.h> 77 78 #include <linux/regulator/consumer.h>
+1
rust/helpers/helpers.c
··· 43 43 #include "poll.c" 44 44 #include "processor.c" 45 45 #include "property.c" 46 + #include "pwm.c" 46 47 #include "rbtree.c" 47 48 #include "rcu.c" 48 49 #include "refcount.c"
+20
rust/helpers/pwm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2025 Samsung Electronics Co., Ltd. 3 + // Author: Michal Wilczynski <m.wilczynski@samsung.com> 4 + 5 + #include <linux/pwm.h> 6 + 7 + struct device *rust_helper_pwmchip_parent(const struct pwm_chip *chip) 8 + { 9 + return pwmchip_parent(chip); 10 + } 11 + 12 + void *rust_helper_pwmchip_get_drvdata(struct pwm_chip *chip) 13 + { 14 + return pwmchip_get_drvdata(chip); 15 + } 16 + 17 + void rust_helper_pwmchip_set_drvdata(struct pwm_chip *chip, void *data) 18 + { 19 + pwmchip_set_drvdata(chip, data); 20 + }
+2
rust/kernel/lib.rs
··· 129 129 pub mod seq_file; 130 130 pub mod sizes; 131 131 mod static_assert; 132 + #[cfg(CONFIG_RUST_PWM_ABSTRACTIONS)] 133 + pub mod pwm; 132 134 #[doc(hidden)] 133 135 pub mod std_vendor; 134 136 pub mod str;
+102
rust/kernel/pwm.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2025 Samsung Electronics Co., Ltd. 3 + // Author: Michal Wilczynski <m.wilczynski@samsung.com> 4 + 5 + //! PWM subsystem abstractions. 6 + //! 7 + //! C header: [`include/linux/pwm.h`](srctree/include/linux/pwm.h). 8 + 9 + use crate::{ 10 + bindings, 11 + prelude::*, 12 + types::Opaque, 13 + }; 14 + use core::convert::TryFrom; 15 + 16 + /// PWM polarity. Mirrors [`enum pwm_polarity`](srctree/include/linux/pwm.h). 17 + #[derive(Copy, Clone, Debug, PartialEq, Eq)] 18 + pub enum Polarity { 19 + /// Normal polarity (duty cycle defines the high period of the signal). 20 + Normal, 21 + 22 + /// Inversed polarity (duty cycle defines the low period of the signal). 23 + Inversed, 24 + } 25 + 26 + impl TryFrom<bindings::pwm_polarity> for Polarity { 27 + type Error = Error; 28 + 29 + fn try_from(polarity: bindings::pwm_polarity) -> Result<Self, Error> { 30 + match polarity { 31 + bindings::pwm_polarity_PWM_POLARITY_NORMAL => Ok(Polarity::Normal), 32 + bindings::pwm_polarity_PWM_POLARITY_INVERSED => Ok(Polarity::Inversed), 33 + _ => Err(EINVAL), 34 + } 35 + } 36 + } 37 + 38 + impl From<Polarity> for bindings::pwm_polarity { 39 + fn from(polarity: Polarity) -> Self { 40 + match polarity { 41 + Polarity::Normal => bindings::pwm_polarity_PWM_POLARITY_NORMAL, 42 + Polarity::Inversed => bindings::pwm_polarity_PWM_POLARITY_INVERSED, 43 + } 44 + } 45 + } 46 + 47 + /// Represents a PWM waveform configuration. 48 + /// Mirrors struct [`struct pwm_waveform`](srctree/include/linux/pwm.h). 49 + #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] 50 + pub struct Waveform { 51 + /// Total duration of one complete PWM cycle, in nanoseconds. 52 + pub period_length_ns: u64, 53 + 54 + /// Duty-cycle active time, in nanoseconds. 55 + /// 56 + /// For a typical normal polarity configuration (active-high) this is the 57 + /// high time of the signal. 58 + pub duty_length_ns: u64, 59 + 60 + /// Duty-cycle start offset, in nanoseconds. 61 + /// 62 + /// Delay from the beginning of the period to the first active edge. 63 + /// In most simple PWM setups this is `0`, so the duty cycle starts 64 + /// immediately at each period’s start. 65 + pub duty_offset_ns: u64, 66 + } 67 + 68 + impl From<bindings::pwm_waveform> for Waveform { 69 + fn from(wf: bindings::pwm_waveform) -> Self { 70 + Waveform { 71 + period_length_ns: wf.period_length_ns, 72 + duty_length_ns: wf.duty_length_ns, 73 + duty_offset_ns: wf.duty_offset_ns, 74 + } 75 + } 76 + } 77 + 78 + impl From<Waveform> for bindings::pwm_waveform { 79 + fn from(wf: Waveform) -> Self { 80 + bindings::pwm_waveform { 81 + period_length_ns: wf.period_length_ns, 82 + duty_length_ns: wf.duty_length_ns, 83 + duty_offset_ns: wf.duty_offset_ns, 84 + } 85 + } 86 + } 87 + 88 + /// Wrapper for PWM state [`struct pwm_state`](srctree/include/linux/pwm.h). 89 + #[repr(transparent)] 90 + pub struct State(bindings::pwm_state); 91 + 92 + impl State { 93 + /// Creates a `State` wrapper by taking ownership of a C `pwm_state` value. 94 + pub(crate) fn from_c(c_state: bindings::pwm_state) -> Self { 95 + State(c_state) 96 + } 97 + 98 + /// Returns `true` if the PWM signal is enabled. 99 + pub fn enabled(&self) -> bool { 100 + self.0.enabled 101 + } 102 + }