@@ -11,6 +11,9 @@ use core::{
1111 pin:: Pin ,
1212} ;
1313
14+ #[ cfg( CONFIG_GPIOLIB_IRQCHIP ) ]
15+ pub use irqchip:: { ChipWithIrqChip , RegistrationWithIrqChip } ;
16+
1417/// The direction of a gpio line.
1518pub enum LineDirection {
1619 /// Direction is input.
@@ -141,14 +144,13 @@ impl<T: Chip> Registration<T> {
141144 parent : & dyn device:: RawDevice ,
142145 data : T :: Data ,
143146 ) -> Result {
144- // SAFETY: We never move out of `this`.
145- let this = unsafe { self . get_unchecked_mut ( ) } ;
146-
147- if this. parent . is_some ( ) {
147+ if self . parent . is_some ( ) {
148148 // Already registered.
149149 return Err ( Error :: EINVAL ) ;
150150 }
151151
152+ // SAFETY: We never move out of `this`.
153+ let this = unsafe { self . get_unchecked_mut ( ) } ;
152154 {
153155 let gc = this. gc . get_mut ( ) ;
154156
@@ -297,3 +299,174 @@ unsafe extern "C" fn set_callback<T: Chip>(
297299 let data = unsafe { T :: Data :: borrow ( bindings:: gpiochip_get_data ( gc) ) } ;
298300 T :: set ( data, offset, value != 0 ) ;
299301}
302+
303+ #[ cfg( CONFIG_GPIOLIB_IRQCHIP ) ]
304+ mod irqchip {
305+ use super :: * ;
306+ use crate :: irq;
307+
308+ /// A gpio chip that includes an irq chip.
309+ pub trait ChipWithIrqChip : Chip {
310+ /// Implements the irq flow for the gpio chip.
311+ fn handle_irq_flow (
312+ _data : <Self :: Data as PointerWrapper >:: Borrowed < ' _ > ,
313+ _desc : & irq:: Descriptor ,
314+ _domain : & irq:: Domain ,
315+ ) ;
316+ }
317+
318+ /// A registration of a gpio chip that includes an irq chip.
319+ pub struct RegistrationWithIrqChip < T : ChipWithIrqChip > {
320+ reg : Registration < T > ,
321+ irq_chip : UnsafeCell < bindings:: irq_chip > ,
322+ parent_irq : u32 ,
323+ }
324+
325+ impl < T : ChipWithIrqChip > RegistrationWithIrqChip < T > {
326+ /// Creates a new [`RegistrationWithIrqChip`] but does not register it yet.
327+ ///
328+ /// It is allowed to move.
329+ pub fn new ( ) -> Self {
330+ Self {
331+ reg : Registration :: new ( ) ,
332+ irq_chip : UnsafeCell :: new ( bindings:: irq_chip:: default ( ) ) ,
333+ parent_irq : 0 ,
334+ }
335+ }
336+
337+ /// Registers a gpio chip and its irq chip with the rest of the kernel.
338+ pub fn register < U : irq:: Chip < Data = T :: Data > > (
339+ mut self : Pin < & mut Self > ,
340+ gpio_count : u16 ,
341+ base : Option < i32 > ,
342+ parent : & dyn device:: RawDevice ,
343+ data : T :: Data ,
344+ parent_irq : u32 ,
345+ ) -> Result {
346+ if self . reg . parent . is_some ( ) {
347+ // Already registered.
348+ return Err ( Error :: EINVAL ) ;
349+ }
350+
351+ // SAFETY: We never move out of `this`.
352+ let this = unsafe { self . as_mut ( ) . get_unchecked_mut ( ) } ;
353+
354+ // Initialise the irq_chip.
355+ {
356+ let irq_chip = this. irq_chip . get_mut ( ) ;
357+ irq_chip. name = parent. name ( ) . as_char_ptr ( ) ;
358+
359+ // SAFETY: The gpio subsystem configures a pointer to `gpio_chip` as the irq chip
360+ // data, so we use `IrqChipAdapter` to convert to the `T::Data`, which is the same
361+ // as `irq::Chip::Data` per the bound above.
362+ unsafe { irq:: init_chip :: < IrqChipAdapter < U > > ( irq_chip) } ;
363+ }
364+
365+ // Initialise gc irq state.
366+ {
367+ let girq = & mut this. reg . gc . get_mut ( ) . irq ;
368+ girq. chip = this. irq_chip . get ( ) ;
369+ // SAFETY: By leaving `parent_handler_data` set to `null`, the gpio subsystem
370+ // initialises it to a pointer to the gpio chip, which is what `FlowHandler<T>`
371+ // expects.
372+ girq. parent_handler = unsafe { irq:: new_flow_handler :: < FlowHandler < T > > ( ) } ;
373+ girq. num_parents = 1 ;
374+ girq. parents = & mut this. parent_irq ;
375+ this. parent_irq = parent_irq;
376+ girq. default_type = bindings:: IRQ_TYPE_NONE ;
377+ girq. handler = Some ( bindings:: handle_bad_irq) ;
378+ }
379+
380+ // SAFETY: `reg` is pinned when `self` is.
381+ let pinned = unsafe { self . map_unchecked_mut ( |r| & mut r. reg ) } ;
382+ pinned. register ( gpio_count, base, parent, data)
383+ }
384+ }
385+
386+ impl < T : ChipWithIrqChip > Default for RegistrationWithIrqChip < T > {
387+ fn default ( ) -> Self {
388+ Self :: new ( )
389+ }
390+ }
391+
392+ // SAFETY: `RegistrationWithIrqChip` doesn't offer any methods or access to fields when shared
393+ // between threads or CPUs, so it is safe to share it.
394+ unsafe impl < T : ChipWithIrqChip > Sync for RegistrationWithIrqChip < T > { }
395+
396+ // SAFETY: Registration with and unregistration from the gpio subsystem (including irq chips for
397+ // them) can happen from any thread. Additionally, `T::Data` (which is dropped during
398+ // unregistration) is `Send`, so it is ok to move `Registration` to different threads.
399+ unsafe impl < T : ChipWithIrqChip > Send for RegistrationWithIrqChip < T > where T :: Data : Send { }
400+
401+ struct FlowHandler < T : ChipWithIrqChip > ( PhantomData < T > ) ;
402+
403+ impl < T : ChipWithIrqChip > irq:: FlowHandler for FlowHandler < T > {
404+ type Data = * mut bindings:: gpio_chip ;
405+
406+ fn handle_irq_flow ( gc : * mut bindings:: gpio_chip , desc : & irq:: Descriptor ) {
407+ // SAFETY: `FlowHandler` is only used in gpio chips, and it is removed when the gpio is
408+ // unregistered, so we know that `gc` must still be valid. We also know that the value
409+ // stored as gpio data was returned by `T::Data::into_pointer` again because
410+ // `FlowHandler` is a private structure only used in this way.
411+ let data = unsafe { T :: Data :: borrow ( bindings:: gpiochip_get_data ( gc) ) } ;
412+
413+ // SAFETY: `gc` is valid (see comment above), so we can dereference it.
414+ let domain = unsafe { irq:: Domain :: from_ptr ( ( * gc) . irq . domain ) } ;
415+
416+ T :: handle_irq_flow ( data, desc, & domain) ;
417+ }
418+ }
419+
420+ /// Adapter from an irq chip with `gpio_chip` pointer as context to one where the gpio chip
421+ /// data is passed as context.
422+ struct IrqChipAdapter < T : irq:: Chip > ( PhantomData < T > ) ;
423+
424+ impl < T : irq:: Chip > irq:: Chip for IrqChipAdapter < T > {
425+ type Data = * mut bindings:: gpio_chip ;
426+ const TO_USE : irq:: ToUse = T :: TO_USE ;
427+
428+ fn ack ( gc : * mut bindings:: gpio_chip , irq_data : & irq:: IrqData ) {
429+ // SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
430+ // gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
431+ // registered, so `gc` is valid.
432+ let data = unsafe { T :: Data :: borrow ( bindings:: gpiochip_get_data ( gc as _ ) ) } ;
433+ T :: ack ( data, irq_data) ;
434+ }
435+
436+ fn mask ( gc : * mut bindings:: gpio_chip , irq_data : & irq:: IrqData ) {
437+ // SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
438+ // gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
439+ // registered, so `gc` is valid.
440+ let data = unsafe { T :: Data :: borrow ( bindings:: gpiochip_get_data ( gc as _ ) ) } ;
441+ T :: mask ( data, irq_data) ;
442+ }
443+
444+ fn unmask ( gc : * mut bindings:: gpio_chip , irq_data : & irq:: IrqData ) {
445+ // SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
446+ // gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
447+ // registered, so `gc` is valid.
448+ let data = unsafe { T :: Data :: borrow ( bindings:: gpiochip_get_data ( gc as _ ) ) } ;
449+ T :: unmask ( data, irq_data) ;
450+ }
451+
452+ fn set_type (
453+ gc : * mut bindings:: gpio_chip ,
454+ irq_data : & mut irq:: LockedIrqData ,
455+ flow_type : u32 ,
456+ ) -> Result < irq:: ExtraResult > {
457+ // SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
458+ // gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
459+ // registered, so `gc` is valid.
460+ let data = unsafe { T :: Data :: borrow ( bindings:: gpiochip_get_data ( gc as _ ) ) } ;
461+ T :: set_type ( data, irq_data, flow_type)
462+ }
463+
464+ fn set_wake ( gc : * mut bindings:: gpio_chip , irq_data : & irq:: IrqData , on : bool ) -> Result {
465+ // SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
466+ // gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
467+ // registered, so `gc` is valid.
468+ let data = unsafe { T :: Data :: borrow ( bindings:: gpiochip_get_data ( gc as _ ) ) } ;
469+ T :: set_wake ( data, irq_data, on)
470+ }
471+ }
472+ }
0 commit comments