[ARM] 3443/1: [S3C2410] Improve IRQ entry code
authorBen Dooks <ben-linux@fluff.org>
Sat, 1 Apr 2006 23:09:26 +0000 (00:09 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 1 Apr 2006 23:09:26 +0000 (00:09 +0100)
Patch from Ben Dooks

Remove the old debug from the IRQ entry code,
update the comments on the handling of the
IRQ registers.

The message "bad interrupt offset" is removed
as it is only helpful for debugging, and can
cause printk() flooding when under load.

Make the code to deal with GPIO interrupts
faster, and use the same path to deal with
unexplained results from the IRQ registers.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
include/asm-arm/arch-s3c2410/entry-macro.S

index cc06b1bd37b245a5f030feb3ef5955f18c2863b0..894c35cf3b1e25ffbec91a5edd1644955f8f00c2 100644 (file)
  * This file is licensed under  the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
+*/
+
+/* We have a problem that the INTOFFSET register does not always
+ * show one interrupt. Occasionally we get two interrupts through
+ * the prioritiser, and this causes the INTOFFSET register to show
+ * what looks like the logical-or of the two interrupt numbers.
+ *
+ * Thanks to Klaus, Shannon, et al for helping to debug this problem
+*/
+
+#define INTPND         (0x10)
+#define INTOFFSET      (0x14)
+#define EXTINTPEND     (0xa8)
+#define EXTINTMASK     (0xa4)
 
- * Modifications:
- *     10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
- */
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
 
-
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 
-               mov     \tmp, #S3C24XX_VA_IRQ
-               ldr     \irqnr, [ \tmp, #0x14 ]         @ get irq no
-30000:
-               teq     \irqnr, #4
-               teqne   \irqnr, #5
-               beq     1002f                           @ external irq reg
-
-               @ debug check to see if interrupt reported is the same
-               @ as the offset....
-
-               teq     \irqnr, #0
-               beq     20002f
-               ldr     \irqstat, [ \tmp, #0x10 ]       @ INTPND
-               mov     \irqstat, \irqstat, lsr \irqnr
-               tst     \irqstat, #1
-               bne     20002f
-
-               /* debug/warning if we get an invalud response from the
-                * INTOFFSET register */
-#if 1
-               stmfd   r13!, { r0 - r4 , r8-r12, r14 }
-               ldr     r1,     [ \tmp, #0x14 ]         @ INTOFFSET
-               ldr     r2,     [ \tmp, #0x10 ]         @ INTPND
-               ldr     r3,     [ \tmp, #0x00 ]         @ SRCPND
-               adr     r0, 20003f
-               bl      printk
-               b       20004f
-
-20003:
-               .ascii  "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
-               .byte   0
-               .align  4
-20004:
-               mov     r1, #1
-               mov     \tmp, #S3C24XX_VA_IRQ
-               ldmfd   r13!, { r0 - r4 , r8-r12, r14 }
-#endif
-
-               @ try working out interrupt number for ourselves
-               mov     \irqnr, #0
-               ldr     \irqstat, [ \tmp, #0x10 ]       @ INTPND
-10021:
-               movs    \irqstat, \irqstat, lsr#1
-               bcs     30000b          @ try and re-start the proccess
-               add     \irqnr, \irqnr, #1
-               cmp     \irqnr, #32
-               ble     10021b
-
-               @ found no interrupt, set Z flag and leave
-               movs    \irqnr, #0
-               b       1001f
-
-20005:
-20002:         @ exit
-               @ we base the s3c2410x interrupts at 16 and above to allow
-               @ isa peripherals to have their standard interrupts, also
-               @ ensure that Z flag is un-set on exit
-
-               @ note, we cannot be sure if we get IRQ_EINT0 (0) that
-               @ there is simply no interrupt pending, so in all other
-               @ cases we jump to say we have found something, otherwise
-               @ we check to see if the interrupt really is assrted
-               adds    \irqnr, \irqnr, #IRQ_EINT0
-               teq     \irqnr, #IRQ_EINT0
-               bne     1001f                           @ exit
-               ldr     \irqstat, [ \tmp, #0x10 ]       @ INTPND
-               teq     \irqstat, #0
-               moveq   \irqnr, #0
-               b       1001f
-
-               @ we get here from no main or external interrupts pending
-1002:
-               add     \tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
-               ldr     \irqstat, [ \tmp, # 0xa8 ]      @ EXTINTPEND
-               ldr     \irqnr, [ \tmp, # 0xa4 ]        @ EXTINTMASK
-
-               bic     \irqstat, \irqstat, \irqnr      @ clear masked irqs
-
-               mov     \irqnr, #IRQ_EINT4              @ start extint nos
-               mov     \irqstat, \irqstat, lsr#4       @ ignore bottom 4 bits
-10021:
-               movs    \irqstat, \irqstat, lsr#1
-               bcs     1004f
-               add     \irqnr, \irqnr, #1
-               cmp     \irqnr, #IRQ_EINT23
-               ble     10021b
-
-               @ found no interrupt, set Z flag and leave
-               movs    \irqnr, #0
-
-1004:          @ ensure Z flag clear in case our MOVS shifted out the last bit
-               teq     \irqnr, #0
+               mov     \base, #S3C24XX_VA_IRQ
+
+               ldr     \irqstat, [ \base, #INTPND]
+               bics    \irqnr, \irqstat, #3<<4         @@ only an GPIO IRQ
+               beq     2000f
+
+               @@ try the interrupt offset register, since it is there
+
+               ldr     \irqnr, [ \base, #INTOFFSET ]
+               mov     \tmp, #1
+               tst     \irqstat, \tmp, lsl \irqnr
+               addne   \irqnr, \irqnr, #IRQ_EINT0
+               bne     1001f
+
+               @@ the number specified is not a valid irq, so try
+               @@ and work it out for ourselves
+
+               mov     \irqnr, #IRQ_EINT0              @@ start here
+               b       3000f
+
+2000:
+               @@ load the GPIO interrupt register, and check it
+
+               add     \tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
+               ldr     \irqstat, [ \tmp, # EXTINTPEND ]
+               ldr     \irqnr,   [ \tmp, # EXTINTMASK ]
+               bics    \irqstat, \irqstat, \irqnr
+               beq     1001f
+
+               mov     \irqnr, #(IRQ_EINT4 - 4)
+
+               @@ work out which irq (if any) we got
+3000:
+               movs    \tmp, \irqstat, lsl#16
+               addeq   \irqnr, \irqnr, #16
+               moveq   \irqstat, \irqstat, lsr#16
+               tst     \irqstat, #0xff
+               addeq   \irqnr, \irqnr, #8
+               moveq   \irqstat, \irqstat, lsr#8
+               tst     \irqstat, #0xf
+               addeq   \irqnr, \irqnr, #4
+               moveq   \irqstat, \irqstat, lsr#4
+               tst     \irqstat, #0x3
+               addeq   \irqnr, \irqnr, #2
+               moveq   \irqstat, \irqstat, lsr#2
+               tst     \irqstat, #0x1
+               addeq   \irqnr, \irqnr, #1
+
+               @@ we have the value
+               movs    \irqnr, \irqnr
+
 1001:
-               @ exit irq routine
-               .endm
+               @@ exit here, Z flag unset if IRQ
 
+       .endm
 
                /* currently don't need an disable_fiq macro */
 
                .macro  disable_fiq
                .endm
-
-