diff options
author | Felipe Balbi <balbi@ti.com> | 2014-09-15 17:15:02 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2014-09-16 17:44:59 -0400 |
commit | 8598066cddd186809c4edf5aae5f018c00079e8c (patch) | |
tree | fa1eee6f1f4a4e2c7feb3905c655f70ff7461fc5 /arch/arm/mach-omap2 | |
parent | eaacabc0d9b637c82788c66955b4ba0efebd5500 (diff) |
arm: omap: irq: move irq.c to drivers/irqchip/
Just move the code over as it has no dependencies
on arch/arm/ anymore.
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap2/irq.c | 393 |
3 files changed, 2 insertions, 395 deletions
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 11ccf0b4e5c2..691d62a8a74b 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
@@ -86,6 +86,7 @@ config ARCH_OMAP2PLUS | |||
86 | select PINCTRL | 86 | select PINCTRL |
87 | select SOC_BUS | 87 | select SOC_BUS |
88 | select TI_PRIV_EDMA | 88 | select TI_PRIV_EDMA |
89 | select OMAP_IRQCHIP | ||
89 | help | 90 | help |
90 | Systems based on OMAP2, OMAP3, OMAP4 or OMAP5 | 91 | Systems based on OMAP2, OMAP3, OMAP4 or OMAP5 |
91 | 92 | ||
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 69bbcba8842f..0b6095c78af1 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile | |||
@@ -10,7 +10,6 @@ obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o gpmc.o timer.o pm.o \ | |||
10 | common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \ | 10 | common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \ |
11 | omap_device.o sram.o drm.o | 11 | omap_device.o sram.o drm.o |
12 | 12 | ||
13 | omap-2-3-common = irq.o | ||
14 | hwmod-common = omap_hwmod.o omap_hwmod_reset.o \ | 13 | hwmod-common = omap_hwmod.o omap_hwmod_reset.o \ |
15 | omap_hwmod_common_data.o | 14 | omap_hwmod_common_data.o |
16 | clock-common = clock.o clock_common_data.o \ | 15 | clock-common = clock.o clock_common_data.o \ |
@@ -20,7 +19,7 @@ secure-common = omap-smc.o omap-secure.o | |||
20 | obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common) | 19 | obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common) |
21 | obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common) | 20 | obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common) |
22 | obj-$(CONFIG_ARCH_OMAP4) += $(hwmod-common) $(secure-common) | 21 | obj-$(CONFIG_ARCH_OMAP4) += $(hwmod-common) $(secure-common) |
23 | obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common) | 22 | obj-$(CONFIG_SOC_AM33XX) += $(hwmod-common) |
24 | obj-$(CONFIG_SOC_OMAP5) += $(hwmod-common) $(secure-common) | 23 | obj-$(CONFIG_SOC_OMAP5) += $(hwmod-common) $(secure-common) |
25 | obj-$(CONFIG_SOC_AM43XX) += $(hwmod-common) $(secure-common) | 24 | obj-$(CONFIG_SOC_AM43XX) += $(hwmod-common) $(secure-common) |
26 | obj-$(CONFIG_SOC_DRA7XX) += $(hwmod-common) $(secure-common) | 25 | obj-$(CONFIG_SOC_DRA7XX) += $(hwmod-common) $(secure-common) |
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c deleted file mode 100644 index b2993e45e84c..000000000000 --- a/arch/arm/mach-omap2/irq.c +++ /dev/null | |||
@@ -1,393 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap2/irq.c | ||
3 | * | ||
4 | * Interrupt handler for OMAP2 boards. | ||
5 | * | ||
6 | * Copyright (C) 2005 Nokia Corporation | ||
7 | * Author: Paul Mundt <paul.mundt@nokia.com> | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/io.h> | ||
18 | |||
19 | #include <asm/exception.h> | ||
20 | #include <asm/mach/irq.h> | ||
21 | #include <linux/irqdomain.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_address.h> | ||
24 | #include <linux/of_irq.h> | ||
25 | |||
26 | #include "soc.h" | ||
27 | #include "common.h" | ||
28 | #include "../../drivers/irqchip/irqchip.h" | ||
29 | |||
30 | /* selected INTC register offsets */ | ||
31 | |||
32 | #define INTC_REVISION 0x0000 | ||
33 | #define INTC_SYSCONFIG 0x0010 | ||
34 | #define INTC_SYSSTATUS 0x0014 | ||
35 | #define INTC_SIR 0x0040 | ||
36 | #define INTC_CONTROL 0x0048 | ||
37 | #define INTC_PROTECTION 0x004C | ||
38 | #define INTC_IDLE 0x0050 | ||
39 | #define INTC_THRESHOLD 0x0068 | ||
40 | #define INTC_MIR0 0x0084 | ||
41 | #define INTC_MIR_CLEAR0 0x0088 | ||
42 | #define INTC_MIR_SET0 0x008c | ||
43 | #define INTC_PENDING_IRQ0 0x0098 | ||
44 | #define INTC_PENDING_IRQ1 0x00b8 | ||
45 | #define INTC_PENDING_IRQ2 0x00d8 | ||
46 | #define INTC_PENDING_IRQ3 0x00f8 | ||
47 | #define INTC_ILR0 0x0100 | ||
48 | |||
49 | #define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */ | ||
50 | #define INTCPS_NR_ILR_REGS 128 | ||
51 | #define INTCPS_NR_MIR_REGS 3 | ||
52 | |||
53 | /* | ||
54 | * OMAP2 has a number of different interrupt controllers, each interrupt | ||
55 | * controller is identified as its own "bank". Register definitions are | ||
56 | * fairly consistent for each bank, but not all registers are implemented | ||
57 | * for each bank.. when in doubt, consult the TRM. | ||
58 | */ | ||
59 | |||
60 | /* Structure to save interrupt controller context */ | ||
61 | struct omap_intc_regs { | ||
62 | u32 sysconfig; | ||
63 | u32 protection; | ||
64 | u32 idle; | ||
65 | u32 threshold; | ||
66 | u32 ilr[INTCPS_NR_ILR_REGS]; | ||
67 | u32 mir[INTCPS_NR_MIR_REGS]; | ||
68 | }; | ||
69 | static struct omap_intc_regs intc_context; | ||
70 | |||
71 | static struct irq_domain *domain; | ||
72 | static void __iomem *omap_irq_base; | ||
73 | static int omap_nr_pending = 3; | ||
74 | static int omap_nr_irqs = 96; | ||
75 | |||
76 | /* INTC bank register get/set */ | ||
77 | static void intc_writel(u32 reg, u32 val) | ||
78 | { | ||
79 | writel_relaxed(val, omap_irq_base + reg); | ||
80 | } | ||
81 | |||
82 | static u32 intc_readl(u32 reg) | ||
83 | { | ||
84 | return readl_relaxed(omap_irq_base + reg); | ||
85 | } | ||
86 | |||
87 | void omap_intc_save_context(void) | ||
88 | { | ||
89 | int i; | ||
90 | |||
91 | intc_context.sysconfig = | ||
92 | intc_readl(INTC_SYSCONFIG); | ||
93 | intc_context.protection = | ||
94 | intc_readl(INTC_PROTECTION); | ||
95 | intc_context.idle = | ||
96 | intc_readl(INTC_IDLE); | ||
97 | intc_context.threshold = | ||
98 | intc_readl(INTC_THRESHOLD); | ||
99 | |||
100 | for (i = 0; i < omap_nr_irqs; i++) | ||
101 | intc_context.ilr[i] = | ||
102 | intc_readl((INTC_ILR0 + 0x4 * i)); | ||
103 | for (i = 0; i < INTCPS_NR_MIR_REGS; i++) | ||
104 | intc_context.mir[i] = | ||
105 | intc_readl(INTC_MIR0 + (0x20 * i)); | ||
106 | } | ||
107 | |||
108 | void omap_intc_restore_context(void) | ||
109 | { | ||
110 | int i; | ||
111 | |||
112 | intc_writel(INTC_SYSCONFIG, intc_context.sysconfig); | ||
113 | intc_writel(INTC_PROTECTION, intc_context.protection); | ||
114 | intc_writel(INTC_IDLE, intc_context.idle); | ||
115 | intc_writel(INTC_THRESHOLD, intc_context.threshold); | ||
116 | |||
117 | for (i = 0; i < omap_nr_irqs; i++) | ||
118 | intc_writel(INTC_ILR0 + 0x4 * i, | ||
119 | intc_context.ilr[i]); | ||
120 | |||
121 | for (i = 0; i < INTCPS_NR_MIR_REGS; i++) | ||
122 | intc_writel(INTC_MIR0 + 0x20 * i, | ||
123 | intc_context.mir[i]); | ||
124 | /* MIRs are saved and restore with other PRCM registers */ | ||
125 | } | ||
126 | |||
127 | void omap3_intc_prepare_idle(void) | ||
128 | { | ||
129 | /* | ||
130 | * Disable autoidle as it can stall interrupt controller, | ||
131 | * cf. errata ID i540 for 3430 (all revisions up to 3.1.x) | ||
132 | */ | ||
133 | intc_writel(INTC_SYSCONFIG, 0); | ||
134 | } | ||
135 | |||
136 | void omap3_intc_resume_idle(void) | ||
137 | { | ||
138 | /* Re-enable autoidle */ | ||
139 | intc_writel(INTC_SYSCONFIG, 1); | ||
140 | } | ||
141 | |||
142 | /* XXX: FIQ and additional INTC support (only MPU at the moment) */ | ||
143 | static void omap_ack_irq(struct irq_data *d) | ||
144 | { | ||
145 | intc_writel(INTC_CONTROL, 0x1); | ||
146 | } | ||
147 | |||
148 | static void omap_mask_ack_irq(struct irq_data *d) | ||
149 | { | ||
150 | irq_gc_mask_disable_reg(d); | ||
151 | omap_ack_irq(d); | ||
152 | } | ||
153 | |||
154 | static void __init omap_irq_soft_reset(void) | ||
155 | { | ||
156 | unsigned long tmp; | ||
157 | |||
158 | tmp = intc_readl(INTC_REVISION) & 0xff; | ||
159 | |||
160 | pr_info("IRQ: Found an INTC at 0x%p (revision %ld.%ld) with %d interrupts\n", | ||
161 | omap_irq_base, tmp >> 4, tmp & 0xf, omap_nr_irqs); | ||
162 | |||
163 | tmp = intc_readl(INTC_SYSCONFIG); | ||
164 | tmp |= 1 << 1; /* soft reset */ | ||
165 | intc_writel(INTC_SYSCONFIG, tmp); | ||
166 | |||
167 | while (!(intc_readl(INTC_SYSSTATUS) & 0x1)) | ||
168 | /* Wait for reset to complete */; | ||
169 | |||
170 | /* Enable autoidle */ | ||
171 | intc_writel(INTC_SYSCONFIG, 1 << 0); | ||
172 | } | ||
173 | |||
174 | int omap_irq_pending(void) | ||
175 | { | ||
176 | int irq; | ||
177 | |||
178 | for (irq = 0; irq < omap_nr_irqs; irq += 32) | ||
179 | if (intc_readl(INTC_PENDING_IRQ0 + | ||
180 | ((irq >> 5) << 5))) | ||
181 | return 1; | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | void omap3_intc_suspend(void) | ||
186 | { | ||
187 | /* A pending interrupt would prevent OMAP from entering suspend */ | ||
188 | omap_ack_irq(NULL); | ||
189 | } | ||
190 | |||
191 | static int __init omap_alloc_gc_of(struct irq_domain *d, void __iomem *base) | ||
192 | { | ||
193 | int ret; | ||
194 | int i; | ||
195 | |||
196 | ret = irq_alloc_domain_generic_chips(d, 32, 1, "INTC", | ||
197 | handle_level_irq, IRQ_NOREQUEST | IRQ_NOPROBE, | ||
198 | IRQ_LEVEL, 0); | ||
199 | if (ret) { | ||
200 | pr_warn("Failed to allocate irq chips\n"); | ||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | for (i = 0; i < omap_nr_pending; i++) { | ||
205 | struct irq_chip_generic *gc; | ||
206 | struct irq_chip_type *ct; | ||
207 | |||
208 | gc = irq_get_domain_generic_chip(d, 32 * i); | ||
209 | gc->reg_base = base; | ||
210 | ct = gc->chip_types; | ||
211 | |||
212 | ct->type = IRQ_TYPE_LEVEL_MASK; | ||
213 | ct->handler = handle_level_irq; | ||
214 | |||
215 | ct->chip.irq_ack = omap_mask_ack_irq; | ||
216 | ct->chip.irq_mask = irq_gc_mask_disable_reg; | ||
217 | ct->chip.irq_unmask = irq_gc_unmask_enable_reg; | ||
218 | |||
219 | ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE; | ||
220 | |||
221 | ct->regs.enable = INTC_MIR_CLEAR0 + 32 * i; | ||
222 | ct->regs.disable = INTC_MIR_SET0 + 32 * i; | ||
223 | } | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static void __init omap_alloc_gc_legacy(void __iomem *base, | ||
229 | unsigned int irq_start, unsigned int num) | ||
230 | { | ||
231 | struct irq_chip_generic *gc; | ||
232 | struct irq_chip_type *ct; | ||
233 | |||
234 | gc = irq_alloc_generic_chip("INTC", 1, irq_start, base, | ||
235 | handle_level_irq); | ||
236 | ct = gc->chip_types; | ||
237 | ct->chip.irq_ack = omap_mask_ack_irq; | ||
238 | ct->chip.irq_mask = irq_gc_mask_disable_reg; | ||
239 | ct->chip.irq_unmask = irq_gc_unmask_enable_reg; | ||
240 | ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE; | ||
241 | |||
242 | ct->regs.enable = INTC_MIR_CLEAR0; | ||
243 | ct->regs.disable = INTC_MIR_SET0; | ||
244 | irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, | ||
245 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
246 | } | ||
247 | |||
248 | static int __init omap_init_irq_of(struct device_node *node) | ||
249 | { | ||
250 | int ret; | ||
251 | |||
252 | omap_irq_base = of_iomap(node, 0); | ||
253 | if (WARN_ON(!omap_irq_base)) | ||
254 | return -ENOMEM; | ||
255 | |||
256 | domain = irq_domain_add_linear(node, omap_nr_irqs, | ||
257 | &irq_generic_chip_ops, NULL); | ||
258 | |||
259 | omap_irq_soft_reset(); | ||
260 | |||
261 | ret = omap_alloc_gc_of(domain, omap_irq_base); | ||
262 | if (ret < 0) | ||
263 | irq_domain_remove(domain); | ||
264 | |||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | static int __init omap_init_irq_legacy(u32 base) | ||
269 | { | ||
270 | int j, irq_base; | ||
271 | |||
272 | omap_irq_base = ioremap(base, SZ_4K); | ||
273 | if (WARN_ON(!omap_irq_base)) | ||
274 | return -ENOMEM; | ||
275 | |||
276 | irq_base = irq_alloc_descs(-1, 0, omap_nr_irqs, 0); | ||
277 | if (irq_base < 0) { | ||
278 | pr_warn("Couldn't allocate IRQ numbers\n"); | ||
279 | irq_base = 0; | ||
280 | } | ||
281 | |||
282 | domain = irq_domain_add_legacy(NULL, omap_nr_irqs, irq_base, 0, | ||
283 | &irq_domain_simple_ops, NULL); | ||
284 | |||
285 | omap_irq_soft_reset(); | ||
286 | |||
287 | for (j = 0; j < omap_nr_irqs; j += 32) | ||
288 | omap_alloc_gc_legacy(omap_irq_base + j, j + irq_base, 32); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int __init omap_init_irq(u32 base, struct device_node *node) | ||
294 | { | ||
295 | if (node) | ||
296 | return omap_init_irq_of(node); | ||
297 | else | ||
298 | return omap_init_irq_legacy(base); | ||
299 | } | ||
300 | |||
301 | static asmlinkage void __exception_irq_entry | ||
302 | omap_intc_handle_irq(struct pt_regs *regs) | ||
303 | { | ||
304 | u32 irqnr = 0; | ||
305 | int handled_irq = 0; | ||
306 | int i; | ||
307 | |||
308 | do { | ||
309 | for (i = 0; i < omap_nr_pending; i++) { | ||
310 | irqnr = intc_readl(INTC_PENDING_IRQ0 + (0x20 * i)); | ||
311 | if (irqnr) | ||
312 | goto out; | ||
313 | } | ||
314 | |||
315 | out: | ||
316 | if (!irqnr) | ||
317 | break; | ||
318 | |||
319 | irqnr = intc_readl(INTC_SIR); | ||
320 | irqnr &= ACTIVEIRQ_MASK; | ||
321 | |||
322 | if (irqnr) { | ||
323 | irqnr = irq_find_mapping(domain, irqnr); | ||
324 | handle_IRQ(irqnr, regs); | ||
325 | handled_irq = 1; | ||
326 | } | ||
327 | } while (irqnr); | ||
328 | |||
329 | /* If an irq is masked or deasserted while active, we will | ||
330 | * keep ending up here with no irq handled. So remove it from | ||
331 | * the INTC with an ack.*/ | ||
332 | if (!handled_irq) | ||
333 | omap_ack_irq(NULL); | ||
334 | } | ||
335 | |||
336 | void __init omap2_init_irq(void) | ||
337 | { | ||
338 | omap_nr_irqs = 96; | ||
339 | omap_nr_pending = 3; | ||
340 | omap_init_irq(OMAP24XX_IC_BASE, NULL); | ||
341 | set_handle_irq(omap_intc_handle_irq); | ||
342 | } | ||
343 | |||
344 | void __init omap3_init_irq(void) | ||
345 | { | ||
346 | omap_nr_irqs = 96; | ||
347 | omap_nr_pending = 3; | ||
348 | omap_init_irq(OMAP34XX_IC_BASE, NULL); | ||
349 | set_handle_irq(omap_intc_handle_irq); | ||
350 | } | ||
351 | |||
352 | void __init ti81xx_init_irq(void) | ||
353 | { | ||
354 | omap_nr_irqs = 96; | ||
355 | omap_nr_pending = 4; | ||
356 | omap_init_irq(OMAP34XX_IC_BASE, NULL); | ||
357 | set_handle_irq(omap_intc_handle_irq); | ||
358 | } | ||
359 | |||
360 | static int __init intc_of_init(struct device_node *node, | ||
361 | struct device_node *parent) | ||
362 | { | ||
363 | struct resource res; | ||
364 | int ret; | ||
365 | |||
366 | omap_nr_pending = 3; | ||
367 | omap_nr_irqs = 96; | ||
368 | |||
369 | if (WARN_ON(!node)) | ||
370 | return -ENODEV; | ||
371 | |||
372 | if (of_address_to_resource(node, 0, &res)) { | ||
373 | WARN(1, "unable to get intc registers\n"); | ||
374 | return -EINVAL; | ||
375 | } | ||
376 | |||
377 | if (of_device_is_compatible(node, "ti,am33xx-intc")) { | ||
378 | omap_nr_irqs = 128; | ||
379 | omap_nr_pending = 4; | ||
380 | } | ||
381 | |||
382 | ret = omap_init_irq(-1, of_node_get(node)); | ||
383 | if (ret < 0) | ||
384 | return ret; | ||
385 | |||
386 | set_handle_irq(omap_intc_handle_irq); | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | IRQCHIP_DECLARE(omap2_intc, "ti,omap2-intc", intc_of_init); | ||
392 | IRQCHIP_DECLARE(omap3_intc, "ti,omap3-intc", intc_of_init); | ||
393 | IRQCHIP_DECLARE(am33xx_intc, "ti,am33xx-intc", intc_of_init); | ||