| // 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)); |
| } |
| } |