@@ -53,6 +53,7 @@ struct thunderx_line {
53
53
struct thunderx_gpio {
54
54
struct gpio_chip chip ;
55
55
u8 __iomem * register_base ;
56
+ struct irq_domain * irqd ;
56
57
struct msix_entry * msix_entries ; /* per line MSI-X */
57
58
struct thunderx_line * line_entries ; /* per line irq info */
58
59
raw_spinlock_t lock ;
@@ -285,60 +286,54 @@ static void thunderx_gpio_set_multiple(struct gpio_chip *chip,
285
286
}
286
287
}
287
288
288
- static void thunderx_gpio_irq_ack (struct irq_data * d )
289
+ static void thunderx_gpio_irq_ack (struct irq_data * data )
289
290
{
290
- struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
291
- struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
291
+ struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
292
292
293
293
writeq (GPIO_INTR_INTR ,
294
- txgpio -> register_base + intr_reg (irqd_to_hwirq ( d ) ));
294
+ txline -> txgpio -> register_base + intr_reg (txline -> line ));
295
295
}
296
296
297
- static void thunderx_gpio_irq_mask (struct irq_data * d )
297
+ static void thunderx_gpio_irq_mask (struct irq_data * data )
298
298
{
299
- struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
300
- struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
299
+ struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
301
300
302
301
writeq (GPIO_INTR_ENA_W1C ,
303
- txgpio -> register_base + intr_reg (irqd_to_hwirq ( d ) ));
302
+ txline -> txgpio -> register_base + intr_reg (txline -> line ));
304
303
}
305
304
306
- static void thunderx_gpio_irq_mask_ack (struct irq_data * d )
305
+ static void thunderx_gpio_irq_mask_ack (struct irq_data * data )
307
306
{
308
- struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
309
- struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
307
+ struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
310
308
311
309
writeq (GPIO_INTR_ENA_W1C | GPIO_INTR_INTR ,
312
- txgpio -> register_base + intr_reg (irqd_to_hwirq ( d ) ));
310
+ txline -> txgpio -> register_base + intr_reg (txline -> line ));
313
311
}
314
312
315
- static void thunderx_gpio_irq_unmask (struct irq_data * d )
313
+ static void thunderx_gpio_irq_unmask (struct irq_data * data )
316
314
{
317
- struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
318
- struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
315
+ struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
319
316
320
317
writeq (GPIO_INTR_ENA_W1S ,
321
- txgpio -> register_base + intr_reg (irqd_to_hwirq ( d ) ));
318
+ txline -> txgpio -> register_base + intr_reg (txline -> line ));
322
319
}
323
320
324
- static int thunderx_gpio_irq_set_type (struct irq_data * d ,
321
+ static int thunderx_gpio_irq_set_type (struct irq_data * data ,
325
322
unsigned int flow_type )
326
323
{
327
- struct gpio_chip * gc = irq_data_get_irq_chip_data (d );
328
- struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
329
- struct thunderx_line * txline =
330
- & txgpio -> line_entries [irqd_to_hwirq (d )];
324
+ struct thunderx_line * txline = irq_data_get_irq_chip_data (data );
325
+ struct thunderx_gpio * txgpio = txline -> txgpio ;
331
326
u64 bit_cfg ;
332
327
333
- irqd_set_trigger_type (d , flow_type );
328
+ irqd_set_trigger_type (data , flow_type );
334
329
335
330
bit_cfg = txline -> fil_bits | GPIO_BIT_CFG_INT_EN ;
336
331
337
332
if (flow_type & IRQ_TYPE_EDGE_BOTH ) {
338
- irq_set_handler_locked (d , handle_fasteoi_ack_irq );
333
+ irq_set_handler_locked (data , handle_fasteoi_ack_irq );
339
334
bit_cfg |= GPIO_BIT_CFG_INT_TYPE ;
340
335
} else {
341
- irq_set_handler_locked (d , handle_fasteoi_mask_irq );
336
+ irq_set_handler_locked (data , handle_fasteoi_mask_irq );
342
337
}
343
338
344
339
raw_spin_lock (& txgpio -> lock );
@@ -367,6 +362,33 @@ static void thunderx_gpio_irq_disable(struct irq_data *data)
367
362
irq_chip_disable_parent (data );
368
363
}
369
364
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
+
370
392
/*
371
393
* Interrupts are chained from underlying MSI-X vectors. We have
372
394
* these irq_chip functions to be able to handle level triggering
@@ -383,32 +405,57 @@ static struct irq_chip thunderx_gpio_irq_chip = {
383
405
.irq_unmask = thunderx_gpio_irq_unmask ,
384
406
.irq_eoi = irq_chip_eoi_parent ,
385
407
.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 ,
386
410
.irq_set_type = thunderx_gpio_irq_set_type ,
387
411
388
412
.flags = IRQCHIP_SET_TYPE_MASKED
389
413
};
390
414
391
- static int thunderx_gpio_child_to_parent_hwirq (struct gpio_chip * gc ,
392
- unsigned int child ,
393
- unsigned int child_type ,
394
- unsigned int * parent ,
395
- unsigned int * parent_type )
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 )
396
419
{
397
- struct thunderx_gpio * txgpio = gpiochip_get_data (gc );
398
-
399
- * parent = txgpio -> base_msi + (2 * child );
400
- * parent_type = IRQ_TYPE_LEVEL_HIGH ;
420
+ struct thunderx_gpio * txgpio = d -> host_data ;
421
+
422
+ if (WARN_ON (fwspec -> param_count < 2 ))
423
+ 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 ;
401
428
return 0 ;
402
429
}
403
430
431
+ static int thunderx_gpio_irq_alloc (struct irq_domain * d , unsigned int virq ,
432
+ unsigned int nr_irqs , void * arg )
433
+ {
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
+ };
444
+
445
+ static int thunderx_gpio_to_irq (struct gpio_chip * chip , unsigned int offset )
446
+ {
447
+ struct thunderx_gpio * txgpio = gpiochip_get_data (chip );
448
+
449
+ return irq_find_mapping (txgpio -> irqd , offset );
450
+ }
451
+
404
452
static int thunderx_gpio_probe (struct pci_dev * pdev ,
405
453
const struct pci_device_id * id )
406
454
{
407
455
void __iomem * const * tbl ;
408
456
struct device * dev = & pdev -> dev ;
409
457
struct thunderx_gpio * txgpio ;
410
458
struct gpio_chip * chip ;
411
- struct gpio_irq_chip * girq ;
412
459
int ngpio , i ;
413
460
int err = 0 ;
414
461
@@ -453,8 +500,8 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
453
500
}
454
501
455
502
txgpio -> msix_entries = devm_kcalloc (dev ,
456
- ngpio , sizeof (struct msix_entry ),
457
- GFP_KERNEL );
503
+ ngpio , sizeof (struct msix_entry ),
504
+ GFP_KERNEL );
458
505
if (!txgpio -> msix_entries ) {
459
506
err = - ENOMEM ;
460
507
goto out ;
@@ -495,6 +542,27 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
495
542
if (err < 0 )
496
543
goto out ;
497
544
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
+
498
566
chip -> label = KBUILD_MODNAME ;
499
567
chip -> parent = dev ;
500
568
chip -> owner = THIS_MODULE ;
@@ -509,28 +577,11 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
509
577
chip -> set = thunderx_gpio_set ;
510
578
chip -> set_multiple = thunderx_gpio_set_multiple ;
511
579
chip -> set_config = thunderx_gpio_set_config ;
512
- girq = & chip -> irq ;
513
- girq -> chip = & thunderx_gpio_irq_chip ;
514
- girq -> fwnode = of_node_to_fwnode (dev -> of_node );
515
- girq -> parent_domain =
516
- irq_get_irq_data (txgpio -> msix_entries [0 ].vector )-> domain ;
517
- girq -> child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq ;
518
- girq -> handler = handle_bad_irq ;
519
- girq -> default_type = IRQ_TYPE_NONE ;
520
-
580
+ chip -> to_irq = thunderx_gpio_to_irq ;
521
581
err = devm_gpiochip_add_data (dev , chip , txgpio );
522
582
if (err )
523
583
goto out ;
524
584
525
- /* Push on irq_data and the domain for each line. */
526
- for (i = 0 ; i < ngpio ; i ++ ) {
527
- err = irq_domain_push_irq (chip -> irq .domain ,
528
- txgpio -> msix_entries [i ].vector ,
529
- chip );
530
- if (err < 0 )
531
- dev_err (dev , "irq_domain_push_irq: %d\n" , err );
532
- }
533
-
534
585
dev_info (dev , "ThunderX GPIO: %d lines with base %d.\n" ,
535
586
ngpio , chip -> base );
536
587
return 0 ;
@@ -545,10 +596,10 @@ static void thunderx_gpio_remove(struct pci_dev *pdev)
545
596
struct thunderx_gpio * txgpio = pci_get_drvdata (pdev );
546
597
547
598
for (i = 0 ; i < txgpio -> chip .ngpio ; i ++ )
548
- irq_domain_pop_irq (txgpio -> chip . irq . domain ,
599
+ irq_domain_pop_irq (txgpio -> irqd ,
549
600
txgpio -> msix_entries [i ].vector );
550
601
551
- irq_domain_remove (txgpio -> chip . irq . domain );
602
+ irq_domain_remove (txgpio -> irqd );
552
603
553
604
pci_set_drvdata (pdev , NULL );
554
605
}
0 commit comments