[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <023e3061cc164087b9079a9f6cb7e9fbf286794e.1740995194.git.viresh.kumar@linaro.org>
Date: Mon, 3 Mar 2025 15:28:10 +0530
From: Viresh Kumar <viresh.kumar@...aro.org>
To: Michael Turquette <mturquette@...libre.com>,
Stephen Boyd <sboyd@...nel.org>,
Miguel Ojeda <ojeda@...nel.org>,
Alex Gaynor <alex.gaynor@...il.com>,
Boqun Feng <boqun.feng@...il.com>,
Gary Guo <gary@...yguo.net>,
Björn Roy Baron <bjorn3_gh@...tonmail.com>,
Benno Lossin <benno.lossin@...ton.me>,
Andreas Hindborg <a.hindborg@...nel.org>,
Alice Ryhl <aliceryhl@...gle.com>,
Trevor Gross <tmgross@...ch.edu>
Cc: Viresh Kumar <viresh.kumar@...aro.org>,
Russell King <linux@...linux.org.uk>,
linux-clk@...r.kernel.org,
linux-kernel@...r.kernel.org,
rust-for-linux@...r.kernel.org,
Vincent Guittot <vincent.guittot@...aro.org>,
Daniel Almeida <daniel.almeida@...labora.com>
Subject: [PATCH V3 2/2] rust: Add initial clk abstractions
Add initial abstractions for the clk APIs. These provide the minimal
functionality needed for common use cases, making them straightforward
to introduce in the first iteration.
These will be used by Rust based cpufreq / OPP layers to begin with.
Tested-by: Daniel Almeida <daniel.almeida@...labora.com>
Reviewed-by: Daniel Almeida <daniel.almeida@...labora.com>
Signed-off-by: Viresh Kumar <viresh.kumar@...aro.org>
---
MAINTAINERS | 1 +
rust/kernel/clk.rs | 134 +++++++++++++++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 1 +
3 files changed, 136 insertions(+)
create mode 100644 rust/kernel/clk.rs
diff --git a/MAINTAINERS b/MAINTAINERS
index 726110d3c988..96e2574f41c0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5779,6 +5779,7 @@ F: include/linux/clk-pr*
F: include/linux/clk/
F: include/linux/of_clk.h
F: rust/helpers/clk.c
+F: rust/kernel/clk.rs
X: drivers/clk/clkdev.c
COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)
diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs
new file mode 100644
index 000000000000..1fa5b7298373
--- /dev/null
+++ b/rust/kernel/clk.rs
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Clock abstractions.
+//!
+//! C header: [`include/linux/clk.h`](srctree/include/linux/clk.h)
+
+use crate::{
+ bindings,
+ device::Device,
+ error::{from_err_ptr, to_result, Result},
+ prelude::*,
+};
+
+use core::{ops::Deref, ptr};
+
+/// Frequency unit.
+pub type Hertz = crate::ffi::c_ulong;
+
+/// A simple implementation of `struct clk` from the C code.
+#[repr(transparent)]
+pub struct Clk(*mut bindings::clk);
+
+impl Clk {
+ /// Gets clock corresponding to a device and a connection id and returns `Clk`.
+ pub fn get(dev: &Device, name: Option<&CStr>) -> Result<Self> {
+ let con_id = if let Some(name) = name {
+ name.as_ptr() as *const _
+ } else {
+ ptr::null()
+ };
+
+ // SAFETY: It is safe to call `clk_get()` for a valid device pointer.
+ Ok(Self(from_err_ptr(unsafe {
+ bindings::clk_get(dev.as_raw(), con_id)
+ })?))
+ }
+
+ /// Obtain the raw `struct clk *`.
+ pub fn as_raw(&self) -> *mut bindings::clk {
+ self.0
+ }
+
+ /// Clock enable.
+ pub fn enable(&self) -> Result<()> {
+ // SAFETY: It is safe to call clk APIs of the C code for a clock pointer earlier returned
+ // by `clk_get()`.
+ to_result(unsafe { bindings::clk_enable(self.as_raw()) })
+ }
+
+ /// Clock disable.
+ pub fn disable(&self) {
+ // SAFETY: It is safe to call clk APIs of the C code for a clock pointer earlier returned
+ // by `clk_get()`.
+ unsafe { bindings::clk_disable(self.as_raw()) };
+ }
+
+ /// Clock prepare.
+ pub fn prepare(&self) -> Result<()> {
+ // SAFETY: It is safe to call clk APIs of the C code for a clock pointer earlier returned
+ // by `clk_get()`.
+ to_result(unsafe { bindings::clk_prepare(self.as_raw()) })
+ }
+
+ /// Clock unprepare.
+ pub fn unprepare(&self) {
+ // SAFETY: It is safe to call clk APIs of the C code for a clock pointer earlier returned
+ // by `clk_get()`.
+ unsafe { bindings::clk_unprepare(self.as_raw()) };
+ }
+
+ /// Clock prepare enable.
+ pub fn prepare_enable(&self) -> Result<()> {
+ // SAFETY: It is safe to call clk APIs of the C code for a clock pointer earlier returned
+ // by `clk_get()`.
+ to_result(unsafe { bindings::clk_prepare_enable(self.as_raw()) })
+ }
+
+ /// Clock disable unprepare.
+ pub fn disable_unprepare(&self) {
+ // SAFETY: It is safe to call clk APIs of the C code for a clock pointer earlier returned
+ // by `clk_get()`.
+ unsafe { bindings::clk_disable_unprepare(self.as_raw()) };
+ }
+
+ /// Clock get rate.
+ pub fn rate(&self) -> Hertz {
+ // SAFETY: It is safe to call clk APIs of the C code for a clock pointer earlier returned
+ // by `clk_get()`.
+ unsafe { bindings::clk_get_rate(self.as_raw()) }
+ }
+
+ /// Clock set rate.
+ pub fn set_rate(&self, rate: Hertz) -> Result<()> {
+ // SAFETY: It is safe to call clk APIs of the C code for a clock pointer earlier returned
+ // by `clk_get()`.
+ to_result(unsafe { bindings::clk_set_rate(self.as_raw(), rate) })
+ }
+}
+
+impl Drop for Clk {
+ fn drop(&mut self) {
+ // SAFETY: It is safe to call clk APIs of the C code for a clock pointer earlier returned
+ // by `clk_get()`.
+ unsafe { bindings::clk_put(self.as_raw()) };
+ }
+}
+
+/// A simple implementation of optional `Clk`.
+pub struct OptionalClk(Clk);
+
+impl OptionalClk {
+ /// Gets optional clock corresponding to a device and a connection id and returns `Clk`.
+ pub fn get(dev: &Device, name: Option<&CStr>) -> Result<Self> {
+ let con_id = if let Some(name) = name {
+ name.as_ptr() as *const _
+ } else {
+ ptr::null()
+ };
+
+ // SAFETY: It is safe to call `clk_get_optional()` for a valid device pointer.
+ Ok(Self(Clk(from_err_ptr(unsafe {
+ bindings::clk_get_optional(dev.as_raw(), con_id)
+ })?)))
+ }
+}
+
+// Make `OptionalClk` behave like `Clk`.
+impl Deref for OptionalClk {
+ type Target = Clk;
+
+ fn deref(&self) -> &Clk {
+ &self.0
+ }
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 496ed32b0911..324b86f127a0 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -40,6 +40,7 @@
pub mod block;
#[doc(hidden)]
pub mod build_assert;
+pub mod clk;
pub mod cred;
pub mod device;
pub mod device_id;
--
2.31.1.272.g89b43f80a514
Powered by blists - more mailing lists