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 } 103