diff options
Diffstat (limited to 'arch/arm/mach-omap2/include/mach/entry-macro.S')
-rw-r--r-- | arch/arm/mach-omap2/include/mach/entry-macro.S | 142 |
1 files changed, 49 insertions, 93 deletions
diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S index 06e64e1fc28a..a48690b90990 100644 --- a/arch/arm/mach-omap2/include/mach/entry-macro.S +++ b/arch/arm/mach-omap2/include/mach/entry-macro.S | |||
@@ -38,41 +38,13 @@ | |||
38 | */ | 38 | */ |
39 | 39 | ||
40 | #ifdef MULTI_OMAP2 | 40 | #ifdef MULTI_OMAP2 |
41 | .pushsection .data | 41 | /* |
42 | omap_irq_base: .word 0 | 42 | * Configure the interrupt base on the first interrupt. |
43 | .popsection | 43 | * See also omap_irq_base_init for setting omap_irq_base. |
44 | 44 | */ | |
45 | /* Configure the interrupt base on the first interrupt */ | ||
46 | .macro get_irqnr_preamble, base, tmp | 45 | .macro get_irqnr_preamble, base, tmp |
47 | 9: | ||
48 | ldr \base, =omap_irq_base @ irq base address | 46 | ldr \base, =omap_irq_base @ irq base address |
49 | ldr \base, [\base, #0] @ irq base value | 47 | ldr \base, [\base, #0] @ irq base value |
50 | cmp \base, #0 @ already configured? | ||
51 | bne 9997f @ nothing to do | ||
52 | |||
53 | mrc p15, 0, \tmp, c0, c0, 0 @ get processor revision | ||
54 | and \tmp, \tmp, #0x000f0000 @ only check architecture | ||
55 | cmp \tmp, #0x00070000 @ is v6? | ||
56 | beq 2400f @ found v6 so it's omap24xx | ||
57 | mrc p15, 0, \tmp, c0, c0, 0 @ get processor revision | ||
58 | and \tmp, \tmp, #0x000000f0 @ check cortex 8 or 9 | ||
59 | cmp \tmp, #0x00000080 @ cortex A-8? | ||
60 | beq 3400f @ found A-8 so it's omap34xx | ||
61 | cmp \tmp, #0x00000090 @ cortex A-9? | ||
62 | beq 4400f @ found A-9 so it's omap44xx | ||
63 | 2400: ldr \base, =OMAP2_IRQ_BASE | ||
64 | ldr \tmp, =omap_irq_base | ||
65 | str \base, [\tmp, #0] | ||
66 | b 9b | ||
67 | 3400: ldr \base, =OMAP3_IRQ_BASE | ||
68 | ldr \tmp, =omap_irq_base | ||
69 | str \base, [\tmp, #0] | ||
70 | b 9b | ||
71 | 4400: ldr \base, =OMAP4_IRQ_BASE | ||
72 | ldr \tmp, =omap_irq_base | ||
73 | str \base, [\tmp, #0] | ||
74 | b 9b | ||
75 | 9997: | ||
76 | .endm | 48 | .endm |
77 | 49 | ||
78 | /* Check the pending interrupts. Note that base already set */ | 50 | /* Check the pending interrupts. Note that base already set */ |
@@ -89,6 +61,14 @@ omap_irq_base: .word 0 | |||
89 | bne 9998f | 61 | bne 9998f |
90 | ldr \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */ | 62 | ldr \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */ |
91 | cmp \irqnr, #0x0 | 63 | cmp \irqnr, #0x0 |
64 | bne 9998f | ||
65 | |||
66 | /* | ||
67 | * ti816x has additional IRQ pending register. Checking this | ||
68 | * register on omap2 & omap3 has no effect (read as 0). | ||
69 | */ | ||
70 | ldr \irqnr, [\base, #0xf8] /* IRQ pending reg 4 */ | ||
71 | cmp \irqnr, #0x0 | ||
92 | 9998: | 72 | 9998: |
93 | ldrne \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET] | 73 | ldrne \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET] |
94 | and \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */ | 74 | and \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */ |
@@ -105,6 +85,35 @@ omap_irq_base: .word 0 | |||
105 | 9999: | 85 | 9999: |
106 | .endm | 86 | .endm |
107 | 87 | ||
88 | #ifdef CONFIG_SMP | ||
89 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
90 | * register) is preserved from the macro above. | ||
91 | * If there is an IPI, we immediately signal end of interrupt | ||
92 | * on the controller, since this requires the original irqstat | ||
93 | * value which we won't easily be able to recreate later. | ||
94 | */ | ||
95 | |||
96 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
97 | bic \irqnr, \irqstat, #0x1c00 | ||
98 | cmp \irqnr, #16 | ||
99 | it cc | ||
100 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
101 | it cs | ||
102 | cmpcs \irqnr, \irqnr | ||
103 | .endm | ||
104 | |||
105 | /* As above, this assumes that irqstat and base are preserved */ | ||
106 | |||
107 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
108 | bic \irqnr, \irqstat, #0x1c00 | ||
109 | mov \tmp, #0 | ||
110 | cmp \irqnr, #29 | ||
111 | itt eq | ||
112 | moveq \tmp, #1 | ||
113 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
114 | cmp \tmp, #0 | ||
115 | .endm | ||
116 | #endif /* CONFIG_SMP */ | ||
108 | 117 | ||
109 | #else /* MULTI_OMAP2 */ | 118 | #else /* MULTI_OMAP2 */ |
110 | 119 | ||
@@ -132,6 +141,11 @@ omap_irq_base: .word 0 | |||
132 | bne 9999f | 141 | bne 9999f |
133 | ldr \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */ | 142 | ldr \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */ |
134 | cmp \irqnr, #0x0 | 143 | cmp \irqnr, #0x0 |
144 | #ifdef CONFIG_SOC_OMAPTI816X | ||
145 | bne 9999f | ||
146 | ldr \irqnr, [\base, #0xf8] /* IRQ pending reg 4 */ | ||
147 | cmp \irqnr, #0x0 | ||
148 | #endif | ||
135 | 9999: | 149 | 9999: |
136 | ldrne \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET] | 150 | ldrne \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET] |
137 | and \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */ | 151 | and \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */ |
@@ -141,74 +155,16 @@ omap_irq_base: .word 0 | |||
141 | 155 | ||
142 | 156 | ||
143 | #ifdef CONFIG_ARCH_OMAP4 | 157 | #ifdef CONFIG_ARCH_OMAP4 |
158 | #define HAVE_GET_IRQNR_PREAMBLE | ||
159 | #include <asm/hardware/entry-macro-gic.S> | ||
144 | 160 | ||
145 | .macro get_irqnr_preamble, base, tmp | 161 | .macro get_irqnr_preamble, base, tmp |
146 | ldr \base, =OMAP4_IRQ_BASE | 162 | ldr \base, =OMAP4_IRQ_BASE |
147 | .endm | 163 | .endm |
148 | 164 | ||
149 | /* | ||
150 | * The interrupt numbering scheme is defined in the | ||
151 | * interrupt controller spec. To wit: | ||
152 | * | ||
153 | * Interrupts 0-15 are IPI | ||
154 | * 16-28 are reserved | ||
155 | * 29-31 are local. We allow 30 to be used for the watchdog. | ||
156 | * 32-1020 are global | ||
157 | * 1021-1022 are reserved | ||
158 | * 1023 is "spurious" (no interrupt) | ||
159 | * | ||
160 | * For now, we ignore all local interrupts so only return an | ||
161 | * interrupt if it's between 30 and 1020. The test_for_ipi | ||
162 | * routine below will pick up on IPIs. | ||
163 | * A simple read from the controller will tell us the number | ||
164 | * of the highest priority enabled interrupt. | ||
165 | * We then just need to check whether it is in the | ||
166 | * valid range for an IRQ (30-1020 inclusive). | ||
167 | */ | ||
168 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
169 | ldr \irqstat, [\base, #GIC_CPU_INTACK] | ||
170 | |||
171 | ldr \tmp, =1021 | ||
172 | |||
173 | bic \irqnr, \irqstat, #0x1c00 | ||
174 | |||
175 | cmp \irqnr, #29 | ||
176 | cmpcc \irqnr, \irqnr | ||
177 | cmpne \irqnr, \tmp | ||
178 | cmpcs \irqnr, \irqnr | ||
179 | .endm | ||
180 | #endif | 165 | #endif |
181 | #endif /* MULTI_OMAP2 */ | ||
182 | 166 | ||
183 | #ifdef CONFIG_SMP | 167 | #endif /* MULTI_OMAP2 */ |
184 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
185 | * register) is preserved from the macro above. | ||
186 | * If there is an IPI, we immediately signal end of interrupt | ||
187 | * on the controller, since this requires the original irqstat | ||
188 | * value which we won't easily be able to recreate later. | ||
189 | */ | ||
190 | |||
191 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
192 | bic \irqnr, \irqstat, #0x1c00 | ||
193 | cmp \irqnr, #16 | ||
194 | it cc | ||
195 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
196 | it cs | ||
197 | cmpcs \irqnr, \irqnr | ||
198 | .endm | ||
199 | |||
200 | /* As above, this assumes that irqstat and base are preserved */ | ||
201 | |||
202 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
203 | bic \irqnr, \irqstat, #0x1c00 | ||
204 | mov \tmp, #0 | ||
205 | cmp \irqnr, #29 | ||
206 | itt eq | ||
207 | moveq \tmp, #1 | ||
208 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
209 | cmp \tmp, #0 | ||
210 | .endm | ||
211 | #endif /* CONFIG_SMP */ | ||
212 | 168 | ||
213 | .macro irq_prio_table | 169 | .macro irq_prio_table |
214 | .endm | 170 | .endm |