diff options
Diffstat (limited to 'arch/mips/mips-boards/malta')
-rw-r--r-- | arch/mips/mips-boards/malta/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/mips-boards/malta/malta_int.c | 354 | ||||
-rw-r--r-- | arch/mips/mips-boards/malta/malta_setup.c | 10 |
3 files changed, 359 insertions, 6 deletions
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile index 931ca4600a63..8dc6e2ac4c03 100644 --- a/arch/mips/mips-boards/malta/Makefile +++ b/arch/mips/mips-boards/malta/Makefile | |||
@@ -22,6 +22,7 @@ | |||
22 | obj-y := malta_int.o malta_platform.o malta_setup.o | 22 | obj-y := malta_int.o malta_platform.o malta_setup.o |
23 | 23 | ||
24 | obj-$(CONFIG_MTD) += malta_mtd.o | 24 | obj-$(CONFIG_MTD) += malta_mtd.o |
25 | # FIXME FIXME FIXME | ||
25 | obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o | 26 | obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o |
26 | 27 | ||
27 | EXTRA_CFLAGS += -Werror | 28 | EXTRA_CFLAGS += -Werror |
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c index dbe60eb55e29..8c495104b321 100644 --- a/arch/mips/mips-boards/malta/malta_int.c +++ b/arch/mips/mips-boards/malta/malta_int.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/random.h> | 32 | #include <linux/random.h> |
33 | 33 | ||
34 | #include <asm/traps.h> | ||
34 | #include <asm/i8259.h> | 35 | #include <asm/i8259.h> |
35 | #include <asm/irq_cpu.h> | 36 | #include <asm/irq_cpu.h> |
36 | #include <asm/irq_regs.h> | 37 | #include <asm/irq_regs.h> |
@@ -41,6 +42,14 @@ | |||
41 | #include <asm/mips-boards/generic.h> | 42 | #include <asm/mips-boards/generic.h> |
42 | #include <asm/mips-boards/msc01_pci.h> | 43 | #include <asm/mips-boards/msc01_pci.h> |
43 | #include <asm/msc01_ic.h> | 44 | #include <asm/msc01_ic.h> |
45 | #include <asm/gic.h> | ||
46 | #include <asm/gcmpregs.h> | ||
47 | |||
48 | int gcmp_present = -1; | ||
49 | int gic_present; | ||
50 | static unsigned long _msc01_biu_base; | ||
51 | static unsigned long _gcmp_base; | ||
52 | static unsigned int ipi_map[NR_CPUS]; | ||
44 | 53 | ||
45 | static DEFINE_SPINLOCK(mips_irq_lock); | 54 | static DEFINE_SPINLOCK(mips_irq_lock); |
46 | 55 | ||
@@ -121,6 +130,17 @@ static void malta_hw0_irqdispatch(void) | |||
121 | do_IRQ(MALTA_INT_BASE + irq); | 130 | do_IRQ(MALTA_INT_BASE + irq); |
122 | } | 131 | } |
123 | 132 | ||
133 | static void malta_ipi_irqdispatch(void) | ||
134 | { | ||
135 | int irq; | ||
136 | |||
137 | irq = gic_get_int(); | ||
138 | if (irq < 0) | ||
139 | return; /* interrupt has already been cleared */ | ||
140 | |||
141 | do_IRQ(MIPS_GIC_IRQ_BASE + irq); | ||
142 | } | ||
143 | |||
124 | static void corehi_irqdispatch(void) | 144 | static void corehi_irqdispatch(void) |
125 | { | 145 | { |
126 | unsigned int intedge, intsteer, pcicmd, pcibadaddr; | 146 | unsigned int intedge, intsteer, pcicmd, pcibadaddr; |
@@ -257,12 +277,61 @@ asmlinkage void plat_irq_dispatch(void) | |||
257 | 277 | ||
258 | if (irq == MIPSCPU_INT_I8259A) | 278 | if (irq == MIPSCPU_INT_I8259A) |
259 | malta_hw0_irqdispatch(); | 279 | malta_hw0_irqdispatch(); |
280 | else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()])) | ||
281 | malta_ipi_irqdispatch(); | ||
260 | else if (irq >= 0) | 282 | else if (irq >= 0) |
261 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); | 283 | do_IRQ(MIPS_CPU_IRQ_BASE + irq); |
262 | else | 284 | else |
263 | spurious_interrupt(); | 285 | spurious_interrupt(); |
264 | } | 286 | } |
265 | 287 | ||
288 | #ifdef CONFIG_MIPS_MT_SMP | ||
289 | |||
290 | |||
291 | #define GIC_MIPS_CPU_IPI_RESCHED_IRQ 3 | ||
292 | #define GIC_MIPS_CPU_IPI_CALL_IRQ 4 | ||
293 | |||
294 | #define MIPS_CPU_IPI_RESCHED_IRQ 0 /* SW int 0 for resched */ | ||
295 | #define C_RESCHED C_SW0 | ||
296 | #define MIPS_CPU_IPI_CALL_IRQ 1 /* SW int 1 for resched */ | ||
297 | #define C_CALL C_SW1 | ||
298 | static int cpu_ipi_resched_irq, cpu_ipi_call_irq; | ||
299 | |||
300 | static void ipi_resched_dispatch(void) | ||
301 | { | ||
302 | do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ); | ||
303 | } | ||
304 | |||
305 | static void ipi_call_dispatch(void) | ||
306 | { | ||
307 | do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ); | ||
308 | } | ||
309 | |||
310 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) | ||
311 | { | ||
312 | return IRQ_HANDLED; | ||
313 | } | ||
314 | |||
315 | static irqreturn_t ipi_call_interrupt(int irq, void *dev_id) | ||
316 | { | ||
317 | smp_call_function_interrupt(); | ||
318 | |||
319 | return IRQ_HANDLED; | ||
320 | } | ||
321 | |||
322 | static struct irqaction irq_resched = { | ||
323 | .handler = ipi_resched_interrupt, | ||
324 | .flags = IRQF_DISABLED|IRQF_PERCPU, | ||
325 | .name = "IPI_resched" | ||
326 | }; | ||
327 | |||
328 | static struct irqaction irq_call = { | ||
329 | .handler = ipi_call_interrupt, | ||
330 | .flags = IRQF_DISABLED|IRQF_PERCPU, | ||
331 | .name = "IPI_call" | ||
332 | }; | ||
333 | #endif /* CONFIG_MIPS_MT_SMP */ | ||
334 | |||
266 | static struct irqaction i8259irq = { | 335 | static struct irqaction i8259irq = { |
267 | .handler = no_action, | 336 | .handler = no_action, |
268 | .name = "XT-PIC cascade" | 337 | .name = "XT-PIC cascade" |
@@ -273,13 +342,13 @@ static struct irqaction corehi_irqaction = { | |||
273 | .name = "CoreHi" | 342 | .name = "CoreHi" |
274 | }; | 343 | }; |
275 | 344 | ||
276 | msc_irqmap_t __initdata msc_irqmap[] = { | 345 | static msc_irqmap_t __initdata msc_irqmap[] = { |
277 | {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, | 346 | {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, |
278 | {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, | 347 | {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, |
279 | }; | 348 | }; |
280 | int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap); | 349 | static int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap); |
281 | 350 | ||
282 | msc_irqmap_t __initdata msc_eicirqmap[] = { | 351 | static msc_irqmap_t __initdata msc_eicirqmap[] = { |
283 | {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, | 352 | {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, |
284 | {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0}, | 353 | {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0}, |
285 | {MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0}, | 354 | {MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0}, |
@@ -291,15 +360,90 @@ msc_irqmap_t __initdata msc_eicirqmap[] = { | |||
291 | {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0}, | 360 | {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0}, |
292 | {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} | 361 | {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} |
293 | }; | 362 | }; |
294 | int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); | 363 | |
364 | static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); | ||
365 | |||
366 | /* | ||
367 | * This GIC specific tabular array defines the association between External | ||
368 | * Interrupts and CPUs/Core Interrupts. The nature of the External | ||
369 | * Interrupts is also defined here - polarity/trigger. | ||
370 | */ | ||
371 | static struct gic_intr_map gic_intr_map[] = { | ||
372 | { GIC_EXT_INTR(0), X, X, X, X, 0 }, | ||
373 | { GIC_EXT_INTR(1), X, X, X, X, 0 }, | ||
374 | { GIC_EXT_INTR(2), X, X, X, X, 0 }, | ||
375 | { GIC_EXT_INTR(3), 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, | ||
376 | { GIC_EXT_INTR(4), 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, | ||
377 | { GIC_EXT_INTR(5), 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, | ||
378 | { GIC_EXT_INTR(6), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, | ||
379 | { GIC_EXT_INTR(7), 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, | ||
380 | { GIC_EXT_INTR(8), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, | ||
381 | { GIC_EXT_INTR(9), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, | ||
382 | { GIC_EXT_INTR(10), X, X, X, X, 0 }, | ||
383 | { GIC_EXT_INTR(11), X, X, X, X, 0 }, | ||
384 | { GIC_EXT_INTR(12), 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, | ||
385 | { GIC_EXT_INTR(13), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, | ||
386 | { GIC_EXT_INTR(14), 0, GIC_MAP_TO_NMI_MSK, GIC_POL_POS, GIC_TRIG_LEVEL, 0 }, | ||
387 | { GIC_EXT_INTR(15), X, X, X, X, 0 }, | ||
388 | { GIC_EXT_INTR(16), 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, | ||
389 | { GIC_EXT_INTR(17), 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, | ||
390 | { GIC_EXT_INTR(18), 1, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, | ||
391 | { GIC_EXT_INTR(19), 1, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, | ||
392 | { GIC_EXT_INTR(20), 2, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, | ||
393 | { GIC_EXT_INTR(21), 2, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, | ||
394 | { GIC_EXT_INTR(22), 3, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, | ||
395 | { GIC_EXT_INTR(23), 3, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_EDGE, 1 }, | ||
396 | }; | ||
397 | |||
398 | /* | ||
399 | * GCMP needs to be detected before any SMP initialisation | ||
400 | */ | ||
401 | int __init gcmp_probe(unsigned long addr, unsigned long size) | ||
402 | { | ||
403 | if (gcmp_present >= 0) | ||
404 | return gcmp_present; | ||
405 | |||
406 | _gcmp_base = (unsigned long) ioremap_nocache(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ); | ||
407 | _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ); | ||
408 | gcmp_present = (GCMPGCB(GCMPB) & GCMP_GCB_GCMPB_GCMPBASE_MSK) == GCMP_BASE_ADDR; | ||
409 | |||
410 | if (gcmp_present) | ||
411 | printk(KERN_DEBUG "GCMP present\n"); | ||
412 | return gcmp_present; | ||
413 | } | ||
414 | |||
415 | void __init fill_ipi_map(void) | ||
416 | { | ||
417 | int i; | ||
418 | |||
419 | for (i = 0; i < ARRAY_SIZE(gic_intr_map); i++) { | ||
420 | if (gic_intr_map[i].ipiflag && (gic_intr_map[i].cpunum != X)) | ||
421 | ipi_map[gic_intr_map[i].cpunum] |= | ||
422 | (1 << (gic_intr_map[i].pin + 2)); | ||
423 | } | ||
424 | } | ||
295 | 425 | ||
296 | void __init arch_init_irq(void) | 426 | void __init arch_init_irq(void) |
297 | { | 427 | { |
428 | int gic_present, gcmp_present; | ||
429 | |||
298 | init_i8259_irqs(); | 430 | init_i8259_irqs(); |
299 | 431 | ||
300 | if (!cpu_has_veic) | 432 | if (!cpu_has_veic) |
301 | mips_cpu_irq_init(); | 433 | mips_cpu_irq_init(); |
302 | 434 | ||
435 | gcmp_present = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ); | ||
436 | if (gcmp_present) { | ||
437 | GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK; | ||
438 | gic_present = 1; | ||
439 | } else { | ||
440 | _msc01_biu_base = (unsigned long) ioremap_nocache(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ); | ||
441 | gic_present = (REG(_msc01_biu_base, MSC01_SC_CFG) & | ||
442 | MSC01_SC_CFG_GICPRES_MSK) >> MSC01_SC_CFG_GICPRES_SHF; | ||
443 | } | ||
444 | if (gic_present) | ||
445 | printk(KERN_DEBUG "GIC present\n"); | ||
446 | |||
303 | switch (mips_revision_sconid) { | 447 | switch (mips_revision_sconid) { |
304 | case MIPS_REVISION_SCON_SOCIT: | 448 | case MIPS_REVISION_SCON_SOCIT: |
305 | case MIPS_REVISION_SCON_ROCIT: | 449 | case MIPS_REVISION_SCON_ROCIT: |
@@ -360,4 +504,206 @@ void __init arch_init_irq(void) | |||
360 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, | 504 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, |
361 | &corehi_irqaction); | 505 | &corehi_irqaction); |
362 | } | 506 | } |
507 | |||
508 | #if defined(CONFIG_MIPS_MT_SMP) | ||
509 | if (gic_present) { | ||
510 | /* FIXME */ | ||
511 | int i; | ||
512 | struct { | ||
513 | unsigned int resched; | ||
514 | unsigned int call; | ||
515 | } ipiirq[] = { | ||
516 | { | ||
517 | .resched = GIC_IPI_EXT_INTR_RESCHED_VPE0, | ||
518 | .call = GIC_IPI_EXT_INTR_CALLFNC_VPE0}, | ||
519 | { | ||
520 | .resched = GIC_IPI_EXT_INTR_RESCHED_VPE1, | ||
521 | .call = GIC_IPI_EXT_INTR_CALLFNC_VPE1 | ||
522 | }, { | ||
523 | .resched = GIC_IPI_EXT_INTR_RESCHED_VPE2, | ||
524 | .call = GIC_IPI_EXT_INTR_CALLFNC_VPE2 | ||
525 | }, { | ||
526 | .resched = GIC_IPI_EXT_INTR_RESCHED_VPE3, | ||
527 | .call = GIC_IPI_EXT_INTR_CALLFNC_VPE3 | ||
528 | } | ||
529 | }; | ||
530 | #define NIPI (sizeof(ipiirq)/sizeof(ipiirq[0])) | ||
531 | fill_ipi_map(); | ||
532 | gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); | ||
533 | if (!gcmp_present) { | ||
534 | /* Enable the GIC */ | ||
535 | i = REG(_msc01_biu_base, MSC01_SC_CFG); | ||
536 | REG(_msc01_biu_base, MSC01_SC_CFG) = | ||
537 | (i | (0x1 << MSC01_SC_CFG_GICENA_SHF)); | ||
538 | pr_debug("GIC Enabled\n"); | ||
539 | } | ||
540 | |||
541 | /* set up ipi interrupts */ | ||
542 | if (cpu_has_vint) { | ||
543 | set_vi_handler(MIPSCPU_INT_IPI0, malta_ipi_irqdispatch); | ||
544 | set_vi_handler(MIPSCPU_INT_IPI1, malta_ipi_irqdispatch); | ||
545 | } | ||
546 | /* Argh.. this really needs sorting out.. */ | ||
547 | printk("CPU%d: status register was %08x\n", smp_processor_id(), read_c0_status()); | ||
548 | write_c0_status(read_c0_status() | STATUSF_IP3 | STATUSF_IP4); | ||
549 | printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status()); | ||
550 | write_c0_status(0x1100dc00); | ||
551 | printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status()); | ||
552 | for (i = 0; i < NIPI; i++) { | ||
553 | setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, &irq_resched); | ||
554 | setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].call, &irq_call); | ||
555 | |||
556 | set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, handle_percpu_irq); | ||
557 | set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].call, handle_percpu_irq); | ||
558 | } | ||
559 | } else { | ||
560 | /* set up ipi interrupts */ | ||
561 | if (cpu_has_veic) { | ||
562 | set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch); | ||
563 | set_vi_handler (MSC01E_INT_SW1, ipi_call_dispatch); | ||
564 | cpu_ipi_resched_irq = MSC01E_INT_SW0; | ||
565 | cpu_ipi_call_irq = MSC01E_INT_SW1; | ||
566 | } else { | ||
567 | if (cpu_has_vint) { | ||
568 | set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); | ||
569 | set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); | ||
570 | } | ||
571 | cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ; | ||
572 | cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ; | ||
573 | } | ||
574 | |||
575 | setup_irq(cpu_ipi_resched_irq, &irq_resched); | ||
576 | setup_irq(cpu_ipi_call_irq, &irq_call); | ||
577 | |||
578 | set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq); | ||
579 | set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq); | ||
580 | } | ||
581 | #endif | ||
582 | } | ||
583 | |||
584 | void malta_be_init(void) | ||
585 | { | ||
586 | if (gcmp_present) { | ||
587 | /* Could change CM error mask register */ | ||
588 | } | ||
589 | } | ||
590 | |||
591 | |||
592 | static char *tr[8] = { | ||
593 | "mem", "gcr", "gic", "mmio", | ||
594 | "0x04", "0x05", "0x06", "0x07" | ||
595 | }; | ||
596 | |||
597 | static char *mcmd[32] = { | ||
598 | [0x00] = "0x00", | ||
599 | [0x01] = "Legacy Write", | ||
600 | [0x02] = "Legacy Read", | ||
601 | [0x03] = "0x03", | ||
602 | [0x04] = "0x04", | ||
603 | [0x05] = "0x05", | ||
604 | [0x06] = "0x06", | ||
605 | [0x07] = "0x07", | ||
606 | [0x08] = "Coherent Read Own", | ||
607 | [0x09] = "Coherent Read Share", | ||
608 | [0x0a] = "Coherent Read Discard", | ||
609 | [0x0b] = "Coherent Ready Share Always", | ||
610 | [0x0c] = "Coherent Upgrade", | ||
611 | [0x0d] = "Coherent Writeback", | ||
612 | [0x0e] = "0x0e", | ||
613 | [0x0f] = "0x0f", | ||
614 | [0x10] = "Coherent Copyback", | ||
615 | [0x11] = "Coherent Copyback Invalidate", | ||
616 | [0x12] = "Coherent Invalidate", | ||
617 | [0x13] = "Coherent Write Invalidate", | ||
618 | [0x14] = "Coherent Completion Sync", | ||
619 | [0x15] = "0x15", | ||
620 | [0x16] = "0x16", | ||
621 | [0x17] = "0x17", | ||
622 | [0x18] = "0x18", | ||
623 | [0x19] = "0x19", | ||
624 | [0x1a] = "0x1a", | ||
625 | [0x1b] = "0x1b", | ||
626 | [0x1c] = "0x1c", | ||
627 | [0x1d] = "0x1d", | ||
628 | [0x1e] = "0x1e", | ||
629 | [0x1f] = "0x1f" | ||
630 | }; | ||
631 | |||
632 | static char *core[8] = { | ||
633 | "Invalid/OK", "Invalid/Data", | ||
634 | "Shared/OK", "Shared/Data", | ||
635 | "Modified/OK", "Modified/Data", | ||
636 | "Exclusive/OK", "Exclusive/Data" | ||
637 | }; | ||
638 | |||
639 | static char *causes[32] = { | ||
640 | "None", "GC_WR_ERR", "GC_RD_ERR", "COH_WR_ERR", | ||
641 | "COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07", | ||
642 | "0x08", "0x09", "0x0a", "0x0b", | ||
643 | "0x0c", "0x0d", "0x0e", "0x0f", | ||
644 | "0x10", "0x11", "0x12", "0x13", | ||
645 | "0x14", "0x15", "0x16", "INTVN_WR_ERR", | ||
646 | "INTVN_RD_ERR", "0x19", "0x1a", "0x1b", | ||
647 | "0x1c", "0x1d", "0x1e", "0x1f" | ||
648 | }; | ||
649 | |||
650 | int malta_be_handler(struct pt_regs *regs, int is_fixup) | ||
651 | { | ||
652 | /* This duplicates the handling in do_be which seems wrong */ | ||
653 | int retval = is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL; | ||
654 | |||
655 | if (gcmp_present) { | ||
656 | unsigned long cm_error = GCMPGCB(GCMEC); | ||
657 | unsigned long cm_addr = GCMPGCB(GCMEA); | ||
658 | unsigned long cm_other = GCMPGCB(GCMEO); | ||
659 | unsigned long cause, ocause; | ||
660 | char buf[256]; | ||
661 | |||
662 | cause = (cm_error & GCMP_GCB_GMEC_ERROR_TYPE_MSK); | ||
663 | if (cause != 0) { | ||
664 | cause >>= GCMP_GCB_GMEC_ERROR_TYPE_SHF; | ||
665 | if (cause < 16) { | ||
666 | unsigned long cca_bits = (cm_error >> 15) & 7; | ||
667 | unsigned long tr_bits = (cm_error >> 12) & 7; | ||
668 | unsigned long mcmd_bits = (cm_error >> 7) & 0x1f; | ||
669 | unsigned long stag_bits = (cm_error >> 3) & 15; | ||
670 | unsigned long sport_bits = (cm_error >> 0) & 7; | ||
671 | |||
672 | snprintf(buf, sizeof(buf), | ||
673 | "CCA=%lu TR=%s MCmd=%s STag=%lu " | ||
674 | "SPort=%lu\n", | ||
675 | cca_bits, tr[tr_bits], mcmd[mcmd_bits], | ||
676 | stag_bits, sport_bits); | ||
677 | } else { | ||
678 | /* glob state & sresp together */ | ||
679 | unsigned long c3_bits = (cm_error >> 18) & 7; | ||
680 | unsigned long c2_bits = (cm_error >> 15) & 7; | ||
681 | unsigned long c1_bits = (cm_error >> 12) & 7; | ||
682 | unsigned long c0_bits = (cm_error >> 9) & 7; | ||
683 | unsigned long sc_bit = (cm_error >> 8) & 1; | ||
684 | unsigned long mcmd_bits = (cm_error >> 3) & 0x1f; | ||
685 | unsigned long sport_bits = (cm_error >> 0) & 7; | ||
686 | snprintf(buf, sizeof(buf), | ||
687 | "C3=%s C2=%s C1=%s C0=%s SC=%s " | ||
688 | "MCmd=%s SPort=%lu\n", | ||
689 | core[c3_bits], core[c2_bits], | ||
690 | core[c1_bits], core[c0_bits], | ||
691 | sc_bit ? "True" : "False", | ||
692 | mcmd[mcmd_bits], sport_bits); | ||
693 | } | ||
694 | |||
695 | ocause = (cm_other & GCMP_GCB_GMEO_ERROR_2ND_MSK) >> | ||
696 | GCMP_GCB_GMEO_ERROR_2ND_SHF; | ||
697 | |||
698 | printk("CM_ERROR=%08lx %s <%s>\n", cm_error, | ||
699 | causes[cause], buf); | ||
700 | printk("CM_ADDR =%08lx\n", cm_addr); | ||
701 | printk("CM_OTHER=%08lx %s\n", cm_other, causes[ocause]); | ||
702 | |||
703 | /* reprime cause register */ | ||
704 | GCMPGCB(GCMEC) = 0; | ||
705 | } | ||
706 | } | ||
707 | |||
708 | return retval; | ||
363 | } | 709 | } |
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c index 2cd8f5734b36..e7cad54936ca 100644 --- a/arch/mips/mips-boards/malta/malta_setup.c +++ b/arch/mips/mips-boards/malta/malta_setup.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Carsten Langgaard, carstenl@mips.com | 2 | * Carsten Langgaard, carstenl@mips.com |
3 | * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. | 3 | * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. |
4 | * Copyright (C) Dmitri Vorobiev | 4 | * Copyright (C) 2008 Dmitri Vorobiev |
5 | * | 5 | * |
6 | * This program is free software; you can distribute it and/or modify it | 6 | * This program is free software; you can distribute it and/or modify it |
7 | * under the terms of the GNU General Public License (Version 2) as | 7 | * under the terms of the GNU General Public License (Version 2) as |
@@ -36,7 +36,10 @@ | |||
36 | #include <linux/console.h> | 36 | #include <linux/console.h> |
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | struct resource standard_io_resources[] = { | 39 | extern void malta_be_init(void); |
40 | extern int malta_be_handler(struct pt_regs *regs, int is_fixup); | ||
41 | |||
42 | static struct resource standard_io_resources[] = { | ||
40 | { | 43 | { |
41 | .name = "dma1", | 44 | .name = "dma1", |
42 | .start = 0x00, | 45 | .start = 0x00, |
@@ -220,4 +223,7 @@ void __init plat_mem_setup(void) | |||
220 | screen_info_setup(); | 223 | screen_info_setup(); |
221 | #endif | 224 | #endif |
222 | mips_reboot_setup(); | 225 | mips_reboot_setup(); |
226 | |||
227 | board_be_init = malta_be_init; | ||
228 | board_be_handler = malta_be_handler; | ||
223 | } | 229 | } |