lpc55s6x/
pint.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 Tock Contributors 2025.
4
5//! Pin Interrupt (PINT) driver for the LPC55S6x family.
6//!
7//! The PINT block provides edge‑sensitive and pattern‑match interrupt
8//! generation from GPIO pins. It works in conjunction with the IOCON and
9//! INPUTMUX modules to route physical pins into the PINT channels.
10//!
11//! Features supported:
12//! - Up to 8 independent pin interrupt channels
13//! - Configurable rising, falling, or both‑edge detection
14//! - Pattern match engine for complex multi‑pin conditions
15//! - Interrupt status and enable/disable control per channel
16//! - Integration with NVIC for interrupt delivery to the Cortex‑M33 core
17//!
18//! Reference: *LPC55S6x/LPC55S2x/LPC552x User Manual* (NXP).
19
20use kernel::utilities::cells::OptionalCell;
21use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
22use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite, WriteOnly};
23use kernel::utilities::StaticRef;
24
25register_structs! {
26    pub PintRegisters {
27        /// Pin Interrupt Mode register
28        (0x00 => isel: ReadWrite<u32, ISEL::Register>),
29        /// Pin interrupt level or rising edge interrupt enable register
30        (0x04 => ienr: ReadWrite<u32, IENR::Register>),
31        /// Pin interrupt level or rising edge interrupt set register
32        (0x08 => sienr: WriteOnly<u32, SIENR::Register>),
33        /// Pin interrupt level (rising edge interrupt) clear register
34        (0x0C => cienr: WriteOnly<u32, CIENR::Register>),
35        /// Pin interrupt active level or falling edge interrupt enable register
36        (0x10 => ienf: ReadWrite<u32, IENF::Register>),
37        /// Pin interrupt active level or falling edge interrupt set register
38        (0x14 => sienf: WriteOnly<u32, SIENF::Register>),
39        /// Pin interrupt active level or falling edge interrupt clear register
40        (0x18 => cienf: WriteOnly<u32, CIENF::Register>),
41        /// Pin interrupt rising edge register
42        (0x1C => rise: ReadWrite<u32, RISE::Register>),
43        /// Pin interrupt falling edge register
44        (0x20 => fall: ReadWrite<u32, FALL::Register>),
45        /// Pin interrupt status register
46        (0x24 => ist: ReadWrite<u32, IST::Register>),
47        (0x28 => @END),
48    }
49}
50register_bitfields![u32,
51ISEL [
52    /// Selects the interrupt mode for each pin interrupt. Bit n configures the pin inte
53    PMODE OFFSET(0) NUMBITS(8) []
54],
55IENR [
56    /// Enables the rising edge or level interrupt for each pin interrupt. Bit n configu
57    ENRL OFFSET(0) NUMBITS(8) []
58],
59SIENR [
60    /// Ones written to this address set bits in the IENR, thus enabling interrupts. Bit
61    SETENRL OFFSET(0) NUMBITS(8) []
62],
63CIENR [
64    /// Ones written to this address clear bits in the IENR, thus disabling the interrup
65    CENRL OFFSET(0) NUMBITS(8) []
66],
67IENF [
68    /// Enables the falling edge or configures the active level interrupt for each pin i
69    ENAF OFFSET(0) NUMBITS(8) []
70],
71SIENF [
72    /// Ones written to this address set bits in the IENF, thus enabling interrupts. Bit
73    SETENAF OFFSET(0) NUMBITS(8) []
74],
75CIENF [
76    /// Ones written to this address clears bits in the IENF, thus disabling interrupts.
77    CENAF OFFSET(0) NUMBITS(8) []
78],
79RISE [
80    /// Rising edge detect. Bit n detects the rising edge of the pin selected in PINTSEL
81    RDET OFFSET(0) NUMBITS(8) []
82],
83FALL [
84    /// Falling edge detect. Bit n detects the falling edge of the pin selected in PINTS
85    FDET OFFSET(0) NUMBITS(8) []
86],
87IST [
88    /// Pin interrupt status. Bit n returns the status, clears the edge interrupt, or in
89    PSTAT OFFSET(0) NUMBITS(8) []
90],
91PMCTRL [
92    /// Specifies whether the 8 pin interrupts are controlled by the pin interrupt funct
93    SEL_PMATCH OFFSET(0) NUMBITS(1) [
94        /// Pin interrupt. Interrupts are driven in response to the standard pin interrupt f
95        PinInterruptInterruptsAreDrivenInResponseToTheStandardPinInterruptFunction = 0,
96        /// Pattern match. Interrupts are driven in response to pattern matches.
97        PatternMatchInterruptsAreDrivenInResponseToPatternMatches = 1
98    ],
99    /// Enables the RXEV output to the CPU and/or to a GPIO output when the specified bo
100    ENA_RXEV OFFSET(1) NUMBITS(1) [
101        /// Disabled. RXEV output to the CPU is disabled.
102        DisabledRXEVOutputToTheCPUIsDisabled = 0,
103        /// Enabled. RXEV output to the CPU is enabled.
104        EnabledRXEVOutputToTheCPUIsEnabled = 1
105    ],
106    /// This field displays the current state of pattern matches. A 1 in any bit of this
107    PMAT OFFSET(24) NUMBITS(8) []
108],
109PMSRC [
110    /// Selects the input source for bit slice 0
111    SRC0 OFFSET(8) NUMBITS(3) [
112        /// Input 0. Selects the pin selected in the PINTSEL0 register as the source to bit
113        Input0SelectsThePinSelectedInThePINTSEL0RegisterAsTheSourceToBitSlice0 = 0,
114        /// Input 1. Selects the pin selected in the PINTSEL1 register as the source to bit
115        Input1SelectsThePinSelectedInThePINTSEL1RegisterAsTheSourceToBitSlice0 = 1,
116        /// Input 2. Selects the pin selected in the PINTSEL2 register as the source to bit
117        Input2SelectsThePinSelectedInThePINTSEL2RegisterAsTheSourceToBitSlice0 = 2,
118        /// Input 3. Selects the pin selected in the PINTSEL3 register as the source to bit
119        Input3SelectsThePinSelectedInThePINTSEL3RegisterAsTheSourceToBitSlice0 = 3,
120        /// Input 4. Selects the pin selected in the PINTSEL4 register as the source to bit
121        Input4SelectsThePinSelectedInThePINTSEL4RegisterAsTheSourceToBitSlice0 = 4,
122        /// Input 5. Selects the pin selected in the PINTSEL5 register as the source to bit
123        Input5SelectsThePinSelectedInThePINTSEL5RegisterAsTheSourceToBitSlice0 = 5,
124        /// Input 6. Selects the pin selected in the PINTSEL6 register as the source to bit
125        Input6SelectsThePinSelectedInThePINTSEL6RegisterAsTheSourceToBitSlice0 = 6,
126        /// Input 7. Selects the pin selected in the PINTSEL7 register as the source to bit
127        Input7SelectsThePinSelectedInThePINTSEL7RegisterAsTheSourceToBitSlice0 = 7
128    ],
129    /// Selects the input source for bit slice 1
130    SRC1 OFFSET(11) NUMBITS(3) [
131        /// Input 0. Selects the pin selected in the PINTSEL0 register as the source to bit
132        Input0SelectsThePinSelectedInThePINTSEL0RegisterAsTheSourceToBitSlice1 = 0,
133        /// Input 1. Selects the pin selected in the PINTSEL1 register as the source to bit
134        Input1SelectsThePinSelectedInThePINTSEL1RegisterAsTheSourceToBitSlice1 = 1,
135        /// Input 2. Selects the pin selected in the PINTSEL2 register as the source to bit
136        Input2SelectsThePinSelectedInThePINTSEL2RegisterAsTheSourceToBitSlice1 = 2,
137        /// Input 3. Selects the pin selected in the PINTSEL3 register as the source to bit
138        Input3SelectsThePinSelectedInThePINTSEL3RegisterAsTheSourceToBitSlice1 = 3,
139        /// Input 4. Selects the pin selected in the PINTSEL4 register as the source to bit
140        Input4SelectsThePinSelectedInThePINTSEL4RegisterAsTheSourceToBitSlice1 = 4,
141        /// Input 5. Selects the pin selected in the PINTSEL5 register as the source to bit
142        Input5SelectsThePinSelectedInThePINTSEL5RegisterAsTheSourceToBitSlice1 = 5,
143        /// Input 6. Selects the pin selected in the PINTSEL6 register as the source to bit
144        Input6SelectsThePinSelectedInThePINTSEL6RegisterAsTheSourceToBitSlice1 = 6,
145        /// Input 7. Selects the pin selected in the PINTSEL7 register as the source to bit
146        Input7SelectsThePinSelectedInThePINTSEL7RegisterAsTheSourceToBitSlice1 = 7
147    ],
148    /// Selects the input source for bit slice 2
149    SRC2 OFFSET(14) NUMBITS(3) [
150        /// Input 0. Selects the pin selected in the PINTSEL0 register as the source to bit
151        Input0SelectsThePinSelectedInThePINTSEL0RegisterAsTheSourceToBitSlice2 = 0,
152        /// Input 1. Selects the pin selected in the PINTSEL1 register as the source to bit
153        Input1SelectsThePinSelectedInThePINTSEL1RegisterAsTheSourceToBitSlice2 = 1,
154        /// Input 2. Selects the pin selected in the PINTSEL2 register as the source to bit
155        Input2SelectsThePinSelectedInThePINTSEL2RegisterAsTheSourceToBitSlice2 = 2,
156        /// Input 3. Selects the pin selected in the PINTSEL3 register as the source to bit
157        Input3SelectsThePinSelectedInThePINTSEL3RegisterAsTheSourceToBitSlice2 = 3,
158        /// Input 4. Selects the pin selected in the PINTSEL4 register as the source to bit
159        Input4SelectsThePinSelectedInThePINTSEL4RegisterAsTheSourceToBitSlice2 = 4,
160        /// Input 5. Selects the pin selected in the PINTSEL5 register as the source to bit
161        Input5SelectsThePinSelectedInThePINTSEL5RegisterAsTheSourceToBitSlice2 = 5,
162        /// Input 6. Selects the pin selected in the PINTSEL6 register as the source to bit
163        Input6SelectsThePinSelectedInThePINTSEL6RegisterAsTheSourceToBitSlice2 = 6,
164        /// Input 7. Selects the pin selected in the PINTSEL7 register as the source to bit
165        Input7SelectsThePinSelectedInThePINTSEL7RegisterAsTheSourceToBitSlice2 = 7
166    ],
167    /// Selects the input source for bit slice 3
168    SRC3 OFFSET(17) NUMBITS(3) [
169        /// Input 0. Selects the pin selected in the PINTSEL0 register as the source to bit
170        Input0SelectsThePinSelectedInThePINTSEL0RegisterAsTheSourceToBitSlice3 = 0,
171        /// Input 1. Selects the pin selected in the PINTSEL1 register as the source to bit
172        Input1SelectsThePinSelectedInThePINTSEL1RegisterAsTheSourceToBitSlice3 = 1,
173        /// Input 2. Selects the pin selected in the PINTSEL2 register as the source to bit
174        Input2SelectsThePinSelectedInThePINTSEL2RegisterAsTheSourceToBitSlice3 = 2,
175        /// Input 3. Selects the pin selected in the PINTSEL3 register as the source to bit
176        Input3SelectsThePinSelectedInThePINTSEL3RegisterAsTheSourceToBitSlice3 = 3,
177        /// Input 4. Selects the pin selected in the PINTSEL4 register as the source to bit
178        Input4SelectsThePinSelectedInThePINTSEL4RegisterAsTheSourceToBitSlice3 = 4,
179        /// Input 5. Selects the pin selected in the PINTSEL5 register as the source to bit
180        Input5SelectsThePinSelectedInThePINTSEL5RegisterAsTheSourceToBitSlice3 = 5,
181        /// Input 6. Selects the pin selected in the PINTSEL6 register as the source to bit
182        Input6SelectsThePinSelectedInThePINTSEL6RegisterAsTheSourceToBitSlice3 = 6,
183        /// Input 7. Selects the pin selected in the PINTSEL7 register as the source to bit
184        Input7SelectsThePinSelectedInThePINTSEL7RegisterAsTheSourceToBitSlice3 = 7
185    ],
186    /// Selects the input source for bit slice 4
187    SRC4 OFFSET(20) NUMBITS(3) [
188        /// Input 0. Selects the pin selected in the PINTSEL0 register as the source to bit
189        Input0SelectsThePinSelectedInThePINTSEL0RegisterAsTheSourceToBitSlice4 = 0,
190        /// Input 1. Selects the pin selected in the PINTSEL1 register as the source to bit
191        Input1SelectsThePinSelectedInThePINTSEL1RegisterAsTheSourceToBitSlice4 = 1,
192        /// Input 2. Selects the pin selected in the PINTSEL2 register as the source to bit
193        Input2SelectsThePinSelectedInThePINTSEL2RegisterAsTheSourceToBitSlice4 = 2,
194        /// Input 3. Selects the pin selected in the PINTSEL3 register as the source to bit
195        Input3SelectsThePinSelectedInThePINTSEL3RegisterAsTheSourceToBitSlice4 = 3,
196        /// Input 4. Selects the pin selected in the PINTSEL4 register as the source to bit
197        Input4SelectsThePinSelectedInThePINTSEL4RegisterAsTheSourceToBitSlice4 = 4,
198        /// Input 5. Selects the pin selected in the PINTSEL5 register as the source to bit
199        Input5SelectsThePinSelectedInThePINTSEL5RegisterAsTheSourceToBitSlice4 = 5,
200        /// Input 6. Selects the pin selected in the PINTSEL6 register as the source to bit
201        Input6SelectsThePinSelectedInThePINTSEL6RegisterAsTheSourceToBitSlice4 = 6,
202        /// Input 7. Selects the pin selected in the PINTSEL7 register as the source to bit
203        Input7SelectsThePinSelectedInThePINTSEL7RegisterAsTheSourceToBitSlice4 = 7
204    ],
205    /// Selects the input source for bit slice 5
206    SRC5 OFFSET(23) NUMBITS(3) [
207        /// Input 0. Selects the pin selected in the PINTSEL0 register as the source to bit
208        Input0SelectsThePinSelectedInThePINTSEL0RegisterAsTheSourceToBitSlice5 = 0,
209        /// Input 1. Selects the pin selected in the PINTSEL1 register as the source to bit
210        Input1SelectsThePinSelectedInThePINTSEL1RegisterAsTheSourceToBitSlice5 = 1,
211        /// Input 2. Selects the pin selected in the PINTSEL2 register as the source to bit
212        Input2SelectsThePinSelectedInThePINTSEL2RegisterAsTheSourceToBitSlice5 = 2,
213        /// Input 3. Selects the pin selected in the PINTSEL3 register as the source to bit
214        Input3SelectsThePinSelectedInThePINTSEL3RegisterAsTheSourceToBitSlice5 = 3,
215        /// Input 4. Selects the pin selected in the PINTSEL4 register as the source to bit
216        Input4SelectsThePinSelectedInThePINTSEL4RegisterAsTheSourceToBitSlice5 = 4,
217        /// Input 5. Selects the pin selected in the PINTSEL5 register as the source to bit
218        Input5SelectsThePinSelectedInThePINTSEL5RegisterAsTheSourceToBitSlice5 = 5,
219        /// Input 6. Selects the pin selected in the PINTSEL6 register as the source to bit
220        Input6SelectsThePinSelectedInThePINTSEL6RegisterAsTheSourceToBitSlice5 = 6,
221        /// Input 7. Selects the pin selected in the PINTSEL7 register as the source to bit
222        Input7SelectsThePinSelectedInThePINTSEL7RegisterAsTheSourceToBitSlice5 = 7
223    ],
224    /// Selects the input source for bit slice 6
225    SRC6 OFFSET(26) NUMBITS(3) [
226        /// Input 0. Selects the pin selected in the PINTSEL0 register as the source to bit
227        Input0SelectsThePinSelectedInThePINTSEL0RegisterAsTheSourceToBitSlice6 = 0,
228        /// Input 1. Selects the pin selected in the PINTSEL1 register as the source to bit
229        Input1SelectsThePinSelectedInThePINTSEL1RegisterAsTheSourceToBitSlice6 = 1,
230        /// Input 2. Selects the pin selected in the PINTSEL2 register as the source to bit
231        Input2SelectsThePinSelectedInThePINTSEL2RegisterAsTheSourceToBitSlice6 = 2,
232        /// Input 3. Selects the pin selected in the PINTSEL3 register as the source to bit
233        Input3SelectsThePinSelectedInThePINTSEL3RegisterAsTheSourceToBitSlice6 = 3,
234        /// Input 4. Selects the pin selected in the PINTSEL4 register as the source to bit
235        Input4SelectsThePinSelectedInThePINTSEL4RegisterAsTheSourceToBitSlice6 = 4,
236        /// Input 5. Selects the pin selected in the PINTSEL5 register as the source to bit
237        Input5SelectsThePinSelectedInThePINTSEL5RegisterAsTheSourceToBitSlice6 = 5,
238        /// Input 6. Selects the pin selected in the PINTSEL6 register as the source to bit
239        Input6SelectsThePinSelectedInThePINTSEL6RegisterAsTheSourceToBitSlice6 = 6,
240        /// Input 7. Selects the pin selected in the PINTSEL7 register as the source to bit
241        Input7SelectsThePinSelectedInThePINTSEL7RegisterAsTheSourceToBitSlice6 = 7
242    ],
243    /// Selects the input source for bit slice 7
244    SRC7 OFFSET(29) NUMBITS(3) [
245        /// Input 0. Selects the pin selected in the PINTSEL0 register as the source to bit
246        Input0SelectsThePinSelectedInThePINTSEL0RegisterAsTheSourceToBitSlice7 = 0,
247        /// Input 1. Selects the pin selected in the PINTSEL1 register as the source to bit
248        Input1SelectsThePinSelectedInThePINTSEL1RegisterAsTheSourceToBitSlice7 = 1,
249        /// Input 2. Selects the pin selected in the PINTSEL2 register as the source to bit
250        Input2SelectsThePinSelectedInThePINTSEL2RegisterAsTheSourceToBitSlice7 = 2,
251        /// Input 3. Selects the pin selected in the PINTSEL3 register as the source to bit
252        Input3SelectsThePinSelectedInThePINTSEL3RegisterAsTheSourceToBitSlice7 = 3,
253        /// Input 4. Selects the pin selected in the PINTSEL4 register as the source to bit
254        Input4SelectsThePinSelectedInThePINTSEL4RegisterAsTheSourceToBitSlice7 = 4,
255        /// Input 5. Selects the pin selected in the PINTSEL5 register as the source to bit
256        Input5SelectsThePinSelectedInThePINTSEL5RegisterAsTheSourceToBitSlice7 = 5,
257        /// Input 6. Selects the pin selected in the PINTSEL6 register as the source to bit
258        Input6SelectsThePinSelectedInThePINTSEL6RegisterAsTheSourceToBitSlice7 = 6,
259        /// Input 7. Selects the pin selected in the PINTSEL7 register as the source to bit
260        Input7SelectsThePinSelectedInThePINTSEL7RegisterAsTheSourceToBitSlice7 = 7
261    ]
262],
263PMCFG [
264    /// Determines whether slice 0 is an endpoint.
265    PROD_ENDPTS0 OFFSET(0) NUMBITS(1) [
266        /// No effect. Slice 0 is not an endpoint.
267        NoEffectSlice0IsNotAnEndpoint = 0,
268        /// endpoint. Slice 0 is the endpoint of a product term (minterm). Pin interrupt 0 i
269        ENDPOINT = 1
270    ],
271    /// Determines whether slice 1 is an endpoint.
272    PROD_ENDPTS1 OFFSET(1) NUMBITS(1) [
273        /// No effect. Slice 1 is not an endpoint.
274        NoEffectSlice1IsNotAnEndpoint = 0,
275        /// endpoint. Slice 1 is the endpoint of a product term (minterm). Pin interrupt 1 i
276        ENDPOINT = 1
277    ],
278    /// Determines whether slice 2 is an endpoint.
279    PROD_ENDPTS2 OFFSET(2) NUMBITS(1) [
280        /// No effect. Slice 2 is not an endpoint.
281        NoEffectSlice2IsNotAnEndpoint = 0,
282        /// endpoint. Slice 2 is the endpoint of a product term (minterm). Pin interrupt 2 i
283        ENDPOINT = 1
284    ],
285    /// Determines whether slice 3 is an endpoint.
286    PROD_ENDPTS3 OFFSET(3) NUMBITS(1) [
287        /// No effect. Slice 3 is not an endpoint.
288        NoEffectSlice3IsNotAnEndpoint = 0,
289        /// endpoint. Slice 3 is the endpoint of a product term (minterm). Pin interrupt 3 i
290        ENDPOINT = 1
291    ],
292    /// Determines whether slice 4 is an endpoint.
293    PROD_ENDPTS4 OFFSET(4) NUMBITS(1) [
294        /// No effect. Slice 4 is not an endpoint.
295        NoEffectSlice4IsNotAnEndpoint = 0,
296        /// endpoint. Slice 4 is the endpoint of a product term (minterm). Pin interrupt 4 i
297        ENDPOINT = 1
298    ],
299    /// Determines whether slice 5 is an endpoint.
300    PROD_ENDPTS5 OFFSET(5) NUMBITS(1) [
301        /// No effect. Slice 5 is not an endpoint.
302        NoEffectSlice5IsNotAnEndpoint = 0,
303        /// endpoint. Slice 5 is the endpoint of a product term (minterm). Pin interrupt 5 i
304        ENDPOINT = 1
305    ],
306    /// Determines whether slice 6 is an endpoint.
307    PROD_ENDPTS6 OFFSET(6) NUMBITS(1) [
308        /// No effect. Slice 6 is not an endpoint.
309        NoEffectSlice6IsNotAnEndpoint = 0,
310        /// endpoint. Slice 6 is the endpoint of a product term (minterm). Pin interrupt 6 i
311        ENDPOINT = 1
312    ],
313    /// Specifies the match contribution condition for bit slice 0.
314    CFG0 OFFSET(8) NUMBITS(3) [
315        /// Constant HIGH. This bit slice always contributes to a product term match.
316        ConstantHIGHThisBitSliceAlwaysContributesToAProductTermMatch = 0,
317        /// Sticky rising edge. Match occurs if a rising edge on the specified input has occ
318        STICKY_RISING_EDGE = 1,
319        /// Sticky falling edge. Match occurs if a falling edge on the specified input has o
320        STICKY_FALLING_EDGE = 2,
321        /// Sticky rising or falling edge. Match occurs if either a rising or falling edge o
322        STICKY_RISING_FALLING_EDGE = 3,
323        /// High level. Match (for this bit slice) occurs when there is a high level on the
324        HIGH_LEVEL = 4,
325        /// Low level. Match occurs when there is a low level on the specified input.
326        LowLevelMatchOccursWhenThereIsALowLevelOnTheSpecifiedInput = 5,
327        /// Constant 0. This bit slice never contributes to a match (should be used to disab
328        CONSTANT_ZERO = 6,
329        /// Event. Non-sticky rising or falling edge. Match occurs on an event - i.e. when e
330        EVENT = 7
331    ],
332    /// Specifies the match contribution condition for bit slice 1.
333    CFG1 OFFSET(11) NUMBITS(3) [
334        /// Constant HIGH. This bit slice always contributes to a product term match.
335        ConstantHIGHThisBitSliceAlwaysContributesToAProductTermMatch = 0,
336        /// Sticky rising edge. Match occurs if a rising edge on the specified input has occ
337        STICKY_RISING_EDGE = 1,
338        /// Sticky falling edge. Match occurs if a falling edge on the specified input has o
339        STICKY_FALLING_EDGE = 2,
340        /// Sticky rising or falling edge. Match occurs if either a rising or falling edge o
341        STICKY_RISING_FALLING_EDGE = 3,
342        /// High level. Match (for this bit slice) occurs when there is a high level on the
343        HIGH_LEVEL = 4,
344        /// Low level. Match occurs when there is a low level on the specified input.
345        LowLevelMatchOccursWhenThereIsALowLevelOnTheSpecifiedInput = 5,
346        /// Constant 0. This bit slice never contributes to a match (should be used to disab
347        CONSTANT_ZERO = 6,
348        /// Event. Non-sticky rising or falling edge. Match occurs on an event - i.e. when e
349        EVENT = 7
350    ],
351    /// Specifies the match contribution condition for bit slice 2.
352    CFG2 OFFSET(14) NUMBITS(3) [
353        /// Constant HIGH. This bit slice always contributes to a product term match.
354        ConstantHIGHThisBitSliceAlwaysContributesToAProductTermMatch = 0,
355        /// Sticky rising edge. Match occurs if a rising edge on the specified input has occ
356        STICKY_RISING_EDGE = 1,
357        /// Sticky falling edge. Match occurs if a falling edge on the specified input has o
358        STICKY_FALLING_EDGE = 2,
359        /// Sticky rising or falling edge. Match occurs if either a rising or falling edge o
360        STICKY_RISING_FALLING_EDGE = 3,
361        /// High level. Match (for this bit slice) occurs when there is a high level on the
362        HIGH_LEVEL = 4,
363        /// Low level. Match occurs when there is a low level on the specified input.
364        LowLevelMatchOccursWhenThereIsALowLevelOnTheSpecifiedInput = 5,
365        /// Constant 0. This bit slice never contributes to a match (should be used to disab
366        CONSTANT_ZERO = 6,
367        /// Event. Non-sticky rising or falling edge. Match occurs on an event - i.e. when e
368        EVENT = 7
369    ],
370    /// Specifies the match contribution condition for bit slice 3.
371    CFG3 OFFSET(17) NUMBITS(3) [
372        /// Constant HIGH. This bit slice always contributes to a product term match.
373        ConstantHIGHThisBitSliceAlwaysContributesToAProductTermMatch = 0,
374        /// Sticky rising edge. Match occurs if a rising edge on the specified input has occ
375        STICKY_RISING_EDGE = 1,
376        /// Sticky falling edge. Match occurs if a falling edge on the specified input has o
377        STICKY_FALLING_EDGE = 2,
378        /// Sticky rising or falling edge. Match occurs if either a rising or falling edge o
379        STICKY_RISING_FALLING_EDGE = 3,
380        /// High level. Match (for this bit slice) occurs when there is a high level on the
381        HIGH_LEVEL = 4,
382        /// Low level. Match occurs when there is a low level on the specified input.
383        LowLevelMatchOccursWhenThereIsALowLevelOnTheSpecifiedInput = 5,
384        /// Constant 0. This bit slice never contributes to a match (should be used to disab
385        CONSTANT_ZERO = 6,
386        /// Event. Non-sticky rising or falling edge. Match occurs on an event - i.e. when e
387        EVENT = 7
388    ],
389    /// Specifies the match contribution condition for bit slice 4.
390    CFG4 OFFSET(20) NUMBITS(3) [
391        /// Constant HIGH. This bit slice always contributes to a product term match.
392        ConstantHIGHThisBitSliceAlwaysContributesToAProductTermMatch = 0,
393        /// Sticky rising edge. Match occurs if a rising edge on the specified input has occ
394        STICKY_RISING_EDGE = 1,
395        /// Sticky falling edge. Match occurs if a falling edge on the specified input has o
396        STICKY_FALLING_EDGE = 2,
397        /// Sticky rising or falling edge. Match occurs if either a rising or falling edge o
398        STICKY_RISING_FALLING_EDGE = 3,
399        /// High level. Match (for this bit slice) occurs when there is a high level on the
400        HIGH_LEVEL = 4,
401        /// Low level. Match occurs when there is a low level on the specified input.
402        LowLevelMatchOccursWhenThereIsALowLevelOnTheSpecifiedInput = 5,
403        /// Constant 0. This bit slice never contributes to a match (should be used to disab
404        CONSTANT_ZERO = 6,
405        /// Event. Non-sticky rising or falling edge. Match occurs on an event - i.e. when e
406        EVENT = 7
407    ],
408    /// Specifies the match contribution condition for bit slice 5.
409    CFG5 OFFSET(23) NUMBITS(3) [
410        /// Constant HIGH. This bit slice always contributes to a product term match.
411        ConstantHIGHThisBitSliceAlwaysContributesToAProductTermMatch = 0,
412        /// Sticky rising edge. Match occurs if a rising edge on the specified input has occ
413        STICKY_RISING_EDGE = 1,
414        /// Sticky falling edge. Match occurs if a falling edge on the specified input has o
415        STICKY_FALLING_EDGE = 2,
416        /// Sticky rising or falling edge. Match occurs if either a rising or falling edge o
417        STICKY_RISING_FALLING_EDGE = 3,
418        /// High level. Match (for this bit slice) occurs when there is a high level on the
419        HIGH_LEVEL = 4,
420        /// Low level. Match occurs when there is a low level on the specified input.
421        LowLevelMatchOccursWhenThereIsALowLevelOnTheSpecifiedInput = 5,
422        /// Constant 0. This bit slice never contributes to a match (should be used to disab
423        CONSTANT_ZERO = 6,
424        /// Event. Non-sticky rising or falling edge. Match occurs on an event - i.e. when e
425        EVENT = 7
426    ],
427    /// Specifies the match contribution condition for bit slice 6.
428    CFG6 OFFSET(26) NUMBITS(3) [
429        /// Constant HIGH. This bit slice always contributes to a product term match.
430        ConstantHIGHThisBitSliceAlwaysContributesToAProductTermMatch = 0,
431        /// Sticky rising edge. Match occurs if a rising edge on the specified input has occ
432        STICKY_RISING_EDGE = 1,
433        /// Sticky falling edge. Match occurs if a falling edge on the specified input has o
434        STICKY_FALLING_EDGE = 2,
435        /// Sticky rising or falling edge. Match occurs if either a rising or falling edge o
436        STICKY_RISING_FALLING_EDGE = 3,
437        /// High level. Match (for this bit slice) occurs when there is a high level on the
438        HIGH_LEVEL = 4,
439        /// Low level. Match occurs when there is a low level on the specified input.
440        LowLevelMatchOccursWhenThereIsALowLevelOnTheSpecifiedInput = 5,
441        /// Constant 0. This bit slice never contributes to a match (should be used to disab
442        CONSTANT_ZERO = 6,
443        /// Event. Non-sticky rising or falling edge. Match occurs on an event - i.e. when e
444        EVENT = 7
445    ],
446    /// Specifies the match contribution condition for bit slice 7.
447    CFG7 OFFSET(29) NUMBITS(3) [
448        /// Constant HIGH. This bit slice always contributes to a product term match.
449        ConstantHIGHThisBitSliceAlwaysContributesToAProductTermMatch = 0,
450        /// Sticky rising edge. Match occurs if a rising edge on the specified input has occ
451        STICKY_RISING_EDGE = 1,
452        /// Sticky falling edge. Match occurs if a falling edge on the specified input has o
453        STICKY_FALLING_EDGE = 2,
454        /// Sticky rising or falling edge. Match occurs if either a rising or falling edge o
455        STICKY_RISING_FALLING_EDGE = 3,
456        /// High level. Match (for this bit slice) occurs when there is a high level on the
457        HIGH_LEVEL = 4,
458        /// Low level. Match occurs when there is a low level on the specified input.
459        LowLevelMatchOccursWhenThereIsALowLevelOnTheSpecifiedInput = 5,
460        /// Constant 0. This bit slice never contributes to a match (should be used to disab
461        CONSTANT_ZERO = 6,
462        /// Event. Non-sticky rising or falling edge. Match occurs on an event - i.e. when e
463        EVENT = 7
464    ]
465]
466];
467pub(crate) const PINT_BASE: StaticRef<PintRegisters> =
468    unsafe { StaticRef::new(0x50004000 as *const PintRegisters) };
469
470#[derive(Clone, Copy)]
471pub enum Edge {
472    Rising,
473    Falling,
474    Both,
475}
476
477pub struct Pint<'a> {
478    registers: StaticRef<PintRegisters>,
479    clients: [OptionalCell<&'a dyn kernel::hil::gpio::Client>; 8],
480}
481
482impl<'a> Pint<'a> {
483    pub const fn new() -> Self {
484        Self {
485            registers: PINT_BASE,
486            clients: [
487                OptionalCell::empty(),
488                OptionalCell::empty(),
489                OptionalCell::empty(),
490                OptionalCell::empty(),
491                OptionalCell::empty(),
492                OptionalCell::empty(),
493                OptionalCell::empty(),
494                OptionalCell::empty(),
495            ],
496        }
497    }
498
499    pub fn set_client(&self, channel: u8, client: &'a dyn kernel::hil::gpio::Client) {
500        if channel < 8 {
501            self.clients[channel as usize].replace(client);
502        }
503    }
504
505    pub fn configure_interrupt(&self, channel: usize, edge: Edge) {
506        if channel < 8 {
507            let mask = 1 << channel;
508
509            self.registers.isel.modify(ISEL::PMODE.val(!mask));
510
511            match edge {
512                Edge::Rising => {
513                    self.registers.sienr.write(SIENR::SETENRL.val(mask));
514                    self.registers.cienf.write(CIENF::CENAF.val(mask));
515                }
516                Edge::Falling => {
517                    self.registers.sienf.write(SIENF::SETENAF.val(mask));
518                    self.registers.cienr.write(CIENR::CENRL.val(mask));
519                }
520                Edge::Both => {
521                    self.registers.sienr.write(SIENR::SETENRL.val(mask));
522                    self.registers.sienf.write(SIENF::SETENAF.val(mask));
523                }
524            }
525        }
526    }
527
528    pub fn handle_interrupt(&self) {
529        let status = self.registers.ist.get();
530
531        self.registers.rise.write(RISE::RDET.val(status));
532        self.registers.fall.write(FALL::FDET.val(status));
533
534        for i in 0..8 {
535            if (status & (1 << i)) != 0 {
536                self.registers.ist.write(IST::PSTAT.val(1 << i));
537                self.clients[i].map(|client| client.fired());
538            }
539        }
540    }
541
542    pub fn disable_interrupt(&self, channel: usize) {
543        if channel < 8 {
544            let mask = 1 << channel;
545
546            self.registers.cienr.write(CIENR::CENRL.val(mask));
547            self.registers.cienf.write(CIENF::CENAF.val(mask));
548        }
549    }
550
551    pub fn read_interrupt(&self) -> u32 {
552        self.registers.rise.get()
553    }
554
555    /// Returns true if the given channel has a pending interrupt.
556    pub fn is_pending(&self, channel: usize) -> bool {
557        let status = self.registers.ist.get();
558        (status & (1 << channel)) != 0
559    }
560
561    /// Clears the pending interrupt for the given channel.
562    pub fn clear_pending(&self, channel: usize) {
563        // Writing a 1 clears the bit
564        self.registers.ist.set(1 << channel);
565    }
566}