[ARM] 3443/1: [S3C2410] Improve IRQ entry code

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>
This commit is contained in:
Ben Dooks
2006-04-02 00:09:26 +01:00
committed by Russell King
parent 23759dc643
commit 26f91fd54d

View File

@@ -6,116 +6,83 @@
* This file is licensed under the terms of the GNU General Public * This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any * License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied. * 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/hardware.h>
#include <asm/arch/irqs.h> #include <asm/arch/irqs.h>
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov \tmp, #S3C24XX_VA_IRQ mov \base, #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 ldr \irqstat, [ \base, #INTPND]
@ as the offset.... bics \irqnr, \irqstat, #3<<4 @@ only an GPIO IRQ
beq 2000f
teq \irqnr, #0 @@ try the interrupt offset register, since it is there
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 ldr \irqnr, [ \base, #INTOFFSET ]
* INTOFFSET register */ mov \tmp, #1
#if 1 tst \irqstat, \tmp, lsl \irqnr
stmfd r13!, { r0 - r4 , r8-r12, r14 } addne \irqnr, \irqnr, #IRQ_EINT0
ldr r1, [ \tmp, #0x14 ] @ INTOFFSET bne 1001f
ldr r2, [ \tmp, #0x10 ] @ INTPND
ldr r3, [ \tmp, #0x00 ] @ SRCPND
adr r0, 20003f
bl printk
b 20004f
20003: @@ the number specified is not a valid irq, so try
.ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n" @@ and work it out for ourselves
.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, #IRQ_EINT0 @@ start here
mov \irqnr, #0 b 3000f
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 2000:
movs \irqnr, #0 @@ load the GPIO interrupt register, and check it
b 1001f
20005: add \tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
20002: @ exit ldr \irqstat, [ \tmp, # EXTINTPEND ]
@ we base the s3c2410x interrupts at 16 and above to allow ldr \irqnr, [ \tmp, # EXTINTMASK ]
@ isa peripherals to have their standard interrupts, also bics \irqstat, \irqstat, \irqnr
@ ensure that Z flag is un-set on exit beq 1001f
@ note, we cannot be sure if we get IRQ_EINT0 (0) that mov \irqnr, #(IRQ_EINT4 - 4)
@ 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 @@ work out which irq (if any) we got
1002: 3000:
add \tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ movs \tmp, \irqstat, lsl#16
ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND addeq \irqnr, \irqnr, #16
ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK 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
bic \irqstat, \irqstat, \irqnr @ clear masked irqs @@ we have the value
movs \irqnr, \irqnr
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
1001: 1001:
@ exit irq routine @@ exit here, Z flag unset if IRQ
.endm
.endm
/* currently don't need an disable_fiq macro */ /* currently don't need an disable_fiq macro */
.macro disable_fiq .macro disable_fiq
.endm .endm