diff options
| author | Michal Wilczynski <m.wilczynski@samsung.com> | 2025-10-16 15:38:02 +0200 |
|---|---|---|
| committer | Uwe Kleine-König <ukleinek@kernel.org> | 2025-11-07 10:03:54 +0100 |
| commit | 7b3dce814a15bc5d9fb6124cd945291012c4ebb9 (patch) | |
| tree | 8904e7586221a9cefd546bc06543bbef9fe88e26 /rust/kernel/pwm.rs | |
| parent | ce284f882022ebcb953984c7eccf4fc4eb531978 (diff) | |
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>
Diffstat (limited to 'rust/kernel/pwm.rs')
| -rw-r--r-- | rust/kernel/pwm.rs | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/rust/kernel/pwm.rs b/rust/kernel/pwm.rs new file mode 100644 index 000000000000..beabf0086a2f --- /dev/null +++ b/rust/kernel/pwm.rs @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2025 Samsung Electronics Co., Ltd. +// Author: Michal Wilczynski <m.wilczynski@samsung.com> + +//! PWM subsystem abstractions. +//! +//! C header: [`include/linux/pwm.h`](srctree/include/linux/pwm.h). + +use crate::{ + bindings, + prelude::*, + types::Opaque, +}; +use core::convert::TryFrom; + +/// PWM polarity. Mirrors [`enum pwm_polarity`](srctree/include/linux/pwm.h). +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Polarity { + /// Normal polarity (duty cycle defines the high period of the signal). + Normal, + + /// Inversed polarity (duty cycle defines the low period of the signal). + Inversed, +} + +impl TryFrom<bindings::pwm_polarity> for Polarity { + type Error = Error; + + fn try_from(polarity: bindings::pwm_polarity) -> Result<Self, Error> { + match polarity { + bindings::pwm_polarity_PWM_POLARITY_NORMAL => Ok(Polarity::Normal), + bindings::pwm_polarity_PWM_POLARITY_INVERSED => Ok(Polarity::Inversed), + _ => Err(EINVAL), + } + } +} + +impl From<Polarity> for bindings::pwm_polarity { + fn from(polarity: Polarity) -> Self { + match polarity { + Polarity::Normal => bindings::pwm_polarity_PWM_POLARITY_NORMAL, + Polarity::Inversed => bindings::pwm_polarity_PWM_POLARITY_INVERSED, + } + } +} + +/// Represents a PWM waveform configuration. +/// Mirrors struct [`struct pwm_waveform`](srctree/include/linux/pwm.h). +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct Waveform { + /// Total duration of one complete PWM cycle, in nanoseconds. + pub period_length_ns: u64, + + /// Duty-cycle active time, in nanoseconds. + /// + /// For a typical normal polarity configuration (active-high) this is the + /// high time of the signal. + pub duty_length_ns: u64, + + /// Duty-cycle start offset, in nanoseconds. + /// + /// Delay from the beginning of the period to the first active edge. + /// In most simple PWM setups this is `0`, so the duty cycle starts + /// immediately at each period’s start. + pub duty_offset_ns: u64, +} + +impl From<bindings::pwm_waveform> for Waveform { + fn from(wf: bindings::pwm_waveform) -> Self { + Waveform { + period_length_ns: wf.period_length_ns, + duty_length_ns: wf.duty_length_ns, + duty_offset_ns: wf.duty_offset_ns, + } + } +} + +impl From<Waveform> for bindings::pwm_waveform { + fn from(wf: Waveform) -> Self { + bindings::pwm_waveform { + period_length_ns: wf.period_length_ns, + duty_length_ns: wf.duty_length_ns, + duty_offset_ns: wf.duty_offset_ns, + } + } +} + +/// Wrapper for PWM state [`struct pwm_state`](srctree/include/linux/pwm.h). +#[repr(transparent)] +pub struct State(bindings::pwm_state); + +impl State { + /// Creates a `State` wrapper by taking ownership of a C `pwm_state` value. + pub(crate) fn from_c(c_state: bindings::pwm_state) -> Self { + State(c_state) + } + + /// Returns `true` if the PWM signal is enabled. + pub fn enabled(&self) -> bool { + self.0.enabled + } +} |
