Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Daniel Almeida and committed by
Mark Brown
2e0fd458 b87ecbc5

+69 -1
+10
rust/helpers/regulator.c
··· 40 40 return regulator_is_enabled(regulator); 41 41 } 42 42 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 + 43 53 #endif
+59 -1
rust/kernel/regulator.rs
··· 18 18 19 19 use crate::{ 20 20 bindings, 21 - device::Device, 21 + device::{Bound, Device}, 22 22 error::{from_err_ptr, to_result, Result}, 23 23 prelude::*, 24 24 }; ··· 68 68 69 69 /// The regulator that caused the error, so that the operation may be retried. 70 70 pub regulator: Regulator<State>, 71 + } 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()) }) 71 106 } 72 107 73 108 /// A `struct regulator` abstraction. ··· 177 142 /// 178 143 /// // ... 179 144 /// 145 + /// Ok(()) 146 + /// } 147 + /// ``` 148 + /// 149 + /// If a driver only cares about the regulator being on for as long it is bound 150 + /// to a device, then it should use [`devm_enable`] or [`devm_enable_optional`]. 151 + /// This should be the default use-case unless more fine-grained control over 152 + /// the regulator's state is required. 153 + /// 154 + /// [`devm_enable`]: crate::regulator::devm_enable 155 + /// [`devm_optional`]: crate::regulator::devm_enable_optional 156 + /// 157 + /// ``` 158 + /// # use kernel::prelude::*; 159 + /// # use kernel::c_str; 160 + /// # use kernel::device::{Bound, Device}; 161 + /// # use kernel::regulator; 162 + /// fn enable(dev: &Device<Bound>) -> Result { 163 + /// // Obtain a reference to a (fictitious) regulator and enable it. This 164 + /// // call only returns whether the operation succeeded. 165 + /// regulator::devm_enable(dev, c_str!("vcc"))?; 166 + /// 167 + /// // The regulator will be disabled and put when `dev` is unbound. 180 168 /// Ok(()) 181 169 /// } 182 170 /// ```