1 // Copyright 2022 the authors.
2 // This project is dual-licensed under Apache 2.0 and MIT terms.
3 // See LICENSE-APACHE and LICENSE-MIT for details.
4 
5 //! Constants for version 1.1 of the Arm Power State Coordination Interface (PSCI) version 1.1, and
6 //! functions to call them.
7 //!
8 //! Note that PSCI and other SMCCC calls may be made via either HVC or SMC. You can choose which one
9 //! to use by building this crate with the corresponding feature (i.e. `hvc` or `smc`). By default
10 //! `hvc` is enabled. If neither feature is enabled then the functions to make calls will not be
11 //! available, but the constants and types are still provided.
12 //!
13 //! This crate currently only supports aarch64 and the SMC64 versions of the various calls, in the
14 //! cases that both SMC32 and SMC64 versions exist.
15 
16 mod calls;
17 pub mod error;
18 
19 pub use calls::{
20     affinity_info, cpu_default_suspend, cpu_freeze, cpu_off, cpu_on, cpu_suspend, mem_protect,
21     mem_protect_check_range, migrate, migrate_info_type, migrate_info_up_cpu, node_hw_state,
22     psci_features, set_suspend_mode, stat_count, stat_residency, system_off, system_reset,
23     system_reset2, system_suspend, version,
24 };
25 pub use error::Error;
26 
27 pub const PSCI_VERSION: u32 = 0x84000000;
28 pub const PSCI_CPU_SUSPEND_32: u32 = 0x84000001;
29 pub const PSCI_CPU_SUSPEND_64: u32 = 0xC4000001;
30 pub const PSCI_CPU_OFF: u32 = 0x84000002;
31 pub const PSCI_CPU_ON_32: u32 = 0x84000003;
32 pub const PSCI_CPU_ON_64: u32 = 0xC4000003;
33 pub const PSCI_AFFINITY_INFO_32: u32 = 0x84000004;
34 pub const PSCI_AFFINITY_INFO_64: u32 = 0xC4000004;
35 pub const PSCI_MIGRATE_32: u32 = 0x84000005;
36 pub const PSCI_MIGRATE_64: u32 = 0xC4000005;
37 pub const PSCI_MIGRATE_INFO_TYPE: u32 = 0x84000006;
38 pub const PSCI_MIGRATE_INFO_UP_CPU_32: u32 = 0x84000007;
39 pub const PSCI_MIGRATE_INFO_UP_CPU_64: u32 = 0xC4000007;
40 pub const PSCI_SYSTEM_OFF: u32 = 0x84000008;
41 pub const PSCI_SYSTEM_RESET: u32 = 0x84000009;
42 pub const PSCI_SYSTEM_RESET2_32: u32 = 0x84000012;
43 pub const PSCI_SYSTEM_RESET2_64: u32 = 0xC4000012;
44 pub const PSCI_MEM_PROTECT: u32 = 0x84000013;
45 pub const PSCI_MEM_PROTECT_CHECK_RANGE_32: u32 = 0x84000014;
46 pub const PSCI_MEM_PROTECT_CHECK_RANGE_64: u32 = 0xC4000014;
47 pub const PSCI_FEATURES: u32 = 0x8400000A;
48 pub const PSCI_CPU_FREEZE: u32 = 0x8400000B;
49 pub const PSCI_CPU_DEFAULT_SUSPEND_32: u32 = 0x8400000C;
50 pub const PSCI_CPU_DEFAULT_SUSPEND_64: u32 = 0xC400000C;
51 pub const PSCI_NODE_HW_STATE_32: u32 = 0x8400000D;
52 pub const PSCI_NODE_HW_STATE_64: u32 = 0xC400000D;
53 pub const PSCI_SYSTEM_SUSPEND_32: u32 = 0x8400000E;
54 pub const PSCI_SYSTEM_SUSPEND_64: u32 = 0xC400000E;
55 pub const PSCI_SET_SUSPEND_MODE: u32 = 0x8400000F;
56 pub const PSCI_STAT_RESIDENCY_32: u32 = 0x84000010;
57 pub const PSCI_STAT_RESIDENCY_64: u32 = 0xC4000010;
58 pub const PSCI_STAT_COUNT_32: u32 = 0x84000011;
59 pub const PSCI_STAT_COUNT_64: u32 = 0xC4000011;
60 
61 /// Selects which affinity level fields are valid in the `target_affinity` parameter to
62 /// `AFFINITY_INFO`.
63 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
64 pub enum LowestAffinityLevel {
65     /// All afinity level fields are valid.
66     All = 0,
67     /// The `Aff0` field is ignored.
68     Aff0Ignored = 1,
69     /// The `Aff0` and `Aff1` fields are ignored.
70     Aff0Aff1Ignored = 2,
71     /// The `Aff0`, `Aff1` and `Aff2` fields are ignored.
72     Aff0Aff1Aff2Ignored = 3,
73 }
74 
75 impl From<LowestAffinityLevel> for u64 {
from(lowest_affinity_level: LowestAffinityLevel) -> u6476     fn from(lowest_affinity_level: LowestAffinityLevel) -> u64 {
77         (lowest_affinity_level as u32).into()
78     }
79 }
80 
81 /// Affinity state values returned by `AFFINITY_INFO`.
82 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
83 pub enum AffinityState {
84     /// At least one core in the affinity instance is on.
85     On = 0,
86     /// All cores in the affinity instance are off.
87     Off = 1,
88     /// The affinity instance is transitioning to the on state.
89     OnPending = 2,
90 }
91 
92 impl TryFrom<i32> for AffinityState {
93     type Error = Error;
94 
try_from(value: i32) -> Result<Self, Error>95     fn try_from(value: i32) -> Result<Self, Error> {
96         match value {
97             0 => Ok(Self::On),
98             1 => Ok(Self::Off),
99             2 => Ok(Self::OnPending),
100             _ => Err(value.into()),
101         }
102     }
103 }
104 
105 /// The level of multicore support in the Trusted OS, as returned by `MIGRATE_INFO_TYPE`.
106 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
107 pub enum MigrateType {
108     /// The Trusted OS will only run on one core, and supports the `MIGRATE` function.
109     MigrateCapable = 0,
110     /// The Trusted OS does not support the `MIGRATE` function.
111     NotMigrateCapable = 1,
112     /// Either there is no Trusted OS, or it doesn't require migration.
113     MigrationNotRequired = 2,
114 }
115 
116 impl TryFrom<i32> for MigrateType {
117     type Error = Error;
118 
try_from(value: i32) -> Result<Self, Error>119     fn try_from(value: i32) -> Result<Self, Error> {
120         match value {
121             0 => Ok(Self::MigrateCapable),
122             1 => Ok(Self::NotMigrateCapable),
123             2 => Ok(Self::MigrationNotRequired),
124             _ => Err(value.into()),
125         }
126     }
127 }
128 
129 /// The power state of a node in the power domain topology, as returned by `NODE_HW_STATE`.
130 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
131 pub enum PowerState {
132     /// The node is in the run state.
133     HwOn = 0,
134     /// The node is fully powered down.
135     HwOff = 1,
136     /// The node is in a standby or retention power state.
137     HwStandby = 2,
138 }
139 
140 impl TryFrom<i32> for PowerState {
141     type Error = Error;
142 
try_from(value: i32) -> Result<Self, Error>143     fn try_from(value: i32) -> Result<Self, Error> {
144         match value {
145             0 => Ok(Self::HwOn),
146             1 => Ok(Self::HwOff),
147             2 => Ok(Self::HwStandby),
148             _ => Err(value.into()),
149         }
150     }
151 }
152 
153 /// The mode to be used by `CPU_SUSPEND`, as set by `PSCI_SET_SUSPEND_MODE`.
154 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
155 pub enum SuspendMode {
156     /// Platform-coordinated mode.
157     PlatformCoordinated = 0,
158     /// OS-initiated mode.
159     OsInitiated = 1,
160 }
161 
162 impl From<SuspendMode> for u32 {
from(suspend_mode: SuspendMode) -> u32163     fn from(suspend_mode: SuspendMode) -> u32 {
164         suspend_mode as u32
165     }
166 }
167