diff options
| author | Andrew Bresticker <abrestic@chromium.org> | 2014-09-18 17:47:24 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2014-11-24 01:44:56 -0500 |
| commit | 18743d2781d01d34d132f952a2e16353ccb4c3de (patch) | |
| tree | 42df699518d3b44c08ef49fa3d893dc38d8ddc5e /arch/mips/mti-malta | |
| parent | c49581a4dfaade3a483f3db85581a2cdb6bb85a0 (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 'arch/mips/mti-malta')
| -rw-r--r-- | arch/mips/mti-malta/malta-int.c | 189 |
1 files changed, 36 insertions, 153 deletions
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index e56563c6f89e..3b3bc1d9ebf9 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c | |||
| @@ -38,14 +38,9 @@ | |||
| 38 | #include <asm/rtlx.h> | 38 | #include <asm/rtlx.h> |
| 39 | 39 | ||
| 40 | static unsigned long _msc01_biu_base; | 40 | static unsigned long _msc01_biu_base; |
| 41 | static unsigned int ipi_map[NR_CPUS]; | ||
| 42 | 41 | ||
| 43 | static DEFINE_RAW_SPINLOCK(mips_irq_lock); | 42 | static DEFINE_RAW_SPINLOCK(mips_irq_lock); |
| 44 | 43 | ||
| 45 | #ifdef CONFIG_MIPS_GIC_IPI | ||
| 46 | DECLARE_BITMAP(ipi_ints, GIC_NUM_INTRS); | ||
| 47 | #endif | ||
| 48 | |||
| 49 | static inline int mips_pcibios_iack(void) | 44 | static inline int mips_pcibios_iack(void) |
| 50 | { | 45 | { |
| 51 | int irq; | 46 | int irq; |
| @@ -127,24 +122,10 @@ static void malta_hw0_irqdispatch(void) | |||
| 127 | #endif | 122 | #endif |
| 128 | } | 123 | } |
| 129 | 124 | ||
| 130 | static void malta_ipi_irqdispatch(void) | 125 | static irqreturn_t i8259_handler(int irq, void *dev_id) |
| 131 | { | 126 | { |
| 132 | #ifdef CONFIG_MIPS_GIC_IPI | 127 | malta_hw0_irqdispatch(); |
| 133 | unsigned long irq; | 128 | return IRQ_HANDLED; |
| 134 | DECLARE_BITMAP(pending, GIC_NUM_INTRS); | ||
| 135 | |||
| 136 | gic_get_int_mask(pending, ipi_ints); | ||
| 137 | |||
| 138 | irq = find_first_bit(pending, GIC_NUM_INTRS); | ||
| 139 | |||
| 140 | while (irq < GIC_NUM_INTRS) { | ||
| 141 | do_IRQ(MIPS_GIC_IRQ_BASE + irq); | ||
| 142 | |||
| 143 | irq = find_next_bit(pending, GIC_NUM_INTRS, irq + 1); | ||
| 144 | } | ||
| 145 | #endif | ||
| 146 | if (gic_compare_int()) | ||
| 147 | do_IRQ(MIPS_GIC_IRQ_BASE); | ||
| 148 | } | 129 | } |
| 149 | 130 | ||
| 150 | static void corehi_irqdispatch(void) | 131 | static void corehi_irqdispatch(void) |
| @@ -203,6 +184,12 @@ static void corehi_irqdispatch(void) | |||
| 203 | die("CoreHi interrupt", regs); | 184 | die("CoreHi interrupt", regs); |
| 204 | } | 185 | } |
| 205 | 186 | ||
| 187 | static irqreturn_t corehi_handler(int irq, void *dev_id) | ||
| 188 | { | ||
| 189 | corehi_irqdispatch(); | ||
| 190 | return IRQ_HANDLED; | ||
| 191 | } | ||
| 192 | |||
| 206 | static inline int clz(unsigned long x) | 193 | static inline int clz(unsigned long x) |
| 207 | { | 194 | { |
| 208 | __asm__( | 195 | __asm__( |
| @@ -286,10 +273,9 @@ asmlinkage void plat_irq_dispatch(void) | |||
| 286 | 273 | ||
| 287 | irq = irq_ffs(pending); | 274 | irq = irq_ffs(pending); |
| 288 | 275 | ||
| 289 | if (irq == MIPSCPU_INT_I8259A) | 276 | /* HACK: GIC doesn't properly dispatch local interrupts yet */ |
| 290 | malta_hw0_irqdispatch(); | 277 | if (gic_present && irq == MIPSCPU_INT_GIC && gic_compare_int()) |
| 291 | else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()])) | 278 | do_IRQ(MIPS_GIC_IRQ_BASE); |
| 292 | malta_ipi_irqdispatch(); | ||
| 293 | else | 279 | else |
| 294 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | 280 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); |
| 295 | } | 281 | } |
| @@ -312,13 +298,6 @@ static void ipi_call_dispatch(void) | |||
| 312 | do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); | 298 | do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); |
| 313 | } | 299 | } |
| 314 | 300 | ||
| 315 | #endif /* CONFIG_MIPS_MT_SMP */ | ||
| 316 | |||
| 317 | #ifdef CONFIG_MIPS_GIC_IPI | ||
| 318 | |||
| 319 | #define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3 | ||
| 320 | #define GIC_MIPS_CPU_IPI_CALL_IRQ 4 | ||
| 321 | |||
| 322 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) | 301 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) |
| 323 | { | 302 | { |
| 324 | #ifdef CONFIG_MIPS_VPE_APSP_API_CMP | 303 | #ifdef CONFIG_MIPS_VPE_APSP_API_CMP |
| @@ -349,31 +328,16 @@ static struct irqaction irq_call = { | |||
| 349 | .flags = IRQF_PERCPU, | 328 | .flags = IRQF_PERCPU, |
| 350 | .name = "IPI_call" | 329 | .name = "IPI_call" |
| 351 | }; | 330 | }; |
| 352 | #endif /* CONFIG_MIPS_GIC_IPI */ | 331 | #endif /* CONFIG_MIPS_MT_SMP */ |
| 353 | |||
| 354 | static int gic_resched_int_base; | ||
| 355 | static int gic_call_int_base; | ||
| 356 | #define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu)) | ||
| 357 | #define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu)) | ||
| 358 | |||
| 359 | unsigned int plat_ipi_call_int_xlate(unsigned int cpu) | ||
| 360 | { | ||
| 361 | return GIC_CALL_INT(cpu); | ||
| 362 | } | ||
| 363 | |||
| 364 | unsigned int plat_ipi_resched_int_xlate(unsigned int cpu) | ||
| 365 | { | ||
| 366 | return GIC_RESCHED_INT(cpu); | ||
| 367 | } | ||
| 368 | 332 | ||
| 369 | static struct irqaction i8259irq = { | 333 | static struct irqaction i8259irq = { |
| 370 | .handler = no_action, | 334 | .handler = i8259_handler, |
| 371 | .name = "XT-PIC cascade", | 335 | .name = "XT-PIC cascade", |
| 372 | .flags = IRQF_NO_THREAD, | 336 | .flags = IRQF_NO_THREAD, |
| 373 | }; | 337 | }; |
| 374 | 338 | ||
| 375 | static struct irqaction corehi_irqaction = { | 339 | static struct irqaction corehi_irqaction = { |
| 376 | .handler = no_action, | 340 | .handler = corehi_handler, |
| 377 | .name = "CoreHi", | 341 | .name = "CoreHi", |
| 378 | .flags = IRQF_NO_THREAD, | 342 | .flags = IRQF_NO_THREAD, |
| 379 | }; | 343 | }; |
| @@ -399,60 +363,6 @@ static msc_irqmap_t msc_eicirqmap[] __initdata = { | |||
| 399 | 363 | ||
| 400 | static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap); | 364 | static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap); |
| 401 | 365 | ||
| 402 | /* | ||
| 403 | * This GIC specific tabular array defines the association between External | ||
| 404 | * Interrupts and CPUs/Core Interrupts. The nature of the External | ||
| 405 | * Interrupts is also defined here - polarity/trigger. | ||
| 406 | */ | ||
| 407 | |||
| 408 | #define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK | ||
| 409 | #define X GIC_UNUSED | ||
| 410 | |||
| 411 | static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { | ||
| 412 | { X, X, X, X, 0 }, | ||
| 413 | { X, X, X, X, 0 }, | ||
| 414 | { X, X, X, X, 0 }, | ||
| 415 | { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 416 | { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 417 | { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 418 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 419 | { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 420 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 421 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 422 | { X, X, X, X, 0 }, | ||
| 423 | { X, X, X, X, 0 }, | ||
| 424 | { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 425 | { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 426 | { 0, GIC_CPU_NMI, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT }, | ||
| 427 | { X, X, X, X, 0 }, | ||
| 428 | /* The remainder of this table is initialised by fill_ipi_map */ | ||
| 429 | }; | ||
| 430 | #undef X | ||
| 431 | |||
| 432 | #ifdef CONFIG_MIPS_GIC_IPI | ||
| 433 | static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin) | ||
| 434 | { | ||
| 435 | int intr = baseintr + cpu; | ||
| 436 | gic_intr_map[intr].cpunum = cpu; | ||
| 437 | gic_intr_map[intr].pin = cpupin; | ||
| 438 | gic_intr_map[intr].polarity = GIC_POL_POS; | ||
| 439 | gic_intr_map[intr].trigtype = GIC_TRIG_EDGE; | ||
| 440 | gic_intr_map[intr].flags = 0; | ||
| 441 | ipi_map[cpu] |= (1 << (cpupin + 2)); | ||
| 442 | bitmap_set(ipi_ints, intr, 1); | ||
| 443 | } | ||
| 444 | |||
| 445 | static void __init fill_ipi_map(void) | ||
| 446 | { | ||
| 447 | int cpu; | ||
| 448 | |||
| 449 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) { | ||
| 450 | fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1); | ||
| 451 | fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2); | ||
| 452 | } | ||
| 453 | } | ||
| 454 | #endif | ||
| 455 | |||
| 456 | void __init arch_init_ipiirq(int irq, struct irqaction *action) | 366 | void __init arch_init_ipiirq(int irq, struct irqaction *action) |
| 457 | { | 367 | { |
| 458 | setup_irq(irq, action); | 368 | setup_irq(irq, action); |
| @@ -461,6 +371,8 @@ void __init arch_init_ipiirq(int irq, struct irqaction *action) | |||
| 461 | 371 | ||
| 462 | void __init arch_init_irq(void) | 372 | void __init arch_init_irq(void) |
| 463 | { | 373 | { |
| 374 | int corehi_irq, i8259_irq; | ||
| 375 | |||
| 464 | init_i8259_irqs(); | 376 | init_i8259_irqs(); |
| 465 | 377 | ||
| 466 | if (!cpu_has_veic) | 378 | if (!cpu_has_veic) |
| @@ -507,34 +419,11 @@ void __init arch_init_irq(void) | |||
| 507 | msc_nr_irqs); | 419 | msc_nr_irqs); |
| 508 | } | 420 | } |
| 509 | 421 | ||
| 510 | if (cpu_has_veic) { | ||
| 511 | set_vi_handler(MSC01E_INT_I8259A, malta_hw0_irqdispatch); | ||
| 512 | set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch); | ||
| 513 | setup_irq(MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq); | ||
| 514 | setup_irq(MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction); | ||
| 515 | } else if (cpu_has_vint) { | ||
| 516 | set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); | ||
| 517 | set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch); | ||
| 518 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); | ||
| 519 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, | ||
| 520 | &corehi_irqaction); | ||
| 521 | } else { | ||
| 522 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); | ||
| 523 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, | ||
| 524 | &corehi_irqaction); | ||
| 525 | } | ||
| 526 | |||
| 527 | if (gic_present) { | 422 | if (gic_present) { |
| 528 | /* FIXME */ | ||
| 529 | int i; | 423 | int i; |
| 530 | #if defined(CONFIG_MIPS_GIC_IPI) | 424 | |
| 531 | gic_call_int_base = GIC_NUM_INTRS - | 425 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, MIPSCPU_INT_GIC, |
| 532 | (NR_CPUS - nr_cpu_ids) * 2 - nr_cpu_ids; | 426 | MIPS_GIC_IRQ_BASE); |
| 533 | gic_resched_int_base = gic_call_int_base - nr_cpu_ids; | ||
| 534 | fill_ipi_map(); | ||
| 535 | #endif | ||
| 536 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, | ||
| 537 | ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); | ||
| 538 | if (!mips_cm_present()) { | 427 | if (!mips_cm_present()) { |
| 539 | /* Enable the GIC */ | 428 | /* Enable the GIC */ |
| 540 | i = REG(_msc01_biu_base, MSC01_SC_CFG); | 429 | i = REG(_msc01_biu_base, MSC01_SC_CFG); |
| @@ -542,28 +431,8 @@ void __init arch_init_irq(void) | |||
| 542 | (i | (0x1 << MSC01_SC_CFG_GICENA_SHF)); | 431 | (i | (0x1 << MSC01_SC_CFG_GICENA_SHF)); |
| 543 | pr_debug("GIC Enabled\n"); | 432 | pr_debug("GIC Enabled\n"); |
| 544 | } | 433 | } |
| 545 | #if defined(CONFIG_MIPS_GIC_IPI) | 434 | i8259_irq = MIPS_GIC_IRQ_BASE + GIC_INT_I8259A; |
| 546 | /* set up ipi interrupts */ | 435 | corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI; |
| 547 | if (cpu_has_vint) { | ||
| 548 | set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch); | ||
| 549 | set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch); | ||
| 550 | } | ||
| 551 | /* Argh.. this really needs sorting out.. */ | ||
| 552 | pr_info("CPU%d: status register was %08x\n", | ||
| 553 | smp_processor_id(), read_c0_status()); | ||
| 554 | write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4); | ||
| 555 | pr_info("CPU%d: status register now %08x\n", | ||
| 556 | smp_processor_id(), read_c0_status()); | ||
| 557 | write_c0_status(0x1100dc00); | ||
| 558 | pr_info("CPU%d: status register frc %08x\n", | ||
| 559 | smp_processor_id(), read_c0_status()); | ||
| 560 | for (i = 0; i < nr_cpu_ids; i++) { | ||
| 561 | arch_init_ipiirq(MIPS_GIC_IRQ_BASE + | ||
| 562 | GIC_RESCHED_INT(i), &irq_resched); | ||
| 563 | arch_init_ipiirq(MIPS_GIC_IRQ_BASE + | ||
| 564 | GIC_CALL_INT(i), &irq_call); | ||
| 565 | } | ||
| 566 | #endif | ||
| 567 | } else { | 436 | } else { |
| 568 | #if defined(CONFIG_MIPS_MT_SMP) | 437 | #if defined(CONFIG_MIPS_MT_SMP) |
| 569 | /* set up ipi interrupts */ | 438 | /* set up ipi interrupts */ |
| @@ -587,7 +456,21 @@ void __init arch_init_irq(void) | |||
| 587 | arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched); | 456 | arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched); |
| 588 | arch_init_ipiirq(cpu_ipi_call_irq, &irq_call); | 457 | arch_init_ipiirq(cpu_ipi_call_irq, &irq_call); |
| 589 | #endif | 458 | #endif |
| 459 | if (cpu_has_veic) { | ||
| 460 | set_vi_handler(MSC01E_INT_I8259A, | ||
| 461 | malta_hw0_irqdispatch); | ||
| 462 | set_vi_handler(MSC01E_INT_COREHI, | ||
| 463 | corehi_irqdispatch); | ||
| 464 | i8259_irq = MSC01E_INT_BASE + MSC01E_INT_I8259A; | ||
| 465 | corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI; | ||
| 466 | } else { | ||
| 467 | i8259_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_I8259A; | ||
| 468 | corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI; | ||
| 469 | } | ||
| 590 | } | 470 | } |
| 471 | |||
| 472 | setup_irq(i8259_irq, &i8259irq); | ||
| 473 | setup_irq(corehi_irq, &corehi_irqaction); | ||
| 591 | } | 474 | } |
| 592 | 475 | ||
| 593 | void malta_be_init(void) | 476 | void malta_be_init(void) |
