From e7f75ad01d590243904c2d95ab47e6b2e9ef6dad Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Fri, 5 Mar 2010 10:43:12 +0000 Subject: powerpc/47x: Base ppc476 support This patch adds the base support for the 476 processor. The code was primarily written by Ben Herrenschmidt and Torez Smith, but I've been maintaining it for a while. The goal is to have a single binary that will run on 44x and 47x, but we still have some details to work out. The biggest is that the L1 cache line size differs on the two platforms, but it's currently a compile-time option. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Torez Smith Signed-off-by: Dave Kleikamp Signed-off-by: Josh Boyer --- arch/powerpc/include/asm/cputable.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/powerpc/include/asm/cputable.h') diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index abb833b0e58f..97ab5089df67 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -365,6 +365,7 @@ extern const char *powerpc_base_platform; #define CPU_FTRS_44X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE) #define CPU_FTRS_440x6 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE | \ CPU_FTR_INDEXED_DCR) +#define CPU_FTRS_47X (CPU_FTRS_440x6) #define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_SPE_COMP | \ CPU_FTR_NODSISRALIGN | CPU_FTR_COHERENT_ICACHE | \ CPU_FTR_UNIFIED_ID_CACHE | CPU_FTR_NOEXECUTE) @@ -453,6 +454,9 @@ enum { #ifdef CONFIG_44x CPU_FTRS_44X | CPU_FTRS_440x6 | #endif +#ifdef CONFIG_PPC_47x + CPU_FTRS_47X | +#endif #ifdef CONFIG_E200 CPU_FTRS_E200 | #endif -- cgit v1.2.3 From fc5e709731429bc2db27897630e7c0089f297680 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Fri, 5 Mar 2010 03:43:18 +0000 Subject: powerpc/476: add machine check handler for 47x core The 47x core's MCSR varies from 44x, so it needs it's own machine check handler. Signed-off-by: Dave Kleikamp Signed-off-by: Josh Boyer --- arch/powerpc/include/asm/cputable.h | 1 + arch/powerpc/kernel/cputable.c | 1 + arch/powerpc/kernel/traps.c | 40 +++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) (limited to 'arch/powerpc/include/asm/cputable.h') diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 97ab5089df67..e3cba4e1eb34 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -72,6 +72,7 @@ extern int machine_check_4xx(struct pt_regs *regs); extern int machine_check_440A(struct pt_regs *regs); extern int machine_check_e500(struct pt_regs *regs); extern int machine_check_e200(struct pt_regs *regs); +extern int machine_check_47x(struct pt_regs *regs); /* NOTE WELL: Update identify_cpu() if fields are added or removed! */ struct cpu_spec { diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index a1d845839727..ad6baf834a76 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1712,6 +1712,7 @@ static struct cpu_spec __initdata cpu_specs[] = { MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL, .icache_bsize = 32, .dcache_bsize = 128, + .machine_check = machine_check_47x, .platform = "ppc470", }, { /* default match */ diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 29d128eb6c43..ca7ce85ebc2e 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -380,6 +380,46 @@ int machine_check_440A(struct pt_regs *regs) } return 0; } + +int machine_check_47x(struct pt_regs *regs) +{ + unsigned long reason = get_mc_reason(regs); + u32 mcsr; + + printk(KERN_ERR "Machine check in kernel mode.\n"); + if (reason & ESR_IMCP) { + printk(KERN_ERR + "Instruction Synchronous Machine Check exception\n"); + mtspr(SPRN_ESR, reason & ~ESR_IMCP); + return 0; + } + mcsr = mfspr(SPRN_MCSR); + if (mcsr & MCSR_IB) + printk(KERN_ERR "Instruction Read PLB Error\n"); + if (mcsr & MCSR_DRB) + printk(KERN_ERR "Data Read PLB Error\n"); + if (mcsr & MCSR_DWB) + printk(KERN_ERR "Data Write PLB Error\n"); + if (mcsr & MCSR_TLBP) + printk(KERN_ERR "TLB Parity Error\n"); + if (mcsr & MCSR_ICP) { + flush_instruction_cache(); + printk(KERN_ERR "I-Cache Parity Error\n"); + } + if (mcsr & MCSR_DCSP) + printk(KERN_ERR "D-Cache Search Parity Error\n"); + if (mcsr & PPC47x_MCSR_GPR) + printk(KERN_ERR "GPR Parity Error\n"); + if (mcsr & PPC47x_MCSR_FPR) + printk(KERN_ERR "FPR Parity Error\n"); + if (mcsr & PPC47x_MCSR_IPR) + printk(KERN_ERR "Machine Check exception is imprecise\n"); + + /* Clear MCSR */ + mtspr(SPRN_MCSR, mcsr); + + return 0; +} #elif defined(CONFIG_E500) int machine_check_e500(struct pt_regs *regs) { -- cgit v1.2.3