psoc62xa/
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 OxidOS Automotive 2025 SRL.
4
5use kernel::hil::gpio::{Configuration, Configure, Input, Interrupt, Output};
6use kernel::utilities::cells::OptionalCell;
7use kernel::utilities::registers::{
8    interfaces::{ReadWriteable, Readable},
9    register_bitfields, register_structs, ReadOnly, ReadWrite,
10};
11use kernel::utilities::StaticRef;
12
13#[repr(C)]
14struct GpioPort {
15    prt_out: ReadWrite<u32, PRT_OUT::Register>,
16    prt_out_clr: ReadWrite<u32, PRT_OUT::Register>,
17    prt_out_set: ReadWrite<u32, PRT_OUT::Register>,
18    prt_out_inv: ReadWrite<u32, PRT_OUT::Register>,
19    prt_in: ReadOnly<u32, PRT_IN::Register>,
20    prt_intr: ReadWrite<u32, PRT_INTR::Register>,
21    prt_intr_mask: ReadWrite<u32, PRT_INTR::Register>,
22    prt_intr_masked: ReadOnly<u32, PRT_INTR::Register>,
23    prt_intr_set: ReadWrite<u32, PRT_INTR::Register>,
24    _reserved0: [u32; 7],
25    prt_intr_cfg: ReadWrite<u32, PRT_INTR_CFG::Register>,
26    prt_cfg: ReadWrite<u32, PRT_CFG::Register>,
27    prt_cfg_in: ReadWrite<u32, PRT_CFG_IN::Register>,
28    prt_cfg_out: ReadWrite<u32, PRT_CFG_OUT::Register>,
29    _reserved1: [u32; 12],
30}
31
32register_structs! {
33    /// GPIO port control/configuration
34    GpioRegisters {
35        (0x000 => ports: [GpioPort; 15]),
36        (0x780 => _reserved0),
37        /// Interrupt port cause register 0
38        (0x4000 => intr_cause0: ReadOnly<u32>),
39        /// Interrupt port cause register 1
40        (0x4004 => intr_cause1: ReadOnly<u32>),
41        /// Interrupt port cause register 2
42        (0x4008 => intr_cause2: ReadOnly<u32>),
43        /// Interrupt port cause register 3
44        (0x400C => intr_cause3: ReadOnly<u32>),
45        /// Extern power supply detection register
46        (0x4010 => vdd_active: ReadOnly<u32, VDD_ACTIVE::Register>),
47        /// Supply detection interrupt register
48        (0x4014 => vdd_intr: ReadWrite<u32, VDD_INTR::Register>),
49        /// Supply detection interrupt mask register
50        (0x4018 => vdd_intr_mask: ReadWrite<u32, VDD_INTR_MASK::Register>),
51        /// Supply detection interrupt masked register
52        (0x401C => vdd_intr_masked: ReadOnly<u32, VDD_INTR_MASKED::Register>),
53        /// Supply detection interrupt set register
54        (0x4020 => vdd_intr_set: ReadWrite<u32, VDD_INTR_SET::Register>),
55        (0x4024 => @END),
56    }
57}
58register_bitfields![u32,
59PRT_OUT [
60    OUT0 OFFSET(0) NUMBITS(1) [],
61    OUT1 OFFSET(1) NUMBITS(1) [],
62    OUT2 OFFSET(2) NUMBITS(1) [],
63    OUT3 OFFSET(3) NUMBITS(1) [],
64    OUT4 OFFSET(4) NUMBITS(1) [],
65    OUT5 OFFSET(5) NUMBITS(1) [],
66    OUT6 OFFSET(6) NUMBITS(1) [],
67    OUT7 OFFSET(7) NUMBITS(1) [],
68],
69PRT_IN [
70    IN0 OFFSET(0) NUMBITS(1) [],
71    IN1 OFFSET(1) NUMBITS(1) [],
72    IN2 OFFSET(2) NUMBITS(1) [],
73    IN3 OFFSET(3) NUMBITS(1) [],
74    IN4 OFFSET(4) NUMBITS(1) [],
75    IN5 OFFSET(5) NUMBITS(1) [],
76    IN6 OFFSET(6) NUMBITS(1) [],
77    IN7 OFFSET(7) NUMBITS(1) [],
78    FLT_IN OFFSET(8) NUMBITS(1) [],
79],
80PRT_INTR [
81    EDGE0 OFFSET(0) NUMBITS(1) [],
82    EDGE1 OFFSET(1) NUMBITS(1) [],
83    EDGE2 OFFSET(2) NUMBITS(1) [],
84    EDGE3 OFFSET(3) NUMBITS(1) [],
85    EDGE4 OFFSET(4) NUMBITS(1) [],
86    EDGE5 OFFSET(5) NUMBITS(1) [],
87    EDGE6 OFFSET(6) NUMBITS(1) [],
88    EDGE7 OFFSET(7) NUMBITS(1) [],
89    FLT_EDGE OFFSET(8) NUMBITS(1) [],
90    IN_IN OFFSET(16) NUMBITS(8) [],
91    FLT_IN_IN OFFSET(24) NUMBITS(1) [],
92],
93PRT_INTR_CFG [
94    EDGE_SEL0 OFFSET(0) NUMBITS(2) [],
95    EDGE_SEL1 OFFSET(2) NUMBITS(2) [],
96    EDGE_SEL2 OFFSET(4) NUMBITS(2) [],
97    EDGE_SEL3 OFFSET(6) NUMBITS(2) [],
98    EDGE_SEL4 OFFSET(8) NUMBITS(2) [],
99    EDGE_SEL5 OFFSET(10) NUMBITS(2) [],
100    EDGE_SEL6 OFFSET(12) NUMBITS(2) [],
101    EDGE_SEL7 OFFSET(14) NUMBITS(2) [],
102    FLT_EDGE_SEL OFFSET(16) NUMBITS(2) [],
103    FLT_SEL OFFSET(18) NUMBITS(3) [],
104],
105PRT_CFG [
106    DRIVE_MODE0 OFFSET(0) NUMBITS(3) [
107        HIGHZ = 0,
108        PULL_UP = 2,
109        PULL_DOWN = 3,
110        OD_DRIVESLOW = 4,
111        OD_DRIVESHIGH = 5,
112        STRONG = 6,
113        PULLUP_DOWN = 7,
114    ],
115    IN_EN0 OFFSET(3) NUMBITS(1) [],
116    DRIVE_MODE1 OFFSET(4) NUMBITS(3) [
117        HIGHZ = 0,
118        PULL_UP = 2,
119        PULL_DOWN = 3,
120        OD_DRIVESLOW = 4,
121        OD_DRIVESHIGH = 5,
122        STRONG = 6,
123        PULLUP_DOWN = 7,
124    ],
125    IN_EN1 OFFSET(7) NUMBITS(1) [],
126    DRIVE_MODE2 OFFSET(8) NUMBITS(3) [
127        HIGHZ = 0,
128        PULL_UP = 2,
129        PULL_DOWN = 3,
130        OD_DRIVESLOW = 4,
131        OD_DRIVESHIGH = 5,
132        STRONG = 6,
133        PULLUP_DOWN = 7,
134    ],
135    IN_EN2 OFFSET(11) NUMBITS(1) [],
136    DRIVE_MODE3 OFFSET(12) NUMBITS(3) [
137        HIGHZ = 0,
138        PULL_UP = 2,
139        PULL_DOWN = 3,
140        OD_DRIVESLOW = 4,
141        OD_DRIVESHIGH = 5,
142        STRONG = 6,
143        PULLUP_DOWN = 7,
144    ],
145    IN_EN3 OFFSET(15) NUMBITS(1) [],
146    DRIVE_MODE4 OFFSET(16) NUMBITS(3) [
147        HIGHZ = 0,
148        PULL_UP = 2,
149        PULL_DOWN = 3,
150        OD_DRIVESLOW = 4,
151        OD_DRIVESHIGH = 5,
152        STRONG = 6,
153        PULLUP_DOWN = 7,
154    ],
155    IN_EN4 OFFSET(19) NUMBITS(1) [],
156    DRIVE_MODE5 OFFSET(20) NUMBITS(3) [
157        HIGHZ = 0,
158        PULL_UP = 2,
159        PULL_DOWN = 3,
160        OD_DRIVESLOW = 4,
161        OD_DRIVESHIGH = 5,
162        STRONG = 6,
163        PULLUP_DOWN = 7,
164    ],
165    IN_EN5 OFFSET(23) NUMBITS(1) [],
166    DRIVE_MODE6 OFFSET(24) NUMBITS(3) [
167        HIGHZ = 0,
168        PULL_UP = 2,
169        PULL_DOWN = 3,
170        OD_DRIVESLOW = 4,
171        OD_DRIVESHIGH = 5,
172        STRONG = 6,
173        PULLUP_DOWN = 7,
174    ],
175    IN_EN6 OFFSET(27) NUMBITS(1) [],
176    DRIVE_MODE7 OFFSET(28) NUMBITS(3) [
177        HIGHZ = 0,
178        PULL_UP = 2,
179        PULL_DOWN = 3,
180        OD_DRIVESLOW = 4,
181        OD_DRIVESHIGH = 5,
182        STRONG = 6,
183        PULLUP_DOWN = 7,
184    ],
185    IN_EN7 OFFSET(31) NUMBITS(1) [],
186],
187PRT_CFG_IN [
188    VTRIP_VTRIP_SEL_0 OFFSET(0) NUMBITS(1) [],
189    VTRIP_VTRIP_SEL_1 OFFSET(1) NUMBITS(1) [],
190    VTRIP_VTRIP_SEL_2 OFFSET(2) NUMBITS(1) [],
191    VTRIP_VTRIP_SEL_3 OFFSET(3) NUMBITS(1) [],
192    VTRIP_VTRIP_SEL_4 OFFSET(4) NUMBITS(1) [],
193    VTRIP_VTRIP_SEL_5 OFFSET(5) NUMBITS(1) [],
194    VTRIP_VTRIP_SEL_6 OFFSET(6) NUMBITS(1) [],
195    VTRIP_VTRIP_SEL_7 OFFSET(7) NUMBITS(1) [],
196],
197PRT_CFG_OUT [
198    SLOW0 OFFSET(0) NUMBITS(1) [],
199    SLOW1 OFFSET(0) NUMBITS(1) [],
200    SLOW2 OFFSET(0) NUMBITS(1) [],
201    SLOW3 OFFSET(0) NUMBITS(1) [],
202    SLOW4 OFFSET(0) NUMBITS(1) [],
203    SLOW5 OFFSET(0) NUMBITS(1) [],
204    SLOW6 OFFSET(0) NUMBITS(1) [],
205    SLOW7 OFFSET(0) NUMBITS(1) [],
206    DRIVE_SEL0 OFFSET(16) NUMBITS(2) [],
207    DRIVE_SEL1 OFFSET(18) NUMBITS(2) [],
208    DRIVE_SEL2 OFFSET(20) NUMBITS(2) [],
209    DRIVE_SEL3 OFFSET(22) NUMBITS(2) [],
210    DRIVE_SEL4 OFFSET(24) NUMBITS(2) [],
211    DRIVE_SEL5 OFFSET(26) NUMBITS(2) [],
212    DRIVE_SEL6 OFFSET(28) NUMBITS(2) [],
213    DRIVE_SEL7 OFFSET(30) NUMBITS(2) [],
214],
215INTR_CAUSE0 [
216    PORT_INT OFFSET(0) NUMBITS(32) []
217],
218INTR_CAUSE1 [
219    PORT_INT OFFSET(0) NUMBITS(32) []
220],
221INTR_CAUSE2 [
222    PORT_INT OFFSET(0) NUMBITS(32) []
223],
224INTR_CAUSE3 [
225    PORT_INT OFFSET(0) NUMBITS(32) []
226],
227VDD_ACTIVE [
228    VDDIO_ACTIVE OFFSET(0) NUMBITS(16) [],
229    VDDA_ACTIVE OFFSET(30) NUMBITS(1) [],
230    VDDD_ACTIVE OFFSET(31) NUMBITS(1) []
231],
232VDD_INTR [
233    VDDIO_ACTIVE OFFSET(0) NUMBITS(16) [],
234    VDDA_ACTIVE OFFSET(30) NUMBITS(1) [],
235    VDDD_ACTIVE OFFSET(31) NUMBITS(1) []
236],
237VDD_INTR_MASK [
238    VDDIO_ACTIVE OFFSET(0) NUMBITS(16) [],
239    VDDA_ACTIVE OFFSET(30) NUMBITS(1) [],
240    VDDD_ACTIVE OFFSET(31) NUMBITS(1) []
241],
242VDD_INTR_MASKED [
243    VDDIO_ACTIVE OFFSET(0) NUMBITS(16) [],
244    VDDA_ACTIVE OFFSET(30) NUMBITS(1) [],
245    VDDD_ACTIVE OFFSET(31) NUMBITS(1) []
246],
247VDD_INTR_SET [
248    VDDIO_ACTIVE OFFSET(0) NUMBITS(16) [],
249    VDDA_ACTIVE OFFSET(30) NUMBITS(1) [],
250    VDDD_ACTIVE OFFSET(31) NUMBITS(1) []
251]
252];
253const GPIO_BASE: StaticRef<GpioRegisters> =
254    unsafe { StaticRef::new(0x40310000 as *const GpioRegisters) };
255
256const HIGHZ: u32 = 0;
257const PULL_UP: u32 = 2;
258const PULL_DOWN: u32 = 3;
259
260#[derive(Clone, Copy, Debug)]
261pub enum PsocPin {
262    P0_0 = 0,
263    P0_1 = 1,
264    P0_2 = 2,
265    P0_3 = 3,
266    P0_4 = 4,
267    P0_5 = 5,
268    P1_0 = 8,
269    P1_1 = 9,
270    P1_2 = 10,
271    P1_3 = 11,
272    P1_4 = 12,
273    P1_5 = 13,
274    P2_0 = 16,
275    P2_1 = 17,
276    P2_2 = 18,
277    P2_3 = 19,
278    P2_4 = 20,
279    P2_5 = 21,
280    P2_6 = 22,
281    P2_7 = 23,
282    P3_0 = 24,
283    P3_1 = 25,
284    P3_2 = 26,
285    P3_3 = 27,
286    P3_4 = 28,
287    P3_5 = 29,
288    P4_0 = 32,
289    P4_1 = 33,
290    P4_2 = 34,
291    P4_3 = 35,
292    P5_0 = 40,
293    P5_1 = 41,
294    P5_2 = 42,
295    P5_3 = 43,
296    P5_4 = 44,
297    P5_5 = 45,
298    P5_6 = 46,
299    P5_7 = 47,
300    P6_0 = 48,
301    P6_1 = 49,
302    P6_2 = 50,
303    P6_3 = 51,
304    P6_4 = 52,
305    P6_5 = 53,
306    P6_6 = 54,
307    P6_7 = 55,
308    P7_0 = 56,
309    P7_1 = 57,
310    P7_2 = 58,
311    P7_3 = 59,
312    P7_4 = 60,
313    P7_5 = 61,
314    P7_6 = 62,
315    P7_7 = 63,
316    P8_0 = 64,
317    P8_1 = 65,
318    P8_2 = 66,
319    P8_3 = 67,
320    P8_4 = 68,
321    P8_5 = 69,
322    P8_6 = 70,
323    P8_7 = 71,
324    P9_0 = 72,
325    P9_1 = 73,
326    P9_2 = 74,
327    P9_3 = 75,
328    P9_4 = 76,
329    P9_5 = 77,
330    P9_6 = 78,
331    P9_7 = 79,
332    P10_0 = 80,
333    P10_1 = 81,
334    P10_2 = 82,
335    P10_3 = 83,
336    P10_4 = 84,
337    P10_5 = 85,
338    P10_6 = 86,
339    P10_7 = 87,
340    P11_0 = 88,
341    P11_1 = 89,
342    P11_2 = 90,
343    P11_3 = 91,
344    P11_4 = 92,
345    P11_5 = 93,
346    P11_6 = 94,
347    P11_7 = 95,
348    P12_0 = 96,
349    P12_1 = 97,
350    P12_2 = 98,
351    P12_3 = 99,
352    P12_4 = 100,
353    P12_5 = 101,
354    P12_6 = 102,
355    P12_7 = 103,
356    P13_0 = 104,
357    P13_1 = 105,
358    P13_2 = 106,
359    P13_3 = 107,
360    P13_4 = 108,
361    P13_5 = 109,
362    P13_6 = 110,
363    P13_7 = 111,
364}
365
366pub struct PsocPins<'a> {
367    pub pins: [Option<GpioPin<'a>>; 112],
368}
369
370impl<'a> PsocPins<'a> {
371    pub const fn new() -> Self {
372        Self {
373            pins: [
374                Some(GpioPin::new(PsocPin::P0_0)),
375                Some(GpioPin::new(PsocPin::P0_1)),
376                Some(GpioPin::new(PsocPin::P0_2)),
377                Some(GpioPin::new(PsocPin::P0_3)),
378                Some(GpioPin::new(PsocPin::P0_4)),
379                Some(GpioPin::new(PsocPin::P0_5)),
380                None,
381                None,
382                Some(GpioPin::new(PsocPin::P1_0)),
383                Some(GpioPin::new(PsocPin::P1_1)),
384                Some(GpioPin::new(PsocPin::P1_2)),
385                Some(GpioPin::new(PsocPin::P1_3)),
386                Some(GpioPin::new(PsocPin::P1_4)),
387                Some(GpioPin::new(PsocPin::P1_5)),
388                None,
389                None,
390                Some(GpioPin::new(PsocPin::P2_0)),
391                Some(GpioPin::new(PsocPin::P2_1)),
392                Some(GpioPin::new(PsocPin::P2_2)),
393                Some(GpioPin::new(PsocPin::P2_3)),
394                Some(GpioPin::new(PsocPin::P2_4)),
395                Some(GpioPin::new(PsocPin::P2_5)),
396                Some(GpioPin::new(PsocPin::P2_6)),
397                Some(GpioPin::new(PsocPin::P2_7)),
398                Some(GpioPin::new(PsocPin::P3_0)),
399                Some(GpioPin::new(PsocPin::P3_1)),
400                Some(GpioPin::new(PsocPin::P3_2)),
401                Some(GpioPin::new(PsocPin::P3_3)),
402                Some(GpioPin::new(PsocPin::P3_4)),
403                Some(GpioPin::new(PsocPin::P3_5)),
404                None,
405                None,
406                Some(GpioPin::new(PsocPin::P4_0)),
407                Some(GpioPin::new(PsocPin::P4_1)),
408                Some(GpioPin::new(PsocPin::P4_2)),
409                Some(GpioPin::new(PsocPin::P4_3)),
410                None,
411                None,
412                None,
413                None,
414                Some(GpioPin::new(PsocPin::P5_0)),
415                Some(GpioPin::new(PsocPin::P5_1)),
416                Some(GpioPin::new(PsocPin::P5_2)),
417                Some(GpioPin::new(PsocPin::P5_3)),
418                Some(GpioPin::new(PsocPin::P5_4)),
419                Some(GpioPin::new(PsocPin::P5_5)),
420                Some(GpioPin::new(PsocPin::P5_6)),
421                Some(GpioPin::new(PsocPin::P5_7)),
422                Some(GpioPin::new(PsocPin::P6_0)),
423                Some(GpioPin::new(PsocPin::P6_1)),
424                Some(GpioPin::new(PsocPin::P6_2)),
425                Some(GpioPin::new(PsocPin::P6_3)),
426                Some(GpioPin::new(PsocPin::P6_4)),
427                Some(GpioPin::new(PsocPin::P6_5)),
428                Some(GpioPin::new(PsocPin::P6_6)),
429                Some(GpioPin::new(PsocPin::P6_7)),
430                Some(GpioPin::new(PsocPin::P7_0)),
431                Some(GpioPin::new(PsocPin::P7_1)),
432                Some(GpioPin::new(PsocPin::P7_2)),
433                Some(GpioPin::new(PsocPin::P7_3)),
434                Some(GpioPin::new(PsocPin::P7_4)),
435                Some(GpioPin::new(PsocPin::P7_5)),
436                Some(GpioPin::new(PsocPin::P7_6)),
437                Some(GpioPin::new(PsocPin::P7_7)),
438                Some(GpioPin::new(PsocPin::P8_0)),
439                Some(GpioPin::new(PsocPin::P8_1)),
440                Some(GpioPin::new(PsocPin::P8_2)),
441                Some(GpioPin::new(PsocPin::P8_3)),
442                Some(GpioPin::new(PsocPin::P8_4)),
443                Some(GpioPin::new(PsocPin::P8_5)),
444                Some(GpioPin::new(PsocPin::P8_6)),
445                Some(GpioPin::new(PsocPin::P8_7)),
446                Some(GpioPin::new(PsocPin::P9_0)),
447                Some(GpioPin::new(PsocPin::P9_1)),
448                Some(GpioPin::new(PsocPin::P9_2)),
449                Some(GpioPin::new(PsocPin::P9_3)),
450                Some(GpioPin::new(PsocPin::P9_4)),
451                Some(GpioPin::new(PsocPin::P9_5)),
452                Some(GpioPin::new(PsocPin::P9_6)),
453                Some(GpioPin::new(PsocPin::P9_7)),
454                Some(GpioPin::new(PsocPin::P10_0)),
455                Some(GpioPin::new(PsocPin::P10_1)),
456                Some(GpioPin::new(PsocPin::P10_2)),
457                Some(GpioPin::new(PsocPin::P10_3)),
458                Some(GpioPin::new(PsocPin::P10_4)),
459                Some(GpioPin::new(PsocPin::P10_5)),
460                Some(GpioPin::new(PsocPin::P10_6)),
461                Some(GpioPin::new(PsocPin::P10_7)),
462                Some(GpioPin::new(PsocPin::P11_0)),
463                Some(GpioPin::new(PsocPin::P11_1)),
464                Some(GpioPin::new(PsocPin::P11_2)),
465                Some(GpioPin::new(PsocPin::P11_3)),
466                Some(GpioPin::new(PsocPin::P11_4)),
467                Some(GpioPin::new(PsocPin::P11_5)),
468                Some(GpioPin::new(PsocPin::P11_6)),
469                Some(GpioPin::new(PsocPin::P11_7)),
470                Some(GpioPin::new(PsocPin::P12_0)),
471                Some(GpioPin::new(PsocPin::P12_1)),
472                Some(GpioPin::new(PsocPin::P12_2)),
473                Some(GpioPin::new(PsocPin::P12_3)),
474                Some(GpioPin::new(PsocPin::P12_4)),
475                Some(GpioPin::new(PsocPin::P12_5)),
476                Some(GpioPin::new(PsocPin::P12_6)),
477                Some(GpioPin::new(PsocPin::P12_7)),
478                Some(GpioPin::new(PsocPin::P13_0)),
479                Some(GpioPin::new(PsocPin::P13_1)),
480                Some(GpioPin::new(PsocPin::P13_2)),
481                Some(GpioPin::new(PsocPin::P13_3)),
482                Some(GpioPin::new(PsocPin::P13_4)),
483                Some(GpioPin::new(PsocPin::P13_5)),
484                Some(GpioPin::new(PsocPin::P13_6)),
485                Some(GpioPin::new(PsocPin::P13_7)),
486            ],
487        }
488    }
489
490    pub fn get_pin(&self, searched_pin: PsocPin) -> &'a GpioPin {
491        self.pins[searched_pin as usize].as_ref().unwrap()
492    }
493
494    pub fn handle_interrupt(&self) {
495        for pin in self.pins.iter() {
496            pin.as_ref().inspect(|pin| pin.handle_interrupt());
497        }
498    }
499}
500
501pub enum DriveMode {
502    HighZ = 0,
503    // Reserved = 1,
504    PullUp = 2,
505    PullDown = 3,
506    OpenDrainLow = 4,
507    OpenDrainHigh = 5,
508    Strong = 6,
509    PullUpDown = 7,
510}
511
512pub struct GpioPin<'a> {
513    registers: StaticRef<GpioRegisters>,
514    pin: usize,
515    port: usize,
516
517    client: OptionalCell<&'a dyn kernel::hil::gpio::Client>,
518}
519
520impl GpioPin<'_> {
521    pub const fn new(id: PsocPin) -> Self {
522        Self {
523            registers: GPIO_BASE,
524            pin: (id as usize) % 8,
525            port: (id as usize) / 8,
526            client: OptionalCell::empty(),
527        }
528    }
529
530    pub fn get_configuration(&self) -> Configuration {
531        let (input_buffer, high_impedance) = if self.pin == 0 {
532            (
533                self.registers.ports[self.port]
534                    .prt_cfg
535                    .is_set(PRT_CFG::IN_EN0),
536                self.registers.ports[self.port]
537                    .prt_cfg
538                    .read(PRT_CFG::DRIVE_MODE0)
539                    == HIGHZ,
540            )
541        } else if self.pin == 1 {
542            (
543                self.registers.ports[self.port]
544                    .prt_cfg
545                    .is_set(PRT_CFG::IN_EN1),
546                self.registers.ports[self.port]
547                    .prt_cfg
548                    .read(PRT_CFG::DRIVE_MODE1)
549                    == HIGHZ,
550            )
551        } else if self.pin == 2 {
552            (
553                self.registers.ports[self.port]
554                    .prt_cfg
555                    .is_set(PRT_CFG::IN_EN2),
556                self.registers.ports[self.port]
557                    .prt_cfg
558                    .read(PRT_CFG::DRIVE_MODE2)
559                    == HIGHZ,
560            )
561        } else if self.pin == 3 {
562            (
563                self.registers.ports[self.port]
564                    .prt_cfg
565                    .is_set(PRT_CFG::IN_EN3),
566                self.registers.ports[self.port]
567                    .prt_cfg
568                    .read(PRT_CFG::DRIVE_MODE3)
569                    == HIGHZ,
570            )
571        } else if self.pin == 4 {
572            (
573                self.registers.ports[self.port]
574                    .prt_cfg
575                    .is_set(PRT_CFG::IN_EN4),
576                self.registers.ports[self.port]
577                    .prt_cfg
578                    .read(PRT_CFG::DRIVE_MODE4)
579                    == HIGHZ,
580            )
581        } else if self.pin == 5 {
582            (
583                self.registers.ports[self.port]
584                    .prt_cfg
585                    .is_set(PRT_CFG::IN_EN5),
586                self.registers.ports[self.port]
587                    .prt_cfg
588                    .read(PRT_CFG::DRIVE_MODE5)
589                    == HIGHZ,
590            )
591        } else if self.pin == 6 {
592            (
593                self.registers.ports[self.port]
594                    .prt_cfg
595                    .is_set(PRT_CFG::IN_EN6),
596                self.registers.ports[self.port]
597                    .prt_cfg
598                    .read(PRT_CFG::DRIVE_MODE6)
599                    == HIGHZ,
600            )
601        } else {
602            (
603                self.registers.ports[self.port]
604                    .prt_cfg
605                    .is_set(PRT_CFG::IN_EN7),
606                self.registers.ports[self.port]
607                    .prt_cfg
608                    .read(PRT_CFG::DRIVE_MODE7)
609                    == HIGHZ,
610            )
611        };
612        match (input_buffer, high_impedance) {
613            (false, false) => Configuration::Output,
614            (false, true) => Configuration::LowPower,
615            (true, true) => Configuration::Input,
616            (true, false) => Configuration::InputOutput,
617        }
618    }
619
620    pub fn configure_drive_mode(&self, drive_mode: DriveMode) {
621        if self.pin == 0 {
622            self.registers.ports[self.port]
623                .prt_cfg
624                .modify(PRT_CFG::DRIVE_MODE0.val(drive_mode as u32));
625        } else if self.pin == 1 {
626            self.registers.ports[self.port]
627                .prt_cfg
628                .modify(PRT_CFG::DRIVE_MODE1.val(drive_mode as u32));
629        } else if self.pin == 2 {
630            self.registers.ports[self.port]
631                .prt_cfg
632                .modify(PRT_CFG::DRIVE_MODE2.val(drive_mode as u32));
633        } else if self.pin == 3 {
634            self.registers.ports[self.port]
635                .prt_cfg
636                .modify(PRT_CFG::DRIVE_MODE3.val(drive_mode as u32));
637        } else if self.pin == 4 {
638            self.registers.ports[self.port]
639                .prt_cfg
640                .modify(PRT_CFG::DRIVE_MODE4.val(drive_mode as u32));
641        } else if self.pin == 5 {
642            self.registers.ports[self.port]
643                .prt_cfg
644                .modify(PRT_CFG::DRIVE_MODE5.val(drive_mode as u32));
645        } else if self.pin == 6 {
646            self.registers.ports[self.port]
647                .prt_cfg
648                .modify(PRT_CFG::DRIVE_MODE6.val(drive_mode as u32));
649        } else {
650            self.registers.ports[self.port]
651                .prt_cfg
652                .modify(PRT_CFG::DRIVE_MODE7.val(drive_mode as u32));
653        }
654    }
655
656    pub fn configure_input(&self, input_enable: bool) {
657        if self.pin == 0 {
658            self.registers.ports[self.port]
659                .prt_cfg
660                .modify(PRT_CFG::IN_EN0.val(input_enable as u32));
661        } else if self.pin == 1 {
662            self.registers.ports[self.port]
663                .prt_cfg
664                .modify(PRT_CFG::IN_EN1.val(input_enable as u32));
665        } else if self.pin == 2 {
666            self.registers.ports[self.port]
667                .prt_cfg
668                .modify(PRT_CFG::IN_EN2.val(input_enable as u32));
669        } else if self.pin == 3 {
670            self.registers.ports[self.port]
671                .prt_cfg
672                .modify(PRT_CFG::IN_EN3.val(input_enable as u32));
673        } else if self.pin == 4 {
674            self.registers.ports[self.port]
675                .prt_cfg
676                .modify(PRT_CFG::IN_EN4.val(input_enable as u32));
677        } else if self.pin == 5 {
678            self.registers.ports[self.port]
679                .prt_cfg
680                .modify(PRT_CFG::IN_EN5.val(input_enable as u32));
681        } else if self.pin == 6 {
682            self.registers.ports[self.port]
683                .prt_cfg
684                .modify(PRT_CFG::IN_EN6.val(input_enable as u32));
685        } else {
686            self.registers.ports[self.port]
687                .prt_cfg
688                .modify(PRT_CFG::IN_EN7.val(input_enable as u32));
689        }
690    }
691
692    pub fn handle_interrupt(&self) {
693        if self.is_pending() {
694            let bitfield = match self.pin {
695                0 => PRT_INTR::EDGE0,
696                1 => PRT_INTR::EDGE1,
697                2 => PRT_INTR::EDGE2,
698                3 => PRT_INTR::EDGE3,
699                4 => PRT_INTR::EDGE4,
700                5 => PRT_INTR::EDGE5,
701                6 => PRT_INTR::EDGE6,
702                _ => PRT_INTR::EDGE7,
703            };
704            self.registers.ports[self.port]
705                .prt_intr
706                .modify(bitfield.val(1));
707            self.client.map(|client| client.fired());
708        }
709    }
710}
711
712impl Input for GpioPin<'_> {
713    fn read(&self) -> bool {
714        match self.get_configuration() {
715            Configuration::Input => {
716                let bitfield = match self.pin {
717                    0 => PRT_IN::IN0,
718                    1 => PRT_IN::IN1,
719                    2 => PRT_IN::IN2,
720                    3 => PRT_IN::IN3,
721                    4 => PRT_IN::IN4,
722                    5 => PRT_IN::IN5,
723                    6 => PRT_IN::IN6,
724                    _ => PRT_IN::IN7,
725                };
726                self.registers.ports[self.port].prt_in.is_set(bitfield)
727            }
728            Configuration::Output => {
729                let bitfield = match self.pin {
730                    0 => PRT_OUT::OUT0,
731                    1 => PRT_OUT::OUT1,
732                    2 => PRT_OUT::OUT2,
733                    3 => PRT_OUT::OUT3,
734                    4 => PRT_OUT::OUT4,
735                    5 => PRT_OUT::OUT5,
736                    6 => PRT_OUT::OUT6,
737                    _ => PRT_OUT::OUT7,
738                };
739                self.registers.ports[self.port].prt_out.is_set(bitfield)
740            }
741            _ => false,
742        }
743    }
744}
745
746impl Output for GpioPin<'_> {
747    fn set(&self) {
748        match self.get_configuration() {
749            Configuration::Output | Configuration::InputOutput => {
750                let bitfield = match self.pin {
751                    0 => PRT_OUT::OUT0,
752                    1 => PRT_OUT::OUT1,
753                    2 => PRT_OUT::OUT2,
754                    3 => PRT_OUT::OUT3,
755                    4 => PRT_OUT::OUT4,
756                    5 => PRT_OUT::OUT5,
757                    6 => PRT_OUT::OUT6,
758                    _ => PRT_OUT::OUT7,
759                };
760                self.registers.ports[self.port]
761                    .prt_out
762                    .modify(bitfield.val(1));
763            }
764            _ => (),
765        }
766    }
767
768    fn clear(&self) {
769        match self.get_configuration() {
770            Configuration::Output | Configuration::InputOutput => {
771                let bitfield = match self.pin {
772                    0 => PRT_OUT::OUT0,
773                    1 => PRT_OUT::OUT1,
774                    2 => PRT_OUT::OUT2,
775                    3 => PRT_OUT::OUT3,
776                    4 => PRT_OUT::OUT4,
777                    5 => PRT_OUT::OUT5,
778                    6 => PRT_OUT::OUT6,
779                    _ => PRT_OUT::OUT7,
780                };
781                self.registers.ports[self.port]
782                    .prt_out
783                    .modify(bitfield.val(0));
784            }
785            _ => (),
786        }
787    }
788
789    fn toggle(&self) -> bool {
790        if self.read() {
791            self.clear();
792            false
793        } else {
794            self.set();
795            true
796        }
797    }
798}
799
800impl Configure for GpioPin<'_> {
801    fn configuration(&self) -> Configuration {
802        self.get_configuration()
803    }
804
805    fn make_input(&self) -> Configuration {
806        self.configure_input(true);
807        self.get_configuration()
808    }
809
810    fn disable_input(&self) -> Configuration {
811        self.configure_input(false);
812        self.get_configuration()
813    }
814
815    fn make_output(&self) -> Configuration {
816        self.configure_drive_mode(DriveMode::Strong);
817        self.get_configuration()
818    }
819
820    fn disable_output(&self) -> Configuration {
821        self.configure_drive_mode(DriveMode::HighZ);
822        self.get_configuration()
823    }
824
825    fn set_floating_state(&self, state: kernel::hil::gpio::FloatingState) {
826        match state {
827            kernel::hil::gpio::FloatingState::PullUp => {
828                self.configure_drive_mode(DriveMode::PullUp);
829                self.set();
830            }
831            kernel::hil::gpio::FloatingState::PullDown => {
832                self.configure_drive_mode(DriveMode::PullDown);
833                self.clear();
834            }
835            kernel::hil::gpio::FloatingState::PullNone => {
836                self.configure_drive_mode(DriveMode::HighZ)
837            }
838        }
839    }
840
841    fn deactivate_to_low_power(&self) {
842        self.configure_drive_mode(DriveMode::HighZ);
843        self.configure_input(false);
844    }
845
846    fn floating_state(&self) -> kernel::hil::gpio::FloatingState {
847        let drive_mode = if self.pin == 0 {
848            self.registers.ports[self.port]
849                .prt_cfg
850                .read(PRT_CFG::DRIVE_MODE0)
851        } else if self.pin == 1 {
852            self.registers.ports[self.port]
853                .prt_cfg
854                .read(PRT_CFG::DRIVE_MODE1)
855        } else if self.pin == 2 {
856            self.registers.ports[self.port]
857                .prt_cfg
858                .read(PRT_CFG::DRIVE_MODE2)
859        } else if self.pin == 3 {
860            self.registers.ports[self.port]
861                .prt_cfg
862                .read(PRT_CFG::DRIVE_MODE3)
863        } else if self.pin == 4 {
864            self.registers.ports[self.port]
865                .prt_cfg
866                .read(PRT_CFG::DRIVE_MODE4)
867        } else if self.pin == 5 {
868            self.registers.ports[self.port]
869                .prt_cfg
870                .read(PRT_CFG::DRIVE_MODE5)
871        } else if self.pin == 6 {
872            self.registers.ports[self.port]
873                .prt_cfg
874                .read(PRT_CFG::DRIVE_MODE6)
875        } else {
876            self.registers.ports[self.port]
877                .prt_cfg
878                .read(PRT_CFG::DRIVE_MODE7)
879        };
880        if drive_mode == PULL_UP {
881            kernel::hil::gpio::FloatingState::PullUp
882        } else if drive_mode == PULL_DOWN {
883            kernel::hil::gpio::FloatingState::PullDown
884        } else {
885            kernel::hil::gpio::FloatingState::PullNone
886        }
887    }
888}
889
890impl<'a> Interrupt<'a> for GpioPin<'a> {
891    fn set_client(&self, client: &'a dyn kernel::hil::gpio::Client) {
892        self.client.set(client);
893    }
894
895    fn enable_interrupts(&self, mode: kernel::hil::gpio::InterruptEdge) {
896        let edge_value = match mode {
897            kernel::hil::gpio::InterruptEdge::RisingEdge => 1,
898            kernel::hil::gpio::InterruptEdge::FallingEdge => 2,
899            kernel::hil::gpio::InterruptEdge::EitherEdge => 3,
900        };
901        if self.pin == 0 {
902            self.registers.ports[self.port]
903                .prt_intr_cfg
904                .modify(PRT_INTR_CFG::EDGE_SEL0.val(edge_value));
905        } else if self.pin == 1 {
906            self.registers.ports[self.port]
907                .prt_intr_cfg
908                .modify(PRT_INTR_CFG::EDGE_SEL1.val(edge_value));
909        } else if self.pin == 2 {
910            self.registers.ports[self.port]
911                .prt_intr_cfg
912                .modify(PRT_INTR_CFG::EDGE_SEL2.val(edge_value));
913        } else if self.pin == 3 {
914            self.registers.ports[self.port]
915                .prt_intr_cfg
916                .modify(PRT_INTR_CFG::EDGE_SEL3.val(edge_value));
917        } else if self.pin == 4 {
918            self.registers.ports[self.port]
919                .prt_intr_cfg
920                .modify(PRT_INTR_CFG::EDGE_SEL4.val(edge_value));
921        } else if self.pin == 5 {
922            self.registers.ports[self.port]
923                .prt_intr_cfg
924                .modify(PRT_INTR_CFG::EDGE_SEL5.val(edge_value));
925        } else if self.pin == 6 {
926            self.registers.ports[self.port]
927                .prt_intr_cfg
928                .modify(PRT_INTR_CFG::EDGE_SEL6.val(edge_value));
929        } else {
930            self.registers.ports[self.port]
931                .prt_intr_cfg
932                .modify(PRT_INTR_CFG::EDGE_SEL7.val(edge_value));
933        }
934        let bitfield = match self.pin {
935            0 => PRT_INTR::EDGE0,
936            1 => PRT_INTR::EDGE1,
937            2 => PRT_INTR::EDGE2,
938            3 => PRT_INTR::EDGE3,
939            4 => PRT_INTR::EDGE4,
940            5 => PRT_INTR::EDGE5,
941            6 => PRT_INTR::EDGE6,
942            _ => PRT_INTR::EDGE7,
943        };
944        self.registers.ports[self.port]
945            .prt_intr_mask
946            .modify(bitfield.val(1));
947    }
948
949    fn disable_interrupts(&self) {
950        let bitfield = match self.pin {
951            0 => PRT_INTR::EDGE0,
952            1 => PRT_INTR::EDGE1,
953            2 => PRT_INTR::EDGE2,
954            3 => PRT_INTR::EDGE3,
955            4 => PRT_INTR::EDGE4,
956            5 => PRT_INTR::EDGE5,
957            6 => PRT_INTR::EDGE6,
958            _ => PRT_INTR::EDGE7,
959        };
960        self.registers.ports[self.port]
961            .prt_intr_mask
962            .modify(bitfield.val(0));
963    }
964
965    fn is_pending(&self) -> bool {
966        let bitfield = match self.pin {
967            0 => PRT_INTR::EDGE0,
968            1 => PRT_INTR::EDGE1,
969            2 => PRT_INTR::EDGE2,
970            3 => PRT_INTR::EDGE3,
971            4 => PRT_INTR::EDGE4,
972            5 => PRT_INTR::EDGE5,
973            6 => PRT_INTR::EDGE6,
974            _ => PRT_INTR::EDGE7,
975        };
976        self.registers.ports[self.port].prt_intr.is_set(bitfield)
977    }
978}