aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorMaxime Bizon <mbizon@freebox.fr>2011-11-04 14:09:32 -0400
committerRalf Baechle <ralf@linux-mips.org>2011-12-07 17:03:03 -0500
commit37c42a741f6c2c76dc5e61650e5d66dd20540aaf (patch)
tree7e36523bbbc016e4606966ef45ba006999b93cc2 /arch/mips
parentf61cced99347783c1f3a7464e88b855a5ca6c227 (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.c104
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_irq.h12
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/irq.h7
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
52static u32 irq_stat_addr, irq_mask_addr; 66static u32 irq_stat_addr, irq_mask_addr;
53static void (*dispatch_internal)(void); 67static void (*dispatch_internal)(void);
68static int is_ext_irq_cascaded;
69static unsigned int ext_irq_start, ext_irq_end;
54 70
55static void bcm63xx_init_irq(void) 71static 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
85static inline void handle_internal(int intbit) 104static 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 */
146static inline void bcm63xx_internal_irq_mask(struct irq_data *d) 171static 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
156static void bcm63xx_internal_irq_unmask(struct irq_data *d) 180static 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
189static void bcm63xx_internal_irq_mask(struct irq_data *d)
190{
191 internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);
192}
193
194static 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 */
170static void bcm63xx_external_irq_mask(struct irq_data *d) 203static 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
180static void bcm63xx_external_irq_unmask(struct irq_data *d) 215static 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
190static void bcm63xx_external_irq_clear(struct irq_data *d) 227static 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
200static 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
208static 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
215static int bcm63xx_external_irq_set_type(struct irq_data *d, 237static 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
276static struct irq_chip bcm63xx_external_irq_chip = { 298static 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
314static struct irqaction cpu_ext_cascade_action = {
315 .handler = no_action,
316 .name = "cascade_extirq",
317 .flags = IRQF_NO_THREAD,
318};
319
295void __init arch_init_irq(void) 320void __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