From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from bali.collaboradmins.com (bali.collaboradmins.com [148.251.105.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED1A53E025D for ; Tue, 24 Mar 2026 09:56:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.251.105.195 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774346185; cv=none; b=JQM5IpH3Fl6E3FIivFhM60I//RxrAa3vHGmBaUahy/6h15FHItEOGMOKoXLFb2AUByR2hGitUxQsHXWfDYr88wF7VnXeWoub07h4Y71+K6PfwUPun1HrEczXz5XW6ql83bFgV4BeH63phTAGcyaXKQK+uRj2AaTn+JhHHi2fSAI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774346185; c=relaxed/simple; bh=EIFmO3MEc75pt+/aVbrGA58k40f8sU4jbmiz+aNjWF4=; h=Date:From:To:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=VrBm3soyhbZzUgYM/2i3qTEqqWFexnD5ljQpsbZqrVr1hfVoi30uJkDt7uO8mNHpod4edVgmjYQw0BS0u3aEk63H2xm9t4bCkWYuQXfAA0sztoN+g0Nx5uUZYJuam+XhRrhq+2pikM8HfZ3u5PwineklDMeTsUBeGQfGW/SIk0Q= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b=pA7IQQWQ; arc=none smtp.client-ip=148.251.105.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=collabora.com header.i=@collabora.com header.b="pA7IQQWQ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1774346177; bh=EIFmO3MEc75pt+/aVbrGA58k40f8sU4jbmiz+aNjWF4=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=pA7IQQWQTzDHtOKsueHvLSFu5taNlf29nyWmT/1eCOK6GiD66djs0zpg45Nfi1+t9 jTeu6/NTzH/uLS3fSubViQrzD2bhRbS/BNIjVPs60O+kl5DkHu7u7j5R8oaAGvqnu3 bBOWLbkMdnYOusJdjE0JZ4qsFSqY/OjrRGKIQUllEfzrVzMzG5B/ZRk3tNSVvYmm0H AUgetEDWogxl2pqXsLVEelnRasipH2r28Pw6pXjrLOmcZ6vZgBDx8QpPxOnMgChqB7 PhMrdWnCMXLeSGk+/mc36/86XM5nJidKh+7bVxDoNFirfwFkX8kB/eiBaJuu4tL5qg W8WY2iiyiApdQ== Received: from fedora (unknown [IPv6:2a01:e0a:2c:6930:d919:a6e:5ea1:8a9f]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (prime256v1) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: bbrezillon) by bali.collaboradmins.com (Postfix) with ESMTPSA id 5400517E59B7; Tue, 24 Mar 2026 10:56:16 +0100 (CET) Date: Tue, 24 Mar 2026 10:56:12 +0100 From: Boris Brezillon To: Deborah Brouwer Cc: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, Boqun Feng , Danilo Krummrich , Alice Ryhl , Daniel Almeida , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Miguel Ojeda , Gary Guo , =?UTF-8?B?QmrDtnJu?= Roy Baron , Benno Lossin , Andreas Hindborg , Trevor Gross , Steven Price , Dirk Behme , Alexandre Courbot Subject: Re: [PATCH v3 01/12] drm/tyr: Use register! macro for GPU_CONTROL Message-ID: <20260324105612.333eab50@fedora> In-Reply-To: <20260323-b4-tyr-use-register-macro-v3-v3-1-a87daf9e4701@collabora.com> References: <20260323-b4-tyr-use-register-macro-v3-v3-0-a87daf9e4701@collabora.com> <20260323-b4-tyr-use-register-macro-v3-v3-1-a87daf9e4701@collabora.com> Organization: Collabora X-Mailer: Claws Mail 4.3.1 (GTK 3.24.51; x86_64-redhat-linux-gnu) Precedence: bulk X-Mailing-List: rust-for-linux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Mon, 23 Mar 2026 17:18:03 -0700 Deborah Brouwer wrote: > From: Daniel Almeida > > 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 > Co-developed-by: Deborah Brouwer > Signed-off-by: Deborah Brouwer Acked-by: Boris Brezillon > --- > 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; > @@ -78,11 +84,15 @@ unsafe impl Send for TyrDrmDeviceData {} > unsafe impl Sync for TyrDrmDeviceData {} > > fn issue_soft_reset(dev: &Device, iomem: &Devres) -> 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 = 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, iomem: &Devres) -> Result { > - 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 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, iomem: &Devres) -> 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, iomem: &Devres) -> 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, iomem: &Devres, 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> for GpuCommand { > + type Error = Error; > + > + fn try_from(val: Bounded) -> Result { > + match val.get() { > + 0 => Ok(GpuCommand::Nop), > + 1 => Ok(GpuCommand::Reset), > + 4 => Ok(GpuCommand::FlushCaches), > + 7 => Ok(GpuCommand::ClearFault), > + _ => Err(EINVAL), > + } > + } > + } > + > + impl From for Bounded { > + 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> for ResetMode { > + type Error = Error; > + > + fn try_from(val: Bounded) -> Result { > + match val.get() { > + 1 => Ok(ResetMode::SoftReset), > + 2 => Ok(ResetMode::HardReset), > + _ => Err(EINVAL), > + } > + } > + } > + > + impl From for Bounded { > + 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> for FlushMode { > + type Error = Error; > + > + fn try_from(val: Bounded) -> Result { > + match val.get() { > + 0 => Ok(FlushMode::None), > + 1 => Ok(FlushMode::Clean), > + 2 => Ok(FlushMode::Invalidate), > + 3 => Ok(FlushMode::CleanInvalidate), > + _ => Err(EINVAL), > + } > + } > + } > + > + impl From for Bounded { > + 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> for ExceptionType { > + type Error = Error; > + > + fn try_from(val: Bounded) -> Result { > + 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 for Bounded { > + 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> for AccessType { > + fn from(val: Bounded) -> Self { > + match val.get() { > + 0 => AccessType::Atomic, > + 1 => AccessType::Execute, > + 2 => AccessType::Read, > + 3 => AccessType::Write, > + _ => unreachable!(), > + } > + } > + } > + > + impl From for Bounded { > + 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> for CoherencyMode { > + type Error = Error; > + > + fn try_from(val: Bounded) -> Result { > + match val.get() { > + 0 => Ok(CoherencyMode::AceLite), > + 1 => Ok(CoherencyMode::Ace), > + 31 => Ok(CoherencyMode::None), > + _ => Err(EINVAL), > + } > + } > + } > + > + impl From for Bounded { > + 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> for McuControlMode { > + type Error = Error; > + > + fn try_from(val: Bounded) -> Result { > + match val.get() { > + 0 => Ok(McuControlMode::Disable), > + 1 => Ok(McuControlMode::Enable), > + 2 => Ok(McuControlMode::Auto), > + _ => Err(EINVAL), > + } > + } > + } > + > + impl From for Bounded { > + 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> for McuStatus { > + fn from(val: Bounded) -> Self { > + match val.get() { > + 0 => McuStatus::Disabled, > + 1 => McuStatus::Enabled, > + 2 => McuStatus::Halt, > + 3 => McuStatus::Fatal, > + _ => unreachable!(), > + } > + } > + } > + > + impl From for Bounded { > + 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; >