1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
|
#![no_std]
pub mod cpu_mode_ctrl {
pub type Instance = ral_registers::Instance<RegisterBlock>;
#[repr(C)]
#[allow(non_snake_case)]
pub struct RegisterBlock {
reserved_0: [u8; 4],
pub CM_AUTHEN_CTRL: u32,
pub CM_INT_CTRL: u32,
pub CM_MISC: u32,
pub CM_MODE_CTRL: u32,
pub CM_MODE_STAT: u32,
reserved_1: [u8; 232],
pub CM_IRQ_WAKEUP_MASK: [u32; 8],
reserved_2: [u8; 32],
pub CM_NON_IRQ_WAKEUP_MASK: u32,
reserved_3: [u8; 12],
pub CM_IRQ_WAKEUP_STAT: [u32; 8],
reserved_4: [u8; 32],
pub CM_NON_IRQ_WAKEUP_STAT: u32,
reserved_5: [u8; 108],
pub CM_SLEEP_SSAR_CTRL: u32,
reserved_6: [u8; 4],
pub CM_SLEEP_LPCG_CTRL: u32,
reserved_7: [u8; 4],
pub CM_SLEEP_PLL_CTRL: u32,
reserved_8: [u8; 4],
pub CM_SLEEP_ISO_CTRL: u32,
reserved_9: [u8; 4],
pub CM_SLEEP_RESET_CTRL: u32,
reserved_10: [u8; 4],
pub CM_SLEEP_POWER_CTRL: u32,
reserved_11: [u8; 100],
pub CM_WAKEUP_POWER_CTRL: u32,
reserved_12: [u8; 4],
pub CM_WAKEUP_RESET_CTRL: u32,
reserved_13: [u8; 4],
pub CM_WAKEUP_ISO_CTRL: u32,
reserved_14: [u8; 4],
pub CM_WAKEUP_PLL_CTRL: u32,
reserved_15: [u8; 4],
pub CM_WAKEUP_LPCG_CTRL: u32,
reserved_16: [u8; 4],
pub CM_WAKEUP_SSAR_CTRL: u32,
reserved_17: [u8; 68],
pub CM_SP_CTRL: u32,
pub CM_SP_STAT: u32,
reserved_18: [u8; 8],
pub CM_RUN_MODE_MAPPING: u32,
pub CM_WAIT_MODE_MAPPING: u32,
pub CM_STOP_MODE_MAPPING: u32,
pub CM_SUSPEND_MODE_MAPPING: u32,
pub CM_SP_MAPPING: [u32; 16],
reserved_19: [u8; 32],
pub CM_STBY_CTRL: u32,
}
ral_registers::register! {
#[doc = "CM Authentication Control"]
pub CM_AUTHEN_CTRL<u32> RW [
#[doc = "Allow user mode access"]
USER start(0) width(1) RW {}
#[doc = "Allow non-secure mode access"]
NONSECURE start(1) width(1) RW {}
#[doc = "Lock NONSECURE and USER"]
LOCK_SETTING start(4) width(1) RW {}
#[doc = "Domain ID white list"]
WHITE_LIST start(8) width(4) RW {}
#[doc = "White list lock"]
LOCK_LIST start(12) width(1) RW {}
#[doc = "Configuration lock"]
LOCK_CFG start(20) width(1) RW {}
]
}
ral_registers::register! {
#[doc = "CM Interrupt Control"]
pub CM_INT_CTRL<u32> RW [
#[doc = "sp_req_not_allowed_for_sleep interrupt enable"]
SP_REQ_NOT_ALLOWED_SLEEP_INT_EN start(0) width(1) RW {}
#[doc = "sp_req_not_allowed_for_wakeup interrupt enable"]
SP_REQ_NOT_ALLOWED_WAKEUP_INT_EN start(1) width(1) RW {}
#[doc = "sp_req_not_allowed_for_soft interrupt enable"]
SP_REQ_NOT_ALLOWED_SOFT_INT_EN start(2) width(1) RW {}
#[doc = "sp_req_not_allowed_for_sleep interrupt status and clear register"]
SP_REQ_NOT_ALLOWED_SLEEP_INT start(16) width(1) RW {}
#[doc = "sp_req_not_allowed_for_wakeup interrupt status and clear register"]
SP_REQ_NOT_ALLOWED_WAKEUP_INT start(17) width(1) RW {}
#[doc = "sp_req_not_allowed_for_soft interrupt status and clear register"]
SP_REQ_NOT_ALLOWED_SOFT_INT start(18) width(1) RW {}
]
}
ral_registers::register! {
#[doc = "Miscellaneous"]
pub CM_MISC<u32> RW [
#[doc = "Non-masked interrupt status"]
NMI_STAT start(0) width(1) RO {}
#[doc = "Allow cpu_sleep_hold_req assert during CPU low power status"]
SLEEP_HOLD_EN start(1) width(1) RW {}
#[doc = "Status of cpu_sleep_hold_ack_b"]
SLEEP_HOLD_STAT start(2) width(1) RO {}
#[doc = "Master CPU"]
MASTER_CPU start(4) width(1) RW {}
]
}
ral_registers::register! {
#[doc = "CPU mode control"]
pub CM_MODE_CTRL<u32> RW [
#[doc = "The CPU mode the CPU platform should transit to on next sleep event"]
CPU_MODE_TARGET start(0) width(2) RW {
#[doc = "Stay in RUN mode"]
RUN = 0,
#[doc = "Transit to WAIT mode"]
WAIT = 0x1,
#[doc = "Transit to STOP mode"]
STOP = 0x2,
#[doc = "Transit to SUSPEND mode"]
SUSPEND = 0x3,
}
#[doc = "WFE assertion can be sleep event"]
WFE_EN start(4) width(1) RW {}
]
}
ral_registers::register! {
#[doc = "CM CPU mode Status"]
pub CM_MODE_STAT<u32> RO [
#[doc = "Current CPU mode"]
CPU_MODE_CURRENT start(0) width(2) RO {
#[doc = "CPU is currently in RUN mode"]
RUN = 0,
#[doc = "CPU is currently in WAIT mode"]
WAIT = 0x1,
#[doc = "CPU is currently in STOP mode"]
STOP = 0x2,
#[doc = "CPU is currently in SUSPEND mode"]
SUSPEND = 0x3,
}
#[doc = "Previous CPU mode"]
CPU_MODE_PREVIOUS start(2) width(2) RO {
#[doc = "CPU was previously in RUN mode"]
RUN = 0,
#[doc = "CPU was previously in WAIT mode"]
WAIT = 0x1,
#[doc = "CPU was previously in STOP mode"]
STOP = 0x2,
#[doc = "CPU was previously in SUSPEND mode"]
SUSPEND = 0x3,
}
]
}
ral_registers::register! {
#[doc = "CM IRQ0~31 wakeup mask"]
pub CM_IRQ_WAKEUP_MASK<u32> RW []
}
ral_registers::register! {
#[doc = "CM non-irq wakeup mask"]
pub CM_NON_IRQ_WAKEUP_MASK<u32> RW [
#[doc = "There are 256 interrupts and 1 event as a wakeup source for GPC. This field masks the 1 event wakeup source."]
EVENT_WAKEUP_MASK start(0) width(1) RW {}
#[doc = "1 means the debug_wakeup_request cannot wakeup CPU platform"]
DEBUG_WAKEUP_MASK start(1) width(1) RW {}
]
}
ral_registers::register! {
#[doc = "CM IRQ0~31 wakeup status"]
pub CM_IRQ_WAKEUP_STAT<u32> RO []
}
ral_registers::register! {
#[doc = "CM non-irq wakeup status"]
pub CM_NON_IRQ_WAKEUP_STAT<u32> RO [
#[doc = "Event wakeup status"]
EVENT_WAKEUP_STAT start(0) width(1) RO {}
#[doc = "Debug wakeup status"]
DEBUG_WAKEUP_STAT start(1) width(1) RO {}
]
}
ral_registers::register! {
#[doc(hidden)]
pub CM_SLEEP_WAKEUP_CTRL<u32> RW [
#[doc = "Step count, useage is depending on CNT_MODE."]
STEP_CNT start(0) width(16) RW {}
#[doc = "Count mode"]
CNT_MODE start(28) width(2) RW {
#[doc = "Counter disable mode: not use step counter, step completes once receiving step_done"]
DISABLE = 0,
#[doc = "Counter delay mode: delay after receiving step_done, delay cycle number is STEP_CNT"]
DELAY = 0x1,
#[doc = "Ignore step_done response, the counter starts to count once step begins, when counter reaches STEP_CNT value, the step completes"]
IGNORE_STEP_DONE = 0x2,
#[doc = "Time out mode, the counter starts to count once step begins, the step completes when either step_done received or counting to STEP_CNT value"]
TIMEOUT = 0x3,
}
#[doc = "Disable this step"]
DISABLE start(31) width(1) RW {}
]
}
use core::num::NonZeroU32;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_SLEEP_LPGC_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_SLEEP_PLL_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_SLEEP_ISO_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_SLEEP_RESET_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_SLEEP_POWER_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_SLEEP_SSAR_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_WAKEUP_LPGC_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_WAKEUP_PLL_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_WAKEUP_ISO_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_WAKEUP_RESET_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_WAKEUP_POWER_CTRL;
#[doc(inline)]
pub use CM_SLEEP_WAKEUP_CTRL as CM_WAKEUP_SSAR_CTRL;
ral_registers::register! {
#[doc = "CM Setpoint Control"]
pub CM_SP_CTRL<u32> RW [
#[doc = "Request a Setpoint transition when this bit is set"]
RUN_EN start(0) width(1) RW {}
#[doc = "The Setpoint that CPU want the system to transit to when CPU_SP_RUN_EN is set"]
RUN start(1) width(4) RW {}
#[doc = "1 means enable Setpoint transition on next CPU platform sleep sequence"]
SLEEP_EN start(5) width(1) RW {}
#[doc = "The Setpoint that CPU want the system to transit to on next CPU platform sleep sequence"]
SLEEP start(6) width(4) RW {}
#[doc = "1 means enable Setpoint transition on next CPU platform wakeup sequence"]
WAKEUP_EN start(10) width(1) RW {}
#[doc = "The Setpoint that CPU want the system to transit to on next CPU platform wakeup sequence"]
WAKEUP start(11) width(4) RW {}
#[doc = "Select the Setpoint transiton on the next CPU platform wakeup sequence"]
WAKEUP_SEL start(15) width(1) RW {}
]
}
ral_registers::register! {
#[doc = "CM Setpoint Status"]
pub CM_SP_STAT<u32> RO [
#[doc = "The current Setpoint of the system"]
CURRENT start(0) width(4) RO {}
#[doc = "The previous Setpoint of the system"]
PREVIOUS start(4) width(4) RO {}
#[doc = "The requested Setpoint from the CPU platform"]
TARGET start(8) width(4) RO {}
]
}
ral_registers::register! {
#[doc(hidden)]
pub CM_MAPPING<u32> RW [
#[doc = "Defines which Setpoint is allowed when CPU enters this mode. Each bit stands for 1 Setpoint, locked by LOCK_CFG field"]
CPU_MAPPING start(0) width(16) RW {}
]
}
#[doc(inline)]
pub use CM_MAPPING as CM_RUN_MODE_MAPPING;
#[doc(inline)]
pub use CM_MAPPING as CM_WAIT_MODE_MAPPING;
#[doc(inline)]
pub use CM_MAPPING as CM_STOP_MODE_MAPPING;
#[doc(inline)]
pub use CM_MAPPING as CM_SUSUPEND_MODE_MAPPING;
#[doc(inline)]
pub use CM_MAPPING as CM_SP_MAPPING;
ral_registers::register! {
#[doc = "CM standby control"]
pub CM_STBY_CTRL<u32> RW [
#[doc = "0x1: Request the chip into standby mode when CPU entering WAIT mode, locked by LOCK_CFG field."]
WAIT start(0) width(1) RW {}
#[doc = "0x1: Request the chip into standby mode when CPU entering STOP mode, locked by LOCK_CFG field."]
STOP start(1) width(1) RW {}
#[doc = "0x1: Request the chip into standby mode when CPU entering SUSPEND mode, locked by LOCK_CFG field."]
SUSPEND start(2) width(1) RW {}
#[doc = "Indicate the CPU is busy entering standby mode."]
SLEEP_BUSY start(16) width(1) RO {}
#[doc = "Indicate the CPU is busy exiting standby mode."]
WAKEUP_BUSY start(17) width(1) RO {}
]
}
/// The wrapped setpoint is invalid.
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct InvalidSetpointError(NonZeroU32);
// Amenable to niche optimizations in a Result, Option.
impl InvalidSetpointError {
/// Returns the invalid setpoint that you specified.
#[inline]
#[must_use]
pub const fn which(self) -> u32 {
self.0.get() - 1
}
/// Produce an error from a user-supplied invalid setpoint.
#[must_use]
#[inline]
fn from_raw(setpoint: u32) -> Self {
// Safety: any setpoint plus one is naturally
// non-zero. Saturating add prevents wrap around,
// ignoring the possibility that the user supplied
// a very invalid setpoint.
Self(unsafe { NonZeroU32::new_unchecked(setpoint.saturating_add(1)) })
}
}
/// Check if a setpoint is valid.
pub fn check_setpoint(setpoint: u32) -> Result<(), InvalidSetpointError> {
if setpoint < 16 {
Ok(())
} else {
Err(InvalidSetpointError::from_raw(setpoint))
}
}
impl core::fmt::Debug for InvalidSetpointError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("InvalidSetpointError")
.field(&self.which())
.finish()
}
}
impl core::fmt::Display for InvalidSetpointError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Invalid setpoint: {}", self.which())
}
}
/// Ask the GPC for a setpoint transition, blocking until
/// the request concludes.
///
/// Your setpoint must be less than 16. Otherwise, this call
/// returns an error.
pub fn request_setpoint_transition(
gpc: Instance,
setpoint: u32,
) -> Result<(), InvalidSetpointError> {
check_setpoint(setpoint)?;
ral_registers::modify_reg!(self, gpc, CM_SP_CTRL, RUN: setpoint as u32, RUN_EN: 1);
while ral_registers::read_reg!(self, gpc, CM_SP_CTRL, RUN_EN == 1) {}
Ok(())
}
#[cfg(test)]
mod tests {
#[test]
fn layout() {
assert_eq!(
core::mem::offset_of!(super::RegisterBlock, CM_SP_CTRL),
0x300
);
assert_eq!(
core::mem::offset_of!(super::RegisterBlock, CM_STBY_CTRL),
0x380
);
}
}
}
|