summaryrefslogtreecommitdiff
path: root/cpu/mpc85xx/traps.c
diff options
context:
space:
mode:
authorAndy Fleming <afleming@freescale.com>2007-08-14 01:34:21 -0500
committerAndrew Fleming-AFLEMING <afleming@freescale.com>2007-08-14 01:34:21 -0500
commit61a21e980a7b9188424d04f1c265fdc5c21c7e85 (patch)
tree9037e89c6f5ccb72b5e8b1dc150c6b0afd569531 /cpu/mpc85xx/traps.c
parent7bd30fc4a6475b41d6679ae3aafc9fa505260c47 (diff)
85xx start.S cleanup and exception support
From: Ed Swarthout <Ed.Swarthout@freescale.com> Support external interrupts from platform to eliminate system hangs. Define CONFIG_INTERRUPTS board configure option to enable. Enable ecm, ddr, lbc, and pci/pcie error interrupts in PIC. Remove extra cpu initialization redundant with hardware initialization. Whitespace cleanup. Define and use _START_OFFSET consistent with other processors using ppc_asm.tmpl Move additional code from .text to boot page to make room for exception vectors at start of image. Handle Machine Check, External and Critical exceptions. Fix e500 machine check error determination in traps.c TEXT_BASE can now be 0xfffc_0000 - which cuts binary image in half. Signed-off-by: Ed Swarthout <Ed.Swarthout@freescale.com> Acked-by: Andy Fleming <afleming@freescale.com>
Diffstat (limited to 'cpu/mpc85xx/traps.c')
-rw-r--r--cpu/mpc85xx/traps.c99
1 files changed, 79 insertions, 20 deletions
diff --git a/cpu/mpc85xx/traps.c b/cpu/mpc85xx/traps.c
index 9cd621c3a..efc80c7ae 100644
--- a/cpu/mpc85xx/traps.c
+++ b/cpu/mpc85xx/traps.c
@@ -1,6 +1,7 @@
/*
* linux/arch/ppc/kernel/traps.c
*
+ * Copyright 2007 Freescale Semiconductor.
* Copyright (C) 2003 Motorola
* Modified by Xianghua Xiao(x.xiao@motorola.com)
*
@@ -145,10 +146,13 @@ CritcalInputException(struct pt_regs *regs)
panic("Critical Input Exception");
}
+int machinecheck_count = 0;
+int machinecheck_error = 0;
void
MachineCheckException(struct pt_regs *regs)
{
unsigned long fixup;
+ unsigned int mcsr, mcsrr0, mcsrr1, mcar;
/* Probing PCI using config cycles cause this exception
* when a device is not present. Catch it and return to
@@ -159,34 +163,62 @@ MachineCheckException(struct pt_regs *regs)
return;
}
+ mcsrr0 = mfspr(SPRN_MCSRR0);
+ mcsrr1 = mfspr(SPRN_MCSRR1);
+ mcsr = mfspr(SPRN_MCSR);
+ mcar = mfspr(SPRN_MCAR);
+
+ machinecheck_count++;
+ machinecheck_error=1;
+
#if defined(CONFIG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
printf("Machine check in kernel mode.\n");
- printf("Caused by (from msr): ");
- printf("regs %p ",regs);
- switch( regs->msr & 0x000F0000) {
- case (0x80000000>>12):
- printf("Machine check signal - probably due to mm fault\n"
- "with mmu off\n");
- break;
- case (0x80000000>>13):
- printf("Transfer error ack signal\n");
- break;
- case (0x80000000>>14):
- printf("Data parity signal\n");
- break;
- case (0x80000000>>15):
- printf("Address parity signal\n");
- break;
- default:
- printf("Unknown values in msr\n");
- }
+ printf("Caused by (from mcsr): ");
+ printf("mcsr = 0x%08x\n", mcsr);
+ if (mcsr & 0x80000000)
+ printf("Machine check input pin\n");
+ if (mcsr & 0x40000000)
+ printf("Instruction cache parity error\n");
+ if (mcsr & 0x20000000)
+ printf("Data cache push parity error\n");
+ if (mcsr & 0x10000000)
+ printf("Data cache parity error\n");
+ if (mcsr & 0x00000080)
+ printf("Bus instruction address error\n");
+ if (mcsr & 0x00000040)
+ printf("Bus Read address error\n");
+ if (mcsr & 0x00000020)
+ printf("Bus Write address error\n");
+ if (mcsr & 0x00000010)
+ printf("Bus Instruction data bus error\n");
+ if (mcsr & 0x00000008)
+ printf("Bus Read data bus error\n");
+ if (mcsr & 0x00000004)
+ printf("Bus Write bus error\n");
+ if (mcsr & 0x00000002)
+ printf("Bus Instruction parity error\n");
+ if (mcsr & 0x00000001)
+ printf("Bus Read parity error\n");
+
show_regs(regs);
+ printf("MCSR=0x%08x \tMCSRR0=0x%08x \nMCSRR1=0x%08x \tMCAR=0x%08x\n",
+ mcsr, mcsrr0, mcsrr1, mcar);
print_backtrace((unsigned long *)regs->gpr[1]);
- panic("machine check");
+ if (machinecheck_count > 10) {
+ panic("machine check count too high\n");
+ }
+
+ if (machinecheck_count > 1) {
+ regs->nip += 4; /* skip offending instruction */
+ printf("Skipping current instr, Returning to 0x%08x\n",
+ regs->nip);
+ } else {
+ printf("Returning back to 0x%08x\n",regs->nip);
+ }
}
void
@@ -253,6 +285,33 @@ UnknownException(struct pt_regs *regs)
regs->nip, regs->msr, regs->trap);
_exception(0, regs);
}
+void
+ExtIntException(struct pt_regs *regs)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile ccsr_pic_t *pic = &immap->im_pic;
+ uint vect;
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("External Interrupt Exception at PC: %lx, SR: %lx, vector=%lx",
+ regs->nip, regs->msr, regs->trap);
+ vect = pic->iack0;
+ printf(" irq IACK0@%05x=%d\n",&pic->iack0,vect);
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ machinecheck_count++;
+#ifdef EXTINT_NOSKIP
+ printf("Returning back to 0x%08x\n",regs->nip);
+#else
+ regs->nip += 4; /* skip offending instruction */
+ printf("Skipping current instr, Returning to 0x%08x\n",regs->nip);
+#endif
+
+}
void
DebugException(struct pt_regs *regs)