rp2040/
resets.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
5use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
6use kernel::utilities::registers::{register_bitfields, register_structs, FieldValue, ReadWrite};
7use kernel::utilities::StaticRef;
8
9register_structs! {
10    ResetsRegisters {
11        /// Reset control. If a bit is set it means the peripheral is in reset. 0 means the
12        (0x000 => reset: ReadWrite<u32, RESET::Register>),
13        /// Watchdog select. If a bit is set then the watchdog will reset this peripheral wh
14        (0x004 => wdsel: ReadWrite<u32, WDSEL::Register>),
15        /// Reset done. If a bit is set then a reset done signal has been returned by the pe
16        (0x008 => reset_done: ReadWrite<u32, RESET_DONE::Register>),
17        (0x00C => @END),
18    }
19}
20register_bitfields![u32,
21    RESET [
22
23        usbctrl OFFSET(24) NUMBITS(1) [],
24
25        uart1 OFFSET(23) NUMBITS(1) [],
26
27        uart0 OFFSET(22) NUMBITS(1) [],
28
29        timer OFFSET(21) NUMBITS(1) [],
30
31        tbman OFFSET(20) NUMBITS(1) [],
32
33        sysinfo OFFSET(19) NUMBITS(1) [],
34
35        syscfg OFFSET(18) NUMBITS(1) [],
36
37        spi1 OFFSET(17) NUMBITS(1) [],
38
39        spi0 OFFSET(16) NUMBITS(1) [],
40
41        rtc OFFSET(15) NUMBITS(1) [],
42
43        pwm OFFSET(14) NUMBITS(1) [],
44
45        pll_usb OFFSET(13) NUMBITS(1) [],
46
47        pll_sys OFFSET(12) NUMBITS(1) [],
48
49        pio1 OFFSET(11) NUMBITS(1) [],
50
51        pio0 OFFSET(10) NUMBITS(1) [],
52
53        pads_qspi OFFSET(9) NUMBITS(1) [],
54
55        pads_bank0 OFFSET(8) NUMBITS(1) [],
56
57        jtag OFFSET(7) NUMBITS(1) [],
58
59        io_qspi OFFSET(6) NUMBITS(1) [],
60
61        io_bank0 OFFSET(5) NUMBITS(1) [],
62
63        i2c1 OFFSET(4) NUMBITS(1) [],
64
65        i2c0 OFFSET(3) NUMBITS(1) [],
66
67        dma OFFSET(2) NUMBITS(1) [],
68
69        busctrl OFFSET(1) NUMBITS(1) [],
70
71        adc OFFSET(0) NUMBITS(1) []
72    ],
73    WDSEL [
74
75        usbctrl OFFSET(24) NUMBITS(1) [],
76
77        uart1 OFFSET(23) NUMBITS(1) [],
78
79        uart0 OFFSET(22) NUMBITS(1) [],
80
81        timer OFFSET(21) NUMBITS(1) [],
82
83        tbman OFFSET(20) NUMBITS(1) [],
84
85        sysinfo OFFSET(19) NUMBITS(1) [],
86
87        syscfg OFFSET(18) NUMBITS(1) [],
88
89        spi1 OFFSET(17) NUMBITS(1) [],
90
91        spi0 OFFSET(16) NUMBITS(1) [],
92
93        rtc OFFSET(15) NUMBITS(1) [],
94
95        pwm OFFSET(14) NUMBITS(1) [],
96
97        pll_usb OFFSET(13) NUMBITS(1) [],
98
99        pll_sys OFFSET(12) NUMBITS(1) [],
100
101        pio1 OFFSET(11) NUMBITS(1) [],
102
103        pio0 OFFSET(10) NUMBITS(1) [],
104
105        pads_qspi OFFSET(9) NUMBITS(1) [],
106
107        pads_bank0 OFFSET(8) NUMBITS(1) [],
108
109        jtag OFFSET(7) NUMBITS(1) [],
110
111        io_qspi OFFSET(6) NUMBITS(1) [],
112
113        io_bank0 OFFSET(5) NUMBITS(1) [],
114
115        i2c1 OFFSET(4) NUMBITS(1) [],
116
117        i2c0 OFFSET(3) NUMBITS(1) [],
118
119        dma OFFSET(2) NUMBITS(1) [],
120
121        busctrl OFFSET(1) NUMBITS(1) [],
122
123        adc OFFSET(0) NUMBITS(1) []
124    ],
125    RESET_DONE [
126
127        usbctrl OFFSET(24) NUMBITS(1) [],
128
129        uart1 OFFSET(23) NUMBITS(1) [],
130
131        uart0 OFFSET(22) NUMBITS(1) [],
132
133        timer OFFSET(21) NUMBITS(1) [],
134
135        tbman OFFSET(20) NUMBITS(1) [],
136
137        sysinfo OFFSET(19) NUMBITS(1) [],
138
139        syscfg OFFSET(18) NUMBITS(1) [],
140
141        spi1 OFFSET(17) NUMBITS(1) [],
142
143        spi0 OFFSET(16) NUMBITS(1) [],
144
145        rtc OFFSET(15) NUMBITS(1) [],
146
147        pwm OFFSET(14) NUMBITS(1) [],
148
149        pll_usb OFFSET(13) NUMBITS(1) [],
150
151        pll_sys OFFSET(12) NUMBITS(1) [],
152
153        pio1 OFFSET(11) NUMBITS(1) [],
154
155        pio0 OFFSET(10) NUMBITS(1) [],
156
157        pads_qspi OFFSET(9) NUMBITS(1) [],
158
159        pads_bank0 OFFSET(8) NUMBITS(1) [],
160
161        jtag OFFSET(7) NUMBITS(1) [],
162
163        io_qspi OFFSET(6) NUMBITS(1) [],
164
165        io_bank0 OFFSET(5) NUMBITS(1) [],
166
167        i2c1 OFFSET(4) NUMBITS(1) [],
168
169        i2c0 OFFSET(3) NUMBITS(1) [],
170
171        dma OFFSET(2) NUMBITS(1) [],
172
173        busctrl OFFSET(1) NUMBITS(1) [],
174
175        adc OFFSET(0) NUMBITS(1) []
176    ]
177];
178const RESETS_BASE: StaticRef<ResetsRegisters> =
179    unsafe { StaticRef::new(0x4000C000 as *const ResetsRegisters) };
180
181pub enum Peripheral {
182    Adc,
183    BusController,
184    Dma,
185    I2c0,
186    I2c1,
187    IOBank0,
188    IOQSpi,
189    Jtag,
190    PadsBank0,
191    PadsQSpi,
192    Pio0,
193    Pio1,
194    PllSys,
195    PllUsb,
196    Pwm,
197    Rtc,
198    Spi0,
199    Spi1,
200    Syscfg,
201    SysInfo,
202    TBMan,
203    Timer,
204    Uart0,
205    Uart1,
206    UsbCtrl,
207}
208
209impl Peripheral {
210    fn get_reset_field_set(&self) -> FieldValue<u32, RESET::Register> {
211        match self {
212            Peripheral::Adc => RESET::adc::SET,
213            Peripheral::BusController => RESET::busctrl::SET,
214            Peripheral::Dma => RESET::dma::SET,
215            Peripheral::I2c0 => RESET::i2c0::SET,
216            Peripheral::I2c1 => RESET::i2c1::SET,
217            Peripheral::IOBank0 => RESET::io_bank0::SET,
218            Peripheral::IOQSpi => RESET::io_qspi::SET,
219            Peripheral::Jtag => RESET::jtag::SET,
220            Peripheral::PadsBank0 => RESET::pads_bank0::SET,
221            Peripheral::PadsQSpi => RESET::pads_qspi::SET,
222            Peripheral::Pio0 => RESET::pio0::SET,
223            Peripheral::Pio1 => RESET::pio1::SET,
224            Peripheral::PllSys => RESET::pll_sys::SET,
225            Peripheral::PllUsb => RESET::pll_usb::SET,
226            Peripheral::Pwm => RESET::pwm::SET,
227            Peripheral::Rtc => RESET::rtc::SET,
228            Peripheral::Spi0 => RESET::spi0::SET,
229            Peripheral::Spi1 => RESET::spi1::SET,
230            Peripheral::Syscfg => RESET::syscfg::SET,
231            Peripheral::SysInfo => RESET::sysinfo::SET,
232            Peripheral::TBMan => RESET::tbman::SET,
233            Peripheral::Timer => RESET::timer::SET,
234            Peripheral::Uart0 => RESET::uart0::SET,
235            Peripheral::Uart1 => RESET::uart1::SET,
236            Peripheral::UsbCtrl => RESET::usbctrl::SET,
237        }
238    }
239
240    fn get_reset_field_clear(&self) -> FieldValue<u32, RESET::Register> {
241        match self {
242            Peripheral::Adc => RESET::adc::CLEAR,
243            Peripheral::BusController => RESET::busctrl::CLEAR,
244            Peripheral::Dma => RESET::dma::CLEAR,
245            Peripheral::I2c0 => RESET::i2c0::CLEAR,
246            Peripheral::I2c1 => RESET::i2c1::CLEAR,
247            Peripheral::IOBank0 => RESET::io_bank0::CLEAR,
248            Peripheral::IOQSpi => RESET::io_qspi::CLEAR,
249            Peripheral::Jtag => RESET::jtag::CLEAR,
250            Peripheral::PadsBank0 => RESET::pads_bank0::CLEAR,
251            Peripheral::PadsQSpi => RESET::pads_qspi::CLEAR,
252            Peripheral::Pio0 => RESET::pio0::CLEAR,
253            Peripheral::Pio1 => RESET::pio1::CLEAR,
254            Peripheral::PllSys => RESET::pll_sys::CLEAR,
255            Peripheral::PllUsb => RESET::pll_usb::CLEAR,
256            Peripheral::Pwm => RESET::pwm::CLEAR,
257            Peripheral::Rtc => RESET::rtc::CLEAR,
258            Peripheral::Spi0 => RESET::spi0::CLEAR,
259            Peripheral::Spi1 => RESET::spi1::CLEAR,
260            Peripheral::Syscfg => RESET::syscfg::CLEAR,
261            Peripheral::SysInfo => RESET::sysinfo::CLEAR,
262            Peripheral::TBMan => RESET::tbman::CLEAR,
263            Peripheral::Timer => RESET::timer::CLEAR,
264            Peripheral::Uart0 => RESET::uart0::CLEAR,
265            Peripheral::Uart1 => RESET::uart1::CLEAR,
266            Peripheral::UsbCtrl => RESET::usbctrl::CLEAR,
267        }
268    }
269
270    fn get_reset_done_field_set(&self) -> FieldValue<u32, RESET_DONE::Register> {
271        match self {
272            Peripheral::Adc => RESET_DONE::adc::SET,
273            Peripheral::BusController => RESET_DONE::busctrl::SET,
274            Peripheral::Dma => RESET_DONE::dma::SET,
275            Peripheral::I2c0 => RESET_DONE::i2c0::SET,
276            Peripheral::I2c1 => RESET_DONE::i2c1::SET,
277            Peripheral::IOBank0 => RESET_DONE::io_bank0::SET,
278            Peripheral::IOQSpi => RESET_DONE::io_qspi::SET,
279            Peripheral::Jtag => RESET_DONE::jtag::SET,
280            Peripheral::PadsBank0 => RESET_DONE::pads_bank0::SET,
281            Peripheral::PadsQSpi => RESET_DONE::pads_qspi::SET,
282            Peripheral::Pio0 => RESET_DONE::pio0::SET,
283            Peripheral::Pio1 => RESET_DONE::pio1::SET,
284            Peripheral::PllSys => RESET_DONE::pll_sys::SET,
285            Peripheral::PllUsb => RESET_DONE::pll_usb::SET,
286            Peripheral::Pwm => RESET_DONE::pwm::SET,
287            Peripheral::Rtc => RESET_DONE::rtc::SET,
288            Peripheral::Spi0 => RESET_DONE::spi0::SET,
289            Peripheral::Spi1 => RESET_DONE::spi1::SET,
290            Peripheral::Syscfg => RESET_DONE::syscfg::SET,
291            Peripheral::SysInfo => RESET_DONE::sysinfo::SET,
292            Peripheral::TBMan => RESET_DONE::tbman::SET,
293            Peripheral::Timer => RESET_DONE::timer::SET,
294            Peripheral::Uart0 => RESET_DONE::uart0::SET,
295            Peripheral::Uart1 => RESET_DONE::uart1::SET,
296            Peripheral::UsbCtrl => RESET_DONE::usbctrl::SET,
297        }
298    }
299}
300
301pub struct Resets {
302    registers: StaticRef<ResetsRegisters>,
303}
304
305impl Resets {
306    pub const fn new() -> Resets {
307        Resets {
308            registers: RESETS_BASE,
309        }
310    }
311
312    pub fn reset(&self, peripherals: &'static [Peripheral]) {
313        if peripherals.len() > 0 {
314            let mut value: FieldValue<u32, RESET::Register> = peripherals[0].get_reset_field_set();
315            for peripheral in peripherals {
316                value += peripheral.get_reset_field_set();
317            }
318            self.registers.reset.modify(value);
319        }
320    }
321
322    pub fn unreset(&self, peripherals: &'static [Peripheral], wait_for: bool) {
323        if peripherals.len() > 0 {
324            let mut value: FieldValue<u32, RESET::Register> =
325                peripherals[0].get_reset_field_clear();
326            for peripheral in peripherals {
327                value += peripheral.get_reset_field_clear();
328            }
329            self.registers.reset.modify(value);
330
331            if wait_for {
332                let mut value_done: FieldValue<u32, RESET_DONE::Register> =
333                    peripherals[0].get_reset_done_field_set();
334                for peripheral in peripherals {
335                    value_done += peripheral.get_reset_done_field_set();
336                }
337                while !self.registers.reset_done.matches_all(value_done) {}
338            }
339        }
340    }
341
342    pub fn reset_all_except(&self, peripherals: &'static [Peripheral]) {
343        let mut value = 0xFFFFFF;
344        for peripheral in peripherals {
345            value ^= peripheral.get_reset_field_set().value;
346        }
347        self.registers.reset.set(value);
348    }
349
350    pub fn unreset_all_except(&self, peripherals: &'static [Peripheral], wait_for: bool) {
351        let mut value = 0;
352        for peripheral in peripherals {
353            value |= peripheral.get_reset_field_set().value;
354        }
355
356        self.registers.reset.set(value);
357
358        if wait_for {
359            value = !value & 0xFFFFF;
360            while (self.registers.reset_done.get() & value) != value {}
361        }
362    }
363
364    pub fn watchdog_reset_all_except(&self, peripherals: &'static [Peripheral]) {
365        let mut value = 0xFFFFFF;
366        for peripheral in peripherals {
367            value ^= peripheral.get_reset_field_set().value;
368        }
369        self.registers.wdsel.set(value);
370    }
371}