aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/bcm63xx
diff options
context:
space:
mode:
authorMaxime Bizon <mbizon@freebox.fr>2011-11-04 14:09:34 -0400
committerRalf Baechle <ralf@linux-mips.org>2011-12-07 17:03:04 -0500
commit6224892c819e96898534c107c72b80a1a8e75abf (patch)
tree4f9f2bc957b221f7dd6f6daea7d993c78813b9ad /arch/mips/bcm63xx
parent71a43927b3bfe1a42cbf7bb174b170f06fa00a1a (diff)
MIPS: BCM63XX: Add external irq support for non 6348 CPUs.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2899/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/bcm63xx')
-rw-r--r--arch/mips/bcm63xx/irq.c131
-rw-r--r--arch/mips/bcm63xx/setup.c30
2 files changed, 127 insertions, 34 deletions
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c
index 11f8942b82dc..9f538846b3f7 100644
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -34,6 +34,9 @@ static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
34#define is_ext_irq_cascaded 0 34#define is_ext_irq_cascaded 0
35#define ext_irq_start 0 35#define ext_irq_start 0
36#define ext_irq_end 0 36#define ext_irq_end 0
37#define ext_irq_count 4
38#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6338
39#define ext_irq_cfg_reg2 0
37#endif 40#endif
38#ifdef CONFIG_BCM63XX_CPU_6345 41#ifdef CONFIG_BCM63XX_CPU_6345
39#define irq_stat_reg PERF_IRQSTAT_6345_REG 42#define irq_stat_reg PERF_IRQSTAT_6345_REG
@@ -42,6 +45,9 @@ static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
42#define is_ext_irq_cascaded 0 45#define is_ext_irq_cascaded 0
43#define ext_irq_start 0 46#define ext_irq_start 0
44#define ext_irq_end 0 47#define ext_irq_end 0
48#define ext_irq_count 0
49#define ext_irq_cfg_reg1 0
50#define ext_irq_cfg_reg2 0
45#endif 51#endif
46#ifdef CONFIG_BCM63XX_CPU_6348 52#ifdef CONFIG_BCM63XX_CPU_6348
47#define irq_stat_reg PERF_IRQSTAT_6348_REG 53#define irq_stat_reg PERF_IRQSTAT_6348_REG
@@ -50,6 +56,9 @@ static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
50#define is_ext_irq_cascaded 0 56#define is_ext_irq_cascaded 0
51#define ext_irq_start 0 57#define ext_irq_start 0
52#define ext_irq_end 0 58#define ext_irq_end 0
59#define ext_irq_count 4
60#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6348
61#define ext_irq_cfg_reg2 0
53#endif 62#endif
54#ifdef CONFIG_BCM63XX_CPU_6358 63#ifdef CONFIG_BCM63XX_CPU_6358
55#define irq_stat_reg PERF_IRQSTAT_6358_REG 64#define irq_stat_reg PERF_IRQSTAT_6358_REG
@@ -58,6 +67,9 @@ static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
58#define is_ext_irq_cascaded 1 67#define is_ext_irq_cascaded 1
59#define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE) 68#define ext_irq_start (BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE)
60#define ext_irq_end (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE) 69#define ext_irq_end (BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE)
70#define ext_irq_count 4
71#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6358
72#define ext_irq_cfg_reg2 0
61#endif 73#endif
62 74
63#if irq_bits == 32 75#if irq_bits == 32
@@ -81,7 +93,9 @@ static inline void bcm63xx_init_irq(void)
81static u32 irq_stat_addr, irq_mask_addr; 93static u32 irq_stat_addr, irq_mask_addr;
82static void (*dispatch_internal)(void); 94static void (*dispatch_internal)(void);
83static int is_ext_irq_cascaded; 95static int is_ext_irq_cascaded;
96static unsigned int ext_irq_count;
84static unsigned int ext_irq_start, ext_irq_end; 97static unsigned int ext_irq_start, ext_irq_end;
98static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
85static void (*internal_irq_mask)(unsigned int irq); 99static void (*internal_irq_mask)(unsigned int irq);
86static void (*internal_irq_unmask)(unsigned int irq); 100static void (*internal_irq_unmask)(unsigned int irq);
87 101
@@ -107,14 +121,18 @@ static void bcm63xx_init_irq(void)
107 irq_stat_addr += PERF_IRQSTAT_6348_REG; 121 irq_stat_addr += PERF_IRQSTAT_6348_REG;
108 irq_mask_addr += PERF_IRQMASK_6348_REG; 122 irq_mask_addr += PERF_IRQMASK_6348_REG;
109 irq_bits = 32; 123 irq_bits = 32;
124 ext_irq_count = 4;
125 ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
110 break; 126 break;
111 case BCM6358_CPU_ID: 127 case BCM6358_CPU_ID:
112 irq_stat_addr += PERF_IRQSTAT_6358_REG; 128 irq_stat_addr += PERF_IRQSTAT_6358_REG;
113 irq_mask_addr += PERF_IRQMASK_6358_REG; 129 irq_mask_addr += PERF_IRQMASK_6358_REG;
114 irq_bits = 32; 130 irq_bits = 32;
131 ext_irq_count = 4;
115 is_ext_irq_cascaded = 1; 132 is_ext_irq_cascaded = 1;
116 ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE; 133 ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
117 ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; 134 ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
135 ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
118 break; 136 break;
119 default: 137 default:
120 BUG(); 138 BUG();
@@ -132,6 +150,13 @@ static void bcm63xx_init_irq(void)
132} 150}
133#endif /* ! BCMCPU_RUNTIME_DETECT */ 151#endif /* ! BCMCPU_RUNTIME_DETECT */
134 152
153static inline u32 get_ext_irq_perf_reg(int irq)
154{
155 if (irq < 4)
156 return ext_irq_cfg_reg1;
157 return ext_irq_cfg_reg2;
158}
159
135static inline void handle_internal(int intbit) 160static inline void handle_internal(int intbit)
136{ 161{
137 if (is_ext_irq_cascaded && 162 if (is_ext_irq_cascaded &&
@@ -273,11 +298,17 @@ static void bcm63xx_internal_irq_unmask(struct irq_data *d)
273static void bcm63xx_external_irq_mask(struct irq_data *d) 298static void bcm63xx_external_irq_mask(struct irq_data *d)
274{ 299{
275 unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; 300 unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
276 u32 reg; 301 u32 reg, regaddr;
277 302
278 reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); 303 regaddr = get_ext_irq_perf_reg(irq);
279 reg &= ~EXTIRQ_CFG_MASK(irq); 304 reg = bcm_perf_readl(regaddr);
280 bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); 305
306 if (BCMCPU_IS_6348())
307 reg &= ~EXTIRQ_CFG_MASK_6348(irq % 4);
308 else
309 reg &= ~EXTIRQ_CFG_MASK(irq % 4);
310
311 bcm_perf_writel(reg, regaddr);
281 if (is_ext_irq_cascaded) 312 if (is_ext_irq_cascaded)
282 internal_irq_mask(irq + ext_irq_start); 313 internal_irq_mask(irq + ext_irq_start);
283} 314}
@@ -285,11 +316,18 @@ static void bcm63xx_external_irq_mask(struct irq_data *d)
285static void bcm63xx_external_irq_unmask(struct irq_data *d) 316static void bcm63xx_external_irq_unmask(struct irq_data *d)
286{ 317{
287 unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; 318 unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
288 u32 reg; 319 u32 reg, regaddr;
320
321 regaddr = get_ext_irq_perf_reg(irq);
322 reg = bcm_perf_readl(regaddr);
323
324 if (BCMCPU_IS_6348())
325 reg |= EXTIRQ_CFG_MASK_6348(irq % 4);
326 else
327 reg |= EXTIRQ_CFG_MASK(irq % 4);
328
329 bcm_perf_writel(reg, regaddr);
289 330
290 reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
291 reg |= EXTIRQ_CFG_MASK(irq);
292 bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
293 if (is_ext_irq_cascaded) 331 if (is_ext_irq_cascaded)
294 internal_irq_unmask(irq + ext_irq_start); 332 internal_irq_unmask(irq + ext_irq_start);
295} 333}
@@ -297,58 +335,93 @@ static void bcm63xx_external_irq_unmask(struct irq_data *d)
297static void bcm63xx_external_irq_clear(struct irq_data *d) 335static void bcm63xx_external_irq_clear(struct irq_data *d)
298{ 336{
299 unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; 337 unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
300 u32 reg; 338 u32 reg, regaddr;
339
340 regaddr = get_ext_irq_perf_reg(irq);
341 reg = bcm_perf_readl(regaddr);
301 342
302 reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); 343 if (BCMCPU_IS_6348())
303 reg |= EXTIRQ_CFG_CLEAR(irq); 344 reg |= EXTIRQ_CFG_CLEAR_6348(irq % 4);
304 bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); 345 else
346 reg |= EXTIRQ_CFG_CLEAR(irq % 4);
347
348 bcm_perf_writel(reg, regaddr);
305} 349}
306 350
307static int bcm63xx_external_irq_set_type(struct irq_data *d, 351static int bcm63xx_external_irq_set_type(struct irq_data *d,
308 unsigned int flow_type) 352 unsigned int flow_type)
309{ 353{
310 unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; 354 unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
311 u32 reg; 355 u32 reg, regaddr;
356 int levelsense, sense, bothedge;
312 357
313 flow_type &= IRQ_TYPE_SENSE_MASK; 358 flow_type &= IRQ_TYPE_SENSE_MASK;
314 359
315 if (flow_type == IRQ_TYPE_NONE) 360 if (flow_type == IRQ_TYPE_NONE)
316 flow_type = IRQ_TYPE_LEVEL_LOW; 361 flow_type = IRQ_TYPE_LEVEL_LOW;
317 362
318 reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); 363 levelsense = sense = bothedge = 0;
319 switch (flow_type) { 364 switch (flow_type) {
320 case IRQ_TYPE_EDGE_BOTH: 365 case IRQ_TYPE_EDGE_BOTH:
321 reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); 366 bothedge = 1;
322 reg |= EXTIRQ_CFG_BOTHEDGE(irq);
323 break; 367 break;
324 368
325 case IRQ_TYPE_EDGE_RISING: 369 case IRQ_TYPE_EDGE_RISING:
326 reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); 370 sense = 1;
327 reg |= EXTIRQ_CFG_SENSE(irq);
328 reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
329 break; 371 break;
330 372
331 case IRQ_TYPE_EDGE_FALLING: 373 case IRQ_TYPE_EDGE_FALLING:
332 reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
333 reg &= ~EXTIRQ_CFG_SENSE(irq);
334 reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
335 break; 374 break;
336 375
337 case IRQ_TYPE_LEVEL_HIGH: 376 case IRQ_TYPE_LEVEL_HIGH:
338 reg |= EXTIRQ_CFG_LEVELSENSE(irq); 377 levelsense = 1;
339 reg |= EXTIRQ_CFG_SENSE(irq); 378 sense = 1;
340 break; 379 break;
341 380
342 case IRQ_TYPE_LEVEL_LOW: 381 case IRQ_TYPE_LEVEL_LOW:
343 reg |= EXTIRQ_CFG_LEVELSENSE(irq); 382 levelsense = 1;
344 reg &= ~EXTIRQ_CFG_SENSE(irq);
345 break; 383 break;
346 384
347 default: 385 default:
348 printk(KERN_ERR "bogus flow type combination given !\n"); 386 printk(KERN_ERR "bogus flow type combination given !\n");
349 return -EINVAL; 387 return -EINVAL;
350 } 388 }
351 bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); 389
390 regaddr = get_ext_irq_perf_reg(irq);
391 reg = bcm_perf_readl(regaddr);
392 irq %= 4;
393
394 if (BCMCPU_IS_6348()) {
395 if (levelsense)
396 reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq);
397 else
398 reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq);
399 if (sense)
400 reg |= EXTIRQ_CFG_SENSE_6348(irq);
401 else
402 reg &= ~EXTIRQ_CFG_SENSE_6348(irq);
403 if (bothedge)
404 reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq);
405 else
406 reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq);
407 }
408
409 if (BCMCPU_IS_6338() || BCMCPU_IS_6358()) {
410 if (levelsense)
411 reg |= EXTIRQ_CFG_LEVELSENSE(irq);
412 else
413 reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
414 if (sense)
415 reg |= EXTIRQ_CFG_SENSE(irq);
416 else
417 reg &= ~EXTIRQ_CFG_SENSE(irq);
418 if (bothedge)
419 reg |= EXTIRQ_CFG_BOTHEDGE(irq);
420 else
421 reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
422 }
423
424 bcm_perf_writel(reg, regaddr);
352 425
353 irqd_set_trigger_type(d, flow_type); 426 irqd_set_trigger_type(d, flow_type);
354 if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) 427 if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -397,12 +470,12 @@ void __init arch_init_irq(void)
397 irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip, 470 irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip,
398 handle_level_irq); 471 handle_level_irq);
399 472
400 for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + 4; ++i) 473 for (i = IRQ_EXTERNAL_BASE; i < IRQ_EXTERNAL_BASE + ext_irq_count; ++i)
401 irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip, 474 irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip,
402 handle_edge_irq); 475 handle_edge_irq);
403 476
404 if (!is_ext_irq_cascaded) { 477 if (!is_ext_irq_cascaded) {
405 for (i = 3; i < 7; ++i) 478 for (i = 3; i < 3 + ext_irq_count; ++i)
406 setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action); 479 setup_irq(MIPS_CPU_IRQ_BASE + i, &cpu_ext_cascade_action);
407 } 480 }
408 481
diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c
index 04a349928643..d209f85d87bb 100644
--- a/arch/mips/bcm63xx/setup.c
+++ b/arch/mips/bcm63xx/setup.c
@@ -63,13 +63,33 @@ static void bcm6348_a1_reboot(void)
63 63
64void bcm63xx_machine_reboot(void) 64void bcm63xx_machine_reboot(void)
65{ 65{
66 u32 reg; 66 u32 reg, perf_regs[2] = { 0, 0 };
67 unsigned int i;
67 68
68 /* mask and clear all external irq */ 69 /* mask and clear all external irq */
69 reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG); 70 switch (bcm63xx_get_cpu_id()) {
70 reg &= ~EXTIRQ_CFG_MASK_ALL; 71 case BCM6338_CPU_ID:
71 reg |= EXTIRQ_CFG_CLEAR_ALL; 72 perf_regs[0] = PERF_EXTIRQ_CFG_REG_6338;
72 bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG); 73 break;
74 case BCM6348_CPU_ID:
75 perf_regs[0] = PERF_EXTIRQ_CFG_REG_6348;
76 break;
77 case BCM6358_CPU_ID:
78 perf_regs[0] = PERF_EXTIRQ_CFG_REG_6358;
79 break;
80 }
81
82 for (i = 0; i < 2; i++) {
83 reg = bcm_perf_readl(perf_regs[i]);
84 if (BCMCPU_IS_6348()) {
85 reg &= ~EXTIRQ_CFG_MASK_ALL_6348;
86 reg |= EXTIRQ_CFG_CLEAR_ALL_6348;
87 } else {
88 reg &= ~EXTIRQ_CFG_MASK_ALL;
89 reg |= EXTIRQ_CFG_CLEAR_ALL;
90 }
91 bcm_perf_writel(reg, perf_regs[i]);
92 }
73 93
74 if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1)) 94 if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1))
75 bcm6348_a1_reboot(); 95 bcm6348_a1_reboot();