public inbox for drm-ai-reviews@public-inbox.freedesktop.org
 help / color / mirror / Atom feed
From: Deborah Brouwer <deborah.brouwer@collabora.com>
To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org,
	Boqun Feng <boqun@kernel.org>
Cc: Danilo Krummrich <dakr@kernel.org>,
	Alice Ryhl <aliceryhl@google.com>,
	Daniel Almeida <daniel.almeida@collabora.com>,
	Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	Maxime Ripard <mripard@kernel.org>,
	Thomas Zimmermann <tzimmermann@suse.de>,
	David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
	Miguel Ojeda <ojeda@kernel.org>, Gary Guo <gary@garyguo.net>,
	Björn Roy Baron <bjorn3_gh@protonmail.com>,
	Benno Lossin <lossin@kernel.org>,
	Andreas Hindborg <a.hindborg@kernel.org>,
	Trevor Gross <tmgross@umich.edu>,
	Steven Price <steven.price@arm.com>,
	Boris Brezillon <boris.brezillon@collabora.com>,
	Dirk Behme <dirk.behme@gmail.com>,
	Alexandre Courbot <acourbot@nvidia.com>,
	Deborah Brouwer <deborah.brouwer@collabora.com>,
	Boqun Feng <boqun@kernel.org>
Subject: [PATCH v3 01/12] drm/tyr: Use register! macro for GPU_CONTROL
Date: Mon, 23 Mar 2026 17:18:03 -0700	[thread overview]
Message-ID: <20260323-b4-tyr-use-register-macro-v3-v3-1-a87daf9e4701@collabora.com> (raw)
In-Reply-To: <20260323-b4-tyr-use-register-macro-v3-v3-0-a87daf9e4701@collabora.com>

From: Daniel Almeida <daniel.almeida@collabora.com>

Convert the GPU_CONTROL register definitions to use the `register!` macro.

Using the `register!` macro allows us to replace manual bit masks and
shifts with typed register and field accessors, which makes the code
easier to read and avoids errors from bit manipulation.

Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
Co-developed-by: Deborah Brouwer <deborah.brouwer@collabora.com>
Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com>
---
 drivers/gpu/drm/tyr/driver.rs |  24 +-
 drivers/gpu/drm/tyr/gpu.rs    | 211 +++++------
 drivers/gpu/drm/tyr/regs.rs   | 803 +++++++++++++++++++++++++++++++++++++++---
 3 files changed, 842 insertions(+), 196 deletions(-)

diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index 611434641580574ec6b5afa49a8fe79888bb7ace..3ebb5e08bfca342f136e8d365b1d9dcb6cc3dbca 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -13,7 +13,10 @@
     devres::Devres,
     drm,
     drm::ioctl,
-    io::poll,
+    io::{
+        poll,
+        Io, //
+    },
     new_mutex,
     of,
     platform,
@@ -33,8 +36,11 @@
     file::TyrDrmFileData,
     gem::TyrObject,
     gpu,
-    gpu::GpuInfo,
-    regs, //
+    gpu::{
+        gpu_info_log, //
+        GpuInfo,
+    },
+    regs::gpu_control::*, //
 };
 
 pub(crate) type IoMem = kernel::io::mem::IoMem<SZ_2M>;
@@ -78,11 +84,15 @@ unsafe impl Send for TyrDrmDeviceData {}
 unsafe impl Sync for TyrDrmDeviceData {}
 
 fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
-    regs::GPU_CMD.write(dev, iomem, regs::GPU_CMD_SOFT_RESET)?;
+    let io = (*iomem).access(dev)?;
+    io.write_reg(GPU_COMMAND::reset(ResetMode::SoftReset));
 
     poll::read_poll_timeout(
-        || regs::GPU_IRQ_RAWSTAT.read(dev, iomem),
-        |status| *status & regs::GPU_IRQ_RAWSTAT_RESET_COMPLETED != 0,
+        || {
+            let io = (*iomem).access(dev)?;
+            Ok(io.read(GPU_IRQ_RAWSTAT))
+        },
+        |status| status.reset_completed(),
         time::Delta::from_millis(1),
         time::Delta::from_millis(100),
     )
@@ -127,7 +137,7 @@ fn probe(
         gpu::l2_power_on(pdev.as_ref(), &iomem)?;
 
         let gpu_info = GpuInfo::new(pdev.as_ref(), &iomem)?;
-        gpu_info.log(pdev);
+        gpu_info_log(pdev.as_ref(), &iomem)?;
 
         let platform: ARef<platform::Device> = pdev.into();
 
diff --git a/drivers/gpu/drm/tyr/gpu.rs b/drivers/gpu/drm/tyr/gpu.rs
index a88775160f981e899e9c9b58debbda33e1b7244d..66fd6c016c62abe3c34669a2e47b680c3a3f873d 100644
--- a/drivers/gpu/drm/tyr/gpu.rs
+++ b/drivers/gpu/drm/tyr/gpu.rs
@@ -5,14 +5,16 @@
     DerefMut, //
 };
 use kernel::{
-    bits::genmask_u32,
     device::{
         Bound,
         Device, //
     },
     devres::Devres,
-    io::poll,
-    platform,
+    io::{
+        poll,
+        register::Array,
+        Io, //
+    },
     prelude::*,
     time::Delta,
     transmute::AsBytes,
@@ -21,7 +23,7 @@
 
 use crate::{
     driver::IoMem,
-    regs, //
+    regs::gpu_control::*, //
 };
 
 /// Struct containing information that can be queried by userspace. This is read from
@@ -29,120 +31,46 @@
 ///
 /// # Invariants
 ///
-/// - The layout of this struct identical to the C `struct drm_panthor_gpu_info`.
+/// - The layout of this struct is identical to the C `struct drm_panthor_gpu_info`.
 #[repr(transparent)]
 #[derive(Clone, Copy)]
 pub(crate) struct GpuInfo(pub(crate) uapi::drm_panthor_gpu_info);
 
 impl GpuInfo {
     pub(crate) fn new(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result<Self> {
-        let gpu_id = regs::GPU_ID.read(dev, iomem)?;
-        let csf_id = regs::GPU_CSF_ID.read(dev, iomem)?;
-        let gpu_rev = regs::GPU_REVID.read(dev, iomem)?;
-        let core_features = regs::GPU_CORE_FEATURES.read(dev, iomem)?;
-        let l2_features = regs::GPU_L2_FEATURES.read(dev, iomem)?;
-        let tiler_features = regs::GPU_TILER_FEATURES.read(dev, iomem)?;
-        let mem_features = regs::GPU_MEM_FEATURES.read(dev, iomem)?;
-        let mmu_features = regs::GPU_MMU_FEATURES.read(dev, iomem)?;
-        let thread_features = regs::GPU_THREAD_FEATURES.read(dev, iomem)?;
-        let max_threads = regs::GPU_THREAD_MAX_THREADS.read(dev, iomem)?;
-        let thread_max_workgroup_size = regs::GPU_THREAD_MAX_WORKGROUP_SIZE.read(dev, iomem)?;
-        let thread_max_barrier_size = regs::GPU_THREAD_MAX_BARRIER_SIZE.read(dev, iomem)?;
-        let coherency_features = regs::GPU_COHERENCY_FEATURES.read(dev, iomem)?;
-
-        let texture_features = regs::GPU_TEXTURE_FEATURES0.read(dev, iomem)?;
-
-        let as_present = regs::GPU_AS_PRESENT.read(dev, iomem)?;
-
-        let shader_present = u64::from(regs::GPU_SHADER_PRESENT_LO.read(dev, iomem)?);
-        let shader_present =
-            shader_present | u64::from(regs::GPU_SHADER_PRESENT_HI.read(dev, iomem)?) << 32;
-
-        let tiler_present = u64::from(regs::GPU_TILER_PRESENT_LO.read(dev, iomem)?);
-        let tiler_present =
-            tiler_present | u64::from(regs::GPU_TILER_PRESENT_HI.read(dev, iomem)?) << 32;
-
-        let l2_present = u64::from(regs::GPU_L2_PRESENT_LO.read(dev, iomem)?);
-        let l2_present = l2_present | u64::from(regs::GPU_L2_PRESENT_HI.read(dev, iomem)?) << 32;
+        let io = (*iomem).access(dev)?;
 
         Ok(Self(uapi::drm_panthor_gpu_info {
-            gpu_id,
-            gpu_rev,
-            csf_id,
-            l2_features,
-            tiler_features,
-            mem_features,
-            mmu_features,
-            thread_features,
-            max_threads,
-            thread_max_workgroup_size,
-            thread_max_barrier_size,
-            coherency_features,
-            // TODO: Add texture_features_{1,2,3}.
-            texture_features: [texture_features, 0, 0, 0],
-            as_present,
+            gpu_id: io.read(GPU_ID).into_raw(),
+            gpu_rev: io.read(REVIDR).into_raw(),
+            csf_id: io.read(CSF_ID).into_raw(),
+            l2_features: io.read(L2_FEATURES).into_raw(),
+            tiler_features: io.read(TILER_FEATURES).into_raw(),
+            mem_features: io.read(MEM_FEATURES).into_raw(),
+            mmu_features: io.read(MMU_FEATURES).into_raw(),
+            thread_features: io.read(THREAD_FEATURES).into_raw(),
+            max_threads: io.read(THREAD_MAX_THREADS).into_raw(),
+            thread_max_workgroup_size: io.read(THREAD_MAX_WORKGROUP_SIZE).into_raw(),
+            thread_max_barrier_size: io.read(THREAD_MAX_BARRIER_SIZE).into_raw(),
+            coherency_features: io.read(COHERENCY_FEATURES).into_raw(),
+            texture_features: [
+                io.read(TEXTURE_FEATURES::at(0)).supported_formats().get(),
+                io.read(TEXTURE_FEATURES::at(1)).supported_formats().get(),
+                io.read(TEXTURE_FEATURES::at(2)).supported_formats().get(),
+                io.read(TEXTURE_FEATURES::at(3)).supported_formats().get(),
+            ],
+            as_present: io.read(AS_PRESENT).into_raw(),
             selected_coherency: uapi::drm_panthor_gpu_coherency_DRM_PANTHOR_GPU_COHERENCY_NONE,
-            shader_present,
-            l2_present,
-            tiler_present,
-            core_features,
+            shader_present: io.read(SHADER_PRESENT).into_raw(),
+            l2_present: io.read(L2_PRESENT).into_raw(),
+            tiler_present: io.read(TILER_PRESENT).into_raw(),
+            core_features: io.read(CORE_FEATURES).into_raw(),
+            // Padding must be zero.
             pad: 0,
+            //GPU_FEATURES register is not available; it was introduced in arch 11.x.
             gpu_features: 0,
         }))
     }
-
-    pub(crate) fn log(&self, pdev: &platform::Device) {
-        let gpu_id = GpuId::from(self.gpu_id);
-
-        let model_name = if let Some(model) = GPU_MODELS
-            .iter()
-            .find(|&f| f.arch_major == gpu_id.arch_major && f.prod_major == gpu_id.prod_major)
-        {
-            model.name
-        } else {
-            "unknown"
-        };
-
-        dev_info!(
-            pdev,
-            "mali-{} id 0x{:x} major 0x{:x} minor 0x{:x} status 0x{:x}",
-            model_name,
-            self.gpu_id >> 16,
-            gpu_id.ver_major,
-            gpu_id.ver_minor,
-            gpu_id.ver_status
-        );
-
-        dev_info!(
-            pdev,
-            "Features: L2:{:#x} Tiler:{:#x} Mem:{:#x} MMU:{:#x} AS:{:#x}",
-            self.l2_features,
-            self.tiler_features,
-            self.mem_features,
-            self.mmu_features,
-            self.as_present
-        );
-
-        dev_info!(
-            pdev,
-            "shader_present=0x{:016x} l2_present=0x{:016x} tiler_present=0x{:016x}",
-            self.shader_present,
-            self.l2_present,
-            self.tiler_present
-        );
-    }
-
-    /// Returns the number of virtual address bits supported by the GPU.
-    #[expect(dead_code)]
-    pub(crate) fn va_bits(&self) -> u32 {
-        self.mmu_features & genmask_u32(0..=7)
-    }
-
-    /// Returns the number of physical address bits supported by the GPU.
-    #[expect(dead_code)]
-    pub(crate) fn pa_bits(&self) -> u32 {
-        (self.mmu_features >> 8) & genmask_u32(0..=7)
-    }
 }
 
 impl Deref for GpuInfo {
@@ -182,38 +110,59 @@ struct GpuModels {
     prod_major: 7,
 }];
 
-#[allow(dead_code)]
-pub(crate) struct GpuId {
-    pub(crate) arch_major: u32,
-    pub(crate) arch_minor: u32,
-    pub(crate) arch_rev: u32,
-    pub(crate) prod_major: u32,
-    pub(crate) ver_major: u32,
-    pub(crate) ver_minor: u32,
-    pub(crate) ver_status: u32,
-}
-
-impl From<u32> for GpuId {
-    fn from(value: u32) -> Self {
-        GpuId {
-            arch_major: (value & genmask_u32(28..=31)) >> 28,
-            arch_minor: (value & genmask_u32(24..=27)) >> 24,
-            arch_rev: (value & genmask_u32(20..=23)) >> 20,
-            prod_major: (value & genmask_u32(16..=19)) >> 16,
-            ver_major: (value & genmask_u32(12..=15)) >> 12,
-            ver_minor: (value & genmask_u32(4..=11)) >> 4,
-            ver_status: value & genmask_u32(0..=3),
-        }
-    }
+pub(crate) fn gpu_info_log(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
+    let io = (*iomem).access(dev)?;
+    let gpu_id = io.read(GPU_ID);
+
+    let model_name = if let Some(model) = GPU_MODELS.iter().find(|&f| {
+        f.arch_major == gpu_id.arch_major().get() && f.prod_major == gpu_id.prod_major().get()
+    }) {
+        model.name
+    } else {
+        "unknown"
+    };
+
+    dev_info!(
+        dev,
+        "mali-{} id 0x{:x} major 0x{:x} minor 0x{:x} status 0x{:x}",
+        model_name,
+        gpu_id.into_raw() >> 16,
+        gpu_id.ver_major().get(),
+        gpu_id.ver_minor().get(),
+        gpu_id.ver_status().get()
+    );
+
+    dev_info!(
+        dev,
+        "Features: L2:{:#x} Tiler:{:#x} Mem:{:#x} MMU:{:#x} AS:{:#x}",
+        io.read(L2_FEATURES).into_raw(),
+        io.read(TILER_FEATURES).into_raw(),
+        io.read(MEM_FEATURES).into_raw(),
+        io.read(MMU_FEATURES).into_raw(),
+        io.read(AS_PRESENT).into_raw(),
+    );
+
+    dev_info!(
+        dev,
+        "shader_present=0x{:016x} l2_present=0x{:016x} tiler_present=0x{:016x}",
+        io.read(SHADER_PRESENT).into_raw(),
+        io.read(L2_PRESENT).into_raw(),
+        io.read(TILER_PRESENT).into_raw(),
+    );
+    Ok(())
 }
 
 /// Powers on the l2 block.
 pub(crate) fn l2_power_on(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
-    regs::L2_PWRON_LO.write(dev, iomem, 1)?;
+    let io = (*iomem).access(dev)?;
+    io.write_reg(L2_PWRON::zeroed().with_const_request::<1>());
 
     poll::read_poll_timeout(
-        || regs::L2_READY_LO.read(dev, iomem),
-        |status| *status == 1,
+        || {
+            let io = (*iomem).access(dev)?;
+            Ok(io.read(L2_READY))
+        },
+        |status| status.ready() == 1,
         Delta::from_millis(1),
         Delta::from_millis(100),
     )
diff --git a/drivers/gpu/drm/tyr/regs.rs b/drivers/gpu/drm/tyr/regs.rs
index 611870c2e6af50a35daaef052db2dd33a7e8059c..5ba4919263af29c6e88435099cf801fa5874b117 100644
--- a/drivers/gpu/drm/tyr/regs.rs
+++ b/drivers/gpu/drm/tyr/regs.rs
@@ -1,5 +1,25 @@
 // SPDX-License-Identifier: GPL-2.0 or MIT
 
+//! # Definitions
+//!
+//! - **CEU**: Command Execution Unit - A hardware component that executes commands (instructions)
+//!   from the command stream.
+//! - **CS**: Command Stream - A sequence of instructions (commands) used to control a particular
+//!   job or sequence of jobs. The instructions exist in one or more command buffers.
+//! - **CSF**: Command Stream Frontend - The interface and implementation for job submission
+//!   exposed to the host CPU driver. This includes the global interface, as well as CSG and CS
+//!   interfaces.
+//! - **CSG**: Command Stream Group - A group of related command streams. The CSF manages multiple
+//!   CSGs, and each CSG contains multiple CSs.
+//! - **CSHW**: Command Stream Hardware - The hardware interpreting command streams, including the
+//!   iterator control aspects. Implements the CSF in conjunction with the MCU.
+//! - **GLB**: Global - Prefix for global interface registers that control operations common to
+//!   all CSs.
+//! - **JASID**: Job Address Space ID - Identifies the address space for a job.
+//! - **MCU**: Microcontroller Unit - Implements the CSF in conjunction with the command stream
+//!   hardware.
+//! - **MMU**: Memory Management Unit - Handles address translation and memory access protection.
+
 // We don't expect that all the registers and fields will be used, even in the
 // future.
 //
@@ -41,64 +61,731 @@ pub(crate) fn write(&self, dev: &Device<Bound>, iomem: &Devres<IoMem>, value: u3
     }
 }
 
-pub(crate) const GPU_ID: Register<0x0> = Register;
-pub(crate) const GPU_L2_FEATURES: Register<0x4> = Register;
-pub(crate) const GPU_CORE_FEATURES: Register<0x8> = Register;
-pub(crate) const GPU_CSF_ID: Register<0x1c> = Register;
-pub(crate) const GPU_REVID: Register<0x280> = Register;
-pub(crate) const GPU_TILER_FEATURES: Register<0xc> = Register;
-pub(crate) const GPU_MEM_FEATURES: Register<0x10> = Register;
-pub(crate) const GPU_MMU_FEATURES: Register<0x14> = Register;
-pub(crate) const GPU_AS_PRESENT: Register<0x18> = Register;
-pub(crate) const GPU_IRQ_RAWSTAT: Register<0x20> = Register;
-
-pub(crate) const GPU_IRQ_RAWSTAT_FAULT: u32 = bit_u32(0);
-pub(crate) const GPU_IRQ_RAWSTAT_PROTECTED_FAULT: u32 = bit_u32(1);
-pub(crate) const GPU_IRQ_RAWSTAT_RESET_COMPLETED: u32 = bit_u32(8);
-pub(crate) const GPU_IRQ_RAWSTAT_POWER_CHANGED_SINGLE: u32 = bit_u32(9);
-pub(crate) const GPU_IRQ_RAWSTAT_POWER_CHANGED_ALL: u32 = bit_u32(10);
-pub(crate) const GPU_IRQ_RAWSTAT_CLEAN_CACHES_COMPLETED: u32 = bit_u32(17);
-pub(crate) const GPU_IRQ_RAWSTAT_DOORBELL_STATUS: u32 = bit_u32(18);
-pub(crate) const GPU_IRQ_RAWSTAT_MCU_STATUS: u32 = bit_u32(19);
-
-pub(crate) const GPU_IRQ_CLEAR: Register<0x24> = Register;
-pub(crate) const GPU_IRQ_MASK: Register<0x28> = Register;
-pub(crate) const GPU_IRQ_STAT: Register<0x2c> = Register;
-pub(crate) const GPU_CMD: Register<0x30> = Register;
-pub(crate) const GPU_CMD_SOFT_RESET: u32 = 1 | (1 << 8);
-pub(crate) const GPU_CMD_HARD_RESET: u32 = 1 | (2 << 8);
-pub(crate) const GPU_THREAD_FEATURES: Register<0xac> = Register;
-pub(crate) const GPU_THREAD_MAX_THREADS: Register<0xa0> = Register;
-pub(crate) const GPU_THREAD_MAX_WORKGROUP_SIZE: Register<0xa4> = Register;
-pub(crate) const GPU_THREAD_MAX_BARRIER_SIZE: Register<0xa8> = Register;
-pub(crate) const GPU_TEXTURE_FEATURES0: Register<0xb0> = Register;
-pub(crate) const GPU_SHADER_PRESENT_LO: Register<0x100> = Register;
-pub(crate) const GPU_SHADER_PRESENT_HI: Register<0x104> = Register;
-pub(crate) const GPU_TILER_PRESENT_LO: Register<0x110> = Register;
-pub(crate) const GPU_TILER_PRESENT_HI: Register<0x114> = Register;
-pub(crate) const GPU_L2_PRESENT_LO: Register<0x120> = Register;
-pub(crate) const GPU_L2_PRESENT_HI: Register<0x124> = Register;
-pub(crate) const L2_READY_LO: Register<0x160> = Register;
-pub(crate) const L2_READY_HI: Register<0x164> = Register;
-pub(crate) const L2_PWRON_LO: Register<0x1a0> = Register;
-pub(crate) const L2_PWRON_HI: Register<0x1a4> = Register;
-pub(crate) const L2_PWRTRANS_LO: Register<0x220> = Register;
-pub(crate) const L2_PWRTRANS_HI: Register<0x204> = Register;
-pub(crate) const L2_PWRACTIVE_LO: Register<0x260> = Register;
-pub(crate) const L2_PWRACTIVE_HI: Register<0x264> = Register;
-
-pub(crate) const MCU_CONTROL: Register<0x700> = Register;
-pub(crate) const MCU_CONTROL_ENABLE: u32 = 1;
-pub(crate) const MCU_CONTROL_AUTO: u32 = 2;
-pub(crate) const MCU_CONTROL_DISABLE: u32 = 0;
-
-pub(crate) const MCU_STATUS: Register<0x704> = Register;
-pub(crate) const MCU_STATUS_DISABLED: u32 = 0;
-pub(crate) const MCU_STATUS_ENABLED: u32 = 1;
-pub(crate) const MCU_STATUS_HALT: u32 = 2;
-pub(crate) const MCU_STATUS_FATAL: u32 = 3;
-
-pub(crate) const GPU_COHERENCY_FEATURES: Register<0x300> = Register;
+/// These registers correspond to the GPU_CONTROL register page.
+/// They are involved in GPU configuration and control.
+pub(crate) mod gpu_control {
+    use core::convert::TryFrom;
+    use kernel::{
+        error::{
+            code::EINVAL,
+            Error, //
+        },
+        num::Bounded,
+        register,
+        uapi, //
+    };
+    use pin_init::Zeroable;
+
+    register! {
+        /// GPU identification register.
+        pub(crate) GPU_ID(u32) @ 0x0 {
+            /// Status of the GPU release.
+            3:0     ver_status;
+            /// Minor release version number.
+            11:4    ver_minor;
+            /// Major release version number.
+            15:12   ver_major;
+            /// Product identifier.
+            19:16   prod_major;
+            /// Architecture patch revision.
+            23:20   arch_rev;
+            /// Architecture minor revision.
+            27:24   arch_minor;
+            /// Architecture major revision.
+            31:28   arch_major;
+        }
+
+        /// Level 2 cache features register.
+        pub(crate) L2_FEATURES(u32) @ 0x4 {
+            /// Cache line size.
+            7:0     line_size;
+            /// Cache associativity.
+            15:8    associativity;
+            /// Cache slice size.
+            23:16   cache_size;
+            /// External bus width.
+            31:24   bus_width;
+        }
+
+        /// Shader core features.
+        pub(crate) CORE_FEATURES(u32) @ 0x8 {
+            /// Shader core variant.
+            7:0     core_variant;
+        }
+
+        /// Tiler features.
+        pub(crate) TILER_FEATURES(u32) @ 0xc {
+            /// Log of the tiler's bin size.
+            5:0     bin_size;
+            /// Maximum number of active levels.
+            11:8    max_levels;
+        }
+
+        /// Memory system features.
+        pub(crate) MEM_FEATURES(u32) @ 0x10 {
+            0:0     coherent_core_group => bool;
+            1:1     coherent_super_group => bool;
+            11:8    l2_slices;
+        }
+
+        /// Memory management unit features.
+        pub(crate) MMU_FEATURES(u32) @ 0x14 {
+            /// Number of bits supported in virtual addresses.
+            7:0     va_bits;
+            /// Number of bits supported in physical addresses.
+            15:8    pa_bits;
+        }
+
+        /// Address spaces present.
+        pub(crate) AS_PRESENT(u32) @ 0x18 {
+            31:0    present;
+        }
+
+        /// CSF version information.
+        pub(crate) CSF_ID(u32) @ 0x1c {
+            /// MCU revision ID.
+            3:0     mcu_rev;
+            /// MCU minor revision number.
+            9:4     mcu_minor;
+            /// MCU major revision number.
+            15:10   mcu_major;
+            /// CSHW revision ID.
+            19:16   cshw_rev;
+            /// CSHW minor revision number.
+            25:20   cshw_minor;
+            /// CSHW major revision number.
+            31:26   cshw_major;
+        }
+
+        /// IRQ sources raw status.
+        /// Writing to this register forces bits on, but does not clear them.
+        pub(crate) GPU_IRQ_RAWSTAT(u32) @ 0x20 {
+            /// A GPU fault has occurred, a 1-bit boolean flag.
+            0:0     gpu_fault => bool;
+            /// A GPU fault has occurred, a 1-bit boolean flag.
+            1:1     gpu_protected_fault => bool;
+            /// Reset has completed, a 1-bit boolean flag.
+            8:8     reset_completed => bool;
+            /// Set when a single power domain has powered up or down, a 1-bit boolean flag.
+            9:9     power_changed_single => bool;
+            /// Set when the all pending power domain changes are completed, a 1-bit boolean flag.
+            10:10   power_changed_all => bool;
+            /// Set when cache cleaning has completed, a 1-bit boolean flag.
+            17:17   clean_caches_completed => bool;
+            /// Mirrors the doorbell interrupt line to the CPU, a 1-bit boolean flag.
+            18:18   doorbell_mirror => bool;
+            /// MCU requires attention, a 1-bit boolean flag.
+            19:19   mcu_status => bool;
+        }
+
+        /// IRQ sources to clear. Write only.
+        pub(crate) GPU_IRQ_CLEAR(u32) @ 0x24 {
+            /// Clear the GPU_FAULT interrupt, a 1-bit boolean flag.
+            0:0     gpu_fault => bool;
+            /// Clear the GPU_PROTECTED_FAULT interrupt, a 1-bit boolean flag.
+            1:1     gpu_protected_fault => bool;
+            /// Clear the RESET_COMPLETED interrupt, a 1-bit boolean flag.
+            8:8     reset_completed => bool;
+            /// Clear the POWER_CHANGED_SINGLE interrupt, a 1-bit boolean flag.
+            9:9     power_changed_single => bool;
+            /// Clear the POWER_CHANGED_ALL interrupt, a 1-bit boolean flag.
+            10:10   power_changed_all => bool;
+            /// Clear the CLEAN_CACHES_COMPLETED interrupt, a 1-bit boolean flag.
+            17:17   clean_caches_completed => bool;
+            /// Clear the MCU_STATUS interrupt, a 1-bit boolean flag.
+            19:19   mcu_status => bool;
+        }
+
+        /// IRQ sources enabled.
+        pub(crate) GPU_IRQ_MASK(u32) @ 0x28 {
+            /// Enable the GPU_FAULT interrupt, a 1-bit boolean flag.
+            0:0     gpu_fault => bool;
+            /// Enable the GPU_PROTECTED_FAULT interrupt, a 1-bit boolean flag.
+            1:1     gpu_protected_fault => bool;
+            /// Enable the RESET_COMPLETED interrupt, a 1-bit boolean flag.
+            8:8     reset_completed => bool;
+            /// Enable the POWER_CHANGED_SINGLE interrupt, a 1-bit boolean flag.
+            9:9     power_changed_single => bool;
+            /// Enable the POWER_CHANGED_ALL interrupt, a 1-bit boolean flag.
+            10:10   power_changed_all => bool;
+            /// Enable the CLEAN_CACHES_COMPLETED interrupt, a 1-bit boolean flag.
+            17:17   clean_caches_completed => bool;
+            /// Enable the DOORBELL_MIRROR interrupt, a 1-bit boolean flag.
+            18:18   doorbell_mirror => bool;
+            /// Enable the MCU_STATUS interrupt, a 1-bit boolean flag.
+            19:19   mcu_status => bool;
+        }
+
+        /// IRQ status for enabled sources. Read only.
+        pub(crate) GPU_IRQ_STATUS(u32) @ 0x2c {
+            /// GPU_FAULT interrupt status, a 1-bit boolean flag.
+            0:0     gpu_fault => bool;
+            /// GPU_PROTECTED_FAULT interrupt status, a 1-bit boolean flag.
+            1:1     gpu_protected_fault => bool;
+            /// RESET_COMPLETED interrupt status, a 1-bit boolean flag.
+            8:8     reset_completed => bool;
+            /// POWER_CHANGED_SINGLE interrupt status, a 1-bit boolean flag.
+            9:9     power_changed_single => bool;
+            /// POWER_CHANGED_ALL interrupt status, a 1-bit boolean flag.
+            10:10   power_changed_all => bool;
+            /// CLEAN_CACHES_COMPLETED interrupt status, a 1-bit boolean flag.
+            17:17   clean_caches_completed => bool;
+            /// DOORBELL_MIRROR interrupt status, a 1-bit boolean flag.
+            18:18   doorbell_mirror => bool;
+            /// MCU_STATUS interrupt status, a 1-bit boolean flag.
+            19:19   mcu_status => bool;
+        }
+    }
+
+    /// Helpers for GPU_COMMAND Register
+    #[derive(Copy, Clone, Debug)]
+    #[repr(u8)]
+    pub(crate) enum GpuCommand {
+        /// No operation. This is the default value.
+        Nop = 0,
+        /// Reset the GPU.
+        Reset = 1,
+        /// Flush caches.
+        FlushCaches = 4,
+        /// Clear GPU faults.
+        ClearFault = 7,
+    }
+
+    impl TryFrom<Bounded<u32, 8>> for GpuCommand {
+        type Error = Error;
+
+        fn try_from(val: Bounded<u32, 8>) -> Result<Self, Self::Error> {
+            match val.get() {
+                0 => Ok(GpuCommand::Nop),
+                1 => Ok(GpuCommand::Reset),
+                4 => Ok(GpuCommand::FlushCaches),
+                7 => Ok(GpuCommand::ClearFault),
+                _ => Err(EINVAL),
+            }
+        }
+    }
+
+    impl From<GpuCommand> for Bounded<u32, 8> {
+        fn from(cmd: GpuCommand) -> Self {
+            (cmd as u8).into()
+        }
+    }
+
+    /// Reset mode for [`GPU_COMMAND::reset()`].
+    #[derive(Copy, Clone, Debug)]
+    #[repr(u8)]
+    pub(crate) enum ResetMode {
+        /// Stop all external bus interfaces, then reset the entire GPU.
+        SoftReset = 1,
+        /// Force a full GPU reset.
+        HardReset = 2,
+    }
+
+    impl TryFrom<Bounded<u32, 4>> for ResetMode {
+        type Error = Error;
+
+        fn try_from(val: Bounded<u32, 4>) -> Result<Self, Self::Error> {
+            match val.get() {
+                1 => Ok(ResetMode::SoftReset),
+                2 => Ok(ResetMode::HardReset),
+                _ => Err(EINVAL),
+            }
+        }
+    }
+
+    impl From<ResetMode> for Bounded<u32, 4> {
+        fn from(mode: ResetMode) -> Self {
+            Bounded::try_new(mode as u32).unwrap()
+        }
+    }
+
+    /// Cache flush mode for [`GPU_COMMAND::flush_caches()`].
+    #[derive(Copy, Clone, Debug)]
+    #[repr(u8)]
+    pub(crate) enum FlushMode {
+        /// No flush.
+        None = 0,
+        /// Clean the caches.
+        Clean = 1,
+        /// Invalidate the caches.
+        Invalidate = 2,
+        /// Clean and invalidate the caches.
+        CleanInvalidate = 3,
+    }
+
+    impl TryFrom<Bounded<u32, 4>> for FlushMode {
+        type Error = Error;
+
+        fn try_from(val: Bounded<u32, 4>) -> Result<Self, Self::Error> {
+            match val.get() {
+                0 => Ok(FlushMode::None),
+                1 => Ok(FlushMode::Clean),
+                2 => Ok(FlushMode::Invalidate),
+                3 => Ok(FlushMode::CleanInvalidate),
+                _ => Err(EINVAL),
+            }
+        }
+    }
+
+    impl From<FlushMode> for Bounded<u32, 4> {
+        fn from(mode: FlushMode) -> Self {
+            Bounded::try_new(mode as u32).unwrap()
+        }
+    }
+
+    register! {
+        /// GPU command register.
+        ///
+        /// Use the constructor methods to create commands:
+        /// - [`GPU_COMMAND::nop()`]
+        /// - [`GPU_COMMAND::reset()`]
+        /// - [`GPU_COMMAND::flush_caches()`]
+        /// - [`GPU_COMMAND::clear_fault()`]
+        pub(crate) GPU_COMMAND (u32) @ 0x30 {
+            7:0     command ?=> GpuCommand;
+        }
+        /// Internal alias for GPU_COMMAND in reset mode.
+        /// Use [`GPU_COMMAND::reset()`] instead.
+        GPU_COMMAND_RESET (u32) => GPU_COMMAND {
+            7:0     command ?=> GpuCommand;
+            11:8    reset_mode ?=> ResetMode;
+        }
+
+        /// Internal alias for GPU_COMMAND in cache flush mode.
+        /// Use [`GPU_COMMAND::flush_caches()`] instead.
+        GPU_COMMAND_FLUSH (u32) => GPU_COMMAND {
+            7:0     command ?=> GpuCommand;
+            /// L2 cache flush mode.
+            11:8    l2_flush ?=> FlushMode;
+            /// Shader core load/store cache flush mode.
+            15:12   lsc_flush ?=> FlushMode;
+            /// Shader core other caches flush mode.
+            19:16   other_flush ?=> FlushMode;
+        }
+    }
+
+    impl GPU_COMMAND {
+        /// Create a NOP command.
+        pub(crate) fn nop() -> Self {
+            Self::zeroed()
+        }
+
+        /// Create a reset command with the specified reset mode.
+        pub(crate) fn reset(mode: ResetMode) -> Self {
+            Self::from_raw(
+                GPU_COMMAND_RESET::zeroed()
+                    .with_command(GpuCommand::Reset)
+                    .with_reset_mode(mode)
+                    .into_raw(),
+            )
+        }
+
+        /// Create a cache flush command with the specified flush modes.
+        pub(crate) fn flush_caches(l2: FlushMode, lsc: FlushMode, other: FlushMode) -> Self {
+            Self::from_raw(
+                GPU_COMMAND_FLUSH::zeroed()
+                    .with_command(GpuCommand::FlushCaches)
+                    .with_l2_flush(l2)
+                    .with_lsc_flush(lsc)
+                    .with_other_flush(other)
+                    .into_raw(),
+            )
+        }
+
+        /// Create a clear fault command.
+        pub(crate) fn clear_fault() -> Self {
+            Self::zeroed().with_command(GpuCommand::ClearFault)
+        }
+    }
+
+    register! {
+        /// GPU status register. Read only.
+        pub(crate) GPU_STATUS(u32) @ 0x34 {
+            /// GPU active, a 1-bit boolean flag.
+            0:0     gpu_active => bool;
+            /// Power manager active, a 1-bit boolean flag
+            1:1     pwr_active => bool;
+            /// Page fault active, a 1-bit boolean flag.
+            4:4     page_fault => bool;
+            /// Protected mode active, a 1-bit boolean flag.
+            7:7     protected_mode_active => bool;
+            /// Debug mode active, a 1-bit boolean flag.
+            8:8     gpu_dbg_enabled => bool;
+        }
+    }
+
+    #[derive(Copy, Clone, Debug)]
+    #[repr(u8)]
+    pub(crate) enum ExceptionType {
+        /// Exception type: No error.
+        Ok = 0x00,
+        /// Exception type: GPU external bus error.
+        GpuBusFault = 0x80,
+        /// Exception type: GPU shareability error.
+        GpuShareabilityFault = 0x88,
+        /// Exception type: System shareability error.
+        SystemShareabilityFault = 0x89,
+        /// Exception type: GPU cacheability error.
+        GpuCacheabilityFault = 0x8A,
+    }
+
+    impl TryFrom<Bounded<u32, 8>> for ExceptionType {
+        type Error = Error;
+
+        fn try_from(val: Bounded<u32, 8>) -> Result<Self, Self::Error> {
+            match val.get() {
+                0x00 => Ok(ExceptionType::Ok),
+                0x80 => Ok(ExceptionType::GpuBusFault),
+                0x88 => Ok(ExceptionType::GpuShareabilityFault),
+                0x89 => Ok(ExceptionType::SystemShareabilityFault),
+                0x8A => Ok(ExceptionType::GpuCacheabilityFault),
+                _ => Err(EINVAL),
+            }
+        }
+    }
+
+    impl From<ExceptionType> for Bounded<u32, 8> {
+        fn from(exc: ExceptionType) -> Self {
+            (exc as u8).into()
+        }
+    }
+
+    #[derive(Copy, Clone, Debug)]
+    #[repr(u8)]
+    pub(crate) enum AccessType {
+        /// Access type: An atomic (read/write) transaction.
+        Atomic = 0,
+        /// Access type: An execute transaction.
+        Execute = 1,
+        /// Access type: A read transaction.
+        Read = 2,
+        /// Access type: A write transaction.
+        Write = 3,
+    }
+
+    impl From<Bounded<u32, 2>> for AccessType {
+        fn from(val: Bounded<u32, 2>) -> Self {
+            match val.get() {
+                0 => AccessType::Atomic,
+                1 => AccessType::Execute,
+                2 => AccessType::Read,
+                3 => AccessType::Write,
+                _ => unreachable!(),
+            }
+        }
+    }
+
+    impl From<AccessType> for Bounded<u32, 2> {
+        fn from(access: AccessType) -> Self {
+            Bounded::try_new(access as u32).unwrap()
+        }
+    }
+
+    register! {
+        /// GPU fault status register. Read only.
+        pub(crate) GPU_FAULTSTATUS(u32) @ 0x3c {
+            /// Exception type.
+            7:0     exception_type ?=> ExceptionType;
+            /// Access type.
+            9:8     access_type => AccessType;
+            /// The GPU_FAULTADDRESS is valid, a 1-bit boolean flag.
+            10:10   address_valid => bool;
+            /// The JASID field is valid, a 1-bit boolean flag.
+            11:11   jasid_valid => bool;
+            /// JASID of the fault, if known.
+            15:12   jasid;
+            /// ID of the source that triggered the fault.
+            31:16   source_id;
+        }
+
+        /// GPU fault address. Read only.
+        /// Once a fault is reported, it must be manually cleared by issuing a
+        /// [`GPU_COMMAND::clear_fault()`] command to the [`GPU_COMMAND`] register. No further GPU
+        /// faults will be reported until the previous fault has been cleared.
+        pub(crate) GPU_FAULTADDRESS(u64) @ 0x40 {
+            63:0    pointer;
+        }
+
+        /// Level 2 cache configuration.
+        pub(crate) L2_CONFIG(u32) @ 0x48 {
+            /// Requested cache size.
+            23:16   cache_size;
+            /// Requested hash function index.
+            31:24   hash_function;
+        }
+
+        /// Global time stamp offset.
+        pub(crate) TIMESTAMP_OFFSET(u64) @ 0x88 {
+            63:0    offset;
+        }
+
+        /// GPU cycle counter. Read only.
+        pub(crate) CYCLE_COUNT(u64) @ 0x90 {
+            63:0    count;
+        }
+
+        /// Global time stamp. Read only.
+        pub(crate) TIMESTAMP(u64) @ 0x98 {
+            63:0    timestamp;
+        }
+
+        /// Maximum number of threads per core. Read only constant.
+        pub(crate) THREAD_MAX_THREADS(u32) @ 0xa0 {
+            31:0    threads;
+        }
+
+        /// Maximum number of threads per workgroup. Read only constant.
+        pub(crate) THREAD_MAX_WORKGROUP_SIZE(u32) @ 0xa4 {
+            31:0    threads;
+        }
+
+        /// Maximum number of threads per barrier. Read only constant.
+        pub(crate) THREAD_MAX_BARRIER_SIZE(u32) @ 0xa8 {
+            31:0    threads;
+        }
+
+        /// Thread features. Read only constant.
+        pub(crate) THREAD_FEATURES(u32) @ 0xac {
+            /// Total number of registers per core.
+            21:0    max_registers;
+            /// Implementation technology type.
+            23:22   implementation_technology;
+            /// Maximum number of compute tasks waiting.
+            31:24   max_task_queue;
+        }
+
+        /// Support flags for compressed texture formats. Read only constant.
+        ///
+        /// A bitmap where each bit indicates support for a specific compressed texture format.
+        /// The bit position maps to an opaque format ID (`texture_features_key_t` in spec).
+        pub(crate) TEXTURE_FEATURES(u32)[4] @ 0xb0 {
+            31:0    supported_formats;
+        }
+
+        /// Shader core present bitmap. Read only constant.
+        pub(crate) SHADER_PRESENT(u64) @ 0x100 {
+            63:0    present;
+        }
+
+        /// Tiler present bitmap. Read only constant.
+        pub(crate) TILER_PRESENT(u64) @ 0x110 {
+            63:0    present;
+        }
+
+        /// L2 cache present bitmap. Read only constant.
+        pub(crate) L2_PRESENT(u64) @ 0x120 {
+            63:0    present;
+        }
+
+        /// Shader core ready bitmap. Read only.
+        pub(crate) SHADER_READY(u64) @ 0x140 {
+            63:0    ready;
+        }
+
+        /// Tiler ready bitmap. Read only.
+        pub(crate) TILER_READY(u64) @ 0x150 {
+            63:0    ready;
+        }
+
+        /// L2 ready bitmap. Read only.
+        pub(crate) L2_READY(u64) @ 0x160 {
+            63:0    ready;
+        }
+
+        /// Shader core power up bitmap.
+        pub(crate) SHADER_PWRON(u64) @ 0x180 {
+            63:0    request;
+        }
+
+        /// Tiler power up bitmap.
+        pub(crate) TILER_PWRON(u64) @ 0x190 {
+            63:0    request;
+        }
+
+        /// L2 power up bitmap.
+        pub(crate) L2_PWRON(u64) @ 0x1a0 {
+            63:0 request;
+        }
+
+        /// Shader core power down bitmap.
+        pub(crate) SHADER_PWROFF(u64) @ 0x1c0 {
+            63:0 request;
+        }
+
+        /// Tiler power down bitmap.
+        pub(crate) TILER_PWROFF(u64) @ 0x1d0 {
+            63:0 request;
+        }
+
+        /// L2 power down bitmap.
+        pub(crate) L2_PWROFF(u64) @ 0x1e0 {
+            63:0 request;
+        }
+
+        /// Shader core power transition bitmap. Read-only.
+        pub(crate) SHADER_PWRTRANS(u64) @ 0x200 {
+            63:0 changing;
+        }
+
+        /// Tiler power transition bitmap. Read-only.
+        pub(crate) TILER_PWRTRANS(u64) @ 0x210 {
+            63:0 changing;
+        }
+
+        /// L2 power transition bitmap. Read-only.
+        pub(crate) L2_PWRTRANS(u64) @ 0x220 {
+            63:0 changing;
+        }
+
+        /// Shader core active bitmap. Read-only.
+        pub(crate) SHADER_PWRACTIVE(u64) @ 0x240 {
+            63:0 active;
+        }
+
+        /// Tiler active bitmap. Read-only.
+        pub(crate) TILER_PWRACTIVE(u64) @ 0x250 {
+            63:0 active;
+        }
+
+        /// L2 active bitmap.  Read-only.
+        pub(crate) L2_PWRACTIVE(u64) @ 0x260 {
+            63:0 active;
+        }
+
+        /// Revision ID. Read only constant.
+        pub(crate) REVIDR(u32) @ 0x280 {
+            31:0    revision;
+        }
+
+        /// Coherency features present. Read only constant.
+        /// Supported protocols on the interconnect between the GPU and the
+        /// system into which it is integrated.
+        pub(crate) COHERENCY_FEATURES(u32) @ 0x300 {
+            /// ACE-Lite protocol supported, a 1-bit boolean flag.
+            0:0     ace_lite => bool;
+            /// ACE protocol supported, a 1-bit boolean flag.
+            1:1     ace => bool;
+        }
+    }
+
+    #[derive(Copy, Clone, Debug)]
+    #[repr(u8)]
+    pub(crate) enum CoherencyMode {
+        /// ACE-Lite coherency protocol.
+        AceLite = uapi::drm_panthor_gpu_coherency_DRM_PANTHOR_GPU_COHERENCY_ACE_LITE as u8,
+        /// ACE coherency protocol.
+        Ace = uapi::drm_panthor_gpu_coherency_DRM_PANTHOR_GPU_COHERENCY_ACE as u8,
+        /// No coherency protocol.
+        None = uapi::drm_panthor_gpu_coherency_DRM_PANTHOR_GPU_COHERENCY_NONE as u8,
+    }
+
+    impl TryFrom<Bounded<u32, 32>> for CoherencyMode {
+        type Error = Error;
+
+        fn try_from(val: Bounded<u32, 32>) -> Result<Self, Self::Error> {
+            match val.get() {
+                0 => Ok(CoherencyMode::AceLite),
+                1 => Ok(CoherencyMode::Ace),
+                31 => Ok(CoherencyMode::None),
+                _ => Err(EINVAL),
+            }
+        }
+    }
+
+    impl From<CoherencyMode> for Bounded<u32, 32> {
+        fn from(mode: CoherencyMode) -> Self {
+            (mode as u8).into()
+        }
+    }
+
+    register! {
+        /// Coherency enable. An index of which coherency protocols should be used.
+        /// This register only selects the protocol for coherency messages on the
+        /// interconnect. This is not to enable or disable coherency controlled by MMU.
+        pub(crate) COHERENCY_ENABLE(u32) @ 0x304 {
+            31:0    l2_cache_protocol_select ?=> CoherencyMode;
+        }
+    }
+
+    /// Helpers for MCU_CONTROL register
+    #[derive(Copy, Clone, Debug)]
+    #[repr(u8)]
+    pub(crate) enum McuControlMode {
+        /// Disable the MCU.
+        Disable = 0,
+        /// Enable the MCU.
+        Enable = 1,
+        /// Enable the MCU to execute and automatically reboot after a fast reset.
+        Auto = 2,
+    }
+
+    impl TryFrom<Bounded<u32, 2>> for McuControlMode {
+        type Error = Error;
+
+        fn try_from(val: Bounded<u32, 2>) -> Result<Self, Self::Error> {
+            match val.get() {
+                0 => Ok(McuControlMode::Disable),
+                1 => Ok(McuControlMode::Enable),
+                2 => Ok(McuControlMode::Auto),
+                _ => Err(EINVAL),
+            }
+        }
+    }
+
+    impl From<McuControlMode> for Bounded<u32, 2> {
+        fn from(mode: McuControlMode) -> Self {
+            Bounded::try_new(mode as u32).unwrap()
+        }
+    }
+
+    register! {
+        /// MCU control.
+        pub(crate) MCU_CONTROL(u32) @ 0x700 {
+            /// Request MCU state change.
+            1:0 req ?=> McuControlMode;
+        }
+    }
+
+    /// Helpers for MCU_STATUS register
+    #[derive(Copy, Clone, Debug)]
+    #[repr(u8)]
+    pub(crate) enum McuStatus {
+        /// MCU is disabled.
+        Disabled = 0,
+        /// MCU is enabled.
+        Enabled = 1,
+        /// The MCU has halted by itself in an orderly manner to enable the core group to be powered down.
+        Halt = 2,
+        /// The MCU has encountered an error that prevents it from continuing.
+        Fatal = 3,
+    }
+
+    impl From<Bounded<u32, 2>> for McuStatus {
+        fn from(val: Bounded<u32, 2>) -> Self {
+            match val.get() {
+                0 => McuStatus::Disabled,
+                1 => McuStatus::Enabled,
+                2 => McuStatus::Halt,
+                3 => McuStatus::Fatal,
+                _ => unreachable!(),
+            }
+        }
+    }
+
+    impl From<McuStatus> for Bounded<u32, 2> {
+        fn from(status: McuStatus) -> Self {
+            Bounded::try_new(status as u32).unwrap()
+        }
+    }
+
+    register! {
+        /// MCU status. Read only.
+        pub(crate) MCU_STATUS(u32) @ 0x704 {
+            /// Read current state of MCU.
+            1:0 value => McuStatus;
+        }
+    }
+}
 
 pub(crate) const JOB_IRQ_RAWSTAT: Register<0x1000> = Register;
 pub(crate) const JOB_IRQ_CLEAR: Register<0x1004> = Register;

-- 
2.52.0


  reply	other threads:[~2026-03-24  0:18 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-24  0:18 [PATCH v3 00/12] drm/tyr: Use register! macro Deborah Brouwer
2026-03-24  0:18 ` Deborah Brouwer [this message]
2026-03-24  9:56   ` [PATCH v3 01/12] drm/tyr: Use register! macro for GPU_CONTROL Boris Brezillon
2026-03-24 11:23   ` Danilo Krummrich
2026-03-24 12:06     ` Boris Brezillon
2026-03-24 17:31       ` Danilo Krummrich
2026-03-24 18:15         ` Boris Brezillon
2026-03-24 19:03           ` Danilo Krummrich
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 02/12] drm/tyr: Print GPU_ID without filtering Deborah Brouwer
2026-03-24  9:54   ` Boris Brezillon
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 03/12] drm/tyr: Set interconnect coherency during probe Deborah Brouwer
2026-03-24  9:55   ` Boris Brezillon
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 04/12] drm/tyr: Use register! macro for JOB_CONTROL Deborah Brouwer
2026-03-24 10:00   ` Boris Brezillon
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 05/12] drm/tyr: Use register! macro for MMU_CONTROL Deborah Brouwer
2026-03-24 10:01   ` Boris Brezillon
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 06/12] drm/tyr: Remove custom register struct Deborah Brouwer
2026-03-24 10:02   ` Boris Brezillon
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 07/12] drm/tyr: Add MMU address space registers Deborah Brouwer
2026-03-24 10:03   ` Boris Brezillon
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 08/12] drm/tyr: Add fields for MEMATTR register Deborah Brouwer
2026-03-24 10:05   ` Boris Brezillon
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 09/12] drm/tyr: Add fields for COMMAND register Deborah Brouwer
2026-03-24 10:09   ` Boris Brezillon
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 10/12] drm/tyr: Add fields for FAULTSTATUS register Deborah Brouwer
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 11/12] drm/tyr: Add fields for TRANSCFG register Deborah Brouwer
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24  0:18 ` [PATCH v3 12/12] drm/tyr: Add DOORBELL_BLOCK registers Deborah Brouwer
2026-03-24 10:10   ` Boris Brezillon
2026-03-24 21:08   ` Claude review: " Claude Code Review Bot
2026-03-24 10:58 ` [PATCH v3 00/12] drm/tyr: Use register! macro Alice Ryhl
2026-03-24 12:35   ` Boris Brezillon
2026-03-24 21:08 ` Claude review: " Claude Code Review Bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260323-b4-tyr-use-register-macro-v3-v3-1-a87daf9e4701@collabora.com \
    --to=deborah.brouwer@collabora.com \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=airlied@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=boris.brezillon@collabora.com \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=dirk.behme@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gary@garyguo.net \
    --cc=lossin@kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=simona@ffwll.ch \
    --cc=steven.price@arm.com \
    --cc=tmgross@umich.edu \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox