diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2015-12-19 06:16:20 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2015-12-19 06:16:20 -0500 |
commit | 4e8dbe9e93436bcf326adbab7f9761dd8e4ecbfc (patch) | |
tree | 128f3a2a1cc33dddc3a0522185acb48d12c1b6ee | |
parent | ef0bf620e9b81845368b9c72ffdbd6834e424526 (diff) | |
parent | a27d21e03eb14a63dae12467a7655be3334ac80c (diff) |
Merge branch 'irq/gic-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull the GIC related updates from Marc Zyngier:
"Not a lot this time (what a relief!), but an interesting series from
Linus Walleij coming out of his work converting the ARM RealView
platforms to DT, and a couple of mundane fixes."
-rw-r--r-- | Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt | 1 | ||||
-rw-r--r-- | drivers/irqchip/Kconfig | 5 | ||||
-rw-r--r-- | drivers/irqchip/Makefile | 1 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-realview.c | 43 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v2m.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic.c | 56 | ||||
-rw-r--r-- | include/linux/irqchip/arm-gic.h | 10 |
7 files changed, 86 insertions, 32 deletions
diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt index cc56021eb60b..5a1cb4bc3dfe 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt | |||
@@ -18,6 +18,7 @@ Main node required properties: | |||
18 | "arm,cortex-a9-gic" | 18 | "arm,cortex-a9-gic" |
19 | "arm,gic-400" | 19 | "arm,gic-400" |
20 | "arm,pl390" | 20 | "arm,pl390" |
21 | "arm,tc11mp-gic" | ||
21 | "brcm,brahma-b15-gic" | 22 | "brcm,brahma-b15-gic" |
22 | "qcom,msm-8660-qgic" | 23 | "qcom,msm-8660-qgic" |
23 | "qcom,msm-qgic2" | 24 | "qcom,msm-qgic2" |
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index b205e158e864..b5f51337ba74 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig | |||
@@ -8,6 +8,11 @@ config ARM_GIC | |||
8 | select IRQ_DOMAIN_HIERARCHY | 8 | select IRQ_DOMAIN_HIERARCHY |
9 | select MULTI_IRQ_HANDLER | 9 | select MULTI_IRQ_HANDLER |
10 | 10 | ||
11 | config ARM_GIC_MAX_NR | ||
12 | int | ||
13 | default 2 if ARCH_REALVIEW | ||
14 | default 1 | ||
15 | |||
11 | config ARM_GIC_V2M | 16 | config ARM_GIC_V2M |
12 | bool | 17 | bool |
13 | depends on ARM_GIC | 18 | depends on ARM_GIC |
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index cd76b11682eb..83d1fce13e86 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
@@ -21,6 +21,7 @@ obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o | |||
21 | obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o | 21 | obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o |
22 | obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o | 22 | obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o |
23 | obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o | 23 | obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o |
24 | obj-$(CONFIG_REALVIEW_DT) += irq-gic-realview.o | ||
24 | obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o | 25 | obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o |
25 | obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o | 26 | obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o |
26 | obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o | 27 | obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o |
diff --git a/drivers/irqchip/irq-gic-realview.c b/drivers/irqchip/irq-gic-realview.c new file mode 100644 index 000000000000..aa46eb280a7f --- /dev/null +++ b/drivers/irqchip/irq-gic-realview.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Special GIC quirks for the ARM RealView | ||
3 | * Copyright (C) 2015 Linus Walleij | ||
4 | */ | ||
5 | #include <linux/of.h> | ||
6 | #include <linux/regmap.h> | ||
7 | #include <linux/mfd/syscon.h> | ||
8 | #include <linux/bitops.h> | ||
9 | #include <linux/irqchip.h> | ||
10 | #include <linux/irqchip/arm-gic.h> | ||
11 | |||
12 | #define REALVIEW_SYS_LOCK_OFFSET 0x20 | ||
13 | #define REALVIEW_PB11MP_SYS_PLD_CTRL1 0x74 | ||
14 | #define VERSATILE_LOCK_VAL 0xA05F | ||
15 | #define PLD_INTMODE_MASK BIT(22)|BIT(23)|BIT(24) | ||
16 | #define PLD_INTMODE_LEGACY 0x0 | ||
17 | #define PLD_INTMODE_NEW_DCC BIT(22) | ||
18 | #define PLD_INTMODE_NEW_NO_DCC BIT(23) | ||
19 | #define PLD_INTMODE_FIQ_ENABLE BIT(24) | ||
20 | |||
21 | static int __init | ||
22 | realview_gic_of_init(struct device_node *node, struct device_node *parent) | ||
23 | { | ||
24 | static struct regmap *map; | ||
25 | |||
26 | /* The PB11MPCore GIC needs to be configured in the syscon */ | ||
27 | map = syscon_regmap_lookup_by_compatible("arm,realview-pb11mp-syscon"); | ||
28 | if (!IS_ERR(map)) { | ||
29 | /* new irq mode with no DCC */ | ||
30 | regmap_write(map, REALVIEW_SYS_LOCK_OFFSET, | ||
31 | VERSATILE_LOCK_VAL); | ||
32 | regmap_update_bits(map, REALVIEW_PB11MP_SYS_PLD_CTRL1, | ||
33 | PLD_INTMODE_NEW_NO_DCC, | ||
34 | PLD_INTMODE_MASK); | ||
35 | regmap_write(map, REALVIEW_SYS_LOCK_OFFSET, 0x0000); | ||
36 | pr_info("TC11MP GIC: set up interrupt controller to NEW mode, no DCC\n"); | ||
37 | } else { | ||
38 | pr_err("TC11MP GIC setup: could not find syscon\n"); | ||
39 | return -ENXIO; | ||
40 | } | ||
41 | return gic_of_init(node, parent); | ||
42 | } | ||
43 | IRQCHIP_DECLARE(armtc11mp_gic, "arm,tc11mp-gic", realview_gic_of_init); | ||
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index 87f8d104acab..ee1e553ee7a6 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c | |||
@@ -389,7 +389,7 @@ int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent) | |||
389 | 389 | ||
390 | ret = gicv2m_init_one(child, parent); | 390 | ret = gicv2m_init_one(child, parent); |
391 | if (ret) { | 391 | if (ret) { |
392 | of_node_put(node); | 392 | of_node_put(child); |
393 | break; | 393 | break; |
394 | } | 394 | } |
395 | } | 395 | } |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index abf2ffaed392..fcbe0b90870d 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -69,6 +69,7 @@ union gic_base { | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | struct gic_chip_data { | 71 | struct gic_chip_data { |
72 | struct irq_chip chip; | ||
72 | union gic_base dist_base; | 73 | union gic_base dist_base; |
73 | union gic_base cpu_base; | 74 | union gic_base cpu_base; |
74 | #ifdef CONFIG_CPU_PM | 75 | #ifdef CONFIG_CPU_PM |
@@ -99,11 +100,7 @@ static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly; | |||
99 | 100 | ||
100 | static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; | 101 | static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE; |
101 | 102 | ||
102 | #ifndef MAX_GIC_NR | 103 | static struct gic_chip_data gic_data[CONFIG_ARM_GIC_MAX_NR] __read_mostly; |
103 | #define MAX_GIC_NR 1 | ||
104 | #endif | ||
105 | |||
106 | static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly; | ||
107 | 104 | ||
108 | #ifdef CONFIG_GIC_NON_BANKED | 105 | #ifdef CONFIG_GIC_NON_BANKED |
109 | static void __iomem *gic_get_percpu_base(union gic_base *base) | 106 | static void __iomem *gic_get_percpu_base(union gic_base *base) |
@@ -336,7 +333,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) | |||
336 | irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); | 333 | irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); |
337 | irqnr = irqstat & GICC_IAR_INT_ID_MASK; | 334 | irqnr = irqstat & GICC_IAR_INT_ID_MASK; |
338 | 335 | ||
339 | if (likely(irqnr > 15 && irqnr < 1021)) { | 336 | if (likely(irqnr > 15 && irqnr < 1020)) { |
340 | if (static_key_true(&supports_deactivate)) | 337 | if (static_key_true(&supports_deactivate)) |
341 | writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); | 338 | writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); |
342 | handle_domain_irq(gic->domain, irqnr, regs); | 339 | handle_domain_irq(gic->domain, irqnr, regs); |
@@ -383,7 +380,6 @@ static void gic_handle_cascade_irq(struct irq_desc *desc) | |||
383 | } | 380 | } |
384 | 381 | ||
385 | static struct irq_chip gic_chip = { | 382 | static struct irq_chip gic_chip = { |
386 | .name = "GIC", | ||
387 | .irq_mask = gic_mask_irq, | 383 | .irq_mask = gic_mask_irq, |
388 | .irq_unmask = gic_unmask_irq, | 384 | .irq_unmask = gic_unmask_irq, |
389 | .irq_eoi = gic_eoi_irq, | 385 | .irq_eoi = gic_eoi_irq, |
@@ -417,8 +413,7 @@ static struct irq_chip gic_eoimode1_chip = { | |||
417 | 413 | ||
418 | void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) | 414 | void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) |
419 | { | 415 | { |
420 | if (gic_nr >= MAX_GIC_NR) | 416 | BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR); |
421 | BUG(); | ||
422 | irq_set_chained_handler_and_data(irq, gic_handle_cascade_irq, | 417 | irq_set_chained_handler_and_data(irq, gic_handle_cascade_irq, |
423 | &gic_data[gic_nr]); | 418 | &gic_data[gic_nr]); |
424 | } | 419 | } |
@@ -524,7 +519,7 @@ int gic_cpu_if_down(unsigned int gic_nr) | |||
524 | void __iomem *cpu_base; | 519 | void __iomem *cpu_base; |
525 | u32 val = 0; | 520 | u32 val = 0; |
526 | 521 | ||
527 | if (gic_nr >= MAX_GIC_NR) | 522 | if (gic_nr >= CONFIG_ARM_GIC_MAX_NR) |
528 | return -EINVAL; | 523 | return -EINVAL; |
529 | 524 | ||
530 | cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); | 525 | cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); |
@@ -548,8 +543,7 @@ static void gic_dist_save(unsigned int gic_nr) | |||
548 | void __iomem *dist_base; | 543 | void __iomem *dist_base; |
549 | int i; | 544 | int i; |
550 | 545 | ||
551 | if (gic_nr >= MAX_GIC_NR) | 546 | BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR); |
552 | BUG(); | ||
553 | 547 | ||
554 | gic_irqs = gic_data[gic_nr].gic_irqs; | 548 | gic_irqs = gic_data[gic_nr].gic_irqs; |
555 | dist_base = gic_data_dist_base(&gic_data[gic_nr]); | 549 | dist_base = gic_data_dist_base(&gic_data[gic_nr]); |
@@ -587,8 +581,7 @@ static void gic_dist_restore(unsigned int gic_nr) | |||
587 | unsigned int i; | 581 | unsigned int i; |
588 | void __iomem *dist_base; | 582 | void __iomem *dist_base; |
589 | 583 | ||
590 | if (gic_nr >= MAX_GIC_NR) | 584 | BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR); |
591 | BUG(); | ||
592 | 585 | ||
593 | gic_irqs = gic_data[gic_nr].gic_irqs; | 586 | gic_irqs = gic_data[gic_nr].gic_irqs; |
594 | dist_base = gic_data_dist_base(&gic_data[gic_nr]); | 587 | dist_base = gic_data_dist_base(&gic_data[gic_nr]); |
@@ -634,8 +627,7 @@ static void gic_cpu_save(unsigned int gic_nr) | |||
634 | void __iomem *dist_base; | 627 | void __iomem *dist_base; |
635 | void __iomem *cpu_base; | 628 | void __iomem *cpu_base; |
636 | 629 | ||
637 | if (gic_nr >= MAX_GIC_NR) | 630 | BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR); |
638 | BUG(); | ||
639 | 631 | ||
640 | dist_base = gic_data_dist_base(&gic_data[gic_nr]); | 632 | dist_base = gic_data_dist_base(&gic_data[gic_nr]); |
641 | cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); | 633 | cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); |
@@ -664,8 +656,7 @@ static void gic_cpu_restore(unsigned int gic_nr) | |||
664 | void __iomem *dist_base; | 656 | void __iomem *dist_base; |
665 | void __iomem *cpu_base; | 657 | void __iomem *cpu_base; |
666 | 658 | ||
667 | if (gic_nr >= MAX_GIC_NR) | 659 | BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR); |
668 | BUG(); | ||
669 | 660 | ||
670 | dist_base = gic_data_dist_base(&gic_data[gic_nr]); | 661 | dist_base = gic_data_dist_base(&gic_data[gic_nr]); |
671 | cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); | 662 | cpu_base = gic_data_cpu_base(&gic_data[gic_nr]); |
@@ -703,7 +694,7 @@ static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) | |||
703 | { | 694 | { |
704 | int i; | 695 | int i; |
705 | 696 | ||
706 | for (i = 0; i < MAX_GIC_NR; i++) { | 697 | for (i = 0; i < CONFIG_ARM_GIC_MAX_NR; i++) { |
707 | #ifdef CONFIG_GIC_NON_BANKED | 698 | #ifdef CONFIG_GIC_NON_BANKED |
708 | /* Skip over unused GICs */ | 699 | /* Skip over unused GICs */ |
709 | if (!gic_data[i].get_base) | 700 | if (!gic_data[i].get_base) |
@@ -835,8 +826,7 @@ void gic_migrate_target(unsigned int new_cpu_id) | |||
835 | int i, ror_val, cpu = smp_processor_id(); | 826 | int i, ror_val, cpu = smp_processor_id(); |
836 | u32 val, cur_target_mask, active_mask; | 827 | u32 val, cur_target_mask, active_mask; |
837 | 828 | ||
838 | if (gic_nr >= MAX_GIC_NR) | 829 | BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR); |
839 | BUG(); | ||
840 | 830 | ||
841 | dist_base = gic_data_dist_base(&gic_data[gic_nr]); | 831 | dist_base = gic_data_dist_base(&gic_data[gic_nr]); |
842 | if (!dist_base) | 832 | if (!dist_base) |
@@ -925,20 +915,15 @@ void __init gic_init_physaddr(struct device_node *node) | |||
925 | static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, | 915 | static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, |
926 | irq_hw_number_t hw) | 916 | irq_hw_number_t hw) |
927 | { | 917 | { |
928 | struct irq_chip *chip = &gic_chip; | 918 | struct gic_chip_data *gic = d->host_data; |
929 | |||
930 | if (static_key_true(&supports_deactivate)) { | ||
931 | if (d->host_data == (void *)&gic_data[0]) | ||
932 | chip = &gic_eoimode1_chip; | ||
933 | } | ||
934 | 919 | ||
935 | if (hw < 32) { | 920 | if (hw < 32) { |
936 | irq_set_percpu_devid(irq); | 921 | irq_set_percpu_devid(irq); |
937 | irq_domain_set_info(d, irq, hw, chip, d->host_data, | 922 | irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data, |
938 | handle_percpu_devid_irq, NULL, NULL); | 923 | handle_percpu_devid_irq, NULL, NULL); |
939 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | 924 | irq_set_status_flags(irq, IRQ_NOAUTOEN); |
940 | } else { | 925 | } else { |
941 | irq_domain_set_info(d, irq, hw, chip, d->host_data, | 926 | irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data, |
942 | handle_fasteoi_irq, NULL, NULL); | 927 | handle_fasteoi_irq, NULL, NULL); |
943 | irq_set_probe(irq); | 928 | irq_set_probe(irq); |
944 | } | 929 | } |
@@ -1040,11 +1025,20 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start, | |||
1040 | struct gic_chip_data *gic; | 1025 | struct gic_chip_data *gic; |
1041 | int gic_irqs, irq_base, i; | 1026 | int gic_irqs, irq_base, i; |
1042 | 1027 | ||
1043 | BUG_ON(gic_nr >= MAX_GIC_NR); | 1028 | BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR); |
1044 | 1029 | ||
1045 | gic_check_cpu_features(); | 1030 | gic_check_cpu_features(); |
1046 | 1031 | ||
1047 | gic = &gic_data[gic_nr]; | 1032 | gic = &gic_data[gic_nr]; |
1033 | |||
1034 | /* Initialize irq_chip */ | ||
1035 | if (static_key_true(&supports_deactivate) && gic_nr == 0) { | ||
1036 | gic->chip = gic_eoimode1_chip; | ||
1037 | } else { | ||
1038 | gic->chip = gic_chip; | ||
1039 | gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d", gic_nr); | ||
1040 | } | ||
1041 | |||
1048 | #ifdef CONFIG_GIC_NON_BANKED | 1042 | #ifdef CONFIG_GIC_NON_BANKED |
1049 | if (percpu_offset) { /* Frankein-GIC without banked registers... */ | 1043 | if (percpu_offset) { /* Frankein-GIC without banked registers... */ |
1050 | unsigned int cpu; | 1044 | unsigned int cpu; |
@@ -1196,7 +1190,7 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base) | |||
1196 | return true; | 1190 | return true; |
1197 | } | 1191 | } |
1198 | 1192 | ||
1199 | static int __init | 1193 | int __init |
1200 | gic_of_init(struct device_node *node, struct device_node *parent) | 1194 | gic_of_init(struct device_node *node, struct device_node *parent) |
1201 | { | 1195 | { |
1202 | void __iomem *cpu_base; | 1196 | void __iomem *cpu_base; |
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index bae69e5d693c..d0a29db73bc7 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h | |||
@@ -103,6 +103,16 @@ struct device_node; | |||
103 | void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); | 103 | void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); |
104 | int gic_cpu_if_down(unsigned int gic_nr); | 104 | int gic_cpu_if_down(unsigned int gic_nr); |
105 | 105 | ||
106 | /* | ||
107 | * Subdrivers that need some preparatory work can initialize their | ||
108 | * chips and call this to register their GICs. | ||
109 | */ | ||
110 | int gic_of_init(struct device_node *node, struct device_node *parent); | ||
111 | |||
112 | /* | ||
113 | * Legacy platforms not converted to DT yet must use this to init | ||
114 | * their GIC | ||
115 | */ | ||
106 | void gic_init(unsigned int nr, int start, | 116 | void gic_init(unsigned int nr, int start, |
107 | void __iomem *dist , void __iomem *cpu); | 117 | void __iomem *dist , void __iomem *cpu); |
108 | 118 | ||