diff options
Diffstat (limited to 'arch/arm/mach-s3c24xx/irq.c')
-rw-r--r-- | arch/arm/mach-s3c24xx/irq.c | 822 |
1 files changed, 0 insertions, 822 deletions
diff --git a/arch/arm/mach-s3c24xx/irq.c b/arch/arm/mach-s3c24xx/irq.c deleted file mode 100644 index cb9f5e011e73..000000000000 --- a/arch/arm/mach-s3c24xx/irq.c +++ /dev/null | |||
@@ -1,822 +0,0 @@ | |||
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/mach/irq.h> | ||
30 | |||
31 | #include <mach/regs-irq.h> | ||
32 | #include <mach/regs-gpio.h> | ||
33 | |||
34 | #include <plat/cpu.h> | ||
35 | #include <plat/regs-irqtype.h> | ||
36 | #include <plat/pm.h> | ||
37 | #include <plat/irq.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 && irq_data->parent_irq) { | ||
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 && irq_data->parent_irq) { | ||
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 | /* FIXME: make static when it's out of plat-samsung/irq.h */ | ||
179 | int s3c_irqext_type(struct irq_data *data, unsigned int type) | ||
180 | { | ||
181 | void __iomem *extint_reg; | ||
182 | void __iomem *gpcon_reg; | ||
183 | unsigned long gpcon_offset, extint_offset; | ||
184 | |||
185 | if ((data->hwirq >= 4) && (data->hwirq <= 7)) { | ||
186 | gpcon_reg = S3C2410_GPFCON; | ||
187 | extint_reg = S3C24XX_EXTINT0; | ||
188 | gpcon_offset = (data->hwirq) * 2; | ||
189 | extint_offset = (data->hwirq) * 4; | ||
190 | } else if ((data->hwirq >= 8) && (data->hwirq <= 15)) { | ||
191 | gpcon_reg = S3C2410_GPGCON; | ||
192 | extint_reg = S3C24XX_EXTINT1; | ||
193 | gpcon_offset = (data->hwirq - 8) * 2; | ||
194 | extint_offset = (data->hwirq - 8) * 4; | ||
195 | } else if ((data->hwirq >= 16) && (data->hwirq <= 23)) { | ||
196 | gpcon_reg = S3C2410_GPGCON; | ||
197 | extint_reg = S3C24XX_EXTINT2; | ||
198 | gpcon_offset = (data->hwirq - 8) * 2; | ||
199 | extint_offset = (data->hwirq - 16) * 4; | ||
200 | } else { | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | |||
204 | return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset, | ||
205 | extint_offset, type); | ||
206 | } | ||
207 | |||
208 | static int s3c_irqext0_type(struct irq_data *data, unsigned int type) | ||
209 | { | ||
210 | void __iomem *extint_reg; | ||
211 | void __iomem *gpcon_reg; | ||
212 | unsigned long gpcon_offset, extint_offset; | ||
213 | |||
214 | if ((data->hwirq >= 0) && (data->hwirq <= 3)) { | ||
215 | gpcon_reg = S3C2410_GPFCON; | ||
216 | extint_reg = S3C24XX_EXTINT0; | ||
217 | gpcon_offset = (data->hwirq) * 2; | ||
218 | extint_offset = (data->hwirq) * 4; | ||
219 | } else { | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
223 | return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset, | ||
224 | extint_offset, type); | ||
225 | } | ||
226 | |||
227 | struct irq_chip s3c_irq_chip = { | ||
228 | .name = "s3c", | ||
229 | .irq_ack = s3c_irq_ack, | ||
230 | .irq_mask = s3c_irq_mask, | ||
231 | .irq_unmask = s3c_irq_unmask, | ||
232 | .irq_set_wake = s3c_irq_wake | ||
233 | }; | ||
234 | |||
235 | struct irq_chip s3c_irq_level_chip = { | ||
236 | .name = "s3c-level", | ||
237 | .irq_mask = s3c_irq_mask, | ||
238 | .irq_unmask = s3c_irq_unmask, | ||
239 | .irq_ack = s3c_irq_ack, | ||
240 | }; | ||
241 | |||
242 | static struct irq_chip s3c_irqext_chip = { | ||
243 | .name = "s3c-ext", | ||
244 | .irq_mask = s3c_irq_mask, | ||
245 | .irq_unmask = s3c_irq_unmask, | ||
246 | .irq_ack = s3c_irq_ack, | ||
247 | .irq_set_type = s3c_irqext_type, | ||
248 | .irq_set_wake = s3c_irqext_wake | ||
249 | }; | ||
250 | |||
251 | static struct irq_chip s3c_irq_eint0t4 = { | ||
252 | .name = "s3c-ext0", | ||
253 | .irq_ack = s3c_irq_ack, | ||
254 | .irq_mask = s3c_irq_mask, | ||
255 | .irq_unmask = s3c_irq_unmask, | ||
256 | .irq_set_wake = s3c_irq_wake, | ||
257 | .irq_set_type = s3c_irqext0_type, | ||
258 | }; | ||
259 | |||
260 | static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
261 | { | ||
262 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
263 | struct s3c_irq_intc *intc = desc->irq_data.domain->host_data; | ||
264 | struct s3c_irq_data *irq_data = &intc->irqs[desc->irq_data.hwirq]; | ||
265 | struct s3c_irq_intc *sub_intc = irq_data->sub_intc; | ||
266 | unsigned long src; | ||
267 | unsigned long msk; | ||
268 | unsigned int n; | ||
269 | |||
270 | chained_irq_enter(chip, desc); | ||
271 | |||
272 | src = __raw_readl(sub_intc->reg_pending); | ||
273 | msk = __raw_readl(sub_intc->reg_mask); | ||
274 | |||
275 | src &= ~msk; | ||
276 | src &= irq_data->sub_bits; | ||
277 | |||
278 | while (src) { | ||
279 | n = __ffs(src); | ||
280 | src &= ~(1 << n); | ||
281 | generic_handle_irq(irq_find_mapping(sub_intc->domain, n)); | ||
282 | } | ||
283 | |||
284 | chained_irq_exit(chip, desc); | ||
285 | } | ||
286 | |||
287 | #ifdef CONFIG_FIQ | ||
288 | /** | ||
289 | * s3c24xx_set_fiq - set the FIQ routing | ||
290 | * @irq: IRQ number to route to FIQ on processor. | ||
291 | * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing. | ||
292 | * | ||
293 | * Change the state of the IRQ to FIQ routing depending on @irq and @on. If | ||
294 | * @on is true, the @irq is checked to see if it can be routed and the | ||
295 | * interrupt controller updated to route the IRQ. If @on is false, the FIQ | ||
296 | * routing is cleared, regardless of which @irq is specified. | ||
297 | */ | ||
298 | int s3c24xx_set_fiq(unsigned int irq, bool on) | ||
299 | { | ||
300 | u32 intmod; | ||
301 | unsigned offs; | ||
302 | |||
303 | if (on) { | ||
304 | offs = irq - FIQ_START; | ||
305 | if (offs > 31) | ||
306 | return -EINVAL; | ||
307 | |||
308 | intmod = 1 << offs; | ||
309 | } else { | ||
310 | intmod = 0; | ||
311 | } | ||
312 | |||
313 | __raw_writel(intmod, S3C2410_INTMOD); | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | EXPORT_SYMBOL_GPL(s3c24xx_set_fiq); | ||
318 | #endif | ||
319 | |||
320 | static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq, | ||
321 | irq_hw_number_t hw) | ||
322 | { | ||
323 | struct s3c_irq_intc *intc = h->host_data; | ||
324 | struct s3c_irq_data *irq_data = &intc->irqs[hw]; | ||
325 | struct s3c_irq_intc *parent_intc; | ||
326 | struct s3c_irq_data *parent_irq_data; | ||
327 | unsigned int irqno; | ||
328 | |||
329 | if (!intc) { | ||
330 | pr_err("irq-s3c24xx: no controller found for hwirq %lu\n", hw); | ||
331 | return -EINVAL; | ||
332 | } | ||
333 | |||
334 | if (!irq_data) { | ||
335 | pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", hw); | ||
336 | return -EINVAL; | ||
337 | } | ||
338 | |||
339 | /* attach controller pointer to irq_data */ | ||
340 | irq_data->intc = intc; | ||
341 | |||
342 | /* set handler and flags */ | ||
343 | switch (irq_data->type) { | ||
344 | case S3C_IRQTYPE_NONE: | ||
345 | return 0; | ||
346 | case S3C_IRQTYPE_EINT: | ||
347 | if (irq_data->parent_irq) | ||
348 | irq_set_chip_and_handler(virq, &s3c_irqext_chip, | ||
349 | handle_edge_irq); | ||
350 | else | ||
351 | irq_set_chip_and_handler(virq, &s3c_irq_eint0t4, | ||
352 | handle_edge_irq); | ||
353 | break; | ||
354 | case S3C_IRQTYPE_EDGE: | ||
355 | if (irq_data->parent_irq || | ||
356 | intc->reg_pending == S3C2416_SRCPND2) | ||
357 | irq_set_chip_and_handler(virq, &s3c_irq_level_chip, | ||
358 | handle_edge_irq); | ||
359 | else | ||
360 | irq_set_chip_and_handler(virq, &s3c_irq_chip, | ||
361 | handle_edge_irq); | ||
362 | break; | ||
363 | case S3C_IRQTYPE_LEVEL: | ||
364 | if (irq_data->parent_irq) | ||
365 | irq_set_chip_and_handler(virq, &s3c_irq_level_chip, | ||
366 | handle_level_irq); | ||
367 | else | ||
368 | irq_set_chip_and_handler(virq, &s3c_irq_chip, | ||
369 | handle_level_irq); | ||
370 | break; | ||
371 | default: | ||
372 | pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type); | ||
373 | return -EINVAL; | ||
374 | } | ||
375 | set_irq_flags(virq, IRQF_VALID); | ||
376 | |||
377 | if (irq_data->parent_irq) { | ||
378 | parent_intc = intc->parent; | ||
379 | if (!parent_intc) { | ||
380 | pr_err("irq-s3c24xx: no parent controller found for hwirq %lu\n", | ||
381 | hw); | ||
382 | goto err; | ||
383 | } | ||
384 | |||
385 | parent_irq_data = &parent_intc->irqs[irq_data->parent_irq]; | ||
386 | if (!irq_data) { | ||
387 | pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", | ||
388 | hw); | ||
389 | goto err; | ||
390 | } | ||
391 | |||
392 | parent_irq_data->sub_intc = intc; | ||
393 | parent_irq_data->sub_bits |= (1UL << hw); | ||
394 | |||
395 | /* attach the demuxer to the parent irq */ | ||
396 | irqno = irq_find_mapping(parent_intc->domain, | ||
397 | irq_data->parent_irq); | ||
398 | if (!irqno) { | ||
399 | pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n", | ||
400 | irq_data->parent_irq); | ||
401 | goto err; | ||
402 | } | ||
403 | irq_set_chained_handler(irqno, s3c_irq_demux); | ||
404 | } | ||
405 | |||
406 | return 0; | ||
407 | |||
408 | err: | ||
409 | set_irq_flags(virq, 0); | ||
410 | |||
411 | /* the only error can result from bad mapping data*/ | ||
412 | return -EINVAL; | ||
413 | } | ||
414 | |||
415 | static struct irq_domain_ops s3c24xx_irq_ops = { | ||
416 | .map = s3c24xx_irq_map, | ||
417 | .xlate = irq_domain_xlate_twocell, | ||
418 | }; | ||
419 | |||
420 | static void s3c24xx_clear_intc(struct s3c_irq_intc *intc) | ||
421 | { | ||
422 | void __iomem *reg_source; | ||
423 | unsigned long pend; | ||
424 | unsigned long last; | ||
425 | int i; | ||
426 | |||
427 | /* if intpnd is set, read the next pending irq from there */ | ||
428 | reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending; | ||
429 | |||
430 | last = 0; | ||
431 | for (i = 0; i < 4; i++) { | ||
432 | pend = __raw_readl(reg_source); | ||
433 | |||
434 | if (pend == 0 || pend == last) | ||
435 | break; | ||
436 | |||
437 | __raw_writel(pend, intc->reg_pending); | ||
438 | if (intc->reg_intpnd) | ||
439 | __raw_writel(pend, intc->reg_intpnd); | ||
440 | |||
441 | pr_info("irq: clearing pending status %08x\n", (int)pend); | ||
442 | last = pend; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np, | ||
447 | struct s3c_irq_data *irq_data, | ||
448 | struct s3c_irq_intc *parent, | ||
449 | unsigned long address) | ||
450 | { | ||
451 | struct s3c_irq_intc *intc; | ||
452 | void __iomem *base = (void *)0xf6000000; /* static mapping */ | ||
453 | int irq_num; | ||
454 | int irq_start; | ||
455 | int irq_offset; | ||
456 | int ret; | ||
457 | |||
458 | intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL); | ||
459 | if (!intc) | ||
460 | return ERR_PTR(-ENOMEM); | ||
461 | |||
462 | intc->irqs = irq_data; | ||
463 | |||
464 | if (parent) | ||
465 | intc->parent = parent; | ||
466 | |||
467 | /* select the correct data for the controller. | ||
468 | * Need to hard code the irq num start and offset | ||
469 | * to preserve the static mapping for now | ||
470 | */ | ||
471 | switch (address) { | ||
472 | case 0x4a000000: | ||
473 | pr_debug("irq: found main intc\n"); | ||
474 | intc->reg_pending = base; | ||
475 | intc->reg_mask = base + 0x08; | ||
476 | intc->reg_intpnd = base + 0x10; | ||
477 | irq_num = 32; | ||
478 | irq_start = S3C2410_IRQ(0); | ||
479 | irq_offset = 0; | ||
480 | break; | ||
481 | case 0x4a000018: | ||
482 | pr_debug("irq: found subintc\n"); | ||
483 | intc->reg_pending = base + 0x18; | ||
484 | intc->reg_mask = base + 0x1c; | ||
485 | irq_num = 29; | ||
486 | irq_start = S3C2410_IRQSUB(0); | ||
487 | irq_offset = 0; | ||
488 | break; | ||
489 | case 0x4a000040: | ||
490 | pr_debug("irq: found intc2\n"); | ||
491 | intc->reg_pending = base + 0x40; | ||
492 | intc->reg_mask = base + 0x48; | ||
493 | intc->reg_intpnd = base + 0x50; | ||
494 | irq_num = 8; | ||
495 | irq_start = S3C2416_IRQ(0); | ||
496 | irq_offset = 0; | ||
497 | break; | ||
498 | case 0x560000a4: | ||
499 | pr_debug("irq: found eintc\n"); | ||
500 | base = (void *)0xfd000000; | ||
501 | |||
502 | intc->reg_mask = base + 0xa4; | ||
503 | intc->reg_pending = base + 0x08; | ||
504 | irq_num = 20; | ||
505 | irq_start = S3C2410_IRQ(32); | ||
506 | irq_offset = 4; | ||
507 | break; | ||
508 | default: | ||
509 | pr_err("irq: unsupported controller address\n"); | ||
510 | ret = -EINVAL; | ||
511 | goto err; | ||
512 | } | ||
513 | |||
514 | /* now that all the data is complete, init the irq-domain */ | ||
515 | s3c24xx_clear_intc(intc); | ||
516 | intc->domain = irq_domain_add_legacy(np, irq_num, irq_start, | ||
517 | irq_offset, &s3c24xx_irq_ops, | ||
518 | intc); | ||
519 | if (!intc->domain) { | ||
520 | pr_err("irq: could not create irq-domain\n"); | ||
521 | ret = -EINVAL; | ||
522 | goto err; | ||
523 | } | ||
524 | |||
525 | return intc; | ||
526 | |||
527 | err: | ||
528 | kfree(intc); | ||
529 | return ERR_PTR(ret); | ||
530 | } | ||
531 | |||
532 | /* s3c24xx_init_irq | ||
533 | * | ||
534 | * Initialise S3C2410 IRQ system | ||
535 | */ | ||
536 | |||
537 | static struct s3c_irq_data init_base[32] = { | ||
538 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | ||
539 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ | ||
540 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ | ||
541 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ | ||
542 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
543 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
544 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
545 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
546 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
547 | { .type = S3C_IRQTYPE_EDGE, }, /* WDT */ | ||
548 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
549 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
550 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
551 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
552 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
553 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
554 | { .type = S3C_IRQTYPE_EDGE, }, /* LCD */ | ||
555 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */ | ||
556 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */ | ||
557 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */ | ||
558 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */ | ||
559 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI */ | ||
560 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
561 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
562 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
563 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
564 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
565 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
566 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
567 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ | ||
568 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
569 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
570 | }; | ||
571 | |||
572 | static struct s3c_irq_data init_eint[32] = { | ||
573 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
574 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
575 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
576 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
577 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */ | ||
578 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */ | ||
579 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */ | ||
580 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */ | ||
581 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */ | ||
582 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */ | ||
583 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */ | ||
584 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */ | ||
585 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */ | ||
586 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */ | ||
587 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */ | ||
588 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */ | ||
589 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */ | ||
590 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */ | ||
591 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */ | ||
592 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */ | ||
593 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */ | ||
594 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */ | ||
595 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */ | ||
596 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */ | ||
597 | }; | ||
598 | |||
599 | static struct s3c_irq_data init_subint[32] = { | ||
600 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ | ||
601 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ | ||
602 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ | ||
603 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
604 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
605 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
606 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
607 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
608 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
609 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
610 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
611 | }; | ||
612 | |||
613 | void __init s3c24xx_init_irq(void) | ||
614 | { | ||
615 | struct s3c_irq_intc *main_intc; | ||
616 | |||
617 | #ifdef CONFIG_FIQ | ||
618 | init_FIQ(FIQ_START); | ||
619 | #endif | ||
620 | |||
621 | main_intc = s3c24xx_init_intc(NULL, &init_base[0], NULL, 0x4a000000); | ||
622 | if (IS_ERR(main_intc)) { | ||
623 | pr_err("irq: could not create main interrupt controller\n"); | ||
624 | return; | ||
625 | } | ||
626 | |||
627 | s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018); | ||
628 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); | ||
629 | } | ||
630 | |||
631 | #ifdef CONFIG_CPU_S3C2416 | ||
632 | static struct s3c_irq_data init_s3c2416base[32] = { | ||
633 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | ||
634 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ | ||
635 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ | ||
636 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ | ||
637 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
638 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
639 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
640 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
641 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
642 | { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */ | ||
643 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
644 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
645 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
646 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
647 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
648 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
649 | { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */ | ||
650 | { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */ | ||
651 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */ | ||
652 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
653 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */ | ||
654 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */ | ||
655 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
656 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
657 | { .type = S3C_IRQTYPE_EDGE, }, /* NAND */ | ||
658 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
659 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
660 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
661 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
662 | { .type = S3C_IRQTYPE_NONE, }, | ||
663 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
664 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
665 | }; | ||
666 | |||
667 | static struct s3c_irq_data init_s3c2416subint[32] = { | ||
668 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ | ||
669 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ | ||
670 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ | ||
671 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
672 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
673 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
674 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
675 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
676 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
677 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
678 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
679 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
680 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
681 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
682 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
683 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */ | ||
684 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */ | ||
685 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */ | ||
686 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */ | ||
687 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */ | ||
688 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */ | ||
689 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */ | ||
690 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */ | ||
691 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */ | ||
692 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */ | ||
693 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */ | ||
694 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */ | ||
695 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */ | ||
696 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */ | ||
697 | }; | ||
698 | |||
699 | static struct s3c_irq_data init_s3c2416_second[32] = { | ||
700 | { .type = S3C_IRQTYPE_EDGE }, /* 2D */ | ||
701 | { .type = S3C_IRQTYPE_EDGE }, /* IIC1 */ | ||
702 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
703 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
704 | { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */ | ||
705 | { .type = S3C_IRQTYPE_EDGE }, /* PCM1 */ | ||
706 | { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */ | ||
707 | { .type = S3C_IRQTYPE_EDGE }, /* I2S1 */ | ||
708 | }; | ||
709 | |||
710 | void __init s3c2416_init_irq(void) | ||
711 | { | ||
712 | struct s3c_irq_intc *main_intc; | ||
713 | |||
714 | pr_info("S3C2416: IRQ Support\n"); | ||
715 | |||
716 | #ifdef CONFIG_FIQ | ||
717 | init_FIQ(FIQ_START); | ||
718 | #endif | ||
719 | |||
720 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL, 0x4a000000); | ||
721 | if (IS_ERR(main_intc)) { | ||
722 | pr_err("irq: could not create main interrupt controller\n"); | ||
723 | return; | ||
724 | } | ||
725 | |||
726 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); | ||
727 | s3c24xx_init_intc(NULL, &init_s3c2416subint[0], main_intc, 0x4a000018); | ||
728 | |||
729 | s3c24xx_init_intc(NULL, &init_s3c2416_second[0], NULL, 0x4a000040); | ||
730 | } | ||
731 | |||
732 | #endif | ||
733 | |||
734 | #ifdef CONFIG_CPU_S3C2443 | ||
735 | static struct s3c_irq_data init_s3c2443base[32] = { | ||
736 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | ||
737 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ | ||
738 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ | ||
739 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ | ||
740 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
741 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
742 | { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */ | ||
743 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
744 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
745 | { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */ | ||
746 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
747 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
748 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
749 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
750 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
751 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
752 | { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */ | ||
753 | { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */ | ||
754 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */ | ||
755 | { .type = S3C_IRQTYPE_EDGE, }, /* CFON */ | ||
756 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */ | ||
757 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */ | ||
758 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
759 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
760 | { .type = S3C_IRQTYPE_EDGE, }, /* NAND */ | ||
761 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
762 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
763 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
764 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
765 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ | ||
766 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
767 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
768 | }; | ||
769 | |||
770 | |||
771 | static struct s3c_irq_data init_s3c2443subint[32] = { | ||
772 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ | ||
773 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ | ||
774 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ | ||
775 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
776 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
777 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
778 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
779 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
780 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
781 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
782 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
783 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */ | ||
784 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */ | ||
785 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
786 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */ | ||
787 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */ | ||
788 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */ | ||
789 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */ | ||
790 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */ | ||
791 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */ | ||
792 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */ | ||
793 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */ | ||
794 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */ | ||
795 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */ | ||
796 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */ | ||
797 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */ | ||
798 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */ | ||
799 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */ | ||
800 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */ | ||
801 | }; | ||
802 | |||
803 | void __init s3c2443_init_irq(void) | ||
804 | { | ||
805 | struct s3c_irq_intc *main_intc; | ||
806 | |||
807 | pr_info("S3C2443: IRQ Support\n"); | ||
808 | |||
809 | #ifdef CONFIG_FIQ | ||
810 | init_FIQ(FIQ_START); | ||
811 | #endif | ||
812 | |||
813 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL, 0x4a000000); | ||
814 | if (IS_ERR(main_intc)) { | ||
815 | pr_err("irq: could not create main interrupt controller\n"); | ||
816 | return; | ||
817 | } | ||
818 | |||
819 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); | ||
820 | s3c24xx_init_intc(NULL, &init_s3c2443subint[0], main_intc, 0x4a000018); | ||
821 | } | ||
822 | #endif | ||