diff options
author | Heiko Stuebner <heiko@sntech.de> | 2013-04-04 01:53:33 -0400 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2013-04-04 01:55:43 -0400 |
commit | 8a407835bef6d47dcef9594d8c85900f994fbedf (patch) | |
tree | cee3276174c734b93adf3e730d1eb9329b66a0e5 /drivers/irqchip | |
parent | 17453dd2e7df20612770ebbf1ab5d506a432210c (diff) |
ARM: S3C24XX: move irq driver to drivers/irqchip
This move is necessary to make use of the irqchip infrastructure
for the following devicetree support for s3c24xx architectures.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/Makefile | 1 | ||||
-rw-r--r-- | drivers/irqchip/irq-s3c24xx.c | 1107 |
2 files changed, 1108 insertions, 0 deletions
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 98e3b87bdf1b..4d65a21eb9b8 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
@@ -2,6 +2,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o | |||
2 | 2 | ||
3 | obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o | 3 | obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o |
4 | obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o | 4 | obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o |
5 | obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o | ||
5 | obj-$(CONFIG_METAG) += irq-metag-ext.o | 6 | obj-$(CONFIG_METAG) += irq-metag-ext.o |
6 | obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o | 7 | obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o |
7 | obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o | 8 | obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o |
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c new file mode 100644 index 000000000000..5c9f8b7a1fd6 --- /dev/null +++ b/drivers/irqchip/irq-s3c24xx.c | |||
@@ -0,0 +1,1107 @@ | |||
1 | /* | ||
2 | * S3C24XX IRQ handling | ||
3 | * | ||
4 | * Copyright (c) 2003-2004 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * Copyright (c) 2012 Heiko Stuebner <heiko@sntech.de> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/init.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/irqdomain.h> | ||
28 | |||
29 | #include <asm/exception.h> | ||
30 | #include <asm/mach/irq.h> | ||
31 | |||
32 | #include <mach/regs-irq.h> | ||
33 | #include <mach/regs-gpio.h> | ||
34 | |||
35 | #include <plat/cpu.h> | ||
36 | #include <plat/regs-irqtype.h> | ||
37 | #include <plat/pm.h> | ||
38 | |||
39 | #define S3C_IRQTYPE_NONE 0 | ||
40 | #define S3C_IRQTYPE_EINT 1 | ||
41 | #define S3C_IRQTYPE_EDGE 2 | ||
42 | #define S3C_IRQTYPE_LEVEL 3 | ||
43 | |||
44 | struct s3c_irq_data { | ||
45 | unsigned int type; | ||
46 | unsigned long parent_irq; | ||
47 | |||
48 | /* data gets filled during init */ | ||
49 | struct s3c_irq_intc *intc; | ||
50 | unsigned long sub_bits; | ||
51 | struct s3c_irq_intc *sub_intc; | ||
52 | }; | ||
53 | |||
54 | /* | ||
55 | * Sructure holding the controller data | ||
56 | * @reg_pending register holding pending irqs | ||
57 | * @reg_intpnd special register intpnd in main intc | ||
58 | * @reg_mask mask register | ||
59 | * @domain irq_domain of the controller | ||
60 | * @parent parent controller for ext and sub irqs | ||
61 | * @irqs irq-data, always s3c_irq_data[32] | ||
62 | */ | ||
63 | struct s3c_irq_intc { | ||
64 | void __iomem *reg_pending; | ||
65 | void __iomem *reg_intpnd; | ||
66 | void __iomem *reg_mask; | ||
67 | struct irq_domain *domain; | ||
68 | struct s3c_irq_intc *parent; | ||
69 | struct s3c_irq_data *irqs; | ||
70 | }; | ||
71 | |||
72 | static void s3c_irq_mask(struct irq_data *data) | ||
73 | { | ||
74 | struct s3c_irq_intc *intc = data->domain->host_data; | ||
75 | struct s3c_irq_intc *parent_intc = intc->parent; | ||
76 | struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq]; | ||
77 | struct s3c_irq_data *parent_data; | ||
78 | unsigned long mask; | ||
79 | unsigned int irqno; | ||
80 | |||
81 | mask = __raw_readl(intc->reg_mask); | ||
82 | mask |= (1UL << data->hwirq); | ||
83 | __raw_writel(mask, intc->reg_mask); | ||
84 | |||
85 | if (parent_intc) { | ||
86 | parent_data = &parent_intc->irqs[irq_data->parent_irq]; | ||
87 | |||
88 | /* check to see if we need to mask the parent IRQ */ | ||
89 | if ((mask & parent_data->sub_bits) == parent_data->sub_bits) { | ||
90 | irqno = irq_find_mapping(parent_intc->domain, | ||
91 | irq_data->parent_irq); | ||
92 | s3c_irq_mask(irq_get_irq_data(irqno)); | ||
93 | } | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static void s3c_irq_unmask(struct irq_data *data) | ||
98 | { | ||
99 | struct s3c_irq_intc *intc = data->domain->host_data; | ||
100 | struct s3c_irq_intc *parent_intc = intc->parent; | ||
101 | struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq]; | ||
102 | unsigned long mask; | ||
103 | unsigned int irqno; | ||
104 | |||
105 | mask = __raw_readl(intc->reg_mask); | ||
106 | mask &= ~(1UL << data->hwirq); | ||
107 | __raw_writel(mask, intc->reg_mask); | ||
108 | |||
109 | if (parent_intc) { | ||
110 | irqno = irq_find_mapping(parent_intc->domain, | ||
111 | irq_data->parent_irq); | ||
112 | s3c_irq_unmask(irq_get_irq_data(irqno)); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | static inline void s3c_irq_ack(struct irq_data *data) | ||
117 | { | ||
118 | struct s3c_irq_intc *intc = data->domain->host_data; | ||
119 | unsigned long bitval = 1UL << data->hwirq; | ||
120 | |||
121 | __raw_writel(bitval, intc->reg_pending); | ||
122 | if (intc->reg_intpnd) | ||
123 | __raw_writel(bitval, intc->reg_intpnd); | ||
124 | } | ||
125 | |||
126 | static int s3c_irqext_type_set(void __iomem *gpcon_reg, | ||
127 | void __iomem *extint_reg, | ||
128 | unsigned long gpcon_offset, | ||
129 | unsigned long extint_offset, | ||
130 | unsigned int type) | ||
131 | { | ||
132 | unsigned long newvalue = 0, value; | ||
133 | |||
134 | /* Set the GPIO to external interrupt mode */ | ||
135 | value = __raw_readl(gpcon_reg); | ||
136 | value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset); | ||
137 | __raw_writel(value, gpcon_reg); | ||
138 | |||
139 | /* Set the external interrupt to pointed trigger type */ | ||
140 | switch (type) | ||
141 | { | ||
142 | case IRQ_TYPE_NONE: | ||
143 | pr_warn("No edge setting!\n"); | ||
144 | break; | ||
145 | |||
146 | case IRQ_TYPE_EDGE_RISING: | ||
147 | newvalue = S3C2410_EXTINT_RISEEDGE; | ||
148 | break; | ||
149 | |||
150 | case IRQ_TYPE_EDGE_FALLING: | ||
151 | newvalue = S3C2410_EXTINT_FALLEDGE; | ||
152 | break; | ||
153 | |||
154 | case IRQ_TYPE_EDGE_BOTH: | ||
155 | newvalue = S3C2410_EXTINT_BOTHEDGE; | ||
156 | break; | ||
157 | |||
158 | case IRQ_TYPE_LEVEL_LOW: | ||
159 | newvalue = S3C2410_EXTINT_LOWLEV; | ||
160 | break; | ||
161 | |||
162 | case IRQ_TYPE_LEVEL_HIGH: | ||
163 | newvalue = S3C2410_EXTINT_HILEV; | ||
164 | break; | ||
165 | |||
166 | default: | ||
167 | pr_err("No such irq type %d", type); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | value = __raw_readl(extint_reg); | ||
172 | value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset); | ||
173 | __raw_writel(value, extint_reg); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int s3c_irqext_type(struct irq_data *data, unsigned int type) | ||
179 | { | ||
180 | void __iomem *extint_reg; | ||
181 | void __iomem *gpcon_reg; | ||
182 | unsigned long gpcon_offset, extint_offset; | ||
183 | |||
184 | if ((data->hwirq >= 4) && (data->hwirq <= 7)) { | ||
185 | gpcon_reg = S3C2410_GPFCON; | ||
186 | extint_reg = S3C24XX_EXTINT0; | ||
187 | gpcon_offset = (data->hwirq) * 2; | ||
188 | extint_offset = (data->hwirq) * 4; | ||
189 | } else if ((data->hwirq >= 8) && (data->hwirq <= 15)) { | ||
190 | gpcon_reg = S3C2410_GPGCON; | ||
191 | extint_reg = S3C24XX_EXTINT1; | ||
192 | gpcon_offset = (data->hwirq - 8) * 2; | ||
193 | extint_offset = (data->hwirq - 8) * 4; | ||
194 | } else if ((data->hwirq >= 16) && (data->hwirq <= 23)) { | ||
195 | gpcon_reg = S3C2410_GPGCON; | ||
196 | extint_reg = S3C24XX_EXTINT2; | ||
197 | gpcon_offset = (data->hwirq - 8) * 2; | ||
198 | extint_offset = (data->hwirq - 16) * 4; | ||
199 | } else { | ||
200 | return -EINVAL; | ||
201 | } | ||
202 | |||
203 | return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset, | ||
204 | extint_offset, type); | ||
205 | } | ||
206 | |||
207 | static int s3c_irqext0_type(struct irq_data *data, unsigned int type) | ||
208 | { | ||
209 | void __iomem *extint_reg; | ||
210 | void __iomem *gpcon_reg; | ||
211 | unsigned long gpcon_offset, extint_offset; | ||
212 | |||
213 | if ((data->hwirq >= 0) && (data->hwirq <= 3)) { | ||
214 | gpcon_reg = S3C2410_GPFCON; | ||
215 | extint_reg = S3C24XX_EXTINT0; | ||
216 | gpcon_offset = (data->hwirq) * 2; | ||
217 | extint_offset = (data->hwirq) * 4; | ||
218 | } else { | ||
219 | return -EINVAL; | ||
220 | } | ||
221 | |||
222 | return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset, | ||
223 | extint_offset, type); | ||
224 | } | ||
225 | |||
226 | static struct irq_chip s3c_irq_chip = { | ||
227 | .name = "s3c", | ||
228 | .irq_ack = s3c_irq_ack, | ||
229 | .irq_mask = s3c_irq_mask, | ||
230 | .irq_unmask = s3c_irq_unmask, | ||
231 | .irq_set_wake = s3c_irq_wake | ||
232 | }; | ||
233 | |||
234 | static struct irq_chip s3c_irq_level_chip = { | ||
235 | .name = "s3c-level", | ||
236 | .irq_mask = s3c_irq_mask, | ||
237 | .irq_unmask = s3c_irq_unmask, | ||
238 | .irq_ack = s3c_irq_ack, | ||
239 | }; | ||
240 | |||
241 | static struct irq_chip s3c_irqext_chip = { | ||
242 | .name = "s3c-ext", | ||
243 | .irq_mask = s3c_irq_mask, | ||
244 | .irq_unmask = s3c_irq_unmask, | ||
245 | .irq_ack = s3c_irq_ack, | ||
246 | .irq_set_type = s3c_irqext_type, | ||
247 | .irq_set_wake = s3c_irqext_wake | ||
248 | }; | ||
249 | |||
250 | static struct irq_chip s3c_irq_eint0t4 = { | ||
251 | .name = "s3c-ext0", | ||
252 | .irq_ack = s3c_irq_ack, | ||
253 | .irq_mask = s3c_irq_mask, | ||
254 | .irq_unmask = s3c_irq_unmask, | ||
255 | .irq_set_wake = s3c_irq_wake, | ||
256 | .irq_set_type = s3c_irqext0_type, | ||
257 | }; | ||
258 | |||
259 | static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
260 | { | ||
261 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
262 | struct s3c_irq_intc *intc = desc->irq_data.domain->host_data; | ||
263 | struct s3c_irq_data *irq_data = &intc->irqs[desc->irq_data.hwirq]; | ||
264 | struct s3c_irq_intc *sub_intc = irq_data->sub_intc; | ||
265 | unsigned long src; | ||
266 | unsigned long msk; | ||
267 | unsigned int n; | ||
268 | |||
269 | chained_irq_enter(chip, desc); | ||
270 | |||
271 | src = __raw_readl(sub_intc->reg_pending); | ||
272 | msk = __raw_readl(sub_intc->reg_mask); | ||
273 | |||
274 | src &= ~msk; | ||
275 | src &= irq_data->sub_bits; | ||
276 | |||
277 | while (src) { | ||
278 | n = __ffs(src); | ||
279 | src &= ~(1 << n); | ||
280 | generic_handle_irq(irq_find_mapping(sub_intc->domain, n)); | ||
281 | } | ||
282 | |||
283 | chained_irq_exit(chip, desc); | ||
284 | } | ||
285 | |||
286 | static struct s3c_irq_intc *main_intc; | ||
287 | static struct s3c_irq_intc *main_intc2; | ||
288 | |||
289 | static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc, | ||
290 | struct pt_regs *regs) | ||
291 | { | ||
292 | int pnd; | ||
293 | int offset; | ||
294 | int irq; | ||
295 | |||
296 | pnd = __raw_readl(intc->reg_intpnd); | ||
297 | if (!pnd) | ||
298 | return false; | ||
299 | |||
300 | /* We have a problem that the INTOFFSET register does not always | ||
301 | * show one interrupt. Occasionally we get two interrupts through | ||
302 | * the prioritiser, and this causes the INTOFFSET register to show | ||
303 | * what looks like the logical-or of the two interrupt numbers. | ||
304 | * | ||
305 | * Thanks to Klaus, Shannon, et al for helping to debug this problem | ||
306 | */ | ||
307 | offset = __raw_readl(intc->reg_intpnd + 4); | ||
308 | |||
309 | /* Find the bit manually, when the offset is wrong. | ||
310 | * The pending register only ever contains the one bit of the next | ||
311 | * interrupt to handle. | ||
312 | */ | ||
313 | if (!(pnd & (1 << offset))) | ||
314 | offset = __ffs(pnd); | ||
315 | |||
316 | irq = irq_find_mapping(intc->domain, offset); | ||
317 | handle_IRQ(irq, regs); | ||
318 | return true; | ||
319 | } | ||
320 | |||
321 | asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs) | ||
322 | { | ||
323 | do { | ||
324 | if (likely(main_intc)) | ||
325 | if (s3c24xx_handle_intc(main_intc, regs)) | ||
326 | continue; | ||
327 | |||
328 | if (main_intc2) | ||
329 | if (s3c24xx_handle_intc(main_intc2, regs)) | ||
330 | continue; | ||
331 | |||
332 | break; | ||
333 | } while (1); | ||
334 | } | ||
335 | |||
336 | #ifdef CONFIG_FIQ | ||
337 | /** | ||
338 | * s3c24xx_set_fiq - set the FIQ routing | ||
339 | * @irq: IRQ number to route to FIQ on processor. | ||
340 | * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing. | ||
341 | * | ||
342 | * Change the state of the IRQ to FIQ routing depending on @irq and @on. If | ||
343 | * @on is true, the @irq is checked to see if it can be routed and the | ||
344 | * interrupt controller updated to route the IRQ. If @on is false, the FIQ | ||
345 | * routing is cleared, regardless of which @irq is specified. | ||
346 | */ | ||
347 | int s3c24xx_set_fiq(unsigned int irq, bool on) | ||
348 | { | ||
349 | u32 intmod; | ||
350 | unsigned offs; | ||
351 | |||
352 | if (on) { | ||
353 | offs = irq - FIQ_START; | ||
354 | if (offs > 31) | ||
355 | return -EINVAL; | ||
356 | |||
357 | intmod = 1 << offs; | ||
358 | } else { | ||
359 | intmod = 0; | ||
360 | } | ||
361 | |||
362 | __raw_writel(intmod, S3C2410_INTMOD); | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | EXPORT_SYMBOL_GPL(s3c24xx_set_fiq); | ||
367 | #endif | ||
368 | |||
369 | static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq, | ||
370 | irq_hw_number_t hw) | ||
371 | { | ||
372 | struct s3c_irq_intc *intc = h->host_data; | ||
373 | struct s3c_irq_data *irq_data = &intc->irqs[hw]; | ||
374 | struct s3c_irq_intc *parent_intc; | ||
375 | struct s3c_irq_data *parent_irq_data; | ||
376 | unsigned int irqno; | ||
377 | |||
378 | /* attach controller pointer to irq_data */ | ||
379 | irq_data->intc = intc; | ||
380 | |||
381 | parent_intc = intc->parent; | ||
382 | |||
383 | /* set handler and flags */ | ||
384 | switch (irq_data->type) { | ||
385 | case S3C_IRQTYPE_NONE: | ||
386 | return 0; | ||
387 | case S3C_IRQTYPE_EINT: | ||
388 | /* On the S3C2412, the EINT0to3 have a parent irq | ||
389 | * but need the s3c_irq_eint0t4 chip | ||
390 | */ | ||
391 | if (parent_intc && (!soc_is_s3c2412() || hw >= 4)) | ||
392 | irq_set_chip_and_handler(virq, &s3c_irqext_chip, | ||
393 | handle_edge_irq); | ||
394 | else | ||
395 | irq_set_chip_and_handler(virq, &s3c_irq_eint0t4, | ||
396 | handle_edge_irq); | ||
397 | break; | ||
398 | case S3C_IRQTYPE_EDGE: | ||
399 | if (parent_intc || intc->reg_pending == S3C2416_SRCPND2) | ||
400 | irq_set_chip_and_handler(virq, &s3c_irq_level_chip, | ||
401 | handle_edge_irq); | ||
402 | else | ||
403 | irq_set_chip_and_handler(virq, &s3c_irq_chip, | ||
404 | handle_edge_irq); | ||
405 | break; | ||
406 | case S3C_IRQTYPE_LEVEL: | ||
407 | if (parent_intc) | ||
408 | irq_set_chip_and_handler(virq, &s3c_irq_level_chip, | ||
409 | handle_level_irq); | ||
410 | else | ||
411 | irq_set_chip_and_handler(virq, &s3c_irq_chip, | ||
412 | handle_level_irq); | ||
413 | break; | ||
414 | default: | ||
415 | pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type); | ||
416 | return -EINVAL; | ||
417 | } | ||
418 | set_irq_flags(virq, IRQF_VALID); | ||
419 | |||
420 | if (parent_intc && irq_data->type != S3C_IRQTYPE_NONE) { | ||
421 | if (irq_data->parent_irq > 31) { | ||
422 | pr_err("irq-s3c24xx: parent irq %lu is out of range\n", | ||
423 | irq_data->parent_irq); | ||
424 | goto err; | ||
425 | } | ||
426 | |||
427 | parent_irq_data = &parent_intc->irqs[irq_data->parent_irq]; | ||
428 | parent_irq_data->sub_intc = intc; | ||
429 | parent_irq_data->sub_bits |= (1UL << hw); | ||
430 | |||
431 | /* attach the demuxer to the parent irq */ | ||
432 | irqno = irq_find_mapping(parent_intc->domain, | ||
433 | irq_data->parent_irq); | ||
434 | if (!irqno) { | ||
435 | pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n", | ||
436 | irq_data->parent_irq); | ||
437 | goto err; | ||
438 | } | ||
439 | irq_set_chained_handler(irqno, s3c_irq_demux); | ||
440 | } | ||
441 | |||
442 | return 0; | ||
443 | |||
444 | err: | ||
445 | set_irq_flags(virq, 0); | ||
446 | |||
447 | /* the only error can result from bad mapping data*/ | ||
448 | return -EINVAL; | ||
449 | } | ||
450 | |||
451 | static struct irq_domain_ops s3c24xx_irq_ops = { | ||
452 | .map = s3c24xx_irq_map, | ||
453 | .xlate = irq_domain_xlate_twocell, | ||
454 | }; | ||
455 | |||
456 | static void s3c24xx_clear_intc(struct s3c_irq_intc *intc) | ||
457 | { | ||
458 | void __iomem *reg_source; | ||
459 | unsigned long pend; | ||
460 | unsigned long last; | ||
461 | int i; | ||
462 | |||
463 | /* if intpnd is set, read the next pending irq from there */ | ||
464 | reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending; | ||
465 | |||
466 | last = 0; | ||
467 | for (i = 0; i < 4; i++) { | ||
468 | pend = __raw_readl(reg_source); | ||
469 | |||
470 | if (pend == 0 || pend == last) | ||
471 | break; | ||
472 | |||
473 | __raw_writel(pend, intc->reg_pending); | ||
474 | if (intc->reg_intpnd) | ||
475 | __raw_writel(pend, intc->reg_intpnd); | ||
476 | |||
477 | pr_info("irq: clearing pending status %08x\n", (int)pend); | ||
478 | last = pend; | ||
479 | } | ||
480 | } | ||
481 | |||
482 | static struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np, | ||
483 | struct s3c_irq_data *irq_data, | ||
484 | struct s3c_irq_intc *parent, | ||
485 | unsigned long address) | ||
486 | { | ||
487 | struct s3c_irq_intc *intc; | ||
488 | void __iomem *base = (void *)0xf6000000; /* static mapping */ | ||
489 | int irq_num; | ||
490 | int irq_start; | ||
491 | int ret; | ||
492 | |||
493 | intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL); | ||
494 | if (!intc) | ||
495 | return ERR_PTR(-ENOMEM); | ||
496 | |||
497 | intc->irqs = irq_data; | ||
498 | |||
499 | if (parent) | ||
500 | intc->parent = parent; | ||
501 | |||
502 | /* select the correct data for the controller. | ||
503 | * Need to hard code the irq num start and offset | ||
504 | * to preserve the static mapping for now | ||
505 | */ | ||
506 | switch (address) { | ||
507 | case 0x4a000000: | ||
508 | pr_debug("irq: found main intc\n"); | ||
509 | intc->reg_pending = base; | ||
510 | intc->reg_mask = base + 0x08; | ||
511 | intc->reg_intpnd = base + 0x10; | ||
512 | irq_num = 32; | ||
513 | irq_start = S3C2410_IRQ(0); | ||
514 | break; | ||
515 | case 0x4a000018: | ||
516 | pr_debug("irq: found subintc\n"); | ||
517 | intc->reg_pending = base + 0x18; | ||
518 | intc->reg_mask = base + 0x1c; | ||
519 | irq_num = 29; | ||
520 | irq_start = S3C2410_IRQSUB(0); | ||
521 | break; | ||
522 | case 0x4a000040: | ||
523 | pr_debug("irq: found intc2\n"); | ||
524 | intc->reg_pending = base + 0x40; | ||
525 | intc->reg_mask = base + 0x48; | ||
526 | intc->reg_intpnd = base + 0x50; | ||
527 | irq_num = 8; | ||
528 | irq_start = S3C2416_IRQ(0); | ||
529 | break; | ||
530 | case 0x560000a4: | ||
531 | pr_debug("irq: found eintc\n"); | ||
532 | base = (void *)0xfd000000; | ||
533 | |||
534 | intc->reg_mask = base + 0xa4; | ||
535 | intc->reg_pending = base + 0x08; | ||
536 | irq_num = 24; | ||
537 | irq_start = S3C2410_IRQ(32); | ||
538 | break; | ||
539 | default: | ||
540 | pr_err("irq: unsupported controller address\n"); | ||
541 | ret = -EINVAL; | ||
542 | goto err; | ||
543 | } | ||
544 | |||
545 | /* now that all the data is complete, init the irq-domain */ | ||
546 | s3c24xx_clear_intc(intc); | ||
547 | intc->domain = irq_domain_add_legacy(np, irq_num, irq_start, | ||
548 | 0, &s3c24xx_irq_ops, | ||
549 | intc); | ||
550 | if (!intc->domain) { | ||
551 | pr_err("irq: could not create irq-domain\n"); | ||
552 | ret = -EINVAL; | ||
553 | goto err; | ||
554 | } | ||
555 | |||
556 | if (address == 0x4a000000) | ||
557 | main_intc = intc; | ||
558 | else if (address == 0x4a000040) | ||
559 | main_intc2 = intc; | ||
560 | |||
561 | set_handle_irq(s3c24xx_handle_irq); | ||
562 | |||
563 | return intc; | ||
564 | |||
565 | err: | ||
566 | kfree(intc); | ||
567 | return ERR_PTR(ret); | ||
568 | } | ||
569 | |||
570 | static struct s3c_irq_data init_eint[32] = { | ||
571 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
572 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
573 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
574 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
575 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */ | ||
576 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */ | ||
577 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */ | ||
578 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */ | ||
579 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */ | ||
580 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */ | ||
581 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */ | ||
582 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */ | ||
583 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */ | ||
584 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */ | ||
585 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */ | ||
586 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */ | ||
587 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */ | ||
588 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */ | ||
589 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */ | ||
590 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */ | ||
591 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */ | ||
592 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */ | ||
593 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */ | ||
594 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */ | ||
595 | }; | ||
596 | |||
597 | #ifdef CONFIG_CPU_S3C2410 | ||
598 | static struct s3c_irq_data init_s3c2410base[32] = { | ||
599 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | ||
600 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ | ||
601 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ | ||
602 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ | ||
603 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
604 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
605 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
606 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
607 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
608 | { .type = S3C_IRQTYPE_EDGE, }, /* WDT */ | ||
609 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
610 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
611 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
612 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
613 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
614 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
615 | { .type = S3C_IRQTYPE_EDGE, }, /* LCD */ | ||
616 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */ | ||
617 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */ | ||
618 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */ | ||
619 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */ | ||
620 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI */ | ||
621 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
622 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
623 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
624 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
625 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
626 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
627 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
628 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ | ||
629 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
630 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
631 | }; | ||
632 | |||
633 | static struct s3c_irq_data init_s3c2410subint[32] = { | ||
634 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ | ||
635 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ | ||
636 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ | ||
637 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
638 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
639 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
640 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
641 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
642 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
643 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
644 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
645 | }; | ||
646 | |||
647 | void __init s3c2410_init_irq(void) | ||
648 | { | ||
649 | struct s3c_irq_intc *main_intc; | ||
650 | |||
651 | #ifdef CONFIG_FIQ | ||
652 | init_FIQ(FIQ_START); | ||
653 | #endif | ||
654 | |||
655 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2410base[0], NULL, 0x4a000000); | ||
656 | if (IS_ERR(main_intc)) { | ||
657 | pr_err("irq: could not create main interrupt controller\n"); | ||
658 | return; | ||
659 | } | ||
660 | |||
661 | s3c24xx_init_intc(NULL, &init_s3c2410subint[0], main_intc, 0x4a000018); | ||
662 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); | ||
663 | } | ||
664 | #endif | ||
665 | |||
666 | #ifdef CONFIG_CPU_S3C2412 | ||
667 | static struct s3c_irq_data init_s3c2412base[32] = { | ||
668 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT0 */ | ||
669 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT1 */ | ||
670 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT2 */ | ||
671 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT3 */ | ||
672 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
673 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
674 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
675 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
676 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
677 | { .type = S3C_IRQTYPE_EDGE, }, /* WDT */ | ||
678 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
679 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
680 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
681 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
682 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
683 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
684 | { .type = S3C_IRQTYPE_EDGE, }, /* LCD */ | ||
685 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */ | ||
686 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */ | ||
687 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */ | ||
688 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */ | ||
689 | { .type = S3C_IRQTYPE_LEVEL, }, /* SDI/CF */ | ||
690 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
691 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
692 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
693 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
694 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
695 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
696 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
697 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ | ||
698 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
699 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
700 | }; | ||
701 | |||
702 | static struct s3c_irq_data init_s3c2412eint[32] = { | ||
703 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 0 }, /* EINT0 */ | ||
704 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 1 }, /* EINT1 */ | ||
705 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 2 }, /* EINT2 */ | ||
706 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 3 }, /* EINT3 */ | ||
707 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */ | ||
708 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */ | ||
709 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */ | ||
710 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */ | ||
711 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */ | ||
712 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */ | ||
713 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */ | ||
714 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */ | ||
715 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */ | ||
716 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */ | ||
717 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */ | ||
718 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */ | ||
719 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */ | ||
720 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */ | ||
721 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */ | ||
722 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */ | ||
723 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */ | ||
724 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */ | ||
725 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */ | ||
726 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */ | ||
727 | }; | ||
728 | |||
729 | static struct s3c_irq_data init_s3c2412subint[32] = { | ||
730 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ | ||
731 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ | ||
732 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ | ||
733 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
734 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
735 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
736 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
737 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
738 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
739 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
740 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
741 | { .type = S3C_IRQTYPE_NONE, }, | ||
742 | { .type = S3C_IRQTYPE_NONE, }, | ||
743 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* SDI */ | ||
744 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */ | ||
745 | }; | ||
746 | |||
747 | void s3c2412_init_irq(void) | ||
748 | { | ||
749 | struct s3c_irq_intc *main_intc; | ||
750 | |||
751 | pr_info("S3C2412: IRQ Support\n"); | ||
752 | |||
753 | #ifdef CONFIG_FIQ | ||
754 | init_FIQ(FIQ_START); | ||
755 | #endif | ||
756 | |||
757 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2412base[0], NULL, 0x4a000000); | ||
758 | if (IS_ERR(main_intc)) { | ||
759 | pr_err("irq: could not create main interrupt controller\n"); | ||
760 | return; | ||
761 | } | ||
762 | |||
763 | s3c24xx_init_intc(NULL, &init_s3c2412eint[0], main_intc, 0x560000a4); | ||
764 | s3c24xx_init_intc(NULL, &init_s3c2412subint[0], main_intc, 0x4a000018); | ||
765 | } | ||
766 | #endif | ||
767 | |||
768 | #ifdef CONFIG_CPU_S3C2416 | ||
769 | static struct s3c_irq_data init_s3c2416base[32] = { | ||
770 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | ||
771 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ | ||
772 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ | ||
773 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ | ||
774 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
775 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
776 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
777 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
778 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
779 | { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */ | ||
780 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
781 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
782 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
783 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
784 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
785 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
786 | { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */ | ||
787 | { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */ | ||
788 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */ | ||
789 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
790 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */ | ||
791 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */ | ||
792 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
793 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
794 | { .type = S3C_IRQTYPE_EDGE, }, /* NAND */ | ||
795 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
796 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
797 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
798 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
799 | { .type = S3C_IRQTYPE_NONE, }, | ||
800 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
801 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
802 | }; | ||
803 | |||
804 | static struct s3c_irq_data init_s3c2416subint[32] = { | ||
805 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ | ||
806 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ | ||
807 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ | ||
808 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
809 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
810 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
811 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
812 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
813 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
814 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
815 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
816 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
817 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
818 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
819 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
820 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */ | ||
821 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */ | ||
822 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */ | ||
823 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */ | ||
824 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */ | ||
825 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */ | ||
826 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */ | ||
827 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */ | ||
828 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */ | ||
829 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */ | ||
830 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */ | ||
831 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */ | ||
832 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */ | ||
833 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */ | ||
834 | }; | ||
835 | |||
836 | static struct s3c_irq_data init_s3c2416_second[32] = { | ||
837 | { .type = S3C_IRQTYPE_EDGE }, /* 2D */ | ||
838 | { .type = S3C_IRQTYPE_EDGE }, /* IIC1 */ | ||
839 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
840 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
841 | { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */ | ||
842 | { .type = S3C_IRQTYPE_EDGE }, /* PCM1 */ | ||
843 | { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */ | ||
844 | { .type = S3C_IRQTYPE_EDGE }, /* I2S1 */ | ||
845 | }; | ||
846 | |||
847 | void __init s3c2416_init_irq(void) | ||
848 | { | ||
849 | struct s3c_irq_intc *main_intc; | ||
850 | |||
851 | pr_info("S3C2416: IRQ Support\n"); | ||
852 | |||
853 | #ifdef CONFIG_FIQ | ||
854 | init_FIQ(FIQ_START); | ||
855 | #endif | ||
856 | |||
857 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL, 0x4a000000); | ||
858 | if (IS_ERR(main_intc)) { | ||
859 | pr_err("irq: could not create main interrupt controller\n"); | ||
860 | return; | ||
861 | } | ||
862 | |||
863 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); | ||
864 | s3c24xx_init_intc(NULL, &init_s3c2416subint[0], main_intc, 0x4a000018); | ||
865 | |||
866 | s3c24xx_init_intc(NULL, &init_s3c2416_second[0], NULL, 0x4a000040); | ||
867 | } | ||
868 | |||
869 | #endif | ||
870 | |||
871 | #ifdef CONFIG_CPU_S3C2440 | ||
872 | static struct s3c_irq_data init_s3c2440base[32] = { | ||
873 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | ||
874 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ | ||
875 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ | ||
876 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ | ||
877 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
878 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
879 | { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */ | ||
880 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
881 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
882 | { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */ | ||
883 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
884 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
885 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
886 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
887 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
888 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
889 | { .type = S3C_IRQTYPE_EDGE, }, /* LCD */ | ||
890 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */ | ||
891 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */ | ||
892 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */ | ||
893 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */ | ||
894 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI */ | ||
895 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
896 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
897 | { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */ | ||
898 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
899 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
900 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
901 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
902 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ | ||
903 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
904 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
905 | }; | ||
906 | |||
907 | static struct s3c_irq_data init_s3c2440subint[32] = { | ||
908 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ | ||
909 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ | ||
910 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ | ||
911 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
912 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
913 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
914 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
915 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
916 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
917 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
918 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
919 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* TC */ | ||
920 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* ADC */ | ||
921 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */ | ||
922 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */ | ||
923 | }; | ||
924 | |||
925 | void __init s3c2440_init_irq(void) | ||
926 | { | ||
927 | struct s3c_irq_intc *main_intc; | ||
928 | |||
929 | pr_info("S3C2440: IRQ Support\n"); | ||
930 | |||
931 | #ifdef CONFIG_FIQ | ||
932 | init_FIQ(FIQ_START); | ||
933 | #endif | ||
934 | |||
935 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL, 0x4a000000); | ||
936 | if (IS_ERR(main_intc)) { | ||
937 | pr_err("irq: could not create main interrupt controller\n"); | ||
938 | return; | ||
939 | } | ||
940 | |||
941 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); | ||
942 | s3c24xx_init_intc(NULL, &init_s3c2440subint[0], main_intc, 0x4a000018); | ||
943 | } | ||
944 | #endif | ||
945 | |||
946 | #ifdef CONFIG_CPU_S3C2442 | ||
947 | static struct s3c_irq_data init_s3c2442base[32] = { | ||
948 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | ||
949 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ | ||
950 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ | ||
951 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ | ||
952 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
953 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
954 | { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */ | ||
955 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
956 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
957 | { .type = S3C_IRQTYPE_EDGE, }, /* WDT */ | ||
958 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
959 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
960 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
961 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
962 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
963 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
964 | { .type = S3C_IRQTYPE_EDGE, }, /* LCD */ | ||
965 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */ | ||
966 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */ | ||
967 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */ | ||
968 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */ | ||
969 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI */ | ||
970 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
971 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
972 | { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */ | ||
973 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
974 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
975 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
976 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
977 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ | ||
978 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
979 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
980 | }; | ||
981 | |||
982 | static struct s3c_irq_data init_s3c2442subint[32] = { | ||
983 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ | ||
984 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ | ||
985 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ | ||
986 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
987 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
988 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
989 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
990 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
991 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
992 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
993 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
994 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* TC */ | ||
995 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* ADC */ | ||
996 | }; | ||
997 | |||
998 | void __init s3c2442_init_irq(void) | ||
999 | { | ||
1000 | struct s3c_irq_intc *main_intc; | ||
1001 | |||
1002 | pr_info("S3C2442: IRQ Support\n"); | ||
1003 | |||
1004 | #ifdef CONFIG_FIQ | ||
1005 | init_FIQ(FIQ_START); | ||
1006 | #endif | ||
1007 | |||
1008 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2442base[0], NULL, 0x4a000000); | ||
1009 | if (IS_ERR(main_intc)) { | ||
1010 | pr_err("irq: could not create main interrupt controller\n"); | ||
1011 | return; | ||
1012 | } | ||
1013 | |||
1014 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); | ||
1015 | s3c24xx_init_intc(NULL, &init_s3c2442subint[0], main_intc, 0x4a000018); | ||
1016 | } | ||
1017 | #endif | ||
1018 | |||
1019 | #ifdef CONFIG_CPU_S3C2443 | ||
1020 | static struct s3c_irq_data init_s3c2443base[32] = { | ||
1021 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | ||
1022 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ | ||
1023 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ | ||
1024 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ | ||
1025 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
1026 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
1027 | { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */ | ||
1028 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
1029 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
1030 | { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */ | ||
1031 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
1032 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
1033 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
1034 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
1035 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
1036 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
1037 | { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */ | ||
1038 | { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */ | ||
1039 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */ | ||
1040 | { .type = S3C_IRQTYPE_EDGE, }, /* CFON */ | ||
1041 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */ | ||
1042 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */ | ||
1043 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
1044 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
1045 | { .type = S3C_IRQTYPE_EDGE, }, /* NAND */ | ||
1046 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
1047 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
1048 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
1049 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
1050 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ | ||
1051 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
1052 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
1053 | }; | ||
1054 | |||
1055 | |||
1056 | static struct s3c_irq_data init_s3c2443subint[32] = { | ||
1057 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ | ||
1058 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ | ||
1059 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ | ||
1060 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
1061 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
1062 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
1063 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
1064 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
1065 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
1066 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
1067 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
1068 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */ | ||
1069 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */ | ||
1070 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
1071 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */ | ||
1072 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */ | ||
1073 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */ | ||
1074 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */ | ||
1075 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */ | ||
1076 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */ | ||
1077 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */ | ||
1078 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */ | ||
1079 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */ | ||
1080 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */ | ||
1081 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */ | ||
1082 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */ | ||
1083 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */ | ||
1084 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */ | ||
1085 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */ | ||
1086 | }; | ||
1087 | |||
1088 | void __init s3c2443_init_irq(void) | ||
1089 | { | ||
1090 | struct s3c_irq_intc *main_intc; | ||
1091 | |||
1092 | pr_info("S3C2443: IRQ Support\n"); | ||
1093 | |||
1094 | #ifdef CONFIG_FIQ | ||
1095 | init_FIQ(FIQ_START); | ||
1096 | #endif | ||
1097 | |||
1098 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL, 0x4a000000); | ||
1099 | if (IS_ERR(main_intc)) { | ||
1100 | pr_err("irq: could not create main interrupt controller\n"); | ||
1101 | return; | ||
1102 | } | ||
1103 | |||
1104 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); | ||
1105 | s3c24xx_init_intc(NULL, &init_s3c2443subint[0], main_intc, 0x4a000018); | ||
1106 | } | ||
1107 | #endif | ||