From: Boris Brezillon <boris.brezillon@collabora.com>
To: Deborah Brouwer <deborah.brouwer@collabora.com>
Cc: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org,
"Boqun Feng" <boqun@kernel.org>,
"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>,
"Dirk Behme" <dirk.behme@gmail.com>,
"Alexandre Courbot" <acourbot@nvidia.com>
Subject: Re: [PATCH v3 01/12] drm/tyr: Use register! macro for GPU_CONTROL
Date: Tue, 24 Mar 2026 10:56:12 +0100 [thread overview]
Message-ID: <20260324105612.333eab50@fedora> (raw)
In-Reply-To: <20260323-b4-tyr-use-register-macro-v3-v3-1-a87daf9e4701@collabora.com>
On Mon, 23 Mar 2026 17:18:03 -0700
Deborah Brouwer <deborah.brouwer@collabora.com> wrote:
> 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>
Acked-by: Boris Brezillon <boris.brezillon@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;
>
next prev parent reply other threads:[~2026-03-24 9:56 UTC|newest]
Thread overview: 30+ 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 ` [PATCH v3 01/12] drm/tyr: Use register! macro for GPU_CONTROL Deborah Brouwer
2026-03-24 9:56 ` Boris Brezillon [this message]
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 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 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 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 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 0:18 ` [PATCH v3 06/12] drm/tyr: Remove custom register struct Deborah Brouwer
2026-03-24 10:02 ` Boris Brezillon
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 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 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 0:18 ` [PATCH v3 10/12] drm/tyr: Add fields for FAULTSTATUS register Deborah Brouwer
2026-03-24 0:18 ` [PATCH v3 11/12] drm/tyr: Add fields for TRANSCFG register Deborah Brouwer
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 10:58 ` [PATCH v3 00/12] drm/tyr: Use register! macro Alice Ryhl
2026-03-24 12:35 ` Boris Brezillon
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=20260324105612.333eab50@fedora \
--to=boris.brezillon@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=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=deborah.brouwer@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