diff --git a/.gitmodules b/.gitmodules index 3f0bd70983..4110f3f94e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,3 +12,6 @@ [submodule "hw/latest/i3c-core-rtl"] path = hw/latest/i3c-core-rtl url = https://github.com/chipsalliance/i3c-core.git +[submodule "hw/latest/caliptra-ss"] + path = hw/latest/caliptra-ss + url = https://github.com/chipsalliance/caliptra-ss.git diff --git a/drivers/src/dma.rs b/drivers/src/dma.rs index 2bb187c2db..614d19c8ad 100644 --- a/drivers/src/dma.rs +++ b/drivers/src/dma.rs @@ -17,6 +17,7 @@ use caliptra_registers::axi_dma::{ enums::{RdRouteE, WrRouteE}, AxiDmaReg, RegisterBlock, }; +use caliptra_registers::caliptra_otp_ctrl::RegisterBlock as FuseCtrlRegisterBlock; use caliptra_registers::i3ccsr::RegisterBlock as I3CRegisterBlock; use core::{cell::Cell, mem::size_of, ops::Add}; use ureg::{Mmio, MmioMut, RealMmioMut}; @@ -612,3 +613,55 @@ impl<'a> DmaRecovery<'a> { }); } } + +pub struct DmaOtpCtrl<'a> { + base: AxiAddr, + dma: &'a Dma, +} + +impl<'a> DmaOtpCtrl<'a> { + #[inline(always)] + pub fn new(base: AxiAddr, dma: &'a Dma) -> Self { + Self { base, dma } + } + + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn with_regs(&self, f: F) -> CaliptraResult + where + F: FnOnce(FuseCtrlRegisterBlock<&DmaMmio>) -> T, + { + let mmio = DmaMmio::new(self.base, self.dma); + // SAFETY: we aren't referencing memory directly + let regs = unsafe { + FuseCtrlRegisterBlock::new_with_mmio( + // substract the recovery offset since all recovery registers are relative to it + core::ptr::null_mut::(), + &mmio, + ) + }; + let t = f(regs); + mmio.check_error(t) + } + + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn with_regs_mut(&self, f: F) -> CaliptraResult + where + F: FnOnce(FuseCtrlRegisterBlock<&DmaMmio>) -> T, + { + let mmio = DmaMmio::new(self.base, self.dma); + // SAFETY: we aren't referencing memory directly + let regs = unsafe { + FuseCtrlRegisterBlock::new_with_mmio( + // substract the recovery offset since all recovery registers are relative to it + core::ptr::null_mut::(), + &mmio, + ) + }; + let t = f(regs); + mmio.check_error(t) + } +} diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs index a8196be5ec..11f26a7143 100644 --- a/drivers/src/lib.rs +++ b/drivers/src/lib.rs @@ -61,7 +61,7 @@ pub use caliptra_error::{CaliptraError, CaliptraResult}; pub use csrng::{Csrng, HealthFailCounts as CsrngHealthFailCounts, Seed as CsrngSeed}; pub use data_vault::{ColdResetEntries, DataVault, WarmResetEntries}; pub use dma::{ - AxiAddr, Dma, DmaReadTarget, DmaReadTransaction, DmaRecovery, DmaWriteOrigin, + AxiAddr, Dma, DmaOtpCtrl, DmaReadTarget, DmaReadTransaction, DmaRecovery, DmaWriteOrigin, DmaWriteTransaction, }; pub use doe::DeobfuscationEngine; diff --git a/hw/latest/caliptra-ss b/hw/latest/caliptra-ss new file mode 160000 index 0000000000..9761642fce --- /dev/null +++ b/hw/latest/caliptra-ss @@ -0,0 +1 @@ +Subproject commit 9761642fce88edb376f60cad0ec39cf6dce5462f diff --git a/hw/latest/registers/src/caliptra_otp_ctrl.rs b/hw/latest/registers/src/caliptra_otp_ctrl.rs new file mode 100644 index 0000000000..51efe3392e --- /dev/null +++ b/hw/latest/registers/src/caliptra_otp_ctrl.rs @@ -0,0 +1,2585 @@ +// Licensed under the Apache-2.0 license. +// +// generated by caliptra_registers_generator with caliptra-rtl repo at 7b80cfa4dac7707450bb0203efbac8d2b16c0685 +// +#![allow(clippy::erasing_op)] +#![allow(clippy::identity_op)] +/// A zero-sized type that represents ownership of this +/// peripheral, used to get access to a Register lock. Most +/// programs create one of these in unsafe code near the top of +/// main(), and pass it to the driver responsible for managing +/// all access to the hardware. +pub struct CaliptraOtpCtrl { + _priv: (), +} +impl CaliptraOtpCtrl { + pub const PTR: *mut u32 = 0x10060000 as *mut u32; + /// # Safety + /// + /// Caller must ensure that all concurrent use of this + /// peripheral in the firmware is done so in a compatible + /// way. The simplest way to enforce this is to only call + /// this function once. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _priv: () } + } + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn regs(&self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn regs_mut(&mut self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } +} +#[allow(dead_code)] +#[derive(Clone, Copy)] +pub struct RegisterBlock> { + ptr: *mut u32, + mmio: TMmio, +} +impl RegisterBlock { + /// # Safety + /// + /// The caller is responsible for ensuring that ptr is valid for + /// volatile reads and writes at any of the offsets in this register + /// block. + #[inline(always)] + pub unsafe fn new(ptr: *mut u32) -> Self { + Self { + ptr, + mmio: core::default::Default::default(), + } + } +} +impl RegisterBlock { + /// # Safety + /// + /// The caller is responsible for ensuring that ptr is valid for + /// volatile reads and writes at any of the offsets in this register + /// block. + #[inline(always)] + pub unsafe fn new_with_mmio(ptr: *mut u32, mmio: TMmio) -> Self { + Self { ptr, mmio } + } + /// Read value: [`caliptra_otp_ctrl::regs::InterruptStateReadVal`]; Write value: [`caliptra_otp_ctrl::regs::InterruptStateWriteVal`] + #[inline(always)] + pub fn interrupt_state( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::InterruptEnableReadVal`]; Write value: [`caliptra_otp_ctrl::regs::InterruptEnableWriteVal`] + #[inline(always)] + pub fn interrupt_enable( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::InterruptTestReadVal`]; Write value: [`caliptra_otp_ctrl::regs::InterruptTestWriteVal`] + #[inline(always)] + pub fn interrupt_test( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(8 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::AlertTestReadVal`]; Write value: [`caliptra_otp_ctrl::regs::AlertTestWriteVal`] + #[inline(always)] + pub fn alert_test(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0xc / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::StatusReadVal`]; Write value: [`caliptra_otp_ctrl::regs::StatusWriteVal`] + #[inline(always)] + pub fn status(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x10 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Register write enable for all direct access interface registers. + /// + /// Read value: [`caliptra_otp_ctrl::regs::DirectAccessRegwenReadVal`]; Write value: [`caliptra_otp_ctrl::regs::DirectAccessRegwenWriteVal`] + #[inline(always)] + pub fn direct_access_regwen( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x38 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Command register for direct accesses. + /// + /// Read value: [`caliptra_otp_ctrl::regs::DirectAccessCmdReadVal`]; Write value: [`caliptra_otp_ctrl::regs::DirectAccessCmdWriteVal`] + #[inline(always)] + pub fn direct_access_cmd( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x3c / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Address register for direct accesses. + /// + /// Read value: [`caliptra_otp_ctrl::regs::DirectAccessAddressReadVal`]; Write value: [`caliptra_otp_ctrl::regs::DirectAccessAddressWriteVal`] + #[inline(always)] + pub fn direct_access_address( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x40 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Register write enable for !!CHECK_TRIGGER. + /// + /// Read value: [`caliptra_otp_ctrl::regs::CheckTriggerRegwenReadVal`]; Write value: [`caliptra_otp_ctrl::regs::CheckTriggerRegwenWriteVal`] + #[inline(always)] + pub fn check_trigger_regwen( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x54 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Command register for direct accesses. + /// + /// Read value: [`caliptra_otp_ctrl::regs::CheckTriggerReadVal`]; Write value: [`caliptra_otp_ctrl::regs::CheckTriggerWriteVal`] + #[inline(always)] + pub fn check_trigger( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x58 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Register write enable for !!INTEGRITY_CHECK_PERIOD and !!CONSISTENCY_CHECK_PERIOD. + /// + /// Read value: [`caliptra_otp_ctrl::regs::CheckRegwenReadVal`]; Write value: [`caliptra_otp_ctrl::regs::CheckRegwenWriteVal`] + #[inline(always)] + pub fn check_regwen( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x5c / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Timeout value for the integrity and consistency checks. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn check_timeout( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x60 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// This value specifies the maximum period that can be generated pseudo-randomly.\nOnly applies to the HW_CFG* and SECRET* partitions once they are locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn integrity_check_period( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x64 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// This value specifies the maximum period that can be generated pseudo-randomly.\nThis applies to the LIFE_CYCLE partition and the HW_CFG* and SECRET* partitions once they are locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn consistency_check_period( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x68 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Runtime read lock for the VENDOR_TEST partition. + /// + /// Read value: [`caliptra_otp_ctrl::regs::VendorTestReadLockReadVal`]; Write value: [`caliptra_otp_ctrl::regs::VendorTestReadLockWriteVal`] + #[inline(always)] + pub fn vendor_test_read_lock( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x6c / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Runtime read lock for the NON_SECRET_FUSES partition. + /// + /// Read value: [`caliptra_otp_ctrl::regs::NonSecretFusesReadLockReadVal`]; Write value: [`caliptra_otp_ctrl::regs::NonSecretFusesReadLockWriteVal`] + #[inline(always)] + pub fn non_secret_fuses_read_lock( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x70 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::Csr0ReadVal`]; Write value: [`caliptra_otp_ctrl::regs::Csr0WriteVal`] + #[inline(always)] + pub fn csr0(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0xa4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::Csr1ReadVal`]; Write value: [`caliptra_otp_ctrl::regs::Csr1WriteVal`] + #[inline(always)] + pub fn csr1(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0xa8 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::Csr2ReadVal`]; Write value: [`caliptra_otp_ctrl::regs::Csr2WriteVal`] + #[inline(always)] + pub fn csr2(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0xac / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::Csr3ReadVal`]; Write value: [`caliptra_otp_ctrl::regs::Csr3WriteVal`] + #[inline(always)] + pub fn csr3(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0xb0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::Csr4ReadVal`]; Write value: [`caliptra_otp_ctrl::regs::Csr4WriteVal`] + #[inline(always)] + pub fn csr4(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0xb4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::Csr5ReadVal`]; Write value: [`caliptra_otp_ctrl::regs::Csr5WriteVal`] + #[inline(always)] + pub fn csr5(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0xb8 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::Csr6ReadVal`]; Write value: [`caliptra_otp_ctrl::regs::Csr6WriteVal`] + #[inline(always)] + pub fn csr6(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0xbc / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read value: [`caliptra_otp_ctrl::regs::Csr7ReadVal`]; Write value: [`caliptra_otp_ctrl::regs::Csr7WriteVal`] + #[inline(always)] + pub fn csr7(&self) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0xc0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + #[inline(always)] + pub fn err_code_rf(&self) -> ErrCodeRfBlock<&TMmio> { + ErrCodeRfBlock { + ptr: unsafe { self.ptr.add(0x14 / core::mem::size_of::()) }, + mmio: core::borrow::Borrow::borrow(&self.mmio), + } + } + #[inline(always)] + pub fn dai_wdata_rf(&self) -> DaiWdataRfBlock<&TMmio> { + DaiWdataRfBlock { + ptr: unsafe { self.ptr.add(0x44 / core::mem::size_of::()) }, + mmio: core::borrow::Borrow::borrow(&self.mmio), + } + } + #[inline(always)] + pub fn dai_rdata_rf(&self) -> DaiRdataRfBlock<&TMmio> { + DaiRdataRfBlock { + ptr: unsafe { self.ptr.add(0x4c / core::mem::size_of::()) }, + mmio: core::borrow::Borrow::borrow(&self.mmio), + } + } + #[inline(always)] + pub fn vendor_test_digest(&self) -> VendorTestDigestBlock<&TMmio> { + VendorTestDigestBlock { + ptr: unsafe { self.ptr.add(0x74 / core::mem::size_of::()) }, + mmio: core::borrow::Borrow::borrow(&self.mmio), + } + } + #[inline(always)] + pub fn non_secret_fuses_digest(&self) -> NonSecretFusesDigestBlock<&TMmio> { + NonSecretFusesDigestBlock { + ptr: unsafe { self.ptr.add(0x7c / core::mem::size_of::()) }, + mmio: core::borrow::Borrow::borrow(&self.mmio), + } + } + #[inline(always)] + pub fn secret0_digest(&self) -> Secret0DigestBlock<&TMmio> { + Secret0DigestBlock { + ptr: unsafe { self.ptr.add(0x84 / core::mem::size_of::()) }, + mmio: core::borrow::Borrow::borrow(&self.mmio), + } + } + #[inline(always)] + pub fn secret1_digest(&self) -> Secret1DigestBlock<&TMmio> { + Secret1DigestBlock { + ptr: unsafe { self.ptr.add(0x8c / core::mem::size_of::()) }, + mmio: core::borrow::Borrow::borrow(&self.mmio), + } + } + #[inline(always)] + pub fn secret2_digest(&self) -> Secret2DigestBlock<&TMmio> { + Secret2DigestBlock { + ptr: unsafe { self.ptr.add(0x94 / core::mem::size_of::()) }, + mmio: core::borrow::Borrow::borrow(&self.mmio), + } + } + #[inline(always)] + pub fn secret3_digest(&self) -> Secret3DigestBlock<&TMmio> { + Secret3DigestBlock { + ptr: unsafe { self.ptr.add(0x9c / core::mem::size_of::()) }, + mmio: core::borrow::Borrow::borrow(&self.mmio), + } + } +} +#[derive(Clone, Copy)] +pub struct ErrCodeRfBlock> { + ptr: *mut u32, + mmio: TMmio, +} +impl ErrCodeRfBlock { + /// This register holds information about error conditions that occurred in the agents + /// interacting with the OTP macr via the internal bus. The error codes should be checked + /// if the partitions, DAI or LCI flag an error in the !!STATUS register, or when an + /// !!INTR_STATE.otp_error has been triggered. Note that all errors trigger an otp_error + /// interrupt, and in addition some errors may trigger either an fatal_macr_error or an + /// fatal_check_error alert. + /// + /// Read value: [`caliptra_otp_ctrl::regs::ErrCodeRegTReadVal`]; Write value: [`caliptra_otp_ctrl::regs::ErrCodeRegTWriteVal`] + #[inline(always)] + pub fn err_code_0( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// This register holds information about error conditions that occurred in the agents + /// interacting with the OTP macr via the internal bus. The error codes should be checked + /// if the partitions, DAI or LCI flag an error in the !!STATUS register, or when an + /// !!INTR_STATE.otp_error has been triggered. Note that all errors trigger an otp_error + /// interrupt, and in addition some errors may trigger either an fatal_macr_error or an + /// fatal_check_error alert. + /// + /// Read value: [`caliptra_otp_ctrl::regs::ErrCodeRegTReadVal`]; Write value: [`caliptra_otp_ctrl::regs::ErrCodeRegTWriteVal`] + #[inline(always)] + pub fn err_code_1( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// This register holds information about error conditions that occurred in the agents + /// interacting with the OTP macr via the internal bus. The error codes should be checked + /// if the partitions, DAI or LCI flag an error in the !!STATUS register, or when an + /// !!INTR_STATE.otp_error has been triggered. Note that all errors trigger an otp_error + /// interrupt, and in addition some errors may trigger either an fatal_macr_error or an + /// fatal_check_error alert. + /// + /// Read value: [`caliptra_otp_ctrl::regs::ErrCodeRegTReadVal`]; Write value: [`caliptra_otp_ctrl::regs::ErrCodeRegTWriteVal`] + #[inline(always)] + pub fn err_code_2( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(8 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// This register holds information about error conditions that occurred in the agents + /// interacting with the OTP macr via the internal bus. The error codes should be checked + /// if the partitions, DAI or LCI flag an error in the !!STATUS register, or when an + /// !!INTR_STATE.otp_error has been triggered. Note that all errors trigger an otp_error + /// interrupt, and in addition some errors may trigger either an fatal_macr_error or an + /// fatal_check_error alert. + /// + /// Read value: [`caliptra_otp_ctrl::regs::ErrCodeRegTReadVal`]; Write value: [`caliptra_otp_ctrl::regs::ErrCodeRegTWriteVal`] + #[inline(always)] + pub fn err_code_3( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0xc / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// This register holds information about error conditions that occurred in the agents + /// interacting with the OTP macr via the internal bus. The error codes should be checked + /// if the partitions, DAI or LCI flag an error in the !!STATUS register, or when an + /// !!INTR_STATE.otp_error has been triggered. Note that all errors trigger an otp_error + /// interrupt, and in addition some errors may trigger either an fatal_macr_error or an + /// fatal_check_error alert. + /// + /// Read value: [`caliptra_otp_ctrl::regs::ErrCodeRegTReadVal`]; Write value: [`caliptra_otp_ctrl::regs::ErrCodeRegTWriteVal`] + #[inline(always)] + pub fn err_code_4( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x10 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// This register holds information about error conditions that occurred in the agents + /// interacting with the OTP macr via the internal bus. The error codes should be checked + /// if the partitions, DAI or LCI flag an error in the !!STATUS register, or when an + /// !!INTR_STATE.otp_error has been triggered. Note that all errors trigger an otp_error + /// interrupt, and in addition some errors may trigger either an fatal_macr_error or an + /// fatal_check_error alert. + /// + /// Read value: [`caliptra_otp_ctrl::regs::ErrCodeRegTReadVal`]; Write value: [`caliptra_otp_ctrl::regs::ErrCodeRegTWriteVal`] + #[inline(always)] + pub fn err_code_5( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x14 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// This register holds information about error conditions that occurred in the agents + /// interacting with the OTP macr via the internal bus. The error codes should be checked + /// if the partitions, DAI or LCI flag an error in the !!STATUS register, or when an + /// !!INTR_STATE.otp_error has been triggered. Note that all errors trigger an otp_error + /// interrupt, and in addition some errors may trigger either an fatal_macr_error or an + /// fatal_check_error alert. + /// + /// Read value: [`caliptra_otp_ctrl::regs::ErrCodeRegTReadVal`]; Write value: [`caliptra_otp_ctrl::regs::ErrCodeRegTWriteVal`] + #[inline(always)] + pub fn err_code_6( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x18 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// This register holds information about error conditions that occurred in the agents + /// interacting with the OTP macr via the internal bus. The error codes should be checked + /// if the partitions, DAI or LCI flag an error in the !!STATUS register, or when an + /// !!INTR_STATE.otp_error has been triggered. Note that all errors trigger an otp_error + /// interrupt, and in addition some errors may trigger either an fatal_macr_error or an + /// fatal_check_error alert. + /// + /// Read value: [`caliptra_otp_ctrl::regs::ErrCodeRegTReadVal`]; Write value: [`caliptra_otp_ctrl::regs::ErrCodeRegTWriteVal`] + #[inline(always)] + pub fn err_code_7( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x1c / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// This register holds information about error conditions that occurred in the agents + /// interacting with the OTP macr via the internal bus. The error codes should be checked + /// if the partitions, DAI or LCI flag an error in the !!STATUS register, or when an + /// !!INTR_STATE.otp_error has been triggered. Note that all errors trigger an otp_error + /// interrupt, and in addition some errors may trigger either an fatal_macr_error or an + /// fatal_check_error alert. + /// + /// Read value: [`caliptra_otp_ctrl::regs::ErrCodeRegTReadVal`]; Write value: [`caliptra_otp_ctrl::regs::ErrCodeRegTWriteVal`] + #[inline(always)] + pub fn err_code_8( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0x20 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } +} +#[derive(Clone, Copy)] +pub struct DaiWdataRfBlock> { + ptr: *mut u32, + mmio: TMmio, +} +impl DaiWdataRfBlock { + /// Write data for direct accesses. + /// Hardware automatically determines the access granule (32bit or 64bit) based on which + /// partition is being written to. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn direct_access_wdata_0( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Write data for direct accesses. + /// Hardware automatically determines the access granule (32bit or 64bit) based on which + /// partition is being written to. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn direct_access_wdata_1( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } +} +#[derive(Clone, Copy)] +pub struct DaiRdataRfBlock> { + ptr: *mut u32, + mmio: TMmio, +} +impl DaiRdataRfBlock { + /// Read data for direct accesses. + /// Hardware automatically determines the access granule (32bit or 64bit) based on which + /// partition is read from. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn direct_access_rdata_0( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Read data for direct accesses. + /// Hardware automatically determines the access granule (32bit or 64bit) based on which + /// partition is read from. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn direct_access_rdata_1( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } +} +#[derive(Clone, Copy)] +pub struct VendorTestDigestBlock> { + ptr: *mut u32, + mmio: TMmio, +} +impl VendorTestDigestBlock { + /// Integrity digest for partition. + /// The integrity digest is 0 by default. Software must write this + /// digest value via the direct access interface in order to lock the partition. + /// After a reset, write access to the VENDOR_TEST partition is locked and\n the digest becomes visible in this CSR. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_0( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Integrity digest for partition. + /// The integrity digest is 0 by default. Software must write this + /// digest value via the direct access interface in order to lock the partition. + /// After a reset, write access to the VENDOR_TEST partition is locked and\n the digest becomes visible in this CSR. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_1( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } +} +#[derive(Clone, Copy)] +pub struct NonSecretFusesDigestBlock> { + ptr: *mut u32, + mmio: TMmio, +} +impl NonSecretFusesDigestBlock { + /// Integrity digest for partition. + /// The integrity digest is 0 by default. Software must write this + /// digest value via the direct access interface in order to lock the partition. + /// After a reset, write access to the VENDOR_TEST partition is locked and\n the digest becomes visible in this CSR. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_0( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Integrity digest for partition. + /// The integrity digest is 0 by default. Software must write this + /// digest value via the direct access interface in order to lock the partition. + /// After a reset, write access to the VENDOR_TEST partition is locked and\n the digest becomes visible in this CSR. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_1( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } +} +#[derive(Clone, Copy)] +pub struct Secret0DigestBlock> { + ptr: *mut u32, + mmio: TMmio, +} +impl Secret0DigestBlock { + /// Integrity digest for secret partition. + /// The integrity digest is 0 by default. The digest calculation can be triggered via the !!DIRECT_ACCESS_CMD. + /// After a reset, the digest then becomes visible in this CSR, and the corresponding partition becomes write-locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_0( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Integrity digest for secret partition. + /// The integrity digest is 0 by default. The digest calculation can be triggered via the !!DIRECT_ACCESS_CMD. + /// After a reset, the digest then becomes visible in this CSR, and the corresponding partition becomes write-locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_1( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } +} +#[derive(Clone, Copy)] +pub struct Secret1DigestBlock> { + ptr: *mut u32, + mmio: TMmio, +} +impl Secret1DigestBlock { + /// Integrity digest for secret partition. + /// The integrity digest is 0 by default. The digest calculation can be triggered via the !!DIRECT_ACCESS_CMD. + /// After a reset, the digest then becomes visible in this CSR, and the corresponding partition becomes write-locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_0( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Integrity digest for secret partition. + /// The integrity digest is 0 by default. The digest calculation can be triggered via the !!DIRECT_ACCESS_CMD. + /// After a reset, the digest then becomes visible in this CSR, and the corresponding partition becomes write-locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_1( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } +} +#[derive(Clone, Copy)] +pub struct Secret2DigestBlock> { + ptr: *mut u32, + mmio: TMmio, +} +impl Secret2DigestBlock { + /// Integrity digest for secret partition. + /// The integrity digest is 0 by default. The digest calculation can be triggered via the !!DIRECT_ACCESS_CMD. + /// After a reset, the digest then becomes visible in this CSR, and the corresponding partition becomes write-locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_0( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Integrity digest for secret partition. + /// The integrity digest is 0 by default. The digest calculation can be triggered via the !!DIRECT_ACCESS_CMD. + /// After a reset, the digest then becomes visible in this CSR, and the corresponding partition becomes write-locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_1( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } +} +#[derive(Clone, Copy)] +pub struct Secret3DigestBlock> { + ptr: *mut u32, + mmio: TMmio, +} +impl Secret3DigestBlock { + /// Integrity digest for secret partition. + /// The integrity digest is 0 by default. The digest calculation can be triggered via the !!DIRECT_ACCESS_CMD. + /// After a reset, the digest then becomes visible in this CSR, and the corresponding partition becomes write-locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_0( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(0 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } + /// Integrity digest for secret partition. + /// The integrity digest is 0 by default. The digest calculation can be triggered via the !!DIRECT_ACCESS_CMD. + /// After a reset, the digest then becomes visible in this CSR, and the corresponding partition becomes write-locked. + /// + /// Read value: [`u32`]; Write value: [`u32`] + #[inline(always)] + pub fn digest_1( + &self, + ) -> ureg::RegRef { + unsafe { + ureg::RegRef::new_with_mmio( + self.ptr.wrapping_add(4 / core::mem::size_of::()), + core::borrow::Borrow::borrow(&self.mmio), + ) + } + } +} +/// A zero-sized type that represents ownership of this +/// peripheral, used to get access to a Register lock. Most +/// programs create one of these in unsafe code near the top of +/// main(), and pass it to the driver responsible for managing +/// all access to the hardware. +pub struct ErrCodeRf { + _priv: (), +} +impl ErrCodeRf { + pub const PTR: *mut u32 = 0x14 as *mut u32; + /// # Safety + /// + /// Caller must ensure that all concurrent use of this + /// peripheral in the firmware is done so in a compatible + /// way. The simplest way to enforce this is to only call + /// this function once. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _priv: () } + } + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn regs(&self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn regs_mut(&mut self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } +} +/// A zero-sized type that represents ownership of this +/// peripheral, used to get access to a Register lock. Most +/// programs create one of these in unsafe code near the top of +/// main(), and pass it to the driver responsible for managing +/// all access to the hardware. +pub struct DaiWdataRf { + _priv: (), +} +impl DaiWdataRf { + pub const PTR: *mut u32 = 0x44 as *mut u32; + /// # Safety + /// + /// Caller must ensure that all concurrent use of this + /// peripheral in the firmware is done so in a compatible + /// way. The simplest way to enforce this is to only call + /// this function once. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _priv: () } + } + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn regs(&self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn regs_mut(&mut self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } +} +/// A zero-sized type that represents ownership of this +/// peripheral, used to get access to a Register lock. Most +/// programs create one of these in unsafe code near the top of +/// main(), and pass it to the driver responsible for managing +/// all access to the hardware. +pub struct DaiRdataRf { + _priv: (), +} +impl DaiRdataRf { + pub const PTR: *mut u32 = 0x4c as *mut u32; + /// # Safety + /// + /// Caller must ensure that all concurrent use of this + /// peripheral in the firmware is done so in a compatible + /// way. The simplest way to enforce this is to only call + /// this function once. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _priv: () } + } + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn regs(&self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn regs_mut(&mut self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } +} +/// A zero-sized type that represents ownership of this +/// peripheral, used to get access to a Register lock. Most +/// programs create one of these in unsafe code near the top of +/// main(), and pass it to the driver responsible for managing +/// all access to the hardware. +pub struct VendorTestDigest { + _priv: (), +} +impl VendorTestDigest { + pub const PTR: *mut u32 = 0x74 as *mut u32; + /// # Safety + /// + /// Caller must ensure that all concurrent use of this + /// peripheral in the firmware is done so in a compatible + /// way. The simplest way to enforce this is to only call + /// this function once. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _priv: () } + } + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn regs(&self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn regs_mut(&mut self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } +} +/// A zero-sized type that represents ownership of this +/// peripheral, used to get access to a Register lock. Most +/// programs create one of these in unsafe code near the top of +/// main(), and pass it to the driver responsible for managing +/// all access to the hardware. +pub struct NonSecretFusesDigest { + _priv: (), +} +impl NonSecretFusesDigest { + pub const PTR: *mut u32 = 0x7c as *mut u32; + /// # Safety + /// + /// Caller must ensure that all concurrent use of this + /// peripheral in the firmware is done so in a compatible + /// way. The simplest way to enforce this is to only call + /// this function once. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _priv: () } + } + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn regs(&self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn regs_mut(&mut self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } +} +/// A zero-sized type that represents ownership of this +/// peripheral, used to get access to a Register lock. Most +/// programs create one of these in unsafe code near the top of +/// main(), and pass it to the driver responsible for managing +/// all access to the hardware. +pub struct Secret0Digest { + _priv: (), +} +impl Secret0Digest { + pub const PTR: *mut u32 = 0x84 as *mut u32; + /// # Safety + /// + /// Caller must ensure that all concurrent use of this + /// peripheral in the firmware is done so in a compatible + /// way. The simplest way to enforce this is to only call + /// this function once. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _priv: () } + } + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn regs(&self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn regs_mut(&mut self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } +} +/// A zero-sized type that represents ownership of this +/// peripheral, used to get access to a Register lock. Most +/// programs create one of these in unsafe code near the top of +/// main(), and pass it to the driver responsible for managing +/// all access to the hardware. +pub struct Secret1Digest { + _priv: (), +} +impl Secret1Digest { + pub const PTR: *mut u32 = 0x8c as *mut u32; + /// # Safety + /// + /// Caller must ensure that all concurrent use of this + /// peripheral in the firmware is done so in a compatible + /// way. The simplest way to enforce this is to only call + /// this function once. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _priv: () } + } + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn regs(&self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn regs_mut(&mut self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } +} +/// A zero-sized type that represents ownership of this +/// peripheral, used to get access to a Register lock. Most +/// programs create one of these in unsafe code near the top of +/// main(), and pass it to the driver responsible for managing +/// all access to the hardware. +pub struct Secret2Digest { + _priv: (), +} +impl Secret2Digest { + pub const PTR: *mut u32 = 0x94 as *mut u32; + /// # Safety + /// + /// Caller must ensure that all concurrent use of this + /// peripheral in the firmware is done so in a compatible + /// way. The simplest way to enforce this is to only call + /// this function once. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _priv: () } + } + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn regs(&self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn regs_mut(&mut self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } +} +/// A zero-sized type that represents ownership of this +/// peripheral, used to get access to a Register lock. Most +/// programs create one of these in unsafe code near the top of +/// main(), and pass it to the driver responsible for managing +/// all access to the hardware. +pub struct Secret3Digest { + _priv: (), +} +impl Secret3Digest { + pub const PTR: *mut u32 = 0x9c as *mut u32; + /// # Safety + /// + /// Caller must ensure that all concurrent use of this + /// peripheral in the firmware is done so in a compatible + /// way. The simplest way to enforce this is to only call + /// this function once. + #[inline(always)] + pub unsafe fn new() -> Self { + Self { _priv: () } + } + /// Returns a register block that can be used to read + /// registers from this peripheral, but cannot write. + #[inline(always)] + pub fn regs(&self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } + /// Return a register block that can be used to read and + /// write this peripheral's registers. + #[inline(always)] + pub fn regs_mut(&mut self) -> RegisterBlock { + RegisterBlock { + ptr: Self::PTR, + mmio: core::default::Default::default(), + } + } +} +pub mod regs { + //! Types that represent the values held by registers. + #[derive(Clone, Copy)] + pub struct AlertTestWriteVal(u32); + impl AlertTestWriteVal { + /// Write 1 to trigger one alert event of this kind. + #[inline(always)] + pub fn fatal_macr_error(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + /// Write 1 to trigger one alert event of this kind. + #[inline(always)] + pub fn fatal_check_error(self, val: bool) -> Self { + Self((self.0 & !(1 << 1)) | (u32::from(val) << 1)) + } + /// Write 1 to trigger one alert event of this kind. + #[inline(always)] + pub fn fatal_bus_integ_error(self, val: bool) -> Self { + Self((self.0 & !(1 << 2)) | (u32::from(val) << 2)) + } + /// Write 1 to trigger one alert event of this kind. + #[inline(always)] + pub fn fatal_prim_otp_alert(self, val: bool) -> Self { + Self((self.0 & !(1 << 3)) | (u32::from(val) << 3)) + } + /// Write 1 to trigger one alert event of this kind. + #[inline(always)] + pub fn recov_prim_otp_alert(self, val: bool) -> Self { + Self((self.0 & !(1 << 4)) | (u32::from(val) << 4)) + } + } + impl From for AlertTestWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: AlertTestWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct CheckRegwenWriteVal(u32); + impl CheckRegwenWriteVal { + /// When cleared to 0, !!INTEGRITY_CHECK_PERIOD and !!CONSISTENCY_CHECK_PERIOD registers cannot be written anymore.\nWrite 0 to clear this bit. + #[inline(always)] + pub fn regwen(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + } + impl From for CheckRegwenWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: CheckRegwenWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct CheckTriggerWriteVal(u32); + impl CheckTriggerWriteVal { + /// Writing 1 to this bit triggers an integrity check. SW should monitor !!STATUS.CHECK_PENDING + /// and wait until the check has been completed. If there are any errors, those will be flagged + /// in the !!STATUS and !!ERR_CODE registers, and via the interrupts and alerts. + #[inline(always)] + pub fn integrity(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + /// Writing 1 to this bit triggers a consistency check. SW should monitor !!STATUS.CHECK_PENDING\nand wait until the check has been completed. If there are any errors, those will be flagged\nin the !!STATUS and !!ERR_CODE registers, and via interrupts and alerts. + #[inline(always)] + pub fn consistency(self, val: bool) -> Self { + Self((self.0 & !(1 << 1)) | (u32::from(val) << 1)) + } + } + impl From for CheckTriggerWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: CheckTriggerWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct CheckTriggerRegwenReadVal(u32); + impl CheckTriggerRegwenReadVal { + /// When cleared to 0, the !!CHECK_TRIGGER register cannot be written anymore. + /// Write 0 to clear this bit. + #[inline(always)] + pub fn regwen(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> CheckTriggerRegwenWriteVal { + CheckTriggerRegwenWriteVal(self.0) + } + } + impl From for CheckTriggerRegwenReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: CheckTriggerRegwenReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct CheckTriggerRegwenWriteVal(u32); + impl CheckTriggerRegwenWriteVal { + /// When cleared to 0, the !!CHECK_TRIGGER register cannot be written anymore. + /// Write 0 to clear this bit. + #[inline(always)] + pub fn regwen(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + } + impl From for CheckTriggerRegwenWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: CheckTriggerRegwenWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr0ReadVal(u32); + impl Csr0ReadVal { + #[inline(always)] + pub fn field0(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + #[inline(always)] + pub fn field1(&self) -> bool { + ((self.0 >> 1) & 1) != 0 + } + #[inline(always)] + pub fn field2(&self) -> bool { + ((self.0 >> 2) & 1) != 0 + } + #[inline(always)] + pub fn field3(&self) -> u32 { + (self.0 >> 4) & 0x3ff + } + #[inline(always)] + pub fn field4(&self) -> u32 { + (self.0 >> 16) & 0x7ff + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> Csr0WriteVal { + Csr0WriteVal(self.0) + } + } + impl From for Csr0ReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr0ReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr0WriteVal(u32); + impl Csr0WriteVal { + #[inline(always)] + pub fn field0(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + #[inline(always)] + pub fn field1(self, val: bool) -> Self { + Self((self.0 & !(1 << 1)) | (u32::from(val) << 1)) + } + #[inline(always)] + pub fn field2(self, val: bool) -> Self { + Self((self.0 & !(1 << 2)) | (u32::from(val) << 2)) + } + #[inline(always)] + pub fn field3(self, val: u32) -> Self { + Self((self.0 & !(0x3ff << 4)) | ((val & 0x3ff) << 4)) + } + #[inline(always)] + pub fn field4(self, val: u32) -> Self { + Self((self.0 & !(0x7ff << 16)) | ((val & 0x7ff) << 16)) + } + } + impl From for Csr0WriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr0WriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr1ReadVal(u32); + impl Csr1ReadVal { + #[inline(always)] + pub fn field0(&self) -> u32 { + (self.0 >> 0) & 0x7f + } + #[inline(always)] + pub fn field1(&self) -> bool { + ((self.0 >> 7) & 1) != 0 + } + #[inline(always)] + pub fn field2(&self) -> u32 { + (self.0 >> 8) & 0x7f + } + #[inline(always)] + pub fn field3(&self) -> bool { + ((self.0 >> 15) & 1) != 0 + } + #[inline(always)] + pub fn field4(&self) -> u32 { + (self.0 >> 16) & 0xffff + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> Csr1WriteVal { + Csr1WriteVal(self.0) + } + } + impl From for Csr1ReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr1ReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr1WriteVal(u32); + impl Csr1WriteVal { + #[inline(always)] + pub fn field0(self, val: u32) -> Self { + Self((self.0 & !(0x7f << 0)) | ((val & 0x7f) << 0)) + } + #[inline(always)] + pub fn field1(self, val: bool) -> Self { + Self((self.0 & !(1 << 7)) | (u32::from(val) << 7)) + } + #[inline(always)] + pub fn field2(self, val: u32) -> Self { + Self((self.0 & !(0x7f << 8)) | ((val & 0x7f) << 8)) + } + #[inline(always)] + pub fn field3(self, val: bool) -> Self { + Self((self.0 & !(1 << 15)) | (u32::from(val) << 15)) + } + #[inline(always)] + pub fn field4(self, val: u32) -> Self { + Self((self.0 & !(0xffff << 16)) | ((val & 0xffff) << 16)) + } + } + impl From for Csr1WriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr1WriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr2ReadVal(u32); + impl Csr2ReadVal { + #[inline(always)] + pub fn field0(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> Csr2WriteVal { + Csr2WriteVal(self.0) + } + } + impl From for Csr2ReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr2ReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr2WriteVal(u32); + impl Csr2WriteVal { + #[inline(always)] + pub fn field0(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + } + impl From for Csr2WriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr2WriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr3ReadVal(u32); + impl Csr3ReadVal { + #[inline(always)] + pub fn field0(&self) -> u32 { + (self.0 >> 0) & 7 + } + #[inline(always)] + pub fn field1(&self) -> u32 { + (self.0 >> 4) & 0x3ff + } + #[inline(always)] + pub fn field2(&self) -> bool { + ((self.0 >> 16) & 1) != 0 + } + #[inline(always)] + pub fn field3(&self) -> bool { + ((self.0 >> 17) & 1) != 0 + } + #[inline(always)] + pub fn field4(&self) -> bool { + ((self.0 >> 18) & 1) != 0 + } + #[inline(always)] + pub fn field5(&self) -> bool { + ((self.0 >> 19) & 1) != 0 + } + #[inline(always)] + pub fn field6(&self) -> bool { + ((self.0 >> 20) & 1) != 0 + } + #[inline(always)] + pub fn field7(&self) -> bool { + ((self.0 >> 21) & 1) != 0 + } + #[inline(always)] + pub fn field8(&self) -> bool { + ((self.0 >> 22) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> Csr3WriteVal { + Csr3WriteVal(self.0) + } + } + impl From for Csr3ReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr3ReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr3WriteVal(u32); + impl Csr3WriteVal { + #[inline(always)] + pub fn field0(self, val: u32) -> Self { + Self((self.0 & !(7 << 0)) | ((val & 7) << 0)) + } + #[inline(always)] + pub fn field1(self, val: u32) -> Self { + Self((self.0 & !(0x3ff << 4)) | ((val & 0x3ff) << 4)) + } + #[inline(always)] + pub fn field2(self, val: bool) -> Self { + Self((self.0 & !(1 << 16)) | (u32::from(val) << 16)) + } + } + impl From for Csr3WriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr3WriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr4ReadVal(u32); + impl Csr4ReadVal { + #[inline(always)] + pub fn field0(&self) -> u32 { + (self.0 >> 0) & 0x3ff + } + #[inline(always)] + pub fn field1(&self) -> bool { + ((self.0 >> 12) & 1) != 0 + } + #[inline(always)] + pub fn field2(&self) -> bool { + ((self.0 >> 13) & 1) != 0 + } + #[inline(always)] + pub fn field3(&self) -> bool { + ((self.0 >> 14) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> Csr4WriteVal { + Csr4WriteVal(self.0) + } + } + impl From for Csr4ReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr4ReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr4WriteVal(u32); + impl Csr4WriteVal { + #[inline(always)] + pub fn field0(self, val: u32) -> Self { + Self((self.0 & !(0x3ff << 0)) | ((val & 0x3ff) << 0)) + } + #[inline(always)] + pub fn field1(self, val: bool) -> Self { + Self((self.0 & !(1 << 12)) | (u32::from(val) << 12)) + } + #[inline(always)] + pub fn field2(self, val: bool) -> Self { + Self((self.0 & !(1 << 13)) | (u32::from(val) << 13)) + } + #[inline(always)] + pub fn field3(self, val: bool) -> Self { + Self((self.0 & !(1 << 14)) | (u32::from(val) << 14)) + } + } + impl From for Csr4WriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr4WriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr5ReadVal(u32); + impl Csr5ReadVal { + #[inline(always)] + pub fn field0(&self) -> u32 { + (self.0 >> 0) & 0x3f + } + #[inline(always)] + pub fn field1(&self) -> u32 { + (self.0 >> 6) & 3 + } + #[inline(always)] + pub fn field2(&self) -> u32 { + (self.0 >> 8) & 0xff + } + #[inline(always)] + pub fn field3(&self) -> u32 { + (self.0 >> 9) & 7 + } + #[inline(always)] + pub fn field4(&self) -> u32 { + (self.0 >> 12) & 0xfff + } + #[inline(always)] + pub fn field5(&self) -> u32 { + (self.0 >> 24) & 0x1fff + } + #[inline(always)] + pub fn field6(&self) -> u32 { + (self.0 >> 16) & 0xffff + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> Csr5WriteVal { + Csr5WriteVal(self.0) + } + } + impl From for Csr5ReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr5ReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr5WriteVal(u32); + impl Csr5WriteVal { + #[inline(always)] + pub fn field0(self, val: u32) -> Self { + Self((self.0 & !(0x3f << 0)) | ((val & 0x3f) << 0)) + } + #[inline(always)] + pub fn field1(self, val: u32) -> Self { + Self((self.0 & !(3 << 6)) | ((val & 3) << 6)) + } + #[inline(always)] + pub fn field6(self, val: u32) -> Self { + Self((self.0 & !(0xffff << 16)) | ((val & 0xffff) << 16)) + } + } + impl From for Csr5WriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr5WriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr6ReadVal(u32); + impl Csr6ReadVal { + #[inline(always)] + pub fn field0(&self) -> u32 { + (self.0 >> 0) & 0x3ff + } + #[inline(always)] + pub fn field1(&self) -> bool { + ((self.0 >> 11) & 1) != 0 + } + #[inline(always)] + pub fn field2(&self) -> bool { + ((self.0 >> 12) & 1) != 0 + } + #[inline(always)] + pub fn field3(&self) -> u32 { + (self.0 >> 16) & 0xffff + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> Csr6WriteVal { + Csr6WriteVal(self.0) + } + } + impl From for Csr6ReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr6ReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr6WriteVal(u32); + impl Csr6WriteVal { + #[inline(always)] + pub fn field0(self, val: u32) -> Self { + Self((self.0 & !(0x3ff << 0)) | ((val & 0x3ff) << 0)) + } + #[inline(always)] + pub fn field1(self, val: bool) -> Self { + Self((self.0 & !(1 << 11)) | (u32::from(val) << 11)) + } + #[inline(always)] + pub fn field2(self, val: bool) -> Self { + Self((self.0 & !(1 << 12)) | (u32::from(val) << 12)) + } + #[inline(always)] + pub fn field3(self, val: u32) -> Self { + Self((self.0 & !(0xffff << 16)) | ((val & 0xffff) << 16)) + } + } + impl From for Csr6WriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr6WriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct Csr7ReadVal(u32); + impl Csr7ReadVal { + #[inline(always)] + pub fn field0(&self) -> u32 { + (self.0 >> 0) & 0x3f + } + #[inline(always)] + pub fn field1(&self) -> u32 { + (self.0 >> 8) & 7 + } + #[inline(always)] + pub fn field2(&self) -> bool { + ((self.0 >> 14) & 1) != 0 + } + #[inline(always)] + pub fn field3(&self) -> bool { + ((self.0 >> 15) & 1) != 0 + } + } + impl From for Csr7ReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: Csr7ReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct DirectAccessAddressReadVal(u32); + impl DirectAccessAddressReadVal { + /// This is the address for the OTP word to be read or written thrugh\nthe direct access interface. Note that the address is aligned to the access size\ninternally, hence bits 1:0 are ignored for 32bit accesses, and bits 2:0 are ignored\nfor 64bit accesses.\n\nFor the digest calculation command, set this register to the partition base offset. + #[inline(always)] + pub fn address(&self) -> u32 { + (self.0 >> 0) & 0xfff + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> DirectAccessAddressWriteVal { + DirectAccessAddressWriteVal(self.0) + } + } + impl From for DirectAccessAddressReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: DirectAccessAddressReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct DirectAccessAddressWriteVal(u32); + impl DirectAccessAddressWriteVal { + /// This is the address for the OTP word to be read or written thrugh\nthe direct access interface. Note that the address is aligned to the access size\ninternally, hence bits 1:0 are ignored for 32bit accesses, and bits 2:0 are ignored\nfor 64bit accesses.\n\nFor the digest calculation command, set this register to the partition base offset. + #[inline(always)] + pub fn address(self, val: u32) -> Self { + Self((self.0 & !(0xfff << 0)) | ((val & 0xfff) << 0)) + } + } + impl From for DirectAccessAddressWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: DirectAccessAddressWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct DirectAccessCmdWriteVal(u32); + impl DirectAccessCmdWriteVal { + /// Initiates a readout sequence that reads the location specified\nby !!DIRECT_ACCESS_ADDRESS. The command places the data read into\n!!DIRECT_ACCESS_RDATA_0 and !!DIRECT_ACCESS_RDATA_1 (for 64bit partitions). + #[inline(always)] + pub fn rd(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + /// Initiates a prgramming sequence that writes the data in !!DIRECT_ACCESS_WDATA_0\nand !!DIRECT_ACCESS_WDATA_1 (for 64bit partitions) to the location specified by\n!!DIRECT_ACCESS_ADDRESS. + #[inline(always)] + pub fn wr(self, val: bool) -> Self { + Self((self.0 & !(1 << 1)) | (u32::from(val) << 1)) + } + /// Initiates the digest calculation and locking sequence for the partition specified by\n!!DIRECT_ACCESS_ADDRESS. + #[inline(always)] + pub fn digest(self, val: bool) -> Self { + Self((self.0 & !(1 << 2)) | (u32::from(val) << 2)) + } + } + impl From for DirectAccessCmdWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: DirectAccessCmdWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct DirectAccessRegwenReadVal(u32); + impl DirectAccessRegwenReadVal { + /// This bit contrls whether the DAI registers can be written.\nWrite 0 to it in order to clear the bit.\n\nNote that the hardware also modulates this bit and sets it to 0 temporarily\nduring an OTP operation such that the corresponding address and data registers\ncannot be modified while an operation is pending. The !!DAI_IDLE status bit\nwill also be set to 0 in such a case. + #[inline(always)] + pub fn regwen(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> DirectAccessRegwenWriteVal { + DirectAccessRegwenWriteVal(self.0) + } + } + impl From for DirectAccessRegwenReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: DirectAccessRegwenReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct DirectAccessRegwenWriteVal(u32); + impl DirectAccessRegwenWriteVal { + /// This bit contrls whether the DAI registers can be written.\nWrite 0 to it in order to clear the bit.\n\nNote that the hardware also modulates this bit and sets it to 0 temporarily\nduring an OTP operation such that the corresponding address and data registers\ncannot be modified while an operation is pending. The !!DAI_IDLE status bit\nwill also be set to 0 in such a case. + #[inline(always)] + pub fn regwen(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + } + impl From for DirectAccessRegwenWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: DirectAccessRegwenWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct InterruptEnableReadVal(u32); + impl InterruptEnableReadVal { + /// Enable interrupt when otp_operation_done is set. + #[inline(always)] + pub fn otp_operation_done(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Enable interrupt when otp_error is set. + #[inline(always)] + pub fn otp_error(&self) -> bool { + ((self.0 >> 1) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> InterruptEnableWriteVal { + InterruptEnableWriteVal(self.0) + } + } + impl From for InterruptEnableReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: InterruptEnableReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct InterruptEnableWriteVal(u32); + impl InterruptEnableWriteVal { + /// Enable interrupt when otp_operation_done is set. + #[inline(always)] + pub fn otp_operation_done(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + /// Enable interrupt when otp_error is set. + #[inline(always)] + pub fn otp_error(self, val: bool) -> Self { + Self((self.0 & !(1 << 1)) | (u32::from(val) << 1)) + } + } + impl From for InterruptEnableWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: InterruptEnableWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct InterruptStateReadVal(u32); + impl InterruptStateReadVal { + /// A direct access command or digest calculation operation has completed. + #[inline(always)] + pub fn otp_operation_done(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// An error has occurred in the OTP contrller. Check the !!ERR_CODE register to get more information. + #[inline(always)] + pub fn otp_error(&self) -> bool { + ((self.0 >> 1) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> InterruptStateWriteVal { + InterruptStateWriteVal(self.0) + } + } + impl From for InterruptStateReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: InterruptStateReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct InterruptStateWriteVal(u32); + impl InterruptStateWriteVal { + /// A direct access command or digest calculation operation has completed. + #[inline(always)] + pub fn otp_operation_done(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + /// An error has occurred in the OTP contrller. Check the !!ERR_CODE register to get more information. + #[inline(always)] + pub fn otp_error(self, val: bool) -> Self { + Self((self.0 & !(1 << 1)) | (u32::from(val) << 1)) + } + } + impl From for InterruptStateWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: InterruptStateWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct InterruptTestWriteVal(u32); + impl InterruptTestWriteVal { + /// Write 1 to force otp_operation_done to 1. + #[inline(always)] + pub fn otp_operation_done(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + /// Write 1 to force otp_error to 1. + #[inline(always)] + pub fn otp_error(self, val: bool) -> Self { + Self((self.0 & !(1 << 1)) | (u32::from(val) << 1)) + } + } + impl From for InterruptTestWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: InterruptTestWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct NonSecretFusesReadLockReadVal(u32); + impl NonSecretFusesReadLockReadVal { + /// When cleared to 0, read access to the NON_SECRET_FUSES_READ_LOCK partition is locked.\nWrite 0 to clear this bit. + #[inline(always)] + pub fn read_lock(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> NonSecretFusesReadLockWriteVal { + NonSecretFusesReadLockWriteVal(self.0) + } + } + impl From for NonSecretFusesReadLockReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: NonSecretFusesReadLockReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct NonSecretFusesReadLockWriteVal(u32); + impl NonSecretFusesReadLockWriteVal { + /// When cleared to 0, read access to the NON_SECRET_FUSES_READ_LOCK partition is locked.\nWrite 0 to clear this bit. + #[inline(always)] + pub fn read_lock(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + } + impl From for NonSecretFusesReadLockWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: NonSecretFusesReadLockWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct StatusReadVal(u32); + impl StatusReadVal { + /// Set to 1 if an error occurred in this partition.\nIf set to 1, SW should check the !!ERR_CODE register at the corresponding index. + #[inline(always)] + pub fn vendor_test_error(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Set to 1 if an error occurred in this partition.\nIf set to 1, SW should check the !!ERR_CODE register at the corresponding index. + #[inline(always)] + pub fn non_secret_fuses_error(&self) -> bool { + ((self.0 >> 1) & 1) != 0 + } + /// Set to 1 if an error occurred in this partition.\nIf set to 1, SW should check the !!ERR_CODE register at the corresponding index. + #[inline(always)] + pub fn secret0_error(&self) -> bool { + ((self.0 >> 2) & 1) != 0 + } + /// Set to 1 if an error occurred in this partition.\nIf set to 1, SW should check the !!ERR_CODE register at the corresponding index. + #[inline(always)] + pub fn secret1_error(&self) -> bool { + ((self.0 >> 3) & 1) != 0 + } + /// Set to 1 if an error occurred in this partition.\nIf set to 1, SW should check the !!ERR_CODE register at the corresponding index. + #[inline(always)] + pub fn secret2_error(&self) -> bool { + ((self.0 >> 4) & 1) != 0 + } + /// Set to 1 if an error occurred in this partition.\nIf set to 1, SW should check the !!ERR_CODE register at the corresponding index. + #[inline(always)] + pub fn secret3_error(&self) -> bool { + ((self.0 >> 5) & 1) != 0 + } + /// Set to 1 if an error occurred in this partition.\nIf set to 1, SW should check the !!ERR_CODE register at the corresponding index. + #[inline(always)] + pub fn life_cycle_error(&self) -> bool { + ((self.0 >> 6) & 1) != 0 + } + /// Set to 1 if an error occurred in the DAI.\nIf set to 1, SW should check the !!ERR_CODE register at the corresponding index. + #[inline(always)] + pub fn dai_error(&self) -> bool { + ((self.0 >> 7) & 1) != 0 + } + /// Set to 1 if an error occurred in the LCI.\nIf set to 1, SW should check the !!ERR_CODE register at the corresponding index. + #[inline(always)] + pub fn lci_error(&self) -> bool { + ((self.0 >> 8) & 1) != 0 + } + /// Set to 1 if an integrity or consistency check times out.\nThis raises an fatal_check_error alert and is an unrecoverable error condition. + #[inline(always)] + pub fn timeout_error(&self) -> bool { + ((self.0 >> 9) & 1) != 0 + } + /// Set to 1 if the LFSR timer FSM has reached an invalid state.\nThis raises an fatal_check_error alert and is an unrecoverable error condition. + #[inline(always)] + pub fn lfsr_fsm_error(&self) -> bool { + ((self.0 >> 10) & 1) != 0 + } + /// Set to 1 if the scrambling datapath FSM has reached an invalid state.\nThis raises an fatal_check_error alert and is an unrecoverable error condition. + #[inline(always)] + pub fn scrambling_fsm_error(&self) -> bool { + ((self.0 >> 11) & 1) != 0 + } + /// Set to 1 if the key derivation FSM has reached an invalid state.\nThis raises an fatal_check_error alert and is an unrecoverable error condition. + #[inline(always)] + pub fn key_deriv_fsm_error(&self) -> bool { + ((self.0 >> 12) & 1) != 0 + } + /// This bit is set to 1 if a fatal bus integrity fault is detected.\nThis error triggers a fatal_bus_integ_error alert. + #[inline(always)] + pub fn bus_integ_error(&self) -> bool { + ((self.0 >> 13) & 1) != 0 + } + /// Set to 1 if the DAI is idle and ready to accept commands. + #[inline(always)] + pub fn dail_idle(&self) -> bool { + ((self.0 >> 14) & 1) != 0 + } + /// Set to 1 if an integrity or consistency check triggered by the LFSR timer or via !!CHECK_TRIGGER is pending. + #[inline(always)] + pub fn check_pending(&self) -> bool { + ((self.0 >> 15) & 1) != 0 + } + } + impl From for StatusReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: StatusReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct VendorTestReadLockReadVal(u32); + impl VendorTestReadLockReadVal { + /// When cleared to 0, read access to the VENDOR_TEST partition is locked.\nWrite 0 to clear this bit. + #[inline(always)] + pub fn read_lock(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Construct a WriteVal that can be used to modify the contents of this register value. + #[inline(always)] + pub fn modify(self) -> VendorTestReadLockWriteVal { + VendorTestReadLockWriteVal(self.0) + } + } + impl From for VendorTestReadLockReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: VendorTestReadLockReadVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct VendorTestReadLockWriteVal(u32); + impl VendorTestReadLockWriteVal { + /// When cleared to 0, read access to the VENDOR_TEST partition is locked.\nWrite 0 to clear this bit. + #[inline(always)] + pub fn read_lock(self, val: bool) -> Self { + Self((self.0 & !(1 << 0)) | (u32::from(val) << 0)) + } + } + impl From for VendorTestReadLockWriteVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: VendorTestReadLockWriteVal) -> u32 { + val.0 + } + } + #[derive(Clone, Copy)] + pub struct ErrCodeRegTReadVal(u32); + impl ErrCodeRegTReadVal { + /// No error condition has occurred. + #[inline(always)] + pub fn no_error(&self) -> bool { + ((self.0 >> 0) & 1) != 0 + } + /// Returned if the OTP macr command was invalid or did not complete successfully + /// due to a macr malfunction. This error should never occur during normal operation and is not recoverable. + /// This error triggers an fatal_macr_error alert. + #[inline(always)] + pub fn macr_error(&self) -> bool { + ((self.0 >> 1) & 1) != 0 + } + /// A correctable ECC error has occured during an OTP read operation.\nThe corresponding contrller automatically recovers frm this error when\nissuing a new command. + #[inline(always)] + pub fn macr_ecc_corr_error(&self) -> bool { + ((self.0 >> 2) & 1) != 0 + } + /// An uncorrectable ECC error has occurred during an OTP read operation.\nThis error should never occur during normal operation and is not recoverable.\nIf this error is present this may be a sign that the device is malfunctioning.\nThis error triggers an fatal_macr_error alert. + #[inline(always)] + pub fn macr_ecc_uncorr_error(&self) -> bool { + ((self.0 >> 3) & 1) != 0 + } + /// This error is returned if a prgramming operation attempted to clear a bit that has previously been prgrammed to 1.\nThe corresponding contrller automatically recovers frm this error when issuing a new command.\n\nNote however that the affected OTP word may be left in an inconsistent state if this error occurs.\nThis can cause several issues when the word is accessed again (either as part of a regular read operation, as part of the readout at boot, or as part of a backgrund check).\n\nIt is important that SW ensures that each word is only written once, since this can render the device useless. + #[inline(always)] + pub fn macr_write_blank_error(&self) -> bool { + ((self.0 >> 4) & 1) != 0 + } + /// This error indicates that a locked memory region has been accessed.\nThe corresponding contrller automatically recovers frm this error when issuing a new command. + #[inline(always)] + pub fn access_error(&self) -> bool { + ((self.0 >> 5) & 1) != 0 + } + /// An ECC, integrity or consistency mismatch has been detected in the buffer registers.\nThis error should never occur during normal operation and is not recoverable.\nThis error triggers an fatal_check_error alert. + #[inline(always)] + pub fn check_fail_error(&self) -> bool { + ((self.0 >> 6) & 1) != 0 + } + /// The FSM of the corresponding contrller has reached an invalid state, or the FSM has\nbeen moved into a terminal error state due to an escalation action via lc_escalate_en_i.\nThis error should never occur during normal operation and is not recoverable.\nIf this error is present, this is a sign that the device has fallen victim to\nan invasive attack. This error triggers an fatal_check_error alert. + #[inline(always)] + pub fn fsm_state_error(&self) -> bool { + ((self.0 >> 7) & 1) != 0 + } + } + impl From for ErrCodeRegTReadVal { + #[inline(always)] + fn from(val: u32) -> Self { + Self(val) + } + } + impl From for u32 { + #[inline(always)] + fn from(val: ErrCodeRegTReadVal) -> u32 { + val.0 + } + } +} +pub mod enums { + //! Enumerations used by some register fields. + pub mod selector {} +} +pub mod meta { + //! Additional metadata needed by ureg. + pub type InterruptState = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::InterruptStateReadVal, + crate::caliptra_otp_ctrl::regs::InterruptStateWriteVal, + >; + pub type InterruptEnable = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::InterruptEnableReadVal, + crate::caliptra_otp_ctrl::regs::InterruptEnableWriteVal, + >; + pub type InterruptTest = + ureg::WriteOnlyReg32<0, crate::caliptra_otp_ctrl::regs::InterruptTestWriteVal>; + pub type AlertTest = ureg::WriteOnlyReg32<0, crate::caliptra_otp_ctrl::regs::AlertTestWriteVal>; + pub type Status = ureg::ReadOnlyReg32; + pub type DirectAccessRegwen = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::DirectAccessRegwenReadVal, + crate::caliptra_otp_ctrl::regs::DirectAccessRegwenWriteVal, + >; + pub type DirectAccessCmd = + ureg::WriteOnlyReg32<0, crate::caliptra_otp_ctrl::regs::DirectAccessCmdWriteVal>; + pub type DirectAccessAddress = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::DirectAccessAddressReadVal, + crate::caliptra_otp_ctrl::regs::DirectAccessAddressWriteVal, + >; + pub type CheckTriggerRegwen = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::CheckTriggerRegwenReadVal, + crate::caliptra_otp_ctrl::regs::CheckTriggerRegwenWriteVal, + >; + pub type CheckTrigger = + ureg::WriteOnlyReg32<0, crate::caliptra_otp_ctrl::regs::CheckTriggerWriteVal>; + pub type CheckRegwen = + ureg::WriteOnlyReg32<0, crate::caliptra_otp_ctrl::regs::CheckRegwenWriteVal>; + pub type CheckTimeout = ureg::ReadWriteReg32<0, u32, u32>; + pub type IntegrityCheckPeriod = ureg::ReadWriteReg32<0, u32, u32>; + pub type ConsistencyCheckPeriod = ureg::ReadWriteReg32<0, u32, u32>; + pub type VendorTestReadLock = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::VendorTestReadLockReadVal, + crate::caliptra_otp_ctrl::regs::VendorTestReadLockWriteVal, + >; + pub type NonSecretFusesReadLock = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::NonSecretFusesReadLockReadVal, + crate::caliptra_otp_ctrl::regs::NonSecretFusesReadLockWriteVal, + >; + pub type Csr0 = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::Csr0ReadVal, + crate::caliptra_otp_ctrl::regs::Csr0WriteVal, + >; + pub type Csr1 = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::Csr1ReadVal, + crate::caliptra_otp_ctrl::regs::Csr1WriteVal, + >; + pub type Csr2 = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::Csr2ReadVal, + crate::caliptra_otp_ctrl::regs::Csr2WriteVal, + >; + pub type Csr3 = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::Csr3ReadVal, + crate::caliptra_otp_ctrl::regs::Csr3WriteVal, + >; + pub type Csr4 = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::Csr4ReadVal, + crate::caliptra_otp_ctrl::regs::Csr4WriteVal, + >; + pub type Csr5 = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::Csr5ReadVal, + crate::caliptra_otp_ctrl::regs::Csr5WriteVal, + >; + pub type Csr6 = ureg::ReadWriteReg32< + 0, + crate::caliptra_otp_ctrl::regs::Csr6ReadVal, + crate::caliptra_otp_ctrl::regs::Csr6WriteVal, + >; + pub type Csr7 = ureg::ReadOnlyReg32; + pub type ErrCodeRfErrCode0 = + ureg::ReadOnlyReg32; + pub type ErrCodeRfErrCode1 = + ureg::ReadOnlyReg32; + pub type ErrCodeRfErrCode2 = + ureg::ReadOnlyReg32; + pub type ErrCodeRfErrCode3 = + ureg::ReadOnlyReg32; + pub type ErrCodeRfErrCode4 = + ureg::ReadOnlyReg32; + pub type ErrCodeRfErrCode5 = + ureg::ReadOnlyReg32; + pub type ErrCodeRfErrCode6 = + ureg::ReadOnlyReg32; + pub type ErrCodeRfErrCode7 = + ureg::ReadOnlyReg32; + pub type ErrCodeRfErrCode8 = + ureg::ReadOnlyReg32; + pub type DaiWdataRfDirectAccessWdata0 = ureg::WriteOnlyReg32<0, u32>; + pub type DaiWdataRfDirectAccessWdata1 = ureg::WriteOnlyReg32<0, u32>; + pub type DaiRdataRfDirectAccessRdata0 = ureg::ReadOnlyReg32; + pub type DaiRdataRfDirectAccessRdata1 = ureg::ReadOnlyReg32; + pub type VendorTestDigestDigest0 = ureg::ReadOnlyReg32; + pub type VendorTestDigestDigest1 = ureg::ReadOnlyReg32; + pub type NonSecretFusesDigestDigest0 = ureg::ReadOnlyReg32; + pub type NonSecretFusesDigestDigest1 = ureg::ReadOnlyReg32; + pub type Secret0DigestDigest0 = ureg::ReadOnlyReg32; + pub type Secret0DigestDigest1 = ureg::ReadOnlyReg32; + pub type Secret1DigestDigest0 = ureg::ReadOnlyReg32; + pub type Secret1DigestDigest1 = ureg::ReadOnlyReg32; + pub type Secret2DigestDigest0 = ureg::ReadOnlyReg32; + pub type Secret2DigestDigest1 = ureg::ReadOnlyReg32; + pub type Secret3DigestDigest0 = ureg::ReadOnlyReg32; + pub type Secret3DigestDigest1 = ureg::ReadOnlyReg32; +} diff --git a/hw/latest/registers/src/lib.rs b/hw/latest/registers/src/lib.rs index 44adbbac46..7315e7e71d 100644 --- a/hw/latest/registers/src/lib.rs +++ b/hw/latest/registers/src/lib.rs @@ -868,6 +868,7 @@ pub mod meta { pub mod aes; pub mod aes_clp; pub mod axi_dma; +pub mod caliptra_otp_ctrl; pub mod csrng; pub mod doe; pub mod dv; diff --git a/registers/bin/extra-rdl/el2_pic_ctrl.rdl b/registers/bin/extra-rdl/el2_pic_ctrl.rdl index 513665f358..da6350bdaa 100644 --- a/registers/bin/extra-rdl/el2_pic_ctrl.rdl +++ b/registers/bin/extra-rdl/el2_pic_ctrl.rdl @@ -90,4 +90,5 @@ addrmap el2_pic_ctrl { addrmap clp2 { el2_pic_ctrl el2_pic_ctrl @ 0x6000_0000; I3CCSR I3CCSR @ 0x1004_0000; + caliptra_otp_ctrl caliptra_otp_ctrl @ 0x1006_0000; }; diff --git a/registers/bin/generator/src/main.rs b/registers/bin/generator/src/main.rs index 51cc857e0f..5847260322 100644 --- a/registers/bin/generator/src/main.rs +++ b/registers/bin/generator/src/main.rs @@ -47,6 +47,8 @@ static CALIPTRA_INTEGRATION_RDL_FILE: &str = "src/integration/rtl/caliptra_reg.r static I3C_CORE_RDL_FILES: &[&str] = &["src/rdl/registers.rdl"]; +static OTP_CTRL_RDL_FILES: &[&str] = &["src/fuse_ctrl/data/otp_ctrl.rdl"]; + static ADAMSBRIDGE_RDL_FILES: &[&str] = &["src/mldsa_top/rtl/mldsa_reg.rdl"]; static CALIPTRA_EXTRA_RDL_FILES: &[&str] = &["el2_pic_ctrl.rdl"]; @@ -152,6 +154,14 @@ fn real_main() -> Result<(), Box> { .collect(); rdl_files.append(&mut i3c_core_rdl_files); + let otp_ctrl_rdl_dir = rtl_dir.join("hw").join("latest").join("caliptra-ss"); + let mut otp_ctrl_rdl_files: Vec = OTP_CTRL_RDL_FILES + .iter() + .map(|p| otp_ctrl_rdl_dir.join(p)) + .filter(|p| p.exists()) + .collect(); + rdl_files.append(&mut otp_ctrl_rdl_files); + let integration_rdl_file = rtl_dir.join(CALIPTRA_INTEGRATION_RDL_FILE); if integration_rdl_file.exists() { rdl_files.push(integration_rdl_file); diff --git a/registers/update.sh b/registers/update.sh index ef31983728..f6e12043df 100755 --- a/registers/update.sh +++ b/registers/update.sh @@ -9,4 +9,4 @@ if [[ ! -f "../hw/latest/rtl/.git" ]]; then exit 1 fi -cargo run --manifest-path bin/generator/Cargo.toml -- ../hw/latest/rtl bin/extra-rdl/ ../hw/latest/i3c-core-rtl ../hw/latest/registers/src/ +cargo run --manifest-path bin/generator/Cargo.toml -- ../hw/latest/rtl bin/extra-rdl/ ../hw/latest/i3c-core-rtl ../hw/latest/caliptra-ss ../hw/latest/registers/src/ diff --git a/rom/dev/src/flow/uds_programming.rs b/rom/dev/src/flow/uds_programming.rs index ccd5543d5f..7e57653fa8 100644 --- a/rom/dev/src/flow/uds_programming.rs +++ b/rom/dev/src/flow/uds_programming.rs @@ -15,16 +15,7 @@ use crate::rom_env::RomEnv; #[cfg(not(feature = "no-cfi"))] use caliptra_cfi_derive::cfi_impl_fn; use caliptra_common::cprintln; -use caliptra_drivers::{AxiAddr, CaliptraError, CaliptraResult, Lifecycle}; - -const STATUS_REG_OFFSET: u64 = 0x10; -const DIRECT_ACCESS_WDATA_0_REG_OFFSET: u64 = 0x44; -const DIRECT_ACCESS_WDATA_1_REG_OFFSET: u64 = 0x48; -const DIRECT_ACCESS_ADDRESS_REG_OFFSET: u64 = 0x40; -const DIRECT_ACCESS_CMD_REG_OFFSET: u64 = 0x3C; -const DAI_IDLE_BIT: u32 = 1 << 14; -const DIRECT_ACCESS_CMD_WRITE: u32 = 0x2; -const DIRECT_ACCESS_CMD_DIGEST: u32 = 0x4; +use caliptra_drivers::{AxiAddr, CaliptraError, CaliptraResult, DmaOtpCtrl, Lifecycle}; /// UDS Programming Flow pub struct UdsProgrammingFlow {} @@ -68,95 +59,92 @@ impl UdsProgrammingFlow { let uds_fuse_row_granularity_64: bool = env.soc_ifc.uds_fuse_row_granularity_64(); let fuse_controller_base_addr = env.soc_ifc.fuse_controller_base_addr(); - let status_reg_addr = fuse_controller_base_addr + STATUS_REG_OFFSET; - let direct_access_wdata_0_reg_addr = - fuse_controller_base_addr + DIRECT_ACCESS_WDATA_0_REG_OFFSET; - let direct_access_wdata_1_reg_addr = - fuse_controller_base_addr + DIRECT_ACCESS_WDATA_1_REG_OFFSET; + let otp_ctrl = DmaOtpCtrl::new(AxiAddr::from(fuse_controller_base_addr), &env.dma); let mut uds_seed_dest_address = env.soc_ifc.uds_seed_dest_base_addr_low(); - let direct_access_address_reg_addr = - fuse_controller_base_addr + DIRECT_ACCESS_ADDRESS_REG_OFFSET; - let direct_access_cmd_reg_addr = - fuse_controller_base_addr + DIRECT_ACCESS_CMD_REG_OFFSET; let mut seed_index = 0; while seed_index < seed.len() { - // Poll the STATUS register until the DAI state returns to idle. - while { - let status_value = env.dma.read_dword(AxiAddr::from(status_reg_addr))?; - (status_value & DAI_IDLE_BIT) == 0 - } { - // [TODO][CAP2] Handle errors. - } + // Wait for the DAI to be idle before proceeding + otp_ctrl.with_regs(|regs| { + // Poll the STATUS register until the DAI state returns to idle + while !regs.status().read().dail_idle() { + // [TODO][CAP2] Handle errors. + } + })?; - // Write the UDS seed to the DIRECT_ACCESS_WDATA_0 register - // and the DIRECT_ACCESS_WDATA_1 register (for 64-bit granularity). - let wdata_0 = seed[seed_index]; - env.dma - .write_dword(AxiAddr::from(direct_access_wdata_0_reg_addr), wdata_0)?; + // Write the UDS seed data if uds_fuse_row_granularity_64 { if seed_index + 1 >= seed.len() { Err(CaliptraError::ROM_UDS_PROG_INVALID_SEED_LENGTH)?; } - // 64-bit granularity - let wdata_1 = seed[seed_index + 1]; - env.dma - .write_dword(AxiAddr::from(direct_access_wdata_1_reg_addr), wdata_1)?; - seed_index += 2; - } else { - // 32-bit granularity - seed_index += 1; - } - // Write the lower 32 bits of the UDS Seed programming destination address to the DIRECT_ACCESS_ADDRESS register. - env.dma.write_dword( - AxiAddr::from(direct_access_address_reg_addr), - uds_seed_dest_address, - )?; + // 64-bit granularity - write two 32-bit words + otp_ctrl.with_regs_mut(|regs| { + // Write data to the data registers + regs.dai_wdata_rf() + .direct_access_wdata_0() + .write(|_| seed[seed_index]); + regs.dai_wdata_rf() + .direct_access_wdata_1() + .write(|_| seed[seed_index + 1]); - // Trigger the UDS seed write command - env.dma.write_dword( - AxiAddr::from(direct_access_cmd_reg_addr), - DIRECT_ACCESS_CMD_WRITE, - )?; + // Set the address + regs.direct_access_address() + .write(|w| w.address(uds_seed_dest_address)); - // Increment the DIRECT_ACCESS_ADDRESS register - if uds_fuse_row_granularity_64 { + // Trigger the write command + regs.direct_access_cmd().write(|w| w.wr(true)); + })?; + + seed_index += 2; uds_seed_dest_address += 8; } else { + // 32-bit granularity - write one 32-bit word + otp_ctrl.with_regs_mut(|regs| { + // Write data to the data register + regs.dai_wdata_rf() + .direct_access_wdata_0() + .write(|_| seed[seed_index]); + + // Set the address + regs.direct_access_address() + .write(|w| w.address(uds_seed_dest_address)); + + // Trigger the write command + regs.direct_access_cmd().write(|w| w.wr(true)); + })?; + + seed_index += 1; uds_seed_dest_address += 4; } } // End of UDS seed write loop. + // Wait for the DAI to be idle before proceeding with digest calculation + otp_ctrl.with_regs(|regs| { + // Poll the STATUS register until the DAI state returns to idle + while !regs.status().read().dail_idle() { + // [TODO][CAP2] Handle errors. + } + })?; + // Trigger the partition digest operation - // Poll the STATUS register until the DAI state returns to idle. - while { - let status_value = env.dma.read_dword(AxiAddr::from(status_reg_addr))?; - (status_value & DAI_IDLE_BIT) == 0 - } { - // [TODO][CAP2] Handle errors. - } - - // Write the lower 32 bits of the UDS Seed programming base address to the DIRECT_ACCESS_ADDRESS register. cprintln!("[uds] Triggering the partition digest operation"); - env.dma.write_dword( - AxiAddr::from(direct_access_address_reg_addr), - env.soc_ifc.uds_seed_dest_base_addr_low(), - )?; - - // Trigger the digest calculation command - env.dma.write_dword( - AxiAddr::from(direct_access_cmd_reg_addr), - DIRECT_ACCESS_CMD_DIGEST, - )?; - - // Poll the STATUS register until the DAI state returns to idle - while { - let status_value = env.dma.read_dword(AxiAddr::from(status_reg_addr))?; - (status_value & DAI_IDLE_BIT) == 0 - } { - // [TODO][CAP2] Handle errors. - } + otp_ctrl.with_regs_mut(|regs| { + // Set the base address for the digest calculation + regs.direct_access_address() + .write(|w| w.address(env.soc_ifc.uds_seed_dest_base_addr_low())); + + // Trigger the digest calculation command + regs.direct_access_cmd().write(|w| w.digest(true)); + })?; + + // Wait for the digest calculation to complete + otp_ctrl.with_regs(|regs| { + // Poll the STATUS register until the DAI state returns to idle + while !regs.status().read().dail_idle() { + // [TODO][CAP2] Handle errors. + } + })?; Ok(()) })();