aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/irqchip/Kconfig1
-rw-r--r--drivers/irqchip/irq-gic-v3.c42
2 files changed, 38 insertions, 5 deletions
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index b21f12f1766d..4631685dfe43 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -14,6 +14,7 @@ config ARM_GIC_V3
14 bool 14 bool
15 select IRQ_DOMAIN 15 select IRQ_DOMAIN
16 select MULTI_IRQ_HANDLER 16 select MULTI_IRQ_HANDLER
17 select IRQ_DOMAIN_HIERARCHY
17 18
18config ARM_NVIC 19config ARM_NVIC
19 bool 20 bool
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index aa17ae805a70..4cb355aff3c6 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -594,14 +594,14 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
594 /* PPIs */ 594 /* PPIs */
595 if (hw < 32) { 595 if (hw < 32) {
596 irq_set_percpu_devid(irq); 596 irq_set_percpu_devid(irq);
597 irq_set_chip_and_handler(irq, &gic_chip, 597 irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data,
598 handle_percpu_devid_irq); 598 handle_percpu_devid_irq, NULL, NULL);
599 set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); 599 set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
600 } 600 }
601 /* SPIs */ 601 /* SPIs */
602 if (hw >= 32 && hw < gic_data.irq_nr) { 602 if (hw >= 32 && hw < gic_data.irq_nr) {
603 irq_set_chip_and_handler(irq, &gic_chip, 603 irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data,
604 handle_fasteoi_irq); 604 handle_fasteoi_irq, NULL, NULL);
605 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 605 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
606 } 606 }
607 irq_set_chip_data(irq, d->host_data); 607 irq_set_chip_data(irq, d->host_data);
@@ -633,9 +633,41 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
633 return 0; 633 return 0;
634} 634}
635 635
636static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
637 unsigned int nr_irqs, void *arg)
638{
639 int i, ret;
640 irq_hw_number_t hwirq;
641 unsigned int type = IRQ_TYPE_NONE;
642 struct of_phandle_args *irq_data = arg;
643
644 ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
645 irq_data->args_count, &hwirq, &type);
646 if (ret)
647 return ret;
648
649 for (i = 0; i < nr_irqs; i++)
650 gic_irq_domain_map(domain, virq + i, hwirq + i);
651
652 return 0;
653}
654
655static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
656 unsigned int nr_irqs)
657{
658 int i;
659
660 for (i = 0; i < nr_irqs; i++) {
661 struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
662 irq_set_handler(virq + i, NULL);
663 irq_domain_reset_irq_data(d);
664 }
665}
666
636static const struct irq_domain_ops gic_irq_domain_ops = { 667static const struct irq_domain_ops gic_irq_domain_ops = {
637 .map = gic_irq_domain_map,
638 .xlate = gic_irq_domain_xlate, 668 .xlate = gic_irq_domain_xlate,
669 .alloc = gic_irq_domain_alloc,
670 .free = gic_irq_domain_free,
639}; 671};
640 672
641static int __init gic_of_init(struct device_node *node, struct device_node *parent) 673static int __init gic_of_init(struct device_node *node, struct device_node *parent)