aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2006-06-24 16:21:37 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-24 16:21:37 -0400
commita019f4a9a7b4ec4986918e9aefa06815cf77b714 (patch)
tree52f98219bc0d86e6c55e48513a6dcfa93a0cb44c
parent22346aea8d39372d6fd207468701e90bf546b882 (diff)
[ARM] 3645/1: S3C2412: irq support for external interrupts
Patch from Ben Dooks Move the decoding of the IRQ_EXT4 and above out of the entry macro, and into an chained irq handler as the EXTINT registers move depending on the CPU being used. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-s3c2410/irq.c49
-rw-r--r--include/asm-arm/arch-s3c2410/entry-macro.S30
-rw-r--r--include/asm-arm/arch-s3c2410/regs-irq.h6
3 files changed, 46 insertions, 39 deletions
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 46465742ed79..6822dc7f7799 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -191,13 +191,9 @@ static struct irqchip s3c_irq_chip = {
191 .ack = s3c_irq_ack, 191 .ack = s3c_irq_ack,
192 .mask = s3c_irq_mask, 192 .mask = s3c_irq_mask,
193 .unmask = s3c_irq_unmask, 193 .unmask = s3c_irq_unmask,
194 .set_wake = s3c_irq_wake 194 .set_wake = s3c_irq_wake
195}; 195};
196 196
197/* S3C2410_EINTMASK
198 * S3C2410_EINTPEND
199 */
200
201static void 197static void
202s3c_irqext_mask(unsigned int irqno) 198s3c_irqext_mask(unsigned int irqno)
203{ 199{
@@ -205,9 +201,9 @@ s3c_irqext_mask(unsigned int irqno)
205 201
206 irqno -= EXTINT_OFF; 202 irqno -= EXTINT_OFF;
207 203
208 mask = __raw_readl(S3C2410_EINTMASK); 204 mask = __raw_readl(S3C24XX_EINTMASK);
209 mask |= ( 1UL << irqno); 205 mask |= ( 1UL << irqno);
210 __raw_writel(mask, S3C2410_EINTMASK); 206 __raw_writel(mask, S3C24XX_EINTMASK);
211 207
212 if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) { 208 if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
213 /* check to see if all need masking */ 209 /* check to see if all need masking */
@@ -232,11 +228,11 @@ s3c_irqext_ack(unsigned int irqno)
232 bit = 1UL << (irqno - EXTINT_OFF); 228 bit = 1UL << (irqno - EXTINT_OFF);
233 229
234 230
235 mask = __raw_readl(S3C2410_EINTMASK); 231 mask = __raw_readl(S3C24XX_EINTMASK);
236 232
237 __raw_writel(bit, S3C2410_EINTPEND); 233 __raw_writel(bit, S3C24XX_EINTPEND);
238 234
239 req = __raw_readl(S3C2410_EINTPEND); 235 req = __raw_readl(S3C24XX_EINTPEND);
240 req &= ~mask; 236 req &= ~mask;
241 237
242 /* not sure if we should be acking the parent irq... */ 238 /* not sure if we should be acking the parent irq... */
@@ -257,9 +253,9 @@ s3c_irqext_unmask(unsigned int irqno)
257 253
258 irqno -= EXTINT_OFF; 254 irqno -= EXTINT_OFF;
259 255
260 mask = __raw_readl(S3C2410_EINTMASK); 256 mask = __raw_readl(S3C24XX_EINTMASK);
261 mask &= ~( 1UL << irqno); 257 mask &= ~( 1UL << irqno);
262 __raw_writel(mask, S3C2410_EINTMASK); 258 __raw_writel(mask, S3C24XX_EINTMASK);
263 259
264 s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23); 260 s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
265} 261}
@@ -572,6 +568,23 @@ s3c_irq_demux_uart2(unsigned int irq,
572 s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs); 568 s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
573} 569}
574 570
571static void
572s3c_irq_demux_extint(unsigned int irq,
573 struct irqdesc *desc,
574 struct pt_regs *regs)
575{
576 unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
577 unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
578
579 eintpnd &= ~eintmsk;
580
581 if (eintpnd) {
582 irq = fls(eintpnd);
583 irq += (IRQ_EINT4 - (4 + 1));
584
585 desc_handle_irq(irq, irq_desc + irq, regs);
586 }
587}
575 588
576/* s3c24xx_init_irq 589/* s3c24xx_init_irq
577 * 590 *
@@ -591,12 +604,12 @@ void __init s3c24xx_init_irq(void)
591 604
592 last = 0; 605 last = 0;
593 for (i = 0; i < 4; i++) { 606 for (i = 0; i < 4; i++) {
594 pend = __raw_readl(S3C2410_EINTPEND); 607 pend = __raw_readl(S3C24XX_EINTPEND);
595 608
596 if (pend == 0 || pend == last) 609 if (pend == 0 || pend == last)
597 break; 610 break;
598 611
599 __raw_writel(pend, S3C2410_EINTPEND); 612 __raw_writel(pend, S3C24XX_EINTPEND);
600 printk("irq: clearing pending ext status %08x\n", (int)pend); 613 printk("irq: clearing pending ext status %08x\n", (int)pend);
601 last = pend; 614 last = pend;
602 } 615 }
@@ -630,12 +643,14 @@ void __init s3c24xx_init_irq(void)
630 643
631 irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); 644 irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
632 645
633 for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) { 646 for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
634 /* set all the s3c2410 internal irqs */ 647 /* set all the s3c2410 internal irqs */
635 648
636 switch (irqno) { 649 switch (irqno) {
637 /* deal with the special IRQs (cascaded) */ 650 /* deal with the special IRQs (cascaded) */
638 651
652 case IRQ_EINT4t7:
653 case IRQ_EINT8t23:
639 case IRQ_UART0: 654 case IRQ_UART0:
640 case IRQ_UART1: 655 case IRQ_UART1:
641 case IRQ_UART2: 656 case IRQ_UART2:
@@ -659,12 +674,14 @@ void __init s3c24xx_init_irq(void)
659 674
660 /* setup the cascade irq handlers */ 675 /* setup the cascade irq handlers */
661 676
677 set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint);
678 set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint);
679
662 set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); 680 set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
663 set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); 681 set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
664 set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); 682 set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
665 set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); 683 set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
666 684
667
668 /* external interrupts */ 685 /* external interrupts */
669 686
670 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { 687 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index 894c35cf3b1e..e09a6b8ec153 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -18,8 +18,6 @@
18 18
19#define INTPND (0x10) 19#define INTPND (0x10)
20#define INTOFFSET (0x14) 20#define INTOFFSET (0x14)
21#define EXTINTPEND (0xa8)
22#define EXTINTMASK (0xa4)
23 21
24#include <asm/hardware.h> 22#include <asm/hardware.h>
25#include <asm/arch/irqs.h> 23#include <asm/arch/irqs.h>
@@ -28,37 +26,23 @@
28 26
29 mov \base, #S3C24XX_VA_IRQ 27 mov \base, #S3C24XX_VA_IRQ
30 28
31 ldr \irqstat, [ \base, #INTPND]
32 bics \irqnr, \irqstat, #3<<4 @@ only an GPIO IRQ
33 beq 2000f
34
35 @@ try the interrupt offset register, since it is there 29 @@ try the interrupt offset register, since it is there
36 30
31 ldr \irqstat, [ \base, #INTPND ]
32 teq \irqstat, #0
33 beq 1002f
37 ldr \irqnr, [ \base, #INTOFFSET ] 34 ldr \irqnr, [ \base, #INTOFFSET ]
38 mov \tmp, #1 35 mov \tmp, #1
39 tst \irqstat, \tmp, lsl \irqnr 36 tst \irqstat, \tmp, lsl \irqnr
40 addne \irqnr, \irqnr, #IRQ_EINT0
41 bne 1001f 37 bne 1001f
42 38
43 @@ the number specified is not a valid irq, so try 39 @@ the number specified is not a valid irq, so try
44 @@ and work it out for ourselves 40 @@ and work it out for ourselves
45 41
46 mov \irqnr, #IRQ_EINT0 @@ start here 42 mov \irqnr, #0 @@ start here
47 b 3000f
48
492000:
50 @@ load the GPIO interrupt register, and check it
51
52 add \tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
53 ldr \irqstat, [ \tmp, # EXTINTPEND ]
54 ldr \irqnr, [ \tmp, # EXTINTMASK ]
55 bics \irqstat, \irqstat, \irqnr
56 beq 1001f
57
58 mov \irqnr, #(IRQ_EINT4 - 4)
59 43
60 @@ work out which irq (if any) we got 44 @@ work out which irq (if any) we got
613000: 45
62 movs \tmp, \irqstat, lsl#16 46 movs \tmp, \irqstat, lsl#16
63 addeq \irqnr, \irqnr, #16 47 addeq \irqnr, \irqnr, #16
64 moveq \irqstat, \irqstat, lsr#16 48 moveq \irqstat, \irqstat, lsr#16
@@ -75,9 +59,9 @@
75 addeq \irqnr, \irqnr, #1 59 addeq \irqnr, \irqnr, #1
76 60
77 @@ we have the value 61 @@ we have the value
78 movs \irqnr, \irqnr
79
801001: 621001:
63 adds \irqnr, \irqnr, #IRQ_EINT0
641002:
81 @@ exit here, Z flag unset if IRQ 65 @@ exit here, Z flag unset if IRQ
82 66
83 .endm 67 .endm
diff --git a/include/asm-arm/arch-s3c2410/regs-irq.h b/include/asm-arm/arch-s3c2410/regs-irq.h
index 24b7292df79e..572fca5d9acf 100644
--- a/include/asm-arm/arch-s3c2410/regs-irq.h
+++ b/include/asm-arm/arch-s3c2410/regs-irq.h
@@ -23,6 +23,7 @@
23 23
24#define S3C2410_IRQREG(x) ((x) + S3C24XX_VA_IRQ) 24#define S3C2410_IRQREG(x) ((x) + S3C24XX_VA_IRQ)
25#define S3C2410_EINTREG(x) ((x) + S3C24XX_VA_GPIO) 25#define S3C2410_EINTREG(x) ((x) + S3C24XX_VA_GPIO)
26#define S3C24XX_EINTREG(x) ((x) + S3C24XX_VA_GPIO2)
26 27
27#define S3C2410_SRCPND S3C2410_IRQREG(0x000) 28#define S3C2410_SRCPND S3C2410_IRQREG(0x000)
28#define S3C2410_INTMOD S3C2410_IRQREG(0x004) 29#define S3C2410_INTMOD S3C2410_IRQREG(0x004)
@@ -40,5 +41,10 @@
40 41
41#define S3C2410_EINTMASK S3C2410_EINTREG(0x0A4) 42#define S3C2410_EINTMASK S3C2410_EINTREG(0x0A4)
42#define S3C2410_EINTPEND S3C2410_EINTREG(0X0A8) 43#define S3C2410_EINTPEND S3C2410_EINTREG(0X0A8)
44#define S3C2412_EINTMASK S3C2410_EINTREG(0x0B4)
45#define S3C2412_EINTPEND S3C2410_EINTREG(0X0B8)
46
47#define S3C24XX_EINTMASK S3C24XX_EINTREG(0x0A4)
48#define S3C24XX_EINTPEND S3C24XX_EINTREG(0X0A8)
43 49
44#endif /* ___ASM_ARCH_REGS_IRQ_H */ 50#endif /* ___ASM_ARCH_REGS_IRQ_H */