33 * Copyright (C) 2017 SiFive
44 * Copyright (C) 2018 Christoph Hellwig
55 */
6+ #define pr_fmt (fmt ) "riscv-plic: " fmt
67#include <linux/cpu.h>
78#include <linux/interrupt.h>
89#include <linux/io.h>
6364#define PLIC_QUIRK_EDGE_INTERRUPT 0
6465
6566struct plic_priv {
66- struct device * dev ;
67+ struct fwnode_handle * fwnode ;
6768 struct cpumask lmask ;
6869 struct irq_domain * irqdomain ;
6970 void __iomem * regs ;
@@ -378,8 +379,8 @@ static void plic_handle_irq(struct irq_desc *desc)
378379 int err = generic_handle_domain_irq (handler -> priv -> irqdomain ,
379380 hwirq );
380381 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 );
383384 }
384385 }
385386
@@ -408,7 +409,8 @@ static int plic_starting_cpu(unsigned int cpu)
408409 enable_percpu_irq (plic_parent_irq ,
409410 irq_get_trigger_type (plic_parent_irq ));
410411 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 );
412414 plic_set_threshold (handler , PLIC_ENABLE_THRESHOLD );
413415
414416 return 0 ;
@@ -424,38 +426,36 @@ static const struct of_device_id plic_match[] = {
424426 {}
425427};
426428
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 ,
428430 u32 * nr_irqs , u32 * nr_contexts )
429431{
430- struct device * dev = & pdev -> dev ;
431432 int rc ;
432433
433434 /*
434435 * Currently, only OF fwnode is supported so extend this
435436 * function for ACPI support.
436437 */
437- if (!is_of_node (dev -> fwnode ))
438+ if (!is_of_node (fwnode ))
438439 return - EINVAL ;
439440
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 );
441442 if (rc ) {
442- dev_err ( dev , " riscv,ndev property not available\n" );
443+ pr_err ( "%pfwP: riscv,ndev property not available\n", fwnode );
443444 return rc ;
444445 }
445446
446- * nr_contexts = of_irq_count (to_of_node (dev -> fwnode ));
447+ * nr_contexts = of_irq_count (to_of_node (fwnode ));
447448 if (WARN_ON (!(* nr_contexts ))) {
448- dev_err ( dev , " no PLIC context available\n" );
449+ pr_err ( "%pfwP: no PLIC context available\n", fwnode );
449450 return - EINVAL ;
450451 }
451452
452453 return 0 ;
453454}
454455
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 ,
456457 u32 * parent_hwirq , int * parent_cpu )
457458{
458- struct device * dev = & pdev -> dev ;
459459 struct of_phandle_args parent ;
460460 unsigned long hartid ;
461461 int rc ;
@@ -464,10 +464,10 @@ static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
464464 * Currently, only OF fwnode is supported so extend this
465465 * function for ACPI support.
466466 */
467- if (!is_of_node (dev -> fwnode ))
467+ if (!is_of_node (fwnode ))
468468 return - EINVAL ;
469469
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 );
471471 if (rc )
472472 return rc ;
473473
@@ -480,48 +480,55 @@ static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
480480 return 0 ;
481481}
482482
483- static int plic_probe (struct platform_device * pdev )
483+ static int plic_probe (struct fwnode_handle * fwnode )
484484{
485485 int error = 0 , nr_contexts , nr_handlers = 0 , cpu , i ;
486- struct device * dev = & pdev -> dev ;
487486 unsigned long plic_quirks = 0 ;
488487 struct plic_handler * handler ;
489488 u32 nr_irqs , parent_hwirq ;
490489 struct plic_priv * priv ;
491490 irq_hw_number_t hwirq ;
491+ void __iomem * regs ;
492492
493- if (is_of_node (dev -> fwnode )) {
493+ if (is_of_node (fwnode )) {
494494 const struct of_device_id * id ;
495495
496- id = of_match_node (plic_match , to_of_node (dev -> fwnode ));
496+ id = of_match_node (plic_match , to_of_node (fwnode ));
497497 if (id )
498498 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 ;
499505 }
500506
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 );
502508 if (error )
503- return error ;
509+ goto fail_free_regs ;
504510
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+ }
508516
509- priv -> dev = dev ;
517+ priv -> fwnode = fwnode ;
510518 priv -> plic_quirks = plic_quirks ;
511519 priv -> nr_irqs = nr_irqs ;
520+ priv -> regs = regs ;
512521
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+ }
520527
521528 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 );
523530 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 );
525532 continue ;
526533 }
527534
@@ -543,7 +550,7 @@ static int plic_probe(struct platform_device *pdev)
543550 }
544551
545552 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 );
547554 continue ;
548555 }
549556
@@ -554,7 +561,7 @@ static int plic_probe(struct platform_device *pdev)
554561 */
555562 handler = per_cpu_ptr (& plic_handlers , cpu );
556563 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 );
558565 plic_set_threshold (handler , PLIC_DISABLE_THRESHOLD );
559566 goto done ;
560567 }
@@ -568,8 +575,8 @@ static int plic_probe(struct platform_device *pdev)
568575 i * CONTEXT_ENABLE_SIZE ;
569576 handler -> priv = priv ;
570577
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 );
573580 if (!handler -> enable_save )
574581 goto fail_cleanup_contexts ;
575582done :
@@ -581,7 +588,7 @@ static int plic_probe(struct platform_device *pdev)
581588 nr_handlers ++ ;
582589 }
583590
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 ,
585592 & plic_irqdomain_ops , priv );
586593 if (WARN_ON (!priv -> irqdomain ))
587594 goto fail_cleanup_contexts ;
@@ -619,13 +626,13 @@ static int plic_probe(struct platform_device *pdev)
619626 }
620627 }
621628
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 );
624631 return 0 ;
625632
626633fail_cleanup_contexts :
627634 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 ))
629636 continue ;
630637 if (parent_hwirq != RV_IRQ_EXT || cpu < 0 )
631638 continue ;
@@ -634,17 +641,37 @@ static int plic_probe(struct platform_device *pdev)
634641 handler -> present = false;
635642 handler -> hart_base = NULL ;
636643 handler -> enable_base = NULL ;
644+ kfree (handler -> enable_save );
637645 handler -> enable_save = NULL ;
638646 handler -> priv = NULL ;
639647 }
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 );
641659}
642660
643661static struct platform_driver plic_driver = {
644662 .driver = {
645663 .name = "riscv-plic" ,
646664 .of_match_table = plic_match ,
665+ .suppress_bind_attrs = true,
647666 },
648- .probe = plic_probe ,
667+ .probe = plic_platform_probe ,
649668};
650669builtin_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