3
3
* Copyright (C) 2017 SiFive
4
4
* Copyright (C) 2018 Christoph Hellwig
5
5
*/
6
+ #define pr_fmt (fmt ) "riscv-plic: " fmt
6
7
#include <linux/cpu.h>
7
8
#include <linux/interrupt.h>
8
9
#include <linux/io.h>
63
64
#define PLIC_QUIRK_EDGE_INTERRUPT 0
64
65
65
66
struct plic_priv {
66
- struct device * dev ;
67
+ struct fwnode_handle * fwnode ;
67
68
struct cpumask lmask ;
68
69
struct irq_domain * irqdomain ;
69
70
void __iomem * regs ;
@@ -378,8 +379,8 @@ static void plic_handle_irq(struct irq_desc *desc)
378
379
int err = generic_handle_domain_irq (handler -> priv -> irqdomain ,
379
380
hwirq );
380
381
if (unlikely (err )) {
381
- dev_warn_ratelimited ( handler -> priv -> dev ,
382
- "can't find mapping for hwirq %lu\n" , hwirq );
382
+ pr_warn_ratelimited ( "%pfwP: can't find mapping for hwirq %lu\n" ,
383
+ handler -> priv -> fwnode , hwirq );
383
384
}
384
385
}
385
386
@@ -408,7 +409,8 @@ static int plic_starting_cpu(unsigned int cpu)
408
409
enable_percpu_irq (plic_parent_irq ,
409
410
irq_get_trigger_type (plic_parent_irq ));
410
411
else
411
- dev_warn (handler -> priv -> dev , "cpu%d: parent irq not available\n" , cpu );
412
+ pr_warn ("%pfwP: cpu%d: parent irq not available\n" ,
413
+ handler -> priv -> fwnode , cpu );
412
414
plic_set_threshold (handler , PLIC_ENABLE_THRESHOLD );
413
415
414
416
return 0 ;
@@ -424,38 +426,36 @@ static const struct of_device_id plic_match[] = {
424
426
{}
425
427
};
426
428
427
- static int plic_parse_nr_irqs_and_contexts (struct platform_device * pdev ,
429
+ static int plic_parse_nr_irqs_and_contexts (struct fwnode_handle * fwnode ,
428
430
u32 * nr_irqs , u32 * nr_contexts )
429
431
{
430
- struct device * dev = & pdev -> dev ;
431
432
int rc ;
432
433
433
434
/*
434
435
* Currently, only OF fwnode is supported so extend this
435
436
* function for ACPI support.
436
437
*/
437
- if (!is_of_node (dev -> fwnode ))
438
+ if (!is_of_node (fwnode ))
438
439
return - EINVAL ;
439
440
440
- rc = of_property_read_u32 (to_of_node (dev -> fwnode ), "riscv,ndev" , nr_irqs );
441
+ rc = of_property_read_u32 (to_of_node (fwnode ), "riscv,ndev" , nr_irqs );
441
442
if (rc ) {
442
- dev_err ( dev , " riscv,ndev property not available\n" );
443
+ pr_err ( "%pfwP: riscv,ndev property not available\n", fwnode );
443
444
return rc ;
444
445
}
445
446
446
- * nr_contexts = of_irq_count (to_of_node (dev -> fwnode ));
447
+ * nr_contexts = of_irq_count (to_of_node (fwnode ));
447
448
if (WARN_ON (!(* nr_contexts ))) {
448
- dev_err ( dev , " no PLIC context available\n" );
449
+ pr_err ( "%pfwP: no PLIC context available\n", fwnode );
449
450
return - EINVAL ;
450
451
}
451
452
452
453
return 0 ;
453
454
}
454
455
455
- static int plic_parse_context_parent (struct platform_device * pdev , u32 context ,
456
+ static int plic_parse_context_parent (struct fwnode_handle * fwnode , u32 context ,
456
457
u32 * parent_hwirq , int * parent_cpu )
457
458
{
458
- struct device * dev = & pdev -> dev ;
459
459
struct of_phandle_args parent ;
460
460
unsigned long hartid ;
461
461
int rc ;
@@ -464,10 +464,10 @@ static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
464
464
* Currently, only OF fwnode is supported so extend this
465
465
* function for ACPI support.
466
466
*/
467
- if (!is_of_node (dev -> fwnode ))
467
+ if (!is_of_node (fwnode ))
468
468
return - EINVAL ;
469
469
470
- rc = of_irq_parse_one (to_of_node (dev -> fwnode ), context , & parent );
470
+ rc = of_irq_parse_one (to_of_node (fwnode ), context , & parent );
471
471
if (rc )
472
472
return rc ;
473
473
@@ -480,48 +480,55 @@ static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
480
480
return 0 ;
481
481
}
482
482
483
- static int plic_probe (struct platform_device * pdev )
483
+ static int plic_probe (struct fwnode_handle * fwnode )
484
484
{
485
485
int error = 0 , nr_contexts , nr_handlers = 0 , cpu , i ;
486
- struct device * dev = & pdev -> dev ;
487
486
unsigned long plic_quirks = 0 ;
488
487
struct plic_handler * handler ;
489
488
u32 nr_irqs , parent_hwirq ;
490
489
struct plic_priv * priv ;
491
490
irq_hw_number_t hwirq ;
491
+ void __iomem * regs ;
492
492
493
- if (is_of_node (dev -> fwnode )) {
493
+ if (is_of_node (fwnode )) {
494
494
const struct of_device_id * id ;
495
495
496
- id = of_match_node (plic_match , to_of_node (dev -> fwnode ));
496
+ id = of_match_node (plic_match , to_of_node (fwnode ));
497
497
if (id )
498
498
plic_quirks = (unsigned long )id -> data ;
499
+
500
+ regs = of_iomap (to_of_node (fwnode ), 0 );
501
+ if (!regs )
502
+ return - ENOMEM ;
503
+ } else {
504
+ return - ENODEV ;
499
505
}
500
506
501
- error = plic_parse_nr_irqs_and_contexts (pdev , & nr_irqs , & nr_contexts );
507
+ error = plic_parse_nr_irqs_and_contexts (fwnode , & nr_irqs , & nr_contexts );
502
508
if (error )
503
- return error ;
509
+ goto fail_free_regs ;
504
510
505
- priv = devm_kzalloc (dev , sizeof (* priv ), GFP_KERNEL );
506
- if (!priv )
507
- return - ENOMEM ;
511
+ priv = kzalloc (sizeof (* priv ), GFP_KERNEL );
512
+ if (!priv ) {
513
+ error = - ENOMEM ;
514
+ goto fail_free_regs ;
515
+ }
508
516
509
- priv -> dev = dev ;
517
+ priv -> fwnode = fwnode ;
510
518
priv -> plic_quirks = plic_quirks ;
511
519
priv -> nr_irqs = nr_irqs ;
520
+ priv -> regs = regs ;
512
521
513
- priv -> regs = devm_platform_ioremap_resource (pdev , 0 );
514
- if (WARN_ON (!priv -> regs ))
515
- return - EIO ;
516
-
517
- priv -> prio_save = devm_bitmap_zalloc (dev , nr_irqs , GFP_KERNEL );
518
- if (!priv -> prio_save )
519
- return - ENOMEM ;
522
+ priv -> prio_save = bitmap_zalloc (nr_irqs , GFP_KERNEL );
523
+ if (!priv -> prio_save ) {
524
+ error = - ENOMEM ;
525
+ goto fail_free_priv ;
526
+ }
520
527
521
528
for (i = 0 ; i < nr_contexts ; i ++ ) {
522
- error = plic_parse_context_parent (pdev , i , & parent_hwirq , & cpu );
529
+ error = plic_parse_context_parent (fwnode , i , & parent_hwirq , & cpu );
523
530
if (error ) {
524
- dev_warn ( dev , " hwirq for context%d not found\n" , i );
531
+ pr_warn ( "%pfwP: hwirq for context%d not found\n", fwnode , i );
525
532
continue ;
526
533
}
527
534
@@ -543,7 +550,7 @@ static int plic_probe(struct platform_device *pdev)
543
550
}
544
551
545
552
if (cpu < 0 ) {
546
- dev_warn ( dev , " Invalid cpuid for context %d\n" , i );
553
+ pr_warn ( "%pfwP: Invalid cpuid for context %d\n", fwnode , i );
547
554
continue ;
548
555
}
549
556
@@ -554,7 +561,7 @@ static int plic_probe(struct platform_device *pdev)
554
561
*/
555
562
handler = per_cpu_ptr (& plic_handlers , cpu );
556
563
if (handler -> present ) {
557
- dev_warn ( dev , " handler already present for context %d.\n" , i );
564
+ pr_warn ( "%pfwP: handler already present for context %d.\n", fwnode , i );
558
565
plic_set_threshold (handler , PLIC_DISABLE_THRESHOLD );
559
566
goto done ;
560
567
}
@@ -568,8 +575,8 @@ static int plic_probe(struct platform_device *pdev)
568
575
i * CONTEXT_ENABLE_SIZE ;
569
576
handler -> priv = priv ;
570
577
571
- handler -> enable_save = devm_kcalloc ( dev , DIV_ROUND_UP (nr_irqs , 32 ),
572
- sizeof (* handler -> enable_save ), GFP_KERNEL );
578
+ handler -> enable_save = kcalloc ( DIV_ROUND_UP (nr_irqs , 32 ),
579
+ sizeof (* handler -> enable_save ), GFP_KERNEL );
573
580
if (!handler -> enable_save )
574
581
goto fail_cleanup_contexts ;
575
582
done :
@@ -581,7 +588,7 @@ static int plic_probe(struct platform_device *pdev)
581
588
nr_handlers ++ ;
582
589
}
583
590
584
- priv -> irqdomain = irq_domain_add_linear (to_of_node (dev -> fwnode ), nr_irqs + 1 ,
591
+ priv -> irqdomain = irq_domain_add_linear (to_of_node (fwnode ), nr_irqs + 1 ,
585
592
& plic_irqdomain_ops , priv );
586
593
if (WARN_ON (!priv -> irqdomain ))
587
594
goto fail_cleanup_contexts ;
@@ -619,13 +626,13 @@ static int plic_probe(struct platform_device *pdev)
619
626
}
620
627
}
621
628
622
- dev_info ( dev , " mapped %d interrupts with %d handlers for %d contexts.\n" ,
623
- nr_irqs , nr_handlers , nr_contexts );
629
+ pr_info ( "%pfwP: mapped %d interrupts with %d handlers for %d contexts.\n" ,
630
+ fwnode , nr_irqs , nr_handlers , nr_contexts );
624
631
return 0 ;
625
632
626
633
fail_cleanup_contexts :
627
634
for (i = 0 ; i < nr_contexts ; i ++ ) {
628
- if (plic_parse_context_parent (pdev , i , & parent_hwirq , & cpu ))
635
+ if (plic_parse_context_parent (fwnode , i , & parent_hwirq , & cpu ))
629
636
continue ;
630
637
if (parent_hwirq != RV_IRQ_EXT || cpu < 0 )
631
638
continue ;
@@ -634,17 +641,37 @@ static int plic_probe(struct platform_device *pdev)
634
641
handler -> present = false;
635
642
handler -> hart_base = NULL ;
636
643
handler -> enable_base = NULL ;
644
+ kfree (handler -> enable_save );
637
645
handler -> enable_save = NULL ;
638
646
handler -> priv = NULL ;
639
647
}
640
- return - ENOMEM ;
648
+ bitmap_free (priv -> prio_save );
649
+ fail_free_priv :
650
+ kfree (priv );
651
+ fail_free_regs :
652
+ iounmap (regs );
653
+ return error ;
654
+ }
655
+
656
+ static int plic_platform_probe (struct platform_device * pdev )
657
+ {
658
+ return plic_probe (pdev -> dev .fwnode );
641
659
}
642
660
643
661
static struct platform_driver plic_driver = {
644
662
.driver = {
645
663
.name = "riscv-plic" ,
646
664
.of_match_table = plic_match ,
665
+ .suppress_bind_attrs = true,
647
666
},
648
- .probe = plic_probe ,
667
+ .probe = plic_platform_probe ,
649
668
};
650
669
builtin_platform_driver (plic_driver );
670
+
671
+ static int __init plic_early_probe (struct device_node * node ,
672
+ struct device_node * parent )
673
+ {
674
+ return plic_probe (& node -> fwnode );
675
+ }
676
+
677
+ IRQCHIP_DECLARE (riscv , "allwinner,sun20i-d1-plic" , plic_early_probe );
0 commit comments