diff options
author | Maxime Bizon <mbizon@freebox.fr> | 2011-11-04 14:09:32 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2011-12-07 17:03:03 -0500 |
commit | 37c42a741f6c2c76dc5e61650e5d66dd20540aaf (patch) | |
tree | 7e36523bbbc016e4606966ef45ba006999b93cc2 /arch/mips | |
parent | f61cced99347783c1f3a7464e88b855a5ca6c227 (diff) |
MIPS: BCM63XX: Prepare irq code to handle different external irq hardware implementation.
External irq only works for 6348, change code to prepare support of
other CPUs.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2895/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/bcm63xx/irq.c | 104 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-bcm63xx/bcm63xx_irq.h | 12 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-bcm63xx/irq.h | 7 |
3 files changed, 79 insertions, 44 deletions
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index a81cd828c769..cdf352b040a9 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c | |||
@@ -25,18 +25,32 @@ static void __dispatch_internal(void) __maybe_unused; | |||
25 | #ifdef CONFIG_BCM63XX_CPU_6338 | 25 | #ifdef CONFIG_BCM63XX_CPU_6338 |
26 | #define irq_stat_reg PERF_IRQSTAT_6338_REG | 26 | #define irq_stat_reg PERF_IRQSTAT_6338_REG |
27 | #define irq_mask_reg PERF_IRQMASK_6338_REG | 27 | #define irq_mask_reg PERF_IRQMASK_6338_REG |
28 | #define is_ext_irq_cascaded 0 | ||
29 | #define ext_irq_start 0 | ||
30 | #define ext_irq_end 0 | ||
28 | #endif | 31 | #endif |
29 | #ifdef CONFIG_BCM63XX_CPU_6345 | 32 | #ifdef CONFIG_BCM63XX_CPU_6345 |
30 | #define irq_stat_reg PERF_IRQSTAT_6345_REG | 33 | #define irq_stat_reg PERF_IRQSTAT_6345_REG |
31 | #define irq_mask_reg PERF_IRQMASK_6345_REG | 34 | #define irq_mask_reg PERF_IRQMASK_6345_REG |
35 | #define is_ext_irq_cascaded 0 | ||
36 | #define ext_irq_start 0 | ||
37 | #define ext_irq_end 0 | ||
32 | #endif | 38 | #endif |
33 | #ifdef CONFIG_BCM63XX_CPU_6348 | 39 | #ifdef CONFIG_BCM63XX_CPU_6348 |
34 | #define irq_stat_reg PERF_IRQSTAT_6348_REG | 40 | #define irq_stat_reg PERF_IRQSTAT_6348_REG |
35 | #define irq_mask_reg PERF_IRQMASK_6348_REG | 41 | #define irq_mask_reg PERF_IRQMASK_6348_REG |
42 | #define dispatch_internal __dispatch_internal | ||
43 | #define is_ext_irq_cascaded 0 | ||
44 | #define ext_irq_start 0 | ||
45 | #define ext_irq_end 0 | ||
36 | #endif | 46 | #endif |
37 | #ifdef CONFIG_BCM63XX_CPU_6358 | 47 | #ifdef CONFIG_BCM63XX_CPU_6358 |
38 | #define irq_stat_reg PERF_IRQSTAT_6358_REG | 48 | #define irq_stat_reg PERF_IRQSTAT_6358_REG |
39 | #define irq_mask_reg PERF_IRQMASK_6358_REG | 49 | #define irq_mask_reg PERF_IRQMASK_6358_REG |
50 | #define dispatch_internal __dispatch_internal | ||
51 | #define is_ext_irq_cascaded 1 | ||
52 | #define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE) | ||
53 | #define ext_irq_end (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE) | ||
40 | #endif | 54 | #endif |
41 | 55 | ||
42 | #define dispatch_internal __dispatch_internal | 56 | #define dispatch_internal __dispatch_internal |
@@ -51,6 +65,8 @@ static inline void bcm63xx_init_irq(void) | |||
51 | 65 | ||
52 | static u32 irq_stat_addr, irq_mask_addr; | 66 | static u32 irq_stat_addr, irq_mask_addr; |
53 | static void (*dispatch_internal)(void); | 67 | static void (*dispatch_internal)(void); |
68 | static int is_ext_irq_cascaded; | ||
69 | static unsigned int ext_irq_start, ext_irq_end; | ||
54 | 70 | ||
55 | static void bcm63xx_init_irq(void) | 71 | static void bcm63xx_init_irq(void) |
56 | { | 72 | { |
@@ -73,6 +89,9 @@ static void bcm63xx_init_irq(void) | |||
73 | case BCM6358_CPU_ID: | 89 | case BCM6358_CPU_ID: |
74 | irq_stat_addr += PERF_IRQSTAT_6358_REG; | 90 | irq_stat_addr += PERF_IRQSTAT_6358_REG; |
75 | irq_mask_addr += PERF_IRQMASK_6358_REG; | 91 | irq_mask_addr += PERF_IRQMASK_6358_REG; |
92 | is_ext_irq_cascaded = 1; | ||
93 | ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE; | ||
94 | ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; | ||
76 | break; | 95 | break; |
77 | default: | 96 | default: |
78 | BUG(); | 97 | BUG(); |
@@ -84,7 +103,11 @@ static void bcm63xx_init_irq(void) | |||
84 | 103 | ||
85 | static inline void handle_internal(int intbit) | 104 | static inline void handle_internal(int intbit) |
86 | { | 105 | { |
87 | do_IRQ(intbit + IRQ_INTERNAL_BASE); | 106 | if (is_ext_irq_cascaded && |
107 | intbit >= ext_irq_start && intbit <= ext_irq_end) | ||
108 | do_IRQ(intbit - ext_irq_start + IRQ_EXTERNAL_BASE); | ||
109 | else | ||
110 | do_IRQ(intbit + IRQ_INTERNAL_BASE); | ||
88 | } | 111 | } |
89 | 112 | ||
90 | /* | 113 | /* |
@@ -128,14 +151,16 @@ asmlinkage void plat_irq_dispatch(void) | |||
128 | do_IRQ(7); | 151 | do_IRQ(7); |
129 | if (cause & CAUSEF_IP2) | 152 | if (cause & CAUSEF_IP2) |
130 | dispatch_internal(); | 153 | dispatch_internal(); |
131 | if (cause & CAUSEF_IP3) | 154 | if (!is_ext_irq_cascaded) { |
132 | do_IRQ(IRQ_EXT_0); | 155 | if (cause & CAUSEF_IP3) |
133 | if (cause & CAUSEF_IP4) | 156 | do_IRQ(IRQ_EXT_0); |
134 | do_IRQ(IRQ_EXT_1); | 157 | if (cause & CAUSEF_IP4) |
135 | if (cause & CAUSEF_IP5) | 158 | do_IRQ(IRQ_EXT_1); |
136 | do_IRQ(IRQ_EXT_2); | 159 | if (cause & CAUSEF_IP5) |
137 | if (cause & CAUSEF_IP6) | 160 | do_IRQ(IRQ_EXT_2); |
138 | do_IRQ(IRQ_EXT_3); | 161 | if (cause & CAUSEF_IP6) |
162 | do_IRQ(IRQ_EXT_3); | ||
163 | } | ||
139 | } while (1); | 164 | } while (1); |
140 | } | 165 | } |
141 | 166 | ||
@@ -143,9 +168,8 @@ asmlinkage void plat_irq_dispatch(void) | |||
143 | * internal IRQs operations: only mask/unmask on PERF irq mask | 168 | * internal IRQs operations: only mask/unmask on PERF irq mask |
144 | * register. | 169 | * register. |
145 | */ | 170 | */ |
146 | static inline void bcm63xx_internal_irq_mask(struct irq_data *d) | 171 | static void internal_irq_mask(unsigned int irq) |
147 | { | 172 | { |
148 | unsigned int irq = d->irq - IRQ_INTERNAL_BASE; | ||
149 | u32 mask; | 173 | u32 mask; |
150 | 174 | ||
151 | mask = bcm_readl(irq_mask_addr); | 175 | mask = bcm_readl(irq_mask_addr); |
@@ -153,9 +177,8 @@ static inline void bcm63xx_internal_irq_mask(struct irq_data *d) | |||
153 | bcm_writel(mask, irq_mask_addr); | 177 | bcm_writel(mask, irq_mask_addr); |
154 | } | 178 | } |
155 | 179 | ||
156 | static void bcm63xx_internal_irq_unmask(struct irq_data *d) | 180 | static void internal_irq_unmask(unsigned int irq) |
157 | { | 181 | { |
158 | unsigned int irq = d->irq - IRQ_INTERNAL_BASE; | ||
159 | u32 mask; | 182 | u32 mask; |
160 | 183 | ||
161 | mask = bcm_readl(irq_mask_addr); | 184 | mask = bcm_readl(irq_mask_addr); |
@@ -163,33 +186,47 @@ static void bcm63xx_internal_irq_unmask(struct irq_data *d) | |||
163 | bcm_writel(mask, irq_mask_addr); | 186 | bcm_writel(mask, irq_mask_addr); |
164 | } | 187 | } |
165 | 188 | ||
189 | static void bcm63xx_internal_irq_mask(struct irq_data *d) | ||
190 | { | ||
191 | internal_irq_mask(d->irq - IRQ_INTERNAL_BASE); | ||
192 | } | ||
193 | |||
194 | static void bcm63xx_internal_irq_unmask(struct irq_data *d) | ||
195 | { | ||
196 | internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE); | ||
197 | } | ||
198 | |||
166 | /* | 199 | /* |
167 | * external IRQs operations: mask/unmask and clear on PERF external | 200 | * external IRQs operations: mask/unmask and clear on PERF external |
168 | * irq control register. | 201 | * irq control register. |
169 | */ | 202 | */ |
170 | static void bcm63xx_external_irq_mask(struct irq_data *d) | 203 | static void bcm63xx_external_irq_mask(struct irq_data *d) |
171 | { | 204 | { |
172 | unsigned int irq = d->irq - IRQ_EXT_BASE; | 205 | unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; |
173 | u32 reg; | 206 | u32 reg; |
174 | 207 | ||
175 | reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); | 208 | reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); |
176 | reg &= ~EXTIRQ_CFG_MASK(irq); | 209 | reg &= ~EXTIRQ_CFG_MASK(irq); |
177 | bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); | 210 | bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); |
211 | if (is_ext_irq_cascaded) | ||
212 | internal_irq_mask(irq + ext_irq_start); | ||
178 | } | 213 | } |
179 | 214 | ||
180 | static void bcm63xx_external_irq_unmask(struct irq_data *d) | 215 | static void bcm63xx_external_irq_unmask(struct irq_data *d) |
181 | { | 216 | { |
182 | unsigned int irq = d->irq - IRQ_EXT_BASE; | 217 | unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; |
183 | u32 reg; | 218 | u32 reg; |
184 | 219 | ||
185 | reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); | 220 | reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); |
186 | reg |= EXTIRQ_CFG_MASK(irq); | 221 | reg |= EXTIRQ_CFG_MASK(irq); |
187 | bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); | 222 | bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); |
223 | if (is_ext_irq_cascaded) | ||
224 | internal_irq_unmask(irq + ext_irq_start); | ||
188 | } | 225 | } |
189 | 226 | ||
190 | static void bcm63xx_external_irq_clear(struct irq_data *d) | 227 | static void bcm63xx_external_irq_clear(struct irq_data *d) |
191 | { | 228 | { |
192 | unsigned int irq = d->irq - IRQ_EXT_BASE; | 229 | unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; |
193 | u32 reg; | 230 | u32 reg; |
194 | 231 | ||
195 | reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); | 232 | reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); |
@@ -197,25 +234,10 @@ static void bcm63xx_external_irq_clear(struct irq_data *d) | |||
197 | bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); | 234 | bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); |
198 | } | 235 | } |
199 | 236 | ||
200 | static unsigned int bcm63xx_external_irq_startup(struct irq_data *d) | ||
201 | { | ||
202 | set_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); | ||
203 | irq_enable_hazard(); | ||
204 | bcm63xx_external_irq_unmask(d); | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static void bcm63xx_external_irq_shutdown(struct irq_data *d) | ||
209 | { | ||
210 | bcm63xx_external_irq_mask(d); | ||
211 | clear_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE)); | ||
212 | irq_disable_hazard(); | ||
213 | } | ||
214 | |||
215 | static int bcm63xx_external_irq_set_type(struct irq_data *d, | 237 | static int bcm63xx_external_irq_set_type(struct irq_data *d, |
216 | unsigned int flow_type) | 238 | unsigned int flow_type) |
217 | { | 239 | { |
218 | unsigned int irq = d->irq - IRQ_EXT_BASE; | 240 | unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; |
219 | u32 reg; | 241 | u32 reg; |
220 | 242 | ||
221 | flow_type &= IRQ_TYPE_SENSE_MASK; | 243 | flow_type &= IRQ_TYPE_SENSE_MASK; |
@@ -275,9 +297,6 @@ static struct irq_chip bcm63xx_internal_irq_chip = { | |||
275 | 297 | ||
276 | static struct irq_chip bcm63xx_external_irq_chip = { | 298 | static struct irq_chip bcm63xx_external_irq_chip = { |
277 | .name = "bcm63xx_epic", | 299 | .name = "bcm63xx_epic", |
278 | .irq_startup = bcm63xx_external_irq_startup, | ||
279 | .irq_shutdown = bcm63xx_external_irq_shutdown, | ||
280 | |||
281 | .irq_ack = bcm63xx_external_irq_clear, | 300 | .irq_ack = bcm63xx_external_irq_clear, |
282 | 301 | ||
283 | .irq_mask = bcm63xx_external_irq_mask, | 302 | .irq_mask = bcm63xx_external_irq_mask, |
@@ -292,6 +311,12 @@ static struct irqaction cpu_ip2_cascade_action = { | |||
292 | .flags = IRQF_NO_THREAD, | 311 | .flags = IRQF_NO_THREAD, |
293 | }; | 312 | }; |
294 | 313 | ||
314 | static struct irqaction cpu_ext_cascade_action = { | ||
315 | .handler = no_action, | ||
316 | .name = "cascade_extirq", | ||
317 | .flags = IRQF_NO_THREAD, | ||
318 | }; | ||
319 | |||
295 | void __init arch_init_irq(void) | 320 | void __init arch_init_irq(void) |
296 | { | 321 | { |
297 | int i; | 322 | int i; |
@@ -302,9 +327,14 @@ void __init arch_init_irq(void) | |||
302 | irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip, | 327 | irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip, |
303 | handle_level_irq); | 328 | handle_level_irq); |
304 | 329 | ||
305 | for (i = IRQ_EXT_BASE; i < IRQ_EXT_BASE + 4; ++i) | 330 | for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + 4; ++i) |
306 | irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip, | 331 | irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip, |
307 | handle_edge_irq); | 332 | handle_edge_irq); |
308 | 333 | ||
309 | setup_irq(IRQ_MIPS_BASE + 2, &cpu_ip2_cascade_action); | 334 | if (!is_ext_irq_cascaded) { |
335 | for (i = 3; i < 7; ++i) | ||
336 | setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action); | ||
337 | } | ||
338 | |||
339 | setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action); | ||
310 | } | 340 | } |
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_irq.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_irq.h index 5f95577c8213..0c3074b871b8 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_irq.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_irq.h | |||
@@ -3,13 +3,11 @@ | |||
3 | 3 | ||
4 | #include <bcm63xx_cpu.h> | 4 | #include <bcm63xx_cpu.h> |
5 | 5 | ||
6 | #define IRQ_MIPS_BASE 0 | ||
7 | #define IRQ_INTERNAL_BASE 8 | 6 | #define IRQ_INTERNAL_BASE 8 |
8 | 7 | #define IRQ_EXTERNAL_BASE 100 | |
9 | #define IRQ_EXT_BASE (IRQ_MIPS_BASE + 3) | 8 | #define IRQ_EXT_0 (IRQ_EXTERNAL_BASE + 0) |
10 | #define IRQ_EXT_0 (IRQ_EXT_BASE + 0) | 9 | #define IRQ_EXT_1 (IRQ_EXTERNAL_BASE + 1) |
11 | #define IRQ_EXT_1 (IRQ_EXT_BASE + 1) | 10 | #define IRQ_EXT_2 (IRQ_EXTERNAL_BASE + 2) |
12 | #define IRQ_EXT_2 (IRQ_EXT_BASE + 2) | 11 | #define IRQ_EXT_3 (IRQ_EXTERNAL_BASE + 3) |
13 | #define IRQ_EXT_3 (IRQ_EXT_BASE + 3) | ||
14 | 12 | ||
15 | #endif /* ! BCM63XX_IRQ_H_ */ | 13 | #endif /* ! BCM63XX_IRQ_H_ */ |
diff --git a/arch/mips/include/asm/mach-bcm63xx/irq.h b/arch/mips/include/asm/mach-bcm63xx/irq.h new file mode 100644 index 000000000000..9332e788a5c9 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm63xx/irq.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __ASM_MACH_BCM63XX_IRQ_H | ||
2 | #define __ASM_MACH_BCM63XX_IRQ_H | ||
3 | |||
4 | #define NR_IRQS 128 | ||
5 | #define MIPS_CPU_IRQ_BASE 0 | ||
6 | |||
7 | #endif | ||