From: Fabien Parent <parent.f@gmail.com>
To: "Rob Herring" <robh@kernel.org>,
"Saravana Kannan" <saravanak@google.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
"Wolfram Sang" <wsa+renesas@sang-engineering.com>,
"Mark Brown" <broonie@kernel.org>,
"Liam Girdwood" <lgirdwood@gmail.com>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Bjorn Andersson" <andersson@kernel.org>,
"Konrad Dybcio" <konradybcio@kernel.org>,
"Fabien Parent" <parent.f@gmail.com>
Cc: devicetree@vger.kernel.org, rust-for-linux@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org,
linux-arm-msm@vger.kernel.org, vinod.koul@linaro.org,
Fabien Parent <fabien.parent@linaro.org>
Subject: [PATCH 6/9] rust: regulator: add support for regmap
Date: Wed, 18 Dec 2024 15:36:36 -0800 [thread overview]
Message-ID: <20241218-ncv6336-v1-6-b8d973747f7a@gmail.com> (raw)
In-Reply-To: <20241218-ncv6336-v1-0-b8d973747f7a@gmail.com>
From: Fabien Parent <fabien.parent@linaro.org>
The regulator API offer many helpers to help simplifies drivers that
use the regmap API. This commit adds partial support for it, only the
function needed by the NCV6336 driver were added.
Signed-off-by: Fabien Parent <fabien.parent@linaro.org>
---
rust/kernel/regulator/driver.rs | 141 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 141 insertions(+)
diff --git a/rust/kernel/regulator/driver.rs b/rust/kernel/regulator/driver.rs
index 8079ea28fd5bf7b6871a0b1d2cea7a6fffcb43ca..e79e93122b094e5e086780f18ecdac5105d07153 100644
--- a/rust/kernel/regulator/driver.rs
+++ b/rust/kernel/regulator/driver.rs
@@ -37,13 +37,27 @@
device,
error::{code::*, from_err_ptr, from_result, Error, Result},
macros::vtable,
+ private::Sealed,
regulator::Mode,
str::CStr,
+ sync::Arc,
types::ForeignOwnable,
ThisModule,
};
+#[cfg(CONFIG_REGMAP)]
+use crate::{error::to_result, regmap::Regmap};
use core::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull};
+#[cfg(not(CONFIG_REGMAP))]
+struct Regmap;
+
+#[cfg(not(CONFIG_REGMAP))]
+impl Regmap {
+ pub fn as_raw(&self) -> *mut bindings::regmap {
+ core::ptr::null_mut()
+ }
+}
+
/// [`Device`]'s status
#[derive(Eq, PartialEq)]
pub enum Status {
@@ -357,6 +371,7 @@ unsafe impl Sync for Desc {}
pub struct Config<T: ForeignOwnable + Send + Sync = ()> {
cfg: bindings::regulator_config,
data: T,
+ regmap: Option<Arc<Regmap>>,
}
impl<T: ForeignOwnable + Send + Sync> Config<T> {
@@ -368,8 +383,16 @@ pub fn new(dev: &device::Device, data: T) -> Self {
..Default::default()
},
data,
+ regmap: None,
}
}
+
+ /// Assign a regmap device to the config
+ #[cfg(CONFIG_REGMAP)]
+ pub fn with_regmap(mut self, regmap: Arc<Regmap>) -> Self {
+ self.regmap = Some(regmap);
+ self
+ }
}
/// Regulator device
@@ -384,6 +407,9 @@ pub fn new(dev: &device::Device, data: T) -> Self {
pub struct Device<T: ForeignOwnable + Send + Sync> {
rdev: NonNull<bindings::regulator_dev>,
_data_type: PhantomData<T>,
+ // The C regmap API does not keep reference count. Keep a reference to the regmap pointer that
+ // is shared to the C regulator API.
+ _regmap: Option<Arc<Regmap>>,
}
impl<T: ForeignOwnable + Send + Sync> Device<T> {
@@ -396,6 +422,7 @@ unsafe fn from_raw(rdev: *mut bindings::regulator_dev) -> ManuallyDrop<Self> {
// valid..
rdev: unsafe { NonNull::new_unchecked(rdev) },
_data_type: PhantomData::<T>,
+ _regmap: None,
})
}
@@ -407,6 +434,11 @@ pub fn register(
) -> Result<Self> {
config.cfg.driver_data = config.data.into_foreign() as _;
+ let regmap = config.regmap.take();
+ if let Some(regmap) = ®map {
+ config.cfg.regmap = regmap.as_raw() as _;
+ };
+
// SAFETY: By the type invariants, we know that `dev.as_ref().as_raw()` is always
// valid and non-null, and the descriptor and config are guaranteed to be valid values,
// hence it is safe to perform the FFI call.
@@ -417,6 +449,7 @@ pub fn register(
Ok(Self {
rdev: NonNull::new(rdev).ok_or(EINVAL)?,
_data_type: PhantomData::<T>,
+ _regmap: regmap,
})
}
@@ -472,6 +505,114 @@ unsafe impl<T: ForeignOwnable + Send + Sync> Send for Device<T> {}
// the C code is insuring proper synchronization of `self.rdev`.
unsafe impl<T: ForeignOwnable + Send + Sync> Sync for Device<T> {}
+impl<T: ForeignOwnable + Send + Sync> Sealed for Device<T> {}
+
+/// Helper functions to implement some of the [`Driver`] trait methods using [`Regmap`].
+///
+/// This trait is implemented by [`Device`] and is Sealed to prevent
+/// to be implemented by anyone else.
+#[cfg(CONFIG_REGMAP)]
+pub trait RegmapHelpers: Sealed {
+ /// Implementation of [`Driver::get_voltage_sel`] using [`Regmap`].
+ fn get_voltage_sel_regmap(&self) -> Result<i32>;
+ /// Implementation of [`Driver::set_voltage_sel`] using [`Regmap`].
+ fn set_voltage_sel_regmap(&self, sel: u32) -> Result;
+
+ /// Implementation of [`Driver::is_enabled`] using [`Regmap`].
+ ///
+ /// [`Desc::with_enable`] or [`Desc::with_inverted_enable`] must have been called
+ /// to setup the fields required by regmap.
+ fn is_enabled_regmap(&self) -> Result<bool>;
+ /// Implementation of [`Driver::enable`] using [`Regmap`].
+ ///
+ /// [`Desc::with_enable`] or [`Desc::with_inverted_enable`] must have been called
+ /// to setup the fields required by regmap.
+ fn enable_regmap(&self) -> Result;
+ /// Implementation of [`Driver::disable`] using [`Regmap`].
+ ///
+ /// [`Desc::with_enable`] or [`Desc::with_inverted_enable`] must have been called
+ /// to setup the fields required by regmap.
+ fn disable_regmap(&self) -> Result;
+
+ /// Implementation of [`Driver::set_active_discharge`] using [`Regmap`].
+ ///
+ /// [`Desc::with_active_discharge`] must have been called to setup the fields required
+ /// by regmap.
+ fn set_active_discharge_regmap(&self, enable: bool) -> Result;
+
+ /// Implementation of [`Driver::set_current_limit`] using [`Regmap`].
+ fn set_current_limit_regmap(&self, min_ua: i32, max_ua: i32) -> Result;
+ /// Implementation of [`Driver::get_current_limit`] using [`Regmap`].
+ fn get_current_limit_regmap(&self) -> Result<i32>;
+}
+
+#[cfg(CONFIG_REGMAP)]
+impl<T: ForeignOwnable + Send + Sync> RegmapHelpers for Device<T> {
+ fn get_voltage_sel_regmap(&self) -> Result<i32> {
+ // SAFETY: The type invariants guarantee that `self.rdev` is valid and non-null,
+ // so it is safe to perform the FFI call.
+ let ret = unsafe { bindings::regulator_get_voltage_sel_regmap(self.rdev.as_ptr()) };
+ if ret < 0 {
+ return Err(Error::from_errno(ret));
+ }
+ Ok(ret)
+ }
+
+ fn set_voltage_sel_regmap(&self, sel: u32) -> Result {
+ // SAFETY: The type invariants guarantee that `self.rdev` is valid and non-null,
+ // so it is safe to perform the FFI call.
+ to_result(unsafe { bindings::regulator_set_voltage_sel_regmap(self.rdev.as_ptr(), sel) })
+ }
+
+ fn is_enabled_regmap(&self) -> Result<bool> {
+ // SAFETY: The type invariants guarantee that `self.rdev` is valid and non-null,
+ // so it is safe to perform the FFI call.
+ let ret = unsafe { bindings::regulator_is_enabled_regmap(self.rdev.as_ptr()) };
+ if ret < 0 {
+ return Err(Error::from_errno(ret));
+ }
+ Ok(ret > 0)
+ }
+
+ fn enable_regmap(&self) -> Result {
+ // SAFETY: The type invariants guarantee that `self.rdev` is valid and non-null,
+ // so it is safe to perform the FFI call.
+ to_result(unsafe { bindings::regulator_enable_regmap(self.rdev.as_ptr()) })
+ }
+
+ fn disable_regmap(&self) -> Result {
+ // SAFETY: The type invariants guarantee that `self.rdev` is valid and non-null,
+ // so it is safe to perform the FFI call.
+ to_result(unsafe { bindings::regulator_disable_regmap(self.rdev.as_ptr()) })
+ }
+
+ fn set_active_discharge_regmap(&self, enable: bool) -> Result {
+ // SAFETY: The type invariants guarantee that `self.rdev` is valid and non-null,
+ // so it is safe to perform the FFI call.
+ to_result(unsafe {
+ bindings::regulator_set_active_discharge_regmap(self.rdev.as_ptr(), enable)
+ })
+ }
+
+ fn set_current_limit_regmap(&self, min_ua: i32, max_ua: i32) -> Result {
+ // SAFETY: The type invariants guarantee that `self.rdev` is valid and non-null,
+ // so it is safe to perform the FFI call.
+ to_result(unsafe {
+ bindings::regulator_set_current_limit_regmap(self.rdev.as_ptr(), min_ua, max_ua)
+ })
+ }
+
+ fn get_current_limit_regmap(&self) -> Result<i32> {
+ // SAFETY: The type invariants guarantee that `self.rdev` is valid and non-null,
+ // so it is safe to perform the FFI call.
+ let ret = unsafe { bindings::regulator_get_current_limit_regmap(self.rdev.as_ptr()) };
+ if ret < 0 {
+ return Err(Error::from_errno(ret));
+ }
+ Ok(ret)
+ }
+}
+
/// [`Device`] type
pub enum Type {
/// Voltage regulator
--
2.45.2
next prev parent reply other threads:[~2024-12-18 23:37 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-18 23:36 [PATCH 0/9] Regulator driver with I2C/Regmap Rust abstractions Fabien Parent
2024-12-18 23:36 ` [PATCH 1/9] rust: i2c: add basic I2C client abstraction Fabien Parent
2024-12-19 13:03 ` Rob Herring
2024-12-19 15:33 ` Fabien Parent
2024-12-18 23:36 ` [PATCH 2/9] rust: add abstraction for regmap Fabien Parent
2024-12-20 13:16 ` Mark Brown
2024-12-18 23:36 ` [PATCH 3/9] rust: error: add declaration for ENOTRECOVERABLE error Fabien Parent
2024-12-18 23:36 ` [PATCH 4/9] rust: regulator: add abstraction for Regulator's modes Fabien Parent
2024-12-18 23:36 ` [PATCH 5/9] rust: regulator: add Regulator Driver abstraction Fabien Parent
2024-12-19 10:26 ` Danilo Krummrich
2024-12-19 16:00 ` Fabien Parent
2024-12-19 18:58 ` Mark Brown
2024-12-18 23:36 ` Fabien Parent [this message]
2024-12-18 23:36 ` [PATCH 7/9] dt-bindings: regulator: add binding for ncv6336 regulator Fabien Parent
2024-12-19 9:28 ` Krzysztof Kozlowski
2024-12-19 16:13 ` Fabien Parent
2024-12-21 20:20 ` Krzysztof Kozlowski
2024-12-18 23:36 ` [PATCH 8/9] regulator: add driver " Fabien Parent
2024-12-19 10:19 ` Dirk Behme
2024-12-20 14:50 ` Mark Brown
2024-12-18 23:36 ` [PATCH 9/9] arm64: dts: qcom: apq8039-t2: add node " Fabien Parent
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241218-ncv6336-v1-6-b8d973747f7a@gmail.com \
--to=parent.f@gmail.com \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=andersson@kernel.org \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=broonie@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=fabien.parent@linaro.org \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=konradybcio@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=lgirdwood@gmail.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ojeda@kernel.org \
--cc=rafael@kernel.org \
--cc=robh@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=saravanak@google.com \
--cc=tmgross@umich.edu \
--cc=vinod.koul@linaro.org \
--cc=wsa+renesas@sang-engineering.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox