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