15
15
#include <linux/module.h>
16
16
#include <linux/pci.h>
17
17
#include <linux/spinlock.h>
18
+ #include <asm-generic/msi.h>
18
19
19
20
20
21
#define GPIO_RX_DAT 0x0
@@ -53,7 +54,6 @@ struct thunderx_line {
53
54
struct thunderx_gpio {
54
55
struct gpio_chip chip ;
55
56
u8 __iomem * register_base ;
56
- struct irq_domain * irqd ;
57
57
struct msix_entry * msix_entries ; /* per line MSI-X */
58
58
struct thunderx_line * line_entries ; /* per line irq info */
59
59
raw_spinlock_t lock ;
@@ -286,54 +286,60 @@ static void thunderx_gpio_set_multiple(struct gpio_chip *chip,
286
286
}
287
287
}
288
288
289
- static void thunderx_gpio_irq_ack (struct irq_data * data )
289
+ static void thunderx_gpio_irq_ack (struct irq_data * d )
290
290
{
291
- struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
291
+ struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
292
+ struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
292
293
293
294
writeq (GPIO_INTR_INTR ,
294
- txline -> txgpio -> register_base + intr_reg (txline -> line ));
295
+ txgpio -> register_base + intr_reg (irqd_to_hwirq ( d ) ));
295
296
}
296
297
297
- static void thunderx_gpio_irq_mask (struct irq_data * data )
298
+ static void thunderx_gpio_irq_mask (struct irq_data * d )
298
299
{
299
- struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
300
+ struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
301
+ struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
300
302
301
303
writeq (GPIO_INTR_ENA_W1C ,
302
- txline -> txgpio -> register_base + intr_reg (txline -> line ));
304
+ txgpio -> register_base + intr_reg (irqd_to_hwirq ( d ) ));
303
305
}
304
306
305
- static void thunderx_gpio_irq_mask_ack (struct irq_data * data )
307
+ static void thunderx_gpio_irq_mask_ack (struct irq_data * d )
306
308
{
307
- struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
309
+ struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
310
+ struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
308
311
309
312
writeq (GPIO_INTR_ENA_W1C | GPIO_INTR_INTR ,
310
- txline -> txgpio -> register_base + intr_reg (txline -> line ));
313
+ txgpio -> register_base + intr_reg (irqd_to_hwirq ( d ) ));
311
314
}
312
315
313
- static void thunderx_gpio_irq_unmask (struct irq_data * data )
316
+ static void thunderx_gpio_irq_unmask (struct irq_data * d )
314
317
{
315
- struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
318
+ struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
319
+ struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
316
320
317
321
writeq (GPIO_INTR_ENA_W1S ,
318
- txline -> txgpio -> register_base + intr_reg (txline -> line ));
322
+ txgpio -> register_base + intr_reg (irqd_to_hwirq ( d ) ));
319
323
}
320
324
321
- static int thunderx_gpio_irq_set_type (struct irq_data * data ,
325
+ static int thunderx_gpio_irq_set_type (struct irq_data * d ,
322
326
unsigned int flow_type )
323
327
{
324
- struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
325
- struct thunderx_gpio * txgpio = txline -> txgpio ;
328
+ struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
329
+ struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
330
+ struct thunderx_line * txline =
331
+ & txgpio -> line_entries [irqd_to_hwirq (d )];
326
332
u64 bit_cfg ;
327
333
328
- irqd_set_trigger_type (data , flow_type );
334
+ irqd_set_trigger_type (d , flow_type );
329
335
330
336
bit_cfg = txline -> fil_bits | GPIO_BIT_CFG_INT_EN ;
331
337
332
338
if (flow_type & IRQ_TYPE_EDGE_BOTH ) {
333
- irq_set_handler_locked (data , handle_fasteoi_ack_irq );
339
+ irq_set_handler_locked (d , handle_fasteoi_ack_irq );
334
340
bit_cfg |= GPIO_BIT_CFG_INT_TYPE ;
335
341
} else {
336
- irq_set_handler_locked (data , handle_fasteoi_mask_irq );
342
+ irq_set_handler_locked (d , handle_fasteoi_mask_irq );
337
343
}
338
344
339
345
raw_spin_lock (& txgpio -> lock );
@@ -362,33 +368,6 @@ static void thunderx_gpio_irq_disable(struct irq_data *data)
362
368
irq_chip_disable_parent (data );
363
369
}
364
370
365
- static int thunderx_gpio_irq_request_resources (struct irq_data * data )
366
- {
367
- struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
368
- struct thunderx_gpio * txgpio = txline -> txgpio ;
369
- int r ;
370
-
371
- r = gpiochip_lock_as_irq (& txgpio -> chip , txline -> line );
372
- if (r )
373
- return r ;
374
-
375
- r = irq_chip_request_resources_parent (data );
376
- if (r )
377
- gpiochip_unlock_as_irq (& txgpio -> chip , txline -> line );
378
-
379
- return r ;
380
- }
381
-
382
- static void thunderx_gpio_irq_release_resources (struct irq_data * data )
383
- {
384
- struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
385
- struct thunderx_gpio * txgpio = txline -> txgpio ;
386
-
387
- irq_chip_release_resources_parent (data );
388
-
389
- gpiochip_unlock_as_irq (& txgpio -> chip , txline -> line );
390
- }
391
-
392
371
/*
393
372
* Interrupts are chained from underlying MSI-X vectors. We have
394
373
* these irq_chip functions to be able to handle level triggering
@@ -405,48 +384,42 @@ static struct irq_chip thunderx_gpio_irq_chip = {
405
384
.irq_unmask = thunderx_gpio_irq_unmask ,
406
385
.irq_eoi = irq_chip_eoi_parent ,
407
386
.irq_set_affinity = irq_chip_set_affinity_parent ,
408
- .irq_request_resources = thunderx_gpio_irq_request_resources ,
409
- .irq_release_resources = thunderx_gpio_irq_release_resources ,
410
387
.irq_set_type = thunderx_gpio_irq_set_type ,
411
388
412
389
.flags = IRQCHIP_SET_TYPE_MASKED
413
390
};
414
391
415
- static int thunderx_gpio_irq_translate (struct irq_domain * d ,
416
- struct irq_fwspec * fwspec ,
417
- irq_hw_number_t * hwirq ,
418
- unsigned int * type )
392
+ static int thunderx_gpio_child_to_parent_hwirq (struct gpio_chip * gc ,
393
+ unsigned int child ,
394
+ unsigned int child_type ,
395
+ unsigned int * parent ,
396
+ unsigned int * parent_type )
419
397
{
420
- struct thunderx_gpio * txgpio = d -> host_data ;
398
+ struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
399
+ struct irq_data * irqd ;
400
+ unsigned int irq ;
421
401
422
- if (WARN_ON (fwspec -> param_count < 2 ))
402
+ irq = txgpio -> msix_entries [child ].vector ;
403
+ irqd = irq_domain_get_irq_data (gc -> irq .parent_domain , irq );
404
+ if (!irqd )
423
405
return - EINVAL ;
424
- if (fwspec -> param [0 ] >= txgpio -> chip .ngpio )
425
- return - EINVAL ;
426
- * hwirq = fwspec -> param [0 ];
427
- * type = fwspec -> param [1 ] & IRQ_TYPE_SENSE_MASK ;
406
+ * parent = irqd_to_hwirq (irqd );
407
+ * parent_type = IRQ_TYPE_LEVEL_HIGH ;
428
408
return 0 ;
429
409
}
430
410
431
- static int thunderx_gpio_irq_alloc (struct irq_domain * d , unsigned int virq ,
432
- unsigned int nr_irqs , void * arg )
411
+ static void * thunderx_gpio_populate_parent_alloc_info (struct gpio_chip * chip ,
412
+ unsigned int parent_hwirq ,
413
+ unsigned int parent_type )
433
414
{
434
- struct thunderx_line * txline = arg ;
435
-
436
- return irq_domain_set_hwirq_and_chip (d , virq , txline -> line ,
437
- & thunderx_gpio_irq_chip , txline );
438
- }
439
-
440
- static const struct irq_domain_ops thunderx_gpio_irqd_ops = {
441
- .alloc = thunderx_gpio_irq_alloc ,
442
- .translate = thunderx_gpio_irq_translate
443
- };
415
+ msi_alloc_info_t * info ;
444
416
445
- static int thunderx_gpio_to_irq ( struct gpio_chip * chip , unsigned int offset )
446
- {
447
- struct thunderx_gpio * txgpio = gpiochip_get_data ( chip ) ;
417
+ info = kmalloc ( sizeof ( * info ), GFP_KERNEL );
418
+ if (! info )
419
+ return NULL ;
448
420
449
- return irq_find_mapping (txgpio -> irqd , offset );
421
+ info -> hwirq = parent_hwirq ;
422
+ return info ;
450
423
}
451
424
452
425
static int thunderx_gpio_probe (struct pci_dev * pdev ,
@@ -456,6 +429,7 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
456
429
struct device * dev = & pdev -> dev ;
457
430
struct thunderx_gpio * txgpio ;
458
431
struct gpio_chip * chip ;
432
+ struct gpio_irq_chip * girq ;
459
433
int ngpio , i ;
460
434
int err = 0 ;
461
435
@@ -500,8 +474,8 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
500
474
}
501
475
502
476
txgpio -> msix_entries = devm_kcalloc (dev ,
503
- ngpio , sizeof (struct msix_entry ),
504
- GFP_KERNEL );
477
+ ngpio , sizeof (struct msix_entry ),
478
+ GFP_KERNEL );
505
479
if (!txgpio -> msix_entries ) {
506
480
err = - ENOMEM ;
507
481
goto out ;
@@ -542,27 +516,6 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
542
516
if (err < 0 )
543
517
goto out ;
544
518
545
- /*
546
- * Push GPIO specific irqdomain on hierarchy created as a side
547
- * effect of the pci_enable_msix()
548
- */
549
- txgpio -> irqd = irq_domain_create_hierarchy (irq_get_irq_data (txgpio -> msix_entries [0 ].vector )-> domain ,
550
- 0 , 0 , of_node_to_fwnode (dev -> of_node ),
551
- & thunderx_gpio_irqd_ops , txgpio );
552
- if (!txgpio -> irqd ) {
553
- err = - ENOMEM ;
554
- goto out ;
555
- }
556
-
557
- /* Push on irq_data and the domain for each line. */
558
- for (i = 0 ; i < ngpio ; i ++ ) {
559
- err = irq_domain_push_irq (txgpio -> irqd ,
560
- txgpio -> msix_entries [i ].vector ,
561
- & txgpio -> line_entries [i ]);
562
- if (err < 0 )
563
- dev_err (dev , "irq_domain_push_irq: %d\n" , err );
564
- }
565
-
566
519
chip -> label = KBUILD_MODNAME ;
567
520
chip -> parent = dev ;
568
521
chip -> owner = THIS_MODULE ;
@@ -577,11 +530,35 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
577
530
chip -> set = thunderx_gpio_set ;
578
531
chip -> set_multiple = thunderx_gpio_set_multiple ;
579
532
chip -> set_config = thunderx_gpio_set_config ;
580
- chip -> to_irq = thunderx_gpio_to_irq ;
533
+ girq = & chip -> irq ;
534
+ girq -> chip = & thunderx_gpio_irq_chip ;
535
+ girq -> fwnode = of_node_to_fwnode (dev -> of_node );
536
+ girq -> parent_domain =
537
+ irq_get_irq_data (txgpio -> msix_entries [0 ].vector )-> domain ;
538
+ girq -> child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq ;
539
+ girq -> populate_parent_alloc_arg = thunderx_gpio_populate_parent_alloc_info ;
540
+ girq -> handler = handle_bad_irq ;
541
+ girq -> default_type = IRQ_TYPE_NONE ;
542
+
581
543
err = devm_gpiochip_add_data (dev , chip , txgpio );
582
544
if (err )
583
545
goto out ;
584
546
547
+ /* Push on irq_data and the domain for each line. */
548
+ for (i = 0 ; i < ngpio ; i ++ ) {
549
+ struct irq_fwspec fwspec ;
550
+
551
+ fwspec .fwnode = of_node_to_fwnode (dev -> of_node );
552
+ fwspec .param_count = 2 ;
553
+ fwspec .param [0 ] = i ;
554
+ fwspec .param [1 ] = IRQ_TYPE_NONE ;
555
+ err = irq_domain_push_irq (girq -> domain ,
556
+ txgpio -> msix_entries [i ].vector ,
557
+ & fwspec );
558
+ if (err < 0 )
559
+ dev_err (dev , "irq_domain_push_irq: %d\n" , err );
560
+ }
561
+
585
562
dev_info (dev , "ThunderX GPIO: %d lines with base %d.\n" ,
586
563
ngpio , chip -> base );
587
564
return 0 ;
@@ -596,10 +573,10 @@ static void thunderx_gpio_remove(struct pci_dev *pdev)
596
573
struct thunderx_gpio * txgpio = pci_get_drvdata (pdev );
597
574
598
575
for (i = 0 ; i < txgpio -> chip .ngpio ; i ++ )
599
- irq_domain_pop_irq (txgpio -> irqd ,
576
+ irq_domain_pop_irq (txgpio -> chip . irq . domain ,
600
577
txgpio -> msix_entries [i ].vector );
601
578
602
- irq_domain_remove (txgpio -> irqd );
579
+ irq_domain_remove (txgpio -> chip . irq . domain );
603
580
604
581
pci_set_drvdata (pdev , NULL );
605
582
}
0 commit comments