aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 17:58:40 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 17:58:40 -0500
commitb274776c54c320763bc12eb035c0e244f76ccb43 (patch)
treec75b70d0824a7ae029229b19d61884039abf2127 /drivers/irqchip
parentb24174b0cbbe383c5bb6097aeb24480b8fd2d338 (diff)
parent3b1209e7994c4d31ff9932a7f566ae1c96b3c443 (diff)
Merge tag 'cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC cleanups from Arnd Bergmann: "A large number of cleanups, all over the platforms. This is dominated largely by the Samsung platforms (s3c, s5p, exynos) and a few of the others moving code out of arch/arm into more appropriate subsystems. The clocksource and irqchip drivers are now abstracted to the point where platforms that are already cleaned up do not need to even specify the driver they use, it can all get configured from the device tree as we do for normal device drivers. The clocksource changes basically touch every single platform in the process. We further clean up the use of platform specific header files here, with the goal of turning more of the platforms over to being "multiplatform" enabled, which implies that they cannot expose their headers to architecture independent code any more. It is expected that no functional changes are part of the cleanup. The overall reduction in total code lines is mostly the result of removing broken and obsolete code." * tag 'cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (133 commits) ARM: mvebu: correct gated clock documentation ARM: kirkwood: add missing include for nsa310 ARM: exynos: move exynos4210-combiner to drivers/irqchip mfd: db8500-prcmu: update resource passing drivers/db8500-cpufreq: delete dangling include ARM: at91: remove NEOCORE 926 board sunxi: Cleanup the reset code and add meaningful registers defines ARM: S3C24XX: header mach/regs-mem.h local ARM: S3C24XX: header mach/regs-power.h local ARM: S3C24XX: header mach/regs-s3c2412-mem.h local ARM: S3C24XX: Remove plat-s3c24xx directory in arch/arm/ ARM: S3C24XX: transform s3c2443 subirqs into new structure ARM: S3C24XX: modify s3c2443 irq init to initialize all irqs ARM: S3C24XX: move s3c2443 irq code to irq.c ARM: S3C24XX: transform s3c2416 irqs into new structure ARM: S3C24XX: modify s3c2416 irq init to initialize all irqs ARM: S3C24XX: move s3c2416 irq init to common irq code ARM: S3C24XX: Modify s3c_irq_wake to use the hwirq property ARM: S3C24XX: Move irq syscore-ops to irq-pm clocksource: always define CLOCKSOURCE_OF_DECLARE ...
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/Kconfig27
-rw-r--r--drivers/irqchip/Makefile7
-rw-r--r--drivers/irqchip/exynos-combiner.c230
-rw-r--r--drivers/irqchip/irq-gic.c845
-rw-r--r--drivers/irqchip/irq-vic.c489
-rw-r--r--drivers/irqchip/irqchip.c30
-rw-r--r--drivers/irqchip/irqchip.h29
-rw-r--r--drivers/irqchip/spear-shirq.c5
8 files changed, 1661 insertions, 1 deletions
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 62ca575701d3..a350969e5efe 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -1,3 +1,30 @@
1config IRQCHIP
2 def_bool y
3 depends on OF_IRQ
4
5config ARM_GIC
6 bool
7 select IRQ_DOMAIN
8 select MULTI_IRQ_HANDLER
9
10config GIC_NON_BANKED
11 bool
12
13config ARM_VIC
14 bool
15 select IRQ_DOMAIN
16 select MULTI_IRQ_HANDLER
17
18config ARM_VIC_NR
19 int
20 default 4 if ARCH_S5PV210
21 default 3 if ARCH_S5PC100
22 default 2
23 depends on ARM_VIC
24 help
25 The maximum number of VICs available in the system, for
26 power management.
27
1config VERSATILE_FPGA_IRQ 28config VERSATILE_FPGA_IRQ
2 bool 29 bool
3 select IRQ_DOMAIN 30 select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index bf4609a5bd9d..e65fbf2cdf71 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -1,4 +1,9 @@
1obj-$(CONFIG_IRQCHIP) += irqchip.o
2
1obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o 3obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
4obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o
2obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o 5obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o
3obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
4obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o 6obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
7obj-$(CONFIG_ARM_GIC) += irq-gic.o
8obj-$(CONFIG_ARM_VIC) += irq-vic.o
9obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c
new file mode 100644
index 000000000000..04d86a9803f4
--- /dev/null
+++ b/drivers/irqchip/exynos-combiner.c
@@ -0,0 +1,230 @@
1/*
2 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
4 *
5 * Combiner irqchip for EXYNOS
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/err.h>
12#include <linux/export.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/irqdomain.h>
16#include <linux/of_address.h>
17#include <linux/of_irq.h>
18#include <asm/mach/irq.h>
19
20#include <plat/cpu.h>
21
22#include "irqchip.h"
23
24#define COMBINER_ENABLE_SET 0x0
25#define COMBINER_ENABLE_CLEAR 0x4
26#define COMBINER_INT_STATUS 0xC
27
28static DEFINE_SPINLOCK(irq_controller_lock);
29
30struct combiner_chip_data {
31 unsigned int irq_offset;
32 unsigned int irq_mask;
33 void __iomem *base;
34};
35
36static struct irq_domain *combiner_irq_domain;
37static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
38
39static inline void __iomem *combiner_base(struct irq_data *data)
40{
41 struct combiner_chip_data *combiner_data =
42 irq_data_get_irq_chip_data(data);
43
44 return combiner_data->base;
45}
46
47static void combiner_mask_irq(struct irq_data *data)
48{
49 u32 mask = 1 << (data->hwirq % 32);
50
51 __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
52}
53
54static void combiner_unmask_irq(struct irq_data *data)
55{
56 u32 mask = 1 << (data->hwirq % 32);
57
58 __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
59}
60
61static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
62{
63 struct combiner_chip_data *chip_data = irq_get_handler_data(irq);
64 struct irq_chip *chip = irq_get_chip(irq);
65 unsigned int cascade_irq, combiner_irq;
66 unsigned long status;
67
68 chained_irq_enter(chip, desc);
69
70 spin_lock(&irq_controller_lock);
71 status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
72 spin_unlock(&irq_controller_lock);
73 status &= chip_data->irq_mask;
74
75 if (status == 0)
76 goto out;
77
78 combiner_irq = __ffs(status);
79
80 cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
81 if (unlikely(cascade_irq >= NR_IRQS))
82 do_bad_IRQ(cascade_irq, desc);
83 else
84 generic_handle_irq(cascade_irq);
85
86 out:
87 chained_irq_exit(chip, desc);
88}
89
90static struct irq_chip combiner_chip = {
91 .name = "COMBINER",
92 .irq_mask = combiner_mask_irq,
93 .irq_unmask = combiner_unmask_irq,
94};
95
96static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
97{
98 unsigned int max_nr;
99
100 if (soc_is_exynos5250())
101 max_nr = EXYNOS5_MAX_COMBINER_NR;
102 else
103 max_nr = EXYNOS4_MAX_COMBINER_NR;
104
105 if (combiner_nr >= max_nr)
106 BUG();
107 if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
108 BUG();
109 irq_set_chained_handler(irq, combiner_handle_cascade_irq);
110}
111
112static void __init combiner_init_one(unsigned int combiner_nr,
113 void __iomem *base)
114{
115 combiner_data[combiner_nr].base = base;
116 combiner_data[combiner_nr].irq_offset = irq_find_mapping(
117 combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER);
118 combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
119
120 /* Disable all interrupts */
121 __raw_writel(combiner_data[combiner_nr].irq_mask,
122 base + COMBINER_ENABLE_CLEAR);
123}
124
125#ifdef CONFIG_OF
126static int combiner_irq_domain_xlate(struct irq_domain *d,
127 struct device_node *controller,
128 const u32 *intspec, unsigned int intsize,
129 unsigned long *out_hwirq,
130 unsigned int *out_type)
131{
132 if (d->of_node != controller)
133 return -EINVAL;
134
135 if (intsize < 2)
136 return -EINVAL;
137
138 *out_hwirq = intspec[0] * MAX_IRQ_IN_COMBINER + intspec[1];
139 *out_type = 0;
140
141 return 0;
142}
143#else
144static int combiner_irq_domain_xlate(struct irq_domain *d,
145 struct device_node *controller,
146 const u32 *intspec, unsigned int intsize,
147 unsigned long *out_hwirq,
148 unsigned int *out_type)
149{
150 return -EINVAL;
151}
152#endif
153
154static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
155 irq_hw_number_t hw)
156{
157 irq_set_chip_and_handler(irq, &combiner_chip, handle_level_irq);
158 irq_set_chip_data(irq, &combiner_data[hw >> 3]);
159 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
160
161 return 0;
162}
163
164static struct irq_domain_ops combiner_irq_domain_ops = {
165 .xlate = combiner_irq_domain_xlate,
166 .map = combiner_irq_domain_map,
167};
168
169void __init combiner_init(void __iomem *combiner_base,
170 struct device_node *np)
171{
172 int i, irq, irq_base;
173 unsigned int max_nr, nr_irq;
174
175 if (np) {
176 if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
177 pr_warning("%s: number of combiners not specified, "
178 "setting default as %d.\n",
179 __func__, EXYNOS4_MAX_COMBINER_NR);
180 max_nr = EXYNOS4_MAX_COMBINER_NR;
181 }
182 } else {
183 max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
184 EXYNOS4_MAX_COMBINER_NR;
185 }
186 nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
187
188 irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
189 if (IS_ERR_VALUE(irq_base)) {
190 irq_base = COMBINER_IRQ(0, 0);
191 pr_warning("%s: irq desc alloc failed. Continuing with %d as linux irq base\n", __func__, irq_base);
192 }
193
194 combiner_irq_domain = irq_domain_add_legacy(np, nr_irq, irq_base, 0,
195 &combiner_irq_domain_ops, &combiner_data);
196 if (WARN_ON(!combiner_irq_domain)) {
197 pr_warning("%s: irq domain init failed\n", __func__);
198 return;
199 }
200
201 for (i = 0; i < max_nr; i++) {
202 combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
203 irq = IRQ_SPI(i);
204#ifdef CONFIG_OF
205 if (np)
206 irq = irq_of_parse_and_map(np, i);
207#endif
208 combiner_cascade_irq(i, irq);
209 }
210}
211
212#ifdef CONFIG_OF
213static int __init combiner_of_init(struct device_node *np,
214 struct device_node *parent)
215{
216 void __iomem *combiner_base;
217
218 combiner_base = of_iomap(np, 0);
219 if (!combiner_base) {
220 pr_err("%s: failed to map combiner registers\n", __func__);
221 return -ENXIO;
222 }
223
224 combiner_init(combiner_base, np);
225
226 return 0;
227}
228IRQCHIP_DECLARE(exynos4210_combiner, "samsung,exynos4210-combiner",
229 combiner_of_init);
230#endif
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
new file mode 100644
index 000000000000..644d72468423
--- /dev/null
+++ b/drivers/irqchip/irq-gic.c
@@ -0,0 +1,845 @@
1/*
2 * linux/arch/arm/common/gic.c
3 *
4 * Copyright (C) 2002 ARM Limited, All Rights Reserved.
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 * Interrupt architecture for the GIC:
11 *
12 * o There is one Interrupt Distributor, which receives interrupts
13 * from system devices and sends them to the Interrupt Controllers.
14 *
15 * o There is one CPU Interface per CPU, which sends interrupts sent
16 * by the Distributor, and interrupts generated locally, to the
17 * associated CPU. The base address of the CPU interface is usually
18 * aliased so that the same address points to different chips depending
19 * on the CPU it is accessed from.
20 *
21 * Note that IRQs 0-31 are special - they are local to each CPU.
22 * As such, the enable set/clear, pending set/clear and active bit
23 * registers are banked per-cpu for these sources.
24 */
25#include <linux/init.h>
26#include <linux/kernel.h>
27#include <linux/err.h>
28#include <linux/module.h>
29#include <linux/list.h>
30#include <linux/smp.h>
31#include <linux/cpu_pm.h>
32#include <linux/cpumask.h>
33#include <linux/io.h>
34#include <linux/of.h>
35#include <linux/of_address.h>
36#include <linux/of_irq.h>
37#include <linux/irqdomain.h>
38#include <linux/interrupt.h>
39#include <linux/percpu.h>
40#include <linux/slab.h>
41#include <linux/irqchip/arm-gic.h>
42
43#include <asm/irq.h>
44#include <asm/exception.h>
45#include <asm/smp_plat.h>
46#include <asm/mach/irq.h>
47
48#include "irqchip.h"
49
50union gic_base {
51 void __iomem *common_base;
52 void __percpu __iomem **percpu_base;
53};
54
55struct gic_chip_data {
56 union gic_base dist_base;
57 union gic_base cpu_base;
58#ifdef CONFIG_CPU_PM
59 u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
60 u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
61 u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
62 u32 __percpu *saved_ppi_enable;
63 u32 __percpu *saved_ppi_conf;
64#endif
65 struct irq_domain *domain;
66 unsigned int gic_irqs;
67#ifdef CONFIG_GIC_NON_BANKED
68 void __iomem *(*get_base)(union gic_base *);
69#endif
70};
71
72static DEFINE_RAW_SPINLOCK(irq_controller_lock);
73
74/*
75 * The GIC mapping of CPU interfaces does not necessarily match
76 * the logical CPU numbering. Let's use a mapping as returned
77 * by the GIC itself.
78 */
79#define NR_GIC_CPU_IF 8
80static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
81
82/*
83 * Supported arch specific GIC irq extension.
84 * Default make them NULL.
85 */
86struct irq_chip gic_arch_extn = {
87 .irq_eoi = NULL,
88 .irq_mask = NULL,
89 .irq_unmask = NULL,
90 .irq_retrigger = NULL,
91 .irq_set_type = NULL,
92 .irq_set_wake = NULL,
93};
94
95#ifndef MAX_GIC_NR
96#define MAX_GIC_NR 1
97#endif
98
99static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
100
101#ifdef CONFIG_GIC_NON_BANKED
102static void __iomem *gic_get_percpu_base(union gic_base *base)
103{
104 return *__this_cpu_ptr(base->percpu_base);
105}
106
107static void __iomem *gic_get_common_base(union gic_base *base)
108{
109 return base->common_base;
110}
111
112static inline void __iomem *gic_data_dist_base(struct gic_chip_data *data)
113{
114 return data->get_base(&data->dist_base);
115}
116
117static inline void __iomem *gic_data_cpu_base(struct gic_chip_data *data)
118{
119 return data->get_base(&data->cpu_base);
120}
121
122static inline void gic_set_base_accessor(struct gic_chip_data *data,
123 void __iomem *(*f)(union gic_base *))
124{
125 data->get_base = f;
126}
127#else
128#define gic_data_dist_base(d) ((d)->dist_base.common_base)
129#define gic_data_cpu_base(d) ((d)->cpu_base.common_base)
130#define gic_set_base_accessor(d,f)
131#endif
132
133static inline void __iomem *gic_dist_base(struct irq_data *d)
134{
135 struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
136 return gic_data_dist_base(gic_data);
137}
138
139static inline void __iomem *gic_cpu_base(struct irq_data *d)
140{
141 struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
142 return gic_data_cpu_base(gic_data);
143}
144
145static inline unsigned int gic_irq(struct irq_data *d)
146{
147 return d->hwirq;
148}
149
150/*
151 * Routines to acknowledge, disable and enable interrupts
152 */
153static void gic_mask_irq(struct irq_data *d)
154{
155 u32 mask = 1 << (gic_irq(d) % 32);
156
157 raw_spin_lock(&irq_controller_lock);
158 writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
159 if (gic_arch_extn.irq_mask)
160 gic_arch_extn.irq_mask(d);
161 raw_spin_unlock(&irq_controller_lock);
162}
163
164static void gic_unmask_irq(struct irq_data *d)
165{
166 u32 mask = 1 << (gic_irq(d) % 32);
167
168 raw_spin_lock(&irq_controller_lock);
169 if (gic_arch_extn.irq_unmask)
170 gic_arch_extn.irq_unmask(d);
171 writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
172 raw_spin_unlock(&irq_controller_lock);
173}
174
175static void gic_eoi_irq(struct irq_data *d)
176{
177 if (gic_arch_extn.irq_eoi) {
178 raw_spin_lock(&irq_controller_lock);
179 gic_arch_extn.irq_eoi(d);
180 raw_spin_unlock(&irq_controller_lock);
181 }
182
183 writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
184}
185
186static int gic_set_type(struct irq_data *d, unsigned int type)
187{
188 void __iomem *base = gic_dist_base(d);
189 unsigned int gicirq = gic_irq(d);
190 u32 enablemask = 1 << (gicirq % 32);
191 u32 enableoff = (gicirq / 32) * 4;
192 u32 confmask = 0x2 << ((gicirq % 16) * 2);
193 u32 confoff = (gicirq / 16) * 4;
194 bool enabled = false;
195 u32 val;
196
197 /* Interrupt configuration for SGIs can't be changed */
198 if (gicirq < 16)
199 return -EINVAL;
200
201 if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
202 return -EINVAL;
203
204 raw_spin_lock(&irq_controller_lock);
205
206 if (gic_arch_extn.irq_set_type)
207 gic_arch_extn.irq_set_type(d, type);
208
209 val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
210 if (type == IRQ_TYPE_LEVEL_HIGH)
211 val &= ~confmask;
212 else if (type == IRQ_TYPE_EDGE_RISING)
213 val |= confmask;
214
215 /*
216 * As recommended by the spec, disable the interrupt before changing
217 * the configuration
218 */
219 if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
220 writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
221 enabled = true;
222 }
223
224 writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
225
226 if (enabled)
227 writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
228
229 raw_spin_unlock(&irq_controller_lock);
230
231 return 0;
232}
233
234static int gic_retrigger(struct irq_data *d)
235{
236 if (gic_arch_extn.irq_retrigger)
237 return gic_arch_extn.irq_retrigger(d);
238
239 return -ENXIO;
240}
241
242#ifdef CONFIG_SMP
243static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
244 bool force)
245{
246 void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
247 unsigned int shift = (gic_irq(d) % 4) * 8;
248 unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
249 u32 val, mask, bit;
250
251 if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
252 return -EINVAL;
253
254 mask = 0xff << shift;
255 bit = gic_cpu_map[cpu] << shift;
256
257 raw_spin_lock(&irq_controller_lock);
258 val = readl_relaxed(reg) & ~mask;
259 writel_relaxed(val | bit, reg);
260 raw_spin_unlock(&irq_controller_lock);
261
262 return IRQ_SET_MASK_OK;
263}
264#endif
265
266#ifdef CONFIG_PM
267static int gic_set_wake(struct irq_data *d, unsigned int on)
268{
269 int ret = -ENXIO;
270
271 if (gic_arch_extn.irq_set_wake)
272 ret = gic_arch_extn.irq_set_wake(d, on);
273
274 return ret;
275}
276
277#else
278#define gic_set_wake NULL
279#endif
280
281static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
282{
283 u32 irqstat, irqnr;
284 struct gic_chip_data *gic = &gic_data[0];
285 void __iomem *cpu_base = gic_data_cpu_base(gic);
286
287 do {
288 irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
289 irqnr = irqstat & ~0x1c00;
290
291 if (likely(irqnr > 15 && irqnr < 1021)) {
292 irqnr = irq_find_mapping(gic->domain, irqnr);
293 handle_IRQ(irqnr, regs);
294 continue;
295 }
296 if (irqnr < 16) {
297 writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
298#ifdef CONFIG_SMP
299 handle_IPI(irqnr, regs);
300#endif
301 continue;
302 }
303 break;
304 } while (1);
305}
306
307static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
308{
309 struct gic_chip_data *chip_data = irq_get_handler_data(irq);
310 struct irq_chip *chip = irq_get_chip(irq);
311 unsigned int cascade_irq, gic_irq;
312 unsigned long status;
313
314 chained_irq_enter(chip, desc);
315
316 raw_spin_lock(&irq_controller_lock);
317 status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK);
318 raw_spin_unlock(&irq_controller_lock);
319
320 gic_irq = (status & 0x3ff);
321 if (gic_irq == 1023)
322 goto out;
323
324 cascade_irq = irq_find_mapping(chip_data->domain, gic_irq);
325 if (unlikely(gic_irq < 32 || gic_irq > 1020))
326 do_bad_IRQ(cascade_irq, desc);
327 else
328 generic_handle_irq(cascade_irq);
329
330 out:
331 chained_irq_exit(chip, desc);
332}
333
334static struct irq_chip gic_chip = {
335 .name = "GIC",
336 .irq_mask = gic_mask_irq,
337 .irq_unmask = gic_unmask_irq,
338 .irq_eoi = gic_eoi_irq,
339 .irq_set_type = gic_set_type,
340 .irq_retrigger = gic_retrigger,
341#ifdef CONFIG_SMP
342 .irq_set_affinity = gic_set_affinity,
343#endif
344 .irq_set_wake = gic_set_wake,
345};
346
347void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
348{
349 if (gic_nr >= MAX_GIC_NR)
350 BUG();
351 if (irq_set_handler_data(irq, &gic_data[gic_nr]) != 0)
352 BUG();
353 irq_set_chained_handler(irq, gic_handle_cascade_irq);
354}
355
356static u8 gic_get_cpumask(struct gic_chip_data *gic)
357{
358 void __iomem *base = gic_data_dist_base(gic);
359 u32 mask, i;
360
361 for (i = mask = 0; i < 32; i += 4) {
362 mask = readl_relaxed(base + GIC_DIST_TARGET + i);
363 mask |= mask >> 16;
364 mask |= mask >> 8;
365 if (mask)
366 break;
367 }
368
369 if (!mask)
370 pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");
371
372 return mask;
373}
374
375static void __init gic_dist_init(struct gic_chip_data *gic)
376{
377 unsigned int i;
378 u32 cpumask;
379 unsigned int gic_irqs = gic->gic_irqs;
380 void __iomem *base = gic_data_dist_base(gic);
381
382 writel_relaxed(0, base + GIC_DIST_CTRL);
383
384 /*
385 * Set all global interrupts to be level triggered, active low.
386 */
387 for (i = 32; i < gic_irqs; i += 16)
388 writel_relaxed(0, base + GIC_DIST_CONFIG + i * 4 / 16);
389
390 /*
391 * Set all global interrupts to this CPU only.
392 */
393 cpumask = gic_get_cpumask(gic);
394 cpumask |= cpumask << 8;
395 cpumask |= cpumask << 16;
396 for (i = 32; i < gic_irqs; i += 4)
397 writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
398
399 /*
400 * Set priority on all global interrupts.
401 */
402 for (i = 32; i < gic_irqs; i += 4)
403 writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
404
405 /*
406 * Disable all interrupts. Leave the PPI and SGIs alone
407 * as these enables are banked registers.
408 */
409 for (i = 32; i < gic_irqs; i += 32)
410 writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
411
412 writel_relaxed(1, base + GIC_DIST_CTRL);
413}
414
415static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
416{
417 void __iomem *dist_base = gic_data_dist_base(gic);
418 void __iomem *base = gic_data_cpu_base(gic);
419 unsigned int cpu_mask, cpu = smp_processor_id();
420 int i;
421
422 /*
423 * Get what the GIC says our CPU mask is.
424 */
425 BUG_ON(cpu >= NR_GIC_CPU_IF);
426 cpu_mask = gic_get_cpumask(gic);
427 gic_cpu_map[cpu] = cpu_mask;
428
429 /*
430 * Clear our mask from the other map entries in case they're
431 * still undefined.
432 */
433 for (i = 0; i < NR_GIC_CPU_IF; i++)
434 if (i != cpu)
435 gic_cpu_map[i] &= ~cpu_mask;
436
437 /*
438 * Deal with the banked PPI and SGI interrupts - disable all
439 * PPI interrupts, ensure all SGI interrupts are enabled.
440 */
441 writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
442 writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
443
444 /*
445 * Set priority on PPI and SGI interrupts
446 */
447 for (i = 0; i < 32; i += 4)
448 writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
449
450 writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
451 writel_relaxed(1, base + GIC_CPU_CTRL);
452}
453
454#ifdef CONFIG_CPU_PM
455/*
456 * Saves the GIC distributor registers during suspend or idle. Must be called
457 * with interrupts disabled but before powering down the GIC. After calling
458 * this function, no interrupts will be delivered by the GIC, and another
459 * platform-specific wakeup source must be enabled.
460 */
461static void gic_dist_save(unsigned int gic_nr)
462{
463 unsigned int gic_irqs;
464 void __iomem *dist_base;
465 int i;
466
467 if (gic_nr >= MAX_GIC_NR)
468 BUG();
469
470 gic_irqs = gic_data[gic_nr].gic_irqs;
471 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
472
473 if (!dist_base)
474 return;
475
476 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
477 gic_data[gic_nr].saved_spi_conf[i] =
478 readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
479
480 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
481 gic_data[gic_nr].saved_spi_target[i] =
482 readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
483
484 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
485 gic_data[gic_nr].saved_spi_enable[i] =
486 readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
487}
488
489/*
490 * Restores the GIC distributor registers during resume or when coming out of
491 * idle. Must be called before enabling interrupts. If a level interrupt
492 * that occured while the GIC was suspended is still present, it will be
493 * handled normally, but any edge interrupts that occured will not be seen by
494 * the GIC and need to be handled by the platform-specific wakeup source.
495 */
496static void gic_dist_restore(unsigned int gic_nr)
497{
498 unsigned int gic_irqs;
499 unsigned int i;
500 void __iomem *dist_base;
501
502 if (gic_nr >= MAX_GIC_NR)
503 BUG();
504
505 gic_irqs = gic_data[gic_nr].gic_irqs;
506 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
507
508 if (!dist_base)
509 return;
510
511 writel_relaxed(0, dist_base + GIC_DIST_CTRL);
512
513 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
514 writel_relaxed(gic_data[gic_nr].saved_spi_conf[i],
515 dist_base + GIC_DIST_CONFIG + i * 4);
516
517 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
518 writel_relaxed(0xa0a0a0a0,
519 dist_base + GIC_DIST_PRI + i * 4);
520
521 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
522 writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
523 dist_base + GIC_DIST_TARGET + i * 4);
524
525 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
526 writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
527 dist_base + GIC_DIST_ENABLE_SET + i * 4);
528
529 writel_relaxed(1, dist_base + GIC_DIST_CTRL);
530}
531
532static void gic_cpu_save(unsigned int gic_nr)
533{
534 int i;
535 u32 *ptr;
536 void __iomem *dist_base;
537 void __iomem *cpu_base;
538
539 if (gic_nr >= MAX_GIC_NR)
540 BUG();
541
542 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
543 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
544
545 if (!dist_base || !cpu_base)
546 return;
547
548 ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
549 for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
550 ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
551
552 ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
553 for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
554 ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
555
556}
557
558static void gic_cpu_restore(unsigned int gic_nr)
559{
560 int i;
561 u32 *ptr;
562 void __iomem *dist_base;
563 void __iomem *cpu_base;
564
565 if (gic_nr >= MAX_GIC_NR)
566 BUG();
567
568 dist_base = gic_data_dist_base(&gic_data[gic_nr]);
569 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
570
571 if (!dist_base || !cpu_base)
572 return;
573
574 ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
575 for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
576 writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
577
578 ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
579 for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
580 writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
581
582 for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
583 writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
584
585 writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
586 writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
587}
588
589static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v)
590{
591 int i;
592
593 for (i = 0; i < MAX_GIC_NR; i++) {
594#ifdef CONFIG_GIC_NON_BANKED
595 /* Skip over unused GICs */
596 if (!gic_data[i].get_base)
597 continue;
598#endif
599 switch (cmd) {
600 case CPU_PM_ENTER:
601 gic_cpu_save(i);
602 break;
603 case CPU_PM_ENTER_FAILED:
604 case CPU_PM_EXIT:
605 gic_cpu_restore(i);
606 break;
607 case CPU_CLUSTER_PM_ENTER:
608 gic_dist_save(i);
609 break;
610 case CPU_CLUSTER_PM_ENTER_FAILED:
611 case CPU_CLUSTER_PM_EXIT:
612 gic_dist_restore(i);
613 break;
614 }
615 }
616
617 return NOTIFY_OK;
618}
619
620static struct notifier_block gic_notifier_block = {
621 .notifier_call = gic_notifier,
622};
623
624static void __init gic_pm_init(struct gic_chip_data *gic)
625{
626 gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
627 sizeof(u32));
628 BUG_ON(!gic->saved_ppi_enable);
629
630 gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
631 sizeof(u32));
632 BUG_ON(!gic->saved_ppi_conf);
633
634 if (gic == &gic_data[0])
635 cpu_pm_register_notifier(&gic_notifier_block);
636}
637#else
638static void __init gic_pm_init(struct gic_chip_data *gic)
639{
640}
641#endif
642
643#ifdef CONFIG_SMP
644void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
645{
646 int cpu;
647 unsigned long map = 0;
648
649 /* Convert our logical CPU mask into a physical one. */
650 for_each_cpu(cpu, mask)
651 map |= 1 << cpu_logical_map(cpu);
652
653 /*
654 * Ensure that stores to Normal memory are visible to the
655 * other CPUs before issuing the IPI.
656 */
657 dsb();
658
659 /* this always happens on GIC0 */
660 writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
661}
662#endif
663
664static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
665 irq_hw_number_t hw)
666{
667 if (hw < 32) {
668 irq_set_percpu_devid(irq);
669 irq_set_chip_and_handler(irq, &gic_chip,
670 handle_percpu_devid_irq);
671 set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
672 } else {
673 irq_set_chip_and_handler(irq, &gic_chip,
674 handle_fasteoi_irq);
675 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
676 }
677 irq_set_chip_data(irq, d->host_data);
678 return 0;
679}
680
681static int gic_irq_domain_xlate(struct irq_domain *d,
682 struct device_node *controller,
683 const u32 *intspec, unsigned int intsize,
684 unsigned long *out_hwirq, unsigned int *out_type)
685{
686 if (d->of_node != controller)
687 return -EINVAL;
688 if (intsize < 3)
689 return -EINVAL;
690
691 /* Get the interrupt number and add 16 to skip over SGIs */
692 *out_hwirq = intspec[1] + 16;
693
694 /* For SPIs, we need to add 16 more to get the GIC irq ID number */
695 if (!intspec[0])
696 *out_hwirq += 16;
697
698 *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
699 return 0;
700}
701
702const struct irq_domain_ops gic_irq_domain_ops = {
703 .map = gic_irq_domain_map,
704 .xlate = gic_irq_domain_xlate,
705};
706
707void __init gic_init_bases(unsigned int gic_nr, int irq_start,
708 void __iomem *dist_base, void __iomem *cpu_base,
709 u32 percpu_offset, struct device_node *node)
710{
711 irq_hw_number_t hwirq_base;
712 struct gic_chip_data *gic;
713 int gic_irqs, irq_base, i;
714
715 BUG_ON(gic_nr >= MAX_GIC_NR);
716
717 gic = &gic_data[gic_nr];
718#ifdef CONFIG_GIC_NON_BANKED
719 if (percpu_offset) { /* Frankein-GIC without banked registers... */
720 unsigned int cpu;
721
722 gic->dist_base.percpu_base = alloc_percpu(void __iomem *);
723 gic->cpu_base.percpu_base = alloc_percpu(void __iomem *);
724 if (WARN_ON(!gic->dist_base.percpu_base ||
725 !gic->cpu_base.percpu_base)) {
726 free_percpu(gic->dist_base.percpu_base);
727 free_percpu(gic->cpu_base.percpu_base);
728 return;
729 }
730
731 for_each_possible_cpu(cpu) {
732 unsigned long offset = percpu_offset * cpu_logical_map(cpu);
733 *per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset;
734 *per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset;
735 }
736
737 gic_set_base_accessor(gic, gic_get_percpu_base);
738 } else
739#endif
740 { /* Normal, sane GIC... */
741 WARN(percpu_offset,
742 "GIC_NON_BANKED not enabled, ignoring %08x offset!",
743 percpu_offset);
744 gic->dist_base.common_base = dist_base;
745 gic->cpu_base.common_base = cpu_base;
746 gic_set_base_accessor(gic, gic_get_common_base);
747 }
748
749 /*
750 * Initialize the CPU interface map to all CPUs.
751 * It will be refined as each CPU probes its ID.
752 */
753 for (i = 0; i < NR_GIC_CPU_IF; i++)
754 gic_cpu_map[i] = 0xff;
755
756 /*
757 * For primary GICs, skip over SGIs.
758 * For secondary GICs, skip over PPIs, too.
759 */
760 if (gic_nr == 0 && (irq_start & 31) > 0) {
761 hwirq_base = 16;
762 if (irq_start != -1)
763 irq_start = (irq_start & ~31) + 16;
764 } else {
765 hwirq_base = 32;
766 }
767
768 /*
769 * Find out how many interrupts are supported.
770 * The GIC only supports up to 1020 interrupt sources.
771 */
772 gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f;
773 gic_irqs = (gic_irqs + 1) * 32;
774 if (gic_irqs > 1020)
775 gic_irqs = 1020;
776 gic->gic_irqs = gic_irqs;
777
778 gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */
779 irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, numa_node_id());
780 if (IS_ERR_VALUE(irq_base)) {
781 WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
782 irq_start);
783 irq_base = irq_start;
784 }
785 gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base,
786 hwirq_base, &gic_irq_domain_ops, gic);
787 if (WARN_ON(!gic->domain))
788 return;
789
790#ifdef CONFIG_SMP
791 set_smp_cross_call(gic_raise_softirq);
792#endif
793
794 set_handle_irq(gic_handle_irq);
795
796 gic_chip.flags |= gic_arch_extn.flags;
797 gic_dist_init(gic);
798 gic_cpu_init(gic);
799 gic_pm_init(gic);
800}
801
802void __cpuinit gic_secondary_init(unsigned int gic_nr)
803{
804 BUG_ON(gic_nr >= MAX_GIC_NR);
805
806 gic_cpu_init(&gic_data[gic_nr]);
807}
808
809#ifdef CONFIG_OF
810static int gic_cnt __initdata = 0;
811
812int __init gic_of_init(struct device_node *node, struct device_node *parent)
813{
814 void __iomem *cpu_base;
815 void __iomem *dist_base;
816 u32 percpu_offset;
817 int irq;
818
819 if (WARN_ON(!node))
820 return -ENODEV;
821
822 dist_base = of_iomap(node, 0);
823 WARN(!dist_base, "unable to map gic dist registers\n");
824
825 cpu_base = of_iomap(node, 1);
826 WARN(!cpu_base, "unable to map gic cpu registers\n");
827
828 if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
829 percpu_offset = 0;
830
831 gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
832
833 if (parent) {
834 irq = irq_of_parse_and_map(node, 0);
835 gic_cascade_irq(gic_cnt, irq);
836 }
837 gic_cnt++;
838 return 0;
839}
840IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init);
841IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);
842IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
843IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
844
845#endif
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
new file mode 100644
index 000000000000..3cf97aaebe40
--- /dev/null
+++ b/drivers/irqchip/irq-vic.c
@@ -0,0 +1,489 @@
1/*
2 * linux/arch/arm/common/vic.c
3 *
4 * Copyright (C) 1999 - 2003 ARM Limited
5 * Copyright (C) 2000 Deep Blue Solutions Ltd
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/export.h>
23#include <linux/init.h>
24#include <linux/list.h>
25#include <linux/io.h>
26#include <linux/irqdomain.h>
27#include <linux/of.h>
28#include <linux/of_address.h>
29#include <linux/of_irq.h>
30#include <linux/syscore_ops.h>
31#include <linux/device.h>
32#include <linux/amba/bus.h>
33#include <linux/irqchip/arm-vic.h>
34
35#include <asm/exception.h>
36#include <asm/mach/irq.h>
37
38#include "irqchip.h"
39
40#define VIC_IRQ_STATUS 0x00
41#define VIC_FIQ_STATUS 0x04
42#define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */
43#define VIC_INT_SOFT 0x18
44#define VIC_INT_SOFT_CLEAR 0x1c
45#define VIC_PROTECT 0x20
46#define VIC_PL190_VECT_ADDR 0x30 /* PL190 only */
47#define VIC_PL190_DEF_VECT_ADDR 0x34 /* PL190 only */
48
49#define VIC_VECT_ADDR0 0x100 /* 0 to 15 (0..31 PL192) */
50#define VIC_VECT_CNTL0 0x200 /* 0 to 15 (0..31 PL192) */
51#define VIC_ITCR 0x300 /* VIC test control register */
52
53#define VIC_VECT_CNTL_ENABLE (1 << 5)
54
55#define VIC_PL192_VECT_ADDR 0xF00
56
57/**
58 * struct vic_device - VIC PM device
59 * @irq: The IRQ number for the base of the VIC.
60 * @base: The register base for the VIC.
61 * @valid_sources: A bitmask of valid interrupts
62 * @resume_sources: A bitmask of interrupts for resume.
63 * @resume_irqs: The IRQs enabled for resume.
64 * @int_select: Save for VIC_INT_SELECT.
65 * @int_enable: Save for VIC_INT_ENABLE.
66 * @soft_int: Save for VIC_INT_SOFT.
67 * @protect: Save for VIC_PROTECT.
68 * @domain: The IRQ domain for the VIC.
69 */
70struct vic_device {
71 void __iomem *base;
72 int irq;
73 u32 valid_sources;
74 u32 resume_sources;
75 u32 resume_irqs;
76 u32 int_select;
77 u32 int_enable;
78 u32 soft_int;
79 u32 protect;
80 struct irq_domain *domain;
81};
82
83/* we cannot allocate memory when VICs are initially registered */
84static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
85
86static int vic_id;
87
88static void vic_handle_irq(struct pt_regs *regs);
89
90/**
91 * vic_init2 - common initialisation code
92 * @base: Base of the VIC.
93 *
94 * Common initialisation code for registration
95 * and resume.
96*/
97static void vic_init2(void __iomem *base)
98{
99 int i;
100
101 for (i = 0; i < 16; i++) {
102 void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
103 writel(VIC_VECT_CNTL_ENABLE | i, reg);
104 }
105
106 writel(32, base + VIC_PL190_DEF_VECT_ADDR);
107}
108
109#ifdef CONFIG_PM
110static void resume_one_vic(struct vic_device *vic)
111{
112 void __iomem *base = vic->base;
113
114 printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base);
115
116 /* re-initialise static settings */
117 vic_init2(base);
118
119 writel(vic->int_select, base + VIC_INT_SELECT);
120 writel(vic->protect, base + VIC_PROTECT);
121
122 /* set the enabled ints and then clear the non-enabled */
123 writel(vic->int_enable, base + VIC_INT_ENABLE);
124 writel(~vic->int_enable, base + VIC_INT_ENABLE_CLEAR);
125
126 /* and the same for the soft-int register */
127
128 writel(vic->soft_int, base + VIC_INT_SOFT);
129 writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR);
130}
131
132static void vic_resume(void)
133{
134 int id;
135
136 for (id = vic_id - 1; id >= 0; id--)
137 resume_one_vic(vic_devices + id);
138}
139
140static void suspend_one_vic(struct vic_device *vic)
141{
142 void __iomem *base = vic->base;
143
144 printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base);
145
146 vic->int_select = readl(base + VIC_INT_SELECT);
147 vic->int_enable = readl(base + VIC_INT_ENABLE);
148 vic->soft_int = readl(base + VIC_INT_SOFT);
149 vic->protect = readl(base + VIC_PROTECT);
150
151 /* set the interrupts (if any) that are used for
152 * resuming the system */
153
154 writel(vic->resume_irqs, base + VIC_INT_ENABLE);
155 writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR);
156}
157
158static int vic_suspend(void)
159{
160 int id;
161
162 for (id = 0; id < vic_id; id++)
163 suspend_one_vic(vic_devices + id);
164
165 return 0;
166}
167
168struct syscore_ops vic_syscore_ops = {
169 .suspend = vic_suspend,
170 .resume = vic_resume,
171};
172
173/**
174 * vic_pm_init - initicall to register VIC pm
175 *
176 * This is called via late_initcall() to register
177 * the resources for the VICs due to the early
178 * nature of the VIC's registration.
179*/
180static int __init vic_pm_init(void)
181{
182 if (vic_id > 0)
183 register_syscore_ops(&vic_syscore_ops);
184
185 return 0;
186}
187late_initcall(vic_pm_init);
188#endif /* CONFIG_PM */
189
190static struct irq_chip vic_chip;
191
192static int vic_irqdomain_map(struct irq_domain *d, unsigned int irq,
193 irq_hw_number_t hwirq)
194{
195 struct vic_device *v = d->host_data;
196
197 /* Skip invalid IRQs, only register handlers for the real ones */
198 if (!(v->valid_sources & (1 << hwirq)))
199 return -ENOTSUPP;
200 irq_set_chip_and_handler(irq, &vic_chip, handle_level_irq);
201 irq_set_chip_data(irq, v->base);
202 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
203 return 0;
204}
205
206/*
207 * Handle each interrupt in a single VIC. Returns non-zero if we've
208 * handled at least one interrupt. This reads the status register
209 * before handling each interrupt, which is necessary given that
210 * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
211 */
212static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
213{
214 u32 stat, irq;
215 int handled = 0;
216
217 while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
218 irq = ffs(stat) - 1;
219 handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
220 handled = 1;
221 }
222
223 return handled;
224}
225
226/*
227 * Keep iterating over all registered VIC's until there are no pending
228 * interrupts.
229 */
230static asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
231{
232 int i, handled;
233
234 do {
235 for (i = 0, handled = 0; i < vic_id; ++i)
236 handled |= handle_one_vic(&vic_devices[i], regs);
237 } while (handled);
238}
239
240static struct irq_domain_ops vic_irqdomain_ops = {
241 .map = vic_irqdomain_map,
242 .xlate = irq_domain_xlate_onetwocell,
243};
244
245/**
246 * vic_register() - Register a VIC.
247 * @base: The base address of the VIC.
248 * @irq: The base IRQ for the VIC.
249 * @valid_sources: bitmask of valid interrupts
250 * @resume_sources: bitmask of interrupts allowed for resume sources.
251 * @node: The device tree node associated with the VIC.
252 *
253 * Register the VIC with the system device tree so that it can be notified
254 * of suspend and resume requests and ensure that the correct actions are
255 * taken to re-instate the settings on resume.
256 *
257 * This also configures the IRQ domain for the VIC.
258 */
259static void __init vic_register(void __iomem *base, unsigned int irq,
260 u32 valid_sources, u32 resume_sources,
261 struct device_node *node)
262{
263 struct vic_device *v;
264 int i;
265
266 if (vic_id >= ARRAY_SIZE(vic_devices)) {
267 printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
268 return;
269 }
270
271 v = &vic_devices[vic_id];
272 v->base = base;
273 v->valid_sources = valid_sources;
274 v->resume_sources = resume_sources;
275 v->irq = irq;
276 set_handle_irq(vic_handle_irq);
277 vic_id++;
278 v->domain = irq_domain_add_simple(node, fls(valid_sources), irq,
279 &vic_irqdomain_ops, v);
280 /* create an IRQ mapping for each valid IRQ */
281 for (i = 0; i < fls(valid_sources); i++)
282 if (valid_sources & (1 << i))
283 irq_create_mapping(v->domain, i);
284}
285
286static void vic_ack_irq(struct irq_data *d)
287{
288 void __iomem *base = irq_data_get_irq_chip_data(d);
289 unsigned int irq = d->hwirq;
290 writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
291 /* moreover, clear the soft-triggered, in case it was the reason */
292 writel(1 << irq, base + VIC_INT_SOFT_CLEAR);
293}
294
295static void vic_mask_irq(struct irq_data *d)
296{
297 void __iomem *base = irq_data_get_irq_chip_data(d);
298 unsigned int irq = d->hwirq;
299 writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
300}
301
302static void vic_unmask_irq(struct irq_data *d)
303{
304 void __iomem *base = irq_data_get_irq_chip_data(d);
305 unsigned int irq = d->hwirq;
306 writel(1 << irq, base + VIC_INT_ENABLE);
307}
308
309#if defined(CONFIG_PM)
310static struct vic_device *vic_from_irq(unsigned int irq)
311{
312 struct vic_device *v = vic_devices;
313 unsigned int base_irq = irq & ~31;
314 int id;
315
316 for (id = 0; id < vic_id; id++, v++) {
317 if (v->irq == base_irq)
318 return v;
319 }
320
321 return NULL;
322}
323
324static int vic_set_wake(struct irq_data *d, unsigned int on)
325{
326 struct vic_device *v = vic_from_irq(d->irq);
327 unsigned int off = d->hwirq;
328 u32 bit = 1 << off;
329
330 if (!v)
331 return -EINVAL;
332
333 if (!(bit & v->resume_sources))
334 return -EINVAL;
335
336 if (on)
337 v->resume_irqs |= bit;
338 else
339 v->resume_irqs &= ~bit;
340
341 return 0;
342}
343#else
344#define vic_set_wake NULL
345#endif /* CONFIG_PM */
346
347static struct irq_chip vic_chip = {
348 .name = "VIC",
349 .irq_ack = vic_ack_irq,
350 .irq_mask = vic_mask_irq,
351 .irq_unmask = vic_unmask_irq,
352 .irq_set_wake = vic_set_wake,
353};
354
355static void __init vic_disable(void __iomem *base)
356{
357 writel(0, base + VIC_INT_SELECT);
358 writel(0, base + VIC_INT_ENABLE);
359 writel(~0, base + VIC_INT_ENABLE_CLEAR);
360 writel(0, base + VIC_ITCR);
361 writel(~0, base + VIC_INT_SOFT_CLEAR);
362}
363
364static void __init vic_clear_interrupts(void __iomem *base)
365{
366 unsigned int i;
367
368 writel(0, base + VIC_PL190_VECT_ADDR);
369 for (i = 0; i < 19; i++) {
370 unsigned int value;
371
372 value = readl(base + VIC_PL190_VECT_ADDR);
373 writel(value, base + VIC_PL190_VECT_ADDR);
374 }
375}
376
377/*
378 * The PL190 cell from ARM has been modified by ST to handle 64 interrupts.
379 * The original cell has 32 interrupts, while the modified one has 64,
380 * replocating two blocks 0x00..0x1f in 0x20..0x3f. In that case
381 * the probe function is called twice, with base set to offset 000
382 * and 020 within the page. We call this "second block".
383 */
384static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
385 u32 vic_sources, struct device_node *node)
386{
387 unsigned int i;
388 int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0;
389
390 /* Disable all interrupts initially. */
391 vic_disable(base);
392
393 /*
394 * Make sure we clear all existing interrupts. The vector registers
395 * in this cell are after the second block of general registers,
396 * so we can address them using standard offsets, but only from
397 * the second base address, which is 0x20 in the page
398 */
399 if (vic_2nd_block) {
400 vic_clear_interrupts(base);
401
402 /* ST has 16 vectors as well, but we don't enable them by now */
403 for (i = 0; i < 16; i++) {
404 void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
405 writel(0, reg);
406 }
407
408 writel(32, base + VIC_PL190_DEF_VECT_ADDR);
409 }
410
411 vic_register(base, irq_start, vic_sources, 0, node);
412}
413
414void __init __vic_init(void __iomem *base, int irq_start,
415 u32 vic_sources, u32 resume_sources,
416 struct device_node *node)
417{
418 unsigned int i;
419 u32 cellid = 0;
420 enum amba_vendor vendor;
421
422 /* Identify which VIC cell this one is, by reading the ID */
423 for (i = 0; i < 4; i++) {
424 void __iomem *addr;
425 addr = (void __iomem *)((u32)base & PAGE_MASK) + 0xfe0 + (i * 4);
426 cellid |= (readl(addr) & 0xff) << (8 * i);
427 }
428 vendor = (cellid >> 12) & 0xff;
429 printk(KERN_INFO "VIC @%p: id 0x%08x, vendor 0x%02x\n",
430 base, cellid, vendor);
431
432 switch(vendor) {
433 case AMBA_VENDOR_ST:
434 vic_init_st(base, irq_start, vic_sources, node);
435 return;
436 default:
437 printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n");
438 /* fall through */
439 case AMBA_VENDOR_ARM:
440 break;
441 }
442
443 /* Disable all interrupts initially. */
444 vic_disable(base);
445
446 /* Make sure we clear all existing interrupts */
447 vic_clear_interrupts(base);
448
449 vic_init2(base);
450
451 vic_register(base, irq_start, vic_sources, resume_sources, node);
452}
453
454/**
455 * vic_init() - initialise a vectored interrupt controller
456 * @base: iomem base address
457 * @irq_start: starting interrupt number, must be muliple of 32
458 * @vic_sources: bitmask of interrupt sources to allow
459 * @resume_sources: bitmask of interrupt sources to allow for resume
460 */
461void __init vic_init(void __iomem *base, unsigned int irq_start,
462 u32 vic_sources, u32 resume_sources)
463{
464 __vic_init(base, irq_start, vic_sources, resume_sources, NULL);
465}
466
467#ifdef CONFIG_OF
468int __init vic_of_init(struct device_node *node, struct device_node *parent)
469{
470 void __iomem *regs;
471
472 if (WARN(parent, "non-root VICs are not supported"))
473 return -EINVAL;
474
475 regs = of_iomap(node, 0);
476 if (WARN_ON(!regs))
477 return -EIO;
478
479 /*
480 * Passing 0 as first IRQ makes the simple domain allocate descriptors
481 */
482 __vic_init(regs, 0, ~0, ~0, node);
483
484 return 0;
485}
486IRQCHIP_DECLARE(arm_pl190_vic, "arm,pl190-vic", vic_of_init);
487IRQCHIP_DECLARE(arm_pl192_vic, "arm,pl192-vic", vic_of_init);
488IRQCHIP_DECLARE(arm_versatile_vic, "arm,versatile-vic", vic_of_init);
489#endif /* CONFIG OF */
diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
new file mode 100644
index 000000000000..f496afce29de
--- /dev/null
+++ b/drivers/irqchip/irqchip.c
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2012 Thomas Petazzoni
3 *
4 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11#include <linux/init.h>
12#include <linux/of_irq.h>
13
14#include "irqchip.h"
15
16/*
17 * This special of_device_id is the sentinel at the end of the
18 * of_device_id[] array of all irqchips. It is automatically placed at
19 * the end of the array by the linker, thanks to being part of a
20 * special section.
21 */
22static const struct of_device_id
23irqchip_of_match_end __used __section(__irqchip_of_end);
24
25extern struct of_device_id __irqchip_begin[];
26
27void __init irqchip_init(void)
28{
29 of_irq_init(__irqchip_begin);
30}
diff --git a/drivers/irqchip/irqchip.h b/drivers/irqchip/irqchip.h
new file mode 100644
index 000000000000..e445ba2d6add
--- /dev/null
+++ b/drivers/irqchip/irqchip.h
@@ -0,0 +1,29 @@
1/*
2 * Copyright (C) 2012 Thomas Petazzoni
3 *
4 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11#ifndef _IRQCHIP_H
12#define _IRQCHIP_H
13
14/*
15 * This macro must be used by the different irqchip drivers to declare
16 * the association between their DT compatible string and their
17 * initialization function.
18 *
19 * @name: name that must be unique accross all IRQCHIP_DECLARE of the
20 * same file.
21 * @compstr: compatible string of the irqchip driver
22 * @fn: initialization function
23 */
24#define IRQCHIP_DECLARE(name,compstr,fn) \
25 static const struct of_device_id irqchip_of_match_##name \
26 __used __section(__irqchip_of_table) \
27 = { .compatible = compstr, .data = fn }
28
29#endif
diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c
index 80e1d2fd9d4c..8527743b5cef 100644
--- a/drivers/irqchip/spear-shirq.c
+++ b/drivers/irqchip/spear-shirq.c
@@ -25,6 +25,8 @@
25#include <linux/of_irq.h> 25#include <linux/of_irq.h>
26#include <linux/spinlock.h> 26#include <linux/spinlock.h>
27 27
28#include "irqchip.h"
29
28static DEFINE_SPINLOCK(lock); 30static DEFINE_SPINLOCK(lock);
29 31
30/* spear300 shared irq registers offsets and masks */ 32/* spear300 shared irq registers offsets and masks */
@@ -300,6 +302,7 @@ int __init spear300_shirq_of_init(struct device_node *np,
300 return shirq_init(spear300_shirq_blocks, 302 return shirq_init(spear300_shirq_blocks,
301 ARRAY_SIZE(spear300_shirq_blocks), np); 303 ARRAY_SIZE(spear300_shirq_blocks), np);
302} 304}
305IRQCHIP_DECLARE(spear300_shirq, "st,spear300-shirq", spear300_shirq_of_init);
303 306
304int __init spear310_shirq_of_init(struct device_node *np, 307int __init spear310_shirq_of_init(struct device_node *np,
305 struct device_node *parent) 308 struct device_node *parent)
@@ -307,6 +310,7 @@ int __init spear310_shirq_of_init(struct device_node *np,
307 return shirq_init(spear310_shirq_blocks, 310 return shirq_init(spear310_shirq_blocks,
308 ARRAY_SIZE(spear310_shirq_blocks), np); 311 ARRAY_SIZE(spear310_shirq_blocks), np);
309} 312}
313IRQCHIP_DECLARE(spear310_shirq, "st,spear310-shirq", spear310_shirq_of_init);
310 314
311int __init spear320_shirq_of_init(struct device_node *np, 315int __init spear320_shirq_of_init(struct device_node *np,
312 struct device_node *parent) 316 struct device_node *parent)
@@ -314,3 +318,4 @@ int __init spear320_shirq_of_init(struct device_node *np,
314 return shirq_init(spear320_shirq_blocks, 318 return shirq_init(spear320_shirq_blocks,
315 ARRAY_SIZE(spear320_shirq_blocks), np); 319 ARRAY_SIZE(spear320_shirq_blocks), np);
316} 320}
321IRQCHIP_DECLARE(spear320_shirq, "st,spear320-shirq", spear320_shirq_of_init);