From nobody Fri Dec 19 16:03:34 2025 Received: from mailout2.w1.samsung.com (mailout2.w1.samsung.com [210.118.77.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 570C327C173 for ; Sat, 24 May 2025 21:15:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.118.77.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121331; cv=none; b=VvdYyVJun2DiWjubx+JmB+f5lsYL93dZtK1sac2RLsf+NDVdQzEFE/w9ZuUA+ccvW15mTSL9BAoN2exrl79XsVW3sHqKwQSdAzHOBKangqQmfAAZgojF5bZGUcmhQtTSNrM57SSEwkbXvaOMT7AJgg32gctuiW5Y6bXLLMWQKJA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121331; c=relaxed/simple; bh=IJ+s5N9hqAIymbUhq8tlqql6sfROOUyoW5+/fjBacEE=; h=From:Date:Subject:MIME-Version:Message-Id:In-Reply-To:To:Cc: Content-Type:References; b=jW2JXTsMll8Zf9tH6teTYjupDsbCoqYb+PEebZIUMui+XAFqf1PUARcKEvoXfABBO9FG8VgmMpWrixgx+C4YH+NEOTx2habk+EcYvXz4q4LjwbNYxUc3BXYK6zFQ+v3fwnBDCw7uwxnJ+Pzw3CZgE3x/+7pPS6wX/tVcSusL6zg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com; spf=pass smtp.mailfrom=samsung.com; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b=rWgmd3bg; arc=none smtp.client-ip=210.118.77.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=samsung.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="rWgmd3bg" Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id 20250524211522euoutp02c88beba88eb4dcdc4e1a15de40e472d4~CkxSjMRgC3042930429euoutp02B for ; Sat, 24 May 2025 21:15:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com 20250524211522euoutp02c88beba88eb4dcdc4e1a15de40e472d4~CkxSjMRgC3042930429euoutp02B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1748121322; bh=Ae98N3tSGBe/h/f96a5r9JmrlJMUez7PRPitsnGiQz8=; h=From:Date:Subject:In-Reply-To:To:Cc:References:From; b=rWgmd3bgWpNYobN0S4SvDtY6THgMGNr7Y/oW4jUFn/ms9eGm81puzqyLl6BBxZk8l LuSVcGSQkpwnmI/GAlymBzUWtAEBy8fqknAMdbRLWRxwA6ZYr2uAABlUvgqzcka+oh OG4WHRsINXe143dqT3SzLx5CekyFapVbKCxaKpoc= Received: from eusmtip2.samsung.com (unknown [203.254.199.222]) by eucas1p1.samsung.com (KnoxPortal) with ESMTPA id 20250524211520eucas1p1378fbab27f4b1ae8808706c074fa217c~CkxRGXwhV0341603416eucas1p16; Sat, 24 May 2025 21:15:20 +0000 (GMT) Received: from AMDC4942.eu.corp.samsungelectronics.net (unknown [106.210.136.40]) by eusmtip2.samsung.com (KnoxPortal) with ESMTPA id 20250524211519eusmtip2c1bebceb9d217c8f6b37932636320e1a~CkxQEOTFj0676606766eusmtip2m; Sat, 24 May 2025 21:15:19 +0000 (GMT) From: Michal Wilczynski Date: Sat, 24 May 2025 23:14:55 +0200 Subject: [PATCH RFC 1/6] rust: Add basic PWM abstractions Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-Id: <20250524-rust-next-pwm-working-fan-for-sending-v1-1-bdd2d5094ff7@samsung.com> In-Reply-To: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Michal Wilczynski , Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Marek Szyprowski Cc: linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org X-Mailer: b4 0.15-dev X-CMS-MailID: 20250524211520eucas1p1378fbab27f4b1ae8808706c074fa217c X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-RootMTR: 20250524211520eucas1p1378fbab27f4b1ae8808706c074fa217c X-EPHeader: CA X-CMS-RootMailID: 20250524211520eucas1p1378fbab27f4b1ae8808706c074fa217c References: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> Introduce initial Rust abstractions for the Linux PWM subsystem. These abstractions provide safe wrappers around the core C data structures and functions, enabling the development of PWM chip drivers in Rust. The main components added are: - A Kconfig option RUST_PWM_ABSTRACTIONS - C helper functions in rust/helpers/pwm.c to provide stable callable interfaces for Rust, for pwmchip_parent, pwmchip_get_drvdata, and pwmchip_set_drvdata - A new Rust module rust/kernel/pwm.rs containing: - Safe wrappers for struct pwm_chip, struct pwm_device, struct pwm_state, and struct pwm_args - An enum Polarity for type safe polarity handling - Functions devm_chip_alloc and devm_chip_add which wrap the kernel's device-managed APIs for PWM chip allocation and registration. - A PwmOps trait and create_pwm_ops function to allow Rust drivers to define their PWM operations, initially supporting the .apply callback. This foundational layer will be used by subsequent patches to implement a specific PWM chip driver in Rust. It focuses on the pwm_chip provider APIs necessary for such a driver. Signed-off-by: Michal Wilczynski --- MAINTAINERS | 6 + drivers/pwm/Kconfig | 8 + rust/bindings/bindings_helper.h | 1 + rust/helpers/helpers.c | 1 + rust/helpers/pwm.c | 20 +++ rust/kernel/lib.rs | 2 + rust/kernel/pwm.rs | 376 ++++++++++++++++++++++++++++++++++++= ++++ 7 files changed, 414 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index b6126bccf17c899cbbf5b729e1f426ff38d04a8e..2b080e8f3d873b1e401b3a2fe12= 07c224c4591fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19678,6 +19678,12 @@ F: include/linux/pwm.h F: include/linux/pwm_backlight.h K: pwm_(config|apply_might_sleep|apply_atomic|ops) =20 +PWM SUBSYSTEM BINDINGS [RUST] +M: Michal Wilczynski +S: Maintained +F: rust/helpers/pwm.c +F: rust/kernel/pwm.rs + PXA GPIO DRIVER M: Robert Jarzmik L: linux-gpio@vger.kernel.org diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 4731d5b90d7edcc61138e4a5bf7e98906953ece4..b5bd5c13b3a5e5a575a0fbfb2e2= 85f5665b7a671 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -755,4 +755,12 @@ config PWM_XILINX To compile this driver as a module, choose M here: the module will be called pwm-xilinx. =20 + config RUST_PWM_ABSTRACTIONS + bool "Rust PWM abstractions support" + depends on RUST + depends on PWM=3Dy + help + Adds support needed for PWM drivers written in Rust. It provides a + wrapper around the C pwm core. + endif diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 43aabecc1d6161398acf3bb402d1f67b48bfcd6f..24a2498f17a2fc56f5dc012a20d= 621007be28b5e 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 34f040e5f260b892fc421a6e55de32cbf90c8c22..7dda45d1794c957d83227362d94= 83eb90543f053 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -26,6 +26,7 @@ #include "platform.c" #include "pci.c" #include "pid_namespace.c" +#include "pwm.c" #include "rbtree.c" #include "rcu.c" #include "refcount.c" diff --git a/rust/helpers/pwm.c b/rust/helpers/pwm.c new file mode 100644 index 0000000000000000000000000000000000000000..d75c588863685d3990b525bb1b8= 4aa4bc35ac397 --- /dev/null +++ b/rust/helpers/pwm.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2025 Samsung Electronics Co., Ltd. +// Author: Michal Wilczynski + +#include + +struct device *rust_helper_pwmchip_parent(const struct pwm_chip *chip) +{ + return pwmchip_parent(chip); +} + +void *rust_helper_pwmchip_get_drvdata(struct pwm_chip *chip) +{ + return pwmchip_get_drvdata(chip); +} + +void rust_helper_pwmchip_set_drvdata(struct pwm_chip *chip, void *data) +{ + pwmchip_set_drvdata(chip, data); +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 1b0b6790a7f33c30af16a056d6afcca3d15a2a0d..72b60afe5f51d8a62b3c95b1b32= 0a48386d14e61 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -92,6 +92,8 @@ pub mod seq_file; pub mod sizes; mod static_assert; +#[cfg(CONFIG_RUST_PWM_ABSTRACTIONS)] +pub mod pwm; #[doc(hidden)] pub mod std_vendor; pub mod str; diff --git a/rust/kernel/pwm.rs b/rust/kernel/pwm.rs new file mode 100644 index 0000000000000000000000000000000000000000..357fda46faa99c4462149658951= ec53bf9cc2d1e --- /dev/null +++ b/rust/kernel/pwm.rs @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2025 Samsung Electronics Co., Ltd. +// Author: Michal Wilczynski + +//! PWM (Pulse Width Modulator) abstractions. +//! +//! This module provides safe Rust abstractions for working with the Linux +//! kernel's PWM subsystem, leveraging types generated by `bindgen` +//! from `` and `drivers/pwm/core.c`. + +use crate::{ + bindings, + device::Device as CoreDevice, + error::*, + prelude::*, + str::CStr, + types::{ForeignOwnable, Opaque}, +}; +use core::marker::PhantomData; + +/// PWM polarity. Mirrors `enum pwm_polarity`. +#[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 From for Polarity { + fn from(polarity: bindings::pwm_polarity) -> Self { + match polarity { + bindings::pwm_polarity_PWM_POLARITY_NORMAL =3D> Polarity::Norm= al, + bindings::pwm_polarity_PWM_POLARITY_INVERSED =3D> Polarity::In= versed, + _ =3D> { + pr_warn!( + "Unknown pwm_polarity value {}, defaulting to Normal\n= ", + polarity + ); + Polarity::Normal + } + } + } +} + +impl From for bindings::pwm_polarity { + fn from(polarity: Polarity) -> Self { + match polarity { + Polarity::Normal =3D> bindings::pwm_polarity_PWM_POLARITY_NORM= AL, + Polarity::Inversed =3D> bindings::pwm_polarity_PWM_POLARITY_IN= VERSED, + } + } +} + +/// Wrapper for board-dependent PWM arguments (`struct pwm_args`). +#[repr(transparent)] +pub struct Args(Opaque); + +impl Args { + /// Creates an `Args` wrapper from the C struct reference. + fn from_c_ref(c_args: &bindings::pwm_args) -> Self { + // SAFETY: Pointer is valid, construct Opaque wrapper. We copy the= data. + Args(Opaque::new(*c_args)) + } + + /// Returns the period of the PWM signal in nanoseconds. + pub fn period(&self) -> u64 { + // SAFETY: Reading from the valid pointer obtained by `get()`. + unsafe { (*self.0.get()).period } + } + + /// Returns the polarity of the PWM signal. + pub fn polarity(&self) -> Polarity { + // SAFETY: Reading from the valid pointer obtained by `get()`. + Polarity::from(unsafe { (*self.0.get()).polarity }) + } +} + +/// Wrapper for PWM state (`struct pwm_state`). +#[repr(transparent)] +pub struct State(Opaque); + +impl State { + /// Creates a new zeroed `State`. + pub fn new() -> Self { + State(Opaque::new(bindings::pwm_state::default())) + } + + /// Creates a `State` wrapper around a copy of a C `pwm_state`. + pub(crate) fn from_c(c_state: bindings::pwm_state) -> Self { + State(Opaque::new(c_state)) + } + + /// Creates a `State` wrapper around a reference to a C `pwm_state`. + fn from_c_ref(c_state: &bindings::pwm_state) -> &Self { + // SAFETY: Pointer is valid, lifetime tied to input ref. Cast poin= ter type. + unsafe { &*(c_state as *const bindings::pwm_state as *const Self) } + } + + /// Gets the period of the PWM signal in nanoseconds. + pub fn period(&self) -> u64 { + unsafe { (*self.0.get()).period } + } + + /// Sets the period of the PWM signal in nanoseconds. + pub fn set_period(&mut self, period_ns: u64) { + unsafe { + (*self.0.get()).period =3D period_ns; + } + } + + /// Gets the duty cycle of the PWM signal in nanoseconds. + pub fn duty_cycle(&self) -> u64 { + unsafe { (*self.0.get()).duty_cycle } + } + + /// Sets the duty cycle of the PWM signal in nanoseconds. + pub fn set_duty_cycle(&mut self, duty_ns: u64) { + unsafe { + (*self.0.get()).duty_cycle =3D duty_ns; + } + } + + /// Returns `true` if the PWM signal is enabled. + pub fn enabled(&self) -> bool { + unsafe { (*self.0.get()).enabled } + } + + /// Sets the enabled state of the PWM signal. + pub fn set_enabled(&mut self, enabled: bool) { + unsafe { + (*self.0.get()).enabled =3D enabled; + } + } + + /// Gets the polarity of the PWM signal. + pub fn polarity(&self) -> Polarity { + Polarity::from(unsafe { (*self.0.get()).polarity }) + } + + /// Sets the polarity of the PWM signal. + pub fn set_polarity(&mut self, polarity: Polarity) { + unsafe { + (*self.0.get()).polarity =3D polarity.into(); + } + } + + /// Returns `true` if the PWM signal is configured for power usage hin= t. + pub fn usage_power(&self) -> bool { + unsafe { (*self.0.get()).usage_power } + } + + /// Sets the power usage hint for the PWM signal. + pub fn set_usage_power(&mut self, usage_power: bool) { + unsafe { + (*self.0.get()).usage_power =3D usage_power; + } + } +} + +/// Wrapper for a PWM device/channel (`struct pwm_device`). +#[repr(transparent)] +pub struct Device(Opaque); + +impl Device { + pub(crate) unsafe fn from_ptr<'a>(ptr: *mut bindings::pwm_device) -> &= 'a mut Self { + unsafe { &mut *ptr.cast::() } + } + + fn as_ptr(&self) -> *mut bindings::pwm_device { + self.0.get() + } + + /// Gets the hardware PWM index for this device within its chip. + pub fn hwpwm(&self) -> u32 { + unsafe { (*self.as_ptr()).hwpwm } + } + + /// Gets a reference to the parent `Chip` that this device belongs to. + pub fn chip(&self) -> &Chip { + unsafe { Chip::from_ptr((*self.as_ptr()).chip) } + } + + /// Gets the label for this PWM device, if any. + pub fn label(&self) -> Option<&CStr> { + let label_ptr =3D unsafe { (*self.as_ptr()).label }; + if label_ptr.is_null() { + None + } else { + Some(unsafe { CStr::from_char_ptr(label_ptr) }) + } + } + + /// Gets a copy of the board-dependent arguments for this PWM device. + pub fn args(&self) -> Args { + Args::from_c_ref(unsafe { &(*self.as_ptr()).args }) + } + + /// Gets a copy of the current state of this PWM device. + pub fn state(&self) -> State { + State::from_c(unsafe { (*self.as_ptr()).state }) + } + + /// Returns `true` if the PWM signal is currently enabled based on its= state. + pub fn is_enabled(&self) -> bool { + self.state().enabled() + } +} + +/// Wrapper for a PWM chip/controller (`struct pwm_chip`). +#[repr(transparent)] +pub struct Chip(Opaque); + +impl Chip { + /// Creates a `Chip` reference from a raw pointer. (Safety notes apply) + pub(crate) unsafe fn from_ptr<'a>(ptr: *mut bindings::pwm_chip) -> &'a= mut Self { + unsafe { &mut *ptr.cast::() } + } + + /// Returns a raw pointer to the underlying `pwm_chip`. + pub(crate) fn as_ptr(&self) -> *mut bindings::pwm_chip { + self.0.get() + } + + /// Gets the number of PWM channels (hardware PWMs) on this chip. + pub fn npwm(&self) -> u32 { + unsafe { (*self.as_ptr()).npwm } + } + + /// Returns `true` if the chip supports atomic operations for configur= ation. + pub fn is_atomic(&self) -> bool { + unsafe { (*self.as_ptr()).atomic } + } + + /// Returns a reference to the embedded `struct device` abstraction (`= CoreDevice`). + pub fn device(&self) -> &CoreDevice { + // SAFETY: `dev` field exists and points to the embedded device. + let dev_ptr =3D unsafe { &(*self.as_ptr()).dev as *const _ as *mut= bindings::device }; + unsafe { &*(dev_ptr as *mut CoreDevice) } + } + + /// Returns a reference to the parent device (`struct device`) of this= PWM chip's device. + pub fn parent_device(&self) -> Option<&CoreDevice> { + // SAFETY: Accessing fields via assumed-valid pointer and bindgen = layout. + let parent_ptr =3D unsafe { bindings::pwmchip_parent(self.as_ptr()= ) }; + if parent_ptr.is_null() { + None + } else { + // SAFETY: Pointer is non-null, assume valid device managed by= kernel. + Some(unsafe { &*(parent_ptr as *mut CoreDevice) }) + } + } + + /// Gets the *typed* driver-specific data associated with this chip's = embedded device. + pub fn get_drvdata(&self) -> Option<&T> { + let ptr =3D unsafe { bindings::pwmchip_get_drvdata(self.as_ptr()) = }; + if ptr.is_null() { + None + } else { + unsafe { Some(&*(ptr as *const T)) } + } + } + + /// Sets the *typed* driver-specific data associated with this chip's = embedded device. + pub fn set_drvdata(&mut self, data: T) { + unsafe { bindings::pwmchip_set_drvdata(self.as_ptr(), data.into_fo= reign() as _) } + } +} + +/// Allocates a PWM chip structure using device resource management. Mirro= rs `devm_pwmchip_alloc`. +pub fn devm_chip_alloc<'a>( + parent: &'a CoreDevice, + npwm: u32, + sizeof_priv: usize, +) -> Result<&'a mut Chip> { + // SAFETY: `devm_pwmchip_alloc` called with valid args. Returns valid = ptr or ERR_PTR. + let parent_ptr =3D parent as *const CoreDevice as *mut bindings::devic= e; + let chip_ptr =3D unsafe { bindings::devm_pwmchip_alloc(parent_ptr, npw= m, sizeof_priv) }; + if unsafe { bindings::IS_ERR(chip_ptr as *const core::ffi::c_void) } { + let err =3D unsafe { bindings::PTR_ERR(chip_ptr as *const core::ff= i::c_void) }; + pr_err!("devm_pwmchip_alloc failed: {}\n", err); + Err(Error::from_errno(err as i32)) + } else { + // SAFETY: `chip_ptr` valid, lifetime managed by `devm` tied to `p= arent`. + Ok(unsafe { &mut *(chip_ptr as *mut Chip) }) + } +} + +/// Registers a PWM chip with the PWM subsystem. Mirrors `__pwmchip_add`. +pub fn chip_add(chip: &mut Chip, ops: &'static PwmOpsVTable) -> Result { + // SAFETY: Pointers are valid. `__pwmchip_add` requires ops to be set. + unsafe { + let chip_ptr =3D chip.as_ptr(); + // Assign the ops pointer directly to the C struct field + (*chip_ptr).ops =3D ops.as_ptr(); + to_result(bindings::__pwmchip_add( + chip_ptr, + core::ptr::null_mut() + )) + } +} + +/// Registers a PWM chip using device resource management. Mirrors `__devm= _pwmchip_add`. +pub fn devm_chip_add(parent: &CoreDevice, chip: &mut Chip, ops: &'static P= wmOpsVTable) -> Result { + // SAFETY: Pointers are valid. `__devm_pwmchip_add` requires ops to be= set. + unsafe { + let chip_ptr =3D chip.as_ptr(); + // Assign the ops pointer directly to the C struct field + (*chip_ptr).ops =3D ops.as_ptr(); + let parent_ptr =3D parent as *const CoreDevice as *mut bindings::d= evice; + to_result(bindings::__devm_pwmchip_add( + parent_ptr, + chip_ptr, + core::ptr::null_mut() + )) + } +} + +/// Trait defining the operations for a PWM driver. Mirrors relevant parts= of `struct pwm_ops`. +pub trait PwmOps: 'static { + /// Atomically apply a new state to the PWM device. Mirrors `pwm_ops->= apply`. + fn apply(chip: &mut Chip, pwm: &mut Device, state: &State) -> Result; + + // TODO: Add other ops like request, free, capture, waveform ops if ne= eded. +} + +/// Holds the vtable for PwmOps implementations. +struct Adapter { + _p: PhantomData, +} + +impl Adapter { + // Trampoline for `apply`. + unsafe extern "C" fn apply_callback( + chip: *mut bindings::pwm_chip, + pwm: *mut bindings::pwm_device, + state: *const bindings::pwm_state, // Input state is const + ) -> core::ffi::c_int { + // SAFETY: Pointers from core are valid. Create temporary wrappers. + let chip_ref =3D unsafe { Chip::from_ptr(chip) }; + let pwm_ref =3D unsafe { Device::from_ptr(pwm) }; + // Use the reference wrapper for the const C state + let state_ref =3D State::from_c_ref(unsafe { &*state }); + + match T::apply(chip_ref, pwm_ref, state_ref) { + Ok(()) =3D> 0, + Err(e) =3D> e.to_errno(), + } + } +} + +/// VTable structure wrapper for PWM operations. Mirrors `struct pwm_ops`. +#[repr(transparent)] +pub struct PwmOpsVTable(Opaque); + +// SAFETY: Holds function pointers, no accessible mutable state via &self. +unsafe impl Sync for PwmOpsVTable {} + +impl PwmOpsVTable { + /// Returns a raw pointer to the underlying `pwm_ops` struct. + pub(crate) fn as_ptr(&self) -> *const bindings::pwm_ops { + self.0.get() + } +} + +/// Creates a PWM operations vtable for a type `T` that implements `PwmOps= `. +/// +/// This is used to bridge Rust trait implementations to the C `struct pwm= _ops` +/// expected by the kernel. +pub const fn create_pwm_ops() -> PwmOpsVTable { + let mut ops: bindings::pwm_ops =3D unsafe { core::mem::zeroed() }; + + ops.apply =3D Some(Adapter::::apply_callback); + + PwmOpsVTable(Opaque::new(ops)) +} --=20 2.34.1 From nobody Fri Dec 19 16:03:34 2025 Received: from mailout1.w1.samsung.com (mailout1.w1.samsung.com [210.118.77.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 02FA227EC74 for ; Sat, 24 May 2025 21:15:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.118.77.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121335; cv=none; b=B/QMds6FSJEw4FGfTi/lxBNSK5Z4p2XhlfcRTraiYXB9XyKhOL2m/MhNbog862Ok/VXm5HTjWsnR6zzPz9tEl6RR6eablgRQ+tCC1XyQydoG5xhJDAoKdM3kP4c98jP8zGmgrOBSyXGXrILByH/VrzIHJSjteyVDI+gAlnfzox8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121335; c=relaxed/simple; bh=7IaK367yI1lVGZhX1Wip/rOtJrFPP5FbOrwTyXypQOw=; h=From:Date:Subject:MIME-Version:Message-Id:In-Reply-To:To:Cc: Content-Type:References; b=MIrjLo9BxbzzvaAZ0vyuZxzQMH4v93CplhLeQkZh1IDtgDnAh6Roeqe/mW7JjrwK8xUBRFjbUuFZ9ThlSySzzDkVB7g9slphs6PcFMQb2HAs6emwsEHr9905s5eBF+TyH5XFzNDFLevgJUp6Kfu0EUqQezMOneRXuDfH32+j2mo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com; spf=pass smtp.mailfrom=samsung.com; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b=pIMsj4eE; arc=none smtp.client-ip=210.118.77.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=samsung.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="pIMsj4eE" Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout1.w1.samsung.com (KnoxPortal) with ESMTP id 20250524211523euoutp012304af28ee13dbae71cbe476b3e80447~CkxTSWi-52399223992euoutp01f for ; Sat, 24 May 2025 21:15:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.w1.samsung.com 20250524211523euoutp012304af28ee13dbae71cbe476b3e80447~CkxTSWi-52399223992euoutp01f DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1748121323; bh=mnCVIgqYN4+4I6dWIR4rHEpcqnjqxXuA7wC3g9VEo/U=; h=From:Date:Subject:In-Reply-To:To:Cc:References:From; b=pIMsj4eECGz0kdoZ5WiQFp8VdaU050uquSp6m5VEZr0TC1SQyhP/fw+SRjXdYMbp/ s08J1UmUBZRSniBxTZxcXrW2cuUIuwgqSVEwsbQ+Nwp2vN2z8YNHXIfhdtJ6WVoC0M HImFsOv1TA+oMluAuTWRA55L0wR6MGeGBYEd1LIA= Received: from eusmtip2.samsung.com (unknown [203.254.199.222]) by eucas1p1.samsung.com (KnoxPortal) with ESMTPA id 20250524211521eucas1p1929a51901c91d1a37e9f4c2da86ff7b0~CkxSJuHyn0444104441eucas1p1P; Sat, 24 May 2025 21:15:21 +0000 (GMT) Received: from AMDC4942.eu.corp.samsungelectronics.net (unknown [106.210.136.40]) by eusmtip2.samsung.com (KnoxPortal) with ESMTPA id 20250524211520eusmtip2b029f711a8bff2e2a1937b3e072fbbdd~CkxRJVqxe0676606766eusmtip2n; Sat, 24 May 2025 21:15:20 +0000 (GMT) From: Michal Wilczynski Date: Sat, 24 May 2025 23:14:56 +0200 Subject: [PATCH RFC 2/6] pwm: Add Rust driver for T-HEAD TH1520 SoC Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-Id: <20250524-rust-next-pwm-working-fan-for-sending-v1-2-bdd2d5094ff7@samsung.com> In-Reply-To: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Michal Wilczynski , Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Marek Szyprowski Cc: linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org X-Mailer: b4 0.15-dev X-CMS-MailID: 20250524211521eucas1p1929a51901c91d1a37e9f4c2da86ff7b0 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-RootMTR: 20250524211521eucas1p1929a51901c91d1a37e9f4c2da86ff7b0 X-EPHeader: CA X-CMS-RootMailID: 20250524211521eucas1p1929a51901c91d1a37e9f4c2da86ff7b0 References: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> Introduce a PWM driver for the T-HEAD TH1520 SoC written in Rust. It utilizes the Rust PWM abstractions added in the previous commit. The driver implements the standard PwmOps for the PWM framework, supporting configuration of period, duty cycle, and polarity for the TH1520's PWM channels. It uses devm managed resources for the PWM chip itself and Rust DevRes for I/O memory. Clock management is handled using Rust's RAII pattern. Signed-off-by: Michal Wilczynski --- MAINTAINERS | 1 + drivers/pwm/Kconfig | 6 + drivers/pwm/Makefile | 1 + drivers/pwm/pwm_th1520.rs | 272 ++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 280 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2b080e8f3d873b1e401b3a2fe1207c224c4591fc..0cfac73aea65076c5ccb50a25ea= 686fb86b472b8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20986,6 +20986,7 @@ F: drivers/mailbox/mailbox-th1520.c F: drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c F: drivers/pinctrl/pinctrl-th1520.c F: drivers/pmdomain/thead/ +F: drivers/pwm/pwm_th1520.rs F: include/dt-bindings/clock/thead,th1520-clk-ap.h F: include/dt-bindings/power/thead,th1520-power.h F: include/linux/firmware/thead/thead,th1520-aon.h diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index b5bd5c13b3a5e5a575a0fbfb2e285f5665b7a671..796fcd8343b7c8e30f62edc2e0f= ecf0e9b1ae20e 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -684,6 +684,12 @@ config PWM_TEGRA To compile this driver as a module, choose M here: the module will be called pwm-tegra. =20 +config PWM_TH1520_RUST + tristate "TH1520 PWM support (Rust)" + depends on RUST_PWM_ABSTRACTIONS + help + Generic PWM framework driver for TH1520 SoC. + config PWM_TIECAP tristate "ECAP PWM support" depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE || ARCH_= K3 || COMPILE_TEST diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 539e0def3f82fcb866ab83a0346a15f7efdd7127..6890f860ada6f1a6ed43dd3a3a9= 584cd2fa877f3 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -70,3 +70,4 @@ obj-$(CONFIG_PWM_TWL_LED) +=3D pwm-twl-led.o obj-$(CONFIG_PWM_VISCONTI) +=3D pwm-visconti.o obj-$(CONFIG_PWM_VT8500) +=3D pwm-vt8500.o obj-$(CONFIG_PWM_XILINX) +=3D pwm-xilinx.o +obj-$(CONFIG_PWM_TH1520_RUST) +=3D pwm_th1520.o diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs new file mode 100644 index 0000000000000000000000000000000000000000..4665e293e8d0bdc1a62a4e295cd= af4d47b3dd134 --- /dev/null +++ b/drivers/pwm/pwm_th1520.rs @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2025 Samsung Electronics Co., Ltd. +// Author: Michal Wilczynski + +//! Rust T-HEAD TH1520 PWM driver +use kernel::{c_str, clk::Clk, device, io::mem::IoMem, of, platform, prelud= e::*, pwm, time}; + +const MAX_PWM_NUM: u32 =3D 6; + +const fn th1520_pwm_chn_base(n: u32) -> u32 { + n * 0x20 +} +const fn th1520_pwm_ctrl(n: u32) -> u32 { + th1520_pwm_chn_base(n) + 0x00 +} +const fn th1520_pwm_per(n: u32) -> u32 { + th1520_pwm_chn_base(n) + 0x08 +} +const fn th1520_pwm_fp(n: u32) -> u32 { + th1520_pwm_chn_base(n) + 0x0c +} + +const PWM_START: u32 =3D 1 << 0; +const PWM_CFG_UPDATE: u32 =3D 1 << 2; +const PWM_CONTINUOUS_MODE: u32 =3D 1 << 5; +const PWM_FPOUT: u32 =3D 1 << 8; +const PWM_INFACTOUT: u32 =3D 1 << 9; + +struct Th1520PwmChipData { + clk: Clk, + iomem: kernel::devres::Devres>, +} + +impl Th1520PwmChipData { + fn _config( + &self, + hwpwm: u32, + duty_ns: u64, + period_ns: u64, + target_polarity: pwm::Polarity, + ) -> Result { + let regs =3D self.iomem.try_access().ok_or_else(|| { + pr_err!("PWM-{}: Failed to access I/O memory in _config\n", hw= pwm); + EBUSY + })?; + + // Calculate cycle values + let rate_hz_u64 =3D self.clk.rate().as_hz() as u64; + + if duty_ns > period_ns { + pr_err!( + "PWM-{}: Duty {}ns > period {}ns\n", + hwpwm, + duty_ns, + period_ns + ); + return Err(EINVAL); + } + if period_ns =3D=3D 0 { + pr_err!("PWM-{}: Period is zero\n", hwpwm); + return Err(EINVAL); + } + + let mut period_cycle =3D mul_div_u64(period_ns, rate_hz_u64, time:= :NSEC_PER_SEC as u64); + if period_cycle > u32::MAX as u64 { + period_cycle =3D u32::MAX as u64; + } + if period_cycle =3D=3D 0 { + pr_err!( + "PWM-{}: Calculated period_cycle is zero, not allowed by H= W\n", + hwpwm + ); + return Err(EINVAL); + } + + let mut duty_cycle =3D mul_div_u64(duty_ns, rate_hz_u64, time::NSE= C_PER_SEC as u64); + if duty_cycle > u32::MAX as u64 { + duty_cycle =3D u32::MAX as u64; + } + + let mut base_ctrl_val =3D PWM_INFACTOUT | PWM_CONTINUOUS_MODE; + if target_polarity =3D=3D pwm::Polarity::Normal { + // FPOUT=3D1 for Normal + base_ctrl_val |=3D PWM_FPOUT; + } else { + // Inversed, FPOUT=3D0 + base_ctrl_val &=3D !PWM_FPOUT; + } + regs.try_write32(base_ctrl_val, th1520_pwm_ctrl(hwpwm) as usize)?; + pr_debug!( + "PWM-{}: _config: Initial CTRL write (polarity, mode): 0x{:x}\= n", + hwpwm, + base_ctrl_val + ); + + // Write period and duty registers + regs.try_write32(period_cycle as u32, th1520_pwm_per(hwpwm) as usi= ze)?; + regs.try_write32(duty_cycle as u32, th1520_pwm_fp(hwpwm) as usize)= ?; + pr_debug!( + "PWM-{}: _config: Period_cyc=3D{}, Duty_cyc=3D{}\n", + hwpwm, + period_cycle, + duty_cycle + ); + + // Apply period/duty by toggling CFG_UPDATE from 0 to 1. + // The `base_ctrl_val` (just written to HW) has CFG_UPDATE=3D0. No= w set it. + let ctrl_val_for_update =3D base_ctrl_val | PWM_CFG_UPDATE; + regs.try_write32(ctrl_val_for_update, th1520_pwm_ctrl(hwpwm) as us= ize)?; + pr_debug!( + "PWM-{}: _config: CTRL write with CFG_UPDATE: 0x{:x}\n", + hwpwm, + ctrl_val_for_update + ); + + Ok(ctrl_val_for_update) + } + + fn _enable(&self, hwpwm: u32, ctrl_val_after_config: u32) -> Result { + let regs =3D self.iomem.try_access().ok_or_else(|| { + pr_err!("PWM-{}: Failed to access I/O memory in _enable\n", hw= pwm); + EBUSY + })?; + + // ctrl_val_after_config already has mode, polarity, and CFG_UPDAT= E correctly set. + // Now add the START bit. START bit auto-clears. + let ctrl_to_start =3D ctrl_val_after_config | PWM_START; + regs.try_write32(ctrl_to_start, th1520_pwm_ctrl(hwpwm) as usize)?; + pr_debug!( + "PWM-{}: _enable: CTRL write with START: 0x{:x}\n", + hwpwm, + ctrl_to_start + ); + Ok(()) + } + + fn _disable(&self, hwpwm: u32) -> Result<()> { + let regs =3D self.iomem.try_access().ok_or_else(|| { + pr_err!("PWM-{}: Failed to access I/O memory in _disable\n", h= wpwm); + EINVAL + })?; + + let mut ctrl_val =3D regs.try_read32(th1520_pwm_ctrl(hwpwm) as usi= ze)?; + pr_debug!("PWM-{}: _disable: Read CTRL: 0x{:x}\n", hwpwm, ctrl_val= ); + + // Ensure CFG_UPDATE is 0 before updating duty (Limitation #4) + if (ctrl_val & PWM_CFG_UPDATE) !=3D 0 { + ctrl_val &=3D !PWM_CFG_UPDATE; + regs.try_write32(ctrl_val, th1520_pwm_ctrl(hwpwm) as usize)?; + pr_debug!( + "PWM-{}: _disable: Cleared CFG_UPDATE, wrote CTRL: 0x{:x}\= n", + hwpwm, + ctrl_val + ); + } + + // Set duty cycle to 0 + regs.try_write32(0, th1520_pwm_fp(hwpwm) as usize)?; + pr_debug!("PWM-{}: _disable: Wrote 0 to DUTY (FP) register\n", hwp= wm); + + // Apply the 0% duty by toggling CFG_UPDATE from 0 to 1 + // Use the ctrl_val that has CFG_UPDATE cleared (or was already cl= ear) + ctrl_val |=3D PWM_CFG_UPDATE; + regs.try_write32(ctrl_val, th1520_pwm_ctrl(hwpwm) as usize)?; + pr_debug!( + "PWM-{}: _disable: Set CFG_UPDATE, wrote CTRL: 0x{:x}\n", + hwpwm, + ctrl_val + ); + + Ok(()) + } +} + +impl pwm::PwmOps for Th1520PwmChipData { + // This driver implements get_state + fn apply( + pwm_chip_ref: &mut pwm::Chip, + pwm_dev: &mut pwm::Device, + target_state: &pwm::State, + ) -> Result { + let data: &Th1520PwmChipData =3D pwm_chip_ref.get_drvdata().ok_or(= EINVAL)?; + let hwpwm =3D pwm_dev.hwpwm(); + + if !target_state.enabled() { + if pwm_dev.state().enabled() { + data._disable(hwpwm)?; + } + + return Ok(()); + } + + // Configure period, duty, and polarity. + // This function also latches period/duty with CFG_UPDATE. + // It returns the control value that was written with CFG_UPDATE s= et. + let ctrl_val_after_config =3D data._config( + hwpwm, + target_state.duty_cycle(), + target_state.period(), + target_state.polarity(), + )?; + + // Enable by setting START bit if it wasn't enabled before this ap= ply call + if !pwm_dev.state().enabled() { + data._enable(hwpwm, ctrl_val_after_config)?; + } + + Ok(()) + } +} + +impl Drop for Th1520PwmChipData { + fn drop(&mut self) { + self.clk.disable_unprepare(); + } +} + +fn mul_div_u64(a: u64, b: u64, c: u64) -> u64 { + if c =3D=3D 0 { + return 0; + } + a.wrapping_mul(b) / c +} + +static TH1520_PWM_OPS: pwm::PwmOpsVTable =3D pwm::create_pwm_ops::(); + +struct Th1520PwmPlatformDriver; + +kernel::of_device_table!( + OF_TABLE, + MODULE_OF_TABLE, + ::IdInfo, + [(of::DeviceId::new(c_str!("thead,th1520-pwm")), ())] +); + +impl platform::Driver for Th1520PwmPlatformDriver { + type IdInfo =3D (); + const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); + + fn probe( + pdev: &platform::Device, + _id_info: Option<&Self::IdInfo>, + ) -> Result>> { + let resource =3D pdev.resource(0).ok_or(ENODEV)?; + let iomem =3D pdev.ioremap_resource(&resource)?; + + let clk =3D Clk::get(pdev.as_ref(), None)?; + + clk.prepare_enable()?; + let driver_data =3D KBox::new(Th1520PwmChipData { clk, iomem }, GF= P_KERNEL)?; + let pwm_chip =3D pwm::devm_chip_alloc(pdev.as_ref(), MAX_PWM_NUM, = 0)?; + + let result =3D pwm::devm_chip_add(pdev.as_ref(), pwm_chip, &TH1520= _PWM_OPS); + if result.is_err() { + pr_err!("Failed to add PWM chip: {:?}\n", result); + return Err(EIO); + } + + pwm_chip.set_drvdata(driver_data); + pr_info!("T-HEAD TH1520 PWM probed correctly\n"); + + Ok(KBox::new(Self, GFP_KERNEL)?.into()) + } +} + +kernel::module_platform_driver! { + type: Th1520PwmPlatformDriver, + name: "pwm_th1520", + author: "Michal Wilczynski", + description: "T-HEAD TH1520 PWM driver", + license: "GPL v2", +} --=20 2.34.1 From nobody Fri Dec 19 16:03:34 2025 Received: from mailout2.w1.samsung.com (mailout2.w1.samsung.com [210.118.77.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8939927EC99 for ; Sat, 24 May 2025 21:15:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.118.77.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121335; cv=none; b=DvKbrmfC/n3RWErfr2lqQDMEwzlCYCTrY3EaqRpG+jLyE6bYRjynIdLgBeTochQ+iMOqAss4/M/Aa71BerTPWS0QOe/Ju8i1EAwXNu4AfFdmgArsTk+IXHh44QyiwSSLWlDtYCzcdBUv4oTt0Nq+5toy3+HdQnbwomGd1yaEYrk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121335; c=relaxed/simple; bh=zui7I72XOEaYjk72Ut9dv3GJFcuqX8Cx9hNGCJlapow=; h=From:Date:Subject:MIME-Version:Message-Id:In-Reply-To:To:Cc: Content-Type:References; b=ckDgJbxiln6XwfsoV6uIKYHVPZpOwMKCBfy7FDhH7xs9VLVxBH+rTnVktmy8yChyxL9q3XyOKd1b9NSddl22JZMMhlVNT/0oOxA3VKar4+kxujrDVMKgPezov9d69qHrjpQN8bPaLAtXKT1pw2jIeSYM1VEBoeI3171V/eeL94A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com; spf=pass smtp.mailfrom=samsung.com; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b=jemXl/OX; arc=none smtp.client-ip=210.118.77.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=samsung.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="jemXl/OX" Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id 20250524211523euoutp027c13e305a9a4714a9fdc57659a9f6128~CkxUA8MX23036130361euoutp02J for ; Sat, 24 May 2025 21:15:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com 20250524211523euoutp027c13e305a9a4714a9fdc57659a9f6128~CkxUA8MX23036130361euoutp02J DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1748121323; bh=8wzaIzSpBE90LSl4LWI/qpw+zDrejg43YHnL4PV7HQI=; h=From:Date:Subject:In-Reply-To:To:Cc:References:From; b=jemXl/OXsy0Wh1Ct6Lco3dC/yQU19/6F9WIf+0BZ4Km/yy7C6zKxvylXiAa7rrmpb YW4z6FzyvlyIZPVab6TDcAr3wiwBMIK65+a+V0oxR9fmW6XlMaNBkTxIYk5U/ICLXz okMjl5CoAlQzLxnkI3gcmFNHmjljkDddMgu5aDog= Received: from eusmtip2.samsung.com (unknown [203.254.199.222]) by eucas1p2.samsung.com (KnoxPortal) with ESMTPA id 20250524211522eucas1p2ab9788753a399bb2d3fb8fe440ea24ac~CkxTNT4_G1830918309eucas1p2I; Sat, 24 May 2025 21:15:22 +0000 (GMT) Received: from AMDC4942.eu.corp.samsungelectronics.net (unknown [106.210.136.40]) by eusmtip2.samsung.com (KnoxPortal) with ESMTPA id 20250524211521eusmtip2c915ef2b2af89fff2e6474c3b477e2cc~CkxSNOh_K0676606766eusmtip2o; Sat, 24 May 2025 21:15:21 +0000 (GMT) From: Michal Wilczynski Date: Sat, 24 May 2025 23:14:57 +0200 Subject: [PATCH RFC 3/6] dt-bindings: pwm: thead: Add T-HEAD TH1520 PWM controller Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-Id: <20250524-rust-next-pwm-working-fan-for-sending-v1-3-bdd2d5094ff7@samsung.com> In-Reply-To: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Michal Wilczynski , Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Marek Szyprowski Cc: linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org X-Mailer: b4 0.15-dev X-CMS-MailID: 20250524211522eucas1p2ab9788753a399bb2d3fb8fe440ea24ac X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-RootMTR: 20250524211522eucas1p2ab9788753a399bb2d3fb8fe440ea24ac X-EPHeader: CA X-CMS-RootMailID: 20250524211522eucas1p2ab9788753a399bb2d3fb8fe440ea24ac References: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> Add the Device Tree binding documentation for the T-HEAD TH1520 SoC PWM controller. Signed-off-by: Michal Wilczynski --- .../devicetree/bindings/pwm/thead,th1520-pwm.yaml | 48 ++++++++++++++++++= ++++ MAINTAINERS | 1 + 2 files changed, 49 insertions(+) diff --git a/Documentation/devicetree/bindings/pwm/thead,th1520-pwm.yaml b/= Documentation/devicetree/bindings/pwm/thead,th1520-pwm.yaml new file mode 100644 index 0000000000000000000000000000000000000000..855aec59ac53c430adc84927123= 5686e87b10e6c --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/thead,th1520-pwm.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pwm/thead,th1520-pwm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: T-HEAD TH1520 PWM controller + +maintainers: + - Michal Wilczynski + +allOf: + - $ref: pwm.yaml# + +properties: + compatible: + const: thead,th1520-pwm + + reg: + maxItems: 1 + + clocks: + items: + - description: SoC PWM clock + + "#pwm-cells": + const: 3 + +required: + - compatible + - reg + - clocks + +unevaluatedProperties: false + +examples: + - | + #include + soc { + #address-cells =3D <2>; + #size-cells =3D <2>; + pwm@ffec01c000 { + compatible =3D "thead,th1520-pwm"; + reg =3D <0xff 0xec01c000 0x0 0x4000>; + clocks =3D <&clk CLK_PWM>; + #pwm-cells =3D <3>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 0cfac73aea65076c5ccb50a25ea686fb86b472b8..2ae758a14e8f5a1e7fab7d85831= b571551a49ee9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20979,6 +20979,7 @@ F: Documentation/devicetree/bindings/firmware/thead= ,th1520-aon.yaml F: Documentation/devicetree/bindings/mailbox/thead,th1520-mbox.yaml F: Documentation/devicetree/bindings/net/thead,th1520-gmac.yaml F: Documentation/devicetree/bindings/pinctrl/thead,th1520-pinctrl.yaml +F: Documentation/devicetree/bindings/pwm/thead,th1520-pwm.yaml F: arch/riscv/boot/dts/thead/ F: drivers/clk/thead/clk-th1520-ap.c F: drivers/firmware/thead,th1520-aon.c --=20 2.34.1 From nobody Fri Dec 19 16:03:34 2025 Received: from mailout2.w1.samsung.com (mailout2.w1.samsung.com [210.118.77.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8920027C15B for ; Sat, 24 May 2025 21:15:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.118.77.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121335; cv=none; b=bs7wdKXKye4YhkvLg+k2CCWpvtxN/tfyGY76uA0PVbd4TDk03P/PHoess+hbBnjUjASpgf0KYfGT0kelmlhkADMYAakw8pkORiin3zhbkNrGV1BGkpkAb829Ud1BfFibIFwLtS4Yn725XddB8AVCEA0eH/4TOaQ0pXQ1M+nKK/A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121335; c=relaxed/simple; bh=f+Zvxh7RpZVeeAMm7ojE6sv3IpEluoCdeLo2/ixV3/o=; h=From:Date:Subject:MIME-Version:Message-Id:In-Reply-To:To:Cc: Content-Type:References; b=NtMWHE4uphzyGBaYWgTy0GPwtMLFDq3mr9P1lXHl3FeybRJCDQ3w6nhh+jLlq66RPIUPn0GUO+10k5icVrb4KVRTCCCMCz0NVR4MfSgZQlBQAYH10fEcaPHzPGLVFh6YJku+yDxvtMNpS2AgLHamzK/laC1NuZvw028RD/cqfAk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com; spf=pass smtp.mailfrom=samsung.com; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b=q1MW/LEl; arc=none smtp.client-ip=210.118.77.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=samsung.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="q1MW/LEl" Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id 20250524211525euoutp029272eec57d354e526ca848da269039cc~CkxVpWM2U3035230352euoutp02M for ; Sat, 24 May 2025 21:15:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com 20250524211525euoutp029272eec57d354e526ca848da269039cc~CkxVpWM2U3035230352euoutp02M DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1748121325; bh=2NOPyMWTWiFmeUoJJtW57RkmSgf3zZf1wFf9qv0a94I=; h=From:Date:Subject:In-Reply-To:To:Cc:References:From; b=q1MW/LElhRmQeLtjGtbKEgXxrXQ9cqR5o72ZBRLnZ0aV9e5yDaQd9B3PIKbYMjKfA I24PyLQhNE9eq6ScylTZoS4v1+o5o/BAlQXFZAqLIRet6BjtxGCWUcArs7rDjZ+oFe 3uzeS70dYogYU37DKjUULCqflLeJos7r/Jt2KARE= Received: from eusmtip2.samsung.com (unknown [203.254.199.222]) by eucas1p2.samsung.com (KnoxPortal) with ESMTPA id 20250524211524eucas1p27d56c24a9950a79086f8f4c7d5fa003f~CkxUTZEN02408724087eucas1p2q; Sat, 24 May 2025 21:15:24 +0000 (GMT) Received: from AMDC4942.eu.corp.samsungelectronics.net (unknown [106.210.136.40]) by eusmtip2.samsung.com (KnoxPortal) with ESMTPA id 20250524211522eusmtip2e428d2ec6420649127fc6ba7ffbeb63b~CkxTRe5te0676606766eusmtip2p; Sat, 24 May 2025 21:15:22 +0000 (GMT) From: Michal Wilczynski Date: Sat, 24 May 2025 23:14:58 +0200 Subject: [PATCH RFC 4/6] riscv: dts: thead: Add PWM controller node Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-Id: <20250524-rust-next-pwm-working-fan-for-sending-v1-4-bdd2d5094ff7@samsung.com> In-Reply-To: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Michal Wilczynski , Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Marek Szyprowski Cc: linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org X-Mailer: b4 0.15-dev X-CMS-MailID: 20250524211524eucas1p27d56c24a9950a79086f8f4c7d5fa003f X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-RootMTR: 20250524211524eucas1p27d56c24a9950a79086f8f4c7d5fa003f X-EPHeader: CA X-CMS-RootMailID: 20250524211524eucas1p27d56c24a9950a79086f8f4c7d5fa003f References: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> Add the Device Tree node for the T-HEAD TH1520 SoC's PWM controller. Signed-off-by: Michal Wilczynski --- arch/riscv/boot/dts/thead/th1520.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/th= ead/th1520.dtsi index 527336417765d8470426f2985e1bc22eeafb31aa..f24e12d7259fabcfbdc2dfa966d= 759db06684ab4 100644 --- a/arch/riscv/boot/dts/thead/th1520.dtsi +++ b/arch/riscv/boot/dts/thead/th1520.dtsi @@ -482,6 +482,13 @@ uart2: serial@ffec010000 { status =3D "disabled"; }; =20 + pwm: pwm@ffec01c000 { + compatible =3D "thead,th1520-pwm"; + reg =3D <0xff 0xec01c000 0x0 0x4000>; + clocks =3D <&clk CLK_PWM>; + #pwm-cells =3D <3>; + }; + clk: clock-controller@ffef010000 { compatible =3D "thead,th1520-clk-ap"; reg =3D <0xff 0xef010000 0x0 0x1000>; --=20 2.34.1 From nobody Fri Dec 19 16:03:34 2025 Received: from mailout2.w1.samsung.com (mailout2.w1.samsung.com [210.118.77.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B80727F4D9 for ; Sat, 24 May 2025 21:15:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.118.77.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121336; cv=none; b=eNi7rXNwgm7zyRdR8Bm+09LZYQ6CcHGOkQMkTFqlDsNoKKfnqLhoKBa2GWEmwuM7OYn2KqpoUFbSVi5QA77oG+qwJV3IFCmIYIjxn+ImOHS5yeJtlWEeQF0dMcoSo7jUdpYe6doJZqaqlYFkBjQhWNMzFkai8aBBsSBiMUEFYC4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121336; c=relaxed/simple; bh=/wsmYassOQ9WI9vIn+R/6Xcj8kfMOeqsIMXvgyAxVD4=; h=From:Date:Subject:MIME-Version:Message-Id:In-Reply-To:To:Cc: Content-Type:References; b=XcW3LuRs3at4uLj7zxabU7B97aRGUX+1uz6R+SvNJFCVHOkdO19JG0CsoFoWmsaa/lDmLs4W4P5dKvjtiEoS2U+WyY0zedweQiy5Oa2CO82E/ZlKRqxsJlSeTYAE1RXDVRlrYUT2rB8SHiump2kjRCbcXc7lXRDBw4txyyDPFhI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com; spf=pass smtp.mailfrom=samsung.com; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b=nSm3fbbf; arc=none smtp.client-ip=210.118.77.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=samsung.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="nSm3fbbf" Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id 20250524211526euoutp028efd99e1827d87d81afdeed786a8844e~CkxWvxuu22567925679euoutp02p for ; Sat, 24 May 2025 21:15:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com 20250524211526euoutp028efd99e1827d87d81afdeed786a8844e~CkxWvxuu22567925679euoutp02p DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1748121326; bh=yfvKCTmfOP4CWdfGBbUZQUNp1klySpsoF9Jq3fSXylU=; h=From:Date:Subject:In-Reply-To:To:Cc:References:From; b=nSm3fbbfvmaQ155OoLC6sr+nk9MyenEntwZXc0mn/AR3mYzoyzKBxtGP+WRW5mXzW 458OGCg7WWmQFysVdBR+7y6p2b21WXf8INdDHMaPm0T9xtWsZ5L34DQIdkw/aokp2i ot9FTrKYQJmixP9JaChbKdt8EAEYvuCwpLOGBIJs= Received: from eusmtip2.samsung.com (unknown [203.254.199.222]) by eucas1p2.samsung.com (KnoxPortal) with ESMTPA id 20250524211525eucas1p244963b69e0531c95a9052e4a7a1d1e01~CkxVawh_W3006630066eucas1p2a; Sat, 24 May 2025 21:15:25 +0000 (GMT) Received: from AMDC4942.eu.corp.samsungelectronics.net (unknown [106.210.136.40]) by eusmtip2.samsung.com (KnoxPortal) with ESMTPA id 20250524211524eusmtip24bdbb3baffcbfe4e6512d3af9c1aa682~CkxUXCNLs0676606766eusmtip2q; Sat, 24 May 2025 21:15:24 +0000 (GMT) From: Michal Wilczynski Date: Sat, 24 May 2025 23:14:59 +0200 Subject: [PATCH RFC 5/6] riscv: dts: thead: Add PVT node Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-Id: <20250524-rust-next-pwm-working-fan-for-sending-v1-5-bdd2d5094ff7@samsung.com> In-Reply-To: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Michal Wilczynski , Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Marek Szyprowski Cc: linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org X-Mailer: b4 0.15-dev X-CMS-MailID: 20250524211525eucas1p244963b69e0531c95a9052e4a7a1d1e01 X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-RootMTR: 20250524211525eucas1p244963b69e0531c95a9052e4a7a1d1e01 X-EPHeader: CA X-CMS-RootMailID: 20250524211525eucas1p244963b69e0531c95a9052e4a7a1d1e01 References: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> Add PVT DT node for thermal sensor. Signed-off-by: Michal Wilczynski --- arch/riscv/boot/dts/thead/th1520.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/th= ead/th1520.dtsi index f24e12d7259fabcfbdc2dfa966d759db06684ab4..faf5c3aaf209b24cd99ddc377a8= 8e08a8cce24fe 100644 --- a/arch/riscv/boot/dts/thead/th1520.dtsi +++ b/arch/riscv/boot/dts/thead/th1520.dtsi @@ -648,6 +648,17 @@ padctrl_aosys: pinctrl@fffff4a000 { thead,pad-group =3D <1>; }; =20 + pvt: pvt@fffff4e000 { + compatible =3D "moortec,mr75203"; + reg =3D <0xff 0xfff4e000 0x0 0x80>, + <0xff 0xfff4e080 0x0 0x100>, + <0xff 0xfff4e180 0x0 0x680>, + <0xff 0xfff4e800 0x0 0x600>; + reg-names =3D "common", "ts", "pd", "vm"; + clocks =3D <&aonsys_clk>; + #thermal-sensor-cells =3D <1>; + }; + gpio@fffff52000 { compatible =3D "snps,dw-apb-gpio"; reg =3D <0xff 0xfff52000 0x0 0x1000>; --=20 2.34.1 From nobody Fri Dec 19 16:03:34 2025 Received: from mailout2.w1.samsung.com (mailout2.w1.samsung.com [210.118.77.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D2CA27F728 for ; Sat, 24 May 2025 21:15:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.118.77.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121336; cv=none; b=Q4z2YqSn9Mo/GahinqcCUQHpyd42AosOaDx/PLVqzrL3/P66zyhi7yS+lHfMfZrKGwcrMNGDbOMzx5uuiYB1HzfZRi6comkIf8WTE/khrAXbDAxcFJqjcrwOWBsb1V6oCEeOIti/U425P1WXfw12a9PTwNdNscTM/OsoEKi0RKU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748121336; c=relaxed/simple; bh=pQpdhYmfxqh3Yfxmei5sPv11PaCzGkgZVRufLVaDNj8=; h=From:Date:Subject:MIME-Version:Message-Id:In-Reply-To:To:Cc: Content-Type:References; b=SUR82ndFH//17vrwOBsmqqcHuuhDzsNOhLo2iZ2b7Dj782p4hyYf17lZcEJlW0pb0yigus8E5Tg34cUnpoCPOKvEUBWSQVfPBWEEhKgB78p0qUIwMPKHneOlOVlGci2NIrBm5zOEZzhzvO3ouneszbGXQCblfNAlug0MoViN70U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com; spf=pass smtp.mailfrom=samsung.com; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b=GkDsiOnk; arc=none smtp.client-ip=210.118.77.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=samsung.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=samsung.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=samsung.com header.i=@samsung.com header.b="GkDsiOnk" Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout2.w1.samsung.com (KnoxPortal) with ESMTP id 20250524211527euoutp02861759143c224944c0d2b15af4f095fb~CkxXs_9B_3036130361euoutp02Q for ; Sat, 24 May 2025 21:15:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout2.w1.samsung.com 20250524211527euoutp02861759143c224944c0d2b15af4f095fb~CkxXs_9B_3036130361euoutp02Q DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1748121327; bh=Thc/4MnT4r5I8ag38cbivyQhpbuX345C1nEB0lzCSSU=; h=From:Date:Subject:In-Reply-To:To:Cc:References:From; b=GkDsiOnkqC+nijHgrhf8+HIxiu3fld84CstiSZaTHcijADsH2dACLGJmmQ6E/6ZFX PsMMoBemlinUpSQqHyUDbc+vwjvpB/xkm1iWemsSP9yA19NkLpWrFKSjeGYHlXxJTF AXHPxhN/Zo88WuJ99BM/R7fV5qBns7FYOTvjiHSY= Received: from eusmtip2.samsung.com (unknown [203.254.199.222]) by eucas1p2.samsung.com (KnoxPortal) with ESMTPA id 20250524211526eucas1p22d608c2baca2908ea62d9e47263b3aec~CkxWc5Euv2217222172eucas1p2j; Sat, 24 May 2025 21:15:26 +0000 (GMT) Received: from AMDC4942.eu.corp.samsungelectronics.net (unknown [106.210.136.40]) by eusmtip2.samsung.com (KnoxPortal) with ESMTPA id 20250524211525eusmtip2bbbad26fe39b7770cb2a2b89091f4cca~CkxVeYWJR0676606766eusmtip2r; Sat, 24 May 2025 21:15:25 +0000 (GMT) From: Michal Wilczynski Date: Sat, 24 May 2025 23:15:00 +0200 Subject: [PATCH RFC 6/6] riscv: dts: thead: Add PWM fan and thermal control Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-Id: <20250524-rust-next-pwm-working-fan-for-sending-v1-6-bdd2d5094ff7@samsung.com> In-Reply-To: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Michal Wilczynski , Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Marek Szyprowski Cc: linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-riscv@lists.infradead.org, devicetree@vger.kernel.org X-Mailer: b4 0.15-dev X-CMS-MailID: 20250524211526eucas1p22d608c2baca2908ea62d9e47263b3aec X-Msg-Generator: CA Content-Type: text/plain; charset="utf-8" X-RootMTR: 20250524211526eucas1p22d608c2baca2908ea62d9e47263b3aec X-EPHeader: CA X-CMS-RootMailID: 20250524211526eucas1p22d608c2baca2908ea62d9e47263b3aec References: <20250524-rust-next-pwm-working-fan-for-sending-v1-0-bdd2d5094ff7@samsung.com> Add Device Tree nodes to enable a PWM controlled fan and it's associated thermal management for the Lichee Pi 4A board. This enables temperature-controlled active cooling for the Lichee Pi 4A board based on SoC temperature. Signed-off-by: Michal Wilczynski --- arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts | 67 +++++++++++++++++++= ++++ 1 file changed, 67 insertions(+) diff --git a/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts b/arch/riscv= /boot/dts/thead/th1520-lichee-pi-4a.dts index 4020c727f09e8e2286fdc7fecd79dbd8eba69556..c58c2085ca92a3234f1350500ce= dae4157f0c35f 100644 --- a/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts +++ b/arch/riscv/boot/dts/thead/th1520-lichee-pi-4a.dts @@ -28,9 +28,76 @@ aliases { chosen { stdout-path =3D "serial0:115200n8"; }; + + thermal-zones { + cpu-thermal { + polling-delay =3D <1000>; + polling-delay-passive =3D <1000>; + thermal-sensors =3D <&pvt 0>; + + trips { + fan_config0: fan-trip0 { + temperature =3D <39000>; + hysteresis =3D <5000>; + type =3D "active"; + }; + + fan_config1: fan-trip1 { + temperature =3D <50000>; + hysteresis =3D <5000>; + type =3D "active"; + }; + + fan_config2: fan-trip2 { + temperature =3D <60000>; + hysteresis =3D <5000>; + type =3D "active"; + }; + }; + + cooling-maps { + map-active-0 { + cooling-device =3D <&fan 1 1>; + trip =3D <&fan_config0>; + }; + + map-active-1 { + cooling-device =3D <&fan 2 2>; + trip =3D <&fan_config1>; + }; + + map-active-2 { + cooling-device =3D <&fan 3 3>; + trip =3D <&fan_config2>; + }; + }; + }; + }; + + fan: pwm-fan { + pinctrl-names =3D "default"; + pinctrl-0 =3D <&fan_pins>; + compatible =3D "pwm-fan"; + #cooling-cells =3D <2>; + pwms =3D <&pwm 1 10000000 0>; + cooling-levels =3D <0 66 196 255>; + }; + }; =20 &padctrl0_apsys { + fan_pins: fan-0 { + pwm1-pins { + pins =3D "GPIO3_3"; /* PWM1 */ + function =3D "pwm"; + bias-disable; + drive-strength =3D <25>; + input-disable; + input-schmitt-disable; + slew-rate =3D <0>; + }; + }; + uart0_pins: uart0-0 { tx-pins { pins =3D "UART0_TXD"; --=20 2.34.1