1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#include <linux/init.h>
45#include <linux/module.h>
46#include <linux/interrupt.h>
47#include <linux/ioport.h>
48#include <linux/ptrace.h>
49#include <linux/sysdev.h>
50
51#include <asm/hardware.h>
52#include <asm/irq.h>
53#include <asm/io.h>
54
55#include <asm/mach/irq.h>
56
57#include <asm/arch/regs-irq.h>
58#include <asm/arch/regs-gpio.h>
59
60#include "pm.h"
61
62#define irqdbf(x...)
63#define irqdbf2(x...)
64
65#define EXTINT_OFF (IRQ_EINT4 - 4)
66
67
68
69#ifdef CONFIG_PM
70
71
72
73
74
75
76
77
78unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
79unsigned long s3c_irqwake_intmask = 0xffffffffL;
80unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
81unsigned long s3c_irqwake_eintmask = 0xffffffffL;
82
83static int
84s3c_irq_wake(unsigned int irqno, unsigned int state)
85{
86 unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
87
88 if (!(s3c_irqwake_intallow & irqbit))
89 return -ENOENT;
90
91 printk(KERN_INFO "wake %s for irq %d\n",
92 state ? "enabled" : "disabled", irqno);
93
94 if (!state)
95 s3c_irqwake_intmask |= irqbit;
96 else
97 s3c_irqwake_intmask &= ~irqbit;
98
99 return 0;
100}
101
102static int
103s3c_irqext_wake(unsigned int irqno, unsigned int state)
104{
105 unsigned long bit = 1L << (irqno - EXTINT_OFF);
106
107 if (!(s3c_irqwake_eintallow & bit))
108 return -ENOENT;
109
110 printk(KERN_INFO "wake %s for irq %d\n",
111 state ? "enabled" : "disabled", irqno);
112
113 if (!state)
114 s3c_irqwake_eintmask |= bit;
115 else
116 s3c_irqwake_eintmask &= ~bit;
117
118 return 0;
119}
120
121#else
122#define s3c_irqext_wake NULL
123#define s3c_irq_wake NULL
124#endif
125
126
127static void
128s3c_irq_mask(unsigned int irqno)
129{
130 unsigned long mask;
131
132 irqno -= IRQ_EINT0;
133
134 mask = __raw_readl(S3C2410_INTMSK);
135 mask |= 1UL << irqno;
136 __raw_writel(mask, S3C2410_INTMSK);
137}
138
139static inline void
140s3c_irq_ack(unsigned int irqno)
141{
142 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
143
144 __raw_writel(bitval, S3C2410_SRCPND);
145 __raw_writel(bitval, S3C2410_INTPND);
146}
147
148static inline void
149s3c_irq_maskack(unsigned int irqno)
150{
151 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
152 unsigned long mask;
153
154 mask = __raw_readl(S3C2410_INTMSK);
155 __raw_writel(mask|bitval, S3C2410_INTMSK);
156
157 __raw_writel(bitval, S3C2410_SRCPND);
158 __raw_writel(bitval, S3C2410_INTPND);
159}
160
161
162static void
163s3c_irq_unmask(unsigned int irqno)
164{
165 unsigned long mask;
166
167 if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
168 irqdbf2("s3c_irq_unmask %d\n", irqno);
169
170 irqno -= IRQ_EINT0;
171
172 mask = __raw_readl(S3C2410_INTMSK);
173 mask &= ~(1UL << irqno);
174 __raw_writel(mask, S3C2410_INTMSK);
175}
176
177static struct irqchip s3c_irq_level_chip = {
178 .ack = s3c_irq_maskack,
179 .mask = s3c_irq_mask,
180 .unmask = s3c_irq_unmask,
181 .wake = s3c_irq_wake
182};
183
184static struct irqchip s3c_irq_chip = {
185 .ack = s3c_irq_ack,
186 .mask = s3c_irq_mask,
187 .unmask = s3c_irq_unmask,
188 .wake = s3c_irq_wake
189};
190
191
192
193
194
195static void
196s3c_irqext_mask(unsigned int irqno)
197{
198 unsigned long mask;
199
200 irqno -= EXTINT_OFF;
201
202 mask = __raw_readl(S3C2410_EINTMASK);
203 mask |= ( 1UL << irqno);
204 __raw_writel(mask, S3C2410_EINTMASK);
205
206 if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
207
208
209 if ((mask & (0xf << 4)) == (0xf << 4)) {
210
211 s3c_irq_mask(IRQ_EINT4t7);
212 }
213 } else {
214
215
216 }
217}
218
219static void
220s3c_irqext_ack(unsigned int irqno)
221{
222 unsigned long req;
223 unsigned long bit;
224 unsigned long mask;
225
226 bit = 1UL << (irqno - EXTINT_OFF);
227
228
229 mask = __raw_readl(S3C2410_EINTMASK);
230
231 __raw_writel(bit, S3C2410_EINTPEND);
232
233 req = __raw_readl(S3C2410_EINTPEND);
234 req &= ~mask;
235
236
237
238 if (irqno <= IRQ_EINT7 ) {
239 if ((req & 0xf0) == 0)
240 s3c_irq_ack(IRQ_EINT4t7);
241 } else {
242 if ((req >> 8) == 0)
243 s3c_irq_ack(IRQ_EINT8t23);
244 }
245}
246
247static void
248s3c_irqext_unmask(unsigned int irqno)
249{
250 unsigned long mask;
251
252 irqno -= EXTINT_OFF;
253
254 mask = __raw_readl(S3C2410_EINTMASK);
255 mask &= ~( 1UL << irqno);
256 __raw_writel(mask, S3C2410_EINTMASK);
257
258 s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
259}
260
261static int
262s3c_irqext_type(unsigned int irq, unsigned int type)
263{
264 unsigned long extint_reg;
265 unsigned long gpcon_reg;
266 unsigned long gpcon_offset, extint_offset;
267 unsigned long newvalue = 0, value;
268
269 if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
270 {
271 gpcon_reg = S3C2410_GPFCON;
272 extint_reg = S3C2410_EXTINT0;
273 gpcon_offset = (irq - IRQ_EINT0) * 2;
274 extint_offset = (irq - IRQ_EINT0) * 4;
275 }
276 else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
277 {
278 gpcon_reg = S3C2410_GPFCON;
279 extint_reg = S3C2410_EXTINT0;
280 gpcon_offset = (irq - (EXTINT_OFF)) * 2;
281 extint_offset = (irq - (EXTINT_OFF)) * 4;
282 }
283 else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
284 {
285 gpcon_reg = S3C2410_GPGCON;
286 extint_reg = S3C2410_EXTINT1;
287 gpcon_offset = (irq - IRQ_EINT8) * 2;
288 extint_offset = (irq - IRQ_EINT8) * 4;
289 }
290 else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
291 {
292 gpcon_reg = S3C2410_GPGCON;
293 extint_reg = S3C2410_EXTINT2;
294 gpcon_offset = (irq - IRQ_EINT8) * 2;
295 extint_offset = (irq - IRQ_EINT16) * 4;
296 } else
297 return -1;
298
299
300 value = __raw_readl(gpcon_reg);
301 value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
302 __raw_writel(value, gpcon_reg);
303
304
305 switch (type)
306 {
307 case IRQT_NOEDGE:
308 printk(KERN_WARNING "No edge setting!\n");
309 break;
310
311 case IRQT_RISING:
312 newvalue = S3C2410_EXTINT_RISEEDGE;
313 break;
314
315 case IRQT_FALLING:
316 newvalue = S3C2410_EXTINT_FALLEDGE;
317 break;
318
319 case IRQT_BOTHEDGE:
320 newvalue = S3C2410_EXTINT_BOTHEDGE;
321 break;
322
323 case IRQT_LOW:
324 newvalue = S3C2410_EXTINT_LOWLEV;
325 break;
326
327 case IRQT_HIGH:
328 newvalue = S3C2410_EXTINT_HILEV;
329 break;
330
331 default:
332 printk(KERN_ERR "No such irq type %d", type);
333 return -1;
334 }
335
336 value = __raw_readl(extint_reg);
337 value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
338 __raw_writel(value, extint_reg);
339
340 return 0;
341}
342
343static struct irqchip s3c_irqext_chip = {
344 .mask = s3c_irqext_mask,
345 .unmask = s3c_irqext_unmask,
346 .ack = s3c_irqext_ack,
347 .type = s3c_irqext_type,
348 .wake = s3c_irqext_wake
349};
350
351static struct irqchip s3c_irq_eint0t4 = {
352 .ack = s3c_irq_ack,
353 .mask = s3c_irq_mask,
354 .unmask = s3c_irq_unmask,
355 .wake = s3c_irq_wake,
356 .type = s3c_irqext_type,
357};
358
359
360
361#define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0))
362#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0))
363#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
364#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
365#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
366
367static inline void
368s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
369 int subcheck)
370{
371 unsigned long mask;
372 unsigned long submask;
373
374 submask = __raw_readl(S3C2410_INTSUBMSK);
375 mask = __raw_readl(S3C2410_INTMSK);
376
377 submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
378
379
380
381 if ((submask & subcheck) == subcheck) {
382 __raw_writel(mask | parentbit, S3C2410_INTMSK);
383 }
384
385
386 __raw_writel(submask, S3C2410_INTSUBMSK);
387
388}
389
390static inline void
391s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
392{
393 unsigned long mask;
394 unsigned long submask;
395
396 submask = __raw_readl(S3C2410_INTSUBMSK);
397 mask = __raw_readl(S3C2410_INTMSK);
398
399 submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
400 mask &= ~parentbit;
401
402
403 __raw_writel(submask, S3C2410_INTSUBMSK);
404 __raw_writel(mask, S3C2410_INTMSK);
405}
406
407
408static inline void
409s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
410{
411 unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
412
413 s3c_irqsub_mask(irqno, parentmask, group);
414
415 __raw_writel(bit, S3C2410_SUBSRCPND);
416
417
418
419
420
421
422 if (1) {
423 __raw_writel(parentmask, S3C2410_SRCPND);
424 __raw_writel(parentmask, S3C2410_INTPND);
425 }
426}
427
428
429
430
431static void
432s3c_irq_uart0_mask(unsigned int irqno)
433{
434 s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
435}
436
437static void
438s3c_irq_uart0_unmask(unsigned int irqno)
439{
440 s3c_irqsub_unmask(irqno, INTMSK_UART0);
441}
442
443static void
444s3c_irq_uart0_ack(unsigned int irqno)
445{
446 s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
447}
448
449static struct irqchip s3c_irq_uart0 = {
450 .mask = s3c_irq_uart0_mask,
451 .unmask = s3c_irq_uart0_unmask,
452 .ack = s3c_irq_uart0_ack,
453};
454
455
456
457static void
458s3c_irq_uart1_mask(unsigned int irqno)
459{
460 s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
461}
462
463static void
464s3c_irq_uart1_unmask(unsigned int irqno)
465{
466 s3c_irqsub_unmask(irqno, INTMSK_UART1);
467}
468
469static void
470s3c_irq_uart1_ack(unsigned int irqno)
471{
472 s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
473}
474
475static struct irqchip s3c_irq_uart1 = {
476 .mask = s3c_irq_uart1_mask,
477 .unmask = s3c_irq_uart1_unmask,
478 .ack = s3c_irq_uart1_ack,
479};
480
481
482
483static void
484s3c_irq_uart2_mask(unsigned int irqno)
485{
486 s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
487}
488
489static void
490s3c_irq_uart2_unmask(unsigned int irqno)
491{
492 s3c_irqsub_unmask(irqno, INTMSK_UART2);
493}
494
495static void
496s3c_irq_uart2_ack(unsigned int irqno)
497{
498 s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
499}
500
501static struct irqchip s3c_irq_uart2 = {
502 .mask = s3c_irq_uart2_mask,
503 .unmask = s3c_irq_uart2_unmask,
504 .ack = s3c_irq_uart2_ack,
505};
506
507
508
509static void
510s3c_irq_adc_mask(unsigned int irqno)
511{
512 s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
513}
514
515static void
516s3c_irq_adc_unmask(unsigned int irqno)
517{
518 s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
519}
520
521static void
522s3c_irq_adc_ack(unsigned int irqno)
523{
524 s3c_irqsub_maskack(irqno, INTMSK_ADCPARENT, 3 << 9);
525}
526
527static struct irqchip s3c_irq_adc = {
528 .mask = s3c_irq_adc_mask,
529 .unmask = s3c_irq_adc_unmask,
530 .ack = s3c_irq_adc_ack,
531};
532
533
534static void s3c_irq_demux_adc(unsigned int irq,
535 struct irqdesc *desc,
536 struct pt_regs *regs)
537{
538 unsigned int subsrc, submsk;
539 unsigned int offset = 9;
540 struct irqdesc *mydesc;
541
542
543
544
545 subsrc = __raw_readl(S3C2410_SUBSRCPND);
546 submsk = __raw_readl(S3C2410_INTSUBMSK);
547
548 subsrc &= ~submsk;
549 subsrc >>= offset;
550 subsrc &= 3;
551
552 if (subsrc != 0) {
553 if (subsrc & 1) {
554 mydesc = irq_desc + IRQ_TC;
555 mydesc->handle( IRQ_TC, mydesc, regs);
556 }
557 if (subsrc & 2) {
558 mydesc = irq_desc + IRQ_ADC;
559 mydesc->handle(IRQ_ADC, mydesc, regs);
560 }
561 }
562}
563
564static void s3c_irq_demux_uart(unsigned int start,
565 struct pt_regs *regs)
566{
567 unsigned int subsrc, submsk;
568 unsigned int offset = start - IRQ_S3CUART_RX0;
569 struct irqdesc *desc;
570
571
572
573
574 subsrc = __raw_readl(S3C2410_SUBSRCPND);
575 submsk = __raw_readl(S3C2410_INTSUBMSK);
576
577 irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
578 start, offset, subsrc, submsk);
579
580 subsrc &= ~submsk;
581 subsrc >>= offset;
582 subsrc &= 7;
583
584 if (subsrc != 0) {
585 desc = irq_desc + start;
586
587 if (subsrc & 1)
588 desc->handle(start, desc, regs);
589
590 desc++;
591
592 if (subsrc & 2)
593 desc->handle(start+1, desc, regs);
594
595 desc++;
596
597 if (subsrc & 4)
598 desc->handle(start+2, desc, regs);
599 }
600}
601
602
603
604static void
605s3c_irq_demux_uart0(unsigned int irq,
606 struct irqdesc *desc,
607 struct pt_regs *regs)
608{
609 irq = irq;
610 s3c_irq_demux_uart(IRQ_S3CUART_RX0, regs);
611}
612
613static void
614s3c_irq_demux_uart1(unsigned int irq,
615 struct irqdesc *desc,
616 struct pt_regs *regs)
617{
618 irq = irq;
619 s3c_irq_demux_uart(IRQ_S3CUART_RX1, regs);
620}
621
622static void
623s3c_irq_demux_uart2(unsigned int irq,
624 struct irqdesc *desc,
625 struct pt_regs *regs)
626{
627 irq = irq;
628 s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
629}
630
631
632
633
634
635
636void __init s3c24xx_init_irq(void)
637{
638 unsigned long pend;
639 unsigned long last;
640 int irqno;
641 int i;
642
643 irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
644
645
646
647 last = 0;
648 for (i = 0; i < 4; i++) {
649 pend = __raw_readl(S3C2410_EINTPEND);
650
651 if (pend == 0 || pend == last)
652 break;
653
654 __raw_writel(pend, S3C2410_EINTPEND);
655 printk("irq: clearing pending ext status %08x\n", (int)pend);
656 last = pend;
657 }
658
659 last = 0;
660 for (i = 0; i < 4; i++) {
661 pend = __raw_readl(S3C2410_INTPND);
662
663 if (pend == 0 || pend == last)
664 break;
665
666 __raw_writel(pend, S3C2410_SRCPND);
667 __raw_writel(pend, S3C2410_INTPND);
668 printk("irq: clearing pending status %08x\n", (int)pend);
669 last = pend;
670 }
671
672 last = 0;
673 for (i = 0; i < 4; i++) {
674 pend = __raw_readl(S3C2410_SUBSRCPND);
675
676 if (pend == 0 || pend == last)
677 break;
678
679 printk("irq: clearing subpending status %08x\n", (int)pend);
680 __raw_writel(pend, S3C2410_SUBSRCPND);
681 last = pend;
682 }
683
684
685
686 irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
687
688 for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {
689
690
691 switch (irqno) {
692
693
694 case IRQ_UART0:
695 case IRQ_UART1:
696 case IRQ_UART2:
697 case IRQ_LCD:
698 case IRQ_ADCPARENT:
699 set_irq_chip(irqno, &s3c_irq_level_chip);
700 set_irq_handler(irqno, do_level_IRQ);
701 break;
702
703 case IRQ_RESERVED6:
704 case IRQ_RESERVED24:
705
706 break;
707
708 default:
709
710 set_irq_chip(irqno, &s3c_irq_chip);
711 set_irq_handler(irqno, do_edge_IRQ);
712 set_irq_flags(irqno, IRQF_VALID);
713 }
714 }
715
716
717
718 set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
719 set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
720 set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
721 set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
722
723
724
725
726 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
727 irqdbf("registering irq %d (ext int)\n", irqno);
728 set_irq_chip(irqno, &s3c_irq_eint0t4);
729 set_irq_handler(irqno, do_edge_IRQ);
730 set_irq_flags(irqno, IRQF_VALID);
731 }
732
733 for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
734 irqdbf("registering irq %d (extended s3c irq)\n", irqno);
735 set_irq_chip(irqno, &s3c_irqext_chip);
736 set_irq_handler(irqno, do_edge_IRQ);
737 set_irq_flags(irqno, IRQF_VALID);
738 }
739
740
741
742 irqdbf("s3c2410: registering external interrupts\n");
743
744 for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
745 irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
746 set_irq_chip(irqno, &s3c_irq_uart0);
747 set_irq_handler(irqno, do_level_IRQ);
748 set_irq_flags(irqno, IRQF_VALID);
749 }
750
751 for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
752 irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
753 set_irq_chip(irqno, &s3c_irq_uart1);
754 set_irq_handler(irqno, do_level_IRQ);
755 set_irq_flags(irqno, IRQF_VALID);
756 }
757
758 for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
759 irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
760 set_irq_chip(irqno, &s3c_irq_uart2);
761 set_irq_handler(irqno, do_level_IRQ);
762 set_irq_flags(irqno, IRQF_VALID);
763 }
764
765 for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
766 irqdbf("registering irq %d (s3c adc irq)\n", irqno);
767 set_irq_chip(irqno, &s3c_irq_adc);
768 set_irq_handler(irqno, do_edge_IRQ);
769 set_irq_flags(irqno, IRQF_VALID);
770 }
771
772 irqdbf("s3c2410: registered interrupt handlers\n");
773}
774