aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt (renamed from Documentation/devicetree/bindings/arm/atmel-aic.txt)0
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/kernel/head.S18
-rw-r--r--arch/arm64/kernel/hyp-stub.S1
-rw-r--r--drivers/irqchip/Kconfig19
-rw-r--r--drivers/irqchip/Makefile5
-rw-r--r--drivers/irqchip/irq-atmel-aic-common.c254
-rw-r--r--drivers/irqchip/irq-atmel-aic-common.h39
-rw-r--r--drivers/irqchip/irq-atmel-aic.c262
-rw-r--r--drivers/irqchip/irq-atmel-aic5.c353
-rw-r--r--drivers/irqchip/irq-gic-common.c115
-rw-r--r--drivers/irqchip/irq-gic-common.h29
-rw-r--r--drivers/irqchip/irq-gic-v3.c692
-rw-r--r--drivers/irqchip/irq-gic.c59
-rw-r--r--include/linux/irq.h2
-rw-r--r--include/linux/irqchip/arm-gic-v3.h198
-rw-r--r--kernel/irq/generic-chip.c5
17 files changed, 1994 insertions, 58 deletions
diff --git a/Documentation/devicetree/bindings/arm/atmel-aic.txt b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
index 2742e9cfd6b1..2742e9cfd6b1 100644
--- a/Documentation/devicetree/bindings/arm/atmel-aic.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index a474de346be6..7fc6e2e458b7 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -10,6 +10,7 @@ config ARM64
10 select ARM_AMBA 10 select ARM_AMBA
11 select ARM_ARCH_TIMER 11 select ARM_ARCH_TIMER
12 select ARM_GIC 12 select ARM_GIC
13 select ARM_GIC_V3
13 select BUILDTIME_EXTABLE_SORT 14 select BUILDTIME_EXTABLE_SORT
14 select CLONE_BACKWARDS 15 select CLONE_BACKWARDS
15 select COMMON_CLK 16 select COMMON_CLK
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index a96d3a6a63f6..96623502519c 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -22,6 +22,7 @@
22 22
23#include <linux/linkage.h> 23#include <linux/linkage.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/irqchip/arm-gic-v3.h>
25 26
26#include <asm/assembler.h> 27#include <asm/assembler.h>
27#include <asm/ptrace.h> 28#include <asm/ptrace.h>
@@ -296,6 +297,23 @@ CPU_LE( bic x0, x0, #(3 << 24) ) // Clear the EE and E0E bits for EL1
296 msr cnthctl_el2, x0 297 msr cnthctl_el2, x0
297 msr cntvoff_el2, xzr // Clear virtual offset 298 msr cntvoff_el2, xzr // Clear virtual offset
298 299
300#ifdef CONFIG_ARM_GIC_V3
301 /* GICv3 system register access */
302 mrs x0, id_aa64pfr0_el1
303 ubfx x0, x0, #24, #4
304 cmp x0, #1
305 b.ne 3f
306
307 mrs x0, ICC_SRE_EL2
308 orr x0, x0, #ICC_SRE_EL2_SRE // Set ICC_SRE_EL2.SRE==1
309 orr x0, x0, #ICC_SRE_EL2_ENABLE // Set ICC_SRE_EL2.Enable==1
310 msr ICC_SRE_EL2, x0
311 isb // Make sure SRE is now set
312 msr ICH_HCR_EL2, xzr // Reset ICC_HCR_EL2 to defaults
313
3143:
315#endif
316
299 /* Populate ID registers. */ 317 /* Populate ID registers. */
300 mrs x0, midr_el1 318 mrs x0, midr_el1
301 mrs x1, mpidr_el1 319 mrs x1, mpidr_el1
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index 0959611d9ff1..a272f335c289 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -19,6 +19,7 @@
19 19
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/linkage.h> 21#include <linux/linkage.h>
22#include <linux/irqchip/arm-gic-v3.h>
22 23
23#include <asm/assembler.h> 24#include <asm/assembler.h>
24#include <asm/ptrace.h> 25#include <asm/ptrace.h>
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 131f18562d7d..4e230e7c76ee 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -10,6 +10,11 @@ config ARM_GIC
10config GIC_NON_BANKED 10config GIC_NON_BANKED
11 bool 11 bool
12 12
13config ARM_GIC_V3
14 bool
15 select IRQ_DOMAIN
16 select MULTI_IRQ_HANDLER
17
13config ARM_NVIC 18config ARM_NVIC
14 bool 19 bool
15 select IRQ_DOMAIN 20 select IRQ_DOMAIN
@@ -30,6 +35,20 @@ config ARM_VIC_NR
30 The maximum number of VICs available in the system, for 35 The maximum number of VICs available in the system, for
31 power management. 36 power management.
32 37
38config ATMEL_AIC_IRQ
39 bool
40 select GENERIC_IRQ_CHIP
41 select IRQ_DOMAIN
42 select MULTI_IRQ_HANDLER
43 select SPARSE_IRQ
44
45config ATMEL_AIC5_IRQ
46 bool
47 select GENERIC_IRQ_CHIP
48 select IRQ_DOMAIN
49 select MULTI_IRQ_HANDLER
50 select SPARSE_IRQ
51
33config BRCMSTB_L2_IRQ 52config BRCMSTB_L2_IRQ
34 bool 53 bool
35 depends on ARM 54 depends on ARM
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 7fba336c4daf..73052ba9ca62 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -16,9 +16,12 @@ obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o
16obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o 16obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
17obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o 17obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
18obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o 18obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
19obj-$(CONFIG_ARM_GIC) += irq-gic.o 19obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o
20obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
20obj-$(CONFIG_ARM_NVIC) += irq-nvic.o 21obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
21obj-$(CONFIG_ARM_VIC) += irq-vic.o 22obj-$(CONFIG_ARM_VIC) += irq-vic.o
23obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic-common.o irq-atmel-aic.o
24obj-$(CONFIG_ATMEL_AIC5_IRQ) += irq-atmel-aic-common.o irq-atmel-aic5.o
22obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o 25obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o
23obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o 26obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o
24obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o 27obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c
new file mode 100644
index 000000000000..6ae3cdee0681
--- /dev/null
+++ b/drivers/irqchip/irq-atmel-aic-common.c
@@ -0,0 +1,254 @@
1/*
2 * Atmel AT91 common AIC (Advanced Interrupt Controller) code shared by
3 * irq-atmel-aic and irq-atmel-aic5 drivers
4 *
5 * Copyright (C) 2004 SAN People
6 * Copyright (C) 2004 ATMEL
7 * Copyright (C) Rick Bronson
8 * Copyright (C) 2014 Free Electrons
9 *
10 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
11 *
12 * This file is licensed under the terms of the GNU General Public
13 * License version 2. This program is licensed "as is" without any
14 * warranty of any kind, whether express or implied.
15 */
16
17#include <linux/errno.h>
18#include <linux/io.h>
19#include <linux/irq.h>
20#include <linux/irqdomain.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23#include <linux/slab.h>
24
25#include "irq-atmel-aic-common.h"
26
27#define AT91_AIC_PRIOR GENMASK(2, 0)
28#define AT91_AIC_IRQ_MIN_PRIORITY 0
29#define AT91_AIC_IRQ_MAX_PRIORITY 7
30
31#define AT91_AIC_SRCTYPE GENMASK(7, 6)
32#define AT91_AIC_SRCTYPE_LOW (0 << 5)
33#define AT91_AIC_SRCTYPE_FALLING (1 << 5)
34#define AT91_AIC_SRCTYPE_HIGH (2 << 5)
35#define AT91_AIC_SRCTYPE_RISING (3 << 5)
36
37struct aic_chip_data {
38 u32 ext_irqs;
39};
40
41static void aic_common_shutdown(struct irq_data *d)
42{
43 struct irq_chip_type *ct = irq_data_get_chip_type(d);
44
45 ct->chip.irq_mask(d);
46}
47
48int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val)
49{
50 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
51 struct aic_chip_data *aic = gc->private;
52 unsigned aic_type;
53
54 switch (type) {
55 case IRQ_TYPE_LEVEL_HIGH:
56 aic_type = AT91_AIC_SRCTYPE_HIGH;
57 break;
58 case IRQ_TYPE_EDGE_RISING:
59 aic_type = AT91_AIC_SRCTYPE_RISING;
60 break;
61 case IRQ_TYPE_LEVEL_LOW:
62 if (!(d->mask & aic->ext_irqs))
63 return -EINVAL;
64
65 aic_type = AT91_AIC_SRCTYPE_LOW;
66 break;
67 case IRQ_TYPE_EDGE_FALLING:
68 if (!(d->mask & aic->ext_irqs))
69 return -EINVAL;
70
71 aic_type = AT91_AIC_SRCTYPE_FALLING;
72 break;
73 default:
74 return -EINVAL;
75 }
76
77 *val &= AT91_AIC_SRCTYPE;
78 *val |= aic_type;
79
80 return 0;
81}
82
83int aic_common_set_priority(int priority, unsigned *val)
84{
85 if (priority < AT91_AIC_IRQ_MIN_PRIORITY ||
86 priority > AT91_AIC_IRQ_MAX_PRIORITY)
87 return -EINVAL;
88
89 *val &= AT91_AIC_PRIOR;
90 *val |= priority;
91
92 return 0;
93}
94
95int aic_common_irq_domain_xlate(struct irq_domain *d,
96 struct device_node *ctrlr,
97 const u32 *intspec,
98 unsigned int intsize,
99 irq_hw_number_t *out_hwirq,
100 unsigned int *out_type)
101{
102 if (WARN_ON(intsize < 3))
103 return -EINVAL;
104
105 if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY) ||
106 (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
107 return -EINVAL;
108
109 *out_hwirq = intspec[0];
110 *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
111
112 return 0;
113}
114
115static void __init aic_common_ext_irq_of_init(struct irq_domain *domain)
116{
117 struct device_node *node = domain->of_node;
118 struct irq_chip_generic *gc;
119 struct aic_chip_data *aic;
120 struct property *prop;
121 const __be32 *p;
122 u32 hwirq;
123
124 gc = irq_get_domain_generic_chip(domain, 0);
125
126 aic = gc->private;
127 aic->ext_irqs |= 1;
128
129 of_property_for_each_u32(node, "atmel,external-irqs", prop, p, hwirq) {
130 gc = irq_get_domain_generic_chip(domain, hwirq);
131 if (!gc) {
132 pr_warn("AIC: external irq %d >= %d skip it\n",
133 hwirq, domain->revmap_size);
134 continue;
135 }
136
137 aic = gc->private;
138 aic->ext_irqs |= (1 << (hwirq % 32));
139 }
140}
141
142#define AT91_RTC_IDR 0x24
143#define AT91_RTC_IMR 0x28
144#define AT91_RTC_IRQ_MASK 0x1f
145
146void __init aic_common_rtc_irq_fixup(struct device_node *root)
147{
148 struct device_node *np;
149 void __iomem *regs;
150
151 np = of_find_compatible_node(root, NULL, "atmel,at91rm9200-rtc");
152 if (!np)
153 np = of_find_compatible_node(root, NULL,
154 "atmel,at91sam9x5-rtc");
155
156 if (!np)
157 return;
158
159 regs = of_iomap(np, 0);
160 of_node_put(np);
161
162 if (!regs)
163 return;
164
165 writel(AT91_RTC_IRQ_MASK, regs + AT91_RTC_IDR);
166
167 iounmap(regs);
168}
169
170void __init aic_common_irq_fixup(const struct of_device_id *matches)
171{
172 struct device_node *root = of_find_node_by_path("/");
173 const struct of_device_id *match;
174
175 if (!root)
176 return;
177
178 match = of_match_node(matches, root);
179 of_node_put(root);
180
181 if (match) {
182 void (*fixup)(struct device_node *) = match->data;
183 fixup(root);
184 }
185
186 of_node_put(root);
187}
188
189struct irq_domain *__init aic_common_of_init(struct device_node *node,
190 const struct irq_domain_ops *ops,
191 const char *name, int nirqs)
192{
193 struct irq_chip_generic *gc;
194 struct irq_domain *domain;
195 struct aic_chip_data *aic;
196 void __iomem *reg_base;
197 int nchips;
198 int ret;
199 int i;
200
201 nchips = DIV_ROUND_UP(nirqs, 32);
202
203 reg_base = of_iomap(node, 0);
204 if (!reg_base)
205 return ERR_PTR(-ENOMEM);
206
207 aic = kcalloc(nchips, sizeof(*aic), GFP_KERNEL);
208 if (!aic) {
209 ret = -ENOMEM;
210 goto err_iounmap;
211 }
212
213 domain = irq_domain_add_linear(node, nchips * 32, ops, aic);
214 if (!domain) {
215 ret = -ENOMEM;
216 goto err_free_aic;
217 }
218
219 ret = irq_alloc_domain_generic_chips(domain, 32, 1, name,
220 handle_level_irq, 0, 0,
221 IRQCHIP_SKIP_SET_WAKE);
222 if (ret)
223 goto err_domain_remove;
224
225 for (i = 0; i < nchips; i++) {
226 gc = irq_get_domain_generic_chip(domain, i * 32);
227
228 gc->reg_base = reg_base;
229
230 gc->unused = 0;
231 gc->wake_enabled = ~0;
232 gc->chip_types[0].type = IRQ_TYPE_SENSE_MASK;
233 gc->chip_types[0].handler = handle_fasteoi_irq;
234 gc->chip_types[0].chip.irq_eoi = irq_gc_eoi;
235 gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
236 gc->chip_types[0].chip.irq_shutdown = aic_common_shutdown;
237 gc->private = &aic[i];
238 }
239
240 aic_common_ext_irq_of_init(domain);
241
242 return domain;
243
244err_domain_remove:
245 irq_domain_remove(domain);
246
247err_free_aic:
248 kfree(aic);
249
250err_iounmap:
251 iounmap(reg_base);
252
253 return ERR_PTR(ret);
254}
diff --git a/drivers/irqchip/irq-atmel-aic-common.h b/drivers/irqchip/irq-atmel-aic-common.h
new file mode 100644
index 000000000000..90aa00e918d6
--- /dev/null
+++ b/drivers/irqchip/irq-atmel-aic-common.h
@@ -0,0 +1,39 @@
1/*
2 * Atmel AT91 common AIC (Advanced Interrupt Controller) header file
3 *
4 * Copyright (C) 2004 SAN People
5 * Copyright (C) 2004 ATMEL
6 * Copyright (C) Rick Bronson
7 * Copyright (C) 2014 Free Electrons
8 *
9 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
10 *
11 * This file is licensed under the terms of the GNU General Public
12 * License version 2. This program is licensed "as is" without any
13 * warranty of any kind, whether express or implied.
14 */
15
16#ifndef __IRQ_ATMEL_AIC_COMMON_H
17#define __IRQ_ATMEL_AIC_COMMON_H
18
19
20int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val);
21
22int aic_common_set_priority(int priority, unsigned *val);
23
24int aic_common_irq_domain_xlate(struct irq_domain *d,
25 struct device_node *ctrlr,
26 const u32 *intspec,
27 unsigned int intsize,
28 irq_hw_number_t *out_hwirq,
29 unsigned int *out_type);
30
31struct irq_domain *__init aic_common_of_init(struct device_node *node,
32 const struct irq_domain_ops *ops,
33 const char *name, int nirqs);
34
35void __init aic_common_rtc_irq_fixup(struct device_node *root);
36
37void __init aic_common_irq_fixup(const struct of_device_id *matches);
38
39#endif /* __IRQ_ATMEL_AIC_COMMON_H */
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
new file mode 100644
index 000000000000..a82869e9fb26
--- /dev/null
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -0,0 +1,262 @@
1/*
2 * Atmel AT91 AIC (Advanced Interrupt Controller) driver
3 *
4 * Copyright (C) 2004 SAN People
5 * Copyright (C) 2004 ATMEL
6 * Copyright (C) Rick Bronson
7 * Copyright (C) 2014 Free Electrons
8 *
9 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
10 *
11 * This file is licensed under the terms of the GNU General Public
12 * License version 2. This program is licensed "as is" without any
13 * warranty of any kind, whether express or implied.
14 */
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <linux/mm.h>
19#include <linux/bitmap.h>
20#include <linux/types.h>
21#include <linux/irq.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/of_irq.h>
25#include <linux/irqdomain.h>
26#include <linux/err.h>
27#include <linux/slab.h>
28#include <linux/io.h>
29
30#include <asm/exception.h>
31#include <asm/mach/irq.h>
32
33#include "irq-atmel-aic-common.h"
34#include "irqchip.h"
35
36/* Number of irq lines managed by AIC */
37#define NR_AIC_IRQS 32
38
39#define AT91_AIC_SMR(n) ((n) * 4)
40
41#define AT91_AIC_SVR(n) (0x80 + ((n) * 4))
42#define AT91_AIC_IVR 0x100
43#define AT91_AIC_FVR 0x104
44#define AT91_AIC_ISR 0x108
45
46#define AT91_AIC_IPR 0x10c
47#define AT91_AIC_IMR 0x110
48#define AT91_AIC_CISR 0x114
49
50#define AT91_AIC_IECR 0x120
51#define AT91_AIC_IDCR 0x124
52#define AT91_AIC_ICCR 0x128
53#define AT91_AIC_ISCR 0x12c
54#define AT91_AIC_EOICR 0x130
55#define AT91_AIC_SPU 0x134
56#define AT91_AIC_DCR 0x138
57
58static struct irq_domain *aic_domain;
59
60static asmlinkage void __exception_irq_entry
61aic_handle(struct pt_regs *regs)
62{
63 struct irq_domain_chip_generic *dgc = aic_domain->gc;
64 struct irq_chip_generic *gc = dgc->gc[0];
65 u32 irqnr;
66 u32 irqstat;
67
68 irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR);
69 irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR);
70
71 irqnr = irq_find_mapping(aic_domain, irqnr);
72
73 if (!irqstat)
74 irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
75 else
76 handle_IRQ(irqnr, regs);
77}
78
79static int aic_retrigger(struct irq_data *d)
80{
81 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
82
83 /* Enable interrupt on AIC5 */
84 irq_gc_lock(gc);
85 irq_reg_writel(d->mask, gc->reg_base + AT91_AIC_ISCR);
86 irq_gc_unlock(gc);
87
88 return 0;
89}
90
91static int aic_set_type(struct irq_data *d, unsigned type)
92{
93 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
94 unsigned int smr;
95 int ret;
96
97 smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(d->hwirq));
98 ret = aic_common_set_type(d, type, &smr);
99 if (ret)
100 return ret;
101
102 irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(d->hwirq));
103
104 return 0;
105}
106
107#ifdef CONFIG_PM
108static void aic_suspend(struct irq_data *d)
109{
110 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
111
112 irq_gc_lock(gc);
113 irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IDCR);
114 irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IECR);
115 irq_gc_unlock(gc);
116}
117
118static void aic_resume(struct irq_data *d)
119{
120 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
121
122 irq_gc_lock(gc);
123 irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IDCR);
124 irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IECR);
125 irq_gc_unlock(gc);
126}
127
128static void aic_pm_shutdown(struct irq_data *d)
129{
130 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
131
132 irq_gc_lock(gc);
133 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR);
134 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR);
135 irq_gc_unlock(gc);
136}
137#else
138#define aic_suspend NULL
139#define aic_resume NULL
140#define aic_pm_shutdown NULL
141#endif /* CONFIG_PM */
142
143static void __init aic_hw_init(struct irq_domain *domain)
144{
145 struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
146 int i;
147
148 /*
149 * Perform 8 End Of Interrupt Command to make sure AIC
150 * will not Lock out nIRQ
151 */
152 for (i = 0; i < 8; i++)
153 irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
154
155 /*
156 * Spurious Interrupt ID in Spurious Vector Register.
157 * When there is no current interrupt, the IRQ Vector Register
158 * reads the value stored in AIC_SPU
159 */
160 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_SPU);
161
162 /* No debugging in AIC: Debug (Protect) Control Register */
163 irq_reg_writel(0, gc->reg_base + AT91_AIC_DCR);
164
165 /* Disable and clear all interrupts initially */
166 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR);
167 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR);
168
169 for (i = 0; i < 32; i++)
170 irq_reg_writel(i, gc->reg_base + AT91_AIC_SVR(i));
171}
172
173static int aic_irq_domain_xlate(struct irq_domain *d,
174 struct device_node *ctrlr,
175 const u32 *intspec, unsigned int intsize,
176 irq_hw_number_t *out_hwirq,
177 unsigned int *out_type)
178{
179 struct irq_domain_chip_generic *dgc = d->gc;
180 struct irq_chip_generic *gc;
181 unsigned smr;
182 int idx;
183 int ret;
184
185 if (!dgc)
186 return -EINVAL;
187
188 ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
189 out_hwirq, out_type);
190 if (ret)
191 return ret;
192
193 idx = intspec[0] / dgc->irqs_per_chip;
194 if (idx >= dgc->num_chips)
195 return -EINVAL;
196
197 gc = dgc->gc[idx];
198
199 irq_gc_lock(gc);
200 smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(*out_hwirq));
201 ret = aic_common_set_priority(intspec[2], &smr);
202 if (!ret)
203 irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(*out_hwirq));
204 irq_gc_unlock(gc);
205
206 return ret;
207}
208
209static const struct irq_domain_ops aic_irq_ops = {
210 .map = irq_map_generic_chip,
211 .xlate = aic_irq_domain_xlate,
212};
213
214static void __init at91sam9_aic_irq_fixup(struct device_node *root)
215{
216 aic_common_rtc_irq_fixup(root);
217}
218
219static const struct of_device_id __initdata aic_irq_fixups[] = {
220 { .compatible = "atmel,at91sam9g45", .data = at91sam9_aic_irq_fixup },
221 { .compatible = "atmel,at91sam9n12", .data = at91sam9_aic_irq_fixup },
222 { .compatible = "atmel,at91sam9rl", .data = at91sam9_aic_irq_fixup },
223 { .compatible = "atmel,at91sam9x5", .data = at91sam9_aic_irq_fixup },
224 { /* sentinel */ },
225};
226
227static int __init aic_of_init(struct device_node *node,
228 struct device_node *parent)
229{
230 struct irq_chip_generic *gc;
231 struct irq_domain *domain;
232
233 if (aic_domain)
234 return -EEXIST;
235
236 domain = aic_common_of_init(node, &aic_irq_ops, "atmel-aic",
237 NR_AIC_IRQS);
238 if (IS_ERR(domain))
239 return PTR_ERR(domain);
240
241 aic_common_irq_fixup(aic_irq_fixups);
242
243 aic_domain = domain;
244 gc = irq_get_domain_generic_chip(domain, 0);
245
246 gc->chip_types[0].regs.eoi = AT91_AIC_EOICR;
247 gc->chip_types[0].regs.enable = AT91_AIC_IECR;
248 gc->chip_types[0].regs.disable = AT91_AIC_IDCR;
249 gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
250 gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
251 gc->chip_types[0].chip.irq_retrigger = aic_retrigger;
252 gc->chip_types[0].chip.irq_set_type = aic_set_type;
253 gc->chip_types[0].chip.irq_suspend = aic_suspend;
254 gc->chip_types[0].chip.irq_resume = aic_resume;
255 gc->chip_types[0].chip.irq_pm_shutdown = aic_pm_shutdown;
256
257 aic_hw_init(domain);
258 set_handle_irq(aic_handle);
259
260 return 0;
261}
262IRQCHIP_DECLARE(at91rm9200_aic, "atmel,at91rm9200-aic", aic_of_init);
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
new file mode 100644
index 000000000000..edb227081524
--- /dev/null
+++ b/drivers/irqchip/irq-atmel-aic5.c
@@ -0,0 +1,353 @@
1/*
2 * Atmel AT91 AIC5 (Advanced Interrupt Controller) driver
3 *
4 * Copyright (C) 2004 SAN People
5 * Copyright (C) 2004 ATMEL
6 * Copyright (C) Rick Bronson
7 * Copyright (C) 2014 Free Electrons
8 *
9 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
10 *
11 * This file is licensed under the terms of the GNU General Public
12 * License version 2. This program is licensed "as is" without any
13 * warranty of any kind, whether express or implied.
14 */
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <linux/mm.h>
19#include <linux/bitmap.h>
20#include <linux/types.h>
21#include <linux/irq.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/of_irq.h>
25#include <linux/irqdomain.h>
26#include <linux/err.h>
27#include <linux/slab.h>
28#include <linux/io.h>
29
30#include <asm/exception.h>
31#include <asm/mach/irq.h>
32
33#include "irq-atmel-aic-common.h"
34#include "irqchip.h"
35
36/* Number of irq lines managed by AIC */
37#define NR_AIC5_IRQS 128
38
39#define AT91_AIC5_SSR 0x0
40#define AT91_AIC5_INTSEL_MSK (0x7f << 0)
41
42#define AT91_AIC5_SMR 0x4
43
44#define AT91_AIC5_SVR 0x8
45#define AT91_AIC5_IVR 0x10
46#define AT91_AIC5_FVR 0x14
47#define AT91_AIC5_ISR 0x18
48
49#define AT91_AIC5_IPR0 0x20
50#define AT91_AIC5_IPR1 0x24
51#define AT91_AIC5_IPR2 0x28
52#define AT91_AIC5_IPR3 0x2c
53#define AT91_AIC5_IMR 0x30
54#define AT91_AIC5_CISR 0x34
55
56#define AT91_AIC5_IECR 0x40
57#define AT91_AIC5_IDCR 0x44
58#define AT91_AIC5_ICCR 0x48
59#define AT91_AIC5_ISCR 0x4c
60#define AT91_AIC5_EOICR 0x38
61#define AT91_AIC5_SPU 0x3c
62#define AT91_AIC5_DCR 0x6c
63
64#define AT91_AIC5_FFER 0x50
65#define AT91_AIC5_FFDR 0x54
66#define AT91_AIC5_FFSR 0x58
67
68static struct irq_domain *aic5_domain;
69
70static asmlinkage void __exception_irq_entry
71aic5_handle(struct pt_regs *regs)
72{
73 struct irq_domain_chip_generic *dgc = aic5_domain->gc;
74 struct irq_chip_generic *gc = dgc->gc[0];
75 u32 irqnr;
76 u32 irqstat;
77
78 irqnr = irq_reg_readl(gc->reg_base + AT91_AIC5_IVR);
79 irqstat = irq_reg_readl(gc->reg_base + AT91_AIC5_ISR);
80
81 irqnr = irq_find_mapping(aic5_domain, irqnr);
82
83 if (!irqstat)
84 irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR);
85 else
86 handle_IRQ(irqnr, regs);
87}
88
89static void aic5_mask(struct irq_data *d)
90{
91 struct irq_domain *domain = d->domain;
92 struct irq_domain_chip_generic *dgc = domain->gc;
93 struct irq_chip_generic *gc = dgc->gc[0];
94
95 /* Disable interrupt on AIC5 */
96 irq_gc_lock(gc);
97 irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
98 irq_reg_writel(1, gc->reg_base + AT91_AIC5_IDCR);
99 gc->mask_cache &= ~d->mask;
100 irq_gc_unlock(gc);
101}
102
103static void aic5_unmask(struct irq_data *d)
104{
105 struct irq_domain *domain = d->domain;
106 struct irq_domain_chip_generic *dgc = domain->gc;
107 struct irq_chip_generic *gc = dgc->gc[0];
108
109 /* Enable interrupt on AIC5 */
110 irq_gc_lock(gc);
111 irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
112 irq_reg_writel(1, gc->reg_base + AT91_AIC5_IECR);
113 gc->mask_cache |= d->mask;
114 irq_gc_unlock(gc);
115}
116
117static int aic5_retrigger(struct irq_data *d)
118{
119 struct irq_domain *domain = d->domain;
120 struct irq_domain_chip_generic *dgc = domain->gc;
121 struct irq_chip_generic *gc = dgc->gc[0];
122
123 /* Enable interrupt on AIC5 */
124 irq_gc_lock(gc);
125 irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
126 irq_reg_writel(1, gc->reg_base + AT91_AIC5_ISCR);
127 irq_gc_unlock(gc);
128
129 return 0;
130}
131
132static int aic5_set_type(struct irq_data *d, unsigned type)
133{
134 struct irq_domain *domain = d->domain;
135 struct irq_domain_chip_generic *dgc = domain->gc;
136 struct irq_chip_generic *gc = dgc->gc[0];
137 unsigned int smr;
138 int ret;
139
140 irq_gc_lock(gc);
141 irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
142 smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR);
143 ret = aic_common_set_type(d, type, &smr);
144 if (!ret)
145 irq_reg_writel(smr, gc->reg_base + AT91_AIC5_SMR);
146 irq_gc_unlock(gc);
147
148 return ret;
149}
150
151#ifdef CONFIG_PM
152static void aic5_suspend(struct irq_data *d)
153{
154 struct irq_domain *domain = d->domain;
155 struct irq_domain_chip_generic *dgc = domain->gc;
156 struct irq_chip_generic *bgc = dgc->gc[0];
157 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
158 int i;
159 u32 mask;
160
161 irq_gc_lock(bgc);
162 for (i = 0; i < dgc->irqs_per_chip; i++) {
163 mask = 1 << i;
164 if ((mask & gc->mask_cache) == (mask & gc->wake_active))
165 continue;
166
167 irq_reg_writel(i + gc->irq_base,
168 bgc->reg_base + AT91_AIC5_SSR);
169 if (mask & gc->wake_active)
170 irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IECR);
171 else
172 irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
173 }
174 irq_gc_unlock(bgc);
175}
176
177static void aic5_resume(struct irq_data *d)
178{
179 struct irq_domain *domain = d->domain;
180 struct irq_domain_chip_generic *dgc = domain->gc;
181 struct irq_chip_generic *bgc = dgc->gc[0];
182 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
183 int i;
184 u32 mask;
185
186 irq_gc_lock(bgc);
187 for (i = 0; i < dgc->irqs_per_chip; i++) {
188 mask = 1 << i;
189 if ((mask & gc->mask_cache) == (mask & gc->wake_active))
190 continue;
191
192 irq_reg_writel(i + gc->irq_base,
193 bgc->reg_base + AT91_AIC5_SSR);
194 if (mask & gc->mask_cache)
195 irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IECR);
196 else
197 irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
198 }
199 irq_gc_unlock(bgc);
200}
201
202static void aic5_pm_shutdown(struct irq_data *d)
203{
204 struct irq_domain *domain = d->domain;
205 struct irq_domain_chip_generic *dgc = domain->gc;
206 struct irq_chip_generic *bgc = dgc->gc[0];
207 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
208 int i;
209
210 irq_gc_lock(bgc);
211 for (i = 0; i < dgc->irqs_per_chip; i++) {
212 irq_reg_writel(i + gc->irq_base,
213 bgc->reg_base + AT91_AIC5_SSR);
214 irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
215 irq_reg_writel(1, bgc->reg_base + AT91_AIC5_ICCR);
216 }
217 irq_gc_unlock(bgc);
218}
219#else
220#define aic5_suspend NULL
221#define aic5_resume NULL
222#define aic5_pm_shutdown NULL
223#endif /* CONFIG_PM */
224
225static void __init aic5_hw_init(struct irq_domain *domain)
226{
227 struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
228 int i;
229
230 /*
231 * Perform 8 End Of Interrupt Command to make sure AIC
232 * will not Lock out nIRQ
233 */
234 for (i = 0; i < 8; i++)
235 irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR);
236
237 /*
238 * Spurious Interrupt ID in Spurious Vector Register.
239 * When there is no current interrupt, the IRQ Vector Register
240 * reads the value stored in AIC_SPU
241 */
242 irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC5_SPU);
243
244 /* No debugging in AIC: Debug (Protect) Control Register */
245 irq_reg_writel(0, gc->reg_base + AT91_AIC5_DCR);
246
247 /* Disable and clear all interrupts initially */
248 for (i = 0; i < domain->revmap_size; i++) {
249 irq_reg_writel(i, gc->reg_base + AT91_AIC5_SSR);
250 irq_reg_writel(i, gc->reg_base + AT91_AIC5_SVR);
251 irq_reg_writel(1, gc->reg_base + AT91_AIC5_IDCR);
252 irq_reg_writel(1, gc->reg_base + AT91_AIC5_ICCR);
253 }
254}
255
256static int aic5_irq_domain_xlate(struct irq_domain *d,
257 struct device_node *ctrlr,
258 const u32 *intspec, unsigned int intsize,
259 irq_hw_number_t *out_hwirq,
260 unsigned int *out_type)
261{
262 struct irq_domain_chip_generic *dgc = d->gc;
263 struct irq_chip_generic *gc;
264 unsigned smr;
265 int ret;
266
267 if (!dgc)
268 return -EINVAL;
269
270 ret = aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
271 out_hwirq, out_type);
272 if (ret)
273 return ret;
274
275 gc = dgc->gc[0];
276
277 irq_gc_lock(gc);
278 irq_reg_writel(*out_hwirq, gc->reg_base + AT91_AIC5_SSR);
279 smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR);
280 ret = aic_common_set_priority(intspec[2], &smr);
281 if (!ret)
282 irq_reg_writel(intspec[2] | smr, gc->reg_base + AT91_AIC5_SMR);
283 irq_gc_unlock(gc);
284
285 return ret;
286}
287
288static const struct irq_domain_ops aic5_irq_ops = {
289 .map = irq_map_generic_chip,
290 .xlate = aic5_irq_domain_xlate,
291};
292
293static void __init sama5d3_aic_irq_fixup(struct device_node *root)
294{
295 aic_common_rtc_irq_fixup(root);
296}
297
298static const struct of_device_id __initdata aic5_irq_fixups[] = {
299 { .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup },
300 { /* sentinel */ },
301};
302
303static int __init aic5_of_init(struct device_node *node,
304 struct device_node *parent,
305 int nirqs)
306{
307 struct irq_chip_generic *gc;
308 struct irq_domain *domain;
309 int nchips;
310 int i;
311
312 if (nirqs > NR_AIC5_IRQS)
313 return -EINVAL;
314
315 if (aic5_domain)
316 return -EEXIST;
317
318 domain = aic_common_of_init(node, &aic5_irq_ops, "atmel-aic5",
319 nirqs);
320 if (IS_ERR(domain))
321 return PTR_ERR(domain);
322
323 aic_common_irq_fixup(aic5_irq_fixups);
324
325 aic5_domain = domain;
326 nchips = aic5_domain->revmap_size / 32;
327 for (i = 0; i < nchips; i++) {
328 gc = irq_get_domain_generic_chip(domain, i * 32);
329
330 gc->chip_types[0].regs.eoi = AT91_AIC5_EOICR;
331 gc->chip_types[0].chip.irq_mask = aic5_mask;
332 gc->chip_types[0].chip.irq_unmask = aic5_unmask;
333 gc->chip_types[0].chip.irq_retrigger = aic5_retrigger;
334 gc->chip_types[0].chip.irq_set_type = aic5_set_type;
335 gc->chip_types[0].chip.irq_suspend = aic5_suspend;
336 gc->chip_types[0].chip.irq_resume = aic5_resume;
337 gc->chip_types[0].chip.irq_pm_shutdown = aic5_pm_shutdown;
338 }
339
340 aic5_hw_init(domain);
341 set_handle_irq(aic5_handle);
342
343 return 0;
344}
345
346#define NR_SAMA5D3_IRQS 50
347
348static int __init sama5d3_aic5_of_init(struct device_node *node,
349 struct device_node *parent)
350{
351 return aic5_of_init(node, parent, NR_SAMA5D3_IRQS);
352}
353IRQCHIP_DECLARE(sama5d3_aic5, "atmel,sama5d3-aic", sama5d3_aic5_of_init);
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
new file mode 100644
index 000000000000..60ac704d2090
--- /dev/null
+++ b/drivers/irqchip/irq-gic-common.c
@@ -0,0 +1,115 @@
1/*
2 * Copyright (C) 2002 ARM Limited, All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/interrupt.h>
18#include <linux/io.h>
19#include <linux/irq.h>
20#include <linux/irqchip/arm-gic.h>
21
22#include "irq-gic-common.h"
23
24void gic_configure_irq(unsigned int irq, unsigned int type,
25 void __iomem *base, void (*sync_access)(void))
26{
27 u32 enablemask = 1 << (irq % 32);
28 u32 enableoff = (irq / 32) * 4;
29 u32 confmask = 0x2 << ((irq % 16) * 2);
30 u32 confoff = (irq / 16) * 4;
31 bool enabled = false;
32 u32 val;
33
34 /*
35 * Read current configuration register, and insert the config
36 * for "irq", depending on "type".
37 */
38 val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
39 if (type == IRQ_TYPE_LEVEL_HIGH)
40 val &= ~confmask;
41 else if (type == IRQ_TYPE_EDGE_RISING)
42 val |= confmask;
43
44 /*
45 * As recommended by the spec, disable the interrupt before changing
46 * the configuration
47 */
48 if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
49 writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
50 if (sync_access)
51 sync_access();
52 enabled = true;
53 }
54
55 /*
56 * Write back the new configuration, and possibly re-enable
57 * the interrupt.
58 */
59 writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
60
61 if (enabled)
62 writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
63
64 if (sync_access)
65 sync_access();
66}
67
68void __init gic_dist_config(void __iomem *base, int gic_irqs,
69 void (*sync_access)(void))
70{
71 unsigned int i;
72
73 /*
74 * Set all global interrupts to be level triggered, active low.
75 */
76 for (i = 32; i < gic_irqs; i += 16)
77 writel_relaxed(0, base + GIC_DIST_CONFIG + i / 4);
78
79 /*
80 * Set priority on all global interrupts.
81 */
82 for (i = 32; i < gic_irqs; i += 4)
83 writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i);
84
85 /*
86 * Disable all interrupts. Leave the PPI and SGIs alone
87 * as they are enabled by redistributor registers.
88 */
89 for (i = 32; i < gic_irqs; i += 32)
90 writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i / 8);
91
92 if (sync_access)
93 sync_access();
94}
95
96void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
97{
98 int i;
99
100 /*
101 * Deal with the banked PPI and SGI interrupts - disable all
102 * PPI interrupts, ensure all SGI interrupts are enabled.
103 */
104 writel_relaxed(0xffff0000, base + GIC_DIST_ENABLE_CLEAR);
105 writel_relaxed(0x0000ffff, base + GIC_DIST_ENABLE_SET);
106
107 /*
108 * Set priority on PPI and SGI interrupts
109 */
110 for (i = 0; i < 32; i += 4)
111 writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
112
113 if (sync_access)
114 sync_access();
115}
diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
new file mode 100644
index 000000000000..b41f02481c3a
--- /dev/null
+++ b/drivers/irqchip/irq-gic-common.h
@@ -0,0 +1,29 @@
1/*
2 * Copyright (C) 2002 ARM Limited, All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef _IRQ_GIC_COMMON_H
18#define _IRQ_GIC_COMMON_H
19
20#include <linux/of.h>
21#include <linux/irqdomain.h>
22
23void gic_configure_irq(unsigned int irq, unsigned int type,
24 void __iomem *base, void (*sync_access)(void));
25void gic_dist_config(void __iomem *base, int gic_irqs,
26 void (*sync_access)(void));
27void gic_cpu_config(void __iomem *base, void (*sync_access)(void));
28
29#endif /* _IRQ_GIC_COMMON_H */
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
new file mode 100644
index 000000000000..81519bae0453
--- /dev/null
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -0,0 +1,692 @@
1/*
2 * Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
3 * Author: Marc Zyngier <marc.zyngier@arm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/cpu.h>
19#include <linux/delay.h>
20#include <linux/interrupt.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23#include <linux/of_irq.h>
24#include <linux/percpu.h>
25#include <linux/slab.h>
26
27#include <linux/irqchip/arm-gic-v3.h>
28
29#include <asm/cputype.h>
30#include <asm/exception.h>
31#include <asm/smp_plat.h>
32
33#include "irq-gic-common.h"
34#include "irqchip.h"
35
36struct gic_chip_data {
37 void __iomem *dist_base;
38 void __iomem **redist_base;
39 void __percpu __iomem **rdist;
40 struct irq_domain *domain;
41 u64 redist_stride;
42 u32 redist_regions;
43 unsigned int irq_nr;
44};
45
46static struct gic_chip_data gic_data __read_mostly;
47
48#define gic_data_rdist() (this_cpu_ptr(gic_data.rdist))
49#define gic_data_rdist_rd_base() (*gic_data_rdist())
50#define gic_data_rdist_sgi_base() (gic_data_rdist_rd_base() + SZ_64K)
51
52/* Our default, arbitrary priority value. Linux only uses one anyway. */
53#define DEFAULT_PMR_VALUE 0xf0
54
55static inline unsigned int gic_irq(struct irq_data *d)
56{
57 return d->hwirq;
58}
59
60static inline int gic_irq_in_rdist(struct irq_data *d)
61{
62 return gic_irq(d) < 32;
63}
64
65static inline void __iomem *gic_dist_base(struct irq_data *d)
66{
67 if (gic_irq_in_rdist(d)) /* SGI+PPI -> SGI_base for this CPU */
68 return gic_data_rdist_sgi_base();
69
70 if (d->hwirq <= 1023) /* SPI -> dist_base */
71 return gic_data.dist_base;
72
73 if (d->hwirq >= 8192)
74 BUG(); /* LPI Detected!!! */
75
76 return NULL;
77}
78
79static void gic_do_wait_for_rwp(void __iomem *base)
80{
81 u32 count = 1000000; /* 1s! */
82
83 while (readl_relaxed(base + GICD_CTLR) & GICD_CTLR_RWP) {
84 count--;
85 if (!count) {
86 pr_err_ratelimited("RWP timeout, gone fishing\n");
87 return;
88 }
89 cpu_relax();
90 udelay(1);
91 };
92}
93
94/* Wait for completion of a distributor change */
95static void gic_dist_wait_for_rwp(void)
96{
97 gic_do_wait_for_rwp(gic_data.dist_base);
98}
99
100/* Wait for completion of a redistributor change */
101static void gic_redist_wait_for_rwp(void)
102{
103 gic_do_wait_for_rwp(gic_data_rdist_rd_base());
104}
105
106/* Low level accessors */
107static u64 gic_read_iar(void)
108{
109 u64 irqstat;
110
111 asm volatile("mrs %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
112 return irqstat;
113}
114
115static void gic_write_pmr(u64 val)
116{
117 asm volatile("msr " __stringify(ICC_PMR_EL1) ", %0" : : "r" (val));
118}
119
120static void gic_write_ctlr(u64 val)
121{
122 asm volatile("msr " __stringify(ICC_CTLR_EL1) ", %0" : : "r" (val));
123 isb();
124}
125
126static void gic_write_grpen1(u64 val)
127{
128 asm volatile("msr " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" (val));
129 isb();
130}
131
132static void gic_write_sgi1r(u64 val)
133{
134 asm volatile("msr " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));
135}
136
137static void gic_enable_sre(void)
138{
139 u64 val;
140
141 asm volatile("mrs %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
142 val |= ICC_SRE_EL1_SRE;
143 asm volatile("msr " __stringify(ICC_SRE_EL1) ", %0" : : "r" (val));
144 isb();
145
146 /*
147 * Need to check that the SRE bit has actually been set. If
148 * not, it means that SRE is disabled at EL2. We're going to
149 * die painfully, and there is nothing we can do about it.
150 *
151 * Kindly inform the luser.
152 */
153 asm volatile("mrs %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
154 if (!(val & ICC_SRE_EL1_SRE))
155 pr_err("GIC: unable to set SRE (disabled at EL2), panic ahead\n");
156}
157
158static void gic_enable_redist(void)
159{
160 void __iomem *rbase;
161 u32 count = 1000000; /* 1s! */
162 u32 val;
163
164 rbase = gic_data_rdist_rd_base();
165
166 /* Wake up this CPU redistributor */
167 val = readl_relaxed(rbase + GICR_WAKER);
168 val &= ~GICR_WAKER_ProcessorSleep;
169 writel_relaxed(val, rbase + GICR_WAKER);
170
171 while (readl_relaxed(rbase + GICR_WAKER) & GICR_WAKER_ChildrenAsleep) {
172 count--;
173 if (!count) {
174 pr_err_ratelimited("redist didn't wake up...\n");
175 return;
176 }
177 cpu_relax();
178 udelay(1);
179 };
180}
181
182/*
183 * Routines to disable, enable, EOI and route interrupts
184 */
185static void gic_poke_irq(struct irq_data *d, u32 offset)
186{
187 u32 mask = 1 << (gic_irq(d) % 32);
188 void (*rwp_wait)(void);
189 void __iomem *base;
190
191 if (gic_irq_in_rdist(d)) {
192 base = gic_data_rdist_sgi_base();
193 rwp_wait = gic_redist_wait_for_rwp;
194 } else {
195 base = gic_data.dist_base;
196 rwp_wait = gic_dist_wait_for_rwp;
197 }
198
199 writel_relaxed(mask, base + offset + (gic_irq(d) / 32) * 4);
200 rwp_wait();
201}
202
203static int gic_peek_irq(struct irq_data *d, u32 offset)
204{
205 u32 mask = 1 << (gic_irq(d) % 32);
206 void __iomem *base;
207
208 if (gic_irq_in_rdist(d))
209 base = gic_data_rdist_sgi_base();
210 else
211 base = gic_data.dist_base;
212
213 return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
214}
215
216static void gic_mask_irq(struct irq_data *d)
217{
218 gic_poke_irq(d, GICD_ICENABLER);
219}
220
221static void gic_unmask_irq(struct irq_data *d)
222{
223 gic_poke_irq(d, GICD_ISENABLER);
224}
225
226static void gic_eoi_irq(struct irq_data *d)
227{
228 gic_write_eoir(gic_irq(d));
229}
230
231static int gic_set_type(struct irq_data *d, unsigned int type)
232{
233 unsigned int irq = gic_irq(d);
234 void (*rwp_wait)(void);
235 void __iomem *base;
236
237 /* Interrupt configuration for SGIs can't be changed */
238 if (irq < 16)
239 return -EINVAL;
240
241 if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
242 return -EINVAL;
243
244 if (gic_irq_in_rdist(d)) {
245 base = gic_data_rdist_sgi_base();
246 rwp_wait = gic_redist_wait_for_rwp;
247 } else {
248 base = gic_data.dist_base;
249 rwp_wait = gic_dist_wait_for_rwp;
250 }
251
252 gic_configure_irq(irq, type, base, rwp_wait);
253
254 return 0;
255}
256
257static u64 gic_mpidr_to_affinity(u64 mpidr)
258{
259 u64 aff;
260
261 aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
262 MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
263 MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
264 MPIDR_AFFINITY_LEVEL(mpidr, 0));
265
266 return aff;
267}
268
269static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
270{
271 u64 irqnr;
272
273 do {
274 irqnr = gic_read_iar();
275
276 if (likely(irqnr > 15 && irqnr < 1020)) {
277 u64 irq = irq_find_mapping(gic_data.domain, irqnr);
278 if (likely(irq)) {
279 handle_IRQ(irq, regs);
280 continue;
281 }
282
283 WARN_ONCE(true, "Unexpected SPI received!\n");
284 gic_write_eoir(irqnr);
285 }
286 if (irqnr < 16) {
287 gic_write_eoir(irqnr);
288#ifdef CONFIG_SMP
289 handle_IPI(irqnr, regs);
290#else
291 WARN_ONCE(true, "Unexpected SGI received!\n");
292#endif
293 continue;
294 }
295 } while (irqnr != ICC_IAR1_EL1_SPURIOUS);
296}
297
298static void __init gic_dist_init(void)
299{
300 unsigned int i;
301 u64 affinity;
302 void __iomem *base = gic_data.dist_base;
303
304 /* Disable the distributor */
305 writel_relaxed(0, base + GICD_CTLR);
306 gic_dist_wait_for_rwp();
307
308 gic_dist_config(base, gic_data.irq_nr, gic_dist_wait_for_rwp);
309
310 /* Enable distributor with ARE, Group1 */
311 writel_relaxed(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
312 base + GICD_CTLR);
313
314 /*
315 * Set all global interrupts to the boot CPU only. ARE must be
316 * enabled.
317 */
318 affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));
319 for (i = 32; i < gic_data.irq_nr; i++)
320 writeq_relaxed(affinity, base + GICD_IROUTER + i * 8);
321}
322
323static int gic_populate_rdist(void)
324{
325 u64 mpidr = cpu_logical_map(smp_processor_id());
326 u64 typer;
327 u32 aff;
328 int i;
329
330 /*
331 * Convert affinity to a 32bit value that can be matched to
332 * GICR_TYPER bits [63:32].
333 */
334 aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
335 MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
336 MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
337 MPIDR_AFFINITY_LEVEL(mpidr, 0));
338
339 for (i = 0; i < gic_data.redist_regions; i++) {
340 void __iomem *ptr = gic_data.redist_base[i];
341 u32 reg;
342
343 reg = readl_relaxed(ptr + GICR_PIDR2) & GIC_PIDR2_ARCH_MASK;
344 if (reg != GIC_PIDR2_ARCH_GICv3 &&
345 reg != GIC_PIDR2_ARCH_GICv4) { /* We're in trouble... */
346 pr_warn("No redistributor present @%p\n", ptr);
347 break;
348 }
349
350 do {
351 typer = readq_relaxed(ptr + GICR_TYPER);
352 if ((typer >> 32) == aff) {
353 gic_data_rdist_rd_base() = ptr;
354 pr_info("CPU%d: found redistributor %llx @%p\n",
355 smp_processor_id(),
356 (unsigned long long)mpidr, ptr);
357 return 0;
358 }
359
360 if (gic_data.redist_stride) {
361 ptr += gic_data.redist_stride;
362 } else {
363 ptr += SZ_64K * 2; /* Skip RD_base + SGI_base */
364 if (typer & GICR_TYPER_VLPIS)
365 ptr += SZ_64K * 2; /* Skip VLPI_base + reserved page */
366 }
367 } while (!(typer & GICR_TYPER_LAST));
368 }
369
370 /* We couldn't even deal with ourselves... */
371 WARN(true, "CPU%d: mpidr %llx has no re-distributor!\n",
372 smp_processor_id(), (unsigned long long)mpidr);
373 return -ENODEV;
374}
375
376static void gic_cpu_init(void)
377{
378 void __iomem *rbase;
379
380 /* Register ourselves with the rest of the world */
381 if (gic_populate_rdist())
382 return;
383
384 gic_enable_redist();
385
386 rbase = gic_data_rdist_sgi_base();
387
388 gic_cpu_config(rbase, gic_redist_wait_for_rwp);
389
390 /* Enable system registers */
391 gic_enable_sre();
392
393 /* Set priority mask register */
394 gic_write_pmr(DEFAULT_PMR_VALUE);
395
396 /* EOI deactivates interrupt too (mode 0) */
397 gic_write_ctlr(ICC_CTLR_EL1_EOImode_drop_dir);
398
399 /* ... and let's hit the road... */
400 gic_write_grpen1(1);
401}
402
403#ifdef CONFIG_SMP
404static int gic_secondary_init(struct notifier_block *nfb,
405 unsigned long action, void *hcpu)
406{
407 if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
408 gic_cpu_init();
409 return NOTIFY_OK;
410}
411
412/*
413 * Notifier for enabling the GIC CPU interface. Set an arbitrarily high
414 * priority because the GIC needs to be up before the ARM generic timers.
415 */
416static struct notifier_block gic_cpu_notifier = {
417 .notifier_call = gic_secondary_init,
418 .priority = 100,
419};
420
421static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
422 u64 cluster_id)
423{
424 int cpu = *base_cpu;
425 u64 mpidr = cpu_logical_map(cpu);
426 u16 tlist = 0;
427
428 while (cpu < nr_cpu_ids) {
429 /*
430 * If we ever get a cluster of more than 16 CPUs, just
431 * scream and skip that CPU.
432 */
433 if (WARN_ON((mpidr & 0xff) >= 16))
434 goto out;
435
436 tlist |= 1 << (mpidr & 0xf);
437
438 cpu = cpumask_next(cpu, mask);
439 if (cpu == nr_cpu_ids)
440 goto out;
441
442 mpidr = cpu_logical_map(cpu);
443
444 if (cluster_id != (mpidr & ~0xffUL)) {
445 cpu--;
446 goto out;
447 }
448 }
449out:
450 *base_cpu = cpu;
451 return tlist;
452}
453
454static void gic_send_sgi(u64 cluster_id, u16 tlist, unsigned int irq)
455{
456 u64 val;
457
458 val = (MPIDR_AFFINITY_LEVEL(cluster_id, 3) << 48 |
459 MPIDR_AFFINITY_LEVEL(cluster_id, 2) << 32 |
460 irq << 24 |
461 MPIDR_AFFINITY_LEVEL(cluster_id, 1) << 16 |
462 tlist);
463
464 pr_debug("CPU%d: ICC_SGI1R_EL1 %llx\n", smp_processor_id(), val);
465 gic_write_sgi1r(val);
466}
467
468static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
469{
470 int cpu;
471
472 if (WARN_ON(irq >= 16))
473 return;
474
475 /*
476 * Ensure that stores to Normal memory are visible to the
477 * other CPUs before issuing the IPI.
478 */
479 smp_wmb();
480
481 for_each_cpu_mask(cpu, *mask) {
482 u64 cluster_id = cpu_logical_map(cpu) & ~0xffUL;
483 u16 tlist;
484
485 tlist = gic_compute_target_list(&cpu, mask, cluster_id);
486 gic_send_sgi(cluster_id, tlist, irq);
487 }
488
489 /* Force the above writes to ICC_SGI1R_EL1 to be executed */
490 isb();
491}
492
493static void gic_smp_init(void)
494{
495 set_smp_cross_call(gic_raise_softirq);
496 register_cpu_notifier(&gic_cpu_notifier);
497}
498
499static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
500 bool force)
501{
502 unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
503 void __iomem *reg;
504 int enabled;
505 u64 val;
506
507 if (gic_irq_in_rdist(d))
508 return -EINVAL;
509
510 /* If interrupt was enabled, disable it first */
511 enabled = gic_peek_irq(d, GICD_ISENABLER);
512 if (enabled)
513 gic_mask_irq(d);
514
515 reg = gic_dist_base(d) + GICD_IROUTER + (gic_irq(d) * 8);
516 val = gic_mpidr_to_affinity(cpu_logical_map(cpu));
517
518 writeq_relaxed(val, reg);
519
520 /*
521 * If the interrupt was enabled, enabled it again. Otherwise,
522 * just wait for the distributor to have digested our changes.
523 */
524 if (enabled)
525 gic_unmask_irq(d);
526 else
527 gic_dist_wait_for_rwp();
528
529 return IRQ_SET_MASK_OK;
530}
531#else
532#define gic_set_affinity NULL
533#define gic_smp_init() do { } while(0)
534#endif
535
536static struct irq_chip gic_chip = {
537 .name = "GICv3",
538 .irq_mask = gic_mask_irq,
539 .irq_unmask = gic_unmask_irq,
540 .irq_eoi = gic_eoi_irq,
541 .irq_set_type = gic_set_type,
542 .irq_set_affinity = gic_set_affinity,
543};
544
545static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
546 irq_hw_number_t hw)
547{
548 /* SGIs are private to the core kernel */
549 if (hw < 16)
550 return -EPERM;
551 /* PPIs */
552 if (hw < 32) {
553 irq_set_percpu_devid(irq);
554 irq_set_chip_and_handler(irq, &gic_chip,
555 handle_percpu_devid_irq);
556 set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
557 }
558 /* SPIs */
559 if (hw >= 32 && hw < gic_data.irq_nr) {
560 irq_set_chip_and_handler(irq, &gic_chip,
561 handle_fasteoi_irq);
562 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
563 }
564 irq_set_chip_data(irq, d->host_data);
565 return 0;
566}
567
568static int gic_irq_domain_xlate(struct irq_domain *d,
569 struct device_node *controller,
570 const u32 *intspec, unsigned int intsize,
571 unsigned long *out_hwirq, unsigned int *out_type)
572{
573 if (d->of_node != controller)
574 return -EINVAL;
575 if (intsize < 3)
576 return -EINVAL;
577
578 switch(intspec[0]) {
579 case 0: /* SPI */
580 *out_hwirq = intspec[1] + 32;
581 break;
582 case 1: /* PPI */
583 *out_hwirq = intspec[1] + 16;
584 break;
585 default:
586 return -EINVAL;
587 }
588
589 *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
590 return 0;
591}
592
593static const struct irq_domain_ops gic_irq_domain_ops = {
594 .map = gic_irq_domain_map,
595 .xlate = gic_irq_domain_xlate,
596};
597
598static int __init gic_of_init(struct device_node *node, struct device_node *parent)
599{
600 void __iomem *dist_base;
601 void __iomem **redist_base;
602 u64 redist_stride;
603 u32 redist_regions;
604 u32 reg;
605 int gic_irqs;
606 int err;
607 int i;
608
609 dist_base = of_iomap(node, 0);
610 if (!dist_base) {
611 pr_err("%s: unable to map gic dist registers\n",
612 node->full_name);
613 return -ENXIO;
614 }
615
616 reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
617 if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
618 pr_err("%s: no distributor detected, giving up\n",
619 node->full_name);
620 err = -ENODEV;
621 goto out_unmap_dist;
622 }
623
624 if (of_property_read_u32(node, "#redistributor-regions", &redist_regions))
625 redist_regions = 1;
626
627 redist_base = kzalloc(sizeof(*redist_base) * redist_regions, GFP_KERNEL);
628 if (!redist_base) {
629 err = -ENOMEM;
630 goto out_unmap_dist;
631 }
632
633 for (i = 0; i < redist_regions; i++) {
634 redist_base[i] = of_iomap(node, 1 + i);
635 if (!redist_base[i]) {
636 pr_err("%s: couldn't map region %d\n",
637 node->full_name, i);
638 err = -ENODEV;
639 goto out_unmap_rdist;
640 }
641 }
642
643 if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
644 redist_stride = 0;
645
646 gic_data.dist_base = dist_base;
647 gic_data.redist_base = redist_base;
648 gic_data.redist_regions = redist_regions;
649 gic_data.redist_stride = redist_stride;
650
651 /*
652 * Find out how many interrupts are supported.
653 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
654 */
655 gic_irqs = readl_relaxed(gic_data.dist_base + GICD_TYPER) & 0x1f;
656 gic_irqs = (gic_irqs + 1) * 32;
657 if (gic_irqs > 1020)
658 gic_irqs = 1020;
659 gic_data.irq_nr = gic_irqs;
660
661 gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
662 &gic_data);
663 gic_data.rdist = alloc_percpu(typeof(*gic_data.rdist));
664
665 if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdist)) {
666 err = -ENOMEM;
667 goto out_free;
668 }
669
670 set_handle_irq(gic_handle_irq);
671
672 gic_smp_init();
673 gic_dist_init();
674 gic_cpu_init();
675
676 return 0;
677
678out_free:
679 if (gic_data.domain)
680 irq_domain_remove(gic_data.domain);
681 free_percpu(gic_data.rdist);
682out_unmap_rdist:
683 for (i = 0; i < redist_regions; i++)
684 if (redist_base[i])
685 iounmap(redist_base[i]);
686 kfree(redist_base);
687out_unmap_dist:
688 iounmap(dist_base);
689 return err;
690}
691
692IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 7e11c9d6ae8c..508b81536b8a 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -46,6 +46,7 @@
46#include <asm/exception.h> 46#include <asm/exception.h>
47#include <asm/smp_plat.h> 47#include <asm/smp_plat.h>
48 48
49#include "irq-gic-common.h"
49#include "irqchip.h" 50#include "irqchip.h"
50 51
51union gic_base { 52union gic_base {
@@ -188,12 +189,6 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
188{ 189{
189 void __iomem *base = gic_dist_base(d); 190 void __iomem *base = gic_dist_base(d);
190 unsigned int gicirq = gic_irq(d); 191 unsigned int gicirq = gic_irq(d);
191 u32 enablemask = 1 << (gicirq % 32);
192 u32 enableoff = (gicirq / 32) * 4;
193 u32 confmask = 0x2 << ((gicirq % 16) * 2);
194 u32 confoff = (gicirq / 16) * 4;
195 bool enabled = false;
196 u32 val;
197 192
198 /* Interrupt configuration for SGIs can't be changed */ 193 /* Interrupt configuration for SGIs can't be changed */
199 if (gicirq < 16) 194 if (gicirq < 16)
@@ -207,25 +202,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
207 if (gic_arch_extn.irq_set_type) 202 if (gic_arch_extn.irq_set_type)
208 gic_arch_extn.irq_set_type(d, type); 203 gic_arch_extn.irq_set_type(d, type);
209 204
210 val = readl_relaxed(base + GIC_DIST_CONFIG + confoff); 205 gic_configure_irq(gicirq, type, base, NULL);
211 if (type == IRQ_TYPE_LEVEL_HIGH)
212 val &= ~confmask;
213 else if (type == IRQ_TYPE_EDGE_RISING)
214 val |= confmask;
215
216 /*
217 * As recommended by the spec, disable the interrupt before changing
218 * the configuration
219 */
220 if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
221 writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
222 enabled = true;
223 }
224
225 writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
226
227 if (enabled)
228 writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
229 206
230 raw_spin_unlock(&irq_controller_lock); 207 raw_spin_unlock(&irq_controller_lock);
231 208
@@ -387,12 +364,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
387 writel_relaxed(0, base + GIC_DIST_CTRL); 364 writel_relaxed(0, base + GIC_DIST_CTRL);
388 365
389 /* 366 /*
390 * Set all global interrupts to be level triggered, active low.
391 */
392 for (i = 32; i < gic_irqs; i += 16)
393 writel_relaxed(0, base + GIC_DIST_CONFIG + i * 4 / 16);
394
395 /*
396 * Set all global interrupts to this CPU only. 367 * Set all global interrupts to this CPU only.
397 */ 368 */
398 cpumask = gic_get_cpumask(gic); 369 cpumask = gic_get_cpumask(gic);
@@ -401,18 +372,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
401 for (i = 32; i < gic_irqs; i += 4) 372 for (i = 32; i < gic_irqs; i += 4)
402 writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4); 373 writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
403 374
404 /* 375 gic_dist_config(base, gic_irqs, NULL);
405 * Set priority on all global interrupts.
406 */
407 for (i = 32; i < gic_irqs; i += 4)
408 writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
409
410 /*
411 * Disable all interrupts. Leave the PPI and SGIs alone
412 * as these enables are banked registers.
413 */
414 for (i = 32; i < gic_irqs; i += 32)
415 writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
416 376
417 writel_relaxed(1, base + GIC_DIST_CTRL); 377 writel_relaxed(1, base + GIC_DIST_CTRL);
418} 378}
@@ -439,18 +399,7 @@ static void gic_cpu_init(struct gic_chip_data *gic)
439 if (i != cpu) 399 if (i != cpu)
440 gic_cpu_map[i] &= ~cpu_mask; 400 gic_cpu_map[i] &= ~cpu_mask;
441 401
442 /* 402 gic_cpu_config(dist_base, NULL);
443 * Deal with the banked PPI and SGI interrupts - disable all
444 * PPI interrupts, ensure all SGI interrupts are enabled.
445 */
446 writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
447 writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
448
449 /*
450 * Set priority on PPI and SGI interrupts
451 */
452 for (i = 0; i < 32; i += 4)
453 writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
454 403
455 writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); 404 writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
456 writel_relaxed(1, base + GIC_CPU_CTRL); 405 writel_relaxed(1, base + GIC_CPU_CTRL);
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 0d998d8b01d8..62af59242ddc 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -771,6 +771,8 @@ void irq_gc_eoi(struct irq_data *d);
771int irq_gc_set_wake(struct irq_data *d, unsigned int on); 771int irq_gc_set_wake(struct irq_data *d, unsigned int on);
772 772
773/* Setup functions for irq_chip_generic */ 773/* Setup functions for irq_chip_generic */
774int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
775 irq_hw_number_t hw_irq);
774struct irq_chip_generic * 776struct irq_chip_generic *
775irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base, 777irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base,
776 void __iomem *reg_base, irq_flow_handler_t handler); 778 void __iomem *reg_base, irq_flow_handler_t handler);
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
new file mode 100644
index 000000000000..30cb7556d43f
--- /dev/null
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -0,0 +1,198 @@
1/*
2 * Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
3 * Author: Marc Zyngier <marc.zyngier@arm.com>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18#ifndef __LINUX_IRQCHIP_ARM_GIC_V3_H
19#define __LINUX_IRQCHIP_ARM_GIC_V3_H
20
21/*
22 * Distributor registers. We assume we're running non-secure, with ARE
23 * being set. Secure-only and non-ARE registers are not described.
24 */
25#define GICD_CTLR 0x0000
26#define GICD_TYPER 0x0004
27#define GICD_IIDR 0x0008
28#define GICD_STATUSR 0x0010
29#define GICD_SETSPI_NSR 0x0040
30#define GICD_CLRSPI_NSR 0x0048
31#define GICD_SETSPI_SR 0x0050
32#define GICD_CLRSPI_SR 0x0058
33#define GICD_SEIR 0x0068
34#define GICD_ISENABLER 0x0100
35#define GICD_ICENABLER 0x0180
36#define GICD_ISPENDR 0x0200
37#define GICD_ICPENDR 0x0280
38#define GICD_ISACTIVER 0x0300
39#define GICD_ICACTIVER 0x0380
40#define GICD_IPRIORITYR 0x0400
41#define GICD_ICFGR 0x0C00
42#define GICD_IROUTER 0x6000
43#define GICD_PIDR2 0xFFE8
44
45#define GICD_CTLR_RWP (1U << 31)
46#define GICD_CTLR_ARE_NS (1U << 4)
47#define GICD_CTLR_ENABLE_G1A (1U << 1)
48#define GICD_CTLR_ENABLE_G1 (1U << 0)
49
50#define GICD_IROUTER_SPI_MODE_ONE (0U << 31)
51#define GICD_IROUTER_SPI_MODE_ANY (1U << 31)
52
53#define GIC_PIDR2_ARCH_MASK 0xf0
54#define GIC_PIDR2_ARCH_GICv3 0x30
55#define GIC_PIDR2_ARCH_GICv4 0x40
56
57/*
58 * Re-Distributor registers, offsets from RD_base
59 */
60#define GICR_CTLR GICD_CTLR
61#define GICR_IIDR 0x0004
62#define GICR_TYPER 0x0008
63#define GICR_STATUSR GICD_STATUSR
64#define GICR_WAKER 0x0014
65#define GICR_SETLPIR 0x0040
66#define GICR_CLRLPIR 0x0048
67#define GICR_SEIR GICD_SEIR
68#define GICR_PROPBASER 0x0070
69#define GICR_PENDBASER 0x0078
70#define GICR_INVLPIR 0x00A0
71#define GICR_INVALLR 0x00B0
72#define GICR_SYNCR 0x00C0
73#define GICR_MOVLPIR 0x0100
74#define GICR_MOVALLR 0x0110
75#define GICR_PIDR2 GICD_PIDR2
76
77#define GICR_WAKER_ProcessorSleep (1U << 1)
78#define GICR_WAKER_ChildrenAsleep (1U << 2)
79
80/*
81 * Re-Distributor registers, offsets from SGI_base
82 */
83#define GICR_ISENABLER0 GICD_ISENABLER
84#define GICR_ICENABLER0 GICD_ICENABLER
85#define GICR_ISPENDR0 GICD_ISPENDR
86#define GICR_ICPENDR0 GICD_ICPENDR
87#define GICR_ISACTIVER0 GICD_ISACTIVER
88#define GICR_ICACTIVER0 GICD_ICACTIVER
89#define GICR_IPRIORITYR0 GICD_IPRIORITYR
90#define GICR_ICFGR0 GICD_ICFGR
91
92#define GICR_TYPER_VLPIS (1U << 1)
93#define GICR_TYPER_LAST (1U << 4)
94
95/*
96 * CPU interface registers
97 */
98#define ICC_CTLR_EL1_EOImode_drop_dir (0U << 1)
99#define ICC_CTLR_EL1_EOImode_drop (1U << 1)
100#define ICC_SRE_EL1_SRE (1U << 0)
101
102/*
103 * Hypervisor interface registers (SRE only)
104 */
105#define ICH_LR_VIRTUAL_ID_MASK ((1UL << 32) - 1)
106
107#define ICH_LR_EOI (1UL << 41)
108#define ICH_LR_GROUP (1UL << 60)
109#define ICH_LR_STATE (3UL << 62)
110#define ICH_LR_PENDING_BIT (1UL << 62)
111#define ICH_LR_ACTIVE_BIT (1UL << 63)
112
113#define ICH_MISR_EOI (1 << 0)
114#define ICH_MISR_U (1 << 1)
115
116#define ICH_HCR_EN (1 << 0)
117#define ICH_HCR_UIE (1 << 1)
118
119#define ICH_VMCR_CTLR_SHIFT 0
120#define ICH_VMCR_CTLR_MASK (0x21f << ICH_VMCR_CTLR_SHIFT)
121#define ICH_VMCR_BPR1_SHIFT 18
122#define ICH_VMCR_BPR1_MASK (7 << ICH_VMCR_BPR1_SHIFT)
123#define ICH_VMCR_BPR0_SHIFT 21
124#define ICH_VMCR_BPR0_MASK (7 << ICH_VMCR_BPR0_SHIFT)
125#define ICH_VMCR_PMR_SHIFT 24
126#define ICH_VMCR_PMR_MASK (0xffUL << ICH_VMCR_PMR_SHIFT)
127
128#define ICC_EOIR1_EL1 S3_0_C12_C12_1
129#define ICC_IAR1_EL1 S3_0_C12_C12_0
130#define ICC_SGI1R_EL1 S3_0_C12_C11_5
131#define ICC_PMR_EL1 S3_0_C4_C6_0
132#define ICC_CTLR_EL1 S3_0_C12_C12_4
133#define ICC_SRE_EL1 S3_0_C12_C12_5
134#define ICC_GRPEN1_EL1 S3_0_C12_C12_7
135
136#define ICC_IAR1_EL1_SPURIOUS 0x3ff
137
138#define ICC_SRE_EL2 S3_4_C12_C9_5
139
140#define ICC_SRE_EL2_SRE (1 << 0)
141#define ICC_SRE_EL2_ENABLE (1 << 3)
142
143/*
144 * System register definitions
145 */
146#define ICH_VSEIR_EL2 S3_4_C12_C9_4
147#define ICH_HCR_EL2 S3_4_C12_C11_0
148#define ICH_VTR_EL2 S3_4_C12_C11_1
149#define ICH_MISR_EL2 S3_4_C12_C11_2
150#define ICH_EISR_EL2 S3_4_C12_C11_3
151#define ICH_ELSR_EL2 S3_4_C12_C11_5
152#define ICH_VMCR_EL2 S3_4_C12_C11_7
153
154#define __LR0_EL2(x) S3_4_C12_C12_ ## x
155#define __LR8_EL2(x) S3_4_C12_C13_ ## x
156
157#define ICH_LR0_EL2 __LR0_EL2(0)
158#define ICH_LR1_EL2 __LR0_EL2(1)
159#define ICH_LR2_EL2 __LR0_EL2(2)
160#define ICH_LR3_EL2 __LR0_EL2(3)
161#define ICH_LR4_EL2 __LR0_EL2(4)
162#define ICH_LR5_EL2 __LR0_EL2(5)
163#define ICH_LR6_EL2 __LR0_EL2(6)
164#define ICH_LR7_EL2 __LR0_EL2(7)
165#define ICH_LR8_EL2 __LR8_EL2(0)
166#define ICH_LR9_EL2 __LR8_EL2(1)
167#define ICH_LR10_EL2 __LR8_EL2(2)
168#define ICH_LR11_EL2 __LR8_EL2(3)
169#define ICH_LR12_EL2 __LR8_EL2(4)
170#define ICH_LR13_EL2 __LR8_EL2(5)
171#define ICH_LR14_EL2 __LR8_EL2(6)
172#define ICH_LR15_EL2 __LR8_EL2(7)
173
174#define __AP0Rx_EL2(x) S3_4_C12_C8_ ## x
175#define ICH_AP0R0_EL2 __AP0Rx_EL2(0)
176#define ICH_AP0R1_EL2 __AP0Rx_EL2(1)
177#define ICH_AP0R2_EL2 __AP0Rx_EL2(2)
178#define ICH_AP0R3_EL2 __AP0Rx_EL2(3)
179
180#define __AP1Rx_EL2(x) S3_4_C12_C9_ ## x
181#define ICH_AP1R0_EL2 __AP1Rx_EL2(0)
182#define ICH_AP1R1_EL2 __AP1Rx_EL2(1)
183#define ICH_AP1R2_EL2 __AP1Rx_EL2(2)
184#define ICH_AP1R3_EL2 __AP1Rx_EL2(3)
185
186#ifndef __ASSEMBLY__
187
188#include <linux/stringify.h>
189
190static inline void gic_write_eoir(u64 irq)
191{
192 asm volatile("msr " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" (irq));
193 isb();
194}
195
196#endif
197
198#endif
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c
index 452d6f2ba21d..cf80e7b0ddab 100644
--- a/kernel/irq/generic-chip.c
+++ b/kernel/irq/generic-chip.c
@@ -341,8 +341,8 @@ static struct lock_class_key irq_nested_lock_class;
341/* 341/*
342 * irq_map_generic_chip - Map a generic chip for an irq domain 342 * irq_map_generic_chip - Map a generic chip for an irq domain
343 */ 343 */
344static int irq_map_generic_chip(struct irq_domain *d, unsigned int virq, 344int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
345 irq_hw_number_t hw_irq) 345 irq_hw_number_t hw_irq)
346{ 346{
347 struct irq_data *data = irq_get_irq_data(virq); 347 struct irq_data *data = irq_get_irq_data(virq);
348 struct irq_domain_chip_generic *dgc = d->gc; 348 struct irq_domain_chip_generic *dgc = d->gc;
@@ -394,6 +394,7 @@ static int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
394 irq_modify_status(virq, dgc->irq_flags_to_clear, dgc->irq_flags_to_set); 394 irq_modify_status(virq, dgc->irq_flags_to_clear, dgc->irq_flags_to_set);
395 return 0; 395 return 0;
396} 396}
397EXPORT_SYMBOL_GPL(irq_map_generic_chip);
397 398
398struct irq_domain_ops irq_generic_chip_ops = { 399struct irq_domain_ops irq_generic_chip_ops = {
399 .map = irq_map_generic_chip, 400 .map = irq_map_generic_chip,