Support for DDR with 32-data path. Addotional notes on injecting
multiple-bit errors.
diff --git a/board/mpc8349emds/mpc8349emds.c b/board/mpc8349emds/mpc8349emds.c
index a468c5a..73a33f6 100644
--- a/board/mpc8349emds/mpc8349emds.c
+++ b/board/mpc8349emds/mpc8349emds.c
@@ -63,11 +63,12 @@
 	if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im)
 		return -1;
 
+	puts("Initializing\n");
+
 	/* DDR SDRAM - Main SODIMM */
 	im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR;
 #if defined(CONFIG_SPD_EEPROM)
-
-	msize = spd_sdram(0);
+	msize = spd_sdram();
 #else
 	msize = fixed_sdram();
 #endif
@@ -106,45 +107,40 @@
 			return -1;
 		}
 	}
+	im->sysconf.ddrlaw[0].bar = ((CFG_DDR_SDRAM_BASE>>12) & 0xfffff);
 	im->sysconf.ddrlaw[0].ar = LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE);
+
 #if (CFG_DDR_SIZE != 256)
 #warning Currenly any ddr size other than 256 is not supported
 #endif
-
-	im->ddr.csbnds[0].csbnds = 0x00100017;
-	im->ddr.csbnds[1].csbnds = 0x0018001f;
-	im->ddr.csbnds[2].csbnds = 0x00000007;
-	im->ddr.csbnds[3].csbnds = 0x0008000f;
-	im->ddr.cs_config[0] = CFG_DDR_CONFIG;
-	im->ddr.cs_config[1] = CFG_DDR_CONFIG;
+	im->ddr.csbnds[2].csbnds = 0x0000000f;
 	im->ddr.cs_config[2] = CFG_DDR_CONFIG;
-	im->ddr.cs_config[3] = CFG_DDR_CONFIG;
-	im->ddr.timing_cfg_1 =
-		3 << TIMING_CFG1_PRETOACT_SHIFT |
-		7 << TIMING_CFG1_ACTTOPRE_SHIFT |
-		3 << TIMING_CFG1_ACTTORW_SHIFT  |
-		4 << TIMING_CFG1_CASLAT_SHIFT   |
-		3 << TIMING_CFG1_REFREC_SHIFT   |
-		3 << TIMING_CFG1_WRREC_SHIFT    |
-		2 << TIMING_CFG1_ACTTOACT_SHIFT |
-		1 << TIMING_CFG1_WRTORD_SHIFT;
-	im->ddr.timing_cfg_2 = 2 << TIMING_CFG2_WR_DATA_DELAY_SHIFT;
+
+	/* currently we use only one CS, so disable the other banks */ 
+	im->ddr.cs_config[0] = 0;
+	im->ddr.cs_config[1] = 0;
+	im->ddr.cs_config[3] = 0;
+
+	im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1;
+	im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2;
+	
 	im->ddr.sdram_cfg =
 		SDRAM_CFG_SREN
 #if defined(CONFIG_DDR_2T_TIMING)
 		| SDRAM_CFG_2T_EN
 #endif
 		| 2 << SDRAM_CFG_SDRAM_TYPE_SHIFT;
-	im->ddr.sdram_mode =
-		0x2000 << SDRAM_MODE_ESD_SHIFT |
-		0x0162 << SDRAM_MODE_SD_SHIFT;
+#if defined (CONFIG_DDR_32BIT)
+	/* for 32-bit mode burst length is 8 */
+	im->ddr.sdram_cfg |= (SDRAM_CFG_32_BE | SDRAM_CFG_8_BE);
+#endif
+	im->ddr.sdram_mode = CFG_DDR_MODE;
 
-	im->ddr.sdram_interval = 0x045B << SDRAM_INTERVAL_REFINT_SHIFT |
-		0x0100 << SDRAM_INTERVAL_BSTOPRE_SHIFT;
+	im->ddr.sdram_interval = CFG_DDR_INTERVAL; 
 	udelay(200);
 
+	/* enable DDR controller */
 	im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN;
-
 	return msize;
 }
 #endif/*!CFG_SPD_EEPROM*/
diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c
index 06a7da8..b4012a8 100644
--- a/cpu/mpc83xx/spd_sdram.c
+++ b/cpu/mpc83xx/spd_sdram.c
@@ -1,4 +1,7 @@
 /*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * 
  * Copyright 2004 Freescale Semiconductor.
  * (C) Copyright 2003 Motorola Inc.
  * Xianghua Xiao (X.Xiao@motorola.com)
@@ -73,7 +76,32 @@
 	return ((int) addr);
 }
 
-long int spd_sdram(int(read_spd)(uint addr))
+#undef SPD_DEBUG
+#ifdef SPD_DEBUG
+static void spd_debug(spd_eeprom_t *spd)
+{
+	printf ("\nDIMM type:       %-18.18s\n", spd->mpart);
+	printf ("SPD size:        %d\n", spd->info_size);
+	printf ("EEPROM size:     %d\n", 1 << spd->chip_size);
+	printf ("Memory type:     %d\n", spd->mem_type);
+	printf ("Row addr:        %d\n", spd->nrow_addr);
+	printf ("Column addr:     %d\n", spd->ncol_addr);
+	printf ("# of rows:       %d\n", spd->nrows);
+	printf ("Row density:     %d\n", spd->row_dens);
+	printf ("# of banks:      %d\n", spd->nbanks);
+	printf ("Data width:      %d\n",
+			256 * spd->dataw_msb + spd->dataw_lsb);
+	printf ("Chip width:      %d\n", spd->primw);
+	printf ("Refresh rate:    %02X\n", spd->refresh);
+	printf ("CAS latencies:   %02X\n", spd->cas_lat);
+	printf ("Write latencies: %02X\n", spd->write_lat);
+	printf ("tRP:             %d\n", spd->trp);
+	printf ("tRCD:            %d\n", spd->trcd);
+	printf ("\n");
+}
+#endif /* SPD_DEBUG */
+
+long int spd_sdram()
 {
 	volatile immap_t *immap = (immap_t *)CFG_IMMRBAR;
 	volatile ddr8349_t *ddr = &immap->ddr;
@@ -85,10 +113,10 @@
 	unsigned char caslat;
 	unsigned int trfc, trfc_clk, trfc_low;
 
-#warning Current spd_sdram does not fit its usage... adjust implementation or API...
-
 	CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd));
-	
+#ifdef SPD_DEBUG
+	spd_debug(&spd);
+#endif
 	if (spd.nrows > 2) {
 		puts("DDR:Only two chip selects are supported on ADS.\n");
 		return 0;
@@ -223,25 +251,31 @@
 	 * Only DDR I is supported
 	 * DDR I and II have different mode-register-set definition
 	 */
-
-	/* burst length is always 4 */
 	switch(caslat) {
 	case 2:
-		ddr->sdram_mode = 0x52; /* 1.5 */
+		tmp = 0x50; /* 1.5 */
 		break;
 	case 3:
-		ddr->sdram_mode = 0x22; /* 2.0 */
+		tmp = 0x20; /* 2.0 */
 		break;
 	case 4:
-		ddr->sdram_mode = 0x62; /* 2.5 */
+		tmp = 0x60; /* 2.5 */
 		break;
 	case 5:
-		ddr->sdram_mode = 0x32; /* 3.0 */
+		tmp = 0x30; /* 3.0 */
 		break;
 	default:
 		puts("DDR:only CAS Latency 1.5, 2.0, 2.5, 3.0 is supported.\n");
 		return 0;
 	}
+#if defined (CONFIG_DDR_32BIT)
+	/* set burst length to 8 for 32-bit data path */
+	tmp |= 0x03;
+#else
+	/* set burst length to 4 - default for 64-bit data path */
+	tmp |= 0x02;
+#endif
+	ddr->sdram_mode = tmp;
 	debug("DDR:sdram_mode=0x%08x\n", ddr->sdram_mode);
 
 	switch(spd.refresh) {
@@ -321,6 +355,10 @@
 	 */
 	tmp = 0xc2000000;
 
+#if defined (CONFIG_DDR_32BIT)
+	/* in 32-Bit mode burst len is 8 beats */
+	tmp |= (SDRAM_CFG_32_BE | SDRAM_CFG_8_BE);
+#endif
 	/*
 	 * sdram_cfg[3] = RD_EN - registered DIMM enable
 	 *   A value of 0x26 indicates micron registered DIMMS (micron.com)
@@ -350,8 +388,7 @@
 	udelay(500);
 
 	debug("DDR:sdram_cfg=0x%08x\n", ddr->sdram_cfg);
-
-	return memsize;/*in MBytes*/
+	return memsize; /*in MBytes*/
 }
 #endif /* CONFIG_SPD_EEPROM */
 
diff --git a/doc/README.mpc8349emds.ddrecc b/doc/README.mpc8349emds.ddrecc
index d8edada..401c0b6 100644
--- a/doc/README.mpc8349emds.ddrecc
+++ b/doc/README.mpc8349emds.ddrecc
@@ -1,3 +1,24 @@
+Overview
+========
+
+The overall usage pattern for ECC diagnostic commands is the following:
+
+  * (injecting errors is initially disabled)
+
+  * define inject mask (which tells the DDR controller what type of errors
+    we'll be injecting: single/multiple bit etc.)
+
+  * enable injecting errors - from now on the controller injects errors as
+    indicated in the inject mask
+
+IMPORTANT NOTICE: enabling injecting multiple-bit errors is potentially
+dangerous as such errors are NOT corrected by the controller. Therefore caution
+should be taken when enabling the injection of multiple-bit errors: it is only
+safe when used on a carefully selected memory area and used under control of
+the 'ecc test' command (see example 'Injecting Multiple-Bit Errors' below). In
+particular, when you simply set the multiple-bit errors in inject mask and
+enable injection, U-Boot is very likely to hang quickly as the errors will be
+injected when it accesses its code, data etc.
 
 
 Use cases for DDR 'ecc' command:
diff --git a/include/configs/MPC8349EMDS.h b/include/configs/MPC8349EMDS.h
index c2bd0f5..39e3d95 100644
--- a/include/configs/MPC8349EMDS.h
+++ b/include/configs/MPC8349EMDS.h
@@ -73,27 +73,46 @@
 #define CONFIG_DDR_ECC_CMD		/* use DDR ECC user commands */
 #define CONFIG_SPD_EEPROM		/* use SPD EEPROM for DDR setup*/
 
+/*
+ * 32-bit data path mode.
+ * 
+ * Please note that using this mode for devices with the real density of 64-bit
+ * effectively reduces the amount of available memory due to the effect of
+ * wrapping around while translating address to row/columns, for example in the
+ * 256MB module the upper 128MB get aliased with contents of the lower
+ * 128MB); normally this define should be used for devices with real 32-bit
+ * data path. 
+ */
+#undef CONFIG_DDR_32BIT
+
 #define CFG_DDR_BASE		0x00000000	/* DDR is system memory*/
 #define CFG_SDRAM_BASE		CFG_DDR_BASE
 #define CFG_DDR_SDRAM_BASE	CFG_DDR_BASE
 #undef  CONFIG_DDR_2T_TIMING
 
 #if defined(CONFIG_SPD_EEPROM)
-	/*
-	 * Determine DDR configuration from I2C interface.
-	 */
-	#define SPD_EEPROM_ADDRESS	0x51		/* DDR DIMM */
+/*
+ * Determine DDR configuration from I2C interface.
+ */
+#define SPD_EEPROM_ADDRESS	0x51		/* DDR DIMM */
+#else
+/*
+ * Manually set up DDR parameters
+ */
+#define CFG_DDR_SIZE		256		/* MB */
+#define CFG_DDR_CONFIG		(CSCONFIG_EN | CSCONFIG_ROW_BIT_13 | CSCONFIG_COL_BIT_10)
+#define CFG_DDR_TIMING_1	0x36332321
+#define CFG_DDR_TIMING_2	0x00000800	/* P9-45,may need tuning */
+#define CFG_DDR_CONTROL		0xc2000000	/* unbuffered,no DYN_PWR */
+#define CFG_DDR_INTERVAL	0x04060100	/* autocharge,no open page */
+
+#if defined(CONFIG_DDR_32BIT)
+/* set burst length to 8 for 32-bit data path */
+#define CFG_DDR_MODE		0x00000023	/* DLL,normal,seq,4/2.5, 8 burst len */
 #else
-	/*
-	 * Manually set up DDR parameters
-	 */
-	#define CFG_DDR_SIZE		128		/* Mb */
-	#define CFG_DDR_CONFIG		(CSCONFIG_EN | CSCONFIG_ROW_BIT_13 | CSCONFIG_COL_BIT_9)
-	#define CFG_DDR_TIMING_1	0x37344321
-	#define CFG_DDR_TIMING_2	0x00000800	/* P9-45,may need tuning */
-	#define CFG_DDR_CONTROL		0xc2000000	/* unbuffered,no DYN_PWR */
-	#define CFG_DDR_MODE		0x00000062	/* DLL,normal,seq,4/2.5 */
-	#define CFG_DDR_INTERVAL	0x05200100	/* autocharge,no open page */
+/* the default burst length is 4 - for 64-bit data path */
+#define CFG_DDR_MODE		0x00000022	/* DLL,normal,seq,4/2.5, 4 burst len */
+#endif
 #endif
 
 /*
diff --git a/include/spd_sdram.h b/include/spd_sdram.h
index 4e754ec..a2be96c 100644
--- a/include/spd_sdram.h
+++ b/include/spd_sdram.h
@@ -1,6 +1,6 @@
 #ifndef _SPD_SDRAM_H_
 #define _SPD_SDRAM_H_
 
-long int spd_sdram(int(read_spd)(uint addr));
+long int spd_sdram(void);
 
 #endif