apollo3/
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//! General Purpose Input/Output driver.
6
7use core::ops::{Index, IndexMut};
8use enum_primitive::cast::FromPrimitive;
9use enum_primitive::enum_from_primitive;
10use kernel::hil::gpio;
11use kernel::utilities::cells::OptionalCell;
12use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
13use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
14use kernel::utilities::StaticRef;
15
16pub const GPIO_BASE_RAW: usize = 0x4001_0000; //safe to export outside crate
17
18const GPIO_BASE: StaticRef<GpioRegisters> =
19    unsafe { StaticRef::new(GPIO_BASE_RAW as *const GpioRegisters) };
20
21pub struct Port<'a> {
22    pins: [GpioPin<'a>; 50],
23}
24
25impl Port<'_> {
26    pub const fn new() -> Self {
27        Self {
28            pins: [
29                GpioPin::new(GPIO_BASE, Pin::Pin00),
30                GpioPin::new(GPIO_BASE, Pin::Pin01),
31                GpioPin::new(GPIO_BASE, Pin::Pin02),
32                GpioPin::new(GPIO_BASE, Pin::Pin03),
33                GpioPin::new(GPIO_BASE, Pin::Pin04),
34                GpioPin::new(GPIO_BASE, Pin::Pin05),
35                GpioPin::new(GPIO_BASE, Pin::Pin06),
36                GpioPin::new(GPIO_BASE, Pin::Pin07),
37                GpioPin::new(GPIO_BASE, Pin::Pin08),
38                GpioPin::new(GPIO_BASE, Pin::Pin09),
39                GpioPin::new(GPIO_BASE, Pin::Pin10),
40                GpioPin::new(GPIO_BASE, Pin::Pin11),
41                GpioPin::new(GPIO_BASE, Pin::Pin12),
42                GpioPin::new(GPIO_BASE, Pin::Pin13),
43                GpioPin::new(GPIO_BASE, Pin::Pin14),
44                GpioPin::new(GPIO_BASE, Pin::Pin15),
45                GpioPin::new(GPIO_BASE, Pin::Pin16),
46                GpioPin::new(GPIO_BASE, Pin::Pin17),
47                GpioPin::new(GPIO_BASE, Pin::Pin18),
48                GpioPin::new(GPIO_BASE, Pin::Pin19),
49                GpioPin::new(GPIO_BASE, Pin::Pin20),
50                GpioPin::new(GPIO_BASE, Pin::Pin21),
51                GpioPin::new(GPIO_BASE, Pin::Pin22),
52                GpioPin::new(GPIO_BASE, Pin::Pin23),
53                GpioPin::new(GPIO_BASE, Pin::Pin24),
54                GpioPin::new(GPIO_BASE, Pin::Pin25),
55                GpioPin::new(GPIO_BASE, Pin::Pin26),
56                GpioPin::new(GPIO_BASE, Pin::Pin27),
57                GpioPin::new(GPIO_BASE, Pin::Pin28),
58                GpioPin::new(GPIO_BASE, Pin::Pin29),
59                GpioPin::new(GPIO_BASE, Pin::Pin30),
60                GpioPin::new(GPIO_BASE, Pin::Pin31),
61                GpioPin::new(GPIO_BASE, Pin::Pin32),
62                GpioPin::new(GPIO_BASE, Pin::Pin33),
63                GpioPin::new(GPIO_BASE, Pin::Pin34),
64                GpioPin::new(GPIO_BASE, Pin::Pin35),
65                GpioPin::new(GPIO_BASE, Pin::Pin36),
66                GpioPin::new(GPIO_BASE, Pin::Pin37),
67                GpioPin::new(GPIO_BASE, Pin::Pin38),
68                GpioPin::new(GPIO_BASE, Pin::Pin39),
69                GpioPin::new(GPIO_BASE, Pin::Pin40),
70                GpioPin::new(GPIO_BASE, Pin::Pin41),
71                GpioPin::new(GPIO_BASE, Pin::Pin42),
72                GpioPin::new(GPIO_BASE, Pin::Pin43),
73                GpioPin::new(GPIO_BASE, Pin::Pin44),
74                GpioPin::new(GPIO_BASE, Pin::Pin45),
75                GpioPin::new(GPIO_BASE, Pin::Pin46),
76                GpioPin::new(GPIO_BASE, Pin::Pin47),
77                GpioPin::new(GPIO_BASE, Pin::Pin48),
78                GpioPin::new(GPIO_BASE, Pin::Pin49),
79            ],
80        }
81    }
82}
83
84impl<'a> Index<usize> for Port<'a> {
85    type Output = GpioPin<'a>;
86
87    fn index(&self, index: usize) -> &GpioPin<'a> {
88        &self.pins[index]
89    }
90}
91
92impl<'a> IndexMut<usize> for Port<'a> {
93    fn index_mut(&mut self, index: usize) -> &mut GpioPin<'a> {
94        &mut self.pins[index]
95    }
96}
97
98impl Port<'_> {
99    pub fn handle_interrupt(&self) {
100        let regs = GPIO_BASE;
101        let mut irqs = regs.int0stat.get();
102        regs.int0clr.set(irqs);
103
104        let mut count = 0;
105        while irqs != 0 && count < self.pins.len() {
106            if (irqs & 0b1) != 0 {
107                self.pins[count].handle_interrupt();
108            }
109            count += 1;
110            irqs >>= 1;
111        }
112
113        let mut irqs = regs.int1stat.get();
114        regs.int1clr.set(irqs);
115
116        let mut count = 0;
117        while irqs != 0 && count < self.pins.len() {
118            if (irqs & 0b1) != 0 {
119                // Offset the count by 32 as it's the second GPIO bank
120                // (top 32 GPIOs)
121                self.pins[count + 32].handle_interrupt();
122            }
123            count += 1;
124            irqs >>= 1;
125        }
126    }
127
128    pub fn enable_uart(&self, tx_pin: &GpioPin, rx_pin: &GpioPin) {
129        let regs = GPIO_BASE;
130
131        match tx_pin.pin as usize {
132            48 => {
133                regs.padkey.set(115);
134                regs.padreg[12].set(regs.padreg[12].get() & 0xffffff00);
135                regs.cfg[6].modify(CFG::GPIO0INTD.val(0x00) + CFG::GPIO0OUTCFG.val(0x00));
136                regs.altpadcfgm
137                    .modify(ALTPADCFG::PAD0_DS1::CLEAR + ALTPADCFG::PAD0_SR::CLEAR);
138                regs.padkey.set(0x00);
139            }
140            _ => {
141                panic!("tx_pin not supported");
142            }
143        }
144
145        match rx_pin.pin as usize {
146            49 => {
147                regs.padkey.set(115);
148                regs.padreg[12].modify(
149                    PADREG::PAD1PULL::CLEAR
150                        + PADREG::PAD1INPEN::SET
151                        + PADREG::PAD1STRNG::CLEAR
152                        + PADREG::PAD1FNCSEL::CLEAR
153                        + PADREG::PAD1RSEL::CLEAR,
154                );
155                regs.cfg[6].modify(
156                    CFG::GPIO1INCFG::CLEAR + CFG::GPIO1INTD.val(0x00) + CFG::GPIO1OUTCFG.val(0x00),
157                );
158                regs.altpadcfgm
159                    .modify(ALTPADCFG::PAD1_DS1::CLEAR + ALTPADCFG::PAD1_SR::CLEAR);
160                regs.padkey.set(0x00);
161            }
162            _ => {
163                panic!("rx_pin not supported");
164            }
165        }
166    }
167
168    /// This function configures some GPIO pins on the Apollo3 to allow
169    /// communication with a SX1262 LoRa module.
170    ///
171    /// The pin mapping is setup to match what is used by the NM180100 SoC (shown below)
172    ///
173    /// IOM3: Semtech SX1262
174    ///     Apollo 3 Pin Number | Apollo 3 Name | SX1262 Pin Number | SX1262 Name | SX1262 Description
175    ///                      H6 |       GPIO 36 |                19 |  NSS        | SPI slave select
176    ///                      J6 |       GPIO 38 |                17 |  MOSI       | SPI slave input
177    ///                      J5 |       GPIO 43 |                16 |  MISO       | SPI slave output
178    ///                      H5 |       GPIO 42 |                18 |  SCK        | SPI clock input
179    ///                      J8 |       GPIO 39 |                14 |  BUSY       | Radio busy indicator
180    ///                      J9 |       GPIO 40 |                13 |  DIO1       | Multipurpose digital I/O
181    ///                      H9 |       GPIO 47 |                6  |  DIO3       | Multipurpose digital I/O
182    ///                      J7 |       GPIO 44 |                15 |  NRESET     | Radio reset signal, active low
183    ///
184    /// This should be used by the lora_things_plus board or any other board using
185    /// the Apollo3 based NM180100 SoC. This function would also work for any
186    /// Apollo3 board using the same pins and IOM as specified above.
187    pub fn enable_sx1262_radio_pins(&self) {
188        let regs = GPIO_BASE;
189
190        regs.padkey.set(115);
191
192        // Pin 36 NSS
193        regs.padreg[9].modify(
194            PADREG::PAD0PULL::CLEAR + PADREG::PAD0INPEN::CLEAR + PADREG::PAD0FNCSEL.val(0x1),
195        );
196        regs.cfg[4].modify(CFG::GPIO4INCFG.val(0x00) + CFG::GPIO4OUTCFG.val(0x00));
197        regs.altpadcfgj
198            .modify(ALTPADCFG::PAD0_DS1::CLEAR + ALTPADCFG::PAD0_SR::CLEAR);
199
200        // Pin 39 Busy
201        regs.padreg[9].modify(
202            PADREG::PAD3INPEN::SET
203                + PADREG::PAD3STRNG::CLEAR
204                + PADREG::PAD3FNCSEL.val(0x3)
205                + PADREG::PAD3RSEL.val(0x0),
206        );
207        regs.cfg[4].modify(
208            CFG::GPIO7INCFG.val(0x00) + CFG::GPIO7OUTCFG.val(0x00) + CFG::GPIO7INTD.val(0x00),
209        );
210        regs.altpadcfgj
211            .modify(ALTPADCFG::PAD3_DS1::CLEAR + ALTPADCFG::PAD3_SR::CLEAR);
212
213        // Pin 40 DIO1
214        regs.padreg[10].modify(
215            PADREG::PAD0PULL::CLEAR
216                + PADREG::PAD0INPEN::SET
217                + PADREG::PAD0STRING::CLEAR
218                + PADREG::PAD0FNCSEL.val(0x3)
219                + PADREG::PAD0RSEL.val(0x0),
220        );
221        regs.cfg[5].modify(
222            CFG::GPIO0INCFG.val(0x00) + CFG::GPIO0OUTCFG.val(0x00) + CFG::GPIO0INTD.val(0x00),
223        );
224        regs.altpadcfgk
225            .modify(ALTPADCFG::PAD0_DS1::CLEAR + ALTPADCFG::PAD0_SR::CLEAR);
226
227        // Pin 47 DIO3
228        regs.padreg[11].modify(
229            PADREG::PAD3PULL::CLEAR
230                + PADREG::PAD3INPEN::SET
231                + PADREG::PAD3STRNG::CLEAR
232                + PADREG::PAD3FNCSEL.val(0x3)
233                + PADREG::PAD3RSEL.val(0x0),
234        );
235        regs.cfg[5].modify(
236            CFG::GPIO7INCFG.val(0x00) + CFG::GPIO7OUTCFG.val(0x00) + CFG::GPIO7INTD.val(0x00),
237        );
238        regs.altpadcfgl
239            .modify(ALTPADCFG::PAD3_DS1::CLEAR + ALTPADCFG::PAD3_SR::CLEAR);
240
241        // Pin 44 NReset
242        regs.padreg[11].modify(
243            PADREG::PAD0PULL::CLEAR
244                + PADREG::PAD0INPEN::CLEAR
245                + PADREG::PAD0STRING::CLEAR
246                + PADREG::PAD0FNCSEL.val(0x3)
247                + PADREG::PAD0RSEL.val(0x0),
248        );
249        regs.cfg[5].modify(
250            CFG::GPIO4INCFG.val(0x00) + CFG::GPIO4OUTCFG.val(0x00) + CFG::GPIO4INTD.val(0x00),
251        );
252        regs.altpadcfgl
253            .modify(ALTPADCFG::PAD0_DS1::CLEAR + ALTPADCFG::PAD0_SR::CLEAR);
254
255        regs.padkey.set(0x00);
256    }
257
258    pub fn enable_i2c(&self, sda: &GpioPin, scl: &GpioPin) {
259        let regs = GPIO_BASE;
260
261        match sda.pin as usize {
262            40 => {
263                regs.padkey.set(115);
264                regs.padreg[10].modify(
265                    PADREG::PAD0PULL::SET
266                        + PADREG::PAD0INPEN::SET
267                        + PADREG::PAD0STRING::SET
268                        + PADREG::PAD0FNCSEL.val(0x4)
269                        + PADREG::PAD0RSEL.val(0x00),
270                );
271                regs.cfg[5].modify(CFG::GPIO0INCFG.val(0x00) + CFG::GPIO0OUTCFG.val(0x02));
272                regs.altpadcfgk
273                    .modify(ALTPADCFG::PAD0_DS1::SET + ALTPADCFG::PAD0_DS1::CLEAR);
274                regs.padkey.set(0x00);
275            }
276            25 => {
277                regs.padkey.set(115);
278                regs.padreg[6].modify(
279                    PADREG::PAD1PULL::SET
280                        + PADREG::PAD1INPEN::SET
281                        + PADREG::PAD1STRNG::SET
282                        + PADREG::PAD1FNCSEL.val(0x4),
283                );
284                regs.cfg[3].modify(CFG::GPIO1INTD.val(0x00) + CFG::GPIO1OUTCFG.val(0x02));
285                regs.altpadcfgg
286                    .modify(ALTPADCFG::PAD1_DS1::CLEAR + ALTPADCFG::PAD1_SR::CLEAR);
287                regs.padkey.set(0x00);
288            }
289            6 => {
290                regs.padkey.set(115);
291                regs.padreg[1].modify(
292                    PADREG::PAD2PULL::SET
293                        + PADREG::PAD2INPEN::SET
294                        + PADREG::PAD2STRNG::SET
295                        + PADREG::PAD2FNCSEL.val(0x00),
296                );
297                regs.cfg[0].modify(CFG::GPIO6OUTCFG.val(0x03) + CFG::GPIO6OUTCFG.val(0x00));
298                regs.altpadcfgb
299                    .modify(ALTPADCFG::PAD2_DS1::SET + ALTPADCFG::PAD2_SR::CLEAR);
300                regs.padkey.set(0x00);
301            }
302            _ => {
303                panic!("sda not supported");
304            }
305        }
306
307        match scl.pin as usize {
308            39 => {
309                regs.padkey.set(115);
310                regs.padreg[9].modify(
311                    PADREG::PAD3PULL::SET
312                        + PADREG::PAD3INPEN::SET
313                        + PADREG::PAD3STRNG::SET
314                        + PADREG::PAD3FNCSEL.val(0x4)
315                        + PADREG::PAD3RSEL.val(0x00),
316                );
317                regs.cfg[4].modify(CFG::GPIO7INTD.val(0x00) + CFG::GPIO7OUTCFG.val(0x02));
318                regs.altpadcfgj
319                    .modify(ALTPADCFG::PAD3_DS1::SET + ALTPADCFG::PAD3_SR::CLEAR);
320                regs.padkey.set(0x00);
321            }
322            27 => {
323                regs.padkey.set(115);
324                regs.padreg[6].modify(
325                    PADREG::PAD3PULL::SET
326                        + PADREG::PAD3INPEN::SET
327                        + PADREG::PAD3STRNG::SET
328                        + PADREG::PAD3FNCSEL.val(0x4),
329                );
330                regs.cfg[3].modify(CFG::GPIO3INTD.val(0x00) + CFG::GPIO3OUTCFG.val(0x02));
331                regs.altpadcfgg
332                    .modify(ALTPADCFG::PAD3_DS1::CLEAR + ALTPADCFG::PAD3_SR::CLEAR);
333                regs.padkey.set(0x00);
334            }
335            5 => {
336                regs.padkey.set(115);
337                regs.padreg[1].modify(
338                    PADREG::PAD1PULL::SET
339                        + PADREG::PAD1INPEN::SET
340                        + PADREG::PAD1STRNG::SET
341                        + PADREG::PAD1FNCSEL.val(0x00)
342                        + PADREG::PAD1RSEL.val(0x00),
343                );
344                regs.cfg[0].modify(CFG::GPIO5OUTCFG.val(0x03) + CFG::GPIO1OUTCFG.val(0x00));
345                regs.altpadcfgb
346                    .modify(ALTPADCFG::PAD1_DS1::SET + ALTPADCFG::PAD1_SR::CLEAR);
347                regs.padkey.set(0x00);
348            }
349            _ => {
350                panic!("scl not supported");
351            }
352        }
353    }
354
355    pub fn enable_i2c_slave(&self, sda: &GpioPin, scl: &GpioPin) {
356        let regs = GPIO_BASE;
357
358        match sda.pin as usize {
359            1 => {
360                regs.padkey.set(115);
361                regs.padreg[0].modify(
362                    PADREG::PAD1PULL::SET
363                        + PADREG::PAD1INPEN::SET
364                        + PADREG::PAD1STRNG::CLEAR
365                        + PADREG::PAD1FNCSEL.val(0x00)
366                        + PADREG::PAD1RSEL.val(0x00),
367                );
368                regs.cfg[0].modify(
369                    CFG::GPIO1INCFG::CLEAR + CFG::GPIO1OUTCFG.val(0x02) + CFG::GPIO1INTD::CLEAR,
370                );
371                regs.altpadcfga
372                    .modify(ALTPADCFG::PAD1_DS1::CLEAR + ALTPADCFG::PAD1_SR::CLEAR);
373                regs.padkey.set(0x00);
374            }
375            _ => {
376                panic!("sda not supported");
377            }
378        }
379
380        match scl.pin as usize {
381            0 => {
382                regs.padkey.set(115);
383                regs.padreg[0].modify(
384                    PADREG::PAD0PULL::CLEAR
385                        + PADREG::PAD0INPEN::SET
386                        + PADREG::PAD0STRING::CLEAR
387                        + PADREG::PAD0FNCSEL.val(0x0)
388                        + PADREG::PAD0RSEL.val(0x0),
389                );
390                regs.cfg[0].modify(
391                    CFG::GPIO0INCFG::CLEAR + CFG::GPIO0OUTCFG.val(0x0) + CFG::GPIO0INTD::CLEAR,
392                );
393                regs.altpadcfga
394                    .modify(ALTPADCFG::PAD0_DS1::CLEAR + ALTPADCFG::PAD0_SR::CLEAR);
395                regs.padkey.set(0x00);
396            }
397            _ => {
398                panic!("scl not supported");
399            }
400        }
401    }
402
403    pub fn enable_spi(&self, sck: &GpioPin, mosi: &GpioPin, miso: &GpioPin) {
404        let regs = GPIO_BASE;
405
406        match sck.pin as usize {
407            5 => {
408                regs.padkey.set(115);
409                regs.padreg[1].modify(
410                    PADREG::PAD1PULL::CLEAR
411                        + PADREG::PAD1INPEN::SET
412                        + PADREG::PAD1STRNG::SET
413                        + PADREG::PAD1FNCSEL.val(0x1)
414                        + PADREG::PAD1RSEL.val(0x00),
415                );
416                regs.cfg[0].modify(
417                    CFG::GPIO1INCFG.val(0x00)
418                        + CFG::GPIO1OUTCFG.val(0x000)
419                        + CFG::GPIO1INTD.val(0x00),
420                );
421                regs.altpadcfgb
422                    .modify(ALTPADCFG::PAD1_DS1::SET + ALTPADCFG::PAD1_SR::CLEAR);
423                regs.padkey.set(0x00);
424            }
425            18 => {
426                regs.padkey.set(115);
427                regs.padreg[4].modify(
428                    PADREG::PAD2PULL::CLEAR
429                        + PADREG::PAD2INPEN::CLEAR
430                        + PADREG::PAD2STRNG::SET
431                        + PADREG::PAD2FNCSEL.val(0x5),
432                );
433                regs.cfg[2].modify(
434                    CFG::GPIO2INCFG.val(0x00)
435                        + CFG::GPIO2OUTCFG.val(0x000)
436                        + CFG::GPIO2INTD.val(0x00),
437                );
438                regs.altpadcfge
439                    .modify(ALTPADCFG::PAD2_DS1::SET + ALTPADCFG::PAD2_SR::CLEAR);
440                regs.padkey.set(0x00);
441            }
442            27 => {
443                regs.padkey.set(115);
444                regs.padreg[6].modify(
445                    PADREG::PAD3PULL::CLEAR
446                        + PADREG::PAD3INPEN::SET
447                        + PADREG::PAD3STRNG::SET
448                        + PADREG::PAD3FNCSEL.val(0x5)
449                        + PADREG::PAD3RSEL.val(0x00),
450                );
451                regs.cfg[3].modify(
452                    CFG::GPIO3INCFG.val(0x00)
453                        + CFG::GPIO3OUTCFG.val(0x000)
454                        + CFG::GPIO3INTD.val(0x00),
455                );
456                regs.altpadcfgg
457                    .modify(ALTPADCFG::PAD3_DS1::SET + ALTPADCFG::PAD3_SR::CLEAR);
458                regs.padkey.set(0x00);
459            }
460            42 => {
461                regs.padkey.set(115);
462                regs.padreg[10].modify(
463                    PADREG::PAD2PULL::CLEAR
464                        + PADREG::PAD2INPEN::SET
465                        + PADREG::PAD2STRNG::SET
466                        + PADREG::PAD2FNCSEL.val(0x5),
467                );
468                regs.cfg[5].modify(
469                    CFG::GPIO2INCFG.val(0x00)
470                        + CFG::GPIO2OUTCFG.val(0x000)
471                        + CFG::GPIO2INTD.val(0x00),
472                );
473                regs.altpadcfgk
474                    .modify(ALTPADCFG::PAD2_DS1::SET + ALTPADCFG::PAD2_SR::CLEAR);
475                regs.padkey.set(0x00);
476            }
477            _ => {
478                panic!("sck not supported");
479            }
480        }
481
482        match mosi.pin as usize {
483            7 => {
484                regs.padkey.set(115);
485                regs.padreg[1].modify(
486                    PADREG::PAD3PULL::CLEAR
487                        + PADREG::PAD3INPEN::CLEAR
488                        + PADREG::PAD3STRNG::SET
489                        + PADREG::PAD3FNCSEL.val(0x1)
490                        + PADREG::PAD3RSEL.val(0x00),
491                );
492                regs.cfg[0].modify(
493                    CFG::GPIO4INCFG.val(0x00)
494                        + CFG::GPIO4OUTCFG.val(0x000)
495                        + CFG::GPIO4INTD.val(0x00),
496                );
497                regs.altpadcfgb
498                    .modify(ALTPADCFG::PAD3_DS1::SET + ALTPADCFG::PAD3_SR::CLEAR);
499                regs.padkey.set(0x00);
500            }
501            17 => {
502                regs.padkey.set(115);
503                regs.padreg[4].modify(
504                    PADREG::PAD2PULL::CLEAR
505                        + PADREG::PAD2INPEN::SET
506                        + PADREG::PAD2STRNG::CLEAR
507                        + PADREG::PAD2FNCSEL.val(0x5),
508                );
509                regs.cfg[2].modify(
510                    CFG::GPIO1INCFG.val(0x00)
511                        + CFG::GPIO1OUTCFG.val(0x000)
512                        + CFG::GPIO1INTD.val(0x00),
513                );
514                regs.altpadcfge
515                    .modify(ALTPADCFG::PAD1_DS1::SET + ALTPADCFG::PAD1_SR::CLEAR);
516                regs.padkey.set(0x00);
517            }
518            28 => {
519                regs.padkey.set(115);
520                regs.padreg[7].modify(
521                    PADREG::PAD0PULL::CLEAR
522                        + PADREG::PAD0INPEN::CLEAR
523                        + PADREG::PAD0STRING::SET
524                        + PADREG::PAD0FNCSEL.val(0x5)
525                        + PADREG::PAD0RSEL.val(0x00),
526                );
527                regs.cfg[3].modify(
528                    CFG::GPIO4INCFG.val(0x00)
529                        + CFG::GPIO4OUTCFG.val(0x000)
530                        + CFG::GPIO4INTD.val(0x00),
531                );
532                regs.altpadcfgh
533                    .modify(ALTPADCFG::PAD0_DS1::SET + ALTPADCFG::PAD0_SR::CLEAR);
534                regs.padkey.set(0x00);
535            }
536            38 => {
537                regs.padkey.set(115);
538                regs.padreg[9].modify(
539                    PADREG::PAD2PULL::CLEAR
540                        + PADREG::PAD2INPEN::CLEAR
541                        + PADREG::PAD2STRNG::CLEAR
542                        + PADREG::PAD2FNCSEL.val(0x5),
543                );
544                regs.cfg[4].modify(
545                    CFG::GPIO6INCFG.val(0x00)
546                        + CFG::GPIO6OUTCFG.val(0x000)
547                        + CFG::GPIO6INTD.val(0x00),
548                );
549                regs.altpadcfgj
550                    .modify(ALTPADCFG::PAD2_DS1::CLEAR + ALTPADCFG::PAD2_SR::CLEAR);
551                regs.padkey.set(0x00);
552            }
553            _ => {
554                panic!("mosi not supported");
555            }
556        }
557
558        match miso.pin as usize {
559            6 => {
560                regs.padkey.set(115);
561                regs.padreg[1].modify(
562                    PADREG::PAD2PULL::CLEAR
563                        + PADREG::PAD2INPEN::SET
564                        + PADREG::PAD2STRNG::CLEAR
565                        + PADREG::PAD2FNCSEL.val(0x1),
566                );
567                regs.cfg[0].modify(
568                    CFG::GPIO3INCFG.val(0x00)
569                        + CFG::GPIO3OUTCFG.val(0x000)
570                        + CFG::GPIO3INTD.val(0x00),
571                );
572                regs.altpadcfgb
573                    .modify(ALTPADCFG::PAD2_DS1::CLEAR + ALTPADCFG::PAD2_SR::CLEAR);
574                regs.padkey.set(0x00);
575            }
576            25 => {
577                regs.padkey.set(115);
578                regs.padreg[6].modify(
579                    PADREG::PAD1PULL::CLEAR
580                        + PADREG::PAD1INPEN::SET
581                        + PADREG::PAD1STRNG::CLEAR
582                        + PADREG::PAD1FNCSEL.val(0x5)
583                        + PADREG::PAD1RSEL.val(0x00),
584                );
585                regs.cfg[3].modify(
586                    CFG::GPIO1INCFG.val(0x00)
587                        + CFG::GPIO1OUTCFG.val(0x000)
588                        + CFG::GPIO1INTD.val(0x00),
589                );
590                regs.altpadcfgg
591                    .modify(ALTPADCFG::PAD1_DS1::CLEAR + ALTPADCFG::PAD1_SR::CLEAR);
592                regs.padkey.set(0x00);
593            }
594            26 => {
595                regs.padkey.set(115);
596                regs.padreg[6].modify(
597                    PADREG::PAD2PULL::CLEAR
598                        + PADREG::PAD2INPEN::SET
599                        + PADREG::PAD2STRNG::CLEAR
600                        + PADREG::PAD2FNCSEL.val(0x5),
601                );
602                regs.cfg[3].modify(
603                    CFG::GPIO2INCFG.val(0x00)
604                        + CFG::GPIO2OUTCFG.val(0x000)
605                        + CFG::GPIO2INTD.val(0x00),
606                );
607                regs.altpadcfgg
608                    .modify(ALTPADCFG::PAD2_DS1::CLEAR + ALTPADCFG::PAD2_SR::CLEAR);
609                regs.padkey.set(0x00);
610            }
611            43 => {
612                regs.padkey.set(115);
613                regs.padreg[10].modify(
614                    PADREG::PAD3PULL::CLEAR
615                        + PADREG::PAD3INPEN::SET
616                        + PADREG::PAD3STRNG::CLEAR
617                        + PADREG::PAD3FNCSEL.val(0x5),
618                );
619                regs.cfg[5].modify(
620                    CFG::GPIO3INCFG.val(0x00)
621                        + CFG::GPIO3OUTCFG.val(0x000)
622                        + CFG::GPIO3INTD.val(0x00),
623                );
624                regs.altpadcfgk
625                    .modify(ALTPADCFG::PAD3_DS1::CLEAR + ALTPADCFG::PAD3_SR::CLEAR);
626                regs.padkey.set(0x00);
627            }
628            _ => {
629                panic!("miso not supported");
630            }
631        }
632    }
633}
634
635enum_from_primitive! {
636    #[derive(Copy, Clone, Debug, PartialEq)]
637    pub enum Pin {
638        Pin00, Pin01, Pin02, Pin03, Pin04, Pin05, Pin06, Pin07,
639        Pin08, Pin09, Pin10, Pin11, Pin12, Pin13, Pin14, Pin15,
640        Pin16, Pin17, Pin18, Pin19, Pin20, Pin21, Pin22, Pin23,
641        Pin24, Pin25, Pin26, Pin27, Pin28, Pin29, Pin30, Pin31,
642        Pin32, Pin33, Pin34, Pin35, Pin36, Pin37, Pin38, Pin39,
643        Pin40, Pin41, Pin42, Pin43, Pin44, Pin45, Pin46, Pin47,
644        Pin48, Pin49,
645    }
646}
647
648register_structs! {
649    pub GpioRegisters {
650        (0x00 => padreg: [ReadWrite<u32, PADREG::Register>; 13]),
651        (0x34 => _reserved0),
652        (0x40 => cfg: [ReadWrite<u32, CFG::Register>; 7]),
653        (0x5C => _reserved1),
654        (0x60 => padkey: ReadWrite<u32, PADKEY::Register>),
655        (0x64 => _reserved2),
656        (0x80 => rda: ReadWrite<u32, RDA::Register>),
657        (0x84 => rdb: ReadWrite<u32, RDB::Register>),
658        (0x88 => wta: ReadWrite<u32, WTA::Register>),
659        (0x8C => wtb: ReadWrite<u32, WTB::Register>),
660        (0x90 => wtsa: ReadWrite<u32, WTSA::Register>),
661        (0x94 => wtsb: ReadWrite<u32, WTSB::Register>),
662        (0x98 => wtca: ReadWrite<u32, WTCA::Register>),
663        (0x9c => wtcb: ReadWrite<u32, WTCB::Register>),
664        (0xA0 => ena: ReadWrite<u32, ENA::Register>),
665        (0xA4 => enb: ReadWrite<u32, ENB::Register>),
666        (0xA8 => ensa: ReadWrite<u32, ENSA::Register>),
667        (0xAC => ensb: ReadWrite<u32, ENSB::Register>),
668        (0xB0 => _reserved3),
669        (0xB4 => enca: ReadWrite<u32, ENCA::Register>),
670        (0xB8 => encb: ReadWrite<u32, ENCB::Register>),
671        (0xBC => stmrcap: ReadWrite<u32, STMRCAP::Register>),
672        (0xC0 => iom0irq: ReadWrite<u32, IOMIRQ::Register>),
673        (0xC4 => iom1irq: ReadWrite<u32, IOMIRQ::Register>),
674        (0xC8 => iom2irq: ReadWrite<u32, IOMIRQ::Register>),
675        (0xCC => iom3irq: ReadWrite<u32, IOMIRQ::Register>),
676        (0xD0 => iom4irq: ReadWrite<u32, IOMIRQ::Register>),
677        (0xD4 => iom5irq: ReadWrite<u32, IOMIRQ::Register>),
678        (0xD8 => bleif5irq: ReadWrite<u32, IOMIRQ::Register>),
679        (0xDC => gpioobs: ReadWrite<u32, GPIOOBS::Register>),
680        (0xE0 => altpadcfga: ReadWrite<u32, ALTPADCFG::Register>),
681        (0xE4 => altpadcfgb: ReadWrite<u32, ALTPADCFG::Register>),
682        (0xE8 => altpadcfgc: ReadWrite<u32, ALTPADCFG::Register>),
683        (0xEC => altpadcfgd: ReadWrite<u32, ALTPADCFG::Register>),
684        (0xF0 => altpadcfge: ReadWrite<u32, ALTPADCFG::Register>),
685        (0xF4 => altpadcfgf: ReadWrite<u32, ALTPADCFG::Register>),
686        (0xF8 => altpadcfgg: ReadWrite<u32, ALTPADCFG::Register>),
687        (0xFC => altpadcfgh: ReadWrite<u32, ALTPADCFG::Register>),
688        (0x100 => altpadcfgi: ReadWrite<u32, ALTPADCFG::Register>),
689        (0x104 => altpadcfgj: ReadWrite<u32, ALTPADCFG::Register>),
690        (0x108 => altpadcfgk: ReadWrite<u32, ALTPADCFG::Register>),
691        (0x10C => altpadcfgl: ReadWrite<u32, ALTPADCFG::Register>),
692        (0x110 => altpadcfgm: ReadWrite<u32, ALTPADCFG::Register>),
693        (0x114 => scdet: ReadWrite<u32, SCDET::Register>),
694        (0x118 => ctencfg: ReadWrite<u32, CTENCFG::Register>),
695        (0x11C => _reserved4),
696        (0x200 => int0en: ReadWrite<u32, INT0::Register>),
697        (0x204 => int0stat: ReadWrite<u32, INT0::Register>),
698        (0x208 => int0clr: ReadWrite<u32, INT0::Register>),
699        (0x20C => int0set: ReadWrite<u32, INT0::Register>),
700        (0x210 => int1en: ReadWrite<u32, INT1::Register>),
701        (0x214 => int1stat: ReadWrite<u32, INT1::Register>),
702        (0x218 => int1clr: ReadWrite<u32, INT1::Register>),
703        (0x21C => int1set: ReadWrite<u32, INT1::Register>),
704        (0x220 => @END),
705    }
706}
707
708register_bitfields![u32,
709    PADREG [
710        PAD0PULL OFFSET(0) NUMBITS(1) [],
711        PAD0INPEN OFFSET(1) NUMBITS(1) [],
712        PAD0STRING OFFSET(2) NUMBITS(1) [],
713        PAD0FNCSEL OFFSET(3) NUMBITS(3) [],
714        PAD0RSEL OFFSET(6) NUMBITS(2) [],
715        PAD1PULL OFFSET(8) NUMBITS(1) [],
716        PAD1INPEN OFFSET(9) NUMBITS(1) [],
717        PAD1STRNG OFFSET(10) NUMBITS(1) [],
718        PAD1FNCSEL OFFSET(11) NUMBITS(3) [],
719        PAD1RSEL OFFSET(14) NUMBITS(2) [],
720        PAD2PULL OFFSET(16) NUMBITS(1) [],
721        PAD2INPEN OFFSET(17) NUMBITS(1) [],
722        PAD2STRNG OFFSET(18) NUMBITS(1) [],
723        PAD2FNCSEL OFFSET(19) NUMBITS(3) [],
724        PAD3PULL OFFSET(24) NUMBITS(1) [],
725        PAD3INPEN OFFSET(25) NUMBITS(1) [],
726        PAD3STRNG OFFSET(26) NUMBITS(1) [],
727        PAD3FNCSEL OFFSET(27) NUMBITS(3) [],
728        PAD3RSEL OFFSET(30) NUMBITS(2) []
729    ],
730    CFG [
731        GPIO0INCFG OFFSET(0) NUMBITS(1) [],
732        GPIO0OUTCFG OFFSET(1) NUMBITS(2) [],
733        GPIO0INTD OFFSET(3) NUMBITS(1) [],
734        GPIO1INCFG OFFSET(4) NUMBITS(1) [],
735        GPIO1OUTCFG OFFSET(5) NUMBITS(2) [],
736        GPIO1INTD OFFSET(7) NUMBITS(1) [],
737        GPIO2INCFG OFFSET(8) NUMBITS(1) [],
738        GPIO2OUTCFG OFFSET(9) NUMBITS(2) [],
739        GPIO2INTD OFFSET(11) NUMBITS(1) [],
740        GPIO3INCFG OFFSET(12) NUMBITS(1) [],
741        GPIO3OUTCFG OFFSET(13) NUMBITS(2) [],
742        GPIO3INTD OFFSET(15) NUMBITS(1) [],
743        GPIO4INCFG OFFSET(16) NUMBITS(1) [],
744        GPIO4OUTCFG OFFSET(17) NUMBITS(2) [],
745        GPIO4INTD OFFSET(19) NUMBITS(1) [],
746        GPIO5INCFG OFFSET(20) NUMBITS(1) [],
747        GPIO5OUTCFG OFFSET(21) NUMBITS(2) [],
748        GPIO5INTD OFFSET(23) NUMBITS(1) [],
749        GPIO6INCFG OFFSET(24) NUMBITS(1) [],
750        GPIO6OUTCFG OFFSET(25) NUMBITS(2) [],
751        GPIO6INTD OFFSET(27) NUMBITS(1) [],
752        GPIO7INCFG OFFSET(28) NUMBITS(1) [],
753        GPIO7OUTCFG OFFSET(29) NUMBITS(2) [],
754        GPIO7INTD OFFSET(31) NUMBITS(1) []
755    ],
756    PADKEY [
757        PADKEY OFFSET(0) NUMBITS(31) []
758    ],
759    RDA [
760        RDA OFFSET(0) NUMBITS(31) []
761    ],
762    RDB [
763        RDB OFFSET(0) NUMBITS(17) []
764    ],
765    WTA [
766        WTA OFFSET(0) NUMBITS(31) []
767    ],
768    WTB [
769        WTB OFFSET(0) NUMBITS(17) []
770    ],
771    WTSA [
772        WTSA OFFSET(0) NUMBITS(31) []
773    ],
774    WTSB [
775        WTSB OFFSET(0) NUMBITS(17) []
776    ],
777    WTCA [
778        WTCA OFFSET(0) NUMBITS(31) []
779    ],
780    WTCB [
781        WTCB OFFSET(0) NUMBITS(17) []
782    ],
783    ENA [
784        ENA OFFSET(0) NUMBITS(31) []
785    ],
786    ENB [
787        ENB OFFSET(0) NUMBITS(17) []
788    ],
789    ENSA [
790        ENSA OFFSET(0) NUMBITS(31) []
791    ],
792    ENSB [
793        ENSB OFFSET(0) NUMBITS(17) []
794    ],
795    ENCA [
796        ENCA OFFSET(0) NUMBITS(31) []
797    ],
798    ENCB [
799        ENCB OFFSET(0) NUMBITS(17) []
800    ],
801    STMRCAP [
802        STSEL0 OFFSET(0) NUMBITS(5) [],
803        STPOL0 OFFSET(6) NUMBITS(1) [],
804        STSEL1 OFFSET(8) NUMBITS(5) [],
805        STPOL1 OFFSET(14) NUMBITS(1) [],
806        STSEL2 OFFSET(16) NUMBITS(5) [],
807        STPOL2 OFFSET(2) NUMBITS(1) [],
808        STSEL3 OFFSET(24) NUMBITS(5) [],
809        STPOL3 OFFSET(30) NUMBITS(1) []
810    ],
811    IOMIRQ [
812        IOMIRQ OFFSET(0) NUMBITS(5) []
813    ],
814    GPIOOBS [
815        OBS_DATA OFFSET(0) NUMBITS(15) []
816    ],
817    ALTPADCFG [
818        PAD0_DS1 OFFSET(0) NUMBITS(1) [],
819        PAD0_SR OFFSET(4) NUMBITS(1) [],
820        PAD1_DS1 OFFSET(8) NUMBITS(1) [],
821        PAD1_SR OFFSET(12) NUMBITS(1) [],
822        PAD2_DS1 OFFSET(16) NUMBITS(1) [],
823        PAD2_SR OFFSET(20) NUMBITS(1) [],
824        PAD3_DS1 OFFSET(24) NUMBITS(1) [],
825        PAD3_SR OFFSET(28) NUMBITS(1) []
826    ],
827    SCDET [
828        SCDET OFFSET(0) NUMBITS(5) []
829    ],
830    CTENCFG [
831        EN0 OFFSET(0) NUMBITS(1) [],
832        EN1 OFFSET(1) NUMBITS(1) [],
833        EN2 OFFSET(2) NUMBITS(1) [],
834        EN3 OFFSET(3) NUMBITS(1) [],
835        EN4 OFFSET(4) NUMBITS(1) [],
836        EN5 OFFSET(5) NUMBITS(1) [],
837        EN6 OFFSET(6) NUMBITS(1) [],
838        EN7 OFFSET(7) NUMBITS(1) [],
839        EN8 OFFSET(8) NUMBITS(1) [],
840        EN9 OFFSET(9) NUMBITS(1) [],
841        EN10 OFFSET(10) NUMBITS(1) [],
842        EN11 OFFSET(11) NUMBITS(1) [],
843        EN12 OFFSET(12) NUMBITS(1) [],
844        EN13 OFFSET(13) NUMBITS(1) [],
845        EN14 OFFSET(14) NUMBITS(1) [],
846        EN15 OFFSET(15) NUMBITS(1) [],
847        EN16 OFFSET(16) NUMBITS(1) [],
848        EN17 OFFSET(17) NUMBITS(1) [],
849        EN18 OFFSET(18) NUMBITS(1) [],
850        EN19 OFFSET(19) NUMBITS(1) [],
851        EN20 OFFSET(20) NUMBITS(1) [],
852        EN21 OFFSET(21) NUMBITS(1) [],
853        EN22 OFFSET(22) NUMBITS(1) [],
854        EN23 OFFSET(23) NUMBITS(1) [],
855        EN24 OFFSET(24) NUMBITS(1) [],
856        EN25 OFFSET(25) NUMBITS(1) [],
857        EN26 OFFSET(26) NUMBITS(1) [],
858        EN27 OFFSET(27) NUMBITS(1) [],
859        EN28 OFFSET(28) NUMBITS(1) [],
860        EN29 OFFSET(29) NUMBITS(1) [],
861        EN30 OFFSET(30) NUMBITS(1) [],
862        EN31 OFFSET(31) NUMBITS(1) []
863    ],
864    INT0 [
865        GPIO0 OFFSET(0) NUMBITS(1) [],
866        GPIO1 OFFSET(1) NUMBITS(1) [],
867        GPIO2 OFFSET(2) NUMBITS(1) [],
868        GPIO3 OFFSET(3) NUMBITS(1) [],
869        GPIO4 OFFSET(4) NUMBITS(1) [],
870        GPIO5 OFFSET(5) NUMBITS(1) [],
871        GPIO6 OFFSET(6) NUMBITS(1) [],
872        GPIO7 OFFSET(7) NUMBITS(1) [],
873        GPIO8 OFFSET(8) NUMBITS(1) [],
874        GPIO9 OFFSET(9) NUMBITS(1) [],
875        GPIO10 OFFSET(10) NUMBITS(1) [],
876        GPIO11 OFFSET(11) NUMBITS(1) [],
877        GPIO12 OFFSET(12) NUMBITS(1) [],
878        GPIO13 OFFSET(13) NUMBITS(1) [],
879        GPIO14 OFFSET(14) NUMBITS(1) [],
880        GPIO15 OFFSET(15) NUMBITS(1) [],
881        GPIO16 OFFSET(16) NUMBITS(1) [],
882        GPIO17 OFFSET(17) NUMBITS(1) [],
883        GPIO18 OFFSET(18) NUMBITS(1) [],
884        GPIO19 OFFSET(19) NUMBITS(1) [],
885        GPIO20 OFFSET(20) NUMBITS(1) [],
886        GPIO21 OFFSET(21) NUMBITS(1) [],
887        GPIO22 OFFSET(22) NUMBITS(1) [],
888        GPIO23 OFFSET(23) NUMBITS(1) [],
889        GPIO24 OFFSET(24) NUMBITS(1) [],
890        GPIO25 OFFSET(25) NUMBITS(1) [],
891        GPIO26 OFFSET(26) NUMBITS(1) [],
892        GPIO27 OFFSET(27) NUMBITS(1) [],
893        GPIO28 OFFSET(28) NUMBITS(1) [],
894        GPIO29 OFFSET(29) NUMBITS(1) [],
895        GPIO30 OFFSET(30) NUMBITS(1) [],
896        GPIO31 OFFSET(31) NUMBITS(1) []
897    ],
898    INT1 [
899        GPIO32 OFFSET(0) NUMBITS(1) [],
900        GPIO33 OFFSET(1) NUMBITS(1) [],
901        GPIO34 OFFSET(2) NUMBITS(1) [],
902        GPIO35 OFFSET(3) NUMBITS(1) [],
903        GPIO36 OFFSET(4) NUMBITS(1) [],
904        GPIO37 OFFSET(5) NUMBITS(1) [],
905        GPIO38 OFFSET(6) NUMBITS(1) [],
906        GPIO39 OFFSET(7) NUMBITS(1) [],
907        GPIO40 OFFSET(8) NUMBITS(1) [],
908        GPIO41 OFFSET(9) NUMBITS(1) [],
909        GPIO42 OFFSET(10) NUMBITS(1) [],
910        GPIO43 OFFSET(11) NUMBITS(1) [],
911        GPIO44 OFFSET(12) NUMBITS(1) [],
912        GPIO45 OFFSET(13) NUMBITS(1) [],
913        GPIO46 OFFSET(14) NUMBITS(1) [],
914        GPIO47 OFFSET(15) NUMBITS(1) [],
915        GPIO48 OFFSET(16) NUMBITS(1) [],
916        GPIO49 OFFSET(17) NUMBITS(1) []
917    ]
918];
919
920pub struct GpioPin<'a> {
921    registers: StaticRef<GpioRegisters>,
922    pin: Pin,
923    client: OptionalCell<&'a dyn gpio::Client>,
924}
925
926impl<'a> GpioPin<'a> {
927    pub const fn new(base: StaticRef<GpioRegisters>, pin: Pin) -> GpioPin<'a> {
928        GpioPin {
929            registers: base,
930            pin,
931            client: OptionalCell::empty(),
932        }
933    }
934
935    pub fn handle_interrupt(&self) {
936        // Trigger the upcall
937        self.client.map(|client| {
938            client.fired();
939        });
940    }
941}
942
943impl gpio::Configure for GpioPin<'_> {
944    fn configuration(&self) -> gpio::Configuration {
945        unimplemented!();
946    }
947
948    fn set_floating_state(&self, mode: gpio::FloatingState) {
949        // Set the key
950        self.registers.padkey.set(115);
951
952        // Configure the pin as GPIO
953        let pagreg_offset = self.pin as usize / 4;
954        let pagreg_value = match self.pin as usize % 4 {
955            0 => PADREG::PAD0FNCSEL.val(0x3),
956            1 => PADREG::PAD1FNCSEL.val(0x3),
957            2 => PADREG::PAD2FNCSEL.val(0x3),
958            3 => PADREG::PAD3FNCSEL.val(0x3),
959            _ => unreachable!(),
960        };
961        self.registers.padreg[pagreg_offset].modify(pagreg_value);
962
963        match mode {
964            gpio::FloatingState::PullUp => {
965                let cfgreg_offset = self.pin as usize / 8;
966                let cfgreg_value = match self.pin as usize % 8 {
967                    0 => CFG::GPIO0OUTCFG.val(0x1),
968                    1 => CFG::GPIO1OUTCFG.val(0x1),
969                    2 => CFG::GPIO2OUTCFG.val(0x1),
970                    3 => CFG::GPIO3OUTCFG.val(0x1),
971                    4 => CFG::GPIO4OUTCFG.val(0x1),
972                    5 => CFG::GPIO5OUTCFG.val(0x1),
973                    6 => CFG::GPIO6OUTCFG.val(0x1),
974                    7 => CFG::GPIO7OUTCFG.val(0x1),
975                    _ => unreachable!(),
976                };
977                self.registers.cfg[cfgreg_offset].modify(cfgreg_value);
978
979                let pagreg_value = match self.pin as usize % 4 {
980                    0 => PADREG::PAD0PULL.val(0x1),
981                    1 => PADREG::PAD1PULL.val(0x1),
982                    2 => PADREG::PAD2PULL.val(0x1),
983                    3 => PADREG::PAD3PULL.val(0x1),
984                    _ => unreachable!(),
985                };
986                self.registers.padreg[pagreg_offset].modify(pagreg_value);
987            }
988            gpio::FloatingState::PullDown => {
989                let cfgreg_offset = self.pin as usize / 8;
990                let cfgreg_value = match self.pin as usize % 8 {
991                    0 => CFG::GPIO0OUTCFG.val(0x2),
992                    1 => CFG::GPIO1OUTCFG.val(0x2),
993                    2 => CFG::GPIO2OUTCFG.val(0x2),
994                    3 => CFG::GPIO3OUTCFG.val(0x2),
995                    4 => CFG::GPIO4OUTCFG.val(0x2),
996                    5 => CFG::GPIO5OUTCFG.val(0x2),
997                    6 => CFG::GPIO6OUTCFG.val(0x2),
998                    7 => CFG::GPIO7OUTCFG.val(0x2),
999                    _ => unreachable!(),
1000                };
1001                self.registers.cfg[cfgreg_offset].modify(cfgreg_value);
1002            }
1003            gpio::FloatingState::PullNone => {
1004                let cfgreg_offset = self.pin as usize / 8;
1005                let cfgreg_value = match self.pin as usize % 8 {
1006                    0 => CFG::GPIO0OUTCFG.val(0x3),
1007                    1 => CFG::GPIO1OUTCFG.val(0x3),
1008                    2 => CFG::GPIO2OUTCFG.val(0x3),
1009                    3 => CFG::GPIO3OUTCFG.val(0x3),
1010                    4 => CFG::GPIO4OUTCFG.val(0x3),
1011                    5 => CFG::GPIO5OUTCFG.val(0x3),
1012                    6 => CFG::GPIO6OUTCFG.val(0x3),
1013                    7 => CFG::GPIO7OUTCFG.val(0x3),
1014                    _ => unreachable!(),
1015                };
1016                self.registers.cfg[cfgreg_offset].modify(cfgreg_value);
1017
1018                let pagreg_value = match self.pin as usize % 4 {
1019                    0 => PADREG::PAD0PULL.val(0x0),
1020                    1 => PADREG::PAD1PULL.val(0x0),
1021                    2 => PADREG::PAD2PULL.val(0x0),
1022                    3 => PADREG::PAD3PULL.val(0x0),
1023                    _ => unreachable!(),
1024                };
1025                self.registers.padreg[pagreg_offset].modify(pagreg_value);
1026            }
1027        }
1028
1029        // Unset key
1030        self.registers.padkey.set(0x00);
1031    }
1032
1033    fn floating_state(&self) -> gpio::FloatingState {
1034        unimplemented!();
1035    }
1036
1037    fn deactivate_to_low_power(&self) {
1038        self.disable_input();
1039        self.disable_output();
1040    }
1041
1042    fn make_output(&self) -> gpio::Configuration {
1043        let regs = self.registers;
1044
1045        // Set the key
1046        regs.padkey.set(115);
1047
1048        // Configure the pin as GPIO
1049        let pagreg_offset = self.pin as usize / 4;
1050        let pagreg_value = match self.pin as usize % 4 {
1051            0 => PADREG::PAD0FNCSEL.val(0x3),
1052            1 => PADREG::PAD1FNCSEL.val(0x3),
1053            2 => PADREG::PAD2FNCSEL.val(0x3),
1054            3 => PADREG::PAD3FNCSEL.val(0x3),
1055            _ => unreachable!(),
1056        };
1057        regs.padreg[pagreg_offset].modify(pagreg_value);
1058
1059        // Set to push/pull
1060        let cfgreg_offset = self.pin as usize / 8;
1061        let cfgreg_value = match self.pin as usize % 8 {
1062            0 => CFG::GPIO0OUTCFG.val(0x1),
1063            1 => CFG::GPIO1OUTCFG.val(0x1),
1064            2 => CFG::GPIO2OUTCFG.val(0x1),
1065            3 => CFG::GPIO3OUTCFG.val(0x1),
1066            4 => CFG::GPIO4OUTCFG.val(0x1),
1067            5 => CFG::GPIO5OUTCFG.val(0x1),
1068            6 => CFG::GPIO6OUTCFG.val(0x1),
1069            7 => CFG::GPIO7OUTCFG.val(0x1),
1070            _ => unreachable!(),
1071        };
1072        regs.cfg[cfgreg_offset].modify(cfgreg_value);
1073
1074        // Unset key
1075        regs.padkey.set(0x00);
1076
1077        gpio::Configuration::Output
1078    }
1079
1080    fn disable_output(&self) -> gpio::Configuration {
1081        let regs = self.registers;
1082
1083        // Set the key
1084        regs.padkey.set(115);
1085
1086        // Configure the pin as GPIO
1087        let pagreg_offset = self.pin as usize / 4;
1088        let pagreg_value = match self.pin as usize % 4 {
1089            0 => PADREG::PAD0FNCSEL.val(0x3),
1090            1 => PADREG::PAD1FNCSEL.val(0x3),
1091            2 => PADREG::PAD2FNCSEL.val(0x3),
1092            3 => PADREG::PAD3FNCSEL.val(0x3),
1093            _ => unreachable!(),
1094        };
1095        regs.padreg[pagreg_offset].modify(pagreg_value);
1096
1097        // Set to disabled (GPIO mode)
1098        let cfgreg_offset = self.pin as usize / 8;
1099        let cfgreg_value = match self.pin as usize % 8 {
1100            0 => CFG::GPIO0OUTCFG.val(0x00),
1101            1 => CFG::GPIO1OUTCFG.val(0x00),
1102            2 => CFG::GPIO2OUTCFG.val(0x00),
1103            3 => CFG::GPIO3OUTCFG.val(0x00),
1104            4 => CFG::GPIO4OUTCFG.val(0x00),
1105            5 => CFG::GPIO5OUTCFG.val(0x00),
1106            6 => CFG::GPIO6OUTCFG.val(0x00),
1107            7 => CFG::GPIO7OUTCFG.val(0x00),
1108            _ => unreachable!(),
1109        };
1110        regs.cfg[cfgreg_offset].modify(cfgreg_value);
1111
1112        // Unset key
1113        regs.padkey.set(0x00);
1114
1115        gpio::Configuration::LowPower
1116    }
1117
1118    fn make_input(&self) -> gpio::Configuration {
1119        let regs = self.registers;
1120
1121        // Set the key
1122        regs.padkey.set(115);
1123
1124        // Configure the pin as GPIO with input enabled
1125        let pagreg_offset = self.pin as usize / 4;
1126        let pagreg_value = match self.pin as usize % 4 {
1127            0 => PADREG::PAD0FNCSEL.val(0x3) + PADREG::PAD0INPEN.val(0x1),
1128            1 => PADREG::PAD1FNCSEL.val(0x3) + PADREG::PAD1INPEN.val(0x1),
1129            2 => PADREG::PAD2FNCSEL.val(0x3) + PADREG::PAD2INPEN.val(0x1),
1130            3 => PADREG::PAD3FNCSEL.val(0x3) + PADREG::PAD3INPEN.val(0x1),
1131            _ => unreachable!(),
1132        };
1133        regs.padreg[pagreg_offset].modify(pagreg_value);
1134
1135        // Unset key
1136        regs.padkey.set(0x00);
1137
1138        gpio::Configuration::Input
1139    }
1140
1141    fn disable_input(&self) -> gpio::Configuration {
1142        let regs = self.registers;
1143
1144        // Set the key
1145        regs.padkey.set(115);
1146
1147        // Configure the pin as GPIO with input disabled
1148        let pagreg_offset = self.pin as usize / 4;
1149        let pagreg_value = match self.pin as usize % 4 {
1150            0 => PADREG::PAD0INPEN.val(0x0),
1151            1 => PADREG::PAD1INPEN.val(0x0),
1152            2 => PADREG::PAD2INPEN.val(0x0),
1153            3 => PADREG::PAD3INPEN.val(0x0),
1154            _ => unreachable!(),
1155        };
1156        regs.padreg[pagreg_offset].modify(pagreg_value);
1157
1158        // Unset key
1159        regs.padkey.set(0x00);
1160
1161        gpio::Configuration::Output
1162    }
1163}
1164
1165impl gpio::Input for GpioPin<'_> {
1166    fn read(&self) -> bool {
1167        let regs = self.registers;
1168
1169        if (self.pin as usize) < 32 {
1170            regs.rda.get() & (1 << self.pin as usize) != 0
1171        } else {
1172            regs.rdb.get() & (1 << (self.pin as usize - 32)) != 0
1173        }
1174    }
1175}
1176
1177impl gpio::Output for GpioPin<'_> {
1178    fn toggle(&self) -> bool {
1179        let regs = self.registers;
1180        let cur_value;
1181
1182        if (self.pin as usize) < 32 {
1183            cur_value = (regs.wtsa.get() & 1 << self.pin as usize) != 0;
1184            if cur_value {
1185                regs.wta.set(1 << self.pin as usize | regs.wtsa.get());
1186            } else {
1187                regs.wta.set(0 << self.pin as usize | regs.wtsa.get());
1188            }
1189        } else {
1190            cur_value = (regs.wtsb.get() & 1 << self.pin as usize) != 0;
1191            if cur_value {
1192                regs.wtb
1193                    .set(1 << (self.pin as usize - 32) | regs.wtsb.get());
1194            } else {
1195                regs.wtb
1196                    .set(0 << (self.pin as usize - 32) | regs.wtsb.get());
1197            }
1198        }
1199
1200        cur_value
1201    }
1202
1203    fn set(&self) {
1204        let regs = self.registers;
1205
1206        if (self.pin as usize) < 32 {
1207            regs.wtsa.set(1 << self.pin as usize);
1208        } else {
1209            regs.wtsb.set(1 << (self.pin as usize - 32));
1210        }
1211    }
1212
1213    fn clear(&self) {
1214        let regs = self.registers;
1215
1216        if (self.pin as usize) < 32 {
1217            regs.wtca.set(1 << self.pin as usize);
1218        } else {
1219            regs.wtcb.set(1 << (self.pin as usize - 32));
1220        }
1221    }
1222}
1223
1224impl<'a> gpio::Interrupt<'a> for GpioPin<'a> {
1225    fn set_client(&self, client: &'a dyn gpio::Client) {
1226        self.client.set(client);
1227    }
1228
1229    fn enable_interrupts(&self, mode: gpio::InterruptEdge) {
1230        let regs = self.registers;
1231
1232        // Set the key
1233        regs.padkey.set(115);
1234
1235        // Configure the pin as GPIO
1236        let pagreg_offset = self.pin as usize / 4;
1237        let pagreg_value = match self.pin as usize % 4 {
1238            0 => PADREG::PAD0FNCSEL.val(0x3),
1239            1 => PADREG::PAD1FNCSEL.val(0x3),
1240            2 => PADREG::PAD2FNCSEL.val(0x3),
1241            3 => PADREG::PAD2FNCSEL.val(0x3),
1242            _ => unreachable!(),
1243        };
1244        regs.padreg[pagreg_offset].modify(pagreg_value);
1245
1246        // Set the edge mode
1247        let cfgreg_offset = self.pin as usize / 8;
1248        match mode {
1249            gpio::InterruptEdge::RisingEdge => {
1250                let cfgreg_value = match self.pin as usize % 8 {
1251                    0 => CFG::GPIO0INTD::CLEAR + CFG::GPIO0INCFG::CLEAR,
1252                    1 => CFG::GPIO1INTD::CLEAR + CFG::GPIO1INCFG::CLEAR,
1253                    2 => CFG::GPIO2INTD::CLEAR + CFG::GPIO2INCFG::CLEAR,
1254                    3 => CFG::GPIO3INTD::CLEAR + CFG::GPIO3INCFG::CLEAR,
1255                    4 => CFG::GPIO4INTD::CLEAR + CFG::GPIO4INCFG::CLEAR,
1256                    5 => CFG::GPIO5INTD::CLEAR + CFG::GPIO5INCFG::CLEAR,
1257                    6 => CFG::GPIO6INTD::CLEAR + CFG::GPIO6INCFG::CLEAR,
1258                    7 => CFG::GPIO7INTD::CLEAR + CFG::GPIO7INCFG::CLEAR,
1259                    _ => unreachable!(),
1260                };
1261                regs.cfg[cfgreg_offset].modify(cfgreg_value);
1262            }
1263            gpio::InterruptEdge::FallingEdge => {
1264                let cfgreg_value = match self.pin as usize % 8 {
1265                    0 => CFG::GPIO0INTD::SET + CFG::GPIO0INCFG::CLEAR,
1266                    1 => CFG::GPIO1INTD::SET + CFG::GPIO1INCFG::CLEAR,
1267                    2 => CFG::GPIO2INTD::SET + CFG::GPIO2INCFG::CLEAR,
1268                    3 => CFG::GPIO3INTD::SET + CFG::GPIO3INCFG::CLEAR,
1269                    4 => CFG::GPIO4INTD::SET + CFG::GPIO4INCFG::CLEAR,
1270                    5 => CFG::GPIO5INTD::SET + CFG::GPIO5INCFG::CLEAR,
1271                    6 => CFG::GPIO6INTD::SET + CFG::GPIO6INCFG::CLEAR,
1272                    7 => CFG::GPIO7INTD::SET + CFG::GPIO7INCFG::CLEAR,
1273                    _ => unreachable!(),
1274                };
1275                regs.cfg[cfgreg_offset].modify(cfgreg_value);
1276            }
1277            gpio::InterruptEdge::EitherEdge => {
1278                let cfgreg_value = match self.pin as usize % 8 {
1279                    0 => CFG::GPIO0INTD::SET + CFG::GPIO0INCFG::SET,
1280                    1 => CFG::GPIO1INTD::SET + CFG::GPIO1INCFG::SET,
1281                    2 => CFG::GPIO2INTD::SET + CFG::GPIO2INCFG::SET,
1282                    3 => CFG::GPIO3INTD::SET + CFG::GPIO3INCFG::SET,
1283                    4 => CFG::GPIO4INTD::SET + CFG::GPIO4INCFG::SET,
1284                    5 => CFG::GPIO5INTD::SET + CFG::GPIO5INCFG::SET,
1285                    6 => CFG::GPIO6INTD::SET + CFG::GPIO6INCFG::SET,
1286                    7 => CFG::GPIO7INTD::SET + CFG::GPIO7INCFG::SET,
1287                    _ => unreachable!(),
1288                };
1289                regs.cfg[cfgreg_offset].modify(cfgreg_value);
1290            }
1291        }
1292
1293        // Enable interrupts
1294        if (self.pin as usize) < 32 {
1295            regs.int0en.set(1 << self.pin as usize | regs.int0en.get());
1296        } else {
1297            regs.int1en
1298                .set(1 << (self.pin as usize - 32) | regs.int1en.get());
1299        }
1300
1301        // Unset key
1302        regs.padkey.set(0x00);
1303    }
1304
1305    fn disable_interrupts(&self) {
1306        let regs = self.registers;
1307
1308        // Disable interrupt
1309        if (self.pin as usize) < 32 {
1310            regs.int0en
1311                .set(!(1 << self.pin as usize) & regs.int0en.get());
1312        } else {
1313            regs.int1en
1314                .set(!(1 << (self.pin as usize - 32)) & regs.int1en.get());
1315        }
1316
1317        // Clear interrupt
1318        if (self.pin as usize) < 32 {
1319            regs.int0clr.set(1 << self.pin as usize);
1320        } else {
1321            regs.int1clr.set(1 << (self.pin as usize - 32));
1322        }
1323    }
1324
1325    fn is_pending(&self) -> bool {
1326        let regs = self.registers;
1327
1328        regs.int0stat.get() | regs.int1stat.get() != 0
1329    }
1330}