Use the register!() macro to define the layout for the Boot0 register and use its accessors through the use of the convenience with_bar!() macro, which uses Revocable::try_access() and converts its returned Option into the proper error as needed.
Signed-off-by: Alexandre Courbot <acour...@nvidia.com> --- drivers/gpu/nova-core/gpu.rs | 5 ++-- drivers/gpu/nova-core/nova_core.rs | 12 ++++++++ drivers/gpu/nova-core/regs.rs | 60 ++++++-------------------------------- 3 files changed, 23 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index 9fe6aedaa9563799c2624d461d4e37ee9b094909..d96901e5c8eace1e7c57c77da7def209e8149cd3 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -135,11 +135,10 @@ pub(crate) struct Spec { impl Spec { fn new(bar: &Devres<Bar0>) -> Result<Spec> { - let bar = bar.try_access().ok_or(ENXIO)?; - let boot0 = regs::Boot0::read(&bar); + let boot0 = with_bar!(bar, |b| regs::Boot0::read(b))?; Ok(Self { - chipset: boot0.chipset().try_into()?, + chipset: boot0.chipset()?, revision: Revision::from_boot0(boot0), }) } diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs index a91cd924054b49966937a8db6aab9cd0614f10de..94f4778c16f6a4d046c2f799129ed0cc68df6fd4 100644 --- a/drivers/gpu/nova-core/nova_core.rs +++ b/drivers/gpu/nova-core/nova_core.rs @@ -2,6 +2,18 @@ //! Nova Core GPU Driver +#[macro_use] +mod macros { + /// Convenience macro to run a closure while holding [`crate::driver::Bar0`]. + /// + /// If the bar cannot be acquired, then `ENXIO` is returned. + macro_rules! with_bar { + ($bar:expr, $closure:expr) => { + $bar.try_access_with($closure).ok_or(ENXIO) + }; + } +} + mod driver; mod firmware; mod gpu; diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs index 50aefb150b0b1c9b73f07fca3b7a070885785485..7bfd2b575fe2184565d495012e55cd0829b0b1ad 100644 --- a/drivers/gpu/nova-core/regs.rs +++ b/drivers/gpu/nova-core/regs.rs @@ -1,55 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 -use crate::driver::Bar0; +use core::ops::Deref; +use kernel::io::Io; +use kernel::register; -// TODO -// -// Create register definitions via generic macros. See task "Generic register -// abstraction" in Documentation/gpu/nova/core/todo.rst. +use crate::gpu::Chipset; -const BOOT0_OFFSET: usize = 0x00000000; - -// 3:0 - chipset minor revision -const BOOT0_MINOR_REV_SHIFT: u8 = 0; -const BOOT0_MINOR_REV_MASK: u32 = 0x0000000f; - -// 7:4 - chipset major revision -const BOOT0_MAJOR_REV_SHIFT: u8 = 4; -const BOOT0_MAJOR_REV_MASK: u32 = 0x000000f0; - -// 23:20 - chipset implementation Identifier (depends on architecture) -const BOOT0_IMPL_SHIFT: u8 = 20; -const BOOT0_IMPL_MASK: u32 = 0x00f00000; - -// 28:24 - chipset architecture identifier -const BOOT0_ARCH_MASK: u32 = 0x1f000000; - -// 28:20 - chipset identifier (virtual register field combining BOOT0_IMPL and -// BOOT0_ARCH) -const BOOT0_CHIPSET_SHIFT: u8 = BOOT0_IMPL_SHIFT; -const BOOT0_CHIPSET_MASK: u32 = BOOT0_IMPL_MASK | BOOT0_ARCH_MASK; - -#[derive(Copy, Clone)] -pub(crate) struct Boot0(u32); - -impl Boot0 { - #[inline] - pub(crate) fn read(bar: &Bar0) -> Self { - Self(bar.readl(BOOT0_OFFSET)) - } - - #[inline] - pub(crate) fn chipset(&self) -> u32 { - (self.0 & BOOT0_CHIPSET_MASK) >> BOOT0_CHIPSET_SHIFT - } - - #[inline] - pub(crate) fn minor_rev(&self) -> u8 { - ((self.0 & BOOT0_MINOR_REV_MASK) >> BOOT0_MINOR_REV_SHIFT) as u8 - } - - #[inline] - pub(crate) fn major_rev(&self) -> u8 { - ((self.0 & BOOT0_MAJOR_REV_MASK) >> BOOT0_MAJOR_REV_SHIFT) as u8 - } -} +register!(Boot0@0x00000000, "Basic revision information about the GPU"; + 3:0 minor_rev => as u8, "minor revision of the chip"; + 7:4 major_rev => as u8, "major revision of the chip"; + 28:20 chipset => try_into Chipset, "chipset model" +); -- 2.48.1