aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorAndrew Bresticker <abrestic@chromium.org>2014-09-18 17:47:24 -0400
committerRalf Baechle <ralf@linux-mips.org>2014-11-24 01:44:56 -0500
commit18743d2781d01d34d132f952a2e16353ccb4c3de (patch)
tree42df699518d3b44c08ef49fa3d893dc38d8ddc5e /drivers/irqchip
parentc49581a4dfaade3a483f3db85581a2cdb6bb85a0 (diff)
irqchip: mips-gic: Stop using per-platform mapping tables
Now that the GIC properly uses IRQ domains, kill off the per-platform routing tables that were used to make the GIC appear transparent. This includes: - removing the mapping tables and the support for applying them, - moving GIC IPI support to the GIC driver, - properly routing the i8259 through the GIC on Malta, and - updating IRQ assignments on SEAD-3 when the GIC is present. Platforms no longer will pass an interrupt mapping table to gic_init. Instead, they will pass the CPU interrupt vector (2 - 7) that they expect the GIC to route interrupts to. Note that in EIC mode this value is ignored and all GIC interrupts are routed to EIC vector 1. Signed-off-by: Andrew Bresticker <abrestic@chromium.org> Acked-by: Jason Cooper <jason@lakedaemon.net> Reviewed-by: Qais Yousef <qais.yousef@imgtec.com> Tested-by: Qais Yousef <qais.yousef@imgtec.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jeffrey Deans <jeffrey.deans@imgtec.com> Cc: Markos Chandras <markos.chandras@imgtec.com> Cc: Paul Burton <paul.burton@imgtec.com> Cc: Jonas Gorski <jogo@openwrt.org> Cc: John Crispin <blogic@openwrt.org> Cc: David Daney <ddaney.cavm@gmail.com> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7816/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-mips-gic.c201
1 files changed, 105 insertions, 96 deletions
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 79ab99781534..633a34639388 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -8,6 +8,8 @@
8 */ 8 */
9#include <linux/bitmap.h> 9#include <linux/bitmap.h>
10#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/interrupt.h>
12#include <linux/sched.h>
11#include <linux/smp.h> 13#include <linux/smp.h>
12#include <linux/irq.h> 14#include <linux/irq.h>
13#include <linux/clocksource.h> 15#include <linux/clocksource.h>
@@ -22,11 +24,8 @@
22unsigned int gic_frequency; 24unsigned int gic_frequency;
23unsigned int gic_present; 25unsigned int gic_present;
24unsigned long _gic_base; 26unsigned long _gic_base;
25unsigned int gic_irq_base;
26unsigned int gic_irq_flags[GIC_NUM_INTRS]; 27unsigned int gic_irq_flags[GIC_NUM_INTRS];
27 28unsigned int gic_cpu_pin;
28/* The index into this array is the vector # of the interrupt. */
29struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS];
30 29
31struct gic_pcpu_mask { 30struct gic_pcpu_mask {
32 DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS); 31 DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
@@ -46,6 +45,8 @@ static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
46static DEFINE_SPINLOCK(gic_lock); 45static DEFINE_SPINLOCK(gic_lock);
47static struct irq_domain *gic_irq_domain; 46static struct irq_domain *gic_irq_domain;
48 47
48static void __gic_irq_dispatch(void);
49
49#if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC) 50#if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC)
50cycle_t gic_read_count(void) 51cycle_t gic_read_count(void)
51{ 52{
@@ -117,21 +118,6 @@ void gic_send_ipi(unsigned int intr)
117 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); 118 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
118} 119}
119 120
120static void gic_eic_irq_dispatch(void)
121{
122 unsigned int cause = read_c0_cause();
123 int irq;
124
125 irq = (cause & ST0_IM) >> STATUSB_IP2;
126 if (irq == 0)
127 irq = -1;
128
129 if (irq >= 0)
130 do_IRQ(gic_irq_base + irq);
131 else
132 spurious_interrupt();
133}
134
135static void __init vpe_local_setup(unsigned int numvpes) 121static void __init vpe_local_setup(unsigned int numvpes)
136{ 122{
137 unsigned long timer_intr = GIC_INT_TMR; 123 unsigned long timer_intr = GIC_INT_TMR;
@@ -166,16 +152,15 @@ static void __init vpe_local_setup(unsigned int numvpes)
166 GIC_MAP_TO_PIN_MSK | timer_intr); 152 GIC_MAP_TO_PIN_MSK | timer_intr);
167 if (cpu_has_veic) { 153 if (cpu_has_veic) {
168 set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET, 154 set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET,
169 gic_eic_irq_dispatch); 155 __gic_irq_dispatch);
170 gic_shared_intr_map[timer_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_TIMER_MSK;
171 } 156 }
172 157
173 if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK) 158 if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
174 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), 159 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
175 GIC_MAP_TO_PIN_MSK | perf_intr); 160 GIC_MAP_TO_PIN_MSK | perf_intr);
176 if (cpu_has_veic) { 161 if (cpu_has_veic) {
177 set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET, gic_eic_irq_dispatch); 162 set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET,
178 gic_shared_intr_map[perf_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_PERFCNT_MSK; 163 __gic_irq_dispatch);
179 } 164 }
180 } 165 }
181} 166}
@@ -343,64 +328,100 @@ static struct irq_chip gic_irq_controller = {
343#endif 328#endif
344}; 329};
345 330
346static void __init gic_setup_intr(unsigned int intr, unsigned int cpu, 331static void __gic_irq_dispatch(void)
347 unsigned int pin, unsigned int polarity, unsigned int trigtype,
348 unsigned int flags)
349{ 332{
350 struct gic_shared_intr_map *map_ptr; 333 unsigned int intr, virq;
351 int i;
352
353 /* Setup Intr to Pin mapping */
354 if (pin & GIC_MAP_TO_NMI_MSK) {
355 int i;
356 334
357 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); 335 while ((intr = gic_get_int()) != GIC_NUM_INTRS) {
358 /* FIXME: hack to route NMI to all cpu's */ 336 virq = irq_linear_revmap(gic_irq_domain, intr);
359 for (i = 0; i < NR_CPUS; i += 32) { 337 do_IRQ(virq);
360 GICWRITE(GIC_REG_ADDR(SHARED,
361 GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)),
362 0xffffffff);
363 }
364 } else {
365 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)),
366 GIC_MAP_TO_PIN_MSK | pin);
367 /* Setup Intr to CPU mapping */
368 GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
369 if (cpu_has_veic) {
370 set_vi_handler(pin + GIC_PIN_TO_VEC_OFFSET,
371 gic_eic_irq_dispatch);
372 map_ptr = &gic_shared_intr_map[pin + GIC_PIN_TO_VEC_OFFSET];
373 if (map_ptr->num_shared_intr >= GIC_MAX_SHARED_INTR)
374 BUG();
375 map_ptr->intr_list[map_ptr->num_shared_intr++] = intr;
376 }
377 } 338 }
339}
378 340
379 /* Setup Intr Polarity */ 341static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc)
380 GIC_SET_POLARITY(intr, polarity); 342{
343 __gic_irq_dispatch();
344}
345
346#ifdef CONFIG_MIPS_GIC_IPI
347static int gic_resched_int_base;
348static int gic_call_int_base;
349
350unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
351{
352 return gic_resched_int_base + cpu;
353}
381 354
382 /* Setup Intr Trigger Type */ 355unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
383 GIC_SET_TRIGGER(intr, trigtype); 356{
357 return gic_call_int_base + cpu;
358}
384 359
385 /* Init Intr Masks */ 360static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
386 GIC_CLR_INTR_MASK(intr); 361{
362 scheduler_ipi();
363
364 return IRQ_HANDLED;
365}
366
367static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
368{
369 smp_call_function_interrupt();
370
371 return IRQ_HANDLED;
372}
387 373
388 /* Initialise per-cpu Interrupt software masks */ 374static struct irqaction irq_resched = {
375 .handler = ipi_resched_interrupt,
376 .flags = IRQF_PERCPU,
377 .name = "IPI resched"
378};
379
380static struct irqaction irq_call = {
381 .handler = ipi_call_interrupt,
382 .flags = IRQF_PERCPU,
383 .name = "IPI call"
384};
385
386static __init void gic_ipi_init_one(unsigned int intr, int cpu,
387 struct irqaction *action)
388{
389 int virq = irq_create_mapping(gic_irq_domain, intr);
390 int i;
391
392 GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
389 for (i = 0; i < NR_CPUS; i++) 393 for (i = 0; i < NR_CPUS; i++)
390 clear_bit(intr, pcpu_masks[i].pcpu_mask); 394 clear_bit(intr, pcpu_masks[i].pcpu_mask);
391 set_bit(intr, pcpu_masks[cpu].pcpu_mask); 395 set_bit(intr, pcpu_masks[cpu].pcpu_mask);
392 396
393 if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0)) 397 irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
394 GIC_SET_INTR_MASK(intr); 398
395 if (trigtype == GIC_TRIG_EDGE) 399 irq_set_handler(virq, handle_percpu_irq);
396 gic_irq_flags[intr] |= GIC_TRIG_EDGE; 400 setup_irq(virq, action);
397} 401}
398 402
399static void __init gic_basic_init(int numintrs, int numvpes, 403static __init void gic_ipi_init(void)
400 struct gic_intr_map *intrmap, int mapsize)
401{ 404{
402 unsigned int i, cpu; 405 int i;
403 unsigned int pin_offset = 0; 406
407 /* Use last 2 * NR_CPUS interrupts as IPIs */
408 gic_resched_int_base = GIC_NUM_INTRS - nr_cpu_ids;
409 gic_call_int_base = gic_resched_int_base - nr_cpu_ids;
410
411 for (i = 0; i < nr_cpu_ids; i++) {
412 gic_ipi_init_one(gic_call_int_base + i, i, &irq_call);
413 gic_ipi_init_one(gic_resched_int_base + i, i, &irq_resched);
414 }
415}
416#else
417static inline void gic_ipi_init(void)
418{
419}
420#endif
421
422static void __init gic_basic_init(int numintrs, int numvpes)
423{
424 unsigned int i;
404 425
405 board_bind_eic_interrupt = &gic_bind_eic_interrupt; 426 board_bind_eic_interrupt = &gic_bind_eic_interrupt;
406 427
@@ -409,31 +430,8 @@ static void __init gic_basic_init(int numintrs, int numvpes,
409 GIC_SET_POLARITY(i, GIC_POL_POS); 430 GIC_SET_POLARITY(i, GIC_POL_POS);
410 GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); 431 GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
411 GIC_CLR_INTR_MASK(i); 432 GIC_CLR_INTR_MASK(i);
412 if (i < GIC_NUM_INTRS) { 433 if (i < GIC_NUM_INTRS)
413 gic_irq_flags[i] = 0; 434 gic_irq_flags[i] = 0;
414 gic_shared_intr_map[i].num_shared_intr = 0;
415 gic_shared_intr_map[i].local_intr_mask = 0;
416 }
417 }
418
419 /*
420 * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract
421 * one because the GIC will add one (since 0=no intr).
422 */
423 if (cpu_has_veic)
424 pin_offset = (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
425
426 /* Setup specifics */
427 for (i = 0; i < mapsize; i++) {
428 cpu = intrmap[i].cpunum;
429 if (cpu == GIC_UNUSED)
430 continue;
431 gic_setup_intr(i,
432 intrmap[i].cpunum,
433 intrmap[i].pin + pin_offset,
434 intrmap[i].polarity,
435 intrmap[i].trigtype,
436 intrmap[i].flags);
437 } 435 }
438 436
439 vpe_local_setup(numvpes); 437 vpe_local_setup(numvpes);
@@ -448,7 +446,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
448 446
449 spin_lock_irqsave(&gic_lock, flags); 447 spin_lock_irqsave(&gic_lock, flags);
450 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)), 448 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)),
451 GIC_MAP_TO_PIN_MSK | 0); 449 GIC_MAP_TO_PIN_MSK | gic_cpu_pin);
452 /* Map to VPE 0 by default */ 450 /* Map to VPE 0 by default */
453 GIC_SH_MAP_TO_VPE_SMASK(hw, 0); 451 GIC_SH_MAP_TO_VPE_SMASK(hw, 0);
454 set_bit(hw, pcpu_masks[0].pcpu_mask); 452 set_bit(hw, pcpu_masks[0].pcpu_mask);
@@ -463,8 +461,7 @@ static struct irq_domain_ops gic_irq_domain_ops = {
463}; 461};
464 462
465void __init gic_init(unsigned long gic_base_addr, 463void __init gic_init(unsigned long gic_base_addr,
466 unsigned long gic_addrspace_size, 464 unsigned long gic_addrspace_size, unsigned int cpu_vec,
467 struct gic_intr_map *intr_map, unsigned int intr_map_size,
468 unsigned int irqbase) 465 unsigned int irqbase)
469{ 466{
470 unsigned int gicconfig; 467 unsigned int gicconfig;
@@ -472,7 +469,6 @@ void __init gic_init(unsigned long gic_base_addr,
472 469
473 _gic_base = (unsigned long) ioremap_nocache(gic_base_addr, 470 _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
474 gic_addrspace_size); 471 gic_addrspace_size);
475 gic_irq_base = irqbase;
476 472
477 GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig); 473 GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
478 numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >> 474 numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
@@ -483,10 +479,23 @@ void __init gic_init(unsigned long gic_base_addr,
483 GIC_SH_CONFIG_NUMVPES_SHF; 479 GIC_SH_CONFIG_NUMVPES_SHF;
484 numvpes = numvpes + 1; 480 numvpes = numvpes + 1;
485 481
482 if (cpu_has_veic) {
483 /* Always use vector 1 in EIC mode */
484 gic_cpu_pin = 0;
485 set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET,
486 __gic_irq_dispatch);
487 } else {
488 gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET;
489 irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec,
490 gic_irq_dispatch);
491 }
492
486 gic_irq_domain = irq_domain_add_simple(NULL, GIC_NUM_INTRS, irqbase, 493 gic_irq_domain = irq_domain_add_simple(NULL, GIC_NUM_INTRS, irqbase,
487 &gic_irq_domain_ops, NULL); 494 &gic_irq_domain_ops, NULL);
488 if (!gic_irq_domain) 495 if (!gic_irq_domain)
489 panic("Failed to add GIC IRQ domain"); 496 panic("Failed to add GIC IRQ domain");
490 497
491 gic_basic_init(numintrs, numvpes, intr_map, intr_map_size); 498 gic_basic_init(numintrs, numvpes);
499
500 gic_ipi_init();
492} 501}