]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
a09e64fb | 2 | * arch/arm/plat-omap/include/mach/entry-macro.S |
1da177e4 LT |
3 | * |
4 | * Low-level IRQ helper macros for OMAP-based platforms | |
5 | * | |
44169075 SS |
6 | * Copyright (C) 2009 Texas Instruments |
7 | * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> | |
8 | * | |
1da177e4 LT |
9 | * This file is licensed under the terms of the GNU General Public |
10 | * License version 2. This program is licensed "as is" without any | |
11 | * warranty of any kind, whether express or implied. | |
12 | */ | |
a09e64fb RK |
13 | #include <mach/hardware.h> |
14 | #include <mach/io.h> | |
15 | #include <mach/irqs.h> | |
44169075 | 16 | #include <asm/hardware/gic.h> |
1da177e4 | 17 | |
ce491cf8 TL |
18 | #include <plat/omap24xx.h> |
19 | #include <plat/omap34xx.h> | |
ce491cf8 | 20 | #include <plat/omap44xx.h> |
9839c6b8 | 21 | |
e735aa8a TL |
22 | #include <plat/multi.h> |
23 | ||
95d2b4e9 TL |
24 | #define OMAP2_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE) |
25 | #define OMAP3_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE) | |
26 | #define OMAP4_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE) | |
27 | #define INTCPS_SIR_IRQ_OFFSET 0x0040 /* omap2/3 active interrupt offset */ | |
28 | #define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */ | |
29 | ||
9839c6b8 TL |
30 | .macro disable_fiq |
31 | .endm | |
32 | ||
1f4d1774 TL |
33 | .macro arch_ret_to_user, tmp1, tmp2 |
34 | .endm | |
35 | ||
e735aa8a TL |
36 | /* |
37 | * Unoptimized irq functions for multi-omap2, 3 and 4 | |
38 | */ | |
95561751 | 39 | |
e735aa8a | 40 | #ifdef MULTI_OMAP2 |
95561751 TL |
41 | .pushsection .data |
42 | omap_irq_base: .word 0 | |
43 | .popsection | |
44 | ||
95561751 TL |
45 | /* Configure the interrupt base on the first interrupt */ |
46 | .macro get_irqnr_preamble, base, tmp | |
47 | 9: | |
48 | ldr \base, =omap_irq_base @ irq base address | |
49 | ldr \base, [\base, #0] @ irq base value | |
50 | cmp \base, #0 @ already configured? | |
61a07c80 | 51 | bne 9997f @ nothing to do |
95561751 TL |
52 | |
53 | mrc p15, 0, \tmp, c0, c0, 0 @ get processor revision | |
54 | and \tmp, \tmp, #0x000f0000 @ only check architecture | |
67d24820 | 55 | cmp \tmp, #0x00070000 @ is v6? |
95561751 | 56 | beq 2400f @ found v6 so it's omap24xx |
61a07c80 TL |
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 | |
95561751 TL |
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 | |
61a07c80 TL |
71 | 4400: ldr \base, =OMAP4_IRQ_BASE |
72 | ldr \tmp, =omap_irq_base | |
73 | str \base, [\tmp, #0] | |
74 | b 9b | |
75 | 9997: | |
95561751 | 76 | .endm |
e735aa8a TL |
77 | |
78 | /* Check the pending interrupts. Note that base already set */ | |
79 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | |
61a07c80 TL |
80 | tst \base, #0x100 @ gic address? |
81 | bne 4401f @ found gic | |
82 | ||
83 | /* Handle omap2 and omap3 */ | |
e735aa8a TL |
84 | ldr \irqnr, [\base, #0x98] /* IRQ pending reg 1 */ |
85 | cmp \irqnr, #0x0 | |
61a07c80 | 86 | bne 9998f |
e735aa8a TL |
87 | ldr \irqnr, [\base, #0xb8] /* IRQ pending reg 2 */ |
88 | cmp \irqnr, #0x0 | |
61a07c80 | 89 | bne 9998f |
e735aa8a TL |
90 | ldr \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */ |
91 | cmp \irqnr, #0x0 | |
61a07c80 | 92 | 9998: |
e735aa8a TL |
93 | ldrne \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET] |
94 | and \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */ | |
61a07c80 TL |
95 | b 9999f |
96 | ||
97 | /* Handle omap4 */ | |
98 | 4401: ldr \irqstat, [\base, #GIC_CPU_INTACK] | |
99 | ldr \tmp, =1021 | |
100 | bic \irqnr, \irqstat, #0x1c00 | |
101 | cmp \irqnr, #29 | |
102 | cmpcc \irqnr, \irqnr | |
103 | cmpne \irqnr, \tmp | |
104 | cmpcs \irqnr, \irqnr | |
105 | 9999: | |
e735aa8a TL |
106 | .endm |
107 | ||
108 | ||
109 | #else /* MULTI_OMAP2 */ | |
110 | ||
111 | ||
112 | /* | |
113 | * Optimized irq functions for omap2, 3 and 4 | |
114 | */ | |
115 | ||
116 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) | |
95561751 TL |
117 | .macro get_irqnr_preamble, base, tmp |
118 | #ifdef CONFIG_ARCH_OMAP2 | |
119 | ldr \base, =OMAP2_IRQ_BASE | |
120 | #else | |
121 | ldr \base, =OMAP3_IRQ_BASE | |
122 | #endif | |
123 | .endm | |
e735aa8a | 124 | |
95561751 | 125 | /* Check the pending interrupts. Note that base already set */ |
9839c6b8 | 126 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp |
9839c6b8 TL |
127 | ldr \irqnr, [\base, #0x98] /* IRQ pending reg 1 */ |
128 | cmp \irqnr, #0x0 | |
95561751 | 129 | bne 9999f |
9839c6b8 TL |
130 | ldr \irqnr, [\base, #0xb8] /* IRQ pending reg 2 */ |
131 | cmp \irqnr, #0x0 | |
95561751 | 132 | bne 9999f |
9839c6b8 TL |
133 | ldr \irqnr, [\base, #0xd8] /* IRQ pending reg 3 */ |
134 | cmp \irqnr, #0x0 | |
95561751 | 135 | 9999: |
cc26b3b0 | 136 | ldrne \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET] |
52414739 | 137 | and \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */ |
9839c6b8 TL |
138 | |
139 | .endm | |
95561751 TL |
140 | #endif |
141 | ||
142 | ||
143 | #ifdef CONFIG_ARCH_OMAP4 | |
144 | ||
95561751 | 145 | .macro get_irqnr_preamble, base, tmp |
be8f3177 | 146 | ldr \base, =OMAP4_IRQ_BASE |
95561751 TL |
147 | .endm |
148 | ||
44169075 SS |
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 | |
44169075 SS |
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 | |
c45bd374 TL |
180 | #endif |
181 | #endif /* MULTI_OMAP2 */ | |
39e1d4c1 | 182 | |
c45bd374 | 183 | #ifdef CONFIG_SMP |
39e1d4c1 SS |
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 | |
c45bd374 | 211 | #endif /* CONFIG_SMP */ |
9839c6b8 TL |
212 | |
213 | .macro irq_prio_table | |
214 | .endm |