[ARM] 3443/1: [S3C2410] Improve IRQ entry code
[linux-2.6/openmoko-kernel/knife-kernel.git] / include / asm-arm / arch-s3c2410 / entry-macro.S
blob894c35cf3b1e25ffbec91a5edd1644955f8f00c2
1 /*
2  * include/asm-arm/arch-s3c2410/entry-macro.S
3  *
4  * Low-level IRQ helper macros for S3C2410-based platforms
5  *
6  * This file is licensed under  the terms of the GNU General Public
7  * License version 2. This program is licensed "as is" without any
8  * warranty of any kind, whether express or implied.
9 */
11 /* We have a problem that the INTOFFSET register does not always
12  * show one interrupt. Occasionally we get two interrupts through
13  * the prioritiser, and this causes the INTOFFSET register to show
14  * what looks like the logical-or of the two interrupt numbers.
15  *
16  * Thanks to Klaus, Shannon, et al for helping to debug this problem
19 #define INTPND          (0x10)
20 #define INTOFFSET       (0x14)
21 #define EXTINTPEND      (0xa8)
22 #define EXTINTMASK      (0xa4)
24 #include <asm/hardware.h>
25 #include <asm/arch/irqs.h>
27         .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
29                 mov     \base, #S3C24XX_VA_IRQ
31                 ldr     \irqstat, [ \base, #INTPND]
32                 bics    \irqnr, \irqstat, #3<<4         @@ only an GPIO IRQ
33                 beq     2000f
35                 @@ try the interrupt offset register, since it is there
37                 ldr     \irqnr, [ \base, #INTOFFSET ]
38                 mov     \tmp, #1
39                 tst     \irqstat, \tmp, lsl \irqnr
40                 addne   \irqnr, \irqnr, #IRQ_EINT0
41                 bne     1001f
43                 @@ the number specified is not a valid irq, so try
44                 @@ and work it out for ourselves
46                 mov     \irqnr, #IRQ_EINT0              @@ start here
47                 b       3000f
49 2000:
50                 @@ load the GPIO interrupt register, and check it
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
58                 mov     \irqnr, #(IRQ_EINT4 - 4)
60                 @@ work out which irq (if any) we got
61 3000:
62                 movs    \tmp, \irqstat, lsl#16
63                 addeq   \irqnr, \irqnr, #16
64                 moveq   \irqstat, \irqstat, lsr#16
65                 tst     \irqstat, #0xff
66                 addeq   \irqnr, \irqnr, #8
67                 moveq   \irqstat, \irqstat, lsr#8
68                 tst     \irqstat, #0xf
69                 addeq   \irqnr, \irqnr, #4
70                 moveq   \irqstat, \irqstat, lsr#4
71                 tst     \irqstat, #0x3
72                 addeq   \irqnr, \irqnr, #2
73                 moveq   \irqstat, \irqstat, lsr#2
74                 tst     \irqstat, #0x1
75                 addeq   \irqnr, \irqnr, #1
77                 @@ we have the value
78                 movs    \irqnr, \irqnr
80 1001:
81                 @@ exit here, Z flag unset if IRQ
83         .endm
85                 /* currently don't need an disable_fiq macro */
87                 .macro  disable_fiq
88                 .endm