diff options
Diffstat (limited to 'cpu/mpc83xx')
| -rw-r--r-- | cpu/mpc83xx/Makefile | 2 | ||||
| -rw-r--r-- | cpu/mpc83xx/config.mk | 5 | ||||
| -rw-r--r-- | cpu/mpc83xx/cpu.c | 118 | ||||
| -rw-r--r-- | cpu/mpc83xx/cpu_init.c | 50 | ||||
| -rw-r--r-- | cpu/mpc83xx/ecc.c | 390 | ||||
| -rw-r--r-- | cpu/mpc83xx/interrupts.c | 4 | ||||
| -rw-r--r-- | cpu/mpc83xx/pci.c | 36 | ||||
| -rw-r--r-- | cpu/mpc83xx/spd_sdram.c | 13 | ||||
| -rw-r--r-- | cpu/mpc83xx/traps.c | 14 | ||||
| -rw-r--r-- | cpu/mpc83xx/u-boot.lds | 122 | 
10 files changed, 687 insertions, 67 deletions
| diff --git a/cpu/mpc83xx/Makefile b/cpu/mpc83xx/Makefile index bb96f774f..232997005 100644 --- a/cpu/mpc83xx/Makefile +++ b/cpu/mpc83xx/Makefile @@ -29,7 +29,7 @@ LIB	= $(obj)lib$(CPU).a  START	= start.o  COBJS	= traps.o cpu.o cpu_init.o speed.o interrupts.o \ -	  spd_sdram.o qe_io.o pci.o +	  spd_sdram.o ecc.o qe_io.o pci.o  SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/mpc83xx/config.mk b/cpu/mpc83xx/config.mk index 8b4ff92b1..2ec395d4c 100644 --- a/cpu/mpc83xx/config.mk +++ b/cpu/mpc83xx/config.mk @@ -20,7 +20,10 @@  # MA 02111-1307 USA  # -PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi +PLATFORM_RELFLAGS += -fPIC -ffixed-r14 -meabi -mrelocatable  PLATFORM_CPPFLAGS += -DCONFIG_MPC83XX -DCONFIG_E300 \  			-ffixed-r2 -ffixed-r29 -msoft-float + +# Use default linker script.  Board port can override in board/*/config.mk +LDSCRIPT := $(SRCTREE)/cpu/mpc83xx/u-boot.lds diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index 841fe8242..adf808301 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -33,8 +33,7 @@  #include <asm/processor.h>  #if defined(CONFIG_OF_FLAT_TREE)  #include <ft_build.h> -#endif -#if defined(CONFIG_OF_LIBFDT) +#elif defined(CONFIG_OF_LIBFDT)  #include <libfdt.h>  #include <libfdt_env.h>  #endif @@ -113,12 +112,14 @@ int checkcpu(void)  	case SPR_8360E_REV11:  	case SPR_8360E_REV12:  	case SPR_8360E_REV20: +	case SPR_8360E_REV21:  		puts("MPC8360E, ");  		break;  	case SPR_8360_REV10:  	case SPR_8360_REV11:  	case SPR_8360_REV12:  	case SPR_8360_REV20: +	case SPR_8360_REV21:  		puts("MPC8360, ");  		break;  	case SPR_8323E_REV10: @@ -150,7 +151,8 @@ int checkcpu(void)  		puts("MPC8313E, ");  		break;  	default: -		puts("Rev: Unknown revision number.\nWarning: Unsupported cpu revision!\n"); +		printf("Rev: Unknown revision number:%08x\n" +			"Warning: Unsupported cpu revision!\n",spridr);  		return 0;  	} @@ -329,154 +331,167 @@ void watchdog_reset (void)  /*   * "Setter" functions used to add/modify FDT entries.   */ -static int fdt_set_eth0(void *fdt, int nodeoffset, const char *name, bd_t *bd) +static int fdt_set_eth0(void *blob, int nodeoffset, const char *name, bd_t *bd)  {  	/*  	 * Fix it up if it exists, don't create it if it doesn't exist.  	 */ -	if (fdt_get_property(fdt, nodeoffset, name, 0)) { -		return fdt_setprop(fdt, nodeoffset, name, bd->bi_enetaddr, 6); +	if (fdt_get_property(blob, nodeoffset, name, 0)) { +		return fdt_setprop(blob, nodeoffset, name, bd->bi_enetaddr, 6);  	} -	return -FDT_ERR_NOTFOUND; +	return 0;  }  #ifdef CONFIG_HAS_ETH1  /* second onboard ethernet port */ -static int fdt_set_eth1(void *fdt, int nodeoffset, const char *name, bd_t *bd) +static int fdt_set_eth1(void *blob, int nodeoffset, const char *name, bd_t *bd)  {  	/*  	 * Fix it up if it exists, don't create it if it doesn't exist.  	 */ -	if (fdt_get_property(fdt, nodeoffset, name, 0)) { -		return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet1addr, 6); +	if (fdt_get_property(blob, nodeoffset, name, 0)) { +		return fdt_setprop(blob, nodeoffset, name, bd->bi_enet1addr, 6);  	} -	return -FDT_ERR_NOTFOUND; +	return 0;  }  #endif  #ifdef CONFIG_HAS_ETH2  /* third onboard ethernet port */ -static int fdt_set_eth2(void *fdt, int nodeoffset, const char *name, bd_t *bd) +static int fdt_set_eth2(void *blob, int nodeoffset, const char *name, bd_t *bd)  {  	/*  	 * Fix it up if it exists, don't create it if it doesn't exist.  	 */ -	if (fdt_get_property(fdt, nodeoffset, name, 0)) { -		return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet2addr, 6); +	if (fdt_get_property(blob, nodeoffset, name, 0)) { +		return fdt_setprop(blob, nodeoffset, name, bd->bi_enet2addr, 6);  	} -	return -FDT_ERR_NOTFOUND; +	return 0;  }  #endif  #ifdef CONFIG_HAS_ETH3  /* fourth onboard ethernet port */ -static int fdt_set_eth3(void *fdt, int nodeoffset, const char *name, bd_t *bd) +static int fdt_set_eth3(void *blob, int nodeoffset, const char *name, bd_t *bd)  {  	/*  	 * Fix it up if it exists, don't create it if it doesn't exist.  	 */ -	if (fdt_get_property(fdt, nodeoffset, name, 0)) { -		return fdt_setprop(fdt, nodeoffset, name, bd->bi_enet3addr, 6); +	if (fdt_get_property(blob, nodeoffset, name, 0)) { +		return fdt_setprop(blob, nodeoffset, name, bd->bi_enet3addr, 6);  	} -	return -FDT_ERR_NOTFOUND; +	return 0;  }  #endif -static int fdt_set_busfreq(void *fdt, int nodeoffset, const char *name, bd_t *bd) +static int fdt_set_busfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)  {  	u32  tmp;  	/*  	 * Create or update the property.  	 */  	tmp = cpu_to_be32(bd->bi_busfreq); -	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +	return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp)); +} + +static int fdt_set_tbfreq(void *blob, int nodeoffset, const char *name, bd_t *bd) +{ +	u32  tmp; +	/* +	 * Create or update the property. +	 */ +	tmp = cpu_to_be32(OF_TBCLK); +	return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));  } +  /* - * Fixups to the fdt.  If "create" is TRUE, the node is created - * unconditionally.  If "create" is FALSE, the node is updated - * only if it already exists. + * Fixups to the fdt.   */  static const struct {  	char *node;  	char *prop; -	int (*set_fn)(void *fdt, int nodeoffset, const char *name, bd_t *bd); +	int (*set_fn)(void *blob, int nodeoffset, const char *name, bd_t *bd);  } fixup_props[] = {  	{	"/cpus/" OF_CPU, -		 "bus-frequency", -		fdt_set_busfreq +		"timebase-frequency", +		fdt_set_tbfreq  	}, -	{	"/cpus/" OF_SOC, +	{	"/cpus/" OF_CPU,  		"bus-frequency",  		fdt_set_busfreq  	}, -	{	"/" OF_SOC "/serial@4500/", +	{	"/cpus/" OF_CPU, +		"clock-frequency", +		fdt_set_busfreq +	}, +	{	"/" OF_SOC "/serial@4500",  		"clock-frequency",  		fdt_set_busfreq  	}, -	{	"/" OF_SOC "/serial@4600/", +	{	"/" OF_SOC "/serial@4600",  		"clock-frequency",  		fdt_set_busfreq  	},  #ifdef CONFIG_TSEC1 -	{	"/" OF_SOC "/ethernet@24000, +	{	"/" OF_SOC "/ethernet@24000",  		"mac-address",  		fdt_set_eth0  	}, -	{	"/" OF_SOC "/ethernet@24000, +	{	"/" OF_SOC "/ethernet@24000",  		"local-mac-address",  		fdt_set_eth0  	},  #endif  #ifdef CONFIG_TSEC2 -	{	"/" OF_SOC "/ethernet@25000, +	{	"/" OF_SOC "/ethernet@25000",  		"mac-address",  		fdt_set_eth1  	}, -	{	"/" OF_SOC "/ethernet@25000, +	{	"/" OF_SOC "/ethernet@25000",  		"local-mac-address",  		fdt_set_eth1  	},  #endif  #ifdef CONFIG_UEC_ETH1  #if CFG_UEC1_UCC_NUM == 0  /* UCC1 */ -	{	"/" OF_QE "/ucc@2000/mac-address", +	{	"/" OF_QE "/ucc@2000",  		"mac-address",  		fdt_set_eth0  	}, -	{	"/" OF_QE "/ucc@2000/mac-address", +	{	"/" OF_QE "/ucc@2000",  		"local-mac-address",  		fdt_set_eth0  	},  #elif CFG_UEC1_UCC_NUM == 2  /* UCC3 */ -	{	"/" OF_QE "/ucc@2200/mac-address", +	{	"/" OF_QE "/ucc@2200",  		"mac-address",  		fdt_set_eth0  	}, -	{	"/" OF_QE "/ucc@2200/mac-address", +	{	"/" OF_QE "/ucc@2200",  		"local-mac-address",  		fdt_set_eth0  	},  #endif -#endif +#endif /* CONFIG_UEC_ETH1 */  #ifdef CONFIG_UEC_ETH2  #if CFG_UEC2_UCC_NUM == 1  /* UCC2 */ -	{	"/" OF_QE "/ucc@3000/mac-address", +	{	"/" OF_QE "/ucc@3000",  		"mac-address",  		fdt_set_eth1  	}, -	{	"/" OF_QE "/ucc@3000/mac-address", +	{	"/" OF_QE "/ucc@3000",  		"local-mac-address",  		fdt_set_eth1  	},  #elif CFG_UEC1_UCC_NUM == 3  /* UCC4 */ -	{	"/" OF_QE "/ucc@3200/mac-address", +	{	"/" OF_QE "/ucc@3200",  		"mac-address",  		fdt_set_eth1  	}, -	{	"/" OF_QE "/ucc@3200/mac-address", +	{	"/" OF_QE "/ucc@3200",  		"local-mac-address",  		fdt_set_eth1  	},  #endif -#endif +#endif /* CONFIG_UEC_ETH2 */  };  void @@ -487,20 +502,23 @@ ft_cpu_setup(void *blob, bd_t *bd)  	int  j;  	for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) { -		nodeoffset = fdt_path_offset(fdt, fixup_props[j].node); +		nodeoffset = fdt_find_node_by_path(blob, fixup_props[j].node);  		if (nodeoffset >= 0) { -			err = (*fixup_props[j].set_fn)(blob, nodeoffset, fixup_props[j].prop, bd); +			err = fixup_props[j].set_fn(blob, nodeoffset, +						    fixup_props[j].prop, bd);  			if (err < 0) -				printf("set_fn/libfdt: %s %s returned %s\n", +				debug("Problem setting %s = %s: %s\n",  					fixup_props[j].node,  					fixup_props[j].prop,  					fdt_strerror(err)); +		} else { +			debug("Couldn't find %s: %s\n", +				fixup_props[j].node, +				fdt_strerror(nodeoffset));  		}  	}  } -#endif - -#if defined(CONFIG_OF_FLAT_TREE) +#elif defined(CONFIG_OF_FLAT_TREE)  void  ft_cpu_setup(void *blob, bd_t *bd)  { diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c index 3ac91619c..722497966 100644 --- a/cpu/mpc83xx/cpu_init.c +++ b/cpu/mpc83xx/cpu_init.c @@ -83,20 +83,30 @@ void cpu_init_f (volatile immap_t * im)  	im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_TSEC2EP) | (CFG_SPCR_TSEC2EP << SPCR_TSEC2EP_SHIFT);  #endif -#ifdef CONFIG_MPC834X  #ifdef CFG_SCCR_TSEC1CM  	/* TSEC1 clock mode */  	im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC1CM) | (CFG_SCCR_TSEC1CM << SCCR_TSEC1CM_SHIFT);  #endif +  #ifdef CFG_SCCR_TSEC2CM  	/* TSEC2 & I2C1 clock mode */  	im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC2CM) | (CFG_SCCR_TSEC2CM << SCCR_TSEC2CM_SHIFT);  #endif + +#ifdef CFG_SCCR_TSEC1ON +	/* TSEC1 clock switch */ +	im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC1ON) | (CFG_SCCR_TSEC1ON << SCCR_TSEC1ON_SHIFT); +#endif + +#ifdef CFG_SCCR_TSEC2ON +	/* TSEC2 clock switch */ +	im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC2ON) | (CFG_SCCR_TSEC2ON << SCCR_TSEC2ON_SHIFT); +#endif +  #ifdef CFG_SCCR_USBMPHCM  	/* USB MPH clock mode */  	im->clk.sccr = (im->clk.sccr & ~SCCR_USBMPHCM) | (CFG_SCCR_USBMPHCM << SCCR_USBMPHCM_SHIFT);  #endif -#endif /* CONFIG_MPC834X */  #ifdef CFG_SCCR_PCICM  	/* PCI & DMA clock mode */ @@ -247,3 +257,39 @@ int cpu_init_r (void)  #endif  	return 0;  } + +/* + * Figure out the cause of the reset + */ +int prt_83xx_rsr(void) +{ +	static struct { +		ulong mask; +		char *desc; +	} bits[] = { +		{ +		RSR_SWSR, "Software Soft"}, { +		RSR_SWHR, "Software Hard"}, { +		RSR_JSRS, "JTAG Soft"}, { +		RSR_CSHR, "Check Stop"}, { +		RSR_SWRS, "Software Watchdog"}, { +		RSR_BMRS, "Bus Monitor"}, { +		RSR_SRS,  "External/Internal Soft"}, { +		RSR_HRS,  "External/Internal Hard"} +	}; +	static int n = sizeof bits / sizeof bits[0]; +	ulong rsr = gd->reset_status; +	int i; +	char *sep; + +	puts("Reset Status:"); + +	sep = " "; +	for (i = 0; i < n; i++) +		if (rsr & bits[i].mask) { +			printf("%s%s", sep, bits[i].desc); +			sep = ", "; +		} +	puts("\n\n"); +	return 0; +} diff --git a/cpu/mpc83xx/ecc.c b/cpu/mpc83xx/ecc.c new file mode 100644 index 000000000..6f1309424 --- /dev/null +++ b/cpu/mpc83xx/ecc.c @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2007 Freescale Semiconductor, Inc. + * + * Dave Liu <daveliu@freescale.com> + * based on the contribution of Marian Balakowicz <m8@semihalf.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 <common.h> +#include <mpc83xx.h> +#include <command.h> + +#if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) +void ecc_print_status(void) +{ +	volatile immap_t *immap = (immap_t *) CFG_IMMR; +	volatile ddr83xx_t *ddr = &immap->ddr; + +	printf("\nECC mode: %s\n\n", +	       (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF"); + +	/* Interrupts */ +	printf("Memory Error Interrupt Enable:\n"); +	printf("  Multiple-Bit Error Interrupt Enable: %d\n", +	       (ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0); +	printf("  Single-Bit Error Interrupt Enable: %d\n", +	       (ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0); +	printf("  Memory Select Error Interrupt Enable: %d\n\n", +	       (ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0); + +	/* Error disable */ +	printf("Memory Error Disable:\n"); +	printf("  Multiple-Bit Error Disable: %d\n", +	       (ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0); +	printf("  Sinle-Bit Error Disable: %d\n", +	       (ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0); +	printf("  Memory Select Error Disable: %d\n\n", +	       (ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0); + +	/* Error injection */ +	printf("Memory Data Path Error Injection Mask High/Low: %08lx %08lx\n", +	       ddr->data_err_inject_hi, ddr->data_err_inject_lo); + +	printf("Memory Data Path Error Injection Mask ECC:\n"); +	printf("  ECC Mirror Byte: %d\n", +	       (ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0); +	printf("  ECC Injection Enable: %d\n", +	       (ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0); +	printf("  ECC Error Injection Mask: 0x%02x\n\n", +	       ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM); + +	/* SBE counter/threshold */ +	printf("Memory Single-Bit Error Management (0..255):\n"); +	printf("  Single-Bit Error Threshold: %d\n", +	       (ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT); +	printf("  Single-Bit Error Counter: %d\n\n", +	       (ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT); + +	/* Error detect */ +	printf("Memory Error Detect:\n"); +	printf("  Multiple Memory Errors: %d\n", +	       (ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0); +	printf("  Multiple-Bit Error: %d\n", +	       (ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0); +	printf("  Single-Bit Error: %d\n", +	       (ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0); +	printf("  Memory Select Error: %d\n\n", +	       (ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0); + +	/* Capture data */ +	printf("Memory Error Address Capture: 0x%08lx\n", ddr->capture_address); +	printf("Memory Data Path Read Capture High/Low: %08lx %08lx\n", +	       ddr->capture_data_hi, ddr->capture_data_lo); +	printf("Memory Data Path Read Capture ECC: 0x%02x\n\n", +	       ddr->capture_ecc & CAPTURE_ECC_ECE); + +	printf("Memory Error Attributes Capture:\n"); +	printf(" Data Beat Number: %d\n", +	       (ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >> +	       ECC_CAPT_ATTR_BNUM_SHIFT); +	printf("  Transaction Size: %d\n", +	       (ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >> +	       ECC_CAPT_ATTR_TSIZ_SHIFT); +	printf("  Transaction Source: %d\n", +	       (ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >> +	       ECC_CAPT_ATTR_TSRC_SHIFT); +	printf("  Transaction Type: %d\n", +	       (ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >> +	       ECC_CAPT_ATTR_TTYP_SHIFT); +	printf("  Error Information Valid: %d\n\n", +	       ddr->capture_attributes & ECC_CAPT_ATTR_VLD); +} + +int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ +	volatile immap_t *immap = (immap_t *) CFG_IMMR; +	volatile ddr83xx_t *ddr = &immap->ddr; +	volatile u32 val; +	u64 *addr; +	u32 count; +	register u64 *i; +	u32 ret[2]; +	u32 pattern[2]; +	u32 writeback[2]; + +	/* The pattern is written into memory to generate error */ +	pattern[0] = 0xfedcba98UL; +	pattern[1] = 0x76543210UL; + +	/* After injecting error, re-initialize the memory with the value */ +	writeback[0] = 0x01234567UL; +	writeback[1] = 0x89abcdefUL; + +	if (argc > 4) { +		printf("Usage:\n%s\n", cmdtp->usage); +		return 1; +	} + +	if (argc == 2) { +		if (strcmp(argv[1], "status") == 0) { +			ecc_print_status(); +			return 0; +		} else if (strcmp(argv[1], "captureclear") == 0) { +			ddr->capture_address = 0; +			ddr->capture_data_hi = 0; +			ddr->capture_data_lo = 0; +			ddr->capture_ecc = 0; +			ddr->capture_attributes = 0; +			return 0; +		} +	} +	if (argc == 3) { +		if (strcmp(argv[1], "sbecnt") == 0) { +			val = simple_strtoul(argv[2], NULL, 10); +			if (val > 255) { +				printf("Incorrect Counter value, " +				       "should be 0..255\n"); +				return 1; +			} + +			val = (val << ECC_ERROR_MAN_SBEC_SHIFT); +			val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET); + +			ddr->err_sbe = val; +			return 0; +		} else if (strcmp(argv[1], "sbethr") == 0) { +			val = simple_strtoul(argv[2], NULL, 10); +			if (val > 255) { +				printf("Incorrect Counter value, " +				       "should be 0..255\n"); +				return 1; +			} + +			val = (val << ECC_ERROR_MAN_SBET_SHIFT); +			val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC); + +			ddr->err_sbe = val; +			return 0; +		} else if (strcmp(argv[1], "errdisable") == 0) { +			val = ddr->err_disable; + +			if (strcmp(argv[2], "+sbe") == 0) { +				val |= ECC_ERROR_DISABLE_SBED; +			} else if (strcmp(argv[2], "+mbe") == 0) { +				val |= ECC_ERROR_DISABLE_MBED; +			} else if (strcmp(argv[2], "+mse") == 0) { +				val |= ECC_ERROR_DISABLE_MSED; +			} else if (strcmp(argv[2], "+all") == 0) { +				val |= (ECC_ERROR_DISABLE_SBED | +					ECC_ERROR_DISABLE_MBED | +					ECC_ERROR_DISABLE_MSED); +			} else if (strcmp(argv[2], "-sbe") == 0) { +				val &= ~ECC_ERROR_DISABLE_SBED; +			} else if (strcmp(argv[2], "-mbe") == 0) { +				val &= ~ECC_ERROR_DISABLE_MBED; +			} else if (strcmp(argv[2], "-mse") == 0) { +				val &= ~ECC_ERROR_DISABLE_MSED; +			} else if (strcmp(argv[2], "-all") == 0) { +				val &= ~(ECC_ERROR_DISABLE_SBED | +					 ECC_ERROR_DISABLE_MBED | +					 ECC_ERROR_DISABLE_MSED); +			} else { +				printf("Incorrect err_disable field\n"); +				return 1; +			} + +			ddr->err_disable = val; +			__asm__ __volatile__("sync"); +			__asm__ __volatile__("isync"); +			return 0; +		} else if (strcmp(argv[1], "errdetectclr") == 0) { +			val = ddr->err_detect; + +			if (strcmp(argv[2], "mme") == 0) { +				val |= ECC_ERROR_DETECT_MME; +			} else if (strcmp(argv[2], "sbe") == 0) { +				val |= ECC_ERROR_DETECT_SBE; +			} else if (strcmp(argv[2], "mbe") == 0) { +				val |= ECC_ERROR_DETECT_MBE; +			} else if (strcmp(argv[2], "mse") == 0) { +				val |= ECC_ERROR_DETECT_MSE; +			} else if (strcmp(argv[2], "all") == 0) { +				val |= (ECC_ERROR_DETECT_MME | +					ECC_ERROR_DETECT_MBE | +					ECC_ERROR_DETECT_SBE | +					ECC_ERROR_DETECT_MSE); +			} else { +				printf("Incorrect err_detect field\n"); +				return 1; +			} + +			ddr->err_detect = val; +			return 0; +		} else if (strcmp(argv[1], "injectdatahi") == 0) { +			val = simple_strtoul(argv[2], NULL, 16); + +			ddr->data_err_inject_hi = val; +			return 0; +		} else if (strcmp(argv[1], "injectdatalo") == 0) { +			val = simple_strtoul(argv[2], NULL, 16); + +			ddr->data_err_inject_lo = val; +			return 0; +		} else if (strcmp(argv[1], "injectecc") == 0) { +			val = simple_strtoul(argv[2], NULL, 16); +			if (val > 0xff) { +				printf("Incorrect ECC inject mask, " +				       "should be 0x00..0xff\n"); +				return 1; +			} +			val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM); + +			ddr->ecc_err_inject = val; +			return 0; +		} else if (strcmp(argv[1], "inject") == 0) { +			val = ddr->ecc_err_inject; + +			if (strcmp(argv[2], "en") == 0) +				val |= ECC_ERR_INJECT_EIEN; +			else if (strcmp(argv[2], "dis") == 0) +				val &= ~ECC_ERR_INJECT_EIEN; +			else +				printf("Incorrect command\n"); + +			ddr->ecc_err_inject = val; +			__asm__ __volatile__("sync"); +			__asm__ __volatile__("isync"); +			return 0; +		} else if (strcmp(argv[1], "mirror") == 0) { +			val = ddr->ecc_err_inject; + +			if (strcmp(argv[2], "en") == 0) +				val |= ECC_ERR_INJECT_EMB; +			else if (strcmp(argv[2], "dis") == 0) +				val &= ~ECC_ERR_INJECT_EMB; +			else +				printf("Incorrect command\n"); + +			ddr->ecc_err_inject = val; +			return 0; +		} +	} +	if (argc == 4) { +		if (strcmp(argv[1], "testdw") == 0) { +			addr = (u64 *) simple_strtoul(argv[2], NULL, 16); +			count = simple_strtoul(argv[3], NULL, 16); + +			if ((u32) addr % 8) { +				printf("Address not alligned on " +				       "double word boundary\n"); +				return 1; +			} +			disable_interrupts(); + +			for (i = addr; i < addr + count; i++) { + +				/* enable injects */ +				ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; +				__asm__ __volatile__("sync"); +				__asm__ __volatile__("isync"); + +				/* write memory location injecting errors */ +				ppcDWstore((u32 *) i, pattern); +				__asm__ __volatile__("sync"); + +				/* disable injects */ +				ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; +				__asm__ __volatile__("sync"); +				__asm__ __volatile__("isync"); + +				/* read data, this generates ECC error */ +				ppcDWload((u32 *) i, ret); +				__asm__ __volatile__("sync"); + +				/* re-initialize memory, double word write the location again, +				 * generates new ECC code this time */ +				ppcDWstore((u32 *) i, writeback); +				__asm__ __volatile__("sync"); +			} +			enable_interrupts(); +			return 0; +		} +		if (strcmp(argv[1], "testword") == 0) { +			addr = (u64 *) simple_strtoul(argv[2], NULL, 16); +			count = simple_strtoul(argv[3], NULL, 16); + +			if ((u32) addr % 8) { +				printf("Address not alligned on " +				       "double word boundary\n"); +				return 1; +			} +			disable_interrupts(); + +			for (i = addr; i < addr + count; i++) { + +				/* enable injects */ +				ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; +				__asm__ __volatile__("sync"); +				__asm__ __volatile__("isync"); + +				/* write memory location injecting errors */ +				*(u32 *) i = 0xfedcba98UL; +				__asm__ __volatile__("sync"); + +				/* sub double word write, +				 * bus will read-modify-write, +				 * generates ECC error */ +				*((u32 *) i + 1) = 0x76543210UL; +				__asm__ __volatile__("sync"); + +				/* disable injects */ +				ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; +				__asm__ __volatile__("sync"); +				__asm__ __volatile__("isync"); + +				/* re-initialize memory, +				 * double word write the location again, +				 * generates new ECC code this time */ +				ppcDWstore((u32 *) i, writeback); +				__asm__ __volatile__("sync"); +			} +			enable_interrupts(); +			return 0; +		} +	} +	printf("Usage:\n%s\n", cmdtp->usage); +	return 1; +} + +U_BOOT_CMD(ecc, 4, 0, do_ecc, +	   "ecc     - support for DDR ECC features\n", +	   "status              - print out status info\n" +	   "ecc captureclear        - clear capture regs data\n" +	   "ecc sbecnt <val>        - set Single-Bit Error counter\n" +	   "ecc sbethr <val>        - set Single-Bit Threshold\n" +	   "ecc errdisable <flag>   - clear/set disable Memory Error Disable, flag:\n" +	   "  [-|+]sbe - Single-Bit Error\n" +	   "  [-|+]mbe - Multiple-Bit Error\n" +	   "  [-|+]mse - Memory Select Error\n" +	   "  [-|+]all - all errors\n" +	   "ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n" +	   "  mme - Multiple Memory Errors\n" +	   "  sbe - Single-Bit Error\n" +	   "  mbe - Multiple-Bit Error\n" +	   "  mse - Memory Select Error\n" +	   "  all - all errors\n" +	   "ecc injectdatahi <hi>  - set Memory Data Path Error Injection Mask High\n" +	   "ecc injectdatalo <lo>  - set Memory Data Path Error Injection Mask Low\n" +	   "ecc injectecc <ecc>    - set ECC Error Injection Mask\n" +	   "ecc inject <en|dis>    - enable/disable error injection\n" +	   "ecc mirror <en|dis>    - enable/disable mirror byte\n" +	   "ecc testdw <addr> <cnt>  - test mem region with double word access:\n" +	   "  - enables injects\n" +	   "  - writes pattern injecting errors with double word access\n" +	   "  - disables injects\n" +	   "  - reads pattern back with double word access, generates error\n" +	   "  - re-inits memory\n" +	   "ecc testword <addr> <cnt>  - test mem region with word access:\n" +	   "  - enables injects\n" +	   "  - writes pattern injecting errors with word access\n" +	   "  - writes pattern with word access, generates error\n" +	   "  - disables injects\n" "  - re-inits memory"); +#endif diff --git a/cpu/mpc83xx/interrupts.c b/cpu/mpc83xx/interrupts.c index bb1fe1af3..98ed21ccf 100644 --- a/cpu/mpc83xx/interrupts.c +++ b/cpu/mpc83xx/interrupts.c @@ -81,7 +81,7 @@ void timer_interrupt_cpu (struct pt_regs *regs)  } -#if (CONFIG_COMMANDS & CFG_CMD_IRQ) +#if defined(CONFIG_CMD_IRQ)  /* ripped this out of ppc4xx/interrupts.c */ @@ -94,4 +94,4 @@ do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])  {  } -#endif		/* CONFIG_COMMANDS & CFG_CMD_IRQ */ +#endif diff --git a/cpu/mpc83xx/pci.c b/cpu/mpc83xx/pci.c index 785d6129d..229821887 100644 --- a/cpu/mpc83xx/pci.c +++ b/cpu/mpc83xx/pci.c @@ -25,7 +25,14 @@  #include <common.h>  #include <pci.h> + +#if defined(CONFIG_OF_LIBFDT) +#include <libfdt.h> +#include <libfdt_env.h> +#elif defined(CONFIG_OF_FLAT_TREE)  #include <ft_build.h> +#endif +  #include <asm/mpc8349_pci.h>  #ifdef CONFIG_83XX_GENERIC_PCI @@ -163,7 +170,34 @@ void mpc83xx_pci_init(int num_buses, struct pci_region **reg, int warmboot)  		pci_init_bus(i, reg[i]);  } -#ifdef CONFIG_OF_FLAT_TREE +#if defined(CONFIG_OF_LIBFDT) +void ft_pci_setup(void *blob, bd_t *bd) +{ +	int nodeoffset; +	int err; +	int tmp[2]; + +	if (pci_num_buses < 1) +		return; + +	nodeoffset = fdt_find_node_by_path(blob, "/" OF_SOC "/pci@8500"); +	if (nodeoffset >= 0) { +		tmp[0] = cpu_to_be32(pci_hose[0].first_busno); +		tmp[1] = cpu_to_be32(pci_hose[0].last_busno); +		err = fdt_setprop(blob, nodeoffset, "bus-range", tmp, sizeof(tmp)); +	} + +	if (pci_num_buses < 2) +		return; + +	nodeoffset = fdt_find_node_by_path(blob, "/" OF_SOC "/pci@8600"); +	if (nodeoffset >= 0) { +		tmp[0] = cpu_to_be32(pci_hose[0].first_busno); +		tmp[1] = cpu_to_be32(pci_hose[0].last_busno); +		err = fdt_setprop(blob, nodeoffset, "bus-range", tmp, sizeof(tmp)); +	} +} +#elif CONFIG_OF_FLAT_TREE  void ft_pci_setup(void *blob, bd_t *bd)  {  	u32 *p; diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c index 647813f68..54f0c83d4 100644 --- a/cpu/mpc83xx/spd_sdram.c +++ b/cpu/mpc83xx/spd_sdram.c @@ -574,7 +574,10 @@ long int spd_sdram()  	/* Check DIMM data bus width */  	if (spd.dataw_lsb == 0x20) { -		burstlen = 0x03; /* 32 bit data bus, burst len is 8 */ +		if (spd.mem_type == SPD_MEMTYPE_DDR) +			burstlen = 0x03; /* 32 bit data bus, burst len is 8 */ +		else +			burstlen = 0x02; /* 32 bit data bus, burst len is 4 */  		printf("\n   DDR DIMM: data bus width is 32 bit");  	} else {  		burstlen = 0x02; /* Others act as 64 bit bus, burst len is 4 */ @@ -730,8 +733,12 @@ long int spd_sdram()  		sdram_cfg |= 0x10000000;  	/* The DIMM is 32bit width */ -	if (spd.dataw_lsb == 0x20) -		sdram_cfg |= 0x000C0000; +	if (spd.dataw_lsb == 0x20) { +		if (spd.mem_type == SPD_MEMTYPE_DDR) +			sdram_cfg |= 0x000C0000; +		if (spd.mem_type == SPD_MEMTYPE_DDR2) +			sdram_cfg |= 0x00080000; +	}  	ddrc_ecc_enable = 0; diff --git a/cpu/mpc83xx/traps.c b/cpu/mpc83xx/traps.c index 152fa7356..dfd6c0386 100644 --- a/cpu/mpc83xx/traps.c +++ b/cpu/mpc83xx/traps.c @@ -140,7 +140,7 @@ MachineCheckException(struct pt_regs *regs)  		return;  	} -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#if defined(CONFIG_CMD_KGDB)  	if (debugger_exception_handler && (*debugger_exception_handler)(regs))  		return;  #endif @@ -176,7 +176,7 @@ MachineCheckException(struct pt_regs *regs)  void  AlignmentException(struct pt_regs *regs)  { -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#if defined(CONFIG_CMD_KGDB)  	if (debugger_exception_handler && (*debugger_exception_handler)(regs))  		return;  #endif @@ -188,7 +188,7 @@ AlignmentException(struct pt_regs *regs)  void  ProgramCheckException(struct pt_regs *regs)  { -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#if defined(CONFIG_CMD_KGDB)  	if (debugger_exception_handler && (*debugger_exception_handler)(regs))  		return;  #endif @@ -200,7 +200,7 @@ ProgramCheckException(struct pt_regs *regs)  void  SoftEmuException(struct pt_regs *regs)  { -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#if defined(CONFIG_CMD_KGDB)  	if (debugger_exception_handler && (*debugger_exception_handler)(regs))  		return;  #endif @@ -213,7 +213,7 @@ SoftEmuException(struct pt_regs *regs)  void  UnknownException(struct pt_regs *regs)  { -#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#if defined(CONFIG_CMD_KGDB)  	if (debugger_exception_handler && (*debugger_exception_handler)(regs))  		return;  #endif @@ -222,7 +222,7 @@ UnknownException(struct pt_regs *regs)  	_exception(0, regs);  } -#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) +#if defined(CONFIG_CMD_BEDBUG)  extern void do_bedbug_breakpoint(struct pt_regs *);  #endif @@ -231,7 +231,7 @@ DebugException(struct pt_regs *regs)  {  	printf("Debugger trap at @ %lx\n", regs->nip );  	show_regs(regs); -#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) +#if defined(CONFIG_CMD_BEDBUG)  	do_bedbug_breakpoint( regs );  #endif  } diff --git a/cpu/mpc83xx/u-boot.lds b/cpu/mpc83xx/u-boot.lds new file mode 100644 index 000000000..ca663bc87 --- /dev/null +++ b/cpu/mpc83xx/u-boot.lds @@ -0,0 +1,122 @@ +/* + * (C) Copyright 2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_ARCH(powerpc) +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)		} +  .rela.text     : { *(.rela.text) 	} +  .rel.data      : { *(.rel.data)		} +  .rela.data     : { *(.rela.data) 	} +  .rel.rodata    : { *(.rel.rodata) 	} +  .rela.rodata   : { *(.rela.rodata) 	} +  .rel.got       : { *(.rel.got)		} +  .rela.got      : { *(.rela.got)		} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)		} +  .rela.bss      : { *(.rela.bss)		} +  .rel.plt       : { *(.rel.plt)		} +  .rela.plt      : { *(.rela.plt)		} +  .init          : { *(.init)	} +  .plt : { *(.plt) } +  .text      : +  { +    cpu/mpc83xx/start.o	(.text) +    *(.text) +    *(.got1) +    . = ALIGN(16); +    *(.rodata) +    *(.rodata1) +    *(.rodata.str1.4) +    *(.eh_frame) +  } +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x0FFF) & 0xFFFFF000; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2; +  __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  . = .; +  __u_boot_cmd_start = .; +  .u_boot_cmd : { *(.u_boot_cmd) } +  __u_boot_cmd_end = .; + + +  . = .; +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(4096); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(4096); +  __init_end = .; + +  __bss_start = .; +  .bss       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } +  _end = . ; +  PROVIDE (end = .); +} +ENTRY(_start) |