This adds cpu_setup functionality to PowerPC 44x platform. The cpu_setup callback is invoked by head_32 code and the identify_cpu() function at early init and is used to initialize FPU on 440EP(x) processors. The FPU initialization was previously done in head_44x.S. Also a workaround for the incorrect write to DDR SDRAM 440EPx/440GRx errata added. Data can be written to wrong address in SDRAM when write pipelining is enabled on plb0. The setup_cpu function for these processors disables write pipelining.
Signed-off-by: Valentine Barshak <[EMAIL PROTECTED]> --- arch/powerpc/kernel/Makefile | 1 arch/powerpc/kernel/cpu_setup_44x.S | 54 ++++++++++++++++++++++++++++++++++++ arch/powerpc/kernel/cputable.c | 25 ++++++++++------ arch/powerpc/kernel/head_44x.S | 10 ------ 4 files changed, 70 insertions(+), 20 deletions(-) diff -ruN linux-2.6.orig/arch/powerpc/kernel/cpu_setup_44x.S linux-2.6/arch/powerpc/kernel/cpu_setup_44x.S --- linux-2.6.orig/arch/powerpc/kernel/cpu_setup_44x.S 1970-01-01 03:00:00.000000000 +0300 +++ linux-2.6/arch/powerpc/kernel/cpu_setup_44x.S 2007-09-20 21:05:44.000000000 +0400 @@ -0,0 +1,54 @@ +/* + * This file contains low level CPU setup functions. + * Valentine Barshak <[EMAIL PROTECTED]> + * MontaVista Software, Inc (c) 2007 + * + * Based on cpu_setup_6xx code by + * Benjamin Herrenschmidt <[EMAIL PROTECTED]> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include <asm/processor.h> +#include <asm/cputable.h> +#include <asm/ppc_asm.h> + +_GLOBAL(__setup_cpu_440ep) + b __init_fpu_44x +_GLOBAL(__setup_cpu_440epx) + mflr r4 + bl __init_fpu_44x +_GLOBAL(__setup_cpu_440grx) + bl __plb_disable_wrp + mtlr r4 + blr + +/* enable APU between CPU and FPU */ +_GLOBAL(__init_fpu_44x) + mfspr r3,SPRN_CCR0 + /* Clear DAPUIB flag in CCR0 */ + rlwinm r3,r3,0,12,10 + mtspr SPRN_CCR0,r3 + isync + blr + +/* + * Workaround for the incorrect write to DDR SDRAM errata. + * The write address can be corrupted during writes to + * DDR SDRAM when write pipelining is enabled on PLB0. + * Disable write pipelining here. + */ +#define DCRN_PLB4A0_ACR 0x81 + +_GLOBAL(__plb_disable_wrp) + mfdcr r3,DCRN_PLB4A0_ACR + /* clear WRP bit in PLB4A0_ACR */ + rlwinm r3,r3,0,8,6 + mtdcr DCRN_PLB4A0_ACR,r3 + isync + blr + diff -ruN linux-2.6.orig/arch/powerpc/kernel/cputable.c linux-2.6/arch/powerpc/kernel/cputable.c --- linux-2.6.orig/arch/powerpc/kernel/cputable.c 2007-09-20 19:30:47.000000000 +0400 +++ linux-2.6/arch/powerpc/kernel/cputable.c 2007-09-20 21:27:35.000000000 +0400 @@ -31,6 +31,9 @@ * and ppc64 */ #ifdef CONFIG_PPC32 +extern void __setup_cpu_440ep(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); @@ -1111,6 +1114,7 @@ .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .icache_bsize = 32, .dcache_bsize = 32, + .cpu_setup = __setup_cpu_440ep, .platform = "ppc440", }, { @@ -1121,6 +1125,7 @@ .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .icache_bsize = 32, .dcache_bsize = 32, + .cpu_setup = __setup_cpu_440ep, .platform = "ppc440", }, { /* 440EPX */ @@ -1131,6 +1136,8 @@ .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .icache_bsize = 32, .dcache_bsize = 32, + .cpu_setup = __setup_cpu_440epx, + .platform = "ppc440", }, { /* 440GRX */ .pvr_mask = 0xf0000ffb, @@ -1140,6 +1147,8 @@ .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, .dcache_bsize = 32, + .cpu_setup = __setup_cpu_440grx, + .platform = "ppc440", }, { /* 440GP Rev. B */ .pvr_mask = 0xf0000fff, @@ -1318,18 +1327,14 @@ for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) if ((pvr & s->pvr_mask) == s->pvr_value) { + cpu_setup_t setup_func = PTRRELOC(s->cpu_setup); + *cur = cpu_specs + i; -#ifdef CONFIG_PPC64 - /* ppc64 expects identify_cpu to also call setup_cpu - * for that processor. I will consolidate that at a - * later time, for now, just use our friend #ifdef. - * we also don't need to PTRRELOC the function pointer - * on ppc64 as we are running at 0 in real mode. + /* ppc expects identify_cpu to also call setup_cpu + * for that processor. */ - if (s->cpu_setup) { - s->cpu_setup(offset, s); - } -#endif /* CONFIG_PPC64 */ + if (setup_func) + setup_func(offset, s); return s; } BUG(); diff -ruN linux-2.6.orig/arch/powerpc/kernel/head_44x.S linux-2.6/arch/powerpc/kernel/head_44x.S --- linux-2.6.orig/arch/powerpc/kernel/head_44x.S 2007-09-20 19:30:47.000000000 +0400 +++ linux-2.6/arch/powerpc/kernel/head_44x.S 2007-09-20 20:04:39.000000000 +0400 @@ -217,16 +217,6 @@ lis r4,[EMAIL PROTECTED] /* IVPR only uses the high 16-bits */ mtspr SPRN_IVPR,r4 -#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) - /* Clear DAPUIB flag in CCR0 (enable APU between CPU and FPU) */ - mfspr r2,SPRN_CCR0 - lis r3,0xffef - ori r3,r3,0xffff - and r2,r2,r3 - mtspr SPRN_CCR0,r2 - isync -#endif - /* * This is where the main kernel code starts. */ diff -ruN linux-2.6.orig/arch/powerpc/kernel/Makefile linux-2.6/arch/powerpc/kernel/Makefile --- linux-2.6.orig/arch/powerpc/kernel/Makefile 2007-09-20 19:30:47.000000000 +0400 +++ linux-2.6/arch/powerpc/kernel/Makefile 2007-09-20 19:52:21.000000000 +0400 @@ -56,6 +56,7 @@ udbg.o misc.o io.o obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o +obj-$(CONFIG_44x) += cpu_setup_44x.o obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o obj-$(CONFIG_MODULES) += ppc_ksyms.o obj-$(CONFIG_BOOTX_TEXT) += btext.o _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev