aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mips-boards
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2008-04-28 12:14:26 -0400
committerRalf Baechle <ralf@linux-mips.org>2008-04-28 12:14:26 -0400
commit39b8d5254246ac56342b72f812255c8f7a74dca9 (patch)
treea9ec6bfb5d09a8367c34cc2067328d1b49bb46c1 /arch/mips/mips-boards
parent308402445e005a039a72b315cd9b5ceeaea0063c (diff)
[MIPS] Add support for MIPS CMP platform.
Signed-off-by: Chris Dearman <chris@mips.com> Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mips-boards')
-rw-r--r--arch/mips/mips-boards/generic/Makefile1
-rw-r--r--arch/mips/mips-boards/generic/amon.c80
-rw-r--r--arch/mips/mips-boards/generic/init.c3
-rw-r--r--arch/mips/mips-boards/generic/time.c29
-rw-r--r--arch/mips/mips-boards/malta/Makefile1
-rw-r--r--arch/mips/mips-boards/malta/malta_int.c346
-rw-r--r--arch/mips/mips-boards/malta/malta_setup.c6
7 files changed, 461 insertions, 5 deletions
diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile
index b31d8dfed1be..f7f87fc09d1e 100644
--- a/arch/mips/mips-boards/generic/Makefile
+++ b/arch/mips/mips-boards/generic/Makefile
@@ -20,6 +20,7 @@
20 20
21obj-y := reset.o display.o init.o memory.o \ 21obj-y := reset.o display.o init.o memory.o \
22 cmdline.o time.o 22 cmdline.o time.o
23obj-y += amon.o
23 24
24obj-$(CONFIG_EARLY_PRINTK) += console.o 25obj-$(CONFIG_EARLY_PRINTK) += console.o
25obj-$(CONFIG_PCI) += pci.o 26obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/mips/mips-boards/generic/amon.c b/arch/mips/mips-boards/generic/amon.c
new file mode 100644
index 000000000000..b7633fda4180
--- /dev/null
+++ b/arch/mips/mips-boards/generic/amon.c
@@ -0,0 +1,80 @@
1/*
2 * Copyright (C) 2007 MIPS Technologies, Inc.
3 * All rights reserved.
4
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * Arbitrary Monitor interface
19 */
20
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/smp.h>
24
25#include <asm-mips/addrspace.h>
26#include <asm-mips/mips-boards/launch.h>
27#include <asm-mips/mipsmtregs.h>
28
29int amon_cpu_avail(int cpu)
30{
31 struct cpulaunch *launch = (struct cpulaunch *)KSEG0ADDR(CPULAUNCH);
32
33 if (cpu < 0 || cpu >= NCPULAUNCH) {
34 pr_debug("avail: cpu%d is out of range\n", cpu);
35 return 0;
36 }
37
38 launch += cpu;
39 if (!(launch->flags & LAUNCH_FREADY)) {
40 pr_debug("avail: cpu%d is not ready\n", cpu);
41 return 0;
42 }
43 if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) {
44 pr_debug("avail: too late.. cpu%d is already gone\n", cpu);
45 return 0;
46 }
47
48 return 1;
49}
50
51void amon_cpu_start(int cpu,
52 unsigned long pc, unsigned long sp,
53 unsigned long gp, unsigned long a0)
54{
55 volatile struct cpulaunch *launch =
56 (struct cpulaunch *)KSEG0ADDR(CPULAUNCH);
57
58 if (!amon_cpu_avail(cpu))
59 return;
60 if (cpu == smp_processor_id()) {
61 pr_debug("launch: I am cpu%d!\n", cpu);
62 return;
63 }
64 launch += cpu;
65
66 pr_debug("launch: starting cpu%d\n", cpu);
67
68 launch->pc = pc;
69 launch->gp = gp;
70 launch->sp = sp;
71 launch->a0 = a0;
72
73 /* Make sure target sees parameters before the go bit */
74 smp_mb();
75
76 launch->flags |= LAUNCH_FGO;
77 while ((launch->flags & LAUNCH_FGONE) == 0)
78 ;
79 pr_debug("launch: cpu%d gone!\n", cpu);
80}
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index 07671fb9074f..852b19492d8c 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -424,6 +424,9 @@ void __init prom_init(void)
424#ifdef CONFIG_SERIAL_8250_CONSOLE 424#ifdef CONFIG_SERIAL_8250_CONSOLE
425 console_config(); 425 console_config();
426#endif 426#endif
427#ifdef CONFIG_MIPS_CMP
428 register_smp_ops(&cmp_smp_ops);
429#endif
427#ifdef CONFIG_MIPS_MT_SMP 430#ifdef CONFIG_MIPS_MT_SMP
428 register_smp_ops(&vsmp_smp_ops); 431 register_smp_ops(&vsmp_smp_ops);
429#endif 432#endif
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index b50e0fc406ac..4fe62fca994e 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -55,16 +55,36 @@
55unsigned long cpu_khz; 55unsigned long cpu_khz;
56 56
57static int mips_cpu_timer_irq; 57static int mips_cpu_timer_irq;
58static int mips_cpu_perf_irq;
58extern int cp0_perfcount_irq; 59extern int cp0_perfcount_irq;
59 60
61DEFINE_PER_CPU(unsigned int, tickcount);
62#define tickcount_this_cpu __get_cpu_var(tickcount)
63static unsigned long ledbitmask;
64
60static void mips_timer_dispatch(void) 65static void mips_timer_dispatch(void)
61{ 66{
67#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_ATLAS)
68 /*
69 * Yes, this is very tacky, won't work as expected with SMTC and
70 * dyntick will break it,
71 * but it gives me a nice warm feeling during debug
72 */
73#define LEDBAR 0xbf000408
74 if (tickcount_this_cpu++ >= HZ) {
75 tickcount_this_cpu = 0;
76 change_bit(smp_processor_id(), &ledbitmask);
77 smp_wmb(); /* Make sure every one else sees the change */
78 /* This will pick up any recent changes made by other CPU's */
79 *(unsigned int *)LEDBAR = ledbitmask;
80 }
81#endif
62 do_IRQ(mips_cpu_timer_irq); 82 do_IRQ(mips_cpu_timer_irq);
63} 83}
64 84
65static void mips_perf_dispatch(void) 85static void mips_perf_dispatch(void)
66{ 86{
67 do_IRQ(cp0_perfcount_irq); 87 do_IRQ(mips_cpu_perf_irq);
68} 88}
69 89
70/* 90/*
@@ -129,19 +149,18 @@ unsigned long read_persistent_clock(void)
129 149
130void __init plat_perf_setup(void) 150void __init plat_perf_setup(void)
131{ 151{
132 cp0_perfcount_irq = -1;
133
134#ifdef MSC01E_INT_BASE 152#ifdef MSC01E_INT_BASE
135 if (cpu_has_veic) { 153 if (cpu_has_veic) {
136 set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch); 154 set_vi_handler(MSC01E_INT_PERFCTR, mips_perf_dispatch);
137 cp0_perfcount_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR; 155 mips_cpu_perf_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
138 } else 156 } else
139#endif 157#endif
140 if (cp0_perfcount_irq >= 0) { 158 if (cp0_perfcount_irq >= 0) {
141 if (cpu_has_vint) 159 if (cpu_has_vint)
142 set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch); 160 set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
161 mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
143#ifdef CONFIG_SMP 162#ifdef CONFIG_SMP
144 set_irq_handler(cp0_perfcount_irq, handle_percpu_irq); 163 set_irq_handler(mips_cpu_perf_irq, handle_percpu_irq);
145#endif 164#endif
146 } 165 }
147} 166}
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 @@
22obj-y := malta_int.o malta_platform.o malta_setup.o 22obj-y := malta_int.o malta_platform.o malta_setup.o
23 23
24obj-$(CONFIG_MTD) += malta_mtd.o 24obj-$(CONFIG_MTD) += malta_mtd.o
25# FIXME FIXME FIXME
25obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o 26obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o
26 27
27EXTRA_CFLAGS += -Werror 28EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index dbe60eb55e29..e1744ae855ce 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
48int gcmp_present = -1;
49int gic_present;
50static unsigned long _msc01_biu_base;
51static unsigned long _gcmp_base;
52static unsigned int ipi_map[NR_CPUS];
44 53
45static DEFINE_SPINLOCK(mips_irq_lock); 54static 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
133static 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
124static void corehi_irqdispatch(void) 144static 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
298static int cpu_ipi_resched_irq, cpu_ipi_call_irq;
299
300static void ipi_resched_dispatch(void)
301{
302 do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
303}
304
305static void ipi_call_dispatch(void)
306{
307 do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
308}
309
310static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
311{
312 return IRQ_HANDLED;
313}
314
315static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
316{
317 smp_call_function_interrupt();
318
319 return IRQ_HANDLED;
320}
321
322static struct irqaction irq_resched = {
323 .handler = ipi_resched_interrupt,
324 .flags = IRQF_DISABLED|IRQF_PERCPU,
325 .name = "IPI_resched"
326};
327
328static 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
266static struct irqaction i8259irq = { 335static struct irqaction i8259irq = {
267 .handler = no_action, 336 .handler = no_action,
268 .name = "XT-PIC cascade" 337 .name = "XT-PIC cascade"
@@ -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};
363
294int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap); 364int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
295 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 */
371static 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 */
401int __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
415void __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}
425
296void __init arch_init_irq(void) 426void __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
584void malta_be_init(void)
585{
586 if (gcmp_present) {
587 /* Could change CM error mask register */
588 }
589}
590
591
592static char *tr[8] = {
593 "mem", "gcr", "gic", "mmio",
594 "0x04", "0x05", "0x06", "0x07"
595};
596
597static 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
632static 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
639static 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
650int 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..4a0f21c76e7b 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -36,6 +36,9 @@
36#include <linux/console.h> 36#include <linux/console.h>
37#endif 37#endif
38 38
39extern void malta_be_init(void);
40extern int malta_be_handler(struct pt_regs *regs, int is_fixup);
41
39struct resource standard_io_resources[] = { 42struct resource standard_io_resources[] = {
40 { 43 {
41 .name = "dma1", 44 .name = "dma1",
@@ -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}