drivers/gpu/nova-core/falcon.rs | 249 +++---- drivers/gpu/nova-core/falcon/gsp.rs | 23 +- drivers/gpu/nova-core/falcon/hal/ga102.rs | 65 +- drivers/gpu/nova-core/falcon/hal/tu102.rs | 11 +- drivers/gpu/nova-core/falcon/sec2.rs | 17 +- drivers/gpu/nova-core/fb.rs | 6 +- drivers/gpu/nova-core/fb/hal/ga100.rs | 40 +- drivers/gpu/nova-core/fb/hal/ga102.rs | 7 +- drivers/gpu/nova-core/fb/hal/tu102.rs | 22 +- drivers/gpu/nova-core/gfw.rs | 11 +- drivers/gpu/nova-core/gpu.rs | 36 +- drivers/gpu/nova-core/gsp/boot.rs | 11 +- drivers/gpu/nova-core/gsp/cmdq.rs | 10 +- drivers/gpu/nova-core/regs.rs | 544 ++++++++------ drivers/gpu/nova-core/regs/macros.rs | 739 ------------------- rust/kernel/io.rs | 347 +++++++-- rust/kernel/io/register.rs | 1135 +++++++++++++++++++++++++++++ rust/kernel/lib.rs | 3 + rust/kernel/num/bounded.rs | 70 +- samples/rust/rust_driver_pci.rs | 84 ++- scripts/Makefile.build | 3 +- 21 files changed, 2118 insertions(+), 1315 deletions(-)
New revision addressing the v6 feedback - the use of "location" instead
of "reference" in particular reads well both in the code and the
comments.
As a reminder, since the previous revision we use the I/O type to
perform the actual I/O instead of the register type, which moves us from
this access pattern:
let boot0 = regs::NV_PMC_BOOT_0::read(bar);
to this arguably more natural one:
let boot0 = bar.read(regs::NV_PMC_BOOT_0);
This revision is based on `driver-core-testing` as of 2026-02-24 with
[1] applied. A tree with this series and its dependencies is available
at [2].
[1] https://lore.kernel.org/all/20260206-io-v2-0-71dea20a06e6@nvidia.com/
[2] https://github.com/Gnurou/linux/tree/b4/register
The first patch enables the `generic_arg_infer` feature, which is
required for generic type inference and used in subsequent patches. This
feature is stable since rustc 1.89.
The second patch adds `shr` and `shl` methods to `Bounded`. These were
suggested by Alice during LPC as a way to avoid the use of the
controversial `Bounded::from_expr` in both the bitfield macro and the
Nova code. The third patch adds another convenience method to obtain a
`bool` from single-bit `Bounded`s, while the fourth patch turns
`Bounded::get` into a const method in order to make register setter
methods const.
Patches 5 and 6 introduce the `IoLoc` and `IoWrite` types around which
I/O accesses are centered. This allows registers to be accessed using
the same `read` and `write` methods as primitive types.
Patch 7 adds the `register!` macro and the types it requires.
Patch 8 updates the Rust PCI sample driver to use `register!`, as per
its TODO item.
Patch 9 illustrates more extensively how this macro is used by
converting nova-core to use it, and removing the local implementation.
This patch is to be merged one cycle after the other patches.
Patch 10 is an RFC allowing a shorter write syntax to be used in the
case of fixed or relative registers. It doesn't need to be merged
immediately, but I think it is a good time to discuss it.
I have also removed Gary's signoff on patches 5 and 7 to make sure it
doesn't get merged before he gives it explicitly.
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
Changes in v7:
- Use `RES + SHIFT >= N` instead of `RES >= N - SHIFT` in
`Bounded::shr`.
- Rename `IoRef` to `IoLoc` and all related types
accordingly.
- Use `Into` trait bounds in both directions on `IoLoc`.
- Add RFC patch allowing fixed register values to be used directly with
`write`.
- Link to v6: https://patch.msgid.link/20260216-register-v6-0-eec9a4de9e9e@nvidia.com
Changes in v6:
- Remove Tested-by tags as the code has considerably changed.
- Make `Bounded::get` const so it can be used with registers.
- Use the `pin_init::zeroed()` const function instead of defining our
own method.
- Generalize all `Io` around the new `IoRef` and `IoWrite` types, and
make registers use these as well.
- Use the more natural pattern of having the `Io` type perform the I/O
access instead of the register type.
- Convert the whole PCI driver example, and not only the PCI
configuration space.
- Rename `Bounded::as_bool` to `Bounded::into_bool`.
- Drop `Bounded::into_inner` in favor of making `Bounded::get` const.
- Link to v5: https://patch.msgid.link/20260129-register-v5-0-c4587c902514@nvidia.com
Changes in v5:
- Rename all setters to `with_*` and `with_const_*`.
- Use `, stride = ` to specify the stride of register arrays.
- Remove `Deref` requirement on the `RegisterIo` trait and make it
`#[doc(hidden)`.
- Simplify the top dispatch rule a bit.
- Link to v4: https://patch.msgid.link/20260128-register-v4-0-aee3a33d9649@nvidia.com
Changes in v4:
- Add `with_` const field setter methods (removing the need to call
`Bounded::new` for constant field values).
- Add `into_inner` const method for `Bounded`.
- Add `from_raw` and const `zeroed` method to create initial register
values.
- More documentation improvements.
- Link to v3: https://patch.msgid.link/20260126-register-v3-0-2328a59d7312@nvidia.com
Changes in v3:
- Sort the Rust features list alphabetically.
- Rebase on top of latest `driver-core-next` including the new Io trait.
- Allow several registers to be defined from the same macro invocation.
- Remove references to `bitfield!` macro.
- Fix doccomment of `shr` and `shl`.
- Use `+` syntax for relative register offsets.
- Move register arrays size and stride to after the backing type declaration.
- Use regular doccomments to document registers and fields (thanks Gary!).
- Remove `Default` implementation and implement the more predictable
`Zeroable` instead.
- Improve doccomments a bit.
- Link to v2: https://patch.msgid.link/20260121-register-v2-0-79d9b8d5e36a@nvidia.com
Changes in v2:
- Remove `bitfield!` and put its rules into `register!` to give it more
time to get reviewed.
- Allow output type larger than strictly required for `shr` and `shl` on
`Bounded`.
- Enable the `generic_arg_infer` feature, required for rustc < 1.89.
- Link to v1: https://patch.msgid.link/20260120-register-v1-0-723a1743b557@nvidia.com
---
Alexandre Courbot (10):
rust: enable the `generic_arg_infer` feature
rust: num: add `shr` and `shl` methods to `Bounded`
rust: num: add `into_bool` method to `Bounded`
rust: num: make Bounded::get const
rust: io: add IoLoc and IoWrite types
rust: io: use generic read/write accessors for primitive accesses
rust: io: add `register!` macro
sample: rust: pci: use `register!` macro
[FOR REFERENCE] gpu: nova-core: use the kernel `register!` macro
RFC: rust: io: allow fixed register values directly in `write`
drivers/gpu/nova-core/falcon.rs | 249 +++----
drivers/gpu/nova-core/falcon/gsp.rs | 23 +-
drivers/gpu/nova-core/falcon/hal/ga102.rs | 65 +-
drivers/gpu/nova-core/falcon/hal/tu102.rs | 11 +-
drivers/gpu/nova-core/falcon/sec2.rs | 17 +-
drivers/gpu/nova-core/fb.rs | 6 +-
drivers/gpu/nova-core/fb/hal/ga100.rs | 40 +-
drivers/gpu/nova-core/fb/hal/ga102.rs | 7 +-
drivers/gpu/nova-core/fb/hal/tu102.rs | 22 +-
drivers/gpu/nova-core/gfw.rs | 11 +-
drivers/gpu/nova-core/gpu.rs | 36 +-
drivers/gpu/nova-core/gsp/boot.rs | 11 +-
drivers/gpu/nova-core/gsp/cmdq.rs | 10 +-
drivers/gpu/nova-core/regs.rs | 544 ++++++++------
drivers/gpu/nova-core/regs/macros.rs | 739 -------------------
rust/kernel/io.rs | 347 +++++++--
rust/kernel/io/register.rs | 1135 +++++++++++++++++++++++++++++
rust/kernel/lib.rs | 3 +
rust/kernel/num/bounded.rs | 70 +-
samples/rust/rust_driver_pci.rs | 84 ++-
scripts/Makefile.build | 3 +-
21 files changed, 2118 insertions(+), 1315 deletions(-)
---
base-commit: 545225ee0b0b6998c7b6ff888f8497681b8b35c4
change-id: 20260117-register-ccaba1d21713
Best regards,
--
Alexandre Courbot <acourbot@nvidia.com>
On 24.02.2026 15:21, Alexandre Courbot wrote:
> New revision addressing the v6 feedback - the use of "location" instead
> of "reference" in particular reads well both in the code and the
> comments.
>
> As a reminder, since the previous revision we use the I/O type to
> perform the actual I/O instead of the register type, which moves us from
> this access pattern:
>
> let boot0 = regs::NV_PMC_BOOT_0::read(bar);
>
> to this arguably more natural one:
>
> let boot0 = bar.read(regs::NV_PMC_BOOT_0);
>
> This revision is based on `driver-core-testing` as of 2026-02-24 with
> [1] applied. A tree with this series and its dependencies is available
> at [2].
>
> [1] https://lore.kernel.org/all/20260206-io-v2-0-71dea20a06e6@nvidia.com/
> [2] https://github.com/Gnurou/linux/tree/b4/register
>
> The first patch enables the `generic_arg_infer` feature, which is
> required for generic type inference and used in subsequent patches. This
> feature is stable since rustc 1.89.
>
> The second patch adds `shr` and `shl` methods to `Bounded`. These were
> suggested by Alice during LPC as a way to avoid the use of the
> controversial `Bounded::from_expr` in both the bitfield macro and the
> Nova code. The third patch adds another convenience method to obtain a
> `bool` from single-bit `Bounded`s, while the fourth patch turns
> `Bounded::get` into a const method in order to make register setter
> methods const.
>
> Patches 5 and 6 introduce the `IoLoc` and `IoWrite` types around which
> I/O accesses are centered. This allows registers to be accessed using
> the same `read` and `write` methods as primitive types.
>
> Patch 7 adds the `register!` macro and the types it requires.
>
> Patch 8 updates the Rust PCI sample driver to use `register!`, as per
> its TODO item.
>
> Patch 9 illustrates more extensively how this macro is used by
> converting nova-core to use it, and removing the local implementation.
> This patch is to be merged one cycle after the other patches.
>
> Patch 10 is an RFC allowing a shorter write syntax to be used in the
> case of fixed or relative registers. It doesn't need to be merged
> immediately, but I think it is a good time to discuss it.
>
> I have also removed Gary's signoff on patches 5 and 7 to make sure it
> doesn't get merged before he gives it explicitly.
>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
>
> ---
> Changes in v7:
> - Use `RES + SHIFT >= N` instead of `RES >= N - SHIFT` in
> `Bounded::shr`.
> - Rename `IoRef` to `IoLoc` and all related types
> accordingly.
> - Use `Into` trait bounds in both directions on `IoLoc`.
> - Add RFC patch allowing fixed register values to be used directly with
> `write`.
> - Link to v6: https://patch.msgid.link/20260216-register-v6-0-eec9a4de9e9e@nvidia.com
>
> Changes in v6:
> - Remove Tested-by tags as the code has considerably changed.
> - Make `Bounded::get` const so it can be used with registers.
> - Use the `pin_init::zeroed()` const function instead of defining our
> own method.
> - Generalize all `Io` around the new `IoRef` and `IoWrite` types, and
> make registers use these as well.
> - Use the more natural pattern of having the `Io` type perform the I/O
> access instead of the register type.
> - Convert the whole PCI driver example, and not only the PCI
> configuration space.
> - Rename `Bounded::as_bool` to `Bounded::into_bool`.
> - Drop `Bounded::into_inner` in favor of making `Bounded::get` const.
> - Link to v5: https://patch.msgid.link/20260129-register-v5-0-c4587c902514@nvidia.com
>
> Changes in v5:
> - Rename all setters to `with_*` and `with_const_*`.
> - Use `, stride = ` to specify the stride of register arrays.
> - Remove `Deref` requirement on the `RegisterIo` trait and make it
> `#[doc(hidden)`.
> - Simplify the top dispatch rule a bit.
> - Link to v4: https://patch.msgid.link/20260128-register-v4-0-aee3a33d9649@nvidia.com
>
> Changes in v4:
> - Add `with_` const field setter methods (removing the need to call
> `Bounded::new` for constant field values).
> - Add `into_inner` const method for `Bounded`.
> - Add `from_raw` and const `zeroed` method to create initial register
> values.
> - More documentation improvements.
> - Link to v3: https://patch.msgid.link/20260126-register-v3-0-2328a59d7312@nvidia.com
>
> Changes in v3:
> - Sort the Rust features list alphabetically.
> - Rebase on top of latest `driver-core-next` including the new Io trait.
> - Allow several registers to be defined from the same macro invocation.
> - Remove references to `bitfield!` macro.
> - Fix doccomment of `shr` and `shl`.
> - Use `+` syntax for relative register offsets.
> - Move register arrays size and stride to after the backing type declaration.
> - Use regular doccomments to document registers and fields (thanks Gary!).
> - Remove `Default` implementation and implement the more predictable
> `Zeroable` instead.
> - Improve doccomments a bit.
> - Link to v2: https://patch.msgid.link/20260121-register-v2-0-79d9b8d5e36a@nvidia.com
>
> Changes in v2:
> - Remove `bitfield!` and put its rules into `register!` to give it more
> time to get reviewed.
> - Allow output type larger than strictly required for `shr` and `shl` on
> `Bounded`.
> - Enable the `generic_arg_infer` feature, required for rustc < 1.89.
> - Link to v1: https://patch.msgid.link/20260120-register-v1-0-723a1743b557@nvidia.com
>
> ---
> Alexandre Courbot (10):
> rust: enable the `generic_arg_infer` feature
> rust: num: add `shr` and `shl` methods to `Bounded`
> rust: num: add `into_bool` method to `Bounded`
> rust: num: make Bounded::get const
> rust: io: add IoLoc and IoWrite types
> rust: io: use generic read/write accessors for primitive accesses
> rust: io: add `register!` macro
> sample: rust: pci: use `register!` macro
> [FOR REFERENCE] gpu: nova-core: use the kernel `register!` macro
> RFC: rust: io: allow fixed register values directly in `write`
>
> drivers/gpu/nova-core/falcon.rs | 249 +++----
> drivers/gpu/nova-core/falcon/gsp.rs | 23 +-
> drivers/gpu/nova-core/falcon/hal/ga102.rs | 65 +-
> drivers/gpu/nova-core/falcon/hal/tu102.rs | 11 +-
> drivers/gpu/nova-core/falcon/sec2.rs | 17 +-
> drivers/gpu/nova-core/fb.rs | 6 +-
> drivers/gpu/nova-core/fb/hal/ga100.rs | 40 +-
> drivers/gpu/nova-core/fb/hal/ga102.rs | 7 +-
> drivers/gpu/nova-core/fb/hal/tu102.rs | 22 +-
> drivers/gpu/nova-core/gfw.rs | 11 +-
> drivers/gpu/nova-core/gpu.rs | 36 +-
> drivers/gpu/nova-core/gsp/boot.rs | 11 +-
> drivers/gpu/nova-core/gsp/cmdq.rs | 10 +-
> drivers/gpu/nova-core/regs.rs | 544 ++++++++------
> drivers/gpu/nova-core/regs/macros.rs | 739 -------------------
> rust/kernel/io.rs | 347 +++++++--
> rust/kernel/io/register.rs | 1135 +++++++++++++++++++++++++++++
> rust/kernel/lib.rs | 3 +
> rust/kernel/num/bounded.rs | 70 +-
> samples/rust/rust_driver_pci.rs | 84 ++-
> scripts/Makefile.build | 3 +-
> 21 files changed, 2118 insertions(+), 1315 deletions(-)
> ---
> base-commit: 545225ee0b0b6998c7b6ff888f8497681b8b35c4
> change-id: 20260117-register-ccaba1d21713
I converted my simple aarch64 TMU timer example [1] over to v7 (many
thanks helping with that!) and gave it a try: It works like with v2.
With that:
Tested-by: Dirk Behme <dirk.behme@de.bosch.com>
Thanks
Dirk
[1]
// SPDX-License-Identifier: GPL-2.0
//! Rust Renesas TMU driver.
use kernel::{
c_str,
device::{Core, Device, Bound},
devres::Devres,
io::{Io, IoCapable, IoKnownSize, mem::IoMem},
irq::{self, Flags, IrqReturn, Registration},
of, platform,
prelude::*,
register,
sync::Arc,
types::ARef,
};
use core::ops::Deref;
use core::sync::atomic::{AtomicU32, Ordering};
struct RenesasTMUDriver {
pdev: ARef<platform::Device>,
_registration: Arc<Registration<Data>>,
_iomem: Arc<Devres<IoMem<TMU_MMIO_SIZE>>>,
}
struct Info;
kernel::of_device_table!(
OF_TABLE,
MODULE_OF_TABLE,
<RenesasTMUDriver as platform::Driver>::IdInfo,
[(of::DeviceId::new(c_str!("renesas,tmu")), Info)]
);
register! {
TSTR(u8) @ 0x04 {
2:2 str2;
1:1 str1;
0:0 str0;
}
TSTRRAW(u8) => TSTR {
7:0 value;
}
TCOR(u32) @ 0x08 {
31:0 tcor;
}
TCNT(u32) @ 0x0C {
31:0 tcnt;
}
TCR(u16) @ 0x10 {
9:9 icpf;
8:8 unf;
7:6 icpe;
5:5 unie;
4:3 ckeg;
2:0 tpsc;
}
TCRRAW(u16) => TCR {
15:0 value;
}
}
impl TCR {
fn handle_underflow<T>(io: &T)
where
T: Io + IoKnownSize + IoCapable<u16>,
{
let tcr: TCR = io.read(TCR);
if tcr.unf().into_bool() {
io.write(tcr.with_unf(false));
}
}
}
const TMU_MMIO_SIZE: usize = 0x14;
// Data shared between process and IRQ context.
#[pin_data]
struct Data {
#[pin]
iomem: Arc<Devres<IoMem<TMU_MMIO_SIZE>>>,
#[pin]
irq_count: AtomicU32,
}
impl irq::Handler for Data {
// Executed in IRQ context.
fn handle(&self, dev: &Device<Bound>) -> IrqReturn {
let count = self.irq_count.fetch_add(1, Ordering::Relaxed);
dev_info!(dev, "Renesas TMU IRQ handler called {} time(s).\n",
count);
// Reset the underflow flag
let io = self.iomem.access(dev).unwrap();
TCR::handle_underflow(io.deref());
IrqReturn::Handled
}
}
impl platform::Driver for RenesasTMUDriver {
type IdInfo = Info;
const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
fn probe(
pdev: &platform::Device<Core>,
_info: Option<&Self::IdInfo>,
) -> impl PinInit<Self, Error> {
let dev = pdev.as_ref();
dev_dbg!(dev, "Probe Rust Renesas TMU driver.\n");
let request = pdev.io_request_by_index(0).ok_or(EINVAL)?;
let iomem =
Arc::pin_init(request.iomap_sized::<TMU_MMIO_SIZE>(), GFP_KERNEL)?;
let io = iomem.access(dev)?;
// Set count to 1 minute. Clock is 16.66MHz / 4 = 4.165MHz
let timeout: u32 = 4165000 * 60; // 1 minute in clock ticks
io.update(TCOR, |r| r.with_tcor(timeout));
io.update(TCNT, |r| r.with_tcnt(timeout));
// Enable underflow interrupt (UNIE, Underflow Interrupt Control)
io.update(TCR, |r| r.with_unie(true));
let request = pdev.irq_by_index(0)?;
dev_info!(dev, "IRQ: {}\n", request.irq());
let clone = iomem.clone();
let handler = try_pin_init!(Data{iomem: clone, irq_count:
AtomicU32::new(1)});
let registration = irq::Registration::new(request,
Flags::SHARED, c_str!("tmu"), handler);
let registration = Arc::pin_init(registration, GFP_KERNEL)?;
// Enable TMU
io.update(TSTR, |r| r.with_str0(true));
// Read back registers to verify
dev_info!(dev, "TSTR: 0x{:x}\n", io.read(TSTRRAW).value());
dev_info!(dev, "TCOR: 0x{:x}\n", io.read(TCOR).tcor());
dev_info!(dev, "TCNT: 0x{:x}\n", io.read(TCNT).tcnt());
dev_info!(dev, "TCR: 0x{:x}\n", io.read(TCRRAW).value());
dev_info!(dev, "probe done\n");
Ok(Self {
pdev: pdev.into(),
_registration: registration,
_iomem: iomem.clone(),
})
}
}
impl Drop for RenesasTMUDriver {
fn drop(&mut self) {
dev_dbg!(self.pdev.as_ref(), "Remove Rust Renesas TMU driver.\n");
}
}
kernel::module_platform_driver! {
type: RenesasTMUDriver,
name: "rust_tmu",
authors: ["Dirk Behme"],
description: "Rust Renesas TMU driver",
license: "GPL v2",
}
On Wed Feb 25, 2026 at 8:58 PM JST, Dirk Behme wrote: > On 24.02.2026 15:21, Alexandre Courbot wrote: >> New revision addressing the v6 feedback - the use of "location" instead >> of "reference" in particular reads well both in the code and the >> comments. >> >> As a reminder, since the previous revision we use the I/O type to >> perform the actual I/O instead of the register type, which moves us from >> this access pattern: >> >> let boot0 = regs::NV_PMC_BOOT_0::read(bar); >> >> to this arguably more natural one: >> >> let boot0 = bar.read(regs::NV_PMC_BOOT_0); >> >> This revision is based on `driver-core-testing` as of 2026-02-24 with >> [1] applied. A tree with this series and its dependencies is available >> at [2]. >> >> [1] https://lore.kernel.org/all/20260206-io-v2-0-71dea20a06e6@nvidia.com/ >> [2] https://github.com/Gnurou/linux/tree/b4/register >> >> The first patch enables the `generic_arg_infer` feature, which is >> required for generic type inference and used in subsequent patches. This >> feature is stable since rustc 1.89. >> >> The second patch adds `shr` and `shl` methods to `Bounded`. These were >> suggested by Alice during LPC as a way to avoid the use of the >> controversial `Bounded::from_expr` in both the bitfield macro and the >> Nova code. The third patch adds another convenience method to obtain a >> `bool` from single-bit `Bounded`s, while the fourth patch turns >> `Bounded::get` into a const method in order to make register setter >> methods const. >> >> Patches 5 and 6 introduce the `IoLoc` and `IoWrite` types around which >> I/O accesses are centered. This allows registers to be accessed using >> the same `read` and `write` methods as primitive types. >> >> Patch 7 adds the `register!` macro and the types it requires. >> >> Patch 8 updates the Rust PCI sample driver to use `register!`, as per >> its TODO item. >> >> Patch 9 illustrates more extensively how this macro is used by >> converting nova-core to use it, and removing the local implementation. >> This patch is to be merged one cycle after the other patches. >> >> Patch 10 is an RFC allowing a shorter write syntax to be used in the >> case of fixed or relative registers. It doesn't need to be merged >> immediately, but I think it is a good time to discuss it. >> >> I have also removed Gary's signoff on patches 5 and 7 to make sure it >> doesn't get merged before he gives it explicitly. >> >> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> >> >> --- >> Changes in v7: >> - Use `RES + SHIFT >= N` instead of `RES >= N - SHIFT` in >> `Bounded::shr`. >> - Rename `IoRef` to `IoLoc` and all related types >> accordingly. >> - Use `Into` trait bounds in both directions on `IoLoc`. >> - Add RFC patch allowing fixed register values to be used directly with >> `write`. >> - Link to v6: https://patch.msgid.link/20260216-register-v6-0-eec9a4de9e9e@nvidia.com >> >> Changes in v6: >> - Remove Tested-by tags as the code has considerably changed. >> - Make `Bounded::get` const so it can be used with registers. >> - Use the `pin_init::zeroed()` const function instead of defining our >> own method. >> - Generalize all `Io` around the new `IoRef` and `IoWrite` types, and >> make registers use these as well. >> - Use the more natural pattern of having the `Io` type perform the I/O >> access instead of the register type. >> - Convert the whole PCI driver example, and not only the PCI >> configuration space. >> - Rename `Bounded::as_bool` to `Bounded::into_bool`. >> - Drop `Bounded::into_inner` in favor of making `Bounded::get` const. >> - Link to v5: https://patch.msgid.link/20260129-register-v5-0-c4587c902514@nvidia.com >> >> Changes in v5: >> - Rename all setters to `with_*` and `with_const_*`. >> - Use `, stride = ` to specify the stride of register arrays. >> - Remove `Deref` requirement on the `RegisterIo` trait and make it >> `#[doc(hidden)`. >> - Simplify the top dispatch rule a bit. >> - Link to v4: https://patch.msgid.link/20260128-register-v4-0-aee3a33d9649@nvidia.com >> >> Changes in v4: >> - Add `with_` const field setter methods (removing the need to call >> `Bounded::new` for constant field values). >> - Add `into_inner` const method for `Bounded`. >> - Add `from_raw` and const `zeroed` method to create initial register >> values. >> - More documentation improvements. >> - Link to v3: https://patch.msgid.link/20260126-register-v3-0-2328a59d7312@nvidia.com >> >> Changes in v3: >> - Sort the Rust features list alphabetically. >> - Rebase on top of latest `driver-core-next` including the new Io trait. >> - Allow several registers to be defined from the same macro invocation. >> - Remove references to `bitfield!` macro. >> - Fix doccomment of `shr` and `shl`. >> - Use `+` syntax for relative register offsets. >> - Move register arrays size and stride to after the backing type declaration. >> - Use regular doccomments to document registers and fields (thanks Gary!). >> - Remove `Default` implementation and implement the more predictable >> `Zeroable` instead. >> - Improve doccomments a bit. >> - Link to v2: https://patch.msgid.link/20260121-register-v2-0-79d9b8d5e36a@nvidia.com >> >> Changes in v2: >> - Remove `bitfield!` and put its rules into `register!` to give it more >> time to get reviewed. >> - Allow output type larger than strictly required for `shr` and `shl` on >> `Bounded`. >> - Enable the `generic_arg_infer` feature, required for rustc < 1.89. >> - Link to v1: https://patch.msgid.link/20260120-register-v1-0-723a1743b557@nvidia.com >> >> --- >> Alexandre Courbot (10): >> rust: enable the `generic_arg_infer` feature >> rust: num: add `shr` and `shl` methods to `Bounded` >> rust: num: add `into_bool` method to `Bounded` >> rust: num: make Bounded::get const >> rust: io: add IoLoc and IoWrite types >> rust: io: use generic read/write accessors for primitive accesses >> rust: io: add `register!` macro >> sample: rust: pci: use `register!` macro >> [FOR REFERENCE] gpu: nova-core: use the kernel `register!` macro >> RFC: rust: io: allow fixed register values directly in `write` >> >> drivers/gpu/nova-core/falcon.rs | 249 +++---- >> drivers/gpu/nova-core/falcon/gsp.rs | 23 +- >> drivers/gpu/nova-core/falcon/hal/ga102.rs | 65 +- >> drivers/gpu/nova-core/falcon/hal/tu102.rs | 11 +- >> drivers/gpu/nova-core/falcon/sec2.rs | 17 +- >> drivers/gpu/nova-core/fb.rs | 6 +- >> drivers/gpu/nova-core/fb/hal/ga100.rs | 40 +- >> drivers/gpu/nova-core/fb/hal/ga102.rs | 7 +- >> drivers/gpu/nova-core/fb/hal/tu102.rs | 22 +- >> drivers/gpu/nova-core/gfw.rs | 11 +- >> drivers/gpu/nova-core/gpu.rs | 36 +- >> drivers/gpu/nova-core/gsp/boot.rs | 11 +- >> drivers/gpu/nova-core/gsp/cmdq.rs | 10 +- >> drivers/gpu/nova-core/regs.rs | 544 ++++++++------ >> drivers/gpu/nova-core/regs/macros.rs | 739 ------------------- >> rust/kernel/io.rs | 347 +++++++-- >> rust/kernel/io/register.rs | 1135 +++++++++++++++++++++++++++++ >> rust/kernel/lib.rs | 3 + >> rust/kernel/num/bounded.rs | 70 +- >> samples/rust/rust_driver_pci.rs | 84 ++- >> scripts/Makefile.build | 3 +- >> 21 files changed, 2118 insertions(+), 1315 deletions(-) >> --- >> base-commit: 545225ee0b0b6998c7b6ff888f8497681b8b35c4 >> change-id: 20260117-register-ccaba1d21713 > > > I converted my simple aarch64 TMU timer example [1] over to v7 (many > thanks helping with that!) and gave it a try: It works like with v2. > With that: > > Tested-by: Dirk Behme <dirk.behme@de.bosch.com> Really appreciated! And I think we are finally converging, so hopefully no more big refactoring ahead. :) Still, please let me know if you saw anything that looked off during the conversion.
On 25.02.2026 14:50, Alexandre Courbot wrote: > On Wed Feb 25, 2026 at 8:58 PM JST, Dirk Behme wrote: >> On 24.02.2026 15:21, Alexandre Courbot wrote: >>> New revision addressing the v6 feedback - the use of "location" instead >>> of "reference" in particular reads well both in the code and the >>> comments. >>> >>> As a reminder, since the previous revision we use the I/O type to >>> perform the actual I/O instead of the register type, which moves us from >>> this access pattern: >>> >>> let boot0 = regs::NV_PMC_BOOT_0::read(bar); >>> >>> to this arguably more natural one: >>> >>> let boot0 = bar.read(regs::NV_PMC_BOOT_0); >>> >>> This revision is based on `driver-core-testing` as of 2026-02-24 with >>> [1] applied. A tree with this series and its dependencies is available >>> at [2]. >>> >>> [1] https://lore.kernel.org/all/20260206-io-v2-0-71dea20a06e6@nvidia.com/ >>> [2] https://github.com/Gnurou/linux/tree/b4/register >>> >>> The first patch enables the `generic_arg_infer` feature, which is >>> required for generic type inference and used in subsequent patches. This >>> feature is stable since rustc 1.89. >>> >>> The second patch adds `shr` and `shl` methods to `Bounded`. These were >>> suggested by Alice during LPC as a way to avoid the use of the >>> controversial `Bounded::from_expr` in both the bitfield macro and the >>> Nova code. The third patch adds another convenience method to obtain a >>> `bool` from single-bit `Bounded`s, while the fourth patch turns >>> `Bounded::get` into a const method in order to make register setter >>> methods const. >>> >>> Patches 5 and 6 introduce the `IoLoc` and `IoWrite` types around which >>> I/O accesses are centered. This allows registers to be accessed using >>> the same `read` and `write` methods as primitive types. >>> >>> Patch 7 adds the `register!` macro and the types it requires. >>> >>> Patch 8 updates the Rust PCI sample driver to use `register!`, as per >>> its TODO item. >>> >>> Patch 9 illustrates more extensively how this macro is used by >>> converting nova-core to use it, and removing the local implementation. >>> This patch is to be merged one cycle after the other patches. >>> >>> Patch 10 is an RFC allowing a shorter write syntax to be used in the >>> case of fixed or relative registers. It doesn't need to be merged >>> immediately, but I think it is a good time to discuss it. >>> >>> I have also removed Gary's signoff on patches 5 and 7 to make sure it >>> doesn't get merged before he gives it explicitly. >>> >>> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> >>> >>> --- >>> Changes in v7: >>> - Use `RES + SHIFT >= N` instead of `RES >= N - SHIFT` in >>> `Bounded::shr`. >>> - Rename `IoRef` to `IoLoc` and all related types >>> accordingly. >>> - Use `Into` trait bounds in both directions on `IoLoc`. >>> - Add RFC patch allowing fixed register values to be used directly with >>> `write`. >>> - Link to v6: https://patch.msgid.link/20260216-register-v6-0-eec9a4de9e9e@nvidia.com >>> >>> Changes in v6: >>> - Remove Tested-by tags as the code has considerably changed. >>> - Make `Bounded::get` const so it can be used with registers. >>> - Use the `pin_init::zeroed()` const function instead of defining our >>> own method. >>> - Generalize all `Io` around the new `IoRef` and `IoWrite` types, and >>> make registers use these as well. >>> - Use the more natural pattern of having the `Io` type perform the I/O >>> access instead of the register type. >>> - Convert the whole PCI driver example, and not only the PCI >>> configuration space. >>> - Rename `Bounded::as_bool` to `Bounded::into_bool`. >>> - Drop `Bounded::into_inner` in favor of making `Bounded::get` const. >>> - Link to v5: https://patch.msgid.link/20260129-register-v5-0-c4587c902514@nvidia.com >>> >>> Changes in v5: >>> - Rename all setters to `with_*` and `with_const_*`. >>> - Use `, stride = ` to specify the stride of register arrays. >>> - Remove `Deref` requirement on the `RegisterIo` trait and make it >>> `#[doc(hidden)`. >>> - Simplify the top dispatch rule a bit. >>> - Link to v4: https://patch.msgid.link/20260128-register-v4-0-aee3a33d9649@nvidia.com >>> >>> Changes in v4: >>> - Add `with_` const field setter methods (removing the need to call >>> `Bounded::new` for constant field values). >>> - Add `into_inner` const method for `Bounded`. >>> - Add `from_raw` and const `zeroed` method to create initial register >>> values. >>> - More documentation improvements. >>> - Link to v3: https://patch.msgid.link/20260126-register-v3-0-2328a59d7312@nvidia.com >>> >>> Changes in v3: >>> - Sort the Rust features list alphabetically. >>> - Rebase on top of latest `driver-core-next` including the new Io trait. >>> - Allow several registers to be defined from the same macro invocation. >>> - Remove references to `bitfield!` macro. >>> - Fix doccomment of `shr` and `shl`. >>> - Use `+` syntax for relative register offsets. >>> - Move register arrays size and stride to after the backing type declaration. >>> - Use regular doccomments to document registers and fields (thanks Gary!). >>> - Remove `Default` implementation and implement the more predictable >>> `Zeroable` instead. >>> - Improve doccomments a bit. >>> - Link to v2: https://patch.msgid.link/20260121-register-v2-0-79d9b8d5e36a@nvidia.com >>> >>> Changes in v2: >>> - Remove `bitfield!` and put its rules into `register!` to give it more >>> time to get reviewed. >>> - Allow output type larger than strictly required for `shr` and `shl` on >>> `Bounded`. >>> - Enable the `generic_arg_infer` feature, required for rustc < 1.89. >>> - Link to v1: https://patch.msgid.link/20260120-register-v1-0-723a1743b557@nvidia.com >>> >>> --- >>> Alexandre Courbot (10): >>> rust: enable the `generic_arg_infer` feature >>> rust: num: add `shr` and `shl` methods to `Bounded` >>> rust: num: add `into_bool` method to `Bounded` >>> rust: num: make Bounded::get const >>> rust: io: add IoLoc and IoWrite types >>> rust: io: use generic read/write accessors for primitive accesses >>> rust: io: add `register!` macro >>> sample: rust: pci: use `register!` macro >>> [FOR REFERENCE] gpu: nova-core: use the kernel `register!` macro >>> RFC: rust: io: allow fixed register values directly in `write` >>> >>> drivers/gpu/nova-core/falcon.rs | 249 +++---- >>> drivers/gpu/nova-core/falcon/gsp.rs | 23 +- >>> drivers/gpu/nova-core/falcon/hal/ga102.rs | 65 +- >>> drivers/gpu/nova-core/falcon/hal/tu102.rs | 11 +- >>> drivers/gpu/nova-core/falcon/sec2.rs | 17 +- >>> drivers/gpu/nova-core/fb.rs | 6 +- >>> drivers/gpu/nova-core/fb/hal/ga100.rs | 40 +- >>> drivers/gpu/nova-core/fb/hal/ga102.rs | 7 +- >>> drivers/gpu/nova-core/fb/hal/tu102.rs | 22 +- >>> drivers/gpu/nova-core/gfw.rs | 11 +- >>> drivers/gpu/nova-core/gpu.rs | 36 +- >>> drivers/gpu/nova-core/gsp/boot.rs | 11 +- >>> drivers/gpu/nova-core/gsp/cmdq.rs | 10 +- >>> drivers/gpu/nova-core/regs.rs | 544 ++++++++------ >>> drivers/gpu/nova-core/regs/macros.rs | 739 ------------------- >>> rust/kernel/io.rs | 347 +++++++-- >>> rust/kernel/io/register.rs | 1135 +++++++++++++++++++++++++++++ >>> rust/kernel/lib.rs | 3 + >>> rust/kernel/num/bounded.rs | 70 +- >>> samples/rust/rust_driver_pci.rs | 84 ++- >>> scripts/Makefile.build | 3 +- >>> 21 files changed, 2118 insertions(+), 1315 deletions(-) >>> --- >>> base-commit: 545225ee0b0b6998c7b6ff888f8497681b8b35c4 >>> change-id: 20260117-register-ccaba1d21713 >> >> >> I converted my simple aarch64 TMU timer example [1] over to v7 (many >> thanks helping with that!) and gave it a try: It works like with v2. >> With that: >> >> Tested-by: Dirk Behme <dirk.behme@de.bosch.com> > > Really appreciated! And I think we are finally converging, so hopefully > no more big refactoring ahead. :) Still, please let me know if you saw > anything that looked off during the conversion. I was slightly surprised about the `set_` to `with_` change. But thinking about it I think it heavily depends on the point of view: If you look at it from a physical register point of view I'm used to "set" a register / bit. So looking from physical register point of view I find using `set_` natural. On the other hand, if we look at the Rust "syntax" you create here like foo.with_a(4).with_b(9).write(io); we write to register foo with bits a being 4 and bits b being 9. So we are doing a write *with* some bits set. From this point of view `with_` fits as well. I think you mentioned that this is discussable. And I think it heavily depends on the point of view you take. So I'm fine either. Thanks Dirk
On Thu Feb 26, 2026 at 9:01 PM JST, Dirk Behme wrote: <snip> >>> I converted my simple aarch64 TMU timer example [1] over to v7 (many >>> thanks helping with that!) and gave it a try: It works like with v2. >>> With that: >>> >>> Tested-by: Dirk Behme <dirk.behme@de.bosch.com> >> >> Really appreciated! And I think we are finally converging, so hopefully >> no more big refactoring ahead. :) Still, please let me know if you saw >> anything that looked off during the conversion. > > > I was slightly surprised about the `set_` to `with_` change. But > thinking about it I think it heavily depends on the point of view: > > If you look at it from a physical register point of view I'm used to > "set" a register / bit. So looking from physical register point of view > I find using `set_` natural. > > On the other hand, if we look at the Rust "syntax" you create here like > > foo.with_a(4).with_b(9).write(io); > > we write to register foo with bits a being 4 and bits b being 9. So we > are doing a write *with* some bits set. From this point of view `with_` > fits as well. > > I think you mentioned that this is discussable. And I think it heavily > depends on the point of view you take. So I'm fine either. This has to do with Rust conventions: we are using a builder pattern, where fields are set by taking the register by value, and returning the updated value. Such methods tend to be prefixed with `with_`, whereas `set_` is typically used for in-plane modification using `&mut self`. Now AFAICT this is not a *codified* convention, just a rather strong unwritten one. But it seems adequate to follow it, so users are not mistaken into thinking the setters do something different than they do. As to why the builder pattern, this is because it is shorter to write io.write(reg.with_foo(true)); than mut foo = ...; reg.set_foo(true); io.write(reg); and also cleaner as it removes the need for the register variable to be mutable.
© 2016 - 2026 Red Hat, Inc.