Skip to content

Commit 2e0fd45

Browse files
danielalmeida-collaborabroonie
authored andcommitted
rust: regulator: add devm_enable and devm_enable_optional
A lot of drivers only care about enabling the regulator for as long as the underlying Device is bound. This can be easily observed due to the extensive use of `devm_regulator_get_enable` and `devm_regulator_get_enable_optional` throughout the kernel. Therefore, make this helper available in Rust. Also add an example noting how it should be the default API unless the driver needs more fine-grained control over the regulator. Suggested-by: Danilo Krummrich <dakr@kernel.org> Reviewed-by: Boqun Feng <boqun.feng@gmail.com> Reviewed-by: Danilo Krummrich <dakr@kernel.org> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com> Link: https://patch.msgid.link/20250910-regulator-remove-dynamic-v3-2-07af4dfa97cc@collabora.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent b87ecbc commit 2e0fd45

2 files changed

Lines changed: 69 additions & 1 deletion

File tree

rust/helpers/regulator.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,14 @@ int rust_helper_regulator_is_enabled(struct regulator *regulator)
4040
return regulator_is_enabled(regulator);
4141
}
4242

43+
int rust_helper_devm_regulator_get_enable(struct device *dev, const char *id)
44+
{
45+
return devm_regulator_get_enable(dev, id);
46+
}
47+
48+
int rust_helper_devm_regulator_get_enable_optional(struct device *dev, const char *id)
49+
{
50+
return devm_regulator_get_enable_optional(dev, id);
51+
}
52+
4353
#endif

rust/kernel/regulator.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
1919
use crate::{
2020
bindings,
21-
device::Device,
21+
device::{Bound, Device},
2222
error::{from_err_ptr, to_result, Result},
2323
prelude::*,
2424
};
@@ -69,6 +69,41 @@ pub struct Error<State: RegulatorState> {
6969
/// The regulator that caused the error, so that the operation may be retried.
7070
pub regulator: Regulator<State>,
7171
}
72+
/// Obtains and enables a [`devres`]-managed regulator for a device.
73+
///
74+
/// This calls [`regulator_disable()`] and [`regulator_put()`] automatically on
75+
/// driver detach.
76+
///
77+
/// This API is identical to `devm_regulator_get_enable()`, and should be
78+
/// preferred over the [`Regulator<T: RegulatorState>`] API if the caller only
79+
/// cares about the regulator being enabled.
80+
///
81+
/// [`devres`]: https://docs.kernel.org/driver-api/driver-model/devres.html
82+
/// [`regulator_disable()`]: https://docs.kernel.org/driver-api/regulator.html#c.regulator_disable
83+
/// [`regulator_put()`]: https://docs.kernel.org/driver-api/regulator.html#c.regulator_put
84+
pub fn devm_enable(dev: &Device<Bound>, name: &CStr) -> Result {
85+
// SAFETY: `dev` is a valid and bound device, while `name` is a valid C
86+
// string.
87+
to_result(unsafe { bindings::devm_regulator_get_enable(dev.as_raw(), name.as_ptr()) })
88+
}
89+
90+
/// Same as [`devm_enable`], but calls `devm_regulator_get_enable_optional`
91+
/// instead.
92+
///
93+
/// This obtains and enables a [`devres`]-managed regulator for a device, but
94+
/// does not print a message nor provides a dummy if the regulator is not found.
95+
///
96+
/// This calls [`regulator_disable()`] and [`regulator_put()`] automatically on
97+
/// driver detach.
98+
///
99+
/// [`devres`]: https://docs.kernel.org/driver-api/driver-model/devres.html
100+
/// [`regulator_disable()`]: https://docs.kernel.org/driver-api/regulator.html#c.regulator_disable
101+
/// [`regulator_put()`]: https://docs.kernel.org/driver-api/regulator.html#c.regulator_put
102+
pub fn devm_enable_optional(dev: &Device<Bound>, name: &CStr) -> Result {
103+
// SAFETY: `dev` is a valid and bound device, while `name` is a valid C
104+
// string.
105+
to_result(unsafe { bindings::devm_regulator_get_enable_optional(dev.as_raw(), name.as_ptr()) })
106+
}
72107

73108
/// A `struct regulator` abstraction.
74109
///
@@ -146,6 +181,29 @@ pub struct Error<State: RegulatorState> {
146181
/// }
147182
/// ```
148183
///
184+
/// If a driver only cares about the regulator being on for as long it is bound
185+
/// to a device, then it should use [`devm_enable`] or [`devm_enable_optional`].
186+
/// This should be the default use-case unless more fine-grained control over
187+
/// the regulator's state is required.
188+
///
189+
/// [`devm_enable`]: crate::regulator::devm_enable
190+
/// [`devm_optional`]: crate::regulator::devm_enable_optional
191+
///
192+
/// ```
193+
/// # use kernel::prelude::*;
194+
/// # use kernel::c_str;
195+
/// # use kernel::device::{Bound, Device};
196+
/// # use kernel::regulator;
197+
/// fn enable(dev: &Device<Bound>) -> Result {
198+
/// // Obtain a reference to a (fictitious) regulator and enable it. This
199+
/// // call only returns whether the operation succeeded.
200+
/// regulator::devm_enable(dev, c_str!("vcc"))?;
201+
///
202+
/// // The regulator will be disabled and put when `dev` is unbound.
203+
/// Ok(())
204+
/// }
205+
/// ```
206+
///
149207
/// ## Disabling a regulator
150208
///
151209
/// ```

0 commit comments

Comments
 (0)