rp2040/
gpio.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//! GPIO, RP2040
6//!
7//! ### Author
8//! * Ioana Culic <ioana.culic@wyliodrin.com>
9
10use enum_primitive::cast::FromPrimitive;
11use enum_primitive::enum_from_primitive;
12use kernel::hil;
13use kernel::utilities::cells::OptionalCell;
14use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
15use kernel::utilities::registers::{register_bitfields, register_structs, ReadOnly, ReadWrite};
16use kernel::utilities::StaticRef;
17
18use crate::chip::Processor;
19#[repr(C)]
20struct GpioPin {
21    status: ReadOnly<u32, GPIOx_STATUS::Register>,
22    ctrl: ReadWrite<u32, GPIOx_CTRL::Register>,
23}
24#[repr(C)]
25struct GpioProc {
26    enable: [ReadWrite<u32, GPIO_INTxx::Register>; 4],
27    force: [ReadWrite<u32, GPIO_INTxx::Register>; 4],
28    status: [ReadWrite<u32, GPIO_INTxx::Register>; 4],
29}
30
31register_structs! {
32    /// GPIO Registers.
33    GpioRegisters {
34        (0x000 => pin: [GpioPin; 30]),
35
36        /// Raw interrupts
37        (0x0f0 => intr: [ReadWrite<u32, GPIO_INTxx::Register>; 4]),
38
39        /// Interrupts for procs
40        (0x100 => interrupt_proc: [GpioProc; 2]),
41
42        /// Wake
43        (0x160 => wake: GpioProc),
44
45        /// End
46        (0x190 => @END),
47    },
48    /// User Bank Pad Control Registers
49    GpioPadRegisters {
50        /// Voltage select
51        (0x00 => voltage: ReadWrite<u32, VOLTAGE_SELECT::Register>),
52
53        /// Pads control
54        (0x04 => gpio_pad: [ReadWrite<u32, GPIO_PAD::Register>; 32]),
55
56        /// End
57        (0x84 => @END),
58    },
59    /// SIO Control Registers
60    SIORegisters {
61        /// Not used
62        (0x000 => cpuid: ReadOnly<u32, CPUID::Register>),
63
64        /// Input value for GPIO pins
65        (0x004 => gpio_in: ReadOnly<u32, GPIO_IN::Register>),
66
67        /// Not used
68        (0x008 => _reserved1),
69
70        /// GPIO output value
71        (0x010 => gpio_out: ReadWrite<u32, GPIO_OUT::Register>),
72
73        /// GPIO output value set
74        (0x014 => gpio_out_set: ReadWrite<u32, GPIO_OUT_SET::Register>),
75
76        /// GPIO output value clear
77        (0x018 => gpio_out_clr: ReadWrite<u32, GPIO_OUT_CLR::Register>),
78
79        /// GPIO output value XOR
80        (0x01c => gpio_out_xor: ReadWrite<u32, GPIO_OUT_XOR::Register>),
81
82        /// GPIO output enable
83        (0x020 => gpio_oe: ReadWrite<u32, GPIO_OE::Register>),
84
85        /// GPIO output enable set
86        (0x024 => gpio_oe_set: ReadWrite<u32, GPIO_OE_SET::Register>),
87
88        /// GPIO output enable clear
89        (0x028 => gpio_oe_clr: ReadWrite<u32, GPIO_OE_CLR::Register>),
90
91        /// Not used
92        (0x02C => _reserved2),
93
94        /// FIFO status
95        (0x050 => fifo_st: ReadWrite<u32, FIFO_ST::Register>),
96
97        /// FIFO write
98        (0x054 => fifo_wr: ReadWrite<u32, FIFO_WR::Register>),
99
100        /// FIFO read
101        (0x058 => fifo_rd: ReadOnly<u32, FIFO_RD::Register>),
102
103        /// End
104        (0x05c => @END),
105    }
106}
107
108register_bitfields![u32,
109    GPIOx_STATUS [
110        /// interrupt to processors, after override is applied
111        IRQTOPROC OFFSET(26) NUMBITS(1) [],
112        /// interrupt from pad before override is applied
113        IRQFROMPAD OFFSET(24) NUMBITS(1) [],
114        /// input signal to peripheral, after override is applied
115        INTOPERI OFFSET(19) NUMBITS(1) [],
116        /// input signal from pad, before override is applied
117        INFROMPAD OFFSET(17) NUMBITS(1) [],
118        /// output enable to pad after register override is applied
119        OETOPAD OFFSET(13) NUMBITS(1) [],
120        /// output enable from selected peripheral, before registeroverride is applied
121        OEFROMPERI OFFSET(12) NUMBITS(1) [],
122        /// output signal to pad after register override is applied
123        OUTTOPAD OFFSET(9) NUMBITS(1) [],
124        /// output signal from selected peripheral, before registeroverride is applied
125        OUTFROMPERI OFFSET(8) NUMBITS(1) []
126    ],
127    GPIOx_CTRL [
128        /// interrupt override?
129        IRQOVER OFFSET(28) NUMBITS(2) [
130            NoInvert = 0,
131            Invert = 1,
132            DriveLow = 2,
133            DriveHigh = 3
134        ],
135        /// input override
136        INOVER OFFSET(16) NUMBITS(2) [
137            NoInvert = 0,
138            Invert = 1,
139            DriveLow = 2,
140            DriveHigh = 3
141        ],
142        /// output enable override
143        OEOVER OFFSET(12) NUMBITS(2) [
144            EnableSignal = 0,
145            EnableInverseSignal = 1,
146            Disable = 2,
147            Enable = 3
148        ],
149        /// output override
150        OUTOVER OFFSET(8) NUMBITS(2) [
151            Signal = 0,
152            InverseSignal = 1,
153            Low = 2,
154            High = 3
155        ],
156        /// Function select
157        FUNCSEL OFFSET(0) NUMBITS(5) [
158            GPIO_FUNC_XIP = 0,
159            GPIO_FUNC_SPI = 1,
160            GPIO_FUNC_UART = 2,
161            GPIO_FUNC_I2C = 3,
162            GPIO_FUNC_PWM = 4,
163            GPIO_FUNC_SIO = 5,
164            GPIO_FUNC_PIO0 = 6,
165            GPIO_FUNC_PIO1 = 7,
166            GPIO_FUNC_GPCK = 8,
167            GPIO_FUNC_USB = 9,
168            GPIO_FUNC_NULL = 0x1f
169        ]
170    ],
171    GPIO_INTxx [
172        GPIO7_EDGE_HIGH OFFSET(31) NUMBITS(1) [],
173        GPIO7_EDGE_LOW OFFSET(30) NUMBITS(1) [],
174        GPIO7_LEVEL_HIGH OFFSET(29) NUMBITS(1) [],
175        GPIO7_LEVEL_LOW OFFSET(28) NUMBITS(1) [],
176
177        GPIO6_EDGE_HIGH OFFSET(27) NUMBITS(1) [],
178        GPIO6_EDGE_LOW OFFSET(26) NUMBITS(1) [],
179        GPIO6_LEVEL_HIGH OFFSET(25) NUMBITS(1) [],
180        GPIO6_LEVEL_LOW OFFSET(24) NUMBITS(1) [],
181
182        GPIO5_EDGE_HIGH OFFSET(23) NUMBITS(1) [],
183        GPIO5_EDGE_LOW OFFSET(22) NUMBITS(1) [],
184        GPIO5_LEVEL_HIGH OFFSET(21) NUMBITS(1) [],
185        GPIO5_LEVEL_LOW OFFSET(20) NUMBITS(1) [],
186
187        GPIO4_EDGE_HIGH OFFSET(19) NUMBITS(1) [],
188        GPIO4_EDGE_LOW OFFSET(18) NUMBITS(1) [],
189        GPIO4_LEVEL_HIGH OFFSET(17) NUMBITS(1) [],
190        GPIO4_LEVEL_LOW OFFSET(16) NUMBITS(1) [],
191
192        GPIO3_EDGE_HIGH OFFSET(15) NUMBITS(1) [],
193        GPIO3_EDGE_LOW OFFSET(14) NUMBITS(1) [],
194        GPIO3_LEVEL_HIGH OFFSET(13) NUMBITS(1) [],
195        GPIO3_LEVEL_LOW OFFSET(12) NUMBITS(1) [],
196
197        GPIO2_EDGE_HIGH OFFSET(11) NUMBITS(1) [],
198        GPIO2_EDGE_LOW OFFSET(10) NUMBITS(1) [],
199        GPIO2_LEVEL_HIGH OFFSET(9) NUMBITS(1) [],
200        GPIO2_LEVEL_LOW OFFSET(8) NUMBITS(1) [],
201
202        GPIO1_EDGE_HIGH OFFSET(7) NUMBITS(1) [],
203        GPIO1_EDGE_LOW OFFSET(6) NUMBITS(1) [],
204        GPIO1_LEVEL_HIGH OFFSET(5) NUMBITS(1) [],
205        GPIO1_LEVEL_LOW OFFSET(4) NUMBITS(1) [],
206
207        GPIO0_EDGE_HIGH OFFSET(3) NUMBITS(1) [],
208        GPIO0_EDGE_LOW OFFSET(2) NUMBITS(1) [],
209        GPIO0_LEVEL_HIGH OFFSET(1) NUMBITS(1) [],
210        GPIO0_LEVEL_LOW OFFSET(0) NUMBITS(1) []
211    ],
212    VOLTAGE_SELECT[
213        VOLTAGE OFFSET(0) NUMBITS(1) [
214            Set3V3 = 0,
215            Set1V8 = 1
216        ]
217    ],
218    GPIO_PAD [
219        OD OFFSET(7) NUMBITS(1) [],
220        IE OFFSET(6) NUMBITS(1) [],
221        DRIVE OFFSET(4) NUMBITS(2) [],
222        PUE OFFSET(3) NUMBITS(1) [],
223        PDE OFFSET(2) NUMBITS(1) [],
224        SCHMITT OFFSET(1) NUMBITS(1) [],
225        SLEWFAST OFFSET(0) NUMBITS(1) []
226    ],
227    GPIO_IN [
228        ///Input value for GPIO0..29
229        IN OFFSET(0) NUMBITS(30) []
230    ],
231    GPIO_OUT [
232        ///Set output level (1/0 → high/low) for GPIO0...29.
233        OUT OFFSET(0) NUMBITS(30) []
234    ],
235    GPIO_OUT_SET [
236        ///Perform an atomic bit-set on GPIO_OUT
237        OUT OFFSET(0) NUMBITS(30) []
238    ],
239    GPIO_OUT_CLR [
240        ///Perform an atomic bit-clear on GPIO_OUT
241        OUT OFFSET(0) NUMBITS(30) []
242    ],
243    GPIO_OUT_XOR [
244        ///Perform an atomic bitwise XOR on GPIO_OUT
245        OUT OFFSET(0) NUMBITS(30) []
246    ],
247    GPIO_OE [
248        ///Set output enable (1/0 → output/input) for GPIO0...29
249        OE OFFSET(0) NUMBITS(30) []
250    ],
251    GPIO_OE_SET [
252        ///Perform an atomic bit-set on GPIO_OE
253        OE OFFSET(0) NUMBITS(30) []
254    ],
255    GPIO_OE_CLR [
256        ///Perform an atomic bit-clear on GPIO_OE
257        OE OFFSET(0) NUMBITS(30) []
258    ],
259    CPUID [
260        VALUE OFFSET(0) NUMBITS (32)
261    ],
262    FIFO_ST [
263        /// FIFO read when empy
264        ROE OFFSET(3) NUMBITS(1) [],
265        /// FIFO written when full
266        WOF OFFSET(2) NUMBITS(1) [],
267        /// FIFO not full
268        RDY OFFSET(1) NUMBITS(1) [],
269        /// FIFO not empty
270        VLD OFFSET(0) NUMBITS(1) []
271    ],
272    FIFO_WR [
273        /// FIFO Write
274        VALUE OFFSET(0) NUMBITS(32)
275    ],
276    FIFO_RD [
277        /// FIFO Read
278        VALUE OFFSET(0) NUMBITS(32)
279    ],
280];
281
282const GPIO_BASE_ADDRESS: usize = 0x40014000;
283const GPIO_BASE: StaticRef<GpioRegisters> =
284    unsafe { StaticRef::new(GPIO_BASE_ADDRESS as *const GpioRegisters) };
285
286const GPIO_PAD_BASE_ADDRESS: usize = 0x4001c000;
287const GPIO_PAD_BASE: StaticRef<GpioPadRegisters> =
288    unsafe { StaticRef::new(GPIO_PAD_BASE_ADDRESS as *const GpioPadRegisters) };
289
290const SIO_BASE_ADDRESS: usize = 0xd0000000;
291const SIO_BASE: StaticRef<SIORegisters> =
292    unsafe { StaticRef::new(SIO_BASE_ADDRESS as *const SIORegisters) };
293
294pub struct RPPins<'a> {
295    pub pins: [RPGpioPin<'a>; 30],
296    gpio_registers: StaticRef<GpioRegisters>,
297}
298
299impl<'a> RPPins<'a> {
300    pub const fn new() -> Self {
301        Self {
302            pins: [
303                RPGpioPin::new(RPGpio::GPIO0),
304                RPGpioPin::new(RPGpio::GPIO1),
305                RPGpioPin::new(RPGpio::GPIO2),
306                RPGpioPin::new(RPGpio::GPIO3),
307                RPGpioPin::new(RPGpio::GPIO4),
308                RPGpioPin::new(RPGpio::GPIO5),
309                RPGpioPin::new(RPGpio::GPIO6),
310                RPGpioPin::new(RPGpio::GPIO7),
311                RPGpioPin::new(RPGpio::GPIO8),
312                RPGpioPin::new(RPGpio::GPIO9),
313                RPGpioPin::new(RPGpio::GPIO10),
314                RPGpioPin::new(RPGpio::GPIO11),
315                RPGpioPin::new(RPGpio::GPIO12),
316                RPGpioPin::new(RPGpio::GPIO13),
317                RPGpioPin::new(RPGpio::GPIO14),
318                RPGpioPin::new(RPGpio::GPIO15),
319                RPGpioPin::new(RPGpio::GPIO16),
320                RPGpioPin::new(RPGpio::GPIO17),
321                RPGpioPin::new(RPGpio::GPIO18),
322                RPGpioPin::new(RPGpio::GPIO19),
323                RPGpioPin::new(RPGpio::GPIO20),
324                RPGpioPin::new(RPGpio::GPIO21),
325                RPGpioPin::new(RPGpio::GPIO22),
326                RPGpioPin::new(RPGpio::GPIO23),
327                RPGpioPin::new(RPGpio::GPIO24),
328                RPGpioPin::new(RPGpio::GPIO25),
329                RPGpioPin::new(RPGpio::GPIO26),
330                RPGpioPin::new(RPGpio::GPIO27),
331                RPGpioPin::new(RPGpio::GPIO28),
332                RPGpioPin::new(RPGpio::GPIO29),
333            ],
334            gpio_registers: GPIO_BASE,
335        }
336    }
337
338    pub fn get_pin(&self, pin: RPGpio) -> &'a RPGpioPin {
339        &self.pins[pin as usize]
340    }
341
342    pub fn handle_interrupt(&self) {
343        for bank_no in 0..4 {
344            let current_val = self.gpio_registers.intr[bank_no].get();
345            let enabled_val = self.gpio_registers.interrupt_proc[0].enable[bank_no].get();
346            for pin in 0..8 {
347                let l_low_reg_no = pin * 4;
348                if (current_val & enabled_val & (1 << l_low_reg_no)) != 0 {
349                    self.pins[pin + bank_no * 8].handle_interrupt();
350                } else if (current_val & enabled_val & (1 << (l_low_reg_no + 1))) != 0 {
351                    self.pins[pin + bank_no * 8].handle_interrupt();
352                } else if (current_val & enabled_val & (1 << (l_low_reg_no + 2))) != 0 {
353                    self.gpio_registers.intr[bank_no].set(current_val & (1 << (l_low_reg_no + 2)));
354                    self.pins[pin + bank_no * 8].handle_interrupt();
355                } else if (current_val & enabled_val & (1 << (l_low_reg_no + 3))) != 0 {
356                    self.gpio_registers.intr[bank_no].set(current_val & (1 << (l_low_reg_no + 3)));
357                    self.pins[pin + bank_no * 8].handle_interrupt();
358                }
359            }
360        }
361    }
362}
363
364enum_from_primitive! {
365    #[derive(Copy, Clone, PartialEq)]
366    #[repr(usize)]
367    #[rustfmt::skip]
368    pub enum RPGpio {
369        GPIO0=0, GPIO1=1, GPIO2=2, GPIO3=3, GPIO4=4, GPIO5=5, GPIO6=6, GPIO7=7,
370        GPIO8=8, GPIO9=9, GPIO10=10, GPIO11=11, GPIO12=12, GPIO13=13, GPIO14=14, GPIO15=15,
371        GPIO16=16, GPIO17=17, GPIO18=18, GPIO19=19, GPIO20=20, GPIO21=21, GPIO22=22, GPIO23=23,
372        GPIO24=24, GPIO25=25, GPIO26=26, GPIO27=27, GPIO28=28, GPIO29=29
373    }
374}
375enum_from_primitive! {
376    #[derive(Copy, Clone, PartialEq)]
377    #[repr(u32)]
378    #[rustfmt::skip]
379
380    pub enum GpioFunction {
381       SPI = 1,
382       UART = 2,
383       I2C = 3,
384       PWM = 4,
385       SIO = 5,
386       PIO0 = 6,
387       PIO1 = 7,
388       GPCK = 8,
389       USB = 9,
390       NULL = 0x1f
391    }
392}
393
394pub struct RPGpioPin<'a> {
395    pin: usize,
396    client: OptionalCell<&'a dyn hil::gpio::Client>,
397    gpio_registers: StaticRef<GpioRegisters>,
398    gpio_pad_registers: StaticRef<GpioPadRegisters>,
399    sio_registers: StaticRef<SIORegisters>,
400}
401
402impl<'a> RPGpioPin<'a> {
403    pub const fn new(pin: RPGpio) -> RPGpioPin<'a> {
404        RPGpioPin {
405            pin: pin as usize,
406            client: OptionalCell::empty(),
407            gpio_registers: GPIO_BASE,
408            gpio_pad_registers: GPIO_PAD_BASE,
409            sio_registers: SIO_BASE,
410        }
411    }
412
413    pub(crate) fn pin(&self) -> usize {
414        self.pin
415    }
416
417    fn get_mode(&self) -> hil::gpio::Configuration {
418        //TODO - read alternate function
419        let pad_output_disable = !self.gpio_pad_registers.gpio_pad[self.pin].is_set(GPIO_PAD::OD);
420        let pin_mask = 1 << self.pin;
421        let sio_output_enable = (self.sio_registers.gpio_oe.read(GPIO_OE::OE) & pin_mask) != 0;
422
423        match (pad_output_disable, sio_output_enable) {
424            (true, true) => hil::gpio::Configuration::Output,
425            (true, false) => hil::gpio::Configuration::Input,
426            (false, _) => hil::gpio::Configuration::LowPower,
427        }
428    }
429
430    fn read_pin(&self) -> bool {
431        //TODO - read alternate function
432        let value = self.sio_registers.gpio_out.read(GPIO_OUT::OUT) & (1 << self.pin);
433        value != 0
434    }
435
436    pub fn set_function(&self, f: GpioFunction) {
437        self.activate_pads();
438        self.gpio_registers.pin[self.pin]
439            .ctrl
440            .write(GPIOx_CTRL::FUNCSEL.val(f as u32));
441    }
442
443    fn get_pullup_pulldown(&self) -> hil::gpio::FloatingState {
444        //TODO - read alternate function
445        let pullup = self.gpio_pad_registers.gpio_pad[self.pin].read(GPIO_PAD::PUE);
446        let pulldown = self.gpio_pad_registers.gpio_pad[self.pin].read(GPIO_PAD::PDE);
447
448        match (pullup, pulldown) {
449            (0, 0) => hil::gpio::FloatingState::PullNone,
450            (0, 1) => hil::gpio::FloatingState::PullDown,
451            (1, 0) => hil::gpio::FloatingState::PullUp,
452            _ => panic!("Invalid GPIO floating state."),
453        }
454    }
455
456    pub fn activate_pads(&self) {
457        self.gpio_pad_registers.gpio_pad[self.pin].modify(GPIO_PAD::OD::CLEAR + GPIO_PAD::IE::SET);
458    }
459
460    pub fn deactivate_pads(&self) {
461        self.gpio_pad_registers.gpio_pad[self.pin].modify(GPIO_PAD::OD::SET + GPIO_PAD::IE::CLEAR);
462    }
463
464    pub fn handle_interrupt(&self) {
465        self.client.map(|client| client.fired());
466    }
467
468    // needed for usb errata https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#RP2040-E5
469
470    pub fn start_usb_errata(&self) -> (u32, u32) {
471        let prev_ctrl = self.gpio_registers.pin[self.pin].ctrl.get();
472        let prev_pad = self.gpio_pad_registers.gpio_pad[self.pin].get();
473
474        self.gpio_pad_registers.gpio_pad[self.pin].modify(GPIO_PAD::PUE::SET + GPIO_PAD::PDE::SET);
475        self.gpio_registers.pin[self.pin]
476            .ctrl
477            .modify(GPIOx_CTRL::OEOVER::Disable);
478
479        self.set_function(GpioFunction::GPCK);
480
481        self.gpio_registers.pin[self.pin]
482            .ctrl
483            .modify(GPIOx_CTRL::INOVER::DriveHigh);
484
485        (prev_ctrl, prev_pad)
486    }
487
488    pub fn finish_usb_errata(&self, prev_ctrl: u32, prev_pad: u32) {
489        self.gpio_registers.pin[self.pin].ctrl.set(prev_ctrl);
490        self.gpio_pad_registers.gpio_pad[self.pin].set(prev_pad);
491    }
492}
493
494impl<'a> hil::gpio::Interrupt<'a> for RPGpioPin<'a> {
495    fn set_client(&self, client: &'a dyn hil::gpio::Client) {
496        self.client.set(client);
497    }
498
499    fn is_pending(&self) -> bool {
500        let interrupt_bank_no = self.pin / 8;
501        let l_low_reg_no = (self.pin * 4) % 32;
502        let current_val = self.gpio_registers.interrupt_proc[0].status[interrupt_bank_no].get();
503        (current_val
504            & (1 << l_low_reg_no)
505            & (1 << (l_low_reg_no + 1))
506            & (1 << (l_low_reg_no + 2))
507            & (1 << (l_low_reg_no + 3)))
508            != 0
509    }
510
511    fn enable_interrupts(&self, mode: hil::gpio::InterruptEdge) {
512        let interrupt_bank_no = self.pin / 8;
513        match mode {
514            hil::gpio::InterruptEdge::RisingEdge => {
515                let high_reg_no = (self.pin * 4 + 3) % 32;
516                let current_val =
517                    self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no].get();
518                self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no]
519                    .set((1 << high_reg_no) | current_val);
520            }
521            hil::gpio::InterruptEdge::FallingEdge => {
522                let low_reg_no = (self.pin * 4 + 2) % 32;
523                let current_val =
524                    self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no].get();
525                self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no]
526                    .set((1 << low_reg_no) | current_val);
527            }
528            hil::gpio::InterruptEdge::EitherEdge => {
529                let low_reg_no = (self.pin * 4 + 2) % 32;
530                let high_reg_no = low_reg_no + 1;
531                let current_val =
532                    self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no].get();
533                self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no]
534                    .set((1 << high_reg_no) | (1 << low_reg_no) | current_val);
535            }
536        }
537    }
538
539    fn disable_interrupts(&self) {
540        let interrupt_bank_no = self.pin / 8;
541        let low_reg_no = (self.pin * 4 + 2) % 32;
542        let high_reg_no = low_reg_no + 1;
543        let current_val = self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no].get();
544        self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no]
545            .set(current_val & !(1 << high_reg_no) & !(1 << low_reg_no));
546    }
547}
548
549impl hil::gpio::Configure for RPGpioPin<'_> {
550    fn configuration(&self) -> hil::gpio::Configuration {
551        self.get_mode()
552    }
553    /// Set output mode
554    fn make_output(&self) -> hil::gpio::Configuration {
555        self.set_function(GpioFunction::SIO);
556        self.activate_pads();
557        self.sio_registers.gpio_oe_set.set(1 << self.pin);
558        self.get_mode()
559    }
560    /// Disable pad output
561    fn disable_output(&self) -> hil::gpio::Configuration {
562        self.set_function(GpioFunction::SIO);
563        self.gpio_pad_registers.gpio_pad[self.pin].modify(GPIO_PAD::OD::SET);
564        self.get_mode()
565    }
566    /// Set input mode
567    fn make_input(&self) -> hil::gpio::Configuration {
568        self.set_function(GpioFunction::SIO);
569        self.activate_pads();
570        self.sio_registers.gpio_oe_clr.set(1 << self.pin);
571        self.get_mode()
572    }
573    /// Disable input mode, will set pin to output mode
574    fn disable_input(&self) -> hil::gpio::Configuration {
575        self.make_output()
576    }
577    fn deactivate_to_low_power(&self) {
578        self.set_function(GpioFunction::SIO);
579        self.gpio_pad_registers.gpio_pad[self.pin].modify(GPIO_PAD::OD::SET);
580    }
581
582    fn set_floating_state(&self, mode: hil::gpio::FloatingState) {
583        match mode {
584            hil::gpio::FloatingState::PullUp => self.gpio_pad_registers.gpio_pad[self.pin]
585                .modify(GPIO_PAD::PUE::SET + GPIO_PAD::PDE::CLEAR),
586            hil::gpio::FloatingState::PullDown => self.gpio_pad_registers.gpio_pad[self.pin]
587                .modify(GPIO_PAD::PUE::CLEAR + GPIO_PAD::PDE::SET),
588            hil::gpio::FloatingState::PullNone => self.gpio_pad_registers.gpio_pad[self.pin]
589                .modify(GPIO_PAD::PUE::CLEAR + GPIO_PAD::PDE::CLEAR),
590        }
591    }
592
593    fn floating_state(&self) -> hil::gpio::FloatingState {
594        self.get_pullup_pulldown()
595    }
596
597    fn is_input(&self) -> bool {
598        let mode = self.get_mode();
599        match mode {
600            hil::gpio::Configuration::Input => true,
601            hil::gpio::Configuration::InputOutput => true,
602            _ => false,
603        }
604    }
605
606    fn is_output(&self) -> bool {
607        let mode = self.get_mode();
608        match mode {
609            hil::gpio::Configuration::Output => true,
610            hil::gpio::Configuration::InputOutput => true,
611            _ => false,
612        }
613    }
614}
615
616impl hil::gpio::Output for RPGpioPin<'_> {
617    fn set(&self) {
618        // For performance this match might be skipped
619        match self.get_mode() {
620            hil::gpio::Configuration::Output | hil::gpio::Configuration::InputOutput => {
621                self.sio_registers.gpio_out_set.set(1 << self.pin);
622            }
623            _ => {}
624        }
625    }
626
627    fn clear(&self) {
628        // For performance this match might be skipped
629        match self.get_mode() {
630            hil::gpio::Configuration::Output | hil::gpio::Configuration::InputOutput => {
631                self.sio_registers.gpio_out_clr.set(1 << self.pin);
632            }
633            _ => {}
634        }
635    }
636
637    fn toggle(&self) -> bool {
638        match self.get_mode() {
639            hil::gpio::Configuration::Output | hil::gpio::Configuration::InputOutput => {
640                self.sio_registers.gpio_out_xor.set(1 << self.pin);
641            }
642            _ => {}
643        }
644        self.read_pin()
645    }
646}
647
648impl hil::gpio::Input for RPGpioPin<'_> {
649    fn read(&self) -> bool {
650        let value = self.sio_registers.gpio_in.read(GPIO_IN::IN) & (1 << self.pin);
651        value != 0
652    }
653}
654
655pub struct SIO {
656    registers: StaticRef<SIORegisters>,
657}
658
659impl SIO {
660    pub const fn new() -> Self {
661        Self {
662            registers: SIO_BASE,
663        }
664    }
665
666    pub fn handle_proc_interrupt(&self, for_processor: Processor) {
667        match for_processor {
668            Processor::Processor0 => {
669                // read data from the fifo
670                self.registers.fifo_rd.get();
671                self.registers.fifo_st.set(0xff);
672            }
673            Processor::Processor1 => {
674                if self.registers.cpuid.get() == 1 {
675                    panic!("Kernel should not run on processor 1");
676                } else {
677                    panic!("SIO_PROC1_IRQ should be ignored for processor 1");
678                }
679            }
680        }
681    }
682
683    pub fn get_processor(&self) -> Processor {
684        let proc_id = self.registers.cpuid.get();
685        match proc_id {
686            0 => Processor::Processor0,
687            1 => Processor::Processor1,
688            _ => panic!("SIO CPUID cannot be {}", proc_id),
689        }
690    }
691}