summaryrefslogtreecommitdiff
path: root/rust/kernel/io
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2026-03-14 10:06:18 +0900
committerDanilo Krummrich <dakr@kernel.org>2026-03-17 20:04:11 +0100
commit9a52a8f5ed97d47c9641248874f4c6a78e136d97 (patch)
tree79fb6405ab453eafcd4e129e56c7840aa402377d /rust/kernel/io
parent20ba6a1dbcb957152f6d858015b3a3311dd6da49 (diff)
downloadlwn-9a52a8f5ed97d47c9641248874f4c6a78e136d97.tar.gz
lwn-9a52a8f5ed97d47c9641248874f4c6a78e136d97.zip
rust: io: introduce `write_reg` and `LocatedRegister`
Some I/O types, like fixed address registers, carry their location alongside their values. For these types, the regular `Io::write` method can lead into repeating the location information twice: once to provide the location itself, another time to build the value. We are also considering supporting making all register values carry their full location information for convenience and safety. Add a new `Io::write_reg` method that takes a single argument implementing `LocatedRegister`, a trait that decomposes implementors into a `(location, value)` tuple. This allows write operations on fixed offset registers to be done while specifying their name only once. Suggested-by: Danilo Krummrich <dakr@kernel.org> Link: https://lore.kernel.org/all/DH0XBLXZD81K.22SWIZ1ZAOW1@kernel.org/ Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Link: https://patch.msgid.link/20260314-register-v9-8-86805b2f7e9d@nvidia.com [ Replace FIFO with VERSION register in the examples. - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'rust/kernel/io')
-rw-r--r--rust/kernel/io/register.rs35
1 files changed, 33 insertions, 2 deletions
diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs
index dbd458aaa761..abc49926abfe 100644
--- a/rust/kernel/io/register.rs
+++ b/rust/kernel/io/register.rs
@@ -80,10 +80,10 @@
//! .with_const_minor_revision::<10>()
//! // Runtime value.
//! .with_vendor_id(obtain_vendor_id());
-//! io.write((), new_boot0);
+//! io.write_reg(new_boot0);
//!
//! // Or, build a new value from zero and write it:
-//! io.write((), BOOT_0::zeroed()
+//! io.write_reg(BOOT_0::zeroed()
//! .with_const_major_revision::<3>()
//! .with_const_minor_revision::<10>()
//! .with_vendor_id(obtain_vendor_id())
@@ -382,6 +382,34 @@ where
}
}
+/// Trait implemented by items that contain both a register value and the absolute I/O location at
+/// which to write it.
+///
+/// Implementors can be used with [`Io::write_reg`](super::Io::write_reg).
+pub trait LocatedRegister {
+ /// Register value to write.
+ type Value: Register;
+ /// Full location information at which to write the value.
+ type Location: IoLoc<Self::Value>;
+
+ /// Consumes `self` and returns a `(location, value)` tuple describing a valid I/O write
+ /// operation.
+ fn into_io_op(self) -> (Self::Location, Self::Value);
+}
+
+impl<T> LocatedRegister for T
+where
+ T: FixedRegister,
+{
+ type Location = FixedRegisterLoc<Self::Value>;
+ type Value = T;
+
+ #[inline(always)]
+ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {
+ (FixedRegisterLoc::new(), self)
+ }
+}
+
/// Defines a dedicated type for a register, including getter and setter methods for its fields and
/// methods to read and write it from an [`Io`](kernel::io::Io) region.
///
@@ -436,6 +464,9 @@ where
/// // The location of fixed offset registers is already contained in their type. Thus, the
/// // `location` argument of `Io::write` is technically redundant and can be replaced by `()`.
/// io.write((), val2);
+///
+/// // Or, the single-argument `Io::write_reg` can be used.
+/// io.write_reg(val2);
/// # }
///
/// ```