diff options
Diffstat (limited to 'arch/arm/common/gic.c')
-rw-r--r-- | arch/arm/common/gic.c | 95 |
1 files changed, 42 insertions, 53 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index c47d6199b784..f0783be17352 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c | |||
@@ -51,7 +51,6 @@ union gic_base { | |||
51 | }; | 51 | }; |
52 | 52 | ||
53 | struct gic_chip_data { | 53 | struct gic_chip_data { |
54 | unsigned int irq_offset; | ||
55 | union gic_base dist_base; | 54 | union gic_base dist_base; |
56 | union gic_base cpu_base; | 55 | union gic_base cpu_base; |
57 | #ifdef CONFIG_CPU_PM | 56 | #ifdef CONFIG_CPU_PM |
@@ -61,9 +60,7 @@ struct gic_chip_data { | |||
61 | u32 __percpu *saved_ppi_enable; | 60 | u32 __percpu *saved_ppi_enable; |
62 | u32 __percpu *saved_ppi_conf; | 61 | u32 __percpu *saved_ppi_conf; |
63 | #endif | 62 | #endif |
64 | #ifdef CONFIG_IRQ_DOMAIN | 63 | struct irq_domain *domain; |
65 | struct irq_domain domain; | ||
66 | #endif | ||
67 | unsigned int gic_irqs; | 64 | unsigned int gic_irqs; |
68 | #ifdef CONFIG_GIC_NON_BANKED | 65 | #ifdef CONFIG_GIC_NON_BANKED |
69 | void __iomem *(*get_base)(union gic_base *); | 66 | void __iomem *(*get_base)(union gic_base *); |
@@ -282,7 +279,7 @@ asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) | |||
282 | irqnr = irqstat & ~0x1c00; | 279 | irqnr = irqstat & ~0x1c00; |
283 | 280 | ||
284 | if (likely(irqnr > 15 && irqnr < 1021)) { | 281 | if (likely(irqnr > 15 && irqnr < 1021)) { |
285 | irqnr = irq_domain_to_irq(&gic->domain, irqnr); | 282 | irqnr = irq_find_mapping(gic->domain, irqnr); |
286 | handle_IRQ(irqnr, regs); | 283 | handle_IRQ(irqnr, regs); |
287 | continue; | 284 | continue; |
288 | } | 285 | } |
@@ -314,8 +311,8 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) | |||
314 | if (gic_irq == 1023) | 311 | if (gic_irq == 1023) |
315 | goto out; | 312 | goto out; |
316 | 313 | ||
317 | cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq); | 314 | cascade_irq = irq_find_mapping(chip_data->domain, gic_irq); |
318 | if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS)) | 315 | if (unlikely(gic_irq < 32 || gic_irq > 1020)) |
319 | do_bad_IRQ(cascade_irq, desc); | 316 | do_bad_IRQ(cascade_irq, desc); |
320 | else | 317 | else |
321 | generic_handle_irq(cascade_irq); | 318 | generic_handle_irq(cascade_irq); |
@@ -348,10 +345,9 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) | |||
348 | 345 | ||
349 | static void __init gic_dist_init(struct gic_chip_data *gic) | 346 | static void __init gic_dist_init(struct gic_chip_data *gic) |
350 | { | 347 | { |
351 | unsigned int i, irq; | 348 | unsigned int i; |
352 | u32 cpumask; | 349 | u32 cpumask; |
353 | unsigned int gic_irqs = gic->gic_irqs; | 350 | unsigned int gic_irqs = gic->gic_irqs; |
354 | struct irq_domain *domain = &gic->domain; | ||
355 | void __iomem *base = gic_data_dist_base(gic); | 351 | void __iomem *base = gic_data_dist_base(gic); |
356 | u32 cpu = cpu_logical_map(smp_processor_id()); | 352 | u32 cpu = cpu_logical_map(smp_processor_id()); |
357 | 353 | ||
@@ -386,23 +382,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic) | |||
386 | for (i = 32; i < gic_irqs; i += 32) | 382 | for (i = 32; i < gic_irqs; i += 32) |
387 | writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); | 383 | writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); |
388 | 384 | ||
389 | /* | ||
390 | * Setup the Linux IRQ subsystem. | ||
391 | */ | ||
392 | irq_domain_for_each_irq(domain, i, irq) { | ||
393 | if (i < 32) { | ||
394 | irq_set_percpu_devid(irq); | ||
395 | irq_set_chip_and_handler(irq, &gic_chip, | ||
396 | handle_percpu_devid_irq); | ||
397 | set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); | ||
398 | } else { | ||
399 | irq_set_chip_and_handler(irq, &gic_chip, | ||
400 | handle_fasteoi_irq); | ||
401 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
402 | } | ||
403 | irq_set_chip_data(irq, gic); | ||
404 | } | ||
405 | |||
406 | writel_relaxed(1, base + GIC_DIST_CTRL); | 385 | writel_relaxed(1, base + GIC_DIST_CTRL); |
407 | } | 386 | } |
408 | 387 | ||
@@ -618,11 +597,27 @@ static void __init gic_pm_init(struct gic_chip_data *gic) | |||
618 | } | 597 | } |
619 | #endif | 598 | #endif |
620 | 599 | ||
621 | #ifdef CONFIG_OF | 600 | static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, |
622 | static int gic_irq_domain_dt_translate(struct irq_domain *d, | 601 | irq_hw_number_t hw) |
623 | struct device_node *controller, | 602 | { |
624 | const u32 *intspec, unsigned int intsize, | 603 | if (hw < 32) { |
625 | unsigned long *out_hwirq, unsigned int *out_type) | 604 | irq_set_percpu_devid(irq); |
605 | irq_set_chip_and_handler(irq, &gic_chip, | ||
606 | handle_percpu_devid_irq); | ||
607 | set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); | ||
608 | } else { | ||
609 | irq_set_chip_and_handler(irq, &gic_chip, | ||
610 | handle_fasteoi_irq); | ||
611 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
612 | } | ||
613 | irq_set_chip_data(irq, d->host_data); | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | static int gic_irq_domain_xlate(struct irq_domain *d, | ||
618 | struct device_node *controller, | ||
619 | const u32 *intspec, unsigned int intsize, | ||
620 | unsigned long *out_hwirq, unsigned int *out_type) | ||
626 | { | 621 | { |
627 | if (d->of_node != controller) | 622 | if (d->of_node != controller) |
628 | return -EINVAL; | 623 | return -EINVAL; |
@@ -639,26 +634,23 @@ static int gic_irq_domain_dt_translate(struct irq_domain *d, | |||
639 | *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; | 634 | *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; |
640 | return 0; | 635 | return 0; |
641 | } | 636 | } |
642 | #endif | ||
643 | 637 | ||
644 | const struct irq_domain_ops gic_irq_domain_ops = { | 638 | const struct irq_domain_ops gic_irq_domain_ops = { |
645 | #ifdef CONFIG_OF | 639 | .map = gic_irq_domain_map, |
646 | .dt_translate = gic_irq_domain_dt_translate, | 640 | .xlate = gic_irq_domain_xlate, |
647 | #endif | ||
648 | }; | 641 | }; |
649 | 642 | ||
650 | void __init gic_init_bases(unsigned int gic_nr, int irq_start, | 643 | void __init gic_init_bases(unsigned int gic_nr, int irq_start, |
651 | void __iomem *dist_base, void __iomem *cpu_base, | 644 | void __iomem *dist_base, void __iomem *cpu_base, |
652 | u32 percpu_offset) | 645 | u32 percpu_offset, struct device_node *node) |
653 | { | 646 | { |
647 | irq_hw_number_t hwirq_base; | ||
654 | struct gic_chip_data *gic; | 648 | struct gic_chip_data *gic; |
655 | struct irq_domain *domain; | 649 | int gic_irqs, irq_base; |
656 | int gic_irqs; | ||
657 | 650 | ||
658 | BUG_ON(gic_nr >= MAX_GIC_NR); | 651 | BUG_ON(gic_nr >= MAX_GIC_NR); |
659 | 652 | ||
660 | gic = &gic_data[gic_nr]; | 653 | gic = &gic_data[gic_nr]; |
661 | domain = &gic->domain; | ||
662 | #ifdef CONFIG_GIC_NON_BANKED | 654 | #ifdef CONFIG_GIC_NON_BANKED |
663 | if (percpu_offset) { /* Frankein-GIC without banked registers... */ | 655 | if (percpu_offset) { /* Frankein-GIC without banked registers... */ |
664 | unsigned int cpu; | 656 | unsigned int cpu; |
@@ -694,10 +686,10 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, | |||
694 | * For primary GICs, skip over SGIs. | 686 | * For primary GICs, skip over SGIs. |
695 | * For secondary GICs, skip over PPIs, too. | 687 | * For secondary GICs, skip over PPIs, too. |
696 | */ | 688 | */ |
697 | domain->hwirq_base = 32; | 689 | hwirq_base = 32; |
698 | if (gic_nr == 0) { | 690 | if (gic_nr == 0) { |
699 | if ((irq_start & 31) > 0) { | 691 | if ((irq_start & 31) > 0) { |
700 | domain->hwirq_base = 16; | 692 | hwirq_base = 16; |
701 | if (irq_start != -1) | 693 | if (irq_start != -1) |
702 | irq_start = (irq_start & ~31) + 16; | 694 | irq_start = (irq_start & ~31) + 16; |
703 | } | 695 | } |
@@ -713,17 +705,17 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, | |||
713 | gic_irqs = 1020; | 705 | gic_irqs = 1020; |
714 | gic->gic_irqs = gic_irqs; | 706 | gic->gic_irqs = gic_irqs; |
715 | 707 | ||
716 | domain->nr_irq = gic_irqs - domain->hwirq_base; | 708 | gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ |
717 | domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq, | 709 | irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, numa_node_id()); |
718 | numa_node_id()); | 710 | if (IS_ERR_VALUE(irq_base)) { |
719 | if (IS_ERR_VALUE(domain->irq_base)) { | ||
720 | WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", | 711 | WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", |
721 | irq_start); | 712 | irq_start); |
722 | domain->irq_base = irq_start; | 713 | irq_base = irq_start; |
723 | } | 714 | } |
724 | domain->priv = gic; | 715 | gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, |
725 | domain->ops = &gic_irq_domain_ops; | 716 | hwirq_base, &gic_irq_domain_ops, gic); |
726 | irq_domain_add(domain); | 717 | if (WARN_ON(!gic->domain)) |
718 | return; | ||
727 | 719 | ||
728 | gic_chip.flags |= gic_arch_extn.flags; | 720 | gic_chip.flags |= gic_arch_extn.flags; |
729 | gic_dist_init(gic); | 721 | gic_dist_init(gic); |
@@ -768,7 +760,6 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) | |||
768 | void __iomem *dist_base; | 760 | void __iomem *dist_base; |
769 | u32 percpu_offset; | 761 | u32 percpu_offset; |
770 | int irq; | 762 | int irq; |
771 | struct irq_domain *domain = &gic_data[gic_cnt].domain; | ||
772 | 763 | ||
773 | if (WARN_ON(!node)) | 764 | if (WARN_ON(!node)) |
774 | return -ENODEV; | 765 | return -ENODEV; |
@@ -782,9 +773,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) | |||
782 | if (of_property_read_u32(node, "cpu-offset", &percpu_offset)) | 773 | if (of_property_read_u32(node, "cpu-offset", &percpu_offset)) |
783 | percpu_offset = 0; | 774 | percpu_offset = 0; |
784 | 775 | ||
785 | domain->of_node = of_node_get(node); | 776 | gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node); |
786 | |||
787 | gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset); | ||
788 | 777 | ||
789 | if (parent) { | 778 | if (parent) { |
790 | irq = irq_of_parse_and_map(node, 0); | 779 | irq = irq_of_parse_and_map(node, 0); |