aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c2410/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-s3c2410/irq.c')
-rw-r--r--arch/arm/mach-s3c2410/irq.c966
1 files changed, 966 insertions, 0 deletions
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
new file mode 100644
index 000000000000..b668c48f4399
--- /dev/null
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -0,0 +1,966 @@
1/* linux/arch/arm/mach-s3c2410/irq.c
2 *
3 * Copyright (c) 2003,2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * Changelog:
21 *
22 * 22-Jul-2004 Ben Dooks <ben@simtec.co.uk>
23 * Fixed compile warnings
24 *
25 * 22-Jul-2004 Roc Wu <cooloney@yahoo.com.cn>
26 * Fixed s3c_extirq_type
27 *
28 * 21-Jul-2004 Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
29 * Addition of ADC/TC demux
30 *
31 * 04-Oct-2004 Klaus Fetscher <k.fetscher@fetron.de>
32 * Fix for set_irq_type() on low EINT numbers
33 *
34 * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
35 * Tidy up KF's patch and sort out new release
36 *
37 * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
38 * Add support for power management controls
39 *
40 * 04-Nov-2004 Ben Dooks
41 * Fix standard IRQ wake for EINT0..4 and RTC
42 *
43 * 22-Feb-2004 Ben Dooks
44 * Fixed edge-triggering on ADC IRQ
45*/
46
47#include <linux/init.h>
48#include <linux/module.h>
49#include <linux/interrupt.h>
50#include <linux/ioport.h>
51#include <linux/ptrace.h>
52#include <linux/sysdev.h>
53
54#include <asm/hardware.h>
55#include <asm/irq.h>
56#include <asm/io.h>
57
58#include <asm/mach/irq.h>
59
60#include <asm/arch/regs-irq.h>
61#include <asm/arch/regs-gpio.h>
62
63#include "cpu.h"
64#include "pm.h"
65
66#define irqdbf(x...)
67#define irqdbf2(x...)
68
69#define EXTINT_OFF (IRQ_EINT4 - 4)
70
71/* wakeup irq control */
72
73#ifdef CONFIG_PM
74
75/* state for IRQs over sleep */
76
77/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
78 *
79 * set bit to 1 in allow bitfield to enable the wakeup settings on it
80*/
81
82unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
83unsigned long s3c_irqwake_intmask = 0xffffffffL;
84unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
85unsigned long s3c_irqwake_eintmask = 0xffffffffL;
86
87static int
88s3c_irq_wake(unsigned int irqno, unsigned int state)
89{
90 unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
91
92 if (!(s3c_irqwake_intallow & irqbit))
93 return -ENOENT;
94
95 printk(KERN_INFO "wake %s for irq %d\n",
96 state ? "enabled" : "disabled", irqno);
97
98 if (!state)
99 s3c_irqwake_intmask |= irqbit;
100 else
101 s3c_irqwake_intmask &= ~irqbit;
102
103 return 0;
104}
105
106static int
107s3c_irqext_wake(unsigned int irqno, unsigned int state)
108{
109 unsigned long bit = 1L << (irqno - EXTINT_OFF);
110
111 if (!(s3c_irqwake_eintallow & bit))
112 return -ENOENT;
113
114 printk(KERN_INFO "wake %s for irq %d\n",
115 state ? "enabled" : "disabled", irqno);
116
117 if (!state)
118 s3c_irqwake_eintmask |= bit;
119 else
120 s3c_irqwake_eintmask &= ~bit;
121
122 return 0;
123}
124
125#else
126#define s3c_irqext_wake NULL
127#define s3c_irq_wake NULL
128#endif
129
130
131static void
132s3c_irq_mask(unsigned int irqno)
133{
134 unsigned long mask;
135
136 irqno -= IRQ_EINT0;
137
138 mask = __raw_readl(S3C2410_INTMSK);
139 mask |= 1UL << irqno;
140 __raw_writel(mask, S3C2410_INTMSK);
141}
142
143static inline void
144s3c_irq_ack(unsigned int irqno)
145{
146 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
147
148 __raw_writel(bitval, S3C2410_SRCPND);
149 __raw_writel(bitval, S3C2410_INTPND);
150}
151
152static inline void
153s3c_irq_maskack(unsigned int irqno)
154{
155 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
156 unsigned long mask;
157
158 mask = __raw_readl(S3C2410_INTMSK);
159 __raw_writel(mask|bitval, S3C2410_INTMSK);
160
161 __raw_writel(bitval, S3C2410_SRCPND);
162 __raw_writel(bitval, S3C2410_INTPND);
163}
164
165
166static void
167s3c_irq_unmask(unsigned int irqno)
168{
169 unsigned long mask;
170
171 if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
172 irqdbf2("s3c_irq_unmask %d\n", irqno);
173
174 irqno -= IRQ_EINT0;
175
176 mask = __raw_readl(S3C2410_INTMSK);
177 mask &= ~(1UL << irqno);
178 __raw_writel(mask, S3C2410_INTMSK);
179}
180
181static struct irqchip s3c_irq_level_chip = {
182 .ack = s3c_irq_maskack,
183 .mask = s3c_irq_mask,
184 .unmask = s3c_irq_unmask,
185 .wake = s3c_irq_wake
186};
187
188static struct irqchip s3c_irq_chip = {
189 .ack = s3c_irq_ack,
190 .mask = s3c_irq_mask,
191 .unmask = s3c_irq_unmask,
192 .wake = s3c_irq_wake
193};
194
195/* S3C2410_EINTMASK
196 * S3C2410_EINTPEND
197 */
198
199static void
200s3c_irqext_mask(unsigned int irqno)
201{
202 unsigned long mask;
203
204 irqno -= EXTINT_OFF;
205
206 mask = __raw_readl(S3C2410_EINTMASK);
207 mask |= ( 1UL << irqno);
208 __raw_writel(mask, S3C2410_EINTMASK);
209
210 if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
211 /* check to see if all need masking */
212
213 if ((mask & (0xf << 4)) == (0xf << 4)) {
214 /* all masked, mask the parent */
215 s3c_irq_mask(IRQ_EINT4t7);
216 }
217 } else {
218 /* todo: the same check as above for the rest of the irq regs...*/
219
220 }
221}
222
223static void
224s3c_irqext_ack(unsigned int irqno)
225{
226 unsigned long req;
227 unsigned long bit;
228 unsigned long mask;
229
230 bit = 1UL << (irqno - EXTINT_OFF);
231
232
233 mask = __raw_readl(S3C2410_EINTMASK);
234
235 __raw_writel(bit, S3C2410_EINTPEND);
236
237 req = __raw_readl(S3C2410_EINTPEND);
238 req &= ~mask;
239
240 /* not sure if we should be acking the parent irq... */
241
242 if (irqno <= IRQ_EINT7 ) {
243 if ((req & 0xf0) == 0)
244 s3c_irq_ack(IRQ_EINT4t7);
245 } else {
246 if ((req >> 8) == 0)
247 s3c_irq_ack(IRQ_EINT8t23);
248 }
249}
250
251static void
252s3c_irqext_unmask(unsigned int irqno)
253{
254 unsigned long mask;
255
256 irqno -= EXTINT_OFF;
257
258 mask = __raw_readl(S3C2410_EINTMASK);
259 mask &= ~( 1UL << irqno);
260 __raw_writel(mask, S3C2410_EINTMASK);
261
262 s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
263}
264
265static int
266s3c_irqext_type(unsigned int irq, unsigned int type)
267{
268 void __iomem *extint_reg;
269 void __iomem *gpcon_reg;
270 unsigned long gpcon_offset, extint_offset;
271 unsigned long newvalue = 0, value;
272
273 if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
274 {
275 gpcon_reg = S3C2410_GPFCON;
276 extint_reg = S3C2410_EXTINT0;
277 gpcon_offset = (irq - IRQ_EINT0) * 2;
278 extint_offset = (irq - IRQ_EINT0) * 4;
279 }
280 else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
281 {
282 gpcon_reg = S3C2410_GPFCON;
283 extint_reg = S3C2410_EXTINT0;
284 gpcon_offset = (irq - (EXTINT_OFF)) * 2;
285 extint_offset = (irq - (EXTINT_OFF)) * 4;
286 }
287 else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
288 {
289 gpcon_reg = S3C2410_GPGCON;
290 extint_reg = S3C2410_EXTINT1;
291 gpcon_offset = (irq - IRQ_EINT8) * 2;
292 extint_offset = (irq - IRQ_EINT8) * 4;
293 }
294 else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
295 {
296 gpcon_reg = S3C2410_GPGCON;
297 extint_reg = S3C2410_EXTINT2;
298 gpcon_offset = (irq - IRQ_EINT8) * 2;
299 extint_offset = (irq - IRQ_EINT16) * 4;
300 } else
301 return -1;
302
303 /* Set the GPIO to external interrupt mode */
304 value = __raw_readl(gpcon_reg);
305 value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
306 __raw_writel(value, gpcon_reg);
307
308 /* Set the external interrupt to pointed trigger type */
309 switch (type)
310 {
311 case IRQT_NOEDGE:
312 printk(KERN_WARNING "No edge setting!\n");
313 break;
314
315 case IRQT_RISING:
316 newvalue = S3C2410_EXTINT_RISEEDGE;
317 break;
318
319 case IRQT_FALLING:
320 newvalue = S3C2410_EXTINT_FALLEDGE;
321 break;
322
323 case IRQT_BOTHEDGE:
324 newvalue = S3C2410_EXTINT_BOTHEDGE;
325 break;
326
327 case IRQT_LOW:
328 newvalue = S3C2410_EXTINT_LOWLEV;
329 break;
330
331 case IRQT_HIGH:
332 newvalue = S3C2410_EXTINT_HILEV;
333 break;
334
335 default:
336 printk(KERN_ERR "No such irq type %d", type);
337 return -1;
338 }
339
340 value = __raw_readl(extint_reg);
341 value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
342 __raw_writel(value, extint_reg);
343
344 return 0;
345}
346
347static struct irqchip s3c_irqext_chip = {
348 .mask = s3c_irqext_mask,
349 .unmask = s3c_irqext_unmask,
350 .ack = s3c_irqext_ack,
351 .type = s3c_irqext_type,
352 .wake = s3c_irqext_wake
353};
354
355static struct irqchip s3c_irq_eint0t4 = {
356 .ack = s3c_irq_ack,
357 .mask = s3c_irq_mask,
358 .unmask = s3c_irq_unmask,
359 .wake = s3c_irq_wake,
360 .type = s3c_irqext_type,
361};
362
363/* mask values for the parent registers for each of the interrupt types */
364
365#define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0))
366#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0))
367#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
368#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
369#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
370
371static inline void
372s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
373 int subcheck)
374{
375 unsigned long mask;
376 unsigned long submask;
377
378 submask = __raw_readl(S3C2410_INTSUBMSK);
379 mask = __raw_readl(S3C2410_INTMSK);
380
381 submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
382
383 /* check to see if we need to mask the parent IRQ */
384
385 if ((submask & subcheck) == subcheck) {
386 __raw_writel(mask | parentbit, S3C2410_INTMSK);
387 }
388
389 /* write back masks */
390 __raw_writel(submask, S3C2410_INTSUBMSK);
391
392}
393
394static inline void
395s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
396{
397 unsigned long mask;
398 unsigned long submask;
399
400 submask = __raw_readl(S3C2410_INTSUBMSK);
401 mask = __raw_readl(S3C2410_INTMSK);
402
403 submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
404 mask &= ~parentbit;
405
406 /* write back masks */
407 __raw_writel(submask, S3C2410_INTSUBMSK);
408 __raw_writel(mask, S3C2410_INTMSK);
409}
410
411
412static inline void
413s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
414{
415 unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
416
417 s3c_irqsub_mask(irqno, parentmask, group);
418
419 __raw_writel(bit, S3C2410_SUBSRCPND);
420
421 /* only ack parent if we've got all the irqs (seems we must
422 * ack, all and hope that the irq system retriggers ok when
423 * the interrupt goes off again)
424 */
425
426 if (1) {
427 __raw_writel(parentmask, S3C2410_SRCPND);
428 __raw_writel(parentmask, S3C2410_INTPND);
429 }
430}
431
432static inline void
433s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
434{
435 unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
436
437 __raw_writel(bit, S3C2410_SUBSRCPND);
438
439 /* only ack parent if we've got all the irqs (seems we must
440 * ack, all and hope that the irq system retriggers ok when
441 * the interrupt goes off again)
442 */
443
444 if (1) {
445 __raw_writel(parentmask, S3C2410_SRCPND);
446 __raw_writel(parentmask, S3C2410_INTPND);
447 }
448}
449
450/* UART0 */
451
452static void
453s3c_irq_uart0_mask(unsigned int irqno)
454{
455 s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
456}
457
458static void
459s3c_irq_uart0_unmask(unsigned int irqno)
460{
461 s3c_irqsub_unmask(irqno, INTMSK_UART0);
462}
463
464static void
465s3c_irq_uart0_ack(unsigned int irqno)
466{
467 s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
468}
469
470static struct irqchip s3c_irq_uart0 = {
471 .mask = s3c_irq_uart0_mask,
472 .unmask = s3c_irq_uart0_unmask,
473 .ack = s3c_irq_uart0_ack,
474};
475
476/* UART1 */
477
478static void
479s3c_irq_uart1_mask(unsigned int irqno)
480{
481 s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
482}
483
484static void
485s3c_irq_uart1_unmask(unsigned int irqno)
486{
487 s3c_irqsub_unmask(irqno, INTMSK_UART1);
488}
489
490static void
491s3c_irq_uart1_ack(unsigned int irqno)
492{
493 s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
494}
495
496static struct irqchip s3c_irq_uart1 = {
497 .mask = s3c_irq_uart1_mask,
498 .unmask = s3c_irq_uart1_unmask,
499 .ack = s3c_irq_uart1_ack,
500};
501
502/* UART2 */
503
504static void
505s3c_irq_uart2_mask(unsigned int irqno)
506{
507 s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
508}
509
510static void
511s3c_irq_uart2_unmask(unsigned int irqno)
512{
513 s3c_irqsub_unmask(irqno, INTMSK_UART2);
514}
515
516static void
517s3c_irq_uart2_ack(unsigned int irqno)
518{
519 s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
520}
521
522static struct irqchip s3c_irq_uart2 = {
523 .mask = s3c_irq_uart2_mask,
524 .unmask = s3c_irq_uart2_unmask,
525 .ack = s3c_irq_uart2_ack,
526};
527
528/* ADC and Touchscreen */
529
530static void
531s3c_irq_adc_mask(unsigned int irqno)
532{
533 s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
534}
535
536static void
537s3c_irq_adc_unmask(unsigned int irqno)
538{
539 s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
540}
541
542static void
543s3c_irq_adc_ack(unsigned int irqno)
544{
545 s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
546}
547
548static struct irqchip s3c_irq_adc = {
549 .mask = s3c_irq_adc_mask,
550 .unmask = s3c_irq_adc_unmask,
551 .ack = s3c_irq_adc_ack,
552};
553
554/* irq demux for adc */
555static void s3c_irq_demux_adc(unsigned int irq,
556 struct irqdesc *desc,
557 struct pt_regs *regs)
558{
559 unsigned int subsrc, submsk;
560 unsigned int offset = 9;
561 struct irqdesc *mydesc;
562
563 /* read the current pending interrupts, and the mask
564 * for what it is available */
565
566 subsrc = __raw_readl(S3C2410_SUBSRCPND);
567 submsk = __raw_readl(S3C2410_INTSUBMSK);
568
569 subsrc &= ~submsk;
570 subsrc >>= offset;
571 subsrc &= 3;
572
573 if (subsrc != 0) {
574 if (subsrc & 1) {
575 mydesc = irq_desc + IRQ_TC;
576 mydesc->handle( IRQ_TC, mydesc, regs);
577 }
578 if (subsrc & 2) {
579 mydesc = irq_desc + IRQ_ADC;
580 mydesc->handle(IRQ_ADC, mydesc, regs);
581 }
582 }
583}
584
585static void s3c_irq_demux_uart(unsigned int start,
586 struct pt_regs *regs)
587{
588 unsigned int subsrc, submsk;
589 unsigned int offset = start - IRQ_S3CUART_RX0;
590 struct irqdesc *desc;
591
592 /* read the current pending interrupts, and the mask
593 * for what it is available */
594
595 subsrc = __raw_readl(S3C2410_SUBSRCPND);
596 submsk = __raw_readl(S3C2410_INTSUBMSK);
597
598 irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
599 start, offset, subsrc, submsk);
600
601 subsrc &= ~submsk;
602 subsrc >>= offset;
603 subsrc &= 7;
604
605 if (subsrc != 0) {
606 desc = irq_desc + start;
607
608 if (subsrc & 1)
609 desc->handle(start, desc, regs);
610
611 desc++;
612
613 if (subsrc & 2)
614 desc->handle(start+1, desc, regs);
615
616 desc++;
617
618 if (subsrc & 4)
619 desc->handle(start+2, desc, regs);
620 }
621}
622
623/* uart demux entry points */
624
625static void
626s3c_irq_demux_uart0(unsigned int irq,
627 struct irqdesc *desc,
628 struct pt_regs *regs)
629{
630 irq = irq;
631 s3c_irq_demux_uart(IRQ_S3CUART_RX0, regs);
632}
633
634static void
635s3c_irq_demux_uart1(unsigned int irq,
636 struct irqdesc *desc,
637 struct pt_regs *regs)
638{
639 irq = irq;
640 s3c_irq_demux_uart(IRQ_S3CUART_RX1, regs);
641}
642
643static void
644s3c_irq_demux_uart2(unsigned int irq,
645 struct irqdesc *desc,
646 struct pt_regs *regs)
647{
648 irq = irq;
649 s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
650}
651
652
653/* s3c24xx_init_irq
654 *
655 * Initialise S3C2410 IRQ system
656*/
657
658void __init s3c24xx_init_irq(void)
659{
660 unsigned long pend;
661 unsigned long last;
662 int irqno;
663 int i;
664
665 irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
666
667 /* first, clear all interrupts pending... */
668
669 last = 0;
670 for (i = 0; i < 4; i++) {
671 pend = __raw_readl(S3C2410_EINTPEND);
672
673 if (pend == 0 || pend == last)
674 break;
675
676 __raw_writel(pend, S3C2410_EINTPEND);
677 printk("irq: clearing pending ext status %08x\n", (int)pend);
678 last = pend;
679 }
680
681 last = 0;
682 for (i = 0; i < 4; i++) {
683 pend = __raw_readl(S3C2410_INTPND);
684
685 if (pend == 0 || pend == last)
686 break;
687
688 __raw_writel(pend, S3C2410_SRCPND);
689 __raw_writel(pend, S3C2410_INTPND);
690 printk("irq: clearing pending status %08x\n", (int)pend);
691 last = pend;
692 }
693
694 last = 0;
695 for (i = 0; i < 4; i++) {
696 pend = __raw_readl(S3C2410_SUBSRCPND);
697
698 if (pend == 0 || pend == last)
699 break;
700
701 printk("irq: clearing subpending status %08x\n", (int)pend);
702 __raw_writel(pend, S3C2410_SUBSRCPND);
703 last = pend;
704 }
705
706 /* register the main interrupts */
707
708 irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
709
710 for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {
711 /* set all the s3c2410 internal irqs */
712
713 switch (irqno) {
714 /* deal with the special IRQs (cascaded) */
715
716 case IRQ_UART0:
717 case IRQ_UART1:
718 case IRQ_UART2:
719 case IRQ_LCD:
720 case IRQ_ADCPARENT:
721 set_irq_chip(irqno, &s3c_irq_level_chip);
722 set_irq_handler(irqno, do_level_IRQ);
723 break;
724
725 case IRQ_RESERVED6:
726 case IRQ_RESERVED24:
727 /* no IRQ here */
728 break;
729
730 default:
731 //irqdbf("registering irq %d (s3c irq)\n", irqno);
732 set_irq_chip(irqno, &s3c_irq_chip);
733 set_irq_handler(irqno, do_edge_IRQ);
734 set_irq_flags(irqno, IRQF_VALID);
735 }
736 }
737
738 /* setup the cascade irq handlers */
739
740 set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
741 set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
742 set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
743 set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
744
745
746 /* external interrupts */
747
748 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
749 irqdbf("registering irq %d (ext int)\n", irqno);
750 set_irq_chip(irqno, &s3c_irq_eint0t4);
751 set_irq_handler(irqno, do_edge_IRQ);
752 set_irq_flags(irqno, IRQF_VALID);
753 }
754
755 for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
756 irqdbf("registering irq %d (extended s3c irq)\n", irqno);
757 set_irq_chip(irqno, &s3c_irqext_chip);
758 set_irq_handler(irqno, do_edge_IRQ);
759 set_irq_flags(irqno, IRQF_VALID);
760 }
761
762 /* register the uart interrupts */
763
764 irqdbf("s3c2410: registering external interrupts\n");
765
766 for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
767 irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
768 set_irq_chip(irqno, &s3c_irq_uart0);
769 set_irq_handler(irqno, do_level_IRQ);
770 set_irq_flags(irqno, IRQF_VALID);
771 }
772
773 for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
774 irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
775 set_irq_chip(irqno, &s3c_irq_uart1);
776 set_irq_handler(irqno, do_level_IRQ);
777 set_irq_flags(irqno, IRQF_VALID);
778 }
779
780 for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
781 irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
782 set_irq_chip(irqno, &s3c_irq_uart2);
783 set_irq_handler(irqno, do_level_IRQ);
784 set_irq_flags(irqno, IRQF_VALID);
785 }
786
787 for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
788 irqdbf("registering irq %d (s3c adc irq)\n", irqno);
789 set_irq_chip(irqno, &s3c_irq_adc);
790 set_irq_handler(irqno, do_edge_IRQ);
791 set_irq_flags(irqno, IRQF_VALID);
792 }
793
794 irqdbf("s3c2410: registered interrupt handlers\n");
795}
796
797/* s3c2440 irq code
798*/
799
800#ifdef CONFIG_CPU_S3C2440
801
802/* WDT/AC97 */
803
804static void s3c_irq_demux_wdtac97(unsigned int irq,
805 struct irqdesc *desc,
806 struct pt_regs *regs)
807{
808 unsigned int subsrc, submsk;
809 struct irqdesc *mydesc;
810
811 /* read the current pending interrupts, and the mask
812 * for what it is available */
813
814 subsrc = __raw_readl(S3C2410_SUBSRCPND);
815 submsk = __raw_readl(S3C2410_INTSUBMSK);
816
817 subsrc &= ~submsk;
818 subsrc >>= 13;
819 subsrc &= 3;
820
821 if (subsrc != 0) {
822 if (subsrc & 1) {
823 mydesc = irq_desc + IRQ_S3C2440_WDT;
824 mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
825 }
826 if (subsrc & 2) {
827 mydesc = irq_desc + IRQ_S3C2440_AC97;
828 mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
829 }
830 }
831}
832
833
834#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0))
835
836static void
837s3c_irq_wdtac97_mask(unsigned int irqno)
838{
839 s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
840}
841
842static void
843s3c_irq_wdtac97_unmask(unsigned int irqno)
844{
845 s3c_irqsub_unmask(irqno, INTMSK_WDT);
846}
847
848static void
849s3c_irq_wdtac97_ack(unsigned int irqno)
850{
851 s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
852}
853
854static struct irqchip s3c_irq_wdtac97 = {
855 .mask = s3c_irq_wdtac97_mask,
856 .unmask = s3c_irq_wdtac97_unmask,
857 .ack = s3c_irq_wdtac97_ack,
858};
859
860/* camera irq */
861
862static void s3c_irq_demux_cam(unsigned int irq,
863 struct irqdesc *desc,
864 struct pt_regs *regs)
865{
866 unsigned int subsrc, submsk;
867 struct irqdesc *mydesc;
868
869 /* read the current pending interrupts, and the mask
870 * for what it is available */
871
872 subsrc = __raw_readl(S3C2410_SUBSRCPND);
873 submsk = __raw_readl(S3C2410_INTSUBMSK);
874
875 subsrc &= ~submsk;
876 subsrc >>= 11;
877 subsrc &= 3;
878
879 if (subsrc != 0) {
880 if (subsrc & 1) {
881 mydesc = irq_desc + IRQ_S3C2440_CAM_C;
882 mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
883 }
884 if (subsrc & 2) {
885 mydesc = irq_desc + IRQ_S3C2440_CAM_P;
886 mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
887 }
888 }
889}
890
891#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
892
893static void
894s3c_irq_cam_mask(unsigned int irqno)
895{
896 s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
897}
898
899static void
900s3c_irq_cam_unmask(unsigned int irqno)
901{
902 s3c_irqsub_unmask(irqno, INTMSK_CAM);
903}
904
905static void
906s3c_irq_cam_ack(unsigned int irqno)
907{
908 s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
909}
910
911static struct irqchip s3c_irq_cam = {
912 .mask = s3c_irq_cam_mask,
913 .unmask = s3c_irq_cam_unmask,
914 .ack = s3c_irq_cam_ack,
915};
916
917static int s3c2440_irq_add(struct sys_device *sysdev)
918{
919 unsigned int irqno;
920
921 printk("S3C2440: IRQ Support\n");
922
923 set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
924 set_irq_handler(IRQ_NFCON, do_level_IRQ);
925 set_irq_flags(IRQ_NFCON, IRQF_VALID);
926
927 /* add new chained handler for wdt, ac7 */
928
929 set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
930 set_irq_handler(IRQ_WDT, do_level_IRQ);
931 set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
932
933 for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
934 set_irq_chip(irqno, &s3c_irq_wdtac97);
935 set_irq_handler(irqno, do_level_IRQ);
936 set_irq_flags(irqno, IRQF_VALID);
937 }
938
939 /* add chained handler for camera */
940
941 set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
942 set_irq_handler(IRQ_CAM, do_level_IRQ);
943 set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
944
945 for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
946 set_irq_chip(irqno, &s3c_irq_cam);
947 set_irq_handler(irqno, do_level_IRQ);
948 set_irq_flags(irqno, IRQF_VALID);
949 }
950
951 return 0;
952}
953
954static struct sysdev_driver s3c2440_irq_driver = {
955 .add = s3c2440_irq_add,
956};
957
958static int s3c24xx_irq_driver(void)
959{
960 return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
961}
962
963arch_initcall(s3c24xx_irq_driver);
964
965#endif /* CONFIG_CPU_S3C2440 */
966