diff options
author | Ben Dooks <ben-linux@fluff.org> | 2006-04-01 18:09:26 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-04-01 18:09:26 -0500 |
commit | 26f91fd54dba57a9bfe2373242ad71792d7af610 (patch) | |
tree | ff89e26139d4de3530a80fb7bf65f58826c95acc | |
parent | 23759dc6430428897a36c4d493f611eca55c9481 (diff) |
[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>
-rw-r--r-- | include/asm-arm/arch-s3c2410/entry-macro.S | 167 |
1 files changed, 67 insertions, 100 deletions
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S index cc06b1bd37b2..894c35cf3b1e 100644 --- a/include/asm-arm/arch-s3c2410/entry-macro.S +++ b/include/asm-arm/arch-s3c2410/entry-macro.S | |||
@@ -6,116 +6,83 @@ | |||
6 | * This file is licensed under the terms of the GNU General Public | 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 | 7 | * License version 2. This program is licensed "as is" without any |
8 | * warranty of any kind, whether express or implied. | 8 | * warranty of any kind, whether express or implied. |
9 | */ | ||
10 | |||
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 | ||
17 | */ | ||
18 | |||
19 | #define INTPND (0x10) | ||
20 | #define INTOFFSET (0x14) | ||
21 | #define EXTINTPEND (0xa8) | ||
22 | #define EXTINTMASK (0xa4) | ||
9 | 23 | ||
10 | * Modifications: | ||
11 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA | ||
12 | */ | ||
13 | #include <asm/hardware.h> | 24 | #include <asm/hardware.h> |
14 | #include <asm/arch/irqs.h> | 25 | #include <asm/arch/irqs.h> |
15 | 26 | ||
16 | |||
17 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | 27 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp |
18 | 28 | ||
19 | mov \tmp, #S3C24XX_VA_IRQ | 29 | mov \base, #S3C24XX_VA_IRQ |
20 | ldr \irqnr, [ \tmp, #0x14 ] @ get irq no | 30 | |
21 | 30000: | 31 | ldr \irqstat, [ \base, #INTPND] |
22 | teq \irqnr, #4 | 32 | bics \irqnr, \irqstat, #3<<4 @@ only an GPIO IRQ |
23 | teqne \irqnr, #5 | 33 | beq 2000f |
24 | beq 1002f @ external irq reg | 34 | |
25 | 35 | @@ try the interrupt offset register, since it is there | |
26 | @ debug check to see if interrupt reported is the same | 36 | |
27 | @ as the offset.... | 37 | ldr \irqnr, [ \base, #INTOFFSET ] |
28 | 38 | mov \tmp, #1 | |
29 | teq \irqnr, #0 | 39 | tst \irqstat, \tmp, lsl \irqnr |
30 | beq 20002f | 40 | addne \irqnr, \irqnr, #IRQ_EINT0 |
31 | ldr \irqstat, [ \tmp, #0x10 ] @ INTPND | 41 | bne 1001f |
32 | mov \irqstat, \irqstat, lsr \irqnr | 42 | |
33 | tst \irqstat, #1 | 43 | @@ the number specified is not a valid irq, so try |
34 | bne 20002f | 44 | @@ and work it out for ourselves |
35 | 45 | ||
36 | /* debug/warning if we get an invalud response from the | 46 | mov \irqnr, #IRQ_EINT0 @@ start here |
37 | * INTOFFSET register */ | 47 | b 3000f |
38 | #if 1 | 48 | |
39 | stmfd r13!, { r0 - r4 , r8-r12, r14 } | 49 | 2000: |
40 | ldr r1, [ \tmp, #0x14 ] @ INTOFFSET | 50 | @@ load the GPIO interrupt register, and check it |
41 | ldr r2, [ \tmp, #0x10 ] @ INTPND | 51 | |
42 | ldr r3, [ \tmp, #0x00 ] @ SRCPND | 52 | add \tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ |
43 | adr r0, 20003f | 53 | ldr \irqstat, [ \tmp, # EXTINTPEND ] |
44 | bl printk | 54 | ldr \irqnr, [ \tmp, # EXTINTMASK ] |
45 | b 20004f | 55 | bics \irqstat, \irqstat, \irqnr |
46 | 56 | beq 1001f | |
47 | 20003: | 57 | |
48 | .ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n" | 58 | mov \irqnr, #(IRQ_EINT4 - 4) |
49 | .byte 0 | 59 | |
50 | .align 4 | 60 | @@ work out which irq (if any) we got |
51 | 20004: | 61 | 3000: |
52 | mov r1, #1 | 62 | movs \tmp, \irqstat, lsl#16 |
53 | mov \tmp, #S3C24XX_VA_IRQ | 63 | addeq \irqnr, \irqnr, #16 |
54 | ldmfd r13!, { r0 - r4 , r8-r12, r14 } | 64 | moveq \irqstat, \irqstat, lsr#16 |
55 | #endif | 65 | tst \irqstat, #0xff |
56 | 66 | addeq \irqnr, \irqnr, #8 | |
57 | @ try working out interrupt number for ourselves | 67 | moveq \irqstat, \irqstat, lsr#8 |
58 | mov \irqnr, #0 | 68 | tst \irqstat, #0xf |
59 | ldr \irqstat, [ \tmp, #0x10 ] @ INTPND | 69 | addeq \irqnr, \irqnr, #4 |
60 | 10021: | 70 | moveq \irqstat, \irqstat, lsr#4 |
61 | movs \irqstat, \irqstat, lsr#1 | 71 | tst \irqstat, #0x3 |
62 | bcs 30000b @ try and re-start the proccess | 72 | addeq \irqnr, \irqnr, #2 |
63 | add \irqnr, \irqnr, #1 | 73 | moveq \irqstat, \irqstat, lsr#2 |
64 | cmp \irqnr, #32 | 74 | tst \irqstat, #0x1 |
65 | ble 10021b | 75 | addeq \irqnr, \irqnr, #1 |
66 | 76 | ||
67 | @ found no interrupt, set Z flag and leave | 77 | @@ we have the value |
68 | movs \irqnr, #0 | 78 | movs \irqnr, \irqnr |
69 | b 1001f | 79 | |
70 | |||
71 | 20005: | ||
72 | 20002: @ exit | ||
73 | @ we base the s3c2410x interrupts at 16 and above to allow | ||
74 | @ isa peripherals to have their standard interrupts, also | ||
75 | @ ensure that Z flag is un-set on exit | ||
76 | |||
77 | @ note, we cannot be sure if we get IRQ_EINT0 (0) that | ||
78 | @ there is simply no interrupt pending, so in all other | ||
79 | @ cases we jump to say we have found something, otherwise | ||
80 | @ we check to see if the interrupt really is assrted | ||
81 | adds \irqnr, \irqnr, #IRQ_EINT0 | ||
82 | teq \irqnr, #IRQ_EINT0 | ||
83 | bne 1001f @ exit | ||
84 | ldr \irqstat, [ \tmp, #0x10 ] @ INTPND | ||
85 | teq \irqstat, #0 | ||
86 | moveq \irqnr, #0 | ||
87 | b 1001f | ||
88 | |||
89 | @ we get here from no main or external interrupts pending | ||
90 | 1002: | ||
91 | add \tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ | ||
92 | ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND | ||
93 | ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK | ||
94 | |||
95 | bic \irqstat, \irqstat, \irqnr @ clear masked irqs | ||
96 | |||
97 | mov \irqnr, #IRQ_EINT4 @ start extint nos | ||
98 | mov \irqstat, \irqstat, lsr#4 @ ignore bottom 4 bits | ||
99 | 10021: | ||
100 | movs \irqstat, \irqstat, lsr#1 | ||
101 | bcs 1004f | ||
102 | add \irqnr, \irqnr, #1 | ||
103 | cmp \irqnr, #IRQ_EINT23 | ||
104 | ble 10021b | ||
105 | |||
106 | @ found no interrupt, set Z flag and leave | ||
107 | movs \irqnr, #0 | ||
108 | |||
109 | 1004: @ ensure Z flag clear in case our MOVS shifted out the last bit | ||
110 | teq \irqnr, #0 | ||
111 | 1001: | 80 | 1001: |
112 | @ exit irq routine | 81 | @@ exit here, Z flag unset if IRQ |
113 | .endm | ||
114 | 82 | ||
83 | .endm | ||
115 | 84 | ||
116 | /* currently don't need an disable_fiq macro */ | 85 | /* currently don't need an disable_fiq macro */ |
117 | 86 | ||
118 | .macro disable_fiq | 87 | .macro disable_fiq |
119 | .endm | 88 | .endm |
120 | |||
121 | |||