1use kernel::utilities::cells::OptionalCell;
8use kernel::utilities::registers::interfaces::{Readable, Writeable};
9use kernel::utilities::registers::{
10 register_bitfields, register_structs, ReadOnly, ReadWrite, WriteOnly,
11};
12use kernel::utilities::StaticRef;
13
14const POWER_BASE: StaticRef<PowerRegisters> =
15 unsafe { StaticRef::new(0x40000000 as *const PowerRegisters) };
16
17const NUM_RAM_BANKS: usize = 9;
20
21register_structs! {
22 PowerRegisters {
23 (0x000 => _reserved0),
24 (0x078 => task_constlat: WriteOnly<u32, Task::Register>),
26 (0x07C => task_lowpwr: WriteOnly<u32, Task::Register>),
28 (0x080 => _reserved1),
29 (0x108 => event_pofwarn: ReadWrite<u32, Event::Register>),
31 (0x10C => _reserved2),
32 (0x114 => event_sleepenter: ReadWrite<u32, Event::Register>),
34 (0x118 => event_sleepexit: ReadWrite<u32, Event::Register>),
36 (0x11C => event_usbdetected: ReadWrite<u32, Event::Register>),
38 (0x120 => event_usbremoved: ReadWrite<u32, Event::Register>),
40 (0x124 => event_usbpwrrdy: ReadWrite<u32, Event::Register>),
42 (0x128 => _reserved3),
43 (0x304 => intenset: ReadWrite<u32, Interrupt::Register>),
45 (0x308 => intenclr: ReadWrite<u32, Interrupt::Register>),
47 (0x30C => _reserved4),
48 (0x400 => resetreas: ReadWrite<u32, ResetReason::Register>),
50 (0x404 => _reserved5),
51 (0x438 => usbregstatus: ReadOnly<u32, UsbRegStatus::Register>),
53 (0x43C => _reserved6),
54 (0x500 => systemoff: WriteOnly<u32, Task::Register>),
56 (0x504 => _reserved7),
57 (0x510 => pofcon: ReadWrite<u32, PowerFailure::Register>),
59 (0x514 => _reserved8),
60 (0x51C => gpregret: ReadWrite<u32, Byte::Register>),
62 (0x520 => gpregret2: ReadWrite<u32, Byte::Register>),
64 (0x524 => _reserved9),
65 (0x578 => dcdcen: ReadWrite<u32, Task::Register>),
67 (0x57C => _reserved10),
68 (0x580 => dcdcen0: ReadWrite<u32, Task::Register>),
70 (0x584 => _reserved11),
71 (0x640 => mainregstatus: ReadOnly<u32, MainSupply::Register>),
73 (0x644 => _reserved12),
74 (0x900 => ram: [RamPowerRegisters; NUM_RAM_BANKS]),
78 (0x990 => @END),
79 },
80
81 RamPowerRegisters {
82 (0x000 => power: ReadWrite<u32, RamPower::Register>),
87 (0x004 => powerset: WriteOnly<u32, RamPower::Register>),
89 (0x008 => powerclr: WriteOnly<u32, RamPower::Register>),
91 (0x00C => _reserved),
92 (0x010 => @END),
93 }
94}
95
96register_bitfields! [u32,
97 Task [
99 ENABLE OFFSET(0) NUMBITS(1)
100 ],
101
102 Event [
104 READY OFFSET(0) NUMBITS(1)
105 ],
106
107 Interrupt [
109 POFWARN OFFSET(2) NUMBITS(1),
110 SLEEPENTER OFFSET(5) NUMBITS(1),
111 SLEEPEXIT OFFSET(6) NUMBITS(1),
112 USBDETECTED OFFSET(7) NUMBITS(1),
113 USBREMOVED OFFSET(8) NUMBITS(1),
114 USBPWRRDY OFFSET(9) NUMBITS(1)
115 ],
116
117 ResetReason [
118 RESETPIN OFFSET(0) NUMBITS(1) [
119 Detected = 1
120 ],
121 DOG OFFSET(1) NUMBITS(1) [
122 Detected = 1
123 ],
124 SREQ OFFSET(2) NUMBITS(1) [
125 Detected = 1
126 ],
127 LOCKUP OFFSET(3) NUMBITS(1) [
128 Detected = 1
129 ],
130 OFF OFFSET(16) NUMBITS(1) [
131 Detected = 1
132 ],
133 LPCOMP OFFSET(17) NUMBITS(1) [
134 Detected = 1
135 ],
136 DIF OFFSET(18) NUMBITS(1) [
137 Detected = 1
138 ],
139 NFC OFFSET(19) NUMBITS(1) [
140 Detected = 1
141 ],
142 VBUS OFFSET(20) NUMBITS(1) [
143 Detected = 1
144 ]
145 ],
146
147 PowerFailure [
148 POF OFFSET(0) NUMBITS(1) [
149 Disabled = 0,
150 Enabled = 1
151 ],
152 THRESHOLD OFFSET(1) NUMBITS(4) [
153 V17 = 4,
154 V18 = 5,
155 V19 = 6,
156 V20 = 7,
157 V21 = 8,
158 V22 = 9,
159 V23 = 10,
160 V24 = 11,
161 V25 = 12,
162 V26 = 13,
163 V27 = 14,
164 V28 = 15
165 ],
166 THRESHOLDVDDH OFFSET(8) NUMBITS(4) [
167 V27 = 0,
168 V28 = 1,
169 V29 = 2,
170 V30 = 3,
171 V31 = 4,
172 V32 = 5,
173 V33 = 6,
174 V34 = 7,
175 V35 = 8,
176 V36 = 9,
177 V37 = 10,
178 V38 = 11,
179 V39 = 12,
180 V40 = 13,
181 V41 = 14,
182 V42 = 15
183 ]
184 ],
185
186 Byte [
187 VALUE OFFSET(0) NUMBITS(8)
188 ],
189
190 UsbRegStatus [
191 VBUSDETECT OFFSET(0) NUMBITS(1),
192 OUTPUTRDY OFFSET(1) NUMBITS(1)
193 ],
194
195 MainSupply [
196 MAINREGSTATUS OFFSET(0) NUMBITS(1) [
197 Normal = 0,
198 High = 1
199 ]
200 ],
201
202 RamPower [
203 S0POWER OFFSET(0) NUMBITS(1),
204 S1POWER OFFSET(1) NUMBITS(1),
205 S2POWER OFFSET(2) NUMBITS(1),
206 S3POWER OFFSET(3) NUMBITS(1),
207 S4POWER OFFSET(4) NUMBITS(1),
208 S5POWER OFFSET(5) NUMBITS(1),
209 S6POWER OFFSET(6) NUMBITS(1),
210 S7POWER OFFSET(7) NUMBITS(1),
211 S8POWER OFFSET(8) NUMBITS(1),
212 S9POWER OFFSET(9) NUMBITS(1),
213 S10POWER OFFSET(10) NUMBITS(1),
214 S11POWER OFFSET(11) NUMBITS(1),
215 S12POWER OFFSET(12) NUMBITS(1),
216 S13POWER OFFSET(13) NUMBITS(1),
217 S14POWER OFFSET(14) NUMBITS(1),
218 S15POWER OFFSET(15) NUMBITS(1),
219 S0RETENTION OFFSET(16) NUMBITS(1),
220 S1RETENTION OFFSET(17) NUMBITS(1),
221 S2RETENTION OFFSET(18) NUMBITS(1),
222 S3RETENTION OFFSET(19) NUMBITS(1),
223 S4RETENTION OFFSET(20) NUMBITS(1),
224 S5RETENTION OFFSET(21) NUMBITS(1),
225 S6RETENTION OFFSET(22) NUMBITS(1),
226 S7RETENTION OFFSET(23) NUMBITS(1),
227 S8RETENTION OFFSET(24) NUMBITS(1),
228 S9RETENTION OFFSET(25) NUMBITS(1),
229 S10RETENTION OFFSET(26) NUMBITS(1),
230 S11RETENTION OFFSET(27) NUMBITS(1),
231 S12RETENTION OFFSET(28) NUMBITS(1),
232 S13RETENTION OFFSET(29) NUMBITS(1),
233 S14RETENTION OFFSET(30) NUMBITS(1),
234 S15RETENTION OFFSET(31) NUMBITS(1)
235 ]
236];
237
238pub struct Power<'a> {
244 registers: StaticRef<PowerRegisters>,
245 usb_client: OptionalCell<&'a dyn PowerClient>,
247}
248
249pub enum MainVoltage {
250 Normal = 0,
253 High = 1,
256}
257
258pub enum PowerEvent {
259 PowerFailure,
260 EnterSleep,
261 ExitSleep,
262 UsbPluggedIn,
263 UsbPluggedOut,
264 UsbPowerReady,
265}
266
267pub trait PowerClient {
268 fn handle_power_event(&self, event: PowerEvent);
269}
270
271impl<'a> Power<'a> {
272 pub const fn new() -> Self {
273 Power {
274 registers: POWER_BASE,
275 usb_client: OptionalCell::empty(),
276 }
277 }
278
279 pub fn set_usb_client(&self, client: &'a dyn PowerClient) {
280 self.usb_client.set(client);
281 }
282
283 pub fn handle_interrupt(&self) {
284 self.disable_all_interrupts();
285
286 if self.registers.event_usbdetected.is_set(Event::READY) {
287 self.registers.event_usbdetected.write(Event::READY::CLEAR);
288 self.usb_client
289 .map(|client| client.handle_power_event(PowerEvent::UsbPluggedIn));
290 }
291
292 if self.registers.event_usbremoved.is_set(Event::READY) {
293 self.registers.event_usbremoved.write(Event::READY::CLEAR);
294 self.usb_client
295 .map(|client| client.handle_power_event(PowerEvent::UsbPluggedOut));
296 }
297
298 if self.registers.event_usbpwrrdy.is_set(Event::READY) {
299 self.registers.event_usbpwrrdy.write(Event::READY::CLEAR);
300 self.usb_client
301 .map(|client| client.handle_power_event(PowerEvent::UsbPowerReady));
302 }
303
304 self.registers.event_pofwarn.write(Event::READY::CLEAR);
306 self.registers.event_sleepenter.write(Event::READY::CLEAR);
307 self.registers.event_sleepexit.write(Event::READY::CLEAR);
308
309 self.enable_interrupts();
310 }
311
312 pub fn enable_interrupts(&self) {
313 self.registers.intenset.write(
314 Interrupt::USBDETECTED::SET + Interrupt::USBREMOVED::SET + Interrupt::USBPWRRDY::SET,
315 );
316 }
317
318 pub fn enable_interrupt(&self, intr: u32) {
319 self.registers.intenset.set(intr);
320 }
321
322 pub fn clear_interrupt(&self, intr: u32) {
323 self.registers.intenclr.set(intr);
324 }
325
326 pub fn disable_all_interrupts(&self) {
327 self.registers.intenclr.set(0xffffffff);
329 }
330
331 pub fn get_main_supply_status(&self) -> MainVoltage {
332 match self
333 .registers
334 .mainregstatus
335 .read_as_enum(MainSupply::MAINREGSTATUS)
336 {
337 Some(MainSupply::MAINREGSTATUS::Value::Normal) => MainVoltage::Normal,
338 Some(MainSupply::MAINREGSTATUS::Value::High) => MainVoltage::High,
339 None => unreachable!(),
341 }
342 }
343
344 pub fn is_vbus_present(&self) -> bool {
345 self.registers.usbregstatus.is_set(UsbRegStatus::VBUSDETECT)
346 }
347
348 pub fn is_usb_power_ready(&self) -> bool {
349 self.registers.usbregstatus.is_set(UsbRegStatus::OUTPUTRDY)
350 }
351
352 pub fn get_gpregret(&self) -> u8 {
361 self.registers.gpregret.read(Byte::VALUE) as u8
362 }
363
364 pub fn set_gpregret(&self, val: u8) {
370 self.registers.gpregret.write(Byte::VALUE.val(val as u32));
371 }
372}