aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2014-11-24 09:35:10 -0500
committerJason Cooper <jason@lakedaemon.net>2014-11-26 10:55:12 -0500
commitf5c1434c217fd72ac0d24d3142d09e49a3d4e72e (patch)
treeaecaafc7fe456cd46d2b6764ca7fcb870a3f4de6 /drivers/irqchip
parent443acc4f37f61e343f3577dc28d7e7fd8b499465 (diff)
irqchip: GICv3: rework redistributor structure
The basic GICv3 driver has almost no use for the redistributor (other than the basic per-CPU interrupts), but the ITS needs a lot more from them. As such, rework the set of data structures. The behaviour of the GICv3 driver is otherwise unaffected. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Link: https://lkml.kernel.org/r/1416839720-18400-4-git-send-email-marc.zyngier@arm.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-gic-v3.c73
1 files changed, 44 insertions, 29 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 4cb355aff3c6..43e57da0d80e 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -34,20 +34,25 @@
34#include "irq-gic-common.h" 34#include "irq-gic-common.h"
35#include "irqchip.h" 35#include "irqchip.h"
36 36
37struct redist_region {
38 void __iomem *redist_base;
39 phys_addr_t phys_base;
40};
41
37struct gic_chip_data { 42struct gic_chip_data {
38 void __iomem *dist_base; 43 void __iomem *dist_base;
39 void __iomem **redist_base; 44 struct redist_region *redist_regions;
40 void __iomem * __percpu *rdist; 45 struct rdists rdists;
41 struct irq_domain *domain; 46 struct irq_domain *domain;
42 u64 redist_stride; 47 u64 redist_stride;
43 u32 redist_regions; 48 u32 nr_redist_regions;
44 unsigned int irq_nr; 49 unsigned int irq_nr;
45}; 50};
46 51
47static struct gic_chip_data gic_data __read_mostly; 52static struct gic_chip_data gic_data __read_mostly;
48 53
49#define gic_data_rdist() (this_cpu_ptr(gic_data.rdist)) 54#define gic_data_rdist() (this_cpu_ptr(gic_data.rdists.rdist))
50#define gic_data_rdist_rd_base() (*gic_data_rdist()) 55#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base)
51#define gic_data_rdist_sgi_base() (gic_data_rdist_rd_base() + SZ_64K) 56#define gic_data_rdist_sgi_base() (gic_data_rdist_rd_base() + SZ_64K)
52 57
53/* Our default, arbitrary priority value. Linux only uses one anyway. */ 58/* Our default, arbitrary priority value. Linux only uses one anyway. */
@@ -333,8 +338,8 @@ static int gic_populate_rdist(void)
333 MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 | 338 MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
334 MPIDR_AFFINITY_LEVEL(mpidr, 0)); 339 MPIDR_AFFINITY_LEVEL(mpidr, 0));
335 340
336 for (i = 0; i < gic_data.redist_regions; i++) { 341 for (i = 0; i < gic_data.nr_redist_regions; i++) {
337 void __iomem *ptr = gic_data.redist_base[i]; 342 void __iomem *ptr = gic_data.redist_regions[i].redist_base;
338 u32 reg; 343 u32 reg;
339 344
340 reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK; 345 reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK;
@@ -347,10 +352,13 @@ static int gic_populate_rdist(void)
347 do { 352 do {
348 typer = readq_relaxed(ptr + GICR_TYPER); 353 typer = readq_relaxed(ptr + GICR_TYPER);
349 if ((typer >> 32) == aff) { 354 if ((typer >> 32) == aff) {
355 u64 offset = ptr - gic_data.redist_regions[i].redist_base;
350 gic_data_rdist_rd_base() = ptr; 356 gic_data_rdist_rd_base() = ptr;
351 pr_info("CPU%d: found redistributor %llx @%p\n", 357 gic_data_rdist()->phys_base = gic_data.redist_regions[i].phys_base + offset;
358 pr_info("CPU%d: found redistributor %llx region %d:%pa\n",
352 smp_processor_id(), 359 smp_processor_id(),
353 (unsigned long long)mpidr, ptr); 360 (unsigned long long)mpidr,
361 i, &gic_data_rdist()->phys_base);
354 return 0; 362 return 0;
355 } 363 }
356 364
@@ -673,9 +681,10 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
673static int __init gic_of_init(struct device_node *node, struct device_node *parent) 681static int __init gic_of_init(struct device_node *node, struct device_node *parent)
674{ 682{
675 void __iomem *dist_base; 683 void __iomem *dist_base;
676 void __iomem **redist_base; 684 struct redist_region *rdist_regs;
677 u64 redist_stride; 685 u64 redist_stride;
678 u32 redist_regions; 686 u32 nr_redist_regions;
687 u32 typer;
679 u32 reg; 688 u32 reg;
680 int gic_irqs; 689 int gic_irqs;
681 int err; 690 int err;
@@ -696,48 +705,54 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
696 goto out_unmap_dist; 705 goto out_unmap_dist;
697 } 706 }
698 707
699 if (of_property_read_u32(node, "#redistributor-regions", &redist_regions)) 708 if (of_property_read_u32(node, "#redistributor-regions", &nr_redist_regions))
700 redist_regions = 1; 709 nr_redist_regions = 1;
701 710
702 redist_base = kzalloc(sizeof(*redist_base) * redist_regions, GFP_KERNEL); 711 rdist_regs = kzalloc(sizeof(*rdist_regs) * nr_redist_regions, GFP_KERNEL);
703 if (!redist_base) { 712 if (!rdist_regs) {
704 err = -ENOMEM; 713 err = -ENOMEM;
705 goto out_unmap_dist; 714 goto out_unmap_dist;
706 } 715 }
707 716
708 for (i = 0; i < redist_regions; i++) { 717 for (i = 0; i < nr_redist_regions; i++) {
709 redist_base[i] = of_iomap(node, 1 + i); 718 struct resource res;
710 if (!redist_base[i]) { 719 int ret;
720
721 ret = of_address_to_resource(node, 1 + i, &res);
722 rdist_regs[i].redist_base = of_iomap(node, 1 + i);
723 if (ret || !rdist_regs[i].redist_base) {
711 pr_err("%s: couldn't map region %d\n", 724 pr_err("%s: couldn't map region %d\n",
712 node->full_name, i); 725 node->full_name, i);
713 err = -ENODEV; 726 err = -ENODEV;
714 goto out_unmap_rdist; 727 goto out_unmap_rdist;
715 } 728 }
729 rdist_regs[i].phys_base = res.start;
716 } 730 }
717 731
718 if (of_property_read_u64(node, "redistributor-stride", &redist_stride)) 732 if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
719 redist_stride = 0; 733 redist_stride = 0;
720 734
721 gic_data.dist_base = dist_base; 735 gic_data.dist_base = dist_base;
722 gic_data.redist_base = redist_base; 736 gic_data.redist_regions = rdist_regs;
723 gic_data.redist_regions = redist_regions; 737 gic_data.nr_redist_regions = nr_redist_regions;
724 gic_data.redist_stride = redist_stride; 738 gic_data.redist_stride = redist_stride;
725 739
726 /* 740 /*
727 * Find out how many interrupts are supported. 741 * Find out how many interrupts are supported.
728 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI) 742 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
729 */ 743 */
730 gic_irqs = readl_relaxed(gic_data.dist_base + GICD_TYPER) & 0x1f; 744 typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
731 gic_irqs = (gic_irqs + 1) * 32; 745 gic_data.rdists.id_bits = GICD_TYPER_ID_BITS(typer);
746 gic_irqs = GICD_TYPER_IRQS(typer);
732 if (gic_irqs > 1020) 747 if (gic_irqs > 1020)
733 gic_irqs = 1020; 748 gic_irqs = 1020;
734 gic_data.irq_nr = gic_irqs; 749 gic_data.irq_nr = gic_irqs;
735 750
736 gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops, 751 gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
737 &gic_data); 752 &gic_data);
738 gic_data.rdist = alloc_percpu(typeof(*gic_data.rdist)); 753 gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
739 754
740 if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdist)) { 755 if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
741 err = -ENOMEM; 756 err = -ENOMEM;
742 goto out_free; 757 goto out_free;
743 } 758 }
@@ -754,12 +769,12 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
754out_free: 769out_free:
755 if (gic_data.domain) 770 if (gic_data.domain)
756 irq_domain_remove(gic_data.domain); 771 irq_domain_remove(gic_data.domain);
757 free_percpu(gic_data.rdist); 772 free_percpu(gic_data.rdists.rdist);
758out_unmap_rdist: 773out_unmap_rdist:
759 for (i = 0; i < redist_regions; i++) 774 for (i = 0; i < nr_redist_regions; i++)
760 if (redist_base[i]) 775 if (rdist_regs[i].redist_base)
761 iounmap(redist_base[i]); 776 iounmap(rdist_regs[i].redist_base);
762 kfree(redist_base); 777 kfree(rdist_regs);
763out_unmap_dist: 778out_unmap_dist:
764 iounmap(dist_base); 779 iounmap(dist_base);
765 return err; 780 return err;