diff options
Diffstat (limited to 'src/arch.rs')
-rw-r--r-- | src/arch.rs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/arch.rs b/src/arch.rs new file mode 100644 index 0000000..e3673f7 --- /dev/null +++ b/src/arch.rs @@ -0,0 +1,88 @@ +// Copyright 2023 the authors. +// This project is dual-licensed under Apache 2.0 and MIT terms. +// See LICENSE-APACHE and LICENSE-MIT for details. + +//! Standard Arm architecture calls. + +mod calls; +pub mod error; + +pub use calls::{ + arch_workaround_1, arch_workaround_2, arch_workaround_3, features, soc_id, version, +}; +use core::fmt::{self, Debug, Display, Formatter}; +pub use error::Error; + +pub const SMCCC_VERSION: u32 = 0x8000_0000; +pub const SMCCC_ARCH_FEATURES: u32 = 0x8000_0001; +pub const SMCCC_ARCH_SOC_ID: u32 = 0x8000_0002; +pub const SMCCC_ARCH_WORKAROUND_1: u32 = 0x8000_8000; +pub const SMCCC_ARCH_WORKAROUND_2: u32 = 0x8000_7FFF; +pub const SMCCC_ARCH_WORKAROUND_3: u32 = 0x8000_3FFF; + +/// A version of the SMC Calling Convention. +#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)] +pub struct Version { + pub major: u16, + pub minor: u16, +} + +impl Display for Version { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}.{}", self.major, self.minor) + } +} + +impl Debug for Version { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + Display::fmt(self, f) + } +} + +impl TryFrom<i32> for Version { + type Error = Error; + + fn try_from(value: i32) -> Result<Self, Error> { + if value < 0 { + Err(value.into()) + } else { + Ok(Self { + major: (value >> 16) as u16, + minor: value as u16, + }) + } + } +} + +impl From<Version> for u32 { + fn from(version: Version) -> Self { + u32::from(version.major) << 16 | u32::from(version.minor) + } +} + +#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)] +#[repr(u32)] +pub enum SocIdType { + /// The SoC version. + Version, + /// The SoC revision. + Revision, +} + +impl From<SocIdType> for u32 { + fn from(id_type: SocIdType) -> Self { + id_type as Self + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn convert_version() { + let version = Version { major: 1, minor: 2 }; + assert_eq!(u32::from(version), 0x0001_0002); + assert_eq!(0x0001_0002.try_into(), Ok(version)); + } +} |