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