1use core::ops::{Index, IndexMut};
8
9use kernel::utilities::StaticRef;
10use lowrisc::gpio::GpioRegisters;
11pub use lowrisc::gpio::{pins, GpioBitfield, GpioPin};
12
13use crate::pinmux::PadConfig;
14use crate::pinmux_config::EarlGreyPinmuxConfig;
15use crate::registers::top_earlgrey::GPIO_BASE_ADDR;
16use crate::registers::top_earlgrey::{
17 MuxedPads, PinmuxInsel, PinmuxOutsel, PinmuxPeripheralIn, PINMUX_MIO_PERIPH_INSEL_IDX_OFFSET,
18};
19
20pub const GPIO_BASE: StaticRef<GpioRegisters> =
21 unsafe { StaticRef::new(GPIO_BASE_ADDR as *const GpioRegisters) };
22
23pub struct Port<'a> {
24 pins: [GpioPin<'a, PadConfig>; 32],
25}
26
27impl From<PinmuxPeripheralIn> for PinmuxOutsel {
28 fn from(pin: PinmuxPeripheralIn) -> Self {
29 match pin {
30 PinmuxPeripheralIn::GpioGpio0 => PinmuxOutsel::GpioGpio0,
31 PinmuxPeripheralIn::GpioGpio1 => PinmuxOutsel::GpioGpio1,
32 PinmuxPeripheralIn::GpioGpio2 => PinmuxOutsel::GpioGpio2,
33 PinmuxPeripheralIn::GpioGpio3 => PinmuxOutsel::GpioGpio3,
34 PinmuxPeripheralIn::GpioGpio4 => PinmuxOutsel::GpioGpio4,
35 PinmuxPeripheralIn::GpioGpio5 => PinmuxOutsel::GpioGpio5,
36 PinmuxPeripheralIn::GpioGpio6 => PinmuxOutsel::GpioGpio6,
37 PinmuxPeripheralIn::GpioGpio7 => PinmuxOutsel::GpioGpio7,
38 PinmuxPeripheralIn::GpioGpio8 => PinmuxOutsel::GpioGpio8,
39 PinmuxPeripheralIn::GpioGpio9 => PinmuxOutsel::GpioGpio9,
40 PinmuxPeripheralIn::GpioGpio10 => PinmuxOutsel::GpioGpio10,
41 PinmuxPeripheralIn::GpioGpio11 => PinmuxOutsel::GpioGpio11,
42 PinmuxPeripheralIn::GpioGpio12 => PinmuxOutsel::GpioGpio12,
43 PinmuxPeripheralIn::GpioGpio13 => PinmuxOutsel::GpioGpio13,
44 PinmuxPeripheralIn::GpioGpio14 => PinmuxOutsel::GpioGpio14,
45 PinmuxPeripheralIn::GpioGpio15 => PinmuxOutsel::GpioGpio15,
46 PinmuxPeripheralIn::GpioGpio16 => PinmuxOutsel::GpioGpio16,
47 PinmuxPeripheralIn::GpioGpio17 => PinmuxOutsel::GpioGpio17,
48 PinmuxPeripheralIn::GpioGpio18 => PinmuxOutsel::GpioGpio18,
49 PinmuxPeripheralIn::GpioGpio19 => PinmuxOutsel::GpioGpio19,
50 PinmuxPeripheralIn::GpioGpio20 => PinmuxOutsel::GpioGpio20,
51 PinmuxPeripheralIn::GpioGpio21 => PinmuxOutsel::GpioGpio21,
52 PinmuxPeripheralIn::GpioGpio22 => PinmuxOutsel::GpioGpio22,
53 PinmuxPeripheralIn::GpioGpio23 => PinmuxOutsel::GpioGpio23,
54 PinmuxPeripheralIn::GpioGpio24 => PinmuxOutsel::GpioGpio24,
55 PinmuxPeripheralIn::GpioGpio25 => PinmuxOutsel::GpioGpio25,
56 PinmuxPeripheralIn::GpioGpio26 => PinmuxOutsel::GpioGpio26,
57 PinmuxPeripheralIn::GpioGpio27 => PinmuxOutsel::GpioGpio27,
58 PinmuxPeripheralIn::GpioGpio28 => PinmuxOutsel::GpioGpio28,
59 PinmuxPeripheralIn::GpioGpio29 => PinmuxOutsel::GpioGpio29,
60 PinmuxPeripheralIn::GpioGpio30 => PinmuxOutsel::GpioGpio30,
61 PinmuxPeripheralIn::GpioGpio31 => PinmuxOutsel::GpioGpio31,
62 _ => PinmuxOutsel::ConstantHighZ,
63 }
64 }
65}
66
67pub fn gpio_pad_config<Layout: EarlGreyPinmuxConfig>(pin: PinmuxPeripheralIn) -> PadConfig {
69 match Layout::INPUT[pin as usize] {
70 PinmuxInsel::ConstantZero | PinmuxInsel::ConstantOne => PadConfig::Unconnected,
72 input_selector => {
73 if let Ok(pad) = MuxedPads::try_from(
74 input_selector as u32 - PINMUX_MIO_PERIPH_INSEL_IDX_OFFSET as u32,
75 ) {
76 let out: PinmuxOutsel = Layout::OUTPUT[pad as usize];
77 if out == PinmuxOutsel::from(pin) {
79 PadConfig::InOut(pad, pin, out)
80 } else {
81 PadConfig::Input(pad, pin)
82 }
83 } else {
84 PadConfig::Unconnected
87 }
88 }
89 }
90}
91
92impl Port<'_> {
94 pub fn new<Layout: EarlGreyPinmuxConfig>() -> Self {
95 Self {
96 #[rustfmt::skip]
98 pins: [
99 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio0), pins::pin0),
100 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio1), pins::pin1),
101 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio2), pins::pin2),
102 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio3), pins::pin3),
103 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio4), pins::pin4),
104 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio5), pins::pin5),
105 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio6), pins::pin6),
106 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio7), pins::pin7),
107 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio8), pins::pin8),
108 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio9), pins::pin9),
109 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio10), pins::pin10),
110 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio11), pins::pin11),
111 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio12), pins::pin12),
112 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio13), pins::pin13),
113 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio14), pins::pin14),
114 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio15), pins::pin15),
115 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio16), pins::pin16),
116 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio17), pins::pin17),
117 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio18), pins::pin18),
118 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio19), pins::pin19),
119 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio20), pins::pin20),
120 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio21), pins::pin21),
121 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio22), pins::pin22),
122 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio23), pins::pin23),
123 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio24), pins::pin24),
124 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio25), pins::pin25),
125 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio26), pins::pin26),
126 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio27), pins::pin27),
127 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio28), pins::pin28),
128 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio29), pins::pin29),
129 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio30), pins::pin30),
130 GpioPin::new(GPIO_BASE, gpio_pad_config::<Layout>(PinmuxPeripheralIn::GpioGpio31), pins::pin31),
131 ],
132 }
133 }
134}
135
136impl<'a> Index<usize> for Port<'a> {
137 type Output = GpioPin<'a, PadConfig>;
138
139 fn index(&self, index: usize) -> &GpioPin<'a, PadConfig> {
140 &self.pins[index]
141 }
142}
143
144impl<'a> IndexMut<usize> for Port<'a> {
145 fn index_mut(&mut self, index: usize) -> &mut GpioPin<'a, PadConfig> {
146 &mut self.pins[index]
147 }
148}