rp2350/
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.
4
5use enum_primitive::cast::FromPrimitive;
6use enum_primitive::enum_from_primitive;
7use kernel::hil;
8use kernel::utilities::cells::OptionalCell;
9use kernel::utilities::registers::{
10    interfaces::{ReadWriteable, Readable, Writeable},
11    register_bitfields, register_structs, ReadOnly, ReadWrite,
12};
13use kernel::utilities::StaticRef;
14
15use crate::chip::Processor;
16#[repr(C)]
17struct GpioPin {
18    status: ReadOnly<u32, GPIOx_STATUS::Register>,
19    ctrl: ReadWrite<u32, GPIOx_CTRL::Register>,
20}
21
22#[repr(C)]
23struct GpioProc {
24    enable: [ReadWrite<u32, GPIO_INTRxx::Register>; 6],
25    force: [ReadWrite<u32, GPIO_INTRxx::Register>; 6],
26    status: [ReadWrite<u32, GPIO_INTRxx::Register>; 6],
27}
28
29register_structs! {
30
31    GpioRegisters {
32        (0x000 => pin: [GpioPin; 48]),
33        (0x180 => _reserved0),
34
35        (0x200 => irqsummary_proc0_secure0: ReadWrite<u32, IRQSUMMARY_PROC0::Register>),
36
37        (0x204 => irqsummary_proc0_secure1: ReadWrite<u32, IRQSUMMARY_PROC0::Register>),
38
39        (0x208 => irqsummary_proc0_nonsecure0: ReadWrite<u32, IRQSUMMARY_PROC0::Register>),
40
41        (0x20C => irqsummary_proc0_nonsecure1: ReadWrite<u32, IRQSUMMARY_PROC0::Register>),
42
43        (0x210 => irqsummary_proc1_secure0: ReadWrite<u32, IRQSUMMARY_PROC1::Register>),
44
45        (0x214 => irqsummary_proc1_secure1: ReadWrite<u32, IRQSUMMARY_PROC1::Register>),
46
47        (0x218 => irqsummary_proc1_nonsecure0: ReadWrite<u32, IRQSUMMARY_PROC1::Register>),
48
49        (0x21C => irqsummary_proc1_nonsecure1: ReadWrite<u32, IRQSUMMARY_PROC1::Register>),
50
51        (0x220 => irqsummary_dormant_wake_secure0: ReadWrite<u32, IRQSUMMARY_PROC0::Register>),
52
53        (0x224 => irqsummary_dormant_wake_secure1: ReadWrite<u32, IRQSUMMARY_PROC1::Register>),
54
55        (0x228 => irqsummary_dormant_wake_nonsecure0: ReadWrite<u32, IRQSUMMARY_PROC0::Register>),
56
57        (0x22C => irqsummary_dormant_wake_nonsecure1: ReadWrite<u32, IRQSUMMARY_PROC1::Register>),
58        /// Raw Interrupts
59        (0x230 => intr: [ReadWrite<u32, GPIO_INTRxx::Register>; 6]),
60        /// Interrupts for procs
61        (0x248 => interrupt_proc: [GpioProc; 2]),
62        /// Interrupt Enable for dormant_wake
63        (0x2D8 => dormant_wake_inte: GpioProc),
64        (0x320 => @END),
65    },
66    GpioPadRegisters {
67        /// Voltage select. Per bank control
68        (0x000 => voltage_select: ReadWrite<u32, VOLTAGE_SELECT::Register>),
69
70        (0x004 => gpio_pad: [ReadWrite<u32, GPIO_PAD::Register>; 48]),
71
72        (0x0C4 => swclk: ReadWrite<u32, SWCLK::Register>),
73
74        (0x0C8 => swd: ReadWrite<u32, SWD::Register>),
75        (0x0CC => @END),
76    },
77    SIORegisters {
78        /// Processor core identifier
79        (0x000 => cpuid: ReadWrite<u32>),
80        /// Input value for GPIO0...31.
81        /// In the Non-secure SIO, Secure-only GPIOs (as per ACCESSCTRL)
82        (0x004 => gpio_in: ReadWrite<u32, GPIO_IN::Register>),
83        /// Input value on GPIO32...47, QSPI IOs and USB pins
84        /// In the Non-secure SIO, Secure-only GPIOs (as per ACCESSCTRL)
85        (0x008 => gpio_hi_in: ReadWrite<u32, GPIO_HI_IN::Register>),
86        (0x00C => _reserved0),
87        /// GPIO0...31 output value
88        (0x010 => gpio_out: ReadWrite<u32, GPIO_OUT::Register>),
89        /// Output value for GPIO32...47, QSPI IOs and USB pins.
90        /// Write to set output level (1/0 -> high/low). Reading back gi
91        /// In the Non-secure SIO, Secure-only GPIOs (as per ACCESSCTRL)
92        (0x014 => gpio_hi_out: ReadWrite<u32, GPIO_HI_OUT::Register>),
93        /// GPIO0...31 output value set
94        (0x018 => gpio_out_set: ReadWrite<u32>),
95        /// Output value set for GPIO32..47, QSPI IOs and USB pins.
96        /// Perform an atomic bit-set on GPIO_HI_OUT, i.e. `GPIO_HI_OUT
97        (0x01C => gpio_hi_out_set: ReadWrite<u32, GPIO_HI_OUT_SET::Register>),
98        /// GPIO0...31 output value clear
99        (0x020 => gpio_out_clr: ReadWrite<u32>),
100        /// Output value clear for GPIO32..47, QSPI IOs and USB pins.
101        /// Perform an atomic bit-clear on GPIO_HI_OUT, i.e. `GPIO_HI_OU
102        (0x024 => gpio_hi_out_clr: ReadWrite<u32, GPIO_HI_OUT_CLR::Register>),
103        /// GPIO0...31 output value XOR
104        (0x028 => gpio_out_xor: ReadWrite<u32>),
105        /// Output value XOR for GPIO32..47, QSPI IOs and USB pins.
106        /// Perform an atomic bitwise XOR on GPIO_HI_OUT, i.e. `GPIO_HI_
107        (0x02C => gpio_hi_out_xor: ReadWrite<u32, GPIO_HI_OUT_XOR::Register>),
108        /// GPIO0...31 output enable
109        (0x030 => gpio_oe: ReadWrite<u32, GPIO_OE::Register>),
110        /// Output enable value for GPIO32...47, QSPI IOs and USB pins.
111        /// Write output enable (1/0 -> output/input). Reading back give
112        /// In the Non-secure SIO, Secure-only GPIOs (as per ACCESSCTRL)
113        (0x034 => gpio_hi_oe: ReadWrite<u32, GPIO_HI_OE::Register>),
114        /// GPIO0...31 output enable set
115        (0x038 => gpio_oe_set: ReadWrite<u32>),
116        /// Output enable set for GPIO32...47, QSPI IOs and USB pins.
117        /// Perform an atomic bit-set on GPIO_HI_OE, i.e. `GPIO_HI_OE |=
118        (0x03C => gpio_hi_oe_set: ReadWrite<u32, GPIO_HI_OE_SET::Register>),
119        /// GPIO0...31 output enable clear
120        (0x040 => gpio_oe_clr: ReadWrite<u32>),
121        /// Output enable clear for GPIO32...47, QSPI IOs and USB pins.
122        /// Perform an atomic bit-clear on GPIO_HI_OE, i.e. `GPIO_HI_OE
123        (0x044 => gpio_hi_oe_clr: ReadWrite<u32, GPIO_HI_OE_CLR::Register>),
124        /// GPIO0...31 output enable XOR
125        (0x048 => gpio_oe_xor: ReadWrite<u32>),
126        /// Output enable XOR for GPIO32...47, QSPI IOs and USB pins.
127        /// Perform an atomic bitwise XOR on GPIO_HI_OE, i.e. `GPIO_HI_O
128        (0x04C => gpio_hi_oe_xor: ReadWrite<u32, GPIO_HI_OE_XOR::Register>),
129        /// Status register for inter-core FIFOs (mailboxes).
130        /// There is one FIFO in the core 0 -> core 1 direction, and one
131        /// Core 0 can see the read side of the 1->0 FIFO (RX), and the
132        /// Core 1 can see the read side of the 0->1 FIFO (RX), and the
133        /// The SIO IRQ for each core is the logical OR of the VLD, WOF
134        (0x050 => fifo_st: ReadWrite<u32, FIFO_ST::Register>),
135        /// Write access to this core's TX FIFO
136        (0x054 => fifo_wr: ReadWrite<u32>),
137        /// Read access to this core's RX FIFO
138        (0x058 => fifo_rd: ReadWrite<u32>),
139        /// Spinlock state
140        /// A bitmap containing the state of all 32 spinlocks (1=locked)
141        /// Mainly intended for debugging.
142        (0x05C => spinlock_st: ReadWrite<u32>),
143        (0x060 => _reserved1),
144        /// Read/write access to accumulator 0
145        (0x080 => interp0_accum0: ReadWrite<u32>),
146        /// Read/write access to accumulator 1
147        (0x084 => interp0_accum1: ReadWrite<u32>),
148        /// Read/write access to BASE0 register.
149        (0x088 => interp0_base0: ReadWrite<u32>),
150        /// Read/write access to BASE1 register.
151        (0x08C => interp0_base1: ReadWrite<u32>),
152        /// Read/write access to BASE2 register.
153        (0x090 => interp0_base2: ReadWrite<u32>),
154        /// Read LANE0 result, and simultaneously write lane results to both accumulators (P
155        (0x094 => interp0_pop_lane0: ReadWrite<u32>),
156        /// Read LANE1 result, and simultaneously write lane results to both accumulators (P
157        (0x098 => interp0_pop_lane1: ReadWrite<u32>),
158        /// Read FULL result, and simultaneously write lane results to both accumulators (PO
159        (0x09C => interp0_pop_full: ReadWrite<u32>),
160        /// Read LANE0 result, without altering any internal state (PEEK).
161        (0x0A0 => interp0_peek_lane0: ReadWrite<u32>),
162        /// Read LANE1 result, without altering any internal state (PEEK).
163        (0x0A4 => interp0_peek_lane1: ReadWrite<u32>),
164        /// Read FULL result, without altering any internal state (PEEK).
165        (0x0A8 => interp0_peek_full: ReadWrite<u32>),
166        /// Control register for lane 0
167        (0x0AC => interp0_ctrl_lane0: ReadWrite<u32, INTERP0_CTRL_LANE0::Register>),
168        /// Control register for lane 1
169        (0x0B0 => interp0_ctrl_lane1: ReadWrite<u32, INTERP0_CTRL_LANE1::Register>),
170        /// Values written here are atomically added to ACCUM0
171        /// Reading yields lane 0's raw shift and mask value (BASE0 not
172        (0x0B4 => interp0_accum0_add: ReadWrite<u32>),
173        /// Values written here are atomically added to ACCUM1
174        /// Reading yields lane 1's raw shift and mask value (BASE1 not
175        (0x0B8 => interp0_accum1_add: ReadWrite<u32>),
176        /// On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously.
177        /// Each half is sign-extended to 32 bits if that lane's SIGNED
178        (0x0BC => interp0_base_1and0: ReadWrite<u32>),
179        /// Read/write access to accumulator 0
180        (0x0C0 => interp1_accum0: ReadWrite<u32>),
181        /// Read/write access to accumulator 1
182        (0x0C4 => interp1_accum1: ReadWrite<u32>),
183        /// Read/write access to BASE0 register.
184        (0x0C8 => interp1_base0: ReadWrite<u32>),
185        /// Read/write access to BASE1 register.
186        (0x0CC => interp1_base1: ReadWrite<u32>),
187        /// Read/write access to BASE2 register.
188        (0x0D0 => interp1_base2: ReadWrite<u32>),
189        /// Read LANE0 result, and simultaneously write lane results to both accumulators (P
190        (0x0D4 => interp1_pop_lane0: ReadWrite<u32>),
191        /// Read LANE1 result, and simultaneously write lane results to both accumulators (P
192        (0x0D8 => interp1_pop_lane1: ReadWrite<u32>),
193        /// Read FULL result, and simultaneously write lane results to both accumulators (PO
194        (0x0DC => interp1_pop_full: ReadWrite<u32>),
195        /// Read LANE0 result, without altering any internal state (PEEK).
196        (0x0E0 => interp1_peek_lane0: ReadWrite<u32>),
197        /// Read LANE1 result, without altering any internal state (PEEK).
198        (0x0E4 => interp1_peek_lane1: ReadWrite<u32>),
199        /// Read FULL result, without altering any internal state (PEEK).
200        (0x0E8 => interp1_peek_full: ReadWrite<u32>),
201        /// Control register for lane 0
202        (0x0EC => interp1_ctrl_lane0: ReadWrite<u32, INTERP1_CTRL_LANE0::Register>),
203        /// Control register for lane 1
204        (0x0F0 => interp1_ctrl_lane1: ReadWrite<u32, INTERP1_CTRL_LANE1::Register>),
205        /// Values written here are atomically added to ACCUM0
206        /// Reading yields lane 0's raw shift and mask value (BASE0 not
207        (0x0F4 => interp1_accum0_add: ReadWrite<u32>),
208        /// Values written here are atomically added to ACCUM1
209        /// Reading yields lane 1's raw shift and mask value (BASE1 not
210        (0x0F8 => interp1_accum1_add: ReadWrite<u32>),
211        /// On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously.
212        /// Each half is sign-extended to 32 bits if that lane's SIGNED
213        (0x0FC => interp1_base_1and0: ReadWrite<u32>),
214        /// Reading from a spinlock address will:
215        /// - Return 0 if lock is already locked
216        /// - Otherwise return nonzero, and simultaneously claim the loc
217        /// Writing (any value) releases the lock.
218        /// If core 0 and core 1 attempt to claim the same lock simultan
219        /// The value returned on success is 0x1 << lock number.
220        (0x100 => spinlock: [ReadWrite<u32, SPINLOCK::Register>; 32]),
221        /// Trigger a doorbell interrupt on the opposite core.
222        /// Write 1 to a bit to set the corresponding bit in DOORBELL_IN
223        /// Read to get the status of the doorbells currently asserted o
224        (0x180 => doorbell_out_set: ReadWrite<u32>),
225        /// Clear doorbells which have been posted to the opposite core. This register is in
226        /// Writing 1 to a bit in DOORBELL_OUT_CLR clears the correspond
227        /// Reading returns the status of the doorbells currently assert
228        (0x184 => doorbell_out_clr: ReadWrite<u32>),
229        /// Write 1s to trigger doorbell interrupts on this core. Read to get status of door
230        (0x188 => doorbell_in_set: ReadWrite<u32>),
231        /// Check and acknowledge doorbells posted to this core. This core's doorbell interr
232        /// Write 1 to each bit to clear that bit. The doorbell interrup
233        (0x18C => doorbell_in_clr: ReadWrite<u32>),
234        /// Detach certain core-local peripherals from Secure SIO, and attach them to Non-se
235        /// This register is per-core, and is only present on the Secure
236        /// Most SIO hardware is duplicated across the Secure and Non-se
237        (0x190 => peri_nonsec: ReadWrite<u32, PERI_NONSEC::Register>),
238        (0x194 => _reserved2),
239        /// Control the assertion of the standard software interrupt (MIP.MSIP) on the RISC-
240        /// Unlike the RISC-V timer, this interrupt is not routed to a n
241        /// It is safe for both cores to write to this register on the s
242        (0x1A0 => riscv_softirq: ReadWrite<u32, RISCV_SOFTIRQ::Register>),
243        /// Control register for the RISC-V 64-bit Machine-mode timer. This timer is only pr
244        /// Note whilst this timer follows the RISC-V privileged specifi
245        (0x1A4 => mtime_ctrl: ReadWrite<u32, MTIME_CTRL::Register>),
246        (0x1A8 => _reserved3),
247        /// Read/write access to the high half of RISC-V Machine-mode timer. This register i
248        (0x1B0 => mtime: ReadWrite<u32>),
249        /// Read/write access to the high half of RISC-V Machine-mode timer. This register i
250        (0x1B4 => mtimeh: ReadWrite<u32>),
251        /// Low half of RISC-V Machine-mode timer comparator. This register is core-local, i
252        /// The timer interrupt is asserted whenever MTIME is greater th
253        (0x1B8 => mtimecmp: ReadWrite<u32>),
254        /// High half of RISC-V Machine-mode timer comparator. This register is core-local.
255        /// The timer interrupt is asserted whenever MTIME is greater th
256        (0x1BC => mtimecmph: ReadWrite<u32>),
257        /// Control register for TMDS encoder.
258        (0x1C0 => tmds_ctrl: ReadWrite<u32, TMDS_CTRL::Register>),
259        /// Write-only access to the TMDS colour data register.
260        (0x1C4 => tmds_wdata: ReadWrite<u32>),
261        /// Get the encoding of one pixel's worth of colour data, packed into a 32-bit value
262        /// The PEEK alias does not shift the colour register when read,
263        (0x1C8 => tmds_peek_single: ReadWrite<u32>),
264        /// Get the encoding of one pixel's worth of colour data, packed into a 32-bit value
265        /// The POP alias shifts the colour register when read, as well
266        (0x1CC => tmds_pop_single: ReadWrite<u32>),
267        /// Get lane 0 of the encoding of two pixels' worth of colour data. Two 10-bit TMDS
268        /// The PEEK alias does not shift the colour register when read,
269        (0x1D0 => tmds_peek_double_l0: ReadWrite<u32>),
270        /// Get lane 0 of the encoding of two pixels' worth of colour data. Two 10-bit TMDS
271        /// The POP alias shifts the colour register when read, accordin
272        (0x1D4 => tmds_pop_double_l0: ReadWrite<u32>),
273        /// Get lane 1 of the encoding of two pixels' worth of colour data. Two 10-bit TMDS
274        /// The PEEK alias does not shift the colour register when read,
275        (0x1D8 => tmds_peek_double_l1: ReadWrite<u32>),
276        /// Get lane 1 of the encoding of two pixels' worth of colour data. Two 10-bit TMDS
277        /// The POP alias shifts the colour register when read, accordin
278        (0x1DC => tmds_pop_double_l1: ReadWrite<u32>),
279        /// Get lane 2 of the encoding of two pixels' worth of colour data. Two 10-bit TMDS
280        /// The PEEK alias does not shift the colour register when read,
281        (0x1E0 => tmds_peek_double_l2: ReadWrite<u32>),
282        /// Get lane 2 of the encoding of two pixels' worth of colour data. Two 10-bit TMDS
283        /// The POP alias shifts the colour register when read, accordin
284        (0x1E4 => tmds_pop_double_l2: ReadWrite<u32>),
285        (0x1E8 => @END),
286    }
287}
288register_bitfields![u32,
289GPIOx_STATUS [
290    /// interrupt to processors, after override is applied
291    IRQTOPROC OFFSET(26) NUMBITS(1) [],
292    /// input signal from pad, before filtering and override are applied
293    INFROMPAD OFFSET(17) NUMBITS(1) [],
294    /// output enable to pad after register override is applied
295    OETOPAD OFFSET(13) NUMBITS(1) [],
296    /// output signal to pad after register override is applied
297    OUTTOPAD OFFSET(9) NUMBITS(1) []
298],
299GPIOx_CTRL [
300
301    IRQOVER OFFSET(28) NUMBITS(2) [
302        /// don't invert the interrupt
303        DoNotInvertTheInterrupt = 0,
304        /// invert the interrupt
305        InvertTheInterrupt = 1,
306        /// drive interrupt low
307        DriveInterruptLow = 2,
308        /// drive interrupt high
309        DriveInterruptHigh = 3
310    ],
311
312    INOVER OFFSET(16) NUMBITS(2) [
313        /// don't invert the peri input
314        DoNotInvertThePeriInput = 0,
315        /// invert the peri input
316        InvertThePeriInput = 1,
317        /// drive peri input low
318        DrivePeriInputLow = 2,
319        /// drive peri input high
320        DrivePeriInputHigh = 3
321    ],
322
323    OEOVER OFFSET(14) NUMBITS(2) [
324        /// drive output enable from peripheral signal selected by funcsel
325        DriveOutputEnableFromPeripheralSignalSelectedByFuncsel = 0,
326        /// drive output enable from inverse of peripheral signal selected by funcsel
327        DriveOutputEnableFromInverseOfPeripheralSignalSelectedByFuncsel = 1,
328        /// disable output
329        DisableOutput = 2,
330        /// enable output
331        EnableOutput = 3
332    ],
333
334    OUTOVER OFFSET(12) NUMBITS(2) [
335        /// drive output from peripheral signal selected by funcsel
336        DriveOutputFromPeripheralSignalSelectedByFuncsel = 0,
337        /// drive output from inverse of peripheral signal selected by funcsel
338        DriveOutputFromInverseOfPeripheralSignalSelectedByFuncsel = 1,
339        /// drive output low
340        DriveOutputLow = 2,
341        /// drive output high
342        DriveOutputHigh = 3
343    ],
344    /// 0-31 -> selects pin function according to the gpio table
345/// 31 == NULL
346    FUNCSEL OFFSET(0) NUMBITS(5) [
347
348        Jtag_tck = 0
349    ]
350],
351IRQSUMMARY_PROC0 [
352
353    GPIO31 OFFSET(31) NUMBITS(1) [],
354
355    GPIO30 OFFSET(30) NUMBITS(1) [],
356
357    GPIO29 OFFSET(29) NUMBITS(1) [],
358
359    GPIO28 OFFSET(28) NUMBITS(1) [],
360
361    GPIO27 OFFSET(27) NUMBITS(1) [],
362
363    GPIO26 OFFSET(26) NUMBITS(1) [],
364
365    GPIO25 OFFSET(25) NUMBITS(1) [],
366
367    GPIO24 OFFSET(24) NUMBITS(1) [],
368
369    GPIO23 OFFSET(23) NUMBITS(1) [],
370
371    GPIO22 OFFSET(22) NUMBITS(1) [],
372
373    GPIO21 OFFSET(21) NUMBITS(1) [],
374
375    GPIO20 OFFSET(20) NUMBITS(1) [],
376
377    GPIO19 OFFSET(19) NUMBITS(1) [],
378
379    GPIO18 OFFSET(18) NUMBITS(1) [],
380
381    GPIO17 OFFSET(17) NUMBITS(1) [],
382
383    GPIO16 OFFSET(16) NUMBITS(1) [],
384
385    GPIO15 OFFSET(15) NUMBITS(1) [],
386
387    GPIO14 OFFSET(14) NUMBITS(1) [],
388
389    GPIO13 OFFSET(13) NUMBITS(1) [],
390
391    GPIO12 OFFSET(12) NUMBITS(1) [],
392
393    GPIO11 OFFSET(11) NUMBITS(1) [],
394
395    GPIO10 OFFSET(10) NUMBITS(1) [],
396
397    GPIO9 OFFSET(9) NUMBITS(1) [],
398
399    GPIO8 OFFSET(8) NUMBITS(1) [],
400
401    GPIO7 OFFSET(7) NUMBITS(1) [],
402
403    GPIO6 OFFSET(6) NUMBITS(1) [],
404
405    GPIO5 OFFSET(5) NUMBITS(1) [],
406
407    GPIO4 OFFSET(4) NUMBITS(1) [],
408
409    GPIO3 OFFSET(3) NUMBITS(1) [],
410
411    GPIO2 OFFSET(2) NUMBITS(1) [],
412
413    GPIO1 OFFSET(1) NUMBITS(1) [],
414
415    GPIO0 OFFSET(0) NUMBITS(1) []
416],
417IRQSUMMARY_PROC1 [
418
419    GPIO47 OFFSET(15) NUMBITS(1) [],
420
421    GPIO46 OFFSET(14) NUMBITS(1) [],
422
423    GPIO45 OFFSET(13) NUMBITS(1) [],
424
425    GPIO44 OFFSET(12) NUMBITS(1) [],
426
427    GPIO43 OFFSET(11) NUMBITS(1) [],
428
429    GPIO42 OFFSET(10) NUMBITS(1) [],
430
431    GPIO41 OFFSET(9) NUMBITS(1) [],
432
433    GPIO40 OFFSET(8) NUMBITS(1) [],
434
435    GPIO39 OFFSET(7) NUMBITS(1) [],
436
437    GPIO38 OFFSET(6) NUMBITS(1) [],
438
439    GPIO37 OFFSET(5) NUMBITS(1) [],
440
441    GPIO36 OFFSET(4) NUMBITS(1) [],
442
443    GPIO35 OFFSET(3) NUMBITS(1) [],
444
445    GPIO34 OFFSET(2) NUMBITS(1) [],
446
447    GPIO33 OFFSET(1) NUMBITS(1) [],
448
449    GPIO32 OFFSET(0) NUMBITS(1) []
450],
451GPIO_INTRxx [
452
453    GPIO7_EDGE_HIGH OFFSET(31) NUMBITS(1) [],
454
455    GPIO7_EDGE_LOW OFFSET(30) NUMBITS(1) [],
456
457    GPIO7_LEVEL_HIGH OFFSET(29) NUMBITS(1) [],
458
459    GPIO7_LEVEL_LOW OFFSET(28) NUMBITS(1) [],
460
461    GPIO6_EDGE_HIGH OFFSET(27) NUMBITS(1) [],
462
463    GPIO6_EDGE_LOW OFFSET(26) NUMBITS(1) [],
464
465    GPIO6_LEVEL_HIGH OFFSET(25) NUMBITS(1) [],
466
467    GPIO6_LEVEL_LOW OFFSET(24) NUMBITS(1) [],
468
469    GPIO5_EDGE_HIGH OFFSET(23) NUMBITS(1) [],
470
471    GPIO5_EDGE_LOW OFFSET(22) NUMBITS(1) [],
472
473    GPIO5_LEVEL_HIGH OFFSET(21) NUMBITS(1) [],
474
475    GPIO5_LEVEL_LOW OFFSET(20) NUMBITS(1) [],
476
477    GPIO4_EDGE_HIGH OFFSET(19) NUMBITS(1) [],
478
479    GPIO4_EDGE_LOW OFFSET(18) NUMBITS(1) [],
480
481    GPIO4_LEVEL_HIGH OFFSET(17) NUMBITS(1) [],
482
483    GPIO4_LEVEL_LOW OFFSET(16) NUMBITS(1) [],
484
485    GPIO3_EDGE_HIGH OFFSET(15) NUMBITS(1) [],
486
487    GPIO3_EDGE_LOW OFFSET(14) NUMBITS(1) [],
488
489    GPIO3_LEVEL_HIGH OFFSET(13) NUMBITS(1) [],
490
491    GPIO3_LEVEL_LOW OFFSET(12) NUMBITS(1) [],
492
493    GPIO2_EDGE_HIGH OFFSET(11) NUMBITS(1) [],
494
495    GPIO2_EDGE_LOW OFFSET(10) NUMBITS(1) [],
496
497    GPIO2_LEVEL_HIGH OFFSET(9) NUMBITS(1) [],
498
499    GPIO2_LEVEL_LOW OFFSET(8) NUMBITS(1) [],
500
501    GPIO1_EDGE_HIGH OFFSET(7) NUMBITS(1) [],
502
503    GPIO1_EDGE_LOW OFFSET(6) NUMBITS(1) [],
504
505    GPIO1_LEVEL_HIGH OFFSET(5) NUMBITS(1) [],
506
507    GPIO1_LEVEL_LOW OFFSET(4) NUMBITS(1) [],
508
509    GPIO0_EDGE_HIGH OFFSET(3) NUMBITS(1) [],
510
511    GPIO0_EDGE_LOW OFFSET(2) NUMBITS(1) [],
512
513    GPIO0_LEVEL_HIGH OFFSET(1) NUMBITS(1) [],
514
515    GPIO0_LEVEL_LOW OFFSET(0) NUMBITS(1) []
516],
517VOLTAGE_SELECT [
518
519    VOLTAGE_SELECT OFFSET(0) NUMBITS(1) [
520        /// Set voltage to 3.3V (DVDD >= 2V5)
521        SetVoltageTo33VDVDD2V5 = 0,
522        /// Set voltage to 1.8V (DVDD <= 1V8)
523        SetVoltageTo18VDVDD1V8 = 1
524    ]
525],
526GPIO_PAD [
527    /// Pad isolation control. Remove this once the pad is configured by software.
528    ISO OFFSET(8) NUMBITS(1) [],
529    /// Output disable. Has priority over output enable from peripherals
530    OD OFFSET(7) NUMBITS(1) [],
531    /// Input enable
532    IE OFFSET(6) NUMBITS(1) [],
533    /// Drive strength.
534    DRIVE OFFSET(4) NUMBITS(2) [
535
536        _2mA = 0,
537        _4mA = 1,
538        _8mA = 2,
539        _12mA = 3
540    ],
541    /// Pull up enable
542    PUE OFFSET(3) NUMBITS(1) [],
543    /// Pull down enable
544    PDE OFFSET(2) NUMBITS(1) [],
545    /// Enable schmitt trigger
546    SCHMITT OFFSET(1) NUMBITS(1) [],
547    /// Slew rate control. 1 = Fast, 0 = Slow
548    SLEWFAST OFFSET(0) NUMBITS(1) []
549],
550SWCLK [
551    /// Pad isolation control. Remove this once the pad is configured by software.
552    ISO OFFSET(8) NUMBITS(1) [],
553    /// Output disable. Has priority over output enable from peripherals
554    OD OFFSET(7) NUMBITS(1) [],
555    /// Input enable
556    IE OFFSET(6) NUMBITS(1) [],
557    /// Drive strength.
558    DRIVE OFFSET(4) NUMBITS(2) [
559
560        _2mA = 0,
561        _4mA = 1,
562        _8mA = 2,
563        _12mA = 3
564    ],
565    /// Pull up enable
566    PUE OFFSET(3) NUMBITS(1) [],
567    /// Pull down enable
568    PDE OFFSET(2) NUMBITS(1) [],
569    /// Enable schmitt trigger
570    SCHMITT OFFSET(1) NUMBITS(1) [],
571    /// Slew rate control. 1 = Fast, 0 = Slow
572    SLEWFAST OFFSET(0) NUMBITS(1) []
573],
574SWD [
575    /// Pad isolation control. Remove this once the pad is configured by software.
576    ISO OFFSET(8) NUMBITS(1) [],
577    /// Output disable. Has priority over output enable from peripherals
578    OD OFFSET(7) NUMBITS(1) [],
579    /// Input enable
580    IE OFFSET(6) NUMBITS(1) [],
581    /// Drive strength.
582    DRIVE OFFSET(4) NUMBITS(2) [
583
584        _2mA = 0,
585        _4mA = 1,
586        _8mA = 2,
587        _12mA = 3
588    ],
589    /// Pull up enable
590    PUE OFFSET(3) NUMBITS(1) [],
591    /// Pull down enable
592    PDE OFFSET(2) NUMBITS(1) [],
593    /// Enable schmitt trigger
594    SCHMITT OFFSET(1) NUMBITS(1) [],
595    /// Slew rate control. 1 = Fast, 0 = Slow
596    SLEWFAST OFFSET(0) NUMBITS(1) []
597],
598CPUID [
599    /// Value is 0 when read from processor core 0, and 1 when read from processor core
600    CPUID OFFSET(0) NUMBITS(32) []
601],
602GPIO_IN [
603
604    GPIO_IN OFFSET(0) NUMBITS(32) []
605],
606GPIO_HI_IN [
607    /// Input value on QSPI SD0 (MOSI), SD1 (MISO), SD2 and SD3 pins
608    QSPI_SD OFFSET(28) NUMBITS(4) [],
609    /// Input value on QSPI CSn pin
610    QSPI_CSN OFFSET(27) NUMBITS(1) [],
611    /// Input value on QSPI SCK pin
612    QSPI_SCK OFFSET(26) NUMBITS(1) [],
613    /// Input value on USB D- pin
614    USB_DM OFFSET(25) NUMBITS(1) [],
615    /// Input value on USB D+ pin
616    USB_DP OFFSET(24) NUMBITS(1) [],
617    /// Input value on GPIO32...47
618    GPIO OFFSET(0) NUMBITS(16) []
619],
620GPIO_OUT [
621    /// Set output level (1/0 -> high/low) for GPIO0...31. Reading back gives the last v
622    /// If core 0 and core 1 both write to GPIO_OUT simultan
623    /// In the Non-secure SIO, Secure-only GPIOs (as per ACC
624    GPIO_OUT OFFSET(0) NUMBITS(32) []
625],
626GPIO_HI_OUT [
627    /// Output value for QSPI SD0 (MOSI), SD1 (MISO), SD2 and SD3 pins
628    QSPI_SD OFFSET(28) NUMBITS(4) [],
629    /// Output value for QSPI CSn pin
630    QSPI_CSN OFFSET(27) NUMBITS(1) [],
631    /// Output value for QSPI SCK pin
632    QSPI_SCK OFFSET(26) NUMBITS(1) [],
633    /// Output value for USB D- pin
634    USB_DM OFFSET(25) NUMBITS(1) [],
635    /// Output value for USB D+ pin
636    USB_DP OFFSET(24) NUMBITS(1) [],
637    /// Output value for GPIO32...47
638    GPIO OFFSET(0) NUMBITS(16) []
639],
640GPIO_OUT_SET [
641    /// Perform an atomic bit-set on GPIO_OUT, i.e. `GPIO_OUT |= wdata`
642    GPIO_OUT_SET OFFSET(0) NUMBITS(32) []
643],
644GPIO_HI_OUT_SET [
645
646    QSPI_SD OFFSET(28) NUMBITS(4) [],
647
648    QSPI_CSN OFFSET(27) NUMBITS(1) [],
649
650    QSPI_SCK OFFSET(26) NUMBITS(1) [],
651
652    USB_DM OFFSET(25) NUMBITS(1) [],
653
654    USB_DP OFFSET(24) NUMBITS(1) [],
655
656    GPIO OFFSET(0) NUMBITS(16) []
657],
658GPIO_OUT_CLR [
659    /// Perform an atomic bit-clear on GPIO_OUT, i.e. `GPIO_OUT &= ~wdata`
660    GPIO_OUT_CLR OFFSET(0) NUMBITS(32) []
661],
662GPIO_HI_OUT_CLR [
663
664    QSPI_SD OFFSET(28) NUMBITS(4) [],
665
666    QSPI_CSN OFFSET(27) NUMBITS(1) [],
667
668    QSPI_SCK OFFSET(26) NUMBITS(1) [],
669
670    USB_DM OFFSET(25) NUMBITS(1) [],
671
672    USB_DP OFFSET(24) NUMBITS(1) [],
673
674    GPIO OFFSET(0) NUMBITS(16) []
675],
676GPIO_OUT_XOR [
677    /// Perform an atomic bitwise XOR on GPIO_OUT, i.e. `GPIO_OUT ^= wdata`
678    GPIO_OUT_XOR OFFSET(0) NUMBITS(32) []
679],
680GPIO_HI_OUT_XOR [
681
682    QSPI_SD OFFSET(28) NUMBITS(4) [],
683
684    QSPI_CSN OFFSET(27) NUMBITS(1) [],
685
686    QSPI_SCK OFFSET(26) NUMBITS(1) [],
687
688    USB_DM OFFSET(25) NUMBITS(1) [],
689
690    USB_DP OFFSET(24) NUMBITS(1) [],
691
692    GPIO OFFSET(0) NUMBITS(16) []
693],
694GPIO_OE [
695    /// Set output enable (1/0 -> output/input) for GPIO0...31. Reading back gives the l
696    /// If core 0 and core 1 both write to GPIO_OE simultane
697    /// In the Non-secure SIO, Secure-only GPIOs (as per ACC
698    GPIO_OE OFFSET(0) NUMBITS(32) []
699],
700GPIO_HI_OE [
701    /// Output enable value for QSPI SD0 (MOSI), SD1 (MISO), SD2 and SD3 pins
702    QSPI_SD OFFSET(28) NUMBITS(4) [],
703    /// Output enable value for QSPI CSn pin
704    QSPI_CSN OFFSET(27) NUMBITS(1) [],
705    /// Output enable value for QSPI SCK pin
706    QSPI_SCK OFFSET(26) NUMBITS(1) [],
707    /// Output enable value for USB D- pin
708    USB_DM OFFSET(25) NUMBITS(1) [],
709    /// Output enable value for USB D+ pin
710    USB_DP OFFSET(24) NUMBITS(1) [],
711    /// Output enable value for GPIO32...47
712    GPIO OFFSET(0) NUMBITS(16) []
713],
714GPIO_OE_SET [
715    /// Perform an atomic bit-set on GPIO_OE, i.e. `GPIO_OE |= wdata`
716    GPIO_OE_SET OFFSET(0) NUMBITS(32) []
717],
718GPIO_HI_OE_SET [
719
720    QSPI_SD OFFSET(28) NUMBITS(4) [],
721
722    QSPI_CSN OFFSET(27) NUMBITS(1) [],
723
724    QSPI_SCK OFFSET(26) NUMBITS(1) [],
725
726    USB_DM OFFSET(25) NUMBITS(1) [],
727
728    USB_DP OFFSET(24) NUMBITS(1) [],
729
730    GPIO OFFSET(0) NUMBITS(16) []
731],
732GPIO_OE_CLR [
733    /// Perform an atomic bit-clear on GPIO_OE, i.e. `GPIO_OE &= ~wdata`
734    GPIO_OE_CLR OFFSET(0) NUMBITS(32) []
735],
736GPIO_HI_OE_CLR [
737
738    QSPI_SD OFFSET(28) NUMBITS(4) [],
739
740    QSPI_CSN OFFSET(27) NUMBITS(1) [],
741
742    QSPI_SCK OFFSET(26) NUMBITS(1) [],
743
744    USB_DM OFFSET(25) NUMBITS(1) [],
745
746    USB_DP OFFSET(24) NUMBITS(1) [],
747
748    GPIO OFFSET(0) NUMBITS(16) []
749],
750GPIO_OE_XOR [
751    /// Perform an atomic bitwise XOR on GPIO_OE, i.e. `GPIO_OE ^= wdata`
752    GPIO_OE_XOR OFFSET(0) NUMBITS(32) []
753],
754GPIO_HI_OE_XOR [
755
756    QSPI_SD OFFSET(28) NUMBITS(4) [],
757
758    QSPI_CSN OFFSET(27) NUMBITS(1) [],
759
760    QSPI_SCK OFFSET(26) NUMBITS(1) [],
761
762    USB_DM OFFSET(25) NUMBITS(1) [],
763
764    USB_DP OFFSET(24) NUMBITS(1) [],
765
766    GPIO OFFSET(0) NUMBITS(16) []
767],
768FIFO_ST [
769    /// Sticky flag indicating the RX FIFO was read when empty. This read was ignored by
770    ROE OFFSET(3) NUMBITS(1) [],
771    /// Sticky flag indicating the TX FIFO was written when full. This write was ignored
772    WOF OFFSET(2) NUMBITS(1) [],
773    /// Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more
774    RDY OFFSET(1) NUMBITS(1) [],
775    /// Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid)
776    VLD OFFSET(0) NUMBITS(1) []
777],
778FIFO_WR [
779
780    FIFO_WR OFFSET(0) NUMBITS(32) []
781],
782FIFO_RD [
783
784    FIFO_RD OFFSET(0) NUMBITS(32) []
785],
786SPINLOCK_ST [
787
788    SPINLOCK_ST OFFSET(0) NUMBITS(32) []
789],
790INTERP0_ACCUM0 [
791
792    INTERP0_ACCUM0 OFFSET(0) NUMBITS(32) []
793],
794INTERP0_ACCUM1 [
795
796    INTERP0_ACCUM1 OFFSET(0) NUMBITS(32) []
797],
798INTERP0_BASE0 [
799
800    INTERP0_BASE0 OFFSET(0) NUMBITS(32) []
801],
802INTERP0_BASE1 [
803
804    INTERP0_BASE1 OFFSET(0) NUMBITS(32) []
805],
806INTERP0_BASE2 [
807
808    INTERP0_BASE2 OFFSET(0) NUMBITS(32) []
809],
810INTERP0_POP_LANE0 [
811
812    INTERP0_POP_LANE0 OFFSET(0) NUMBITS(32) []
813],
814INTERP0_POP_LANE1 [
815
816    INTERP0_POP_LANE1 OFFSET(0) NUMBITS(32) []
817],
818INTERP0_POP_FULL [
819
820    INTERP0_POP_FULL OFFSET(0) NUMBITS(32) []
821],
822INTERP0_PEEK_LANE0 [
823
824    INTERP0_PEEK_LANE0 OFFSET(0) NUMBITS(32) []
825],
826INTERP0_PEEK_LANE1 [
827
828    INTERP0_PEEK_LANE1 OFFSET(0) NUMBITS(32) []
829],
830INTERP0_PEEK_FULL [
831
832    INTERP0_PEEK_FULL OFFSET(0) NUMBITS(32) []
833],
834INTERP0_CTRL_LANE0 [
835    /// Set if either OVERF0 or OVERF1 is set.
836    OVERF OFFSET(25) NUMBITS(1) [],
837    /// Indicates if any masked-off MSBs in ACCUM1 are set.
838    OVERF1 OFFSET(24) NUMBITS(1) [],
839    /// Indicates if any masked-off MSBs in ACCUM0 are set.
840    OVERF0 OFFSET(23) NUMBITS(1) [],
841    /// Only present on INTERP0 on each core. If BLEND mode is enabled:
842    /// - LANE1 result is a linear interpolation between BAS
843    /// by the 8 LSBs of lane 1 shift and mask value (a frac
844    /// 0 and 255/256ths)
845    /// - LANE0 result does not have BASE0 added (yields onl
846    /// - FULL result does not have lane 1 shift+mask value
847    /// LANE1 SIGNED flag controls whether the interpolation
848    BLEND OFFSET(21) NUMBITS(1) [],
849    /// ORed into bits 29:28 of the lane result presented to the processor on the bus.
850    /// No effect on the internal 32-bit datapath. Handy for
851    /// of pointers into flash or SRAM.
852    FORCE_MSB OFFSET(19) NUMBITS(2) [],
853    /// If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL resul
854    ADD_RAW OFFSET(18) NUMBITS(1) [],
855    /// If 1, feed the opposite lane's result into this lane's accumulator on POP.
856    CROSS_RESULT OFFSET(17) NUMBITS(1) [],
857    /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardwar
858    /// Takes effect even if ADD_RAW is set (the CROSS_INPUT
859    CROSS_INPUT OFFSET(16) NUMBITS(1) [],
860    /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 3
861    /// before adding to BASE0, and LANE0 PEEK/POP appear ex
862    SIGNED OFFSET(15) NUMBITS(1) [],
863    /// The most-significant bit allowed to pass by the mask (inclusive)
864    /// Setting MSB < LSB may cause chip to turn inside-out
865    MASK_MSB OFFSET(10) NUMBITS(5) [],
866    /// The least-significant bit allowed to pass by the mask (inclusive)
867    MASK_LSB OFFSET(5) NUMBITS(5) [],
868    /// Right-rotate applied to accumulator before masking. By appropriately configuring
869    SHIFT OFFSET(0) NUMBITS(5) []
870],
871INTERP0_CTRL_LANE1 [
872    /// ORed into bits 29:28 of the lane result presented to the processor on the bus.
873    /// No effect on the internal 32-bit datapath. Handy for
874    /// of pointers into flash or SRAM.
875    FORCE_MSB OFFSET(19) NUMBITS(2) [],
876    /// If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL resul
877    ADD_RAW OFFSET(18) NUMBITS(1) [],
878    /// If 1, feed the opposite lane's result into this lane's accumulator on POP.
879    CROSS_RESULT OFFSET(17) NUMBITS(1) [],
880    /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardwar
881    /// Takes effect even if ADD_RAW is set (the CROSS_INPUT
882    CROSS_INPUT OFFSET(16) NUMBITS(1) [],
883    /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 3
884    /// before adding to BASE1, and LANE1 PEEK/POP appear ex
885    SIGNED OFFSET(15) NUMBITS(1) [],
886    /// The most-significant bit allowed to pass by the mask (inclusive)
887    /// Setting MSB < LSB may cause chip to turn inside-out
888    MASK_MSB OFFSET(10) NUMBITS(5) [],
889    /// The least-significant bit allowed to pass by the mask (inclusive)
890    MASK_LSB OFFSET(5) NUMBITS(5) [],
891    /// Right-rotate applied to accumulator before masking. By appropriately configuring
892    SHIFT OFFSET(0) NUMBITS(5) []
893],
894INTERP0_ACCUM0_ADD [
895
896    INTERP0_ACCUM0_ADD OFFSET(0) NUMBITS(24) []
897],
898INTERP0_ACCUM1_ADD [
899
900    INTERP0_ACCUM1_ADD OFFSET(0) NUMBITS(24) []
901],
902INTERP0_BASE_1AND0 [
903
904    INTERP0_BASE_1AND0 OFFSET(0) NUMBITS(32) []
905],
906INTERP1_ACCUM0 [
907
908    INTERP1_ACCUM0 OFFSET(0) NUMBITS(32) []
909],
910INTERP1_ACCUM1 [
911
912    INTERP1_ACCUM1 OFFSET(0) NUMBITS(32) []
913],
914INTERP1_BASE0 [
915
916    INTERP1_BASE0 OFFSET(0) NUMBITS(32) []
917],
918INTERP1_BASE1 [
919
920    INTERP1_BASE1 OFFSET(0) NUMBITS(32) []
921],
922INTERP1_BASE2 [
923
924    INTERP1_BASE2 OFFSET(0) NUMBITS(32) []
925],
926INTERP1_POP_LANE0 [
927
928    INTERP1_POP_LANE0 OFFSET(0) NUMBITS(32) []
929],
930INTERP1_POP_LANE1 [
931
932    INTERP1_POP_LANE1 OFFSET(0) NUMBITS(32) []
933],
934INTERP1_POP_FULL [
935
936    INTERP1_POP_FULL OFFSET(0) NUMBITS(32) []
937],
938INTERP1_PEEK_LANE0 [
939
940    INTERP1_PEEK_LANE0 OFFSET(0) NUMBITS(32) []
941],
942INTERP1_PEEK_LANE1 [
943
944    INTERP1_PEEK_LANE1 OFFSET(0) NUMBITS(32) []
945],
946INTERP1_PEEK_FULL [
947
948    INTERP1_PEEK_FULL OFFSET(0) NUMBITS(32) []
949],
950INTERP1_CTRL_LANE0 [
951    /// Set if either OVERF0 or OVERF1 is set.
952    OVERF OFFSET(25) NUMBITS(1) [],
953    /// Indicates if any masked-off MSBs in ACCUM1 are set.
954    OVERF1 OFFSET(24) NUMBITS(1) [],
955    /// Indicates if any masked-off MSBs in ACCUM0 are set.
956    OVERF0 OFFSET(23) NUMBITS(1) [],
957    /// Only present on INTERP1 on each core. If CLAMP mode is enabled:
958    /// - LANE0 result is shifted and masked ACCUM0, clamped
959    /// BASE0 and an upper bound of BASE1.
960    /// - Signedness of these comparisons is determined by L
961    CLAMP OFFSET(22) NUMBITS(1) [],
962    /// ORed into bits 29:28 of the lane result presented to the processor on the bus.
963    /// No effect on the internal 32-bit datapath. Handy for
964    /// of pointers into flash or SRAM.
965    FORCE_MSB OFFSET(19) NUMBITS(2) [],
966    /// If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL resul
967    ADD_RAW OFFSET(18) NUMBITS(1) [],
968    /// If 1, feed the opposite lane's result into this lane's accumulator on POP.
969    CROSS_RESULT OFFSET(17) NUMBITS(1) [],
970    /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardwar
971    /// Takes effect even if ADD_RAW is set (the CROSS_INPUT
972    CROSS_INPUT OFFSET(16) NUMBITS(1) [],
973    /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 3
974    /// before adding to BASE0, and LANE0 PEEK/POP appear ex
975    SIGNED OFFSET(15) NUMBITS(1) [],
976    /// The most-significant bit allowed to pass by the mask (inclusive)
977    /// Setting MSB < LSB may cause chip to turn inside-out
978    MASK_MSB OFFSET(10) NUMBITS(5) [],
979    /// The least-significant bit allowed to pass by the mask (inclusive)
980    MASK_LSB OFFSET(5) NUMBITS(5) [],
981    /// Right-rotate applied to accumulator before masking. By appropriately configuring
982    SHIFT OFFSET(0) NUMBITS(5) []
983],
984INTERP1_CTRL_LANE1 [
985    /// ORed into bits 29:28 of the lane result presented to the processor on the bus.
986    /// No effect on the internal 32-bit datapath. Handy for
987    /// of pointers into flash or SRAM.
988    FORCE_MSB OFFSET(19) NUMBITS(2) [],
989    /// If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL resul
990    ADD_RAW OFFSET(18) NUMBITS(1) [],
991    /// If 1, feed the opposite lane's result into this lane's accumulator on POP.
992    CROSS_RESULT OFFSET(17) NUMBITS(1) [],
993    /// If 1, feed the opposite lane's accumulator into this lane's shift + mask hardwar
994    /// Takes effect even if ADD_RAW is set (the CROSS_INPUT
995    CROSS_INPUT OFFSET(16) NUMBITS(1) [],
996    /// If SIGNED is set, the shifted and masked accumulator value is sign-extended to 3
997    /// before adding to BASE1, and LANE1 PEEK/POP appear ex
998    SIGNED OFFSET(15) NUMBITS(1) [],
999    /// The most-significant bit allowed to pass by the mask (inclusive)
1000    /// Setting MSB < LSB may cause chip to turn inside-out
1001    MASK_MSB OFFSET(10) NUMBITS(5) [],
1002    /// The least-significant bit allowed to pass by the mask (inclusive)
1003    MASK_LSB OFFSET(5) NUMBITS(5) [],
1004    /// Right-rotate applied to accumulator before masking. By appropriately configuring
1005    SHIFT OFFSET(0) NUMBITS(5) []
1006],
1007INTERP1_ACCUM0_ADD [
1008
1009    INTERP1_ACCUM0_ADD OFFSET(0) NUMBITS(24) []
1010],
1011INTERP1_ACCUM1_ADD [
1012
1013    INTERP1_ACCUM1_ADD OFFSET(0) NUMBITS(24) []
1014],
1015INTERP1_BASE_1AND0 [
1016
1017    INTERP1_BASE_1AND0 OFFSET(0) NUMBITS(32) []
1018],
1019SPINLOCK [
1020
1021    SPINLOCK OFFSET(0) NUMBITS(32) []
1022],
1023DOORBELL_OUT_SET [
1024
1025    DOORBELL_OUT_SET OFFSET(0) NUMBITS(8) []
1026],
1027DOORBELL_OUT_CLR [
1028
1029    DOORBELL_OUT_CLR OFFSET(0) NUMBITS(8) []
1030],
1031DOORBELL_IN_SET [
1032
1033    DOORBELL_IN_SET OFFSET(0) NUMBITS(8) []
1034],
1035DOORBELL_IN_CLR [
1036
1037    DOORBELL_IN_CLR OFFSET(0) NUMBITS(8) []
1038],
1039PERI_NONSEC [
1040    /// IF 1, detach TMDS encoder (of this core) from the Secure SIO, and attach to the
1041    TMDS OFFSET(5) NUMBITS(1) [],
1042    /// If 1, detach interpolator 1 (of this core) from the Secure SIO, and attach to th
1043    INTERP1 OFFSET(1) NUMBITS(1) [],
1044    /// If 1, detach interpolator 0 (of this core) from the Secure SIO, and attach to th
1045    INTERP0 OFFSET(0) NUMBITS(1) []
1046],
1047RISCV_SOFTIRQ [
1048    /// Write 1 to atomically clear the core 1 software interrupt flag. Read to get the
1049    CORE1_CLR OFFSET(9) NUMBITS(1) [],
1050    /// Write 1 to atomically clear the core 0 software interrupt flag. Read to get the
1051    CORE0_CLR OFFSET(8) NUMBITS(1) [],
1052    /// Write 1 to atomically set the core 1 software interrupt flag. Read to get the st
1053    CORE1_SET OFFSET(1) NUMBITS(1) [],
1054    /// Write 1 to atomically set the core 0 software interrupt flag. Read to get the st
1055    CORE0_SET OFFSET(0) NUMBITS(1) []
1056],
1057MTIME_CTRL [
1058    /// If 1, the timer pauses when core 1 is in the debug halt state.
1059    DBGPAUSE_CORE1 OFFSET(3) NUMBITS(1) [],
1060    /// If 1, the timer pauses when core 0 is in the debug halt state.
1061    DBGPAUSE_CORE0 OFFSET(2) NUMBITS(1) [],
1062    /// If 1, increment the timer every cycle (i.e. run directly from the system clock),
1063    FULLSPEED OFFSET(1) NUMBITS(1) [],
1064    /// Timer enable bit. When 0, the timer will not increment automatically.
1065    EN OFFSET(0) NUMBITS(1) []
1066],
1067MTIME [
1068
1069    MTIME OFFSET(0) NUMBITS(32) []
1070],
1071MTIMEH [
1072
1073    MTIMEH OFFSET(0) NUMBITS(32) []
1074],
1075MTIMECMP [
1076
1077    MTIMECMP OFFSET(0) NUMBITS(32) []
1078],
1079MTIMECMPH [
1080
1081    MTIMECMPH OFFSET(0) NUMBITS(32) []
1082],
1083TMDS_CTRL [
1084    /// Clear the running DC balance state of the TMDS encoders. This bit should be writ
1085    CLEAR_BALANCE OFFSET(28) NUMBITS(1) [],
1086    /// When encoding two pixels's worth of symbols in one cycle (a read of a PEEK/POP_D
1087    /// This control disables that shift, so that both encod
1088    PIX2_NOSHIFT OFFSET(27) NUMBITS(1) [],
1089    /// Shift applied to the colour data register with each read of a POP alias register
1090    /// Reading from the POP_SINGLE register, or reading fro
1091    /// Reading from a POP_DOUBLE register when PIX2_NOSHIFT
1092    PIX_SHIFT OFFSET(24) NUMBITS(3) [
1093        /// Do not shift the colour data register.
1094        DoNotShiftTheColourDataRegister = 0,
1095        /// Shift the colour data register by 1 bit
1096        ShiftTheColourDataRegisterBy1Bit = 1,
1097        /// Shift the colour data register by 2 bits
1098        ShiftTheColourDataRegisterBy2Bits = 2,
1099        /// Shift the colour data register by 4 bits
1100        ShiftTheColourDataRegisterBy4Bits = 3,
1101        /// Shift the colour data register by 8 bits
1102        ShiftTheColourDataRegisterBy8Bits = 4,
1103        /// Shift the colour data register by 16 bits
1104        ShiftTheColourDataRegisterBy16Bits = 5
1105    ],
1106    /// Enable lane interleaving for reads of PEEK_SINGLE/POP_SINGLE.
1107    /// When interleaving is disabled, each of the 3 symbols
1108    /// When interleaving is enabled, the symbols are packed
1109    INTERLEAVE OFFSET(23) NUMBITS(1) [],
1110    /// Number of valid colour MSBs for lane 2 (1-8 bits, encoded as 0 through 7). Remai
1111    L2_NBITS OFFSET(18) NUMBITS(3) [],
1112    /// Number of valid colour MSBs for lane 1 (1-8 bits, encoded as 0 through 7). Remai
1113    L1_NBITS OFFSET(15) NUMBITS(3) [],
1114    /// Number of valid colour MSBs for lane 0 (1-8 bits, encoded as 0 through 7). Remai
1115    L0_NBITS OFFSET(12) NUMBITS(3) [],
1116    /// Right-rotate the 16 LSBs of the colour accumulator by 0-15 bits, in order to get
1117    /// For example, for RGB565 (red most significant), red
1118    L2_ROT OFFSET(8) NUMBITS(4) [],
1119    /// Right-rotate the 16 LSBs of the colour accumulator by 0-15 bits, in order to get
1120    /// For example, for RGB565, green is bits 10:5, so shou
1121    L1_ROT OFFSET(4) NUMBITS(4) [],
1122    /// Right-rotate the 16 LSBs of the colour accumulator by 0-15 bits, in order to get
1123    /// For example, for RGB565 (red most significant), blue
1124    L0_ROT OFFSET(0) NUMBITS(4) []
1125],
1126TMDS_WDATA [
1127
1128    TMDS_WDATA OFFSET(0) NUMBITS(32) []
1129],
1130TMDS_PEEK_SINGLE [
1131
1132    TMDS_PEEK_SINGLE OFFSET(0) NUMBITS(32) []
1133],
1134TMDS_POP_SINGLE [
1135
1136    TMDS_POP_SINGLE OFFSET(0) NUMBITS(32) []
1137],
1138TMDS_PEEK_DOUBLE_L0 [
1139
1140    TMDS_PEEK_DOUBLE_L0 OFFSET(0) NUMBITS(32) []
1141],
1142TMDS_POP_DOUBLE_L0 [
1143
1144    TMDS_POP_DOUBLE_L0 OFFSET(0) NUMBITS(32) []
1145],
1146TMDS_PEEK_DOUBLE_L1 [
1147
1148    TMDS_PEEK_DOUBLE_L1 OFFSET(0) NUMBITS(32) []
1149],
1150TMDS_POP_DOUBLE_L1 [
1151
1152    TMDS_POP_DOUBLE_L1 OFFSET(0) NUMBITS(32) []
1153],
1154TMDS_PEEK_DOUBLE_L2 [
1155
1156    TMDS_PEEK_DOUBLE_L2 OFFSET(0) NUMBITS(32) []
1157],
1158TMDS_POP_DOUBLE_L2 [
1159
1160    TMDS_POP_DOUBLE_L2 OFFSET(0) NUMBITS(32) []
1161]
1162];
1163const GPIO_BASE: StaticRef<GpioRegisters> =
1164    unsafe { StaticRef::new(0x40028000 as *const GpioRegisters) };
1165const GPIO_PAD_BASE: StaticRef<GpioPadRegisters> =
1166    unsafe { StaticRef::new(0x40038000 as *const GpioPadRegisters) };
1167const SIO_BASE: StaticRef<SIORegisters> =
1168    unsafe { StaticRef::new(0xD0000000 as *const SIORegisters) };
1169
1170pub struct RPPins<'a> {
1171    pub pins: [RPGpioPin<'a>; 30],
1172    gpio_registers: StaticRef<GpioRegisters>,
1173}
1174
1175impl<'a> RPPins<'a> {
1176    pub const fn new() -> Self {
1177        Self {
1178            pins: [
1179                RPGpioPin::new(RPGpio::GPIO0),
1180                RPGpioPin::new(RPGpio::GPIO1),
1181                RPGpioPin::new(RPGpio::GPIO2),
1182                RPGpioPin::new(RPGpio::GPIO3),
1183                RPGpioPin::new(RPGpio::GPIO4),
1184                RPGpioPin::new(RPGpio::GPIO5),
1185                RPGpioPin::new(RPGpio::GPIO6),
1186                RPGpioPin::new(RPGpio::GPIO7),
1187                RPGpioPin::new(RPGpio::GPIO8),
1188                RPGpioPin::new(RPGpio::GPIO9),
1189                RPGpioPin::new(RPGpio::GPIO10),
1190                RPGpioPin::new(RPGpio::GPIO11),
1191                RPGpioPin::new(RPGpio::GPIO12),
1192                RPGpioPin::new(RPGpio::GPIO13),
1193                RPGpioPin::new(RPGpio::GPIO14),
1194                RPGpioPin::new(RPGpio::GPIO15),
1195                RPGpioPin::new(RPGpio::GPIO16),
1196                RPGpioPin::new(RPGpio::GPIO17),
1197                RPGpioPin::new(RPGpio::GPIO18),
1198                RPGpioPin::new(RPGpio::GPIO19),
1199                RPGpioPin::new(RPGpio::GPIO20),
1200                RPGpioPin::new(RPGpio::GPIO21),
1201                RPGpioPin::new(RPGpio::GPIO22),
1202                RPGpioPin::new(RPGpio::GPIO23),
1203                RPGpioPin::new(RPGpio::GPIO24),
1204                RPGpioPin::new(RPGpio::GPIO25),
1205                RPGpioPin::new(RPGpio::GPIO26),
1206                RPGpioPin::new(RPGpio::GPIO27),
1207                RPGpioPin::new(RPGpio::GPIO28),
1208                RPGpioPin::new(RPGpio::GPIO29),
1209            ],
1210            gpio_registers: GPIO_BASE,
1211        }
1212    }
1213
1214    pub fn get_pin(&self, pin: RPGpio) -> &'a RPGpioPin {
1215        &self.pins[pin as usize]
1216    }
1217
1218    pub fn handle_interrupt(&self) {
1219        for bank_no in 0..4 {
1220            let current_val = self.gpio_registers.intr[bank_no].get();
1221            let enabled_val = self.gpio_registers.interrupt_proc[0].enable[bank_no].get();
1222            for pin in 0..8 {
1223                let l_low_reg_no = pin * 4;
1224                if (current_val & enabled_val & (1 << l_low_reg_no)) != 0 {
1225                    self.pins[pin + bank_no * 8].handle_interrupt();
1226                } else if (current_val & enabled_val & (1 << (l_low_reg_no + 1))) != 0 {
1227                    self.pins[pin + bank_no * 8].handle_interrupt();
1228                } else if (current_val & enabled_val & (1 << (l_low_reg_no + 2))) != 0 {
1229                    self.gpio_registers.intr[bank_no].set(current_val & (1 << (l_low_reg_no + 2)));
1230                    self.pins[pin + bank_no * 8].handle_interrupt();
1231                } else if (current_val & enabled_val & (1 << (l_low_reg_no + 3))) != 0 {
1232                    self.gpio_registers.intr[bank_no].set(current_val & (1 << (l_low_reg_no + 3)));
1233                    self.pins[pin + bank_no * 8].handle_interrupt();
1234                }
1235            }
1236        }
1237    }
1238}
1239
1240enum_from_primitive! {
1241    #[derive(Copy, Clone, PartialEq)]
1242    #[repr(usize)]
1243    #[rustfmt::skip]
1244    pub enum RPGpio {
1245        GPIO0=0, GPIO1=1, GPIO2=2, GPIO3=3, GPIO4=4, GPIO5=5, GPIO6=6, GPIO7=7,
1246        GPIO8=8, GPIO9=9, GPIO10=10, GPIO11=11, GPIO12=12, GPIO13=13, GPIO14=14, GPIO15=15,
1247        GPIO16=16, GPIO17=17, GPIO18=18, GPIO19=19, GPIO20=20, GPIO21=21, GPIO22=22, GPIO23=23,
1248        GPIO24=24, GPIO25=25, GPIO26=26, GPIO27=27, GPIO28=28, GPIO29=29
1249    }
1250}
1251enum_from_primitive! {
1252    #[derive(Copy, Clone, PartialEq)]
1253    #[repr(u32)]
1254    #[rustfmt::skip]
1255
1256    pub enum GpioFunction {
1257       SPI = 1,
1258       UART = 2,
1259       I2C = 3,
1260       PWM = 4,
1261       SIO = 5,
1262       PIO0 = 6,
1263       PIO1 = 7,
1264       PIO2 = 8,
1265       XIP = 9,
1266       USB = 0xa,
1267       NULL = 0x1f
1268    }
1269}
1270
1271pub struct RPGpioPin<'a> {
1272    pin: usize,
1273    client: OptionalCell<&'a dyn hil::gpio::Client>,
1274    gpio_registers: StaticRef<GpioRegisters>,
1275    gpio_pad_registers: StaticRef<GpioPadRegisters>,
1276    sio_registers: StaticRef<SIORegisters>,
1277}
1278
1279#[allow(dead_code)]
1280impl<'a> RPGpioPin<'a> {
1281    pub const fn new(pin: RPGpio) -> RPGpioPin<'a> {
1282        RPGpioPin {
1283            pin: pin as usize,
1284            client: OptionalCell::empty(),
1285            gpio_registers: GPIO_BASE,
1286            gpio_pad_registers: GPIO_PAD_BASE,
1287            sio_registers: SIO_BASE,
1288        }
1289    }
1290
1291    fn get_mode(&self) -> hil::gpio::Configuration {
1292        //TODO - read alternate function
1293        let pad_output_disable = !self.gpio_pad_registers.gpio_pad[self.pin].is_set(GPIO_PAD::OD);
1294        let pin_mask = 1 << self.pin;
1295        let sio_output_enable = (self.sio_registers.gpio_oe.read(GPIO_OE::GPIO_OE) & pin_mask) != 0;
1296
1297        match (pad_output_disable, sio_output_enable) {
1298            (true, true) => hil::gpio::Configuration::Output,
1299            (true, false) => hil::gpio::Configuration::Input,
1300            (false, _) => hil::gpio::Configuration::LowPower,
1301        }
1302    }
1303
1304    fn read_pin(&self) -> bool {
1305        //TODO - read alternate function
1306        let value = self.sio_registers.gpio_out.read(GPIO_OUT::GPIO_OUT) & (1 << self.pin);
1307        value != 0
1308    }
1309
1310    pub fn set_function(&self, f: GpioFunction) {
1311        self.activate_pads();
1312        self.gpio_registers.pin[self.pin]
1313            .ctrl
1314            .write(GPIOx_CTRL::FUNCSEL.val(f as u32));
1315
1316        // Remove the pad isolation
1317        self.gpio_pad_registers.gpio_pad[self.pin].modify(GPIO_PAD::ISO::CLEAR);
1318    }
1319
1320    fn get_pullup_pulldown(&self) -> hil::gpio::FloatingState {
1321        //TODO - read alternate function
1322        let pullup = self.gpio_pad_registers.gpio_pad[self.pin].read(GPIO_PAD::PUE);
1323        let pulldown = self.gpio_pad_registers.gpio_pad[self.pin].read(GPIO_PAD::PDE);
1324
1325        match (pullup, pulldown) {
1326            (0, 0) => hil::gpio::FloatingState::PullNone,
1327            (0, 1) => hil::gpio::FloatingState::PullDown,
1328            (1, 0) => hil::gpio::FloatingState::PullUp,
1329            _ => panic!("Invalid GPIO floating state."),
1330        }
1331    }
1332
1333    pub fn activate_pads(&self) {
1334        self.gpio_pad_registers.gpio_pad[self.pin].modify(GPIO_PAD::OD::CLEAR + GPIO_PAD::IE::SET);
1335    }
1336
1337    pub fn deactivate_pads(&self) {
1338        self.gpio_pad_registers.gpio_pad[self.pin].modify(GPIO_PAD::OD::SET + GPIO_PAD::IE::CLEAR);
1339    }
1340
1341    pub fn handle_interrupt(&self) {
1342        self.client.map(|client| client.fired());
1343    }
1344
1345    pub fn make_output(&self) {
1346        self.set_function(GpioFunction::SIO);
1347        self.activate_pads();
1348        self.sio_registers.gpio_oe_set.set(1 << self.pin);
1349    }
1350
1351    pub fn set_pin(&self) {
1352        self.sio_registers.gpio_out_set.set(1 << self.pin);
1353    }
1354}
1355
1356impl<'a> hil::gpio::Interrupt<'a> for RPGpioPin<'a> {
1357    fn set_client(&self, client: &'a dyn hil::gpio::Client) {
1358        self.client.set(client);
1359    }
1360
1361    fn is_pending(&self) -> bool {
1362        let interrupt_bank_no = self.pin / 8;
1363        let l_low_reg_no = (self.pin * 4) % 32;
1364        let current_val = self.gpio_registers.interrupt_proc[0].status[interrupt_bank_no].get();
1365        (current_val
1366            & (1 << l_low_reg_no)
1367            & (1 << (l_low_reg_no + 1))
1368            & (1 << (l_low_reg_no + 2))
1369            & (1 << (l_low_reg_no + 3)))
1370            != 0
1371    }
1372
1373    fn enable_interrupts(&self, mode: hil::gpio::InterruptEdge) {
1374        let interrupt_bank_no = self.pin / 8;
1375        match mode {
1376            hil::gpio::InterruptEdge::RisingEdge => {
1377                let high_reg_no = (self.pin * 4 + 3) % 32;
1378                let current_val =
1379                    self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no].get();
1380                self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no]
1381                    .set((1 << high_reg_no) | current_val);
1382            }
1383            hil::gpio::InterruptEdge::FallingEdge => {
1384                let low_reg_no = (self.pin * 4 + 2) % 32;
1385                let current_val =
1386                    self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no].get();
1387                self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no]
1388                    .set((1 << low_reg_no) | current_val);
1389            }
1390            hil::gpio::InterruptEdge::EitherEdge => {
1391                let low_reg_no = (self.pin * 4 + 2) % 32;
1392                let high_reg_no = low_reg_no + 1;
1393                let current_val =
1394                    self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no].get();
1395                self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no]
1396                    .set((1 << high_reg_no) | (1 << low_reg_no) | current_val);
1397            }
1398        }
1399    }
1400
1401    fn disable_interrupts(&self) {
1402        let interrupt_bank_no = self.pin / 8;
1403        let low_reg_no = (self.pin * 4 + 2) % 32;
1404        let high_reg_no = low_reg_no + 1;
1405        let current_val = self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no].get();
1406        self.gpio_registers.interrupt_proc[0].enable[interrupt_bank_no]
1407            .set(current_val & !(1 << high_reg_no) & !(1 << low_reg_no));
1408    }
1409}
1410
1411impl hil::gpio::Configure for RPGpioPin<'_> {
1412    fn configuration(&self) -> hil::gpio::Configuration {
1413        self.get_mode()
1414    }
1415    /// Set output mode
1416    fn make_output(&self) -> hil::gpio::Configuration {
1417        self.set_function(GpioFunction::SIO);
1418        self.activate_pads();
1419        self.sio_registers.gpio_oe_set.set(1 << self.pin);
1420        self.get_mode()
1421    }
1422    /// Disable pad output
1423    fn disable_output(&self) -> hil::gpio::Configuration {
1424        self.set_function(GpioFunction::SIO);
1425        self.gpio_pad_registers.gpio_pad[self.pin].modify(GPIO_PAD::OD::SET);
1426        self.get_mode()
1427    }
1428    /// Set input mode
1429    fn make_input(&self) -> hil::gpio::Configuration {
1430        self.set_function(GpioFunction::SIO);
1431        self.activate_pads();
1432        self.sio_registers.gpio_oe_clr.set(1 << self.pin);
1433        self.get_mode()
1434    }
1435    /// Disable input mode, will set pin to output mode
1436    fn disable_input(&self) -> hil::gpio::Configuration {
1437        self.make_output();
1438        self.get_mode()
1439    }
1440    fn deactivate_to_low_power(&self) {
1441        self.set_function(GpioFunction::SIO);
1442        self.gpio_pad_registers.gpio_pad[self.pin].modify(GPIO_PAD::OD::SET);
1443    }
1444
1445    fn set_floating_state(&self, mode: hil::gpio::FloatingState) {
1446        match mode {
1447            hil::gpio::FloatingState::PullUp => self.gpio_pad_registers.gpio_pad[self.pin]
1448                .modify(GPIO_PAD::PUE::SET + GPIO_PAD::PDE::CLEAR),
1449            hil::gpio::FloatingState::PullDown => self.gpio_pad_registers.gpio_pad[self.pin]
1450                .modify(GPIO_PAD::PUE::CLEAR + GPIO_PAD::PDE::SET),
1451            hil::gpio::FloatingState::PullNone => self.gpio_pad_registers.gpio_pad[self.pin]
1452                .modify(GPIO_PAD::PUE::CLEAR + GPIO_PAD::PDE::CLEAR),
1453        }
1454    }
1455
1456    fn floating_state(&self) -> hil::gpio::FloatingState {
1457        self.get_pullup_pulldown()
1458    }
1459
1460    fn is_input(&self) -> bool {
1461        let mode = self.get_mode();
1462        match mode {
1463            hil::gpio::Configuration::Input => true,
1464            hil::gpio::Configuration::InputOutput => true,
1465            _ => false,
1466        }
1467    }
1468
1469    fn is_output(&self) -> bool {
1470        let mode = self.get_mode();
1471        match mode {
1472            hil::gpio::Configuration::Output => true,
1473            hil::gpio::Configuration::InputOutput => true,
1474            _ => false,
1475        }
1476    }
1477}
1478
1479impl hil::gpio::Output for RPGpioPin<'_> {
1480    fn set(&self) {
1481        // For performance this match might be skipped
1482        match self.get_mode() {
1483            hil::gpio::Configuration::Output | hil::gpio::Configuration::InputOutput => {
1484                self.sio_registers.gpio_out_set.set(1 << self.pin);
1485            }
1486            _ => {}
1487        }
1488    }
1489
1490    fn clear(&self) {
1491        // For performance this match might be skipped
1492        match self.get_mode() {
1493            hil::gpio::Configuration::Output | hil::gpio::Configuration::InputOutput => {
1494                self.sio_registers.gpio_out_clr.set(1 << self.pin);
1495            }
1496            _ => {}
1497        }
1498    }
1499
1500    fn toggle(&self) -> bool {
1501        match self.get_mode() {
1502            hil::gpio::Configuration::Output | hil::gpio::Configuration::InputOutput => {
1503                self.sio_registers.gpio_out_xor.set(1 << self.pin);
1504            }
1505            _ => {}
1506        }
1507        self.read_pin()
1508    }
1509}
1510
1511impl hil::gpio::Input for RPGpioPin<'_> {
1512    fn read(&self) -> bool {
1513        let value = self.sio_registers.gpio_in.read(GPIO_IN::GPIO_IN) & (1 << self.pin);
1514        value != 0
1515    }
1516}
1517
1518pub struct SIO {
1519    registers: StaticRef<SIORegisters>,
1520}
1521
1522impl SIO {
1523    pub const fn new() -> Self {
1524        Self {
1525            registers: SIO_BASE,
1526        }
1527    }
1528
1529    pub fn handle_proc_interrupt(&self, for_processor: Processor) {
1530        match for_processor {
1531            Processor::Processor0 => {
1532                // read data from the fifo
1533                self.registers.fifo_rd.get();
1534                self.registers.fifo_st.set(0xff);
1535            }
1536            Processor::Processor1 => {
1537                if self.registers.cpuid.get() == 1 {
1538                    panic!("Kernel should not run on processor 1");
1539                } else {
1540                    panic!("SIO_PROC1_IRQ should be ignored for processor 1");
1541                }
1542            }
1543        }
1544    }
1545
1546    pub fn get_processor(&self) -> Processor {
1547        let proc_id = self.registers.cpuid.get();
1548        match proc_id {
1549            0 => Processor::Processor0,
1550            1 => Processor::Processor1,
1551            _ => panic!("SIO CPUID cannot be {}", proc_id),
1552        }
1553    }
1554}