1
2
3
4
5
6
7
8
9
10#include <linux/init.h>
11#include <linux/slab.h>
12#include <linux/module.h>
13#include <linux/io.h>
14#include <linux/err.h>
15#include <linux/interrupt.h>
16#include <linux/ioport.h>
17#include <linux/device.h>
18#include <linux/irqdomain.h>
19#include <linux/irqchip.h>
20#include <linux/irqchip/chained_irq.h>
21#include <linux/of.h>
22#include <linux/of_irq.h>
23#include <linux/of_address.h>
24#include <linux/spi/s3c24xx.h>
25
26#include <asm/exception.h>
27#include <asm/mach/irq.h>
28
29#include <mach/irqs.h>
30#include "regs-irq.h"
31#include "regs-gpio.h"
32
33#include "cpu.h"
34#include "regs-irqtype.h"
35#include "pm.h"
36#include "s3c24xx.h"
37
38#define S3C_IRQTYPE_NONE 0
39#define S3C_IRQTYPE_EINT 1
40#define S3C_IRQTYPE_EDGE 2
41#define S3C_IRQTYPE_LEVEL 3
42
43struct s3c_irq_data {
44 unsigned int type;
45 unsigned long offset;
46 unsigned long parent_irq;
47
48
49 struct s3c_irq_intc *intc;
50 unsigned long sub_bits;
51 struct s3c_irq_intc *sub_intc;
52};
53
54
55
56
57
58
59
60
61
62
63struct 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
73
74
75
76
77
78static struct s3c_irq_intc *s3c_intc[3];
79
80static void s3c_irq_mask(struct irq_data *data)
81{
82 struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
83 struct s3c_irq_intc *intc = irq_data->intc;
84 struct s3c_irq_intc *parent_intc = intc->parent;
85 struct s3c_irq_data *parent_data;
86 unsigned long mask;
87 unsigned int irqno;
88
89 mask = readl_relaxed(intc->reg_mask);
90 mask |= (1UL << irq_data->offset);
91 writel_relaxed(mask, intc->reg_mask);
92
93 if (parent_intc) {
94 parent_data = &parent_intc->irqs[irq_data->parent_irq];
95
96
97
98
99
100 if ((mask & parent_data->sub_bits) == parent_data->sub_bits) {
101 irqno = irq_find_mapping(parent_intc->domain,
102 irq_data->parent_irq);
103 s3c_irq_mask(irq_get_irq_data(irqno));
104 }
105 }
106}
107
108static void s3c_irq_unmask(struct irq_data *data)
109{
110 struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
111 struct s3c_irq_intc *intc = irq_data->intc;
112 struct s3c_irq_intc *parent_intc = intc->parent;
113 unsigned long mask;
114 unsigned int irqno;
115
116 mask = readl_relaxed(intc->reg_mask);
117 mask &= ~(1UL << irq_data->offset);
118 writel_relaxed(mask, intc->reg_mask);
119
120 if (parent_intc) {
121 irqno = irq_find_mapping(parent_intc->domain,
122 irq_data->parent_irq);
123 s3c_irq_unmask(irq_get_irq_data(irqno));
124 }
125}
126
127static inline void s3c_irq_ack(struct irq_data *data)
128{
129 struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
130 struct s3c_irq_intc *intc = irq_data->intc;
131 unsigned long bitval = 1UL << irq_data->offset;
132
133 writel_relaxed(bitval, intc->reg_pending);
134 if (intc->reg_intpnd)
135 writel_relaxed(bitval, intc->reg_intpnd);
136}
137
138static int s3c_irq_type(struct irq_data *data, unsigned int type)
139{
140 switch (type) {
141 case IRQ_TYPE_NONE:
142 break;
143 case IRQ_TYPE_EDGE_RISING:
144 case IRQ_TYPE_EDGE_FALLING:
145 case IRQ_TYPE_EDGE_BOTH:
146 irq_set_handler(data->irq, handle_edge_irq);
147 break;
148 case IRQ_TYPE_LEVEL_LOW:
149 case IRQ_TYPE_LEVEL_HIGH:
150 irq_set_handler(data->irq, handle_level_irq);
151 break;
152 default:
153 pr_err("No such irq type %d\n", type);
154 return -EINVAL;
155 }
156
157 return 0;
158}
159
160static int s3c_irqext_type_set(void __iomem *gpcon_reg,
161 void __iomem *extint_reg,
162 unsigned long gpcon_offset,
163 unsigned long extint_offset,
164 unsigned int type)
165{
166 unsigned long newvalue = 0, value;
167
168
169 value = readl_relaxed(gpcon_reg);
170 value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
171 writel_relaxed(value, gpcon_reg);
172
173
174 switch (type)
175 {
176 case IRQ_TYPE_NONE:
177 pr_warn("No edge setting!\n");
178 break;
179
180 case IRQ_TYPE_EDGE_RISING:
181 newvalue = S3C2410_EXTINT_RISEEDGE;
182 break;
183
184 case IRQ_TYPE_EDGE_FALLING:
185 newvalue = S3C2410_EXTINT_FALLEDGE;
186 break;
187
188 case IRQ_TYPE_EDGE_BOTH:
189 newvalue = S3C2410_EXTINT_BOTHEDGE;
190 break;
191
192 case IRQ_TYPE_LEVEL_LOW:
193 newvalue = S3C2410_EXTINT_LOWLEV;
194 break;
195
196 case IRQ_TYPE_LEVEL_HIGH:
197 newvalue = S3C2410_EXTINT_HILEV;
198 break;
199
200 default:
201 pr_err("No such irq type %d\n", type);
202 return -EINVAL;
203 }
204
205 value = readl_relaxed(extint_reg);
206 value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
207 writel_relaxed(value, extint_reg);
208
209 return 0;
210}
211
212static int s3c_irqext_type(struct irq_data *data, unsigned int type)
213{
214 void __iomem *extint_reg;
215 void __iomem *gpcon_reg;
216 unsigned long gpcon_offset, extint_offset;
217
218 if ((data->hwirq >= 4) && (data->hwirq <= 7)) {
219 gpcon_reg = S3C2410_GPFCON;
220 extint_reg = S3C24XX_EXTINT0;
221 gpcon_offset = (data->hwirq) * 2;
222 extint_offset = (data->hwirq) * 4;
223 } else if ((data->hwirq >= 8) && (data->hwirq <= 15)) {
224 gpcon_reg = S3C2410_GPGCON;
225 extint_reg = S3C24XX_EXTINT1;
226 gpcon_offset = (data->hwirq - 8) * 2;
227 extint_offset = (data->hwirq - 8) * 4;
228 } else if ((data->hwirq >= 16) && (data->hwirq <= 23)) {
229 gpcon_reg = S3C2410_GPGCON;
230 extint_reg = S3C24XX_EXTINT2;
231 gpcon_offset = (data->hwirq - 8) * 2;
232 extint_offset = (data->hwirq - 16) * 4;
233 } else {
234 return -EINVAL;
235 }
236
237 return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
238 extint_offset, type);
239}
240
241static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
242{
243 void __iomem *extint_reg;
244 void __iomem *gpcon_reg;
245 unsigned long gpcon_offset, extint_offset;
246
247 if (data->hwirq <= 3) {
248 gpcon_reg = S3C2410_GPFCON;
249 extint_reg = S3C24XX_EXTINT0;
250 gpcon_offset = (data->hwirq) * 2;
251 extint_offset = (data->hwirq) * 4;
252 } else {
253 return -EINVAL;
254 }
255
256 return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
257 extint_offset, type);
258}
259
260static struct irq_chip s3c_irq_chip = {
261 .name = "s3c",
262 .irq_ack = s3c_irq_ack,
263 .irq_mask = s3c_irq_mask,
264 .irq_unmask = s3c_irq_unmask,
265 .irq_set_type = s3c_irq_type,
266 .irq_set_wake = s3c_irq_wake
267};
268
269static struct irq_chip s3c_irq_level_chip = {
270 .name = "s3c-level",
271 .irq_mask = s3c_irq_mask,
272 .irq_unmask = s3c_irq_unmask,
273 .irq_ack = s3c_irq_ack,
274 .irq_set_type = s3c_irq_type,
275};
276
277static struct irq_chip s3c_irqext_chip = {
278 .name = "s3c-ext",
279 .irq_mask = s3c_irq_mask,
280 .irq_unmask = s3c_irq_unmask,
281 .irq_ack = s3c_irq_ack,
282 .irq_set_type = s3c_irqext_type,
283 .irq_set_wake = s3c_irqext_wake
284};
285
286static struct irq_chip s3c_irq_eint0t4 = {
287 .name = "s3c-ext0",
288 .irq_ack = s3c_irq_ack,
289 .irq_mask = s3c_irq_mask,
290 .irq_unmask = s3c_irq_unmask,
291 .irq_set_wake = s3c_irq_wake,
292 .irq_set_type = s3c_irqext0_type,
293};
294
295static void s3c_irq_demux(struct irq_desc *desc)
296{
297 struct irq_chip *chip = irq_desc_get_chip(desc);
298 struct s3c_irq_data *irq_data = irq_desc_get_chip_data(desc);
299 struct s3c_irq_intc *intc = irq_data->intc;
300 struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
301 unsigned int n, offset, irq;
302 unsigned long src, msk;
303
304
305
306
307
308 offset = irq_domain_get_of_node(intc->domain) ? 32 : 0;
309
310 chained_irq_enter(chip, desc);
311
312 src = readl_relaxed(sub_intc->reg_pending);
313 msk = readl_relaxed(sub_intc->reg_mask);
314
315 src &= ~msk;
316 src &= irq_data->sub_bits;
317
318 while (src) {
319 n = __ffs(src);
320 src &= ~(1 << n);
321 irq = irq_find_mapping(sub_intc->domain, offset + n);
322 generic_handle_irq(irq);
323 }
324
325 chained_irq_exit(chip, desc);
326}
327
328static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
329 struct pt_regs *regs, int intc_offset)
330{
331 int pnd;
332 int offset;
333
334 pnd = readl_relaxed(intc->reg_intpnd);
335 if (!pnd)
336 return false;
337
338
339 if (!irq_domain_get_of_node(intc->domain))
340 intc_offset = 0;
341
342
343
344
345
346
347
348
349 offset = readl_relaxed(intc->reg_intpnd + 4);
350
351
352
353
354
355 if (!(pnd & (1 << offset)))
356 offset = __ffs(pnd);
357
358 handle_domain_irq(intc->domain, intc_offset + offset, regs);
359 return true;
360}
361
362static asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs)
363{
364 do {
365 if (likely(s3c_intc[0]))
366 if (s3c24xx_handle_intc(s3c_intc[0], regs, 0))
367 continue;
368
369 if (s3c_intc[2])
370 if (s3c24xx_handle_intc(s3c_intc[2], regs, 64))
371 continue;
372
373 break;
374 } while (1);
375}
376
377#ifdef CONFIG_FIQ
378
379
380
381
382
383
384
385
386
387
388
389
390
391int s3c24xx_set_fiq(unsigned int irq, u32 *ack_ptr, bool on)
392{
393 u32 intmod;
394 unsigned offs;
395
396 if (on) {
397 offs = irq - FIQ_START;
398 if (offs > 31)
399 return 0;
400
401 intmod = 1 << offs;
402 } else {
403 intmod = 0;
404 }
405
406 if (ack_ptr)
407 *ack_ptr = intmod;
408 writel_relaxed(intmod, S3C2410_INTMOD);
409
410 return intmod;
411}
412
413EXPORT_SYMBOL_GPL(s3c24xx_set_fiq);
414#endif
415
416static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
417 irq_hw_number_t hw)
418{
419 struct s3c_irq_intc *intc = h->host_data;
420 struct s3c_irq_data *irq_data = &intc->irqs[hw];
421 struct s3c_irq_intc *parent_intc;
422 struct s3c_irq_data *parent_irq_data;
423 unsigned int irqno;
424
425
426 irq_data->intc = intc;
427 irq_data->offset = hw;
428
429 parent_intc = intc->parent;
430
431
432 switch (irq_data->type) {
433 case S3C_IRQTYPE_NONE:
434 return 0;
435 case S3C_IRQTYPE_EINT:
436
437
438
439 if (parent_intc && (!soc_is_s3c2412() || hw >= 4))
440 irq_set_chip_and_handler(virq, &s3c_irqext_chip,
441 handle_edge_irq);
442 else
443 irq_set_chip_and_handler(virq, &s3c_irq_eint0t4,
444 handle_edge_irq);
445 break;
446 case S3C_IRQTYPE_EDGE:
447 if (parent_intc || intc->reg_pending == S3C2416_SRCPND2)
448 irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
449 handle_edge_irq);
450 else
451 irq_set_chip_and_handler(virq, &s3c_irq_chip,
452 handle_edge_irq);
453 break;
454 case S3C_IRQTYPE_LEVEL:
455 if (parent_intc)
456 irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
457 handle_level_irq);
458 else
459 irq_set_chip_and_handler(virq, &s3c_irq_chip,
460 handle_level_irq);
461 break;
462 default:
463 pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
464 return -EINVAL;
465 }
466
467 irq_set_chip_data(virq, irq_data);
468
469 if (parent_intc && irq_data->type != S3C_IRQTYPE_NONE) {
470 if (irq_data->parent_irq > 31) {
471 pr_err("irq-s3c24xx: parent irq %lu is out of range\n",
472 irq_data->parent_irq);
473 return -EINVAL;
474 }
475
476 parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
477 parent_irq_data->sub_intc = intc;
478 parent_irq_data->sub_bits |= (1UL << hw);
479
480
481 irqno = irq_find_mapping(parent_intc->domain,
482 irq_data->parent_irq);
483 if (!irqno) {
484 pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
485 irq_data->parent_irq);
486 return -EINVAL;
487 }
488 irq_set_chained_handler(irqno, s3c_irq_demux);
489 }
490
491 return 0;
492}
493
494static const struct irq_domain_ops s3c24xx_irq_ops = {
495 .map = s3c24xx_irq_map,
496 .xlate = irq_domain_xlate_twocell,
497};
498
499static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
500{
501 void __iomem *reg_source;
502 unsigned long pend;
503 unsigned long last;
504 int i;
505
506
507 reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending;
508
509 last = 0;
510 for (i = 0; i < 4; i++) {
511 pend = readl_relaxed(reg_source);
512
513 if (pend == 0 || pend == last)
514 break;
515
516 writel_relaxed(pend, intc->reg_pending);
517 if (intc->reg_intpnd)
518 writel_relaxed(pend, intc->reg_intpnd);
519
520 pr_info("irq: clearing pending status %08x\n", (int)pend);
521 last = pend;
522 }
523}
524
525static struct s3c_irq_intc * __init s3c24xx_init_intc(struct device_node *np,
526 struct s3c_irq_data *irq_data,
527 struct s3c_irq_intc *parent,
528 unsigned long address)
529{
530 struct s3c_irq_intc *intc;
531 void __iomem *base = (void *)0xf6000000;
532 int irq_num;
533 int irq_start;
534 int ret;
535
536 intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
537 if (!intc)
538 return ERR_PTR(-ENOMEM);
539
540 intc->irqs = irq_data;
541
542 if (parent)
543 intc->parent = parent;
544
545
546
547
548
549 switch (address) {
550 case 0x4a000000:
551 pr_debug("irq: found main intc\n");
552 intc->reg_pending = base;
553 intc->reg_mask = base + 0x08;
554 intc->reg_intpnd = base + 0x10;
555 irq_num = 32;
556 irq_start = S3C2410_IRQ(0);
557 break;
558 case 0x4a000018:
559 pr_debug("irq: found subintc\n");
560 intc->reg_pending = base + 0x18;
561 intc->reg_mask = base + 0x1c;
562 irq_num = 29;
563 irq_start = S3C2410_IRQSUB(0);
564 break;
565 case 0x4a000040:
566 pr_debug("irq: found intc2\n");
567 intc->reg_pending = base + 0x40;
568 intc->reg_mask = base + 0x48;
569 intc->reg_intpnd = base + 0x50;
570 irq_num = 8;
571 irq_start = S3C2416_IRQ(0);
572 break;
573 case 0x560000a4:
574 pr_debug("irq: found eintc\n");
575 base = (void *)0xfd000000;
576
577 intc->reg_mask = base + 0xa4;
578 intc->reg_pending = base + 0xa8;
579 irq_num = 24;
580 irq_start = S3C2410_IRQ(32);
581 break;
582 default:
583 pr_err("irq: unsupported controller address\n");
584 ret = -EINVAL;
585 goto err;
586 }
587
588
589 s3c24xx_clear_intc(intc);
590 intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
591 0, &s3c24xx_irq_ops,
592 intc);
593 if (!intc->domain) {
594 pr_err("irq: could not create irq-domain\n");
595 ret = -EINVAL;
596 goto err;
597 }
598
599 set_handle_irq(s3c24xx_handle_irq);
600
601 return intc;
602
603err:
604 kfree(intc);
605 return ERR_PTR(ret);
606}
607
608static struct s3c_irq_data __maybe_unused init_eint[32] = {
609 { .type = S3C_IRQTYPE_NONE, },
610 { .type = S3C_IRQTYPE_NONE, },
611 { .type = S3C_IRQTYPE_NONE, },
612 { .type = S3C_IRQTYPE_NONE, },
613 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 },
614 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 },
615 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 },
616 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 },
617 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
618 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
619 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
620 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
621 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
622 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
623 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
624 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
625 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
626 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
627 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
628 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
629 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
630 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
631 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
632 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
633};
634
635#ifdef CONFIG_CPU_S3C2410
636static struct s3c_irq_data init_s3c2410base[32] = {
637 { .type = S3C_IRQTYPE_EINT, },
638 { .type = S3C_IRQTYPE_EINT, },
639 { .type = S3C_IRQTYPE_EINT, },
640 { .type = S3C_IRQTYPE_EINT, },
641 { .type = S3C_IRQTYPE_LEVEL, },
642 { .type = S3C_IRQTYPE_LEVEL, },
643 { .type = S3C_IRQTYPE_NONE, },
644 { .type = S3C_IRQTYPE_EDGE, },
645 { .type = S3C_IRQTYPE_EDGE, },
646 { .type = S3C_IRQTYPE_EDGE, },
647 { .type = S3C_IRQTYPE_EDGE, },
648 { .type = S3C_IRQTYPE_EDGE, },
649 { .type = S3C_IRQTYPE_EDGE, },
650 { .type = S3C_IRQTYPE_EDGE, },
651 { .type = S3C_IRQTYPE_EDGE, },
652 { .type = S3C_IRQTYPE_LEVEL, },
653 { .type = S3C_IRQTYPE_EDGE, },
654 { .type = S3C_IRQTYPE_EDGE, },
655 { .type = S3C_IRQTYPE_EDGE, },
656 { .type = S3C_IRQTYPE_EDGE, },
657 { .type = S3C_IRQTYPE_EDGE, },
658 { .type = S3C_IRQTYPE_EDGE, },
659 { .type = S3C_IRQTYPE_EDGE, },
660 { .type = S3C_IRQTYPE_LEVEL, },
661 { .type = S3C_IRQTYPE_NONE, },
662 { .type = S3C_IRQTYPE_EDGE, },
663 { .type = S3C_IRQTYPE_EDGE, },
664 { .type = S3C_IRQTYPE_EDGE, },
665 { .type = S3C_IRQTYPE_LEVEL, },
666 { .type = S3C_IRQTYPE_EDGE, },
667 { .type = S3C_IRQTYPE_EDGE, },
668 { .type = S3C_IRQTYPE_LEVEL, },
669};
670
671static struct s3c_irq_data init_s3c2410subint[32] = {
672 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
673 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
674 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
675 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
676 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
677 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
678 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
679 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
680 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
681 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
682 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
683};
684
685void __init s3c2410_init_irq(void)
686{
687#ifdef CONFIG_FIQ
688 init_FIQ(FIQ_START);
689#endif
690
691 s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2410base[0], NULL,
692 0x4a000000);
693 if (IS_ERR(s3c_intc[0])) {
694 pr_err("irq: could not create main interrupt controller\n");
695 return;
696 }
697
698 s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2410subint[0],
699 s3c_intc[0], 0x4a000018);
700 s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
701}
702#endif
703
704#ifdef CONFIG_CPU_S3C2412
705static struct s3c_irq_data init_s3c2412base[32] = {
706 { .type = S3C_IRQTYPE_LEVEL, },
707 { .type = S3C_IRQTYPE_LEVEL, },
708 { .type = S3C_IRQTYPE_LEVEL, },
709 { .type = S3C_IRQTYPE_LEVEL, },
710 { .type = S3C_IRQTYPE_LEVEL, },
711 { .type = S3C_IRQTYPE_LEVEL, },
712 { .type = S3C_IRQTYPE_NONE, },
713 { .type = S3C_IRQTYPE_EDGE, },
714 { .type = S3C_IRQTYPE_EDGE, },
715 { .type = S3C_IRQTYPE_EDGE, },
716 { .type = S3C_IRQTYPE_EDGE, },
717 { .type = S3C_IRQTYPE_EDGE, },
718 { .type = S3C_IRQTYPE_EDGE, },
719 { .type = S3C_IRQTYPE_EDGE, },
720 { .type = S3C_IRQTYPE_EDGE, },
721 { .type = S3C_IRQTYPE_LEVEL, },
722 { .type = S3C_IRQTYPE_EDGE, },
723 { .type = S3C_IRQTYPE_EDGE, },
724 { .type = S3C_IRQTYPE_EDGE, },
725 { .type = S3C_IRQTYPE_EDGE, },
726 { .type = S3C_IRQTYPE_EDGE, },
727 { .type = S3C_IRQTYPE_LEVEL, },
728 { .type = S3C_IRQTYPE_EDGE, },
729 { .type = S3C_IRQTYPE_LEVEL, },
730 { .type = S3C_IRQTYPE_NONE, },
731 { .type = S3C_IRQTYPE_EDGE, },
732 { .type = S3C_IRQTYPE_EDGE, },
733 { .type = S3C_IRQTYPE_EDGE, },
734 { .type = S3C_IRQTYPE_LEVEL, },
735 { .type = S3C_IRQTYPE_EDGE, },
736 { .type = S3C_IRQTYPE_EDGE, },
737 { .type = S3C_IRQTYPE_LEVEL, },
738};
739
740static struct s3c_irq_data init_s3c2412eint[32] = {
741 { .type = S3C_IRQTYPE_EINT, .parent_irq = 0 },
742 { .type = S3C_IRQTYPE_EINT, .parent_irq = 1 },
743 { .type = S3C_IRQTYPE_EINT, .parent_irq = 2 },
744 { .type = S3C_IRQTYPE_EINT, .parent_irq = 3 },
745 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 },
746 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 },
747 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 },
748 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 },
749 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
750 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
751 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
752 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
753 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
754 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
755 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
756 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
757 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
758 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
759 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
760 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
761 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
762 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
763 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
764 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 },
765};
766
767static struct s3c_irq_data init_s3c2412subint[32] = {
768 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
769 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
770 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
771 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
772 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
773 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
774 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
775 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
776 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
777 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
778 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
779 { .type = S3C_IRQTYPE_NONE, },
780 { .type = S3C_IRQTYPE_NONE, },
781 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 },
782 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 },
783};
784
785void __init s3c2412_init_irq(void)
786{
787 pr_info("S3C2412: IRQ Support\n");
788
789#ifdef CONFIG_FIQ
790 init_FIQ(FIQ_START);
791#endif
792
793 s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2412base[0], NULL,
794 0x4a000000);
795 if (IS_ERR(s3c_intc[0])) {
796 pr_err("irq: could not create main interrupt controller\n");
797 return;
798 }
799
800 s3c24xx_init_intc(NULL, &init_s3c2412eint[0], s3c_intc[0], 0x560000a4);
801 s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2412subint[0],
802 s3c_intc[0], 0x4a000018);
803}
804#endif
805
806#ifdef CONFIG_CPU_S3C2416
807static struct s3c_irq_data init_s3c2416base[32] = {
808 { .type = S3C_IRQTYPE_EINT, },
809 { .type = S3C_IRQTYPE_EINT, },
810 { .type = S3C_IRQTYPE_EINT, },
811 { .type = S3C_IRQTYPE_EINT, },
812 { .type = S3C_IRQTYPE_LEVEL, },
813 { .type = S3C_IRQTYPE_LEVEL, },
814 { .type = S3C_IRQTYPE_NONE, },
815 { .type = S3C_IRQTYPE_EDGE, },
816 { .type = S3C_IRQTYPE_EDGE, },
817 { .type = S3C_IRQTYPE_LEVEL, },
818 { .type = S3C_IRQTYPE_EDGE, },
819 { .type = S3C_IRQTYPE_EDGE, },
820 { .type = S3C_IRQTYPE_EDGE, },
821 { .type = S3C_IRQTYPE_EDGE, },
822 { .type = S3C_IRQTYPE_EDGE, },
823 { .type = S3C_IRQTYPE_LEVEL, },
824 { .type = S3C_IRQTYPE_LEVEL, },
825 { .type = S3C_IRQTYPE_LEVEL, },
826 { .type = S3C_IRQTYPE_LEVEL, },
827 { .type = S3C_IRQTYPE_NONE, },
828 { .type = S3C_IRQTYPE_EDGE, },
829 { .type = S3C_IRQTYPE_EDGE, },
830 { .type = S3C_IRQTYPE_EDGE, },
831 { .type = S3C_IRQTYPE_LEVEL, },
832 { .type = S3C_IRQTYPE_EDGE, },
833 { .type = S3C_IRQTYPE_EDGE, },
834 { .type = S3C_IRQTYPE_EDGE, },
835 { .type = S3C_IRQTYPE_EDGE, },
836 { .type = S3C_IRQTYPE_LEVEL, },
837 { .type = S3C_IRQTYPE_NONE, },
838 { .type = S3C_IRQTYPE_EDGE, },
839 { .type = S3C_IRQTYPE_LEVEL, },
840};
841
842static struct s3c_irq_data init_s3c2416subint[32] = {
843 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
844 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
845 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
846 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
847 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
848 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
849 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
850 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
851 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
852 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
853 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
854 { .type = S3C_IRQTYPE_NONE },
855 { .type = S3C_IRQTYPE_NONE },
856 { .type = S3C_IRQTYPE_NONE },
857 { .type = S3C_IRQTYPE_NONE },
858 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 },
859 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 },
860 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 },
861 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
862 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
863 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
864 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
865 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
866 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
867 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 },
868 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 },
869 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 },
870 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 },
871 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 },
872};
873
874static struct s3c_irq_data init_s3c2416_second[32] = {
875 { .type = S3C_IRQTYPE_EDGE },
876 { .type = S3C_IRQTYPE_NONE },
877 { .type = S3C_IRQTYPE_NONE },
878 { .type = S3C_IRQTYPE_NONE },
879 { .type = S3C_IRQTYPE_EDGE },
880 { .type = S3C_IRQTYPE_NONE },
881 { .type = S3C_IRQTYPE_EDGE },
882};
883
884void __init s3c2416_init_irq(void)
885{
886 pr_info("S3C2416: IRQ Support\n");
887
888#ifdef CONFIG_FIQ
889 init_FIQ(FIQ_START);
890#endif
891
892 s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL,
893 0x4a000000);
894 if (IS_ERR(s3c_intc[0])) {
895 pr_err("irq: could not create main interrupt controller\n");
896 return;
897 }
898
899 s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
900 s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2416subint[0],
901 s3c_intc[0], 0x4a000018);
902
903 s3c_intc[2] = s3c24xx_init_intc(NULL, &init_s3c2416_second[0],
904 NULL, 0x4a000040);
905}
906
907#endif
908
909#ifdef CONFIG_CPU_S3C2440
910static struct s3c_irq_data init_s3c2440base[32] = {
911 { .type = S3C_IRQTYPE_EINT, },
912 { .type = S3C_IRQTYPE_EINT, },
913 { .type = S3C_IRQTYPE_EINT, },
914 { .type = S3C_IRQTYPE_EINT, },
915 { .type = S3C_IRQTYPE_LEVEL, },
916 { .type = S3C_IRQTYPE_LEVEL, },
917 { .type = S3C_IRQTYPE_LEVEL, },
918 { .type = S3C_IRQTYPE_EDGE, },
919 { .type = S3C_IRQTYPE_EDGE, },
920 { .type = S3C_IRQTYPE_LEVEL, },
921 { .type = S3C_IRQTYPE_EDGE, },
922 { .type = S3C_IRQTYPE_EDGE, },
923 { .type = S3C_IRQTYPE_EDGE, },
924 { .type = S3C_IRQTYPE_EDGE, },
925 { .type = S3C_IRQTYPE_EDGE, },
926 { .type = S3C_IRQTYPE_LEVEL, },
927 { .type = S3C_IRQTYPE_EDGE, },
928 { .type = S3C_IRQTYPE_EDGE, },
929 { .type = S3C_IRQTYPE_EDGE, },
930 { .type = S3C_IRQTYPE_EDGE, },
931 { .type = S3C_IRQTYPE_EDGE, },
932 { .type = S3C_IRQTYPE_EDGE, },
933 { .type = S3C_IRQTYPE_EDGE, },
934 { .type = S3C_IRQTYPE_LEVEL, },
935 { .type = S3C_IRQTYPE_LEVEL, },
936 { .type = S3C_IRQTYPE_EDGE, },
937 { .type = S3C_IRQTYPE_EDGE, },
938 { .type = S3C_IRQTYPE_EDGE, },
939 { .type = S3C_IRQTYPE_LEVEL, },
940 { .type = S3C_IRQTYPE_EDGE, },
941 { .type = S3C_IRQTYPE_EDGE, },
942 { .type = S3C_IRQTYPE_LEVEL, },
943};
944
945static struct s3c_irq_data init_s3c2440subint[32] = {
946 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
947 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
948 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
949 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
950 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
951 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
952 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
953 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
954 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
955 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
956 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
957 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 },
958 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 },
959 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 },
960 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 },
961};
962
963void __init s3c2440_init_irq(void)
964{
965 pr_info("S3C2440: IRQ Support\n");
966
967#ifdef CONFIG_FIQ
968 init_FIQ(FIQ_START);
969#endif
970
971 s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL,
972 0x4a000000);
973 if (IS_ERR(s3c_intc[0])) {
974 pr_err("irq: could not create main interrupt controller\n");
975 return;
976 }
977
978 s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
979 s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2440subint[0],
980 s3c_intc[0], 0x4a000018);
981}
982#endif
983
984#ifdef CONFIG_CPU_S3C2442
985static struct s3c_irq_data init_s3c2442base[32] = {
986 { .type = S3C_IRQTYPE_EINT, },
987 { .type = S3C_IRQTYPE_EINT, },
988 { .type = S3C_IRQTYPE_EINT, },
989 { .type = S3C_IRQTYPE_EINT, },
990 { .type = S3C_IRQTYPE_LEVEL, },
991 { .type = S3C_IRQTYPE_LEVEL, },
992 { .type = S3C_IRQTYPE_LEVEL, },
993 { .type = S3C_IRQTYPE_EDGE, },
994 { .type = S3C_IRQTYPE_EDGE, },
995 { .type = S3C_IRQTYPE_EDGE, },
996 { .type = S3C_IRQTYPE_EDGE, },
997 { .type = S3C_IRQTYPE_EDGE, },
998 { .type = S3C_IRQTYPE_EDGE, },
999 { .type = S3C_IRQTYPE_EDGE, },
1000 { .type = S3C_IRQTYPE_EDGE, },
1001 { .type = S3C_IRQTYPE_LEVEL, },
1002 { .type = S3C_IRQTYPE_EDGE, },
1003 { .type = S3C_IRQTYPE_EDGE, },
1004 { .type = S3C_IRQTYPE_EDGE, },
1005 { .type = S3C_IRQTYPE_EDGE, },
1006 { .type = S3C_IRQTYPE_EDGE, },
1007 { .type = S3C_IRQTYPE_EDGE, },
1008 { .type = S3C_IRQTYPE_EDGE, },
1009 { .type = S3C_IRQTYPE_LEVEL, },
1010 { .type = S3C_IRQTYPE_LEVEL, },
1011 { .type = S3C_IRQTYPE_EDGE, },
1012 { .type = S3C_IRQTYPE_EDGE, },
1013 { .type = S3C_IRQTYPE_EDGE, },
1014 { .type = S3C_IRQTYPE_LEVEL, },
1015 { .type = S3C_IRQTYPE_EDGE, },
1016 { .type = S3C_IRQTYPE_EDGE, },
1017 { .type = S3C_IRQTYPE_LEVEL, },
1018};
1019
1020static struct s3c_irq_data init_s3c2442subint[32] = {
1021 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
1022 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
1023 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
1024 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
1025 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
1026 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
1027 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
1028 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
1029 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
1030 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
1031 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
1032 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 },
1033 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 },
1034};
1035
1036void __init s3c2442_init_irq(void)
1037{
1038 pr_info("S3C2442: IRQ Support\n");
1039
1040#ifdef CONFIG_FIQ
1041 init_FIQ(FIQ_START);
1042#endif
1043
1044 s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2442base[0], NULL,
1045 0x4a000000);
1046 if (IS_ERR(s3c_intc[0])) {
1047 pr_err("irq: could not create main interrupt controller\n");
1048 return;
1049 }
1050
1051 s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
1052 s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2442subint[0],
1053 s3c_intc[0], 0x4a000018);
1054}
1055#endif
1056
1057#ifdef CONFIG_CPU_S3C2443
1058static struct s3c_irq_data init_s3c2443base[32] = {
1059 { .type = S3C_IRQTYPE_EINT, },
1060 { .type = S3C_IRQTYPE_EINT, },
1061 { .type = S3C_IRQTYPE_EINT, },
1062 { .type = S3C_IRQTYPE_EINT, },
1063 { .type = S3C_IRQTYPE_LEVEL, },
1064 { .type = S3C_IRQTYPE_LEVEL, },
1065 { .type = S3C_IRQTYPE_LEVEL, },
1066 { .type = S3C_IRQTYPE_EDGE, },
1067 { .type = S3C_IRQTYPE_EDGE, },
1068 { .type = S3C_IRQTYPE_LEVEL, },
1069 { .type = S3C_IRQTYPE_EDGE, },
1070 { .type = S3C_IRQTYPE_EDGE, },
1071 { .type = S3C_IRQTYPE_EDGE, },
1072 { .type = S3C_IRQTYPE_EDGE, },
1073 { .type = S3C_IRQTYPE_EDGE, },
1074 { .type = S3C_IRQTYPE_LEVEL, },
1075 { .type = S3C_IRQTYPE_LEVEL, },
1076 { .type = S3C_IRQTYPE_LEVEL, },
1077 { .type = S3C_IRQTYPE_LEVEL, },
1078 { .type = S3C_IRQTYPE_EDGE, },
1079 { .type = S3C_IRQTYPE_EDGE, },
1080 { .type = S3C_IRQTYPE_EDGE, },
1081 { .type = S3C_IRQTYPE_EDGE, },
1082 { .type = S3C_IRQTYPE_LEVEL, },
1083 { .type = S3C_IRQTYPE_EDGE, },
1084 { .type = S3C_IRQTYPE_EDGE, },
1085 { .type = S3C_IRQTYPE_EDGE, },
1086 { .type = S3C_IRQTYPE_EDGE, },
1087 { .type = S3C_IRQTYPE_LEVEL, },
1088 { .type = S3C_IRQTYPE_EDGE, },
1089 { .type = S3C_IRQTYPE_EDGE, },
1090 { .type = S3C_IRQTYPE_LEVEL, },
1091};
1092
1093
1094static struct s3c_irq_data init_s3c2443subint[32] = {
1095 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
1096 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
1097 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 },
1098 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
1099 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
1100 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 },
1101 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
1102 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
1103 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 },
1104 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
1105 { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 },
1106 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 },
1107 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 },
1108 { .type = S3C_IRQTYPE_NONE },
1109 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 },
1110 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 },
1111 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 },
1112 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 },
1113 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
1114 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
1115 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
1116 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
1117 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
1118 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 },
1119 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 },
1120 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 },
1121 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 },
1122 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 },
1123 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 },
1124};
1125
1126void __init s3c2443_init_irq(void)
1127{
1128 pr_info("S3C2443: IRQ Support\n");
1129
1130#ifdef CONFIG_FIQ
1131 init_FIQ(FIQ_START);
1132#endif
1133
1134 s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL,
1135 0x4a000000);
1136 if (IS_ERR(s3c_intc[0])) {
1137 pr_err("irq: could not create main interrupt controller\n");
1138 return;
1139 }
1140
1141 s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
1142 s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2443subint[0],
1143 s3c_intc[0], 0x4a000018);
1144}
1145#endif
1146
1147#ifdef CONFIG_OF
1148static int s3c24xx_irq_map_of(struct irq_domain *h, unsigned int virq,
1149 irq_hw_number_t hw)
1150{
1151 unsigned int ctrl_num = hw / 32;
1152 unsigned int intc_hw = hw % 32;
1153 struct s3c_irq_intc *intc = s3c_intc[ctrl_num];
1154 struct s3c_irq_intc *parent_intc = intc->parent;
1155 struct s3c_irq_data *irq_data = &intc->irqs[intc_hw];
1156
1157
1158 irq_data->intc = intc;
1159 irq_data->offset = intc_hw;
1160
1161 if (!parent_intc)
1162 irq_set_chip_and_handler(virq, &s3c_irq_chip, handle_edge_irq);
1163 else
1164 irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
1165 handle_edge_irq);
1166
1167 irq_set_chip_data(virq, irq_data);
1168
1169 return 0;
1170}
1171
1172
1173
1174
1175static int s3c24xx_irq_xlate_of(struct irq_domain *d, struct device_node *n,
1176 const u32 *intspec, unsigned int intsize,
1177 irq_hw_number_t *out_hwirq, unsigned int *out_type)
1178{
1179 struct s3c_irq_intc *intc;
1180 struct s3c_irq_intc *parent_intc;
1181 struct s3c_irq_data *irq_data;
1182 struct s3c_irq_data *parent_irq_data;
1183 int irqno;
1184
1185 if (WARN_ON(intsize < 4))
1186 return -EINVAL;
1187
1188 if (intspec[0] > 2 || !s3c_intc[intspec[0]]) {
1189 pr_err("controller number %d invalid\n", intspec[0]);
1190 return -EINVAL;
1191 }
1192 intc = s3c_intc[intspec[0]];
1193
1194 *out_hwirq = intspec[0] * 32 + intspec[2];
1195 *out_type = intspec[3] & IRQ_TYPE_SENSE_MASK;
1196
1197 parent_intc = intc->parent;
1198 if (parent_intc) {
1199 irq_data = &intc->irqs[intspec[2]];
1200 irq_data->parent_irq = intspec[1];
1201 parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
1202 parent_irq_data->sub_intc = intc;
1203 parent_irq_data->sub_bits |= (1UL << intspec[2]);
1204
1205
1206 irqno = irq_create_mapping(parent_intc->domain, intspec[1]);
1207 if (irqno < 0) {
1208 pr_err("irq: could not map parent interrupt\n");
1209 return irqno;
1210 }
1211
1212 irq_set_chained_handler(irqno, s3c_irq_demux);
1213 }
1214
1215 return 0;
1216}
1217
1218static const struct irq_domain_ops s3c24xx_irq_ops_of = {
1219 .map = s3c24xx_irq_map_of,
1220 .xlate = s3c24xx_irq_xlate_of,
1221};
1222
1223struct s3c24xx_irq_of_ctrl {
1224 char *name;
1225 unsigned long offset;
1226 struct s3c_irq_intc **handle;
1227 struct s3c_irq_intc **parent;
1228 struct irq_domain_ops *ops;
1229};
1230
1231static int __init s3c_init_intc_of(struct device_node *np,
1232 struct device_node *interrupt_parent,
1233 struct s3c24xx_irq_of_ctrl *s3c_ctrl, int num_ctrl)
1234{
1235 struct s3c_irq_intc *intc;
1236 struct s3c24xx_irq_of_ctrl *ctrl;
1237 struct irq_domain *domain;
1238 void __iomem *reg_base;
1239 int i;
1240
1241 reg_base = of_iomap(np, 0);
1242 if (!reg_base) {
1243 pr_err("irq-s3c24xx: could not map irq registers\n");
1244 return -EINVAL;
1245 }
1246
1247 domain = irq_domain_add_linear(np, num_ctrl * 32,
1248 &s3c24xx_irq_ops_of, NULL);
1249 if (!domain) {
1250 pr_err("irq: could not create irq-domain\n");
1251 return -EINVAL;
1252 }
1253
1254 for (i = 0; i < num_ctrl; i++) {
1255 ctrl = &s3c_ctrl[i];
1256
1257 pr_debug("irq: found controller %s\n", ctrl->name);
1258
1259 intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
1260 if (!intc)
1261 return -ENOMEM;
1262
1263 intc->domain = domain;
1264 intc->irqs = kcalloc(32, sizeof(struct s3c_irq_data),
1265 GFP_KERNEL);
1266 if (!intc->irqs) {
1267 kfree(intc);
1268 return -ENOMEM;
1269 }
1270
1271 if (ctrl->parent) {
1272 intc->reg_pending = reg_base + ctrl->offset;
1273 intc->reg_mask = reg_base + ctrl->offset + 0x4;
1274
1275 if (*(ctrl->parent)) {
1276 intc->parent = *(ctrl->parent);
1277 } else {
1278 pr_warn("irq: parent of %s missing\n",
1279 ctrl->name);
1280 kfree(intc->irqs);
1281 kfree(intc);
1282 continue;
1283 }
1284 } else {
1285 intc->reg_pending = reg_base + ctrl->offset;
1286 intc->reg_mask = reg_base + ctrl->offset + 0x08;
1287 intc->reg_intpnd = reg_base + ctrl->offset + 0x10;
1288 }
1289
1290 s3c24xx_clear_intc(intc);
1291 s3c_intc[i] = intc;
1292 }
1293
1294 set_handle_irq(s3c24xx_handle_irq);
1295
1296 return 0;
1297}
1298
1299static struct s3c24xx_irq_of_ctrl s3c2410_ctrl[] = {
1300 {
1301 .name = "intc",
1302 .offset = 0,
1303 }, {
1304 .name = "subintc",
1305 .offset = 0x18,
1306 .parent = &s3c_intc[0],
1307 }
1308};
1309
1310static int __init s3c2410_init_intc_of(struct device_node *np,
1311 struct device_node *interrupt_parent)
1312{
1313 return s3c_init_intc_of(np, interrupt_parent,
1314 s3c2410_ctrl, ARRAY_SIZE(s3c2410_ctrl));
1315}
1316IRQCHIP_DECLARE(s3c2410_irq, "samsung,s3c2410-irq", s3c2410_init_intc_of);
1317
1318static struct s3c24xx_irq_of_ctrl s3c2416_ctrl[] = {
1319 {
1320 .name = "intc",
1321 .offset = 0,
1322 }, {
1323 .name = "subintc",
1324 .offset = 0x18,
1325 .parent = &s3c_intc[0],
1326 }, {
1327 .name = "intc2",
1328 .offset = 0x40,
1329 }
1330};
1331
1332static int __init s3c2416_init_intc_of(struct device_node *np,
1333 struct device_node *interrupt_parent)
1334{
1335 return s3c_init_intc_of(np, interrupt_parent,
1336 s3c2416_ctrl, ARRAY_SIZE(s3c2416_ctrl));
1337}
1338IRQCHIP_DECLARE(s3c2416_irq, "samsung,s3c2416-irq", s3c2416_init_intc_of);
1339#endif
1340