@@ -11,6 +11,9 @@ use core::{
11
11
pin:: Pin ,
12
12
} ;
13
13
14
+ #[ cfg( CONFIG_GPIOLIB_IRQCHIP ) ]
15
+ pub use irqchip:: { ChipWithIrqChip , RegistrationWithIrqChip } ;
16
+
14
17
/// The direction of a gpio line.
15
18
pub enum LineDirection {
16
19
/// Direction is input.
@@ -141,14 +144,13 @@ impl<T: Chip> Registration<T> {
141
144
parent : & dyn device:: RawDevice ,
142
145
data : T :: Data ,
143
146
) -> 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 ( ) {
148
148
// Already registered.
149
149
return Err ( Error :: EINVAL ) ;
150
150
}
151
151
152
+ // SAFETY: We never move out of `this`.
153
+ let this = unsafe { self . get_unchecked_mut ( ) } ;
152
154
{
153
155
let gc = this. gc . get_mut ( ) ;
154
156
@@ -297,3 +299,174 @@ unsafe extern "C" fn set_callback<T: Chip>(
297
299
let data = unsafe { T :: Data :: borrow ( bindings:: gpiochip_get_data ( gc) ) } ;
298
300
T :: set ( data, offset, value != 0 ) ;
299
301
}
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