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