xref: /linux/rust/kernel/pwm.rs (revision a69a54f8dffb105b2df2e606b4c9f61127d006ac)
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     container_of,
12     device::{self, Bound},
13     devres,
14     error::{self, to_result},
15     prelude::*,
16     types::{ARef, AlwaysRefCounted, Opaque},
17 };
18 use core::{marker::PhantomData, ptr::NonNull};
19 
20 /// Represents a PWM waveform configuration.
21 /// Mirrors struct [`struct pwm_waveform`](srctree/include/linux/pwm.h).
22 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
23 pub struct Waveform {
24     /// Total duration of one complete PWM cycle, in nanoseconds.
25     pub period_length_ns: u64,
26 
27     /// Duty-cycle active time, in nanoseconds.
28     ///
29     /// For a typical normal polarity configuration (active-high) this is the
30     /// high time of the signal.
31     pub duty_length_ns: u64,
32 
33     /// Duty-cycle start offset, in nanoseconds.
34     ///
35     /// Delay from the beginning of the period to the first active edge.
36     /// In most simple PWM setups this is `0`, so the duty cycle starts
37     /// immediately at each period’s start.
38     pub duty_offset_ns: u64,
39 }
40 
41 impl From<bindings::pwm_waveform> for Waveform {
42     fn from(wf: bindings::pwm_waveform) -> Self {
43         Waveform {
44             period_length_ns: wf.period_length_ns,
45             duty_length_ns: wf.duty_length_ns,
46             duty_offset_ns: wf.duty_offset_ns,
47         }
48     }
49 }
50 
51 impl From<Waveform> for bindings::pwm_waveform {
52     fn from(wf: Waveform) -> Self {
53         bindings::pwm_waveform {
54             period_length_ns: wf.period_length_ns,
55             duty_length_ns: wf.duty_length_ns,
56             duty_offset_ns: wf.duty_offset_ns,
57         }
58     }
59 }
60 
61 /// Describes the outcome of a `round_waveform` operation.
62 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
63 pub enum RoundingOutcome {
64     /// The requested waveform was achievable exactly or by rounding values down.
65     ExactOrRoundedDown,
66 
67     /// The requested waveform could only be achieved by rounding up.
68     RoundedUp,
69 }
70 
71 /// Wrapper for a PWM device [`struct pwm_device`](srctree/include/linux/pwm.h).
72 #[repr(transparent)]
73 pub struct Device(Opaque<bindings::pwm_device>);
74 
75 impl Device {
76     /// Creates a reference to a [`Device`] from a valid C pointer.
77     ///
78     /// # Safety
79     ///
80     /// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
81     /// returned [`Device`] reference.
82     pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::pwm_device) -> &'a Self {
83         // SAFETY: The safety requirements guarantee the validity of the dereference, while the
84         // `Device` type being transparent makes the cast ok.
85         unsafe { &*ptr.cast::<Self>() }
86     }
87 
88     /// Returns a raw pointer to the underlying `pwm_device`.
89     fn as_raw(&self) -> *mut bindings::pwm_device {
90         self.0.get()
91     }
92 
93     /// Gets the hardware PWM index for this device within its chip.
94     pub fn hwpwm(&self) -> u32 {
95         // SAFETY: `self.as_raw()` provides a valid pointer for `self`'s lifetime.
96         unsafe { (*self.as_raw()).hwpwm }
97     }
98 
99     /// Gets a reference to the parent `Chip` that this device belongs to.
100     pub fn chip<T: PwmOps>(&self) -> &Chip<T> {
101         // SAFETY: `self.as_raw()` provides a valid pointer. (*self.as_raw()).chip
102         // is assumed to be a valid pointer to `pwm_chip` managed by the kernel.
103         // Chip::from_raw's safety conditions must be met.
104         unsafe { Chip::<T>::from_raw((*self.as_raw()).chip) }
105     }
106 
107     /// Gets the label for this PWM device, if any.
108     pub fn label(&self) -> Option<&CStr> {
109         // SAFETY: self.as_raw() provides a valid pointer.
110         let label_ptr = unsafe { (*self.as_raw()).label };
111         if label_ptr.is_null() {
112             return None
113         }
114 
115         // SAFETY: label_ptr is non-null and points to a C string
116         // managed by the kernel, valid for the lifetime of the PWM device.
117         Some(unsafe { CStr::from_char_ptr(label_ptr) })
118     }
119 
120     /// Sets the PWM waveform configuration and enables the PWM signal.
121     pub fn set_waveform(&self, wf: &Waveform, exact: bool) -> Result {
122         let c_wf = bindings::pwm_waveform::from(*wf);
123 
124         // SAFETY: `self.as_raw()` provides a valid `*mut pwm_device` pointer.
125         // `&c_wf` is a valid pointer to a `pwm_waveform` struct. The C function
126         // handles all necessary internal locking.
127         let ret = unsafe { bindings::pwm_set_waveform_might_sleep(self.as_raw(), &c_wf, exact) };
128         to_result(ret)
129     }
130 
131     /// Queries the hardware for the configuration it would apply for a given
132     /// request.
133     pub fn round_waveform(&self, wf: &mut Waveform) -> Result<RoundingOutcome> {
134         let mut c_wf = bindings::pwm_waveform::from(*wf);
135 
136         // SAFETY: `self.as_raw()` provides a valid `*mut pwm_device` pointer.
137         // `&mut c_wf` is a valid pointer to a mutable `pwm_waveform` struct that
138         // the C function will update.
139         let ret = unsafe { bindings::pwm_round_waveform_might_sleep(self.as_raw(), &mut c_wf) };
140 
141         to_result(ret)?;
142 
143         *wf = Waveform::from(c_wf);
144 
145         if ret == 1 {
146             Ok(RoundingOutcome::RoundedUp)
147         } else {
148             Ok(RoundingOutcome::ExactOrRoundedDown)
149         }
150     }
151 
152     /// Reads the current waveform configuration directly from the hardware.
153     pub fn get_waveform(&self) -> Result<Waveform> {
154         let mut c_wf = bindings::pwm_waveform::default();
155 
156         // SAFETY: `self.as_raw()` is a valid pointer. We provide a valid pointer
157         // to a stack-allocated `pwm_waveform` struct for the kernel to fill.
158         let ret = unsafe { bindings::pwm_get_waveform_might_sleep(self.as_raw(), &mut c_wf) };
159 
160         to_result(ret)?;
161 
162         Ok(Waveform::from(c_wf))
163     }
164 }
165 
166 /// The result of a `round_waveform_tohw` operation.
167 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
168 pub struct RoundedWaveform<WfHw> {
169     /// A status code, 0 for success or 1 if values were rounded up.
170     pub status: c_int,
171     /// The driver-specific hardware representation of the waveform.
172     pub hardware_waveform: WfHw,
173 }
174 
175 /// Trait defining the operations for a PWM driver.
176 pub trait PwmOps: 'static + Sized {
177     /// The driver-specific hardware representation of a waveform.
178     ///
179     /// This type must be [`Copy`], [`Default`], and fit within `PWM_WFHWSIZE`.
180     type WfHw: Copy + Default;
181 
182     /// Optional hook for when a PWM device is requested.
183     fn request(
184         _chip: &Chip<Self>,
185         _pwm: &Device,
186         _parent_dev: &device::Device<Bound>,
187     ) -> Result {
188         Ok(())
189     }
190 
191     /// Optional hook for capturing a PWM signal.
192     fn capture(
193         _chip: &Chip<Self>,
194         _pwm: &Device,
195         _result: &mut bindings::pwm_capture,
196         _timeout: usize,
197         _parent_dev: &device::Device<Bound>,
198     ) -> Result {
199         Err(ENOTSUPP)
200     }
201 
202     /// Convert a generic waveform to the hardware-specific representation.
203     /// This is typically a pure calculation and does not perform I/O.
204     fn round_waveform_tohw(
205         _chip: &Chip<Self>,
206         _pwm: &Device,
207         _wf: &Waveform,
208     ) -> Result<RoundedWaveform<Self::WfHw>> {
209         Err(ENOTSUPP)
210     }
211 
212     /// Convert a hardware-specific representation back to a generic waveform.
213     /// This is typically a pure calculation and does not perform I/O.
214     fn round_waveform_fromhw(
215         _chip: &Chip<Self>,
216         _pwm: &Device,
217         _wfhw: &Self::WfHw,
218         _wf: &mut Waveform,
219     ) -> Result {
220         Err(ENOTSUPP)
221     }
222 
223     /// Read the current hardware configuration into the hardware-specific representation.
224     fn read_waveform(
225         _chip: &Chip<Self>,
226         _pwm: &Device,
227         _parent_dev: &device::Device<Bound>,
228     ) -> Result<Self::WfHw> {
229         Err(ENOTSUPP)
230     }
231 
232     /// Write a hardware-specific waveform configuration to the hardware.
233     fn write_waveform(
234         _chip: &Chip<Self>,
235         _pwm: &Device,
236         _wfhw: &Self::WfHw,
237         _parent_dev: &device::Device<Bound>,
238     ) -> Result {
239         Err(ENOTSUPP)
240     }
241 }
242 
243 /// Bridges Rust `PwmOps` to the C `pwm_ops` vtable.
244 struct Adapter<T: PwmOps> {
245     _p: PhantomData<T>,
246 }
247 
248 impl<T: PwmOps> Adapter<T> {
249     const VTABLE: PwmOpsVTable = create_pwm_ops::<T>();
250 
251     /// # Safety
252     ///
253     /// `wfhw_ptr` must be valid for writes of `size_of::<T::WfHw>()` bytes.
254     unsafe fn serialize_wfhw(wfhw: &T::WfHw, wfhw_ptr: *mut c_void) -> Result {
255         let size = core::mem::size_of::<T::WfHw>();
256 
257         build_assert!(size <= bindings::PWM_WFHWSIZE as usize);
258 
259         // SAFETY: The caller ensures `wfhw_ptr` is valid for `size` bytes.
260         unsafe {
261             core::ptr::copy_nonoverlapping(
262                 core::ptr::from_ref::<T::WfHw>(wfhw).cast::<u8>(),
263                 wfhw_ptr.cast::<u8>(),
264                 size,
265             );
266         }
267 
268         Ok(())
269     }
270 
271     /// # Safety
272     ///
273     /// `wfhw_ptr` must be valid for reads of `size_of::<T::WfHw>()` bytes.
274     unsafe fn deserialize_wfhw(wfhw_ptr: *const c_void) -> Result<T::WfHw> {
275         let size = core::mem::size_of::<T::WfHw>();
276 
277         build_assert!(size <= bindings::PWM_WFHWSIZE as usize);
278 
279         let mut wfhw = T::WfHw::default();
280         // SAFETY: The caller ensures `wfhw_ptr` is valid for `size` bytes.
281         unsafe {
282             core::ptr::copy_nonoverlapping(
283                 wfhw_ptr.cast::<u8>(),
284                 core::ptr::from_mut::<T::WfHw>(&mut wfhw).cast::<u8>(),
285                 size,
286             );
287         }
288 
289         Ok(wfhw)
290     }
291 
292     /// # Safety
293     ///
294     /// `dev` must be a valid pointer to a `bindings::device` embedded within a
295     /// `bindings::pwm_chip`. This function is called by the device core when the
296     /// last reference to the device is dropped.
297     unsafe extern "C" fn release_callback(dev: *mut bindings::device) {
298         // SAFETY: The function's contract guarantees that `dev` points to a `device`
299         // field embedded within a valid `pwm_chip`. `container_of!` can therefore
300         // safely calculate the address of the containing struct.
301         let c_chip_ptr = unsafe { container_of!(dev, bindings::pwm_chip, dev) };
302 
303         // SAFETY: `c_chip_ptr` is a valid pointer to a `pwm_chip` as established
304         // above. Calling this FFI function is safe.
305         let drvdata_ptr = unsafe { bindings::pwmchip_get_drvdata(c_chip_ptr) };
306 
307         // SAFETY: The driver data was initialized in `new`. We run its destructor here.
308         unsafe { core::ptr::drop_in_place(drvdata_ptr.cast::<T>()) };
309 
310         // Now, call the original release function to free the `pwm_chip` itself.
311         // SAFETY: `dev` is the valid pointer passed into this callback, which is
312         // the expected argument for `pwmchip_release`.
313         unsafe { bindings::pwmchip_release(dev); }
314     }
315 
316     /// # Safety
317     ///
318     /// Pointers from C must be valid.
319     unsafe extern "C" fn request_callback(
320         chip_ptr: *mut bindings::pwm_chip,
321         pwm_ptr: *mut bindings::pwm_device,
322     ) -> c_int {
323         // SAFETY: PWM core guarentees `chip_ptr` and `pwm_ptr` are valid pointers.
324         let (chip, pwm) = unsafe { (Chip::<T>::from_raw(chip_ptr), Device::from_raw(pwm_ptr)) };
325 
326         // SAFETY: The PWM core guarantees the parent device exists and is bound during callbacks.
327         let bound_parent = unsafe { chip.bound_parent_device() };
328         match T::request(chip, pwm, bound_parent) {
329             Ok(()) => 0,
330             Err(e) => e.to_errno(),
331         }
332     }
333 
334     /// # Safety
335     ///
336     /// Pointers from C must be valid.
337     unsafe extern "C" fn capture_callback(
338         chip_ptr: *mut bindings::pwm_chip,
339         pwm_ptr: *mut bindings::pwm_device,
340         res: *mut bindings::pwm_capture,
341         timeout: usize,
342     ) -> c_int {
343         // SAFETY: Relies on the function's contract that `chip_ptr` and `pwm_ptr` are valid
344         // pointers.
345         let (chip, pwm, result) = unsafe {
346             (
347                 Chip::<T>::from_raw(chip_ptr),
348                 Device::from_raw(pwm_ptr),
349                 &mut *res,
350             )
351         };
352 
353         // SAFETY: The PWM core guarantees the parent device exists and is bound during callbacks.
354         let bound_parent = unsafe { chip.bound_parent_device() };
355         match T::capture(chip, pwm, result, timeout, bound_parent) {
356             Ok(()) => 0,
357             Err(e) => e.to_errno(),
358         }
359     }
360 
361     /// # Safety
362     ///
363     /// Pointers from C must be valid.
364     unsafe extern "C" fn round_waveform_tohw_callback(
365         chip_ptr: *mut bindings::pwm_chip,
366         pwm_ptr: *mut bindings::pwm_device,
367         wf_ptr: *const bindings::pwm_waveform,
368         wfhw_ptr: *mut c_void,
369     ) -> c_int {
370         // SAFETY: Relies on the function's contract that `chip_ptr` and `pwm_ptr` are valid
371         // pointers.
372         let (chip, pwm, wf) = unsafe {
373             (
374                 Chip::<T>::from_raw(chip_ptr),
375                 Device::from_raw(pwm_ptr),
376                 Waveform::from(*wf_ptr),
377             )
378         };
379         match T::round_waveform_tohw(chip, pwm, &wf) {
380             Ok(rounded) => {
381                 // SAFETY: `wfhw_ptr` is valid per this function's safety contract.
382                 if unsafe { Self::serialize_wfhw(&rounded.hardware_waveform, wfhw_ptr) }.is_err() {
383                     return EINVAL.to_errno();
384                 }
385                 rounded.status
386             }
387             Err(e) => e.to_errno(),
388         }
389     }
390 
391     /// # Safety
392     ///
393     /// Pointers from C must be valid.
394     unsafe extern "C" fn round_waveform_fromhw_callback(
395         chip_ptr: *mut bindings::pwm_chip,
396         pwm_ptr: *mut bindings::pwm_device,
397         wfhw_ptr: *const c_void,
398         wf_ptr: *mut bindings::pwm_waveform,
399     ) -> c_int {
400         // SAFETY: Relies on the function's contract that `chip_ptr` and `pwm_ptr` are valid
401         // pointers.
402         let (chip, pwm) = unsafe { (Chip::<T>::from_raw(chip_ptr), Device::from_raw(pwm_ptr)) };
403         // SAFETY: `deserialize_wfhw`'s safety contract is met by this function's contract.
404         let wfhw = match unsafe { Self::deserialize_wfhw(wfhw_ptr) } {
405             Ok(v) => v,
406             Err(e) => return e.to_errno(),
407         };
408 
409         let mut rust_wf = Waveform::default();
410         match T::round_waveform_fromhw(chip, pwm, &wfhw, &mut rust_wf) {
411             Ok(()) => {
412                 // SAFETY: `wf_ptr` is guaranteed valid by the C caller.
413                 unsafe {
414                     *wf_ptr = rust_wf.into();
415                 };
416                 0
417             }
418             Err(e) => e.to_errno(),
419         }
420     }
421 
422     /// # Safety
423     ///
424     /// Pointers from C must be valid.
425     unsafe extern "C" fn read_waveform_callback(
426         chip_ptr: *mut bindings::pwm_chip,
427         pwm_ptr: *mut bindings::pwm_device,
428         wfhw_ptr: *mut c_void,
429     ) -> c_int {
430         // SAFETY: Relies on the function's contract that `chip_ptr` and `pwm_ptr` are valid
431         // pointers.
432         let (chip, pwm) = unsafe { (Chip::<T>::from_raw(chip_ptr), Device::from_raw(pwm_ptr)) };
433 
434         // SAFETY: The PWM core guarantees the parent device exists and is bound during callbacks.
435         let bound_parent = unsafe { chip.bound_parent_device() };
436         match T::read_waveform(chip, pwm, bound_parent) {
437             // SAFETY: `wfhw_ptr` is valid per this function's safety contract.
438             Ok(wfhw) => match unsafe { Self::serialize_wfhw(&wfhw, wfhw_ptr) } {
439                 Ok(()) => 0,
440                 Err(e) => e.to_errno(),
441             },
442             Err(e) => e.to_errno(),
443         }
444     }
445 
446     /// # Safety
447     ///
448     /// Pointers from C must be valid.
449     unsafe extern "C" fn write_waveform_callback(
450         chip_ptr: *mut bindings::pwm_chip,
451         pwm_ptr: *mut bindings::pwm_device,
452         wfhw_ptr: *const c_void,
453     ) -> c_int {
454         // SAFETY: Relies on the function's contract that `chip_ptr` and `pwm_ptr` are valid
455         // pointers.
456         let (chip, pwm) = unsafe { (Chip::<T>::from_raw(chip_ptr), Device::from_raw(pwm_ptr)) };
457 
458         // SAFETY: The PWM core guarantees the parent device exists and is bound during callbacks.
459         let bound_parent = unsafe { chip.bound_parent_device() };
460 
461         // SAFETY: `wfhw_ptr` is valid per this function's safety contract.
462         let wfhw = match unsafe { Self::deserialize_wfhw(wfhw_ptr) } {
463             Ok(v) => v,
464             Err(e) => return e.to_errno(),
465         };
466         match T::write_waveform(chip, pwm, &wfhw, bound_parent) {
467             Ok(()) => 0,
468             Err(e) => e.to_errno(),
469         }
470     }
471 }
472 
473 /// VTable structure wrapper for PWM operations.
474 /// Mirrors [`struct pwm_ops`](srctree/include/linux/pwm.h).
475 #[repr(transparent)]
476 pub struct PwmOpsVTable(bindings::pwm_ops);
477 
478 // SAFETY: PwmOpsVTable is Send. The vtable contains only function pointers
479 // and a size, which are simple data types that can be safely moved across
480 // threads. The thread-safety of calling these functions is handled by the
481 // kernel's locking mechanisms.
482 unsafe impl Send for PwmOpsVTable {}
483 
484 // SAFETY: PwmOpsVTable is Sync. The vtable is immutable after it is created,
485 // so it can be safely referenced and accessed concurrently by multiple threads
486 // e.g. to read the function pointers.
487 unsafe impl Sync for PwmOpsVTable {}
488 
489 impl PwmOpsVTable {
490     /// Returns a raw pointer to the underlying `pwm_ops` struct.
491     pub(crate) fn as_raw(&self) -> *const bindings::pwm_ops {
492         &self.0
493     }
494 }
495 
496 /// Creates a PWM operations vtable for a type `T` that implements `PwmOps`.
497 ///
498 /// This is used to bridge Rust trait implementations to the C `struct pwm_ops`
499 /// expected by the kernel.
500 pub const fn create_pwm_ops<T: PwmOps>() -> PwmOpsVTable {
501     // SAFETY: `core::mem::zeroed()` is unsafe. For `pwm_ops`, all fields are
502     // `Option<extern "C" fn(...)>` or data, so a zeroed pattern (None/0) is valid initially.
503     let mut ops: bindings::pwm_ops = unsafe { core::mem::zeroed() };
504 
505     ops.request = Some(Adapter::<T>::request_callback);
506     ops.capture = Some(Adapter::<T>::capture_callback);
507 
508     ops.round_waveform_tohw = Some(Adapter::<T>::round_waveform_tohw_callback);
509     ops.round_waveform_fromhw = Some(Adapter::<T>::round_waveform_fromhw_callback);
510     ops.read_waveform = Some(Adapter::<T>::read_waveform_callback);
511     ops.write_waveform = Some(Adapter::<T>::write_waveform_callback);
512     ops.sizeof_wfhw = core::mem::size_of::<T::WfHw>();
513 
514     PwmOpsVTable(ops)
515 }
516 
517 /// Wrapper for a PWM chip/controller ([`struct pwm_chip`](srctree/include/linux/pwm.h)).
518 #[repr(transparent)]
519 pub struct Chip<T: PwmOps>(Opaque<bindings::pwm_chip>, PhantomData<T>);
520 
521 impl<T: PwmOps> Chip<T> {
522     /// Creates a reference to a [`Chip`] from a valid pointer.
523     ///
524     /// # Safety
525     ///
526     /// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
527     /// returned [`Chip`] reference.
528     pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::pwm_chip) -> &'a Self {
529         // SAFETY: The safety requirements guarantee the validity of the dereference, while the
530         // `Chip` type being transparent makes the cast ok.
531         unsafe { &*ptr.cast::<Self>() }
532     }
533 
534     /// Returns a raw pointer to the underlying `pwm_chip`.
535     pub(crate) fn as_raw(&self) -> *mut bindings::pwm_chip {
536         self.0.get()
537     }
538 
539     /// Gets the number of PWM channels (hardware PWMs) on this chip.
540     pub fn num_channels(&self) -> u32 {
541         // SAFETY: `self.as_raw()` provides a valid pointer for `self`'s lifetime.
542         unsafe { (*self.as_raw()).npwm }
543     }
544 
545     /// Returns `true` if the chip supports atomic operations for configuration.
546     pub fn is_atomic(&self) -> bool {
547         // SAFETY: `self.as_raw()` provides a valid pointer for `self`'s lifetime.
548         unsafe { (*self.as_raw()).atomic }
549     }
550 
551     /// Returns a reference to the embedded `struct device` abstraction.
552     pub fn device(&self) -> &device::Device {
553         // SAFETY:
554         // - `self.as_raw()` provides a valid pointer to `bindings::pwm_chip`.
555         // - The `dev` field is an instance of `bindings::device` embedded
556         //   within `pwm_chip`.
557         // - Taking a pointer to this embedded field is valid.
558         // - `device::Device` is `#[repr(transparent)]`.
559         // - The lifetime of the returned reference is tied to `self`.
560         unsafe { device::Device::from_raw(&raw mut (*self.as_raw()).dev) }
561     }
562 
563     /// Gets the typed driver specific data associated with this chip's embedded device.
564     pub fn drvdata(&self) -> &T {
565         // SAFETY: `pwmchip_get_drvdata` returns the pointer to the private data area,
566         // which we know holds our `T`. The pointer is valid for the lifetime of `self`.
567         unsafe { &*bindings::pwmchip_get_drvdata(self.as_raw()).cast::<T>() }
568     }
569 
570     /// Returns a reference to the parent device of this PWM chip's device.
571     ///
572     /// # Safety
573     ///
574     /// The caller must guarantee that the parent device exists and is bound.
575     /// This is guaranteed by the PWM core during `PwmOps` callbacks.
576     unsafe fn bound_parent_device(&self) -> &device::Device<Bound> {
577         // SAFETY: Per the function's safety contract, the parent device exists.
578         let parent = unsafe { self.device().parent().unwrap_unchecked() };
579 
580         // SAFETY: Per the function's safety contract, the parent device is bound.
581         // This is guaranteed by the PWM core during `PwmOps` callbacks.
582         unsafe { parent.as_bound() }
583     }
584 
585     /// Allocates and wraps a PWM chip using `bindings::pwmchip_alloc`.
586     ///
587     /// Returns an [`ARef<Chip>`] managing the chip's lifetime via refcounting
588     /// on its embedded `struct device`.
589     pub fn new(
590         parent_dev: &device::Device,
591         num_channels: u32,
592         data: impl pin_init::PinInit<T, Error>,
593     ) -> Result<ARef<Self>> {
594         let sizeof_priv = core::mem::size_of::<T>();
595         // SAFETY: `pwmchip_alloc` allocates memory for the C struct and our private data.
596         let c_chip_ptr_raw = unsafe {
597             bindings::pwmchip_alloc(parent_dev.as_raw(), num_channels, sizeof_priv)
598         };
599 
600         let c_chip_ptr: *mut bindings::pwm_chip = error::from_err_ptr(c_chip_ptr_raw)?;
601 
602         // SAFETY: The `drvdata` pointer is the start of the private area, which is where
603         // we will construct our `T` object.
604         let drvdata_ptr = unsafe { bindings::pwmchip_get_drvdata(c_chip_ptr) };
605 
606         // SAFETY: We construct the `T` object in-place in the allocated private memory.
607         unsafe { data.__pinned_init(drvdata_ptr.cast())? };
608 
609         // SAFETY: `c_chip_ptr` points to a valid chip.
610         unsafe { (*c_chip_ptr).dev.release = Some(Adapter::<T>::release_callback); }
611 
612         // SAFETY: `c_chip_ptr` points to a valid chip.
613         // The `Adapter`'s `VTABLE` has a 'static lifetime, so the pointer
614         // returned by `as_raw()` is always valid.
615         unsafe { (*c_chip_ptr).ops = Adapter::<T>::VTABLE.as_raw(); }
616 
617         // Cast the `*mut bindings::pwm_chip` to `*mut Chip`. This is valid because
618         // `Chip` is `repr(transparent)` over `Opaque<bindings::pwm_chip>`, and
619         // `Opaque<T>` is `repr(transparent)` over `T`.
620         let chip_ptr_as_self = c_chip_ptr.cast::<Self>();
621 
622         // SAFETY: `chip_ptr_as_self` points to a valid `Chip` (layout-compatible with
623         // `bindings::pwm_chip`) whose embedded device has refcount 1.
624         // `ARef::from_raw` takes this pointer and manages it via `AlwaysRefCounted`.
625         Ok(unsafe { ARef::from_raw(NonNull::new_unchecked(chip_ptr_as_self)) })
626     }
627 }
628 
629 // SAFETY: Implements refcounting for `Chip` using the embedded `struct device`.
630 unsafe impl<T: PwmOps> AlwaysRefCounted for Chip<T> {
631     #[inline]
632     fn inc_ref(&self) {
633         // SAFETY: `self.0.get()` points to a valid `pwm_chip` because `self` exists.
634         // The embedded `dev` is valid. `get_device` increments its refcount.
635         unsafe { bindings::get_device(&raw mut (*self.0.get()).dev); }
636     }
637 
638     #[inline]
639     unsafe fn dec_ref(obj: NonNull<Chip<T>>) {
640         let c_chip_ptr = obj.cast::<bindings::pwm_chip>().as_ptr();
641 
642         // SAFETY: `obj` is a valid pointer to a `Chip` (and thus `bindings::pwm_chip`)
643         // with a non-zero refcount. `put_device` handles decrement and final release.
644         unsafe { bindings::put_device(&raw mut (*c_chip_ptr).dev); }
645     }
646 }
647 
648 // SAFETY: `Chip` is a wrapper around `*mut bindings::pwm_chip`. The underlying C
649 // structure's state is managed and synchronized by the kernel's device model
650 // and PWM core locking mechanisms. Therefore, it is safe to move the `Chip`
651 // wrapper (and the pointer it contains) across threads.
652 unsafe impl<T: PwmOps + Send> Send for Chip<T> {}
653 
654 // SAFETY: It is safe for multiple threads to have shared access (`&Chip`) because
655 // the `Chip` data is immutable from the Rust side without holding the appropriate
656 // kernel locks, which the C core is responsible for. Any interior mutability is
657 // handled and synchronized by the C kernel code.
658 unsafe impl<T: PwmOps + Sync> Sync for Chip<T> {}
659 
660 /// A resource guard that ensures `pwmchip_remove` is called on drop.
661 ///
662 /// This struct is intended to be managed by the `devres` framework by transferring its ownership
663 /// via [`Devres::register`]. This ties the lifetime of the PWM chip registration
664 /// to the lifetime of the underlying device.
665 pub struct Registration<T: PwmOps> {
666     chip: ARef<Chip<T>>,
667 }
668 
669 impl<T: 'static + PwmOps + Send + Sync> Registration<T> {
670     /// Registers a PWM chip with the PWM subsystem.
671     ///
672     /// Transfers its ownership to the `devres` framework, which ties its lifetime
673     /// to the parent device.
674     /// On unbind of the parent device, the `devres` entry will be dropped, automatically
675     /// calling `pwmchip_remove`. This function should be called from the driver's `probe`.
676     pub fn register(
677         dev: &device::Device<Bound>,
678         chip: ARef<Chip<T>>,
679     ) -> Result {
680 	let chip_parent = chip.device().parent().ok_or(EINVAL)?;
681         if dev.as_raw() != chip_parent.as_raw() {
682             return Err(EINVAL);
683         }
684 
685         let c_chip_ptr = chip.as_raw();
686 
687         // SAFETY: `c_chip_ptr` points to a valid chip with its ops initialized.
688         // `__pwmchip_add` is the C function to register the chip with the PWM core.
689         unsafe {
690             to_result(bindings::__pwmchip_add(c_chip_ptr, core::ptr::null_mut()))?;
691         }
692 
693         let registration = Registration { chip };
694 
695         devres::register(dev, registration, GFP_KERNEL)
696     }
697 }
698 
699 impl<T: PwmOps> Drop for Registration<T> {
700     fn drop(&mut self) {
701         let chip_raw = self.chip.as_raw();
702 
703         // SAFETY: `chip_raw` points to a chip that was successfully registered.
704         // `bindings::pwmchip_remove` is the correct C function to unregister it.
705         // This `drop` implementation is called automatically by `devres` on driver unbind.
706         unsafe { bindings::pwmchip_remove(chip_raw); }
707     }
708 }
709 
710 /// Declares a kernel module that exposes a single PWM driver.
711 ///
712 /// # Examples
713 ///
714 ///```ignore
715 /// kernel::module_pwm_platform_driver! {
716 ///     type: MyDriver,
717 ///     name: "Module name",
718 ///     authors: ["Author name"],
719 ///     description: "Description",
720 ///     license: "GPL v2",
721 /// }
722 ///```
723 #[macro_export]
724 macro_rules! module_pwm_platform_driver {
725     ($($user_args:tt)*) => {
726         $crate::module_platform_driver! {
727             $($user_args)*
728             imports_ns: ["PWM"],
729         }
730     };
731 }
732