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