1use kernel::hil::gpio;
22use kernel::utilities::cells::OptionalCell;
23use kernel::utilities::registers::interfaces::{Readable, Writeable};
24use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite, WriteOnly};
25use kernel::utilities::StaticRef;
26
27register_structs! {
28 pub GpioRegisters {
29 (0x0000 => _reserved0: [u8; 0x2000]),
30 (0x2000 => dir_0: ReadWrite<u32, DIR::Register>),
31 (0x2004 => dir_1: ReadWrite<u32, DIR::Register>),
32 (0x2008 => _reserved1: [u8; 0x78]),
33 (0x2080 => mask_0: ReadWrite<u32, MASK::Register>),
34 (0x2084 => mask_1: ReadWrite<u32, MASK::Register>),
35 (0x2088 => _reserved2: [u8; 0x78]),
36 (0x2100 => pin_0: ReadWrite<u32, PIN::Register>),
37 (0x2104 => pin_1: ReadWrite<u32, PIN::Register>),
38 (0x2108 => _reserved3: [u8; 0x78]),
39 (0x2180 => mpin_0: ReadWrite<u32, MPIN::Register>),
40 (0x2184 => mpin_1: ReadWrite<u32, MPIN::Register>),
41 (0x2188 => _reserved4: [u8; 0x78]),
42 (0x2200 => set_0: WriteOnly<u32, SET::Register>),
43 (0x2204 => set_1: WriteOnly<u32, SET::Register>),
44 (0x2208 => _reserved5: [u8; 0x78]),
45 (0x2280 => clr_0: WriteOnly<u32, CLR::Register>),
46 (0x2284 => clr_1: WriteOnly<u32, CLR::Register>),
47 (0x2288 => _reserved6: [u8; 0x78]),
48 (0x2300 => not_0: WriteOnly<u32, NOT::Register>),
49 (0x2304 => not_1: WriteOnly<u32, NOT::Register>),
50 (0x2308 => _reserved7: [u8; 0x78]),
51 (0x2380 => dirset_0: WriteOnly<u32, DIRSET::Register>),
52 (0x2384 => dirset_1: WriteOnly<u32, DIRSET::Register>),
53 (0x2388 => _reserved8: [u8; 0x78]),
54 (0x2400 => dirclr_0: WriteOnly<u32, DIRCLR::Register>),
55 (0x2404 => dirclr_1: WriteOnly<u32, DIRCLR::Register>),
56 (0x2408 => _reserved9: [u8; 0x78]),
57 (0x2480 => dirnot_0: WriteOnly<u32, DIRNOT::Register>),
58 (0x2484 => dirnot_1: WriteOnly<u32, DIRNOT::Register>),
59 (0x2488 => @END),
60 }
61}
62
63register_bitfields![u32,
64 DIR [ DIRP OFFSET(0) NUMBITS(32) [] ], MASK [ MASKP OFFSET(0) NUMBITS(32) [] ],
65 PIN [ PORT OFFSET(0) NUMBITS(32) [] ], MPIN [ MPORTP OFFSET(0) NUMBITS(32) [] ],
66 SET [ SETP OFFSET(0) NUMBITS(32) [] ], CLR [ CLRP OFFSET(0) NUMBITS(32) [] ],
67 NOT [ NOTP OFFSET(0) NUMBITS(32) [] ], DIRSET [ DIRSETP OFFSET(0) NUMBITS(32) [] ],
68 DIRCLR [ DIRCLRP OFFSET(0) NUMBITS(32) [] ], DIRNOT [ DIRNOTP OFFSET(0) NUMBITS(32) [] ]
69];
70
71pub(crate) const GPIO_BASE: StaticRef<GpioRegisters> =
72 unsafe { StaticRef::new(0x5008_C000 as *const GpioRegisters) };
73
74#[derive(Clone, Copy, Debug, PartialEq)]
75#[allow(non_camel_case_types)]
76pub enum LPCPin {
77 P0_0 = 0,
78 P0_1 = 1,
79 P0_2 = 2,
80 P0_3 = 3,
81 P0_4 = 4,
82 P0_5 = 5,
83 P0_6 = 6,
84 P0_7 = 7,
85 P0_8 = 8,
86 P0_9 = 9,
87 P0_10 = 10,
88 P0_11 = 11,
89 P0_12 = 12,
90 P0_13 = 13,
91 P0_14 = 14,
92 P0_15 = 15,
93 P0_16 = 16,
94 P0_17 = 17,
95 P0_18 = 18,
96 P0_19 = 19,
97 P0_20 = 20,
98 P0_21 = 21,
99 P0_22 = 22,
100 P0_23 = 23,
101 P0_24 = 24,
102 P0_25 = 25,
103 P0_26 = 26,
104 P0_27 = 27,
105 P0_28 = 28,
106 P0_29 = 29,
107 P0_30 = 30,
108 P0_31 = 31,
109 P1_0 = 32,
110 P1_1 = 33,
111 P1_2 = 34,
112 P1_3 = 35,
113 P1_4 = 36,
114 P1_5 = 37,
115 P1_6 = 38,
116 P1_7 = 39,
117 P1_8 = 40,
118 P1_9 = 41,
119 P1_10 = 42,
120 P1_11 = 43,
121 P1_12 = 44,
122 P1_13 = 45,
123 P1_14 = 46,
124 P1_15 = 47,
125 P1_16 = 48,
126 P1_17 = 49,
127 P1_18 = 50,
128 P1_19 = 51,
129 P1_20 = 52,
130 P1_21 = 53,
131 P1_22 = 54,
132 P1_23 = 55,
133 P1_24 = 56,
134 P1_25 = 57,
135 P1_26 = 58,
136 P1_27 = 59,
137 P1_28 = 60,
138 P1_29 = 61,
139 P1_30 = 62,
140 P1_31 = 63,
141}
142
143#[repr(u8)]
144#[derive(Copy, Clone, Debug, PartialEq, Eq)]
145pub enum Port {
146 Port0 = 0,
147 Port1 = 1,
148}
149
150pub struct Pins<'a> {
151 pub pins: [GpioPin<'a>; 64],
152 pub inputmux: Inputmux,
153 pub iocon: Iocon,
154 pub pint: Pint<'a>,
155}
156
157impl<'a> Pins<'a> {
158 pub const fn new() -> Self {
159 let inputmux = Inputmux::new();
160 let iocon = Iocon::new();
161 let pint = Pint::new();
162 Self {
163 pins: [
164 GpioPin::new(LPCPin::P0_0),
165 GpioPin::new(LPCPin::P0_1),
166 GpioPin::new(LPCPin::P0_2),
167 GpioPin::new(LPCPin::P0_3),
168 GpioPin::new(LPCPin::P0_4),
169 GpioPin::new(LPCPin::P0_5),
170 GpioPin::new(LPCPin::P0_6),
171 GpioPin::new(LPCPin::P0_7),
172 GpioPin::new(LPCPin::P0_8),
173 GpioPin::new(LPCPin::P0_9),
174 GpioPin::new(LPCPin::P0_10),
175 GpioPin::new(LPCPin::P0_11),
176 GpioPin::new(LPCPin::P0_12),
177 GpioPin::new(LPCPin::P0_13),
178 GpioPin::new(LPCPin::P0_14),
179 GpioPin::new(LPCPin::P0_15),
180 GpioPin::new(LPCPin::P0_16),
181 GpioPin::new(LPCPin::P0_17),
182 GpioPin::new(LPCPin::P0_18),
183 GpioPin::new(LPCPin::P0_19),
184 GpioPin::new(LPCPin::P0_20),
185 GpioPin::new(LPCPin::P0_21),
186 GpioPin::new(LPCPin::P0_22),
187 GpioPin::new(LPCPin::P0_23),
188 GpioPin::new(LPCPin::P0_24),
189 GpioPin::new(LPCPin::P0_25),
190 GpioPin::new(LPCPin::P0_26),
191 GpioPin::new(LPCPin::P0_27),
192 GpioPin::new(LPCPin::P0_28),
193 GpioPin::new(LPCPin::P0_29),
194 GpioPin::new(LPCPin::P0_30),
195 GpioPin::new(LPCPin::P0_31),
196 GpioPin::new(LPCPin::P1_0),
197 GpioPin::new(LPCPin::P1_1),
198 GpioPin::new(LPCPin::P1_2),
199 GpioPin::new(LPCPin::P1_3),
200 GpioPin::new(LPCPin::P1_4),
201 GpioPin::new(LPCPin::P1_5),
202 GpioPin::new(LPCPin::P1_6),
203 GpioPin::new(LPCPin::P1_7),
204 GpioPin::new(LPCPin::P1_8),
205 GpioPin::new(LPCPin::P1_9),
206 GpioPin::new(LPCPin::P1_10),
207 GpioPin::new(LPCPin::P1_11),
208 GpioPin::new(LPCPin::P1_12),
209 GpioPin::new(LPCPin::P1_13),
210 GpioPin::new(LPCPin::P1_14),
211 GpioPin::new(LPCPin::P1_15),
212 GpioPin::new(LPCPin::P1_16),
213 GpioPin::new(LPCPin::P1_17),
214 GpioPin::new(LPCPin::P1_18),
215 GpioPin::new(LPCPin::P1_19),
216 GpioPin::new(LPCPin::P1_20),
217 GpioPin::new(LPCPin::P1_21),
218 GpioPin::new(LPCPin::P1_22),
219 GpioPin::new(LPCPin::P1_23),
220 GpioPin::new(LPCPin::P1_24),
221 GpioPin::new(LPCPin::P1_25),
222 GpioPin::new(LPCPin::P1_26),
223 GpioPin::new(LPCPin::P1_27),
224 GpioPin::new(LPCPin::P1_28),
225 GpioPin::new(LPCPin::P1_29),
226 GpioPin::new(LPCPin::P1_30),
227 GpioPin::new(LPCPin::P1_31),
228 ],
229 inputmux,
230 iocon,
231 pint,
232 }
233 }
234 pub fn get_pin(&self, searched_pin: LPCPin) -> &GpioPin<'a> {
245 &self.pins[searched_pin as usize]
246 }
247
248 pub fn handle_interrupt(&self) {
249 self.pint.handle_interrupt();
250
251 for pin in self.pins.iter() {
252 pin.handle_interrupt();
253 }
254 }
255
256 pub fn set_inputmux(&'a self) {
257 for pin in self.pins.iter() {
258 pin.set_inputmux(&self.inputmux);
259 }
260 }
261
262 pub fn set_iocon(&'a self) {
263 for pin in self.pins.iter() {
264 pin.set_iocon(&self.iocon);
265 }
266 }
267
268 pub fn set_pint(&'a self) {
269 for pin in self.pins.iter() {
270 pin.set_pint(&self.pint);
271 }
272 }
273
274 pub fn init(&'a self) {
275 self.set_inputmux();
276 self.set_iocon();
277 self.set_pint();
278 }
279}
280
281pub struct GpioPin<'a> {
282 registers: StaticRef<GpioRegisters>,
283 port: Port,
284 pin: u8,
285 client: OptionalCell<&'a dyn gpio::Client>,
286 inputmux: OptionalCell<&'a Inputmux>,
287 iocon: OptionalCell<&'a Iocon>,
288 pint: OptionalCell<&'a Pint<'a>>,
289}
290
291pub use kernel::hil::gpio::{Configure, Input, Interrupt, Output, Pin};
292
293use crate::inputmux::Inputmux;
294use crate::iocon::Iocon;
295use crate::pint::{Edge, Pint};
296
297impl<'a> GpioPin<'a> {
298 pub const fn new(pin_name: LPCPin) -> Self {
299 let pin_num = pin_name as u8;
300 let port = match pin_num / 32 {
301 0 => Port::Port0,
302 1 => Port::Port1,
303 _ => panic!("Invalid pin number for LPCPin"),
304 };
305 Self {
306 registers: GPIO_BASE,
307 port,
308 pin: pin_num % 32,
309 client: OptionalCell::empty(),
310 inputmux: OptionalCell::empty(),
311 iocon: OptionalCell::empty(),
312 pint: OptionalCell::empty(),
313 }
314 }
315
316 fn pin_mask(&self) -> u32 {
317 1 << self.pin
318 }
319
320 fn is_output(&self) -> bool {
321 match self.port {
322 Port::Port0 => (self.registers.dir_0.get() & self.pin_mask()) != 0,
323 Port::Port1 => (self.registers.dir_1.get() & self.pin_mask()) != 0,
324 }
325 }
326
327 pub fn get_pin_num(&self) -> usize {
328 (self.port as usize * 32) + self.pin as usize
329 }
330
331 pub fn handle_interrupt(&self) {
332 self.pint.map(|pint| {
333 pint.handle_interrupt();
334 });
335 }
336
337 pub fn set_inputmux(&self, inputmux: &'a Inputmux) {
338 self.inputmux.set(inputmux);
339 }
340 pub fn set_iocon(&self, iocon: &'a Iocon) {
341 self.iocon.set(iocon);
342 }
343 pub fn set_pint(&self, pint: &'a Pint<'a>) {
344 self.pint.set(pint);
345 }
346}
347
348impl gpio::Output for GpioPin<'_> {
349 fn set(&self) {
350 match self.port {
351 Port::Port0 => self.registers.set_0.write(SET::SETP.val(self.pin_mask())),
352 Port::Port1 => self.registers.set_1.write(SET::SETP.val(self.pin_mask())),
353 }
354 }
355
356 fn clear(&self) {
357 match self.port {
358 Port::Port0 => self.registers.clr_0.write(CLR::CLRP.val(self.pin_mask())),
359 Port::Port1 => self.registers.clr_1.write(CLR::CLRP.val(self.pin_mask())),
360 }
361 }
362
363 fn toggle(&self) -> bool {
364 match self.port {
365 Port::Port0 => self.registers.not_0.write(NOT::NOTP.val(self.pin_mask())),
366 Port::Port1 => self.registers.not_1.write(NOT::NOTP.val(self.pin_mask())),
367 }
368 self.read()
369 }
370}
371
372impl gpio::Input for GpioPin<'_> {
373 fn read(&self) -> bool {
374 match self.port {
375 Port::Port0 => self.registers.pin_0.get() & self.pin_mask() != 0,
376 Port::Port1 => self.registers.pin_1.get() & self.pin_mask() != 0,
377 }
378 }
379}
380
381impl gpio::Configure for GpioPin<'_> {
382 fn make_output(&self) -> gpio::Configuration {
383 match self.port {
384 Port::Port0 => self
385 .registers
386 .dirset_0
387 .write(DIRSET::DIRSETP.val(self.pin_mask())),
388 Port::Port1 => self
389 .registers
390 .dirset_1
391 .write(DIRSET::DIRSETP.val(self.pin_mask())),
392 }
393 gpio::Configuration::Output
394 }
395
396 fn make_input(&self) -> gpio::Configuration {
397 match self.port {
398 Port::Port0 => self
399 .registers
400 .dirclr_0
401 .write(DIRCLR::DIRCLRP.val(self.pin_mask())),
402 Port::Port1 => self
403 .registers
404 .dirclr_1
405 .write(DIRCLR::DIRCLRP.val(self.pin_mask())),
406 }
407 gpio::Configuration::Input
408 }
409
410 fn configuration(&self) -> gpio::Configuration {
411 if self.is_output() {
412 gpio::Configuration::Output
413 } else {
414 gpio::Configuration::Input
415 }
416 }
417
418 fn set_floating_state(&self, state: kernel::hil::gpio::FloatingState) {
419 let pins = [
420 LPCPin::P0_0,
421 LPCPin::P0_1,
422 LPCPin::P0_2,
423 LPCPin::P0_3,
424 LPCPin::P0_4,
425 LPCPin::P0_5,
426 LPCPin::P0_6,
427 LPCPin::P0_7,
428 LPCPin::P0_8,
429 LPCPin::P0_9,
430 LPCPin::P0_10,
431 LPCPin::P0_11,
432 LPCPin::P0_12,
433 LPCPin::P0_13,
434 LPCPin::P0_14,
435 LPCPin::P0_15,
436 LPCPin::P0_16,
437 LPCPin::P0_17,
438 LPCPin::P0_18,
439 LPCPin::P0_19,
440 LPCPin::P0_20,
441 LPCPin::P0_21,
442 LPCPin::P0_22,
443 LPCPin::P0_23,
444 LPCPin::P0_24,
445 LPCPin::P0_25,
446 LPCPin::P0_26,
447 LPCPin::P0_27,
448 LPCPin::P0_28,
449 LPCPin::P0_29,
450 LPCPin::P0_30,
451 LPCPin::P0_31,
452 LPCPin::P1_0,
453 LPCPin::P1_1,
454 LPCPin::P1_2,
455 LPCPin::P1_3,
456 LPCPin::P1_4,
457 LPCPin::P1_5,
458 LPCPin::P1_6,
459 LPCPin::P1_7,
460 LPCPin::P1_8,
461 LPCPin::P1_9,
462 LPCPin::P1_10,
463 LPCPin::P1_11,
464 LPCPin::P1_12,
465 LPCPin::P1_13,
466 LPCPin::P1_14,
467 LPCPin::P1_15,
468 LPCPin::P1_16,
469 LPCPin::P1_17,
470 LPCPin::P1_18,
471 LPCPin::P1_19,
472 LPCPin::P1_20,
473 LPCPin::P1_21,
474 LPCPin::P1_22,
475 LPCPin::P1_23,
476 LPCPin::P1_24,
477 LPCPin::P1_25,
478 LPCPin::P1_26,
479 LPCPin::P1_27,
480 LPCPin::P1_28,
481 LPCPin::P1_29,
482 LPCPin::P1_30,
483 LPCPin::P1_31,
484 ];
485
486 for pin in pins.iter() {
487 match state {
488 gpio::FloatingState::PullNone => {
489 self.iocon.map(|iocon| {
490 iocon.set_pull_none(*pin);
491 });
492 }
493 gpio::FloatingState::PullUp => {
494 self.iocon.map(|iocon| {
495 iocon.set_pull_up(*pin);
496 });
497 }
498 gpio::FloatingState::PullDown => {
499 self.iocon.map(|iocon| {
500 iocon.set_pull_down(*pin);
501 });
502 }
503 }
504 }
505 }
506 fn floating_state(&self) -> gpio::FloatingState {
507 gpio::FloatingState::PullNone
508 }
509 fn disable_input(&self) -> gpio::Configuration {
510 self.make_output()
511 }
512 fn disable_output(&self) -> gpio::Configuration {
513 self.make_input()
514 }
515 fn deactivate_to_low_power(&self) {
516 let _state = gpio::FloatingState::PullNone;
517 self.make_input();
518 }
519}
520
521impl<'a> gpio::Interrupt<'a> for GpioPin<'a> {
522 fn set_client(&self, client: &'a dyn gpio::Client) {
523 self.client.set(client);
524 self.pint.map(|pint| {
525 pint.set_client(0, client);
526 });
527 }
528
529 fn enable_interrupts(&self, mode: gpio::InterruptEdge) {
530 match mode {
531 gpio::InterruptEdge::RisingEdge => {
532 self.pint.map(|pint| {
533 pint.configure_interrupt(0, Edge::Rising);
534 });
535 }
536 gpio::InterruptEdge::FallingEdge => {
537 self.pint.map(|pint| {
538 pint.configure_interrupt(0, Edge::Falling);
539 });
540 }
541 gpio::InterruptEdge::EitherEdge => {
542 self.pint.map(|pint| {
543 pint.configure_interrupt(0, Edge::Both);
544 });
545 }
546 }
547 }
548
549 fn disable_interrupts(&self) {
550 self.pint.map(|pint| {
551 pint.disable_interrupt(0);
552 });
553 }
554
555 fn is_pending(&self) -> bool {
556 self.pint.map_or(false, |pint| {
557 let channel = 0;
558 pint.is_pending(channel)
559 })
560 }
561}