nrf52/
power.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Power management
6
7use 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
17// Note: only the nrf52833+ have 9 banks, but we create all of them to avoid
18// gating this code by a feature.
19const NUM_RAM_BANKS: usize = 9;
20
21register_structs! {
22    PowerRegisters {
23        (0x000 => _reserved0),
24        /// Enable Constant Latency mode
25        (0x078 => task_constlat: WriteOnly<u32, Task::Register>),
26        /// Enable Low-power mode (variable latency)
27        (0x07C => task_lowpwr: WriteOnly<u32, Task::Register>),
28        (0x080 => _reserved1),
29        /// Power failure warning
30        (0x108 => event_pofwarn: ReadWrite<u32, Event::Register>),
31        (0x10C => _reserved2),
32        /// CPU entered WFI/WFE sleep
33        (0x114 => event_sleepenter: ReadWrite<u32, Event::Register>),
34        /// CPU exited WFI/WFE sleep
35        (0x118 => event_sleepexit: ReadWrite<u32, Event::Register>),
36        /// Voltage supply detected on VBUS
37        (0x11C => event_usbdetected: ReadWrite<u32, Event::Register>),
38        /// Voltage supply removed from VBUS
39        (0x120 => event_usbremoved: ReadWrite<u32, Event::Register>),
40        /// USB 3.3V supply ready
41        (0x124 => event_usbpwrrdy: ReadWrite<u32, Event::Register>),
42        (0x128 => _reserved3),
43        /// Enable interrupt
44        (0x304 => intenset: ReadWrite<u32, Interrupt::Register>),
45        /// Disable interrupt
46        (0x308 => intenclr: ReadWrite<u32, Interrupt::Register>),
47        (0x30C => _reserved4),
48        /// Reset reason
49        (0x400 => resetreas: ReadWrite<u32, ResetReason::Register>),
50        (0x404 => _reserved5),
51        /// USB supply status
52        (0x438 => usbregstatus: ReadOnly<u32, UsbRegStatus::Register>),
53        (0x43C => _reserved6),
54        /// System OFF register
55        (0x500 => systemoff: WriteOnly<u32, Task::Register>),
56        (0x504 => _reserved7),
57        /// Power failure comparator configuration
58        (0x510 => pofcon: ReadWrite<u32, PowerFailure::Register>),
59        (0x514 => _reserved8),
60        /// General purpose retention register
61        (0x51C => gpregret: ReadWrite<u32, Byte::Register>),
62        /// General purpose retention register
63        (0x520 => gpregret2: ReadWrite<u32, Byte::Register>),
64        (0x524 => _reserved9),
65        /// Enable DC/DC converter for REG1 stage
66        (0x578 => dcdcen: ReadWrite<u32, Task::Register>),
67        (0x57C => _reserved10),
68        /// Enable DC/DC converter for REG0 stage
69        (0x580 => dcdcen0: ReadWrite<u32, Task::Register>),
70        (0x584 => _reserved11),
71        /// Main supply status
72        (0x640 => mainregstatus: ReadOnly<u32, MainSupply::Register>),
73        (0x644 => _reserved12),
74        /// RAMx power control registers
75        /// - Address: 0x900 - 0x980 (<= nRF52832)
76        /// - Address: 0x900 - 0x990 (>= nRF52833)
77        (0x900 => ram: [RamPowerRegisters; NUM_RAM_BANKS]),
78        (0x990 => @END),
79    },
80
81    RamPowerRegisters {
82        /// RAMn power control register.
83        /// The RAM size will vary depending on product variant, and the
84        /// RAMn register will only be present if the corresponding RAM AHB
85        /// slave is present on the device.
86        (0x000 => power: ReadWrite<u32, RamPower::Register>),
87        /// RAMn power control set register
88        (0x004 => powerset: WriteOnly<u32, RamPower::Register>),
89        /// RAMn power control clear register
90        (0x008 => powerclr: WriteOnly<u32, RamPower::Register>),
91        (0x00C => _reserved),
92        (0x010 => @END),
93    }
94}
95
96register_bitfields! [u32,
97    /// Start task
98    Task [
99        ENABLE OFFSET(0) NUMBITS(1)
100    ],
101
102    /// Read event
103    Event [
104        READY OFFSET(0) NUMBITS(1)
105    ],
106
107    /// Power management Interrupts
108    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
238/// The USB state machine needs to be notified of power events (USB detected, USB
239/// removed, USB power ready) in order to be initialized and shut down properly.
240///
241/// These events come from the power management registers of this module; that's
242/// this has a USB client to notify.
243pub struct Power<'a> {
244    registers: StaticRef<PowerRegisters>,
245    /// A client to which to notify USB plug-in/plug-out/power-ready events.
246    usb_client: OptionalCell<&'a dyn PowerClient>,
247}
248
249pub enum MainVoltage {
250    /// Normal voltage mode, when supply voltage is connected to both the VDD and
251    /// VDDH pins (so that VDD equals VDDH).
252    Normal = 0,
253    /// High voltage mode, when supply voltage is only connected to the VDDH pin,
254    /// and the VDD pin is not connected to any voltage supply.
255    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        // Clearing unused events
305        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        // disable all possible interrupts
328        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            // This case shouldn't happen as the register only holds 1 bit.
340            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    /// Return the contents of the GPREGRET (general purpose retention register)
353    /// register.
354    ///
355    /// This register is a "retention" register because it preserves eight bits
356    /// of its state across a soft reset.
357    ///
358    /// This is used to set a flag before a reset to instruct the bootloader to
359    /// stay in the bootloader mode.
360    pub fn get_gpregret(&self) -> u8 {
361        self.registers.gpregret.read(Byte::VALUE) as u8
362    }
363
364    /// Set the value of the GPREGRET (general purpose retention register)
365    /// register.
366    ///
367    /// This is used to set a flag before a reset to instruct the bootloader to
368    /// stay in the bootloader mode.
369    pub fn set_gpregret(&self, val: u8) {
370        self.registers.gpregret.write(Byte::VALUE.val(val as u32));
371    }
372}