All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 01/10] Display RDIMM if detected
@ 2010-12-09  2:55 York Sun
  2010-12-09  2:55 ` [U-Boot] [PATCH 02/10] make the hwconfig buffer deeper York Sun
                   ` (9 more replies)
  0 siblings, 10 replies; 28+ messages in thread
From: York Sun @ 2010-12-09  2:55 UTC (permalink / raw)
  To: u-boot

Print a message when a RDIMM is detected.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 .../cpu/mpc8xxx/ddr/lc_common_dimm_params.c        |   19 +++++++------------
 1 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
index 029e566..af0250d 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
@@ -98,7 +98,7 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	unsigned int tDQSQ_max_ps = 0;
 	unsigned int tQHS_ps = 0;
 
-	unsigned int temp1, temp2, temp3;
+	unsigned int temp1, temp2;
 	unsigned int additive_latency = 0;
 #if !defined(CONFIG_FSL_DDR3)
 	const unsigned int mclk_ps = get_memory_clk_period_ps();
@@ -215,21 +215,16 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	}
 
 	outpdimm->all_DIMMs_registered = 0;
+	outpdimm->all_DIMMs_unbuffered = 0;
 	if (temp1 && !temp2) {
 		outpdimm->all_DIMMs_registered = 1;
-	}
-
-	outpdimm->all_DIMMs_unbuffered = 0;
-	if (!temp1 && temp2) {
+		printf("Detected RDIMM(s)\n");
+	} else if (!temp1 && temp2) {
 		outpdimm->all_DIMMs_unbuffered = 1;
-	}
-
-	/* CHECKME: */
-	if (!outpdimm->all_DIMMs_registered
-	    && !outpdimm->all_DIMMs_unbuffered) {
+		printf("Detected UDIMM(s)\n");
+	} else
 		printf("ERROR:  Mix of registered buffered and unbuffered "
 				"DIMMs detected!\n");
-	}
 
 	temp1 = 0;
 	if (outpdimm->all_DIMMs_registered)
@@ -237,7 +232,7 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 			outpdimm->rcw[j] = dimm_params[0].rcw[j];
 			for (i = 1; i < number_of_dimms; i++)
 				if (dimm_params[i].rcw[j] != dimm_params[0].rcw[j]) {
-					temp3 = 1;
+					temp1 = 1;
 					break;
 				}
 		}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 02/10] make the hwconfig buffer deeper
  2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
@ 2010-12-09  2:55 ` York Sun
  2010-12-09 10:12   ` Wolfgang Denk
  2010-12-09  2:55 ` [U-Boot] [PATCH 03/10] Enable ECC on/off control in hwconfig York Sun
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: York Sun @ 2010-12-09  2:55 UTC (permalink / raw)
  To: u-boot

To temporarily fix buffer issue when running at flash, use bigger buffer
to push down the stack deeper.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 common/hwconfig.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/common/hwconfig.c b/common/hwconfig.c
index 3c9759f..1b33d95 100644
--- a/common/hwconfig.c
+++ b/common/hwconfig.c
@@ -71,7 +71,7 @@ next:
 const char *cpu_hwconfig __attribute__((weak));
 const char *board_hwconfig __attribute__((weak));
 
-#define HWCONFIG_PRE_RELOC_BUF_SIZE	128
+#define HWCONFIG_PRE_RELOC_BUF_SIZE	256
 
 static const char *__hwconfig(const char *opt, size_t *arglen)
 {
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 03/10] Enable ECC on/off control in hwconfig
  2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
  2010-12-09  2:55 ` [U-Boot] [PATCH 02/10] make the hwconfig buffer deeper York Sun
@ 2010-12-09  2:55 ` York Sun
  2010-12-09  2:55 ` [U-Boot] [PATCH 04/10] Enable ECC for corenet_ds York Sun
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 28+ messages in thread
From: York Sun @ 2010-12-09  2:55 UTC (permalink / raw)
  To: u-boot

Add fsl_ddr:ecc=on in hwconfig. If ECC is enabled in board configuration file,
ECC can be turned on/off by this switch. If this switch is omitted, it is ON by
default.

Syntax is
hwconfig=fsl_ddr:ecc=on

Signed-off-by: York Sun <yorksun@freescale.com>
---
 arch/powerpc/cpu/mpc8xxx/ddr/options.c |    9 ++++++---
 doc/README.fsl-ddr                     |    7 +++++++
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c
index ca5f63e..f876e20 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/options.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/options.c
@@ -82,10 +82,13 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 	/* Operational Mode Paramters */
 
 	/* Pick ECC modes */
-#ifdef CONFIG_DDR_ECC
-	popts->ECC_mode = 1;		  /* 0 = disabled, 1 = enabled */
-#else
 	popts->ECC_mode = 0;		  /* 0 = disabled, 1 = enabled */
+#ifdef CONFIG_DDR_ECC
+	if (hwconfig_sub("fsl_ddr", "ecc")) {
+		if (hwconfig_subarg_cmp("fsl_ddr", "ecc", "on"))
+			popts->ECC_mode = 1;
+	} else
+		popts->ECC_mode = 1;
 #endif
 	popts->ECC_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */
 
diff --git a/doc/README.fsl-ddr b/doc/README.fsl-ddr
index 1657ef6..9e3c539 100644
--- a/doc/README.fsl-ddr
+++ b/doc/README.fsl-ddr
@@ -78,6 +78,13 @@ If the DDR controller supports address hashing, it can be enabled by hwconfig.
 Syntax is:
 hwconfig=fsl_ddr:addr_hash=true
 
+Memory controller ECC on/off
+============================
+If ECC is enabled in board configuratoin file, i.e. #define CONFIG_DDR_ECC,
+ECC can be turned on/off by hwconfig.
+
+Syntax is
+hwconfig=fsl_ddr:ecc=off
 
 Memory testing options for mpc85xx
 ==================================
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 04/10] Enable ECC for corenet_ds
  2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
  2010-12-09  2:55 ` [U-Boot] [PATCH 02/10] make the hwconfig buffer deeper York Sun
  2010-12-09  2:55 ` [U-Boot] [PATCH 03/10] Enable ECC on/off control in hwconfig York Sun
@ 2010-12-09  2:55 ` York Sun
  2010-12-09  2:55 ` [U-Boot] [PATCH 05/10] Adding more registers and options York Sun
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 28+ messages in thread
From: York Sun @ 2010-12-09  2:55 UTC (permalink / raw)
  To: u-boot

ECC can be turned on/off by hwconfig without recompiling. So enable it
by default.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 include/configs/corenet_ds.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/configs/corenet_ds.h b/include/configs/corenet_ds.h
index 454a30a..49f0a26 100644
--- a/include/configs/corenet_ds.h
+++ b/include/configs/corenet_ds.h
@@ -76,7 +76,7 @@
 #define CONFIG_BACKSIDE_L2_CACHE
 #define CONFIG_SYS_INIT_L2CSR0		L2CSR0_L2E
 #define CONFIG_BTB			/* toggle branch predition */
-/*#define	CONFIG_DDR_ECC*/
+#define	CONFIG_DDR_ECC
 #ifdef CONFIG_DDR_ECC
 #define CONFIG_ECC_INIT_VIA_DDRCONTROLLER
 #define CONFIG_MEM_INIT_VALUE		0xdeadbeef
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 05/10] Adding more registers and options
  2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
                   ` (2 preceding siblings ...)
  2010-12-09  2:55 ` [U-Boot] [PATCH 04/10] Enable ECC for corenet_ds York Sun
@ 2010-12-09  2:55 ` York Sun
  2010-12-14  5:10   ` Kumar Gala
  2010-12-09  2:55 ` [U-Boot] [PATCH 06/10] Enable unique mode registers and dynamic ODT for DDR3 York Sun
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: York Sun @ 2010-12-09  2:55 UTC (permalink / raw)
  To: u-boot

Add writing to cdr1, cdr2, err_disable, err_int_en and debug registers
Add options to override rcw, address parity to RDIMMs.
Use array for debug registeres.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 arch/powerpc/cpu/mpc85xx/ddr-gen3.c      |   10 ++++++++--
 arch/powerpc/include/asm/fsl_ddr_sdram.h |   12 ++++++++++++
 arch/powerpc/include/asm/immap_85xx.h    |   19 +------------------
 3 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
index 5805b3f..14a905d 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
@@ -80,6 +80,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	out_be32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr);
 	out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1);
 	out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2);
+	out_be32(&ddr->ddr_cdr1, regs->ddr_cdr1);
+	out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+	out_be32(&ddr->err_disable, regs->err_disable);
+	out_be32(&ddr->err_int_en, regs->err_int_en);
+	for (i = 0; i < 18; i++)
+		out_be32(&ddr->debug[i], regs->debug[i]);
+
 #ifdef CONFIG_SYS_P4080_ERRATUM_DDR7
 	/*
 	 * Do not use automatic driver calibration, Instead of
@@ -104,8 +111,7 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	if ((((in_be32(&ddr->sdram_cfg) >> 24) & 0x7) == SDRAM_TYPE_DDR2)
 	    && in_be32(&ddr->sdram_cfg) & 0x80000) {
 		/* set DEBUG_1[31] */
-		u32 temp = in_be32(&ddr->debug_1);
-		out_be32(&ddr->debug_1, temp | 1);
+		setbits_be32(&ddr->debug[0], 1);
 	}
 #endif
 
diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h
index 17d4b31..6ec95b6 100644
--- a/arch/powerpc/include/asm/fsl_ddr_sdram.h
+++ b/arch/powerpc/include/asm/fsl_ddr_sdram.h
@@ -120,6 +120,11 @@ typedef struct fsl_ddr_cfg_regs_s {
 	unsigned int ddr_sdram_rcw_1;
 	unsigned int ddr_sdram_rcw_2;
 	unsigned int ddr_eor;
+	unsigned int ddr_cdr1;
+	unsigned int ddr_cdr2;
+	unsigned int err_disable;
+	unsigned int err_int_en;
+	unsigned int debug[18];
 } fsl_ddr_cfg_regs_t;
 
 typedef struct memctl_options_partial_s {
@@ -175,6 +180,7 @@ typedef struct memctl_options_s {
 	/* mirrior DIMMs for DDR3 */
 	unsigned int mirrored_dimm;
 	unsigned int quad_rank_present;
+	unsigned int ap_en;	/* address parity enable for RDIMM */
 
 	/* Global Timing Parameters */
 	unsigned int cas_latency_override;
@@ -210,6 +216,12 @@ typedef struct memctl_options_s {
 	unsigned int zq_en;
 	/* Write leveling */
 	unsigned int wrlvl_en;
+	/* RCW override for RDIMM */
+	unsigned int rcw_override;
+	unsigned int rcw_1;
+	unsigned int rcw_2;
+	/* control register 1 */
+	unsigned int ddr_cdr1;
 } memctl_options_t;
 
 extern phys_size_t fsl_ddr_sdram(void);
diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h
index ee7338a..474082f 100644
--- a/arch/powerpc/include/asm/immap_85xx.h
+++ b/arch/powerpc/include/asm/immap_85xx.h
@@ -222,24 +222,7 @@ typedef struct ccsr_ddr {
 	u32	capture_ext_address;	/* Error Extended Addr Capture */
 	u32	err_sbe;		/* Single-Bit ECC Error Management */
 	u8	res11[164];
-	u32	debug_1;
-	u32	debug_2;
-	u32	debug_3;
-	u32	debug_4;
-	u32	debug_5;
-	u32	debug_6;
-	u32	debug_7;
-	u32	debug_8;
-	u32	debug_9;
-	u32	debug_10;
-	u32	debug_11;
-	u32	debug_12;
-	u32	debug_13;
-	u32	debug_14;
-	u32	debug_15;
-	u32	debug_16;
-	u32	debug_17;
-	u32	debug_18;
+	u32	debug[18];		/* debug_1 to debug_18 */
 	u8	res12[184];
 } ccsr_ddr_t;
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 06/10] Enable unique mode registers and dynamic ODT for DDR3
  2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
                   ` (3 preceding siblings ...)
  2010-12-09  2:55 ` [U-Boot] [PATCH 05/10] Adding more registers and options York Sun
@ 2010-12-09  2:55 ` York Sun
  2010-12-14  5:13   ` Kumar Gala
  2010-12-14  7:54   ` Wolfgang Denk
  2010-12-09  2:55 ` [U-Boot] [PATCH 07/10] Adding more SPD registers York Sun
                   ` (4 subsequent siblings)
  9 siblings, 2 replies; 28+ messages in thread
From: York Sun @ 2010-12-09  2:55 UTC (permalink / raw)
  To: u-boot

Added fsl_ddr_get_version() function to poll DDRC IP version (major, minor,
errata) to determine if unique mode registers are available. This function may
be needed for future other platforms if such a feature exists. If true, always
use unique mode registers. Dynamic ODT is enabled if needed. The table is
documented in doc/README.fsl-ddr.

Enable address parity and RCW by default for RDIMMs.

Change default output driver impedance from 34 ohm to 40ohm. Make it 34ohm for
quad-rank RDIMMs.

Use a formula to calculate rodt_on for timing_cfg_5.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 arch/powerpc/cpu/mpc85xx/ddr-gen3.c      |   18 ++
 arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c |  305 +++++++++++++++++++++++++----
 arch/powerpc/cpu/mpc8xxx/ddr/options.c   |  308 +++++++++++++++++++++++++++++-
 arch/powerpc/include/asm/fsl_ddr_sdram.h |   18 ++
 board/freescale/corenet_ds/ddr.c         |  125 ++++++-------
 doc/README.fsl-ddr                       |   67 +++++++-
 6 files changed, 723 insertions(+), 118 deletions(-)

diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
index 14a905d..568f9f4 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
@@ -66,6 +66,12 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
 	out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
 	out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
+	out_be32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3);
+	out_be32(&ddr->sdram_mode_4, regs->ddr_sdram_mode_4);
+	out_be32(&ddr->sdram_mode_5, regs->ddr_sdram_mode_5);
+	out_be32(&ddr->sdram_mode_6, regs->ddr_sdram_mode_6);
+	out_be32(&ddr->sdram_mode_7, regs->ddr_sdram_mode_7);
+	out_be32(&ddr->sdram_mode_8, regs->ddr_sdram_mode_8);
 	out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl);
 	out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
 	out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
@@ -133,3 +139,15 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 		udelay(10000);		/* throttle polling rate */
 	}
 }
+
+u32 fsl_ddr_get_version(void)
+{
+	ccsr_ddr_t *ddr;
+	u32 ver_major_minor_errata;
+
+	ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+	ver_major_minor_errata = (in_be32(&ddr->ip_rev1) & 0xFFFF) << 8;
+	ver_major_minor_errata |= (in_be32(&ddr->ip_rev2) & 0xFF00) >> 8;
+
+	return ver_major_minor_errata;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
index 3fec100..2132986 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
@@ -18,7 +18,13 @@
 
 #include "ddr.h"
 
-extern unsigned int picos_to_mclk(unsigned int picos);
+u32 __attribute__((weak)) fsl_ddr_get_version(void)
+{
+	return 0;
+}
+
+unsigned int picos_to_mclk(unsigned int picos);
+
 /*
  * Determine Rtt value.
  *
@@ -187,7 +193,8 @@ static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)
  * Avoid writing for DDR I.  The new PQ38 DDR controller
  * dreams up non-zero default values to be backwards compatible.
  */
-static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr)
+static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts)
 {
 	unsigned char trwt_mclk = 0;   /* Read-to-write turnaround */
 	unsigned char twrt_mclk = 0;   /* Write-to-read turnaround */
@@ -204,7 +211,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr)
 	/* Mode register set cycle time (tMRD). */
 	unsigned char tmrd_mclk;
 
-#if defined(CONFIG_FSL_DDR3)
+#ifdef CONFIG_FSL_DDR3
 	/*
 	 * (tXARD and tXARDS). Empirical?
 	 * The DDR3 spec has not tXARD,
@@ -214,13 +221,21 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr)
 	 * tAXPD=1, need design to confirm.
 	 */
 	int tXP = max((get_memory_clk_period_ps() * 3), 7500); /* unit=ps */
-	act_pd_exit_mclk = picos_to_mclk(tXP);
-	/* Mode register MR0[A12] is '1' - fast exit */
-	pre_pd_exit_mclk = act_pd_exit_mclk;
-	taxpd_mclk = 1;
 	tmrd_mclk = 4;
 	/* set the turnaround time */
 	trwt_mclk = 1;
+
+	if (popts->dynamic_power == 0) {	/* powerdown is not used */
+		act_pd_exit_mclk = 1;
+		pre_pd_exit_mclk = 1;
+		taxpd_mclk = 1;
+	} else {
+		/* act_pd_exit_mclk = tXARD, see above */
+		act_pd_exit_mclk = picos_to_mclk(tXP);
+		/* Mode register MR0[A12] is '1' - fast exit */
+		pre_pd_exit_mclk = act_pd_exit_mclk;
+		taxpd_mclk = 1;
+	}
 #else /* CONFIG_FSL_DDR2 */
 	/*
 	 * (tXARD and tXARDS). Empirical?
@@ -450,28 +465,34 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 
 /* DDR SDRAM Register Control Word */
 static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
 			       const common_timing_params_t *common_dimm)
 {
 	if (common_dimm->all_DIMMs_registered
 		&& !common_dimm->all_DIMMs_unbuffered) {
-		ddr->ddr_sdram_rcw_1 =
-			common_dimm->rcw[0] << 28 | \
-			common_dimm->rcw[1] << 24 | \
-			common_dimm->rcw[2] << 20 | \
-			common_dimm->rcw[3] << 16 | \
-			common_dimm->rcw[4] << 12 | \
-			common_dimm->rcw[5] << 8 | \
-			common_dimm->rcw[6] << 4 | \
-			common_dimm->rcw[7];
-		ddr->ddr_sdram_rcw_2 =
-			common_dimm->rcw[8] << 28 | \
-			common_dimm->rcw[9] << 24 | \
-			common_dimm->rcw[10] << 20 | \
-			common_dimm->rcw[11] << 16 | \
-			common_dimm->rcw[12] << 12 | \
-			common_dimm->rcw[13] << 8 | \
-			common_dimm->rcw[14] << 4 | \
-			common_dimm->rcw[15];
+		if (popts->rcw_override) {
+			ddr->ddr_sdram_rcw_1 = popts->rcw_1;
+			ddr->ddr_sdram_rcw_2 = popts->rcw_2;
+		} else {
+			ddr->ddr_sdram_rcw_1 =
+				common_dimm->rcw[0] << 28 | \
+				common_dimm->rcw[1] << 24 | \
+				common_dimm->rcw[2] << 20 | \
+				common_dimm->rcw[3] << 16 | \
+				common_dimm->rcw[4] << 12 | \
+				common_dimm->rcw[5] << 8 | \
+				common_dimm->rcw[6] << 4 | \
+				common_dimm->rcw[7];
+			ddr->ddr_sdram_rcw_2 =
+				common_dimm->rcw[8] << 28 | \
+				common_dimm->rcw[9] << 24 | \
+				common_dimm->rcw[10] << 20 | \
+				common_dimm->rcw[11] << 16 | \
+				common_dimm->rcw[12] << 12 | \
+				common_dimm->rcw[13] << 8 | \
+				common_dimm->rcw[14] << 4 | \
+				common_dimm->rcw[15];
+		}
 		debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n", ddr->ddr_sdram_rcw_1);
 		debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n", ddr->ddr_sdram_rcw_2);
 	}
@@ -509,8 +530,14 @@ static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
 		ecc_en = 0;
 	}
 
-	rd_en = (common_dimm->all_DIMMs_registered
-		 && !common_dimm->all_DIMMs_unbuffered);
+	if (common_dimm->all_DIMMs_registered
+		&& !common_dimm->all_DIMMs_unbuffered) {
+		rd_en = 1;
+		twoT_en = 0;
+	} else {
+		rd_en = 0;
+		twoT_en = popts->twoT_en;
+	}
 
 	sdram_type = CONFIG_FSL_SDRAM_TYPE;
 
@@ -530,7 +557,6 @@ static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
 	}
 
 	threeT_en = popts->threeT_en;
-	twoT_en = popts->twoT_en;
 	ba_intlv_ctl = popts->ba_intlv_ctl;
 	hse = popts->half_strength_driver_enable;
 
@@ -558,7 +584,8 @@ static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
 
 /* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */
 static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
-			       const memctl_options_t *popts)
+			       const memctl_options_t *popts,
+			       unsigned int unq_mrs_en)
 {
 	unsigned int frc_sr = 0;	/* Force self refresh */
 	unsigned int sr_ie = 0;		/* Self-refresh interrupt enable */
@@ -598,11 +625,17 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 	obc_cfg = 0;
 #endif
 
-	ap_en = 0;	/* Make this configurable? */
+	if (popts->registered_dimm_en) {
+		rcw_en = 1;
+		ap_en = popts->ap_en;
+	} else {
+		rcw_en = 0;
+		ap_en = 0;
+	}
 
 #if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
 	/* Use the DDR controller to auto initialize memory. */
-	d_init = 1;
+	d_init = popts->ECC_init_using_memctl;
 	ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE;
 	debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init);
 #else
@@ -613,7 +646,6 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 #if defined(CONFIG_FSL_DDR3)
 	md_en = popts->mirrored_dimm;
 #endif
-	rcw_en = popts->registered_dimm_en;
 	qd_en = popts->quad_rank_present ? 1 : 0;
 	ddr->ddr_sdram_cfg_2 = (0
 		| ((frc_sr & 0x1) << 31)
@@ -623,6 +655,7 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 		| ((odt_cfg & 0x3) << 21)
 		| ((num_pr & 0xf) << 12)
 		| (qd_en << 9)
+		| (unq_mrs_en << 8)
 		| ((obc_cfg & 0x1) << 6)
 		| ((ap_en & 0x1) << 5)
 		| ((d_init & 0x1) << 4)
@@ -648,7 +681,8 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
 
 	if (popts->rtt_override)
 		rtt_wr = popts->rtt_wr_override_value;
-
+	else
+		rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
 	esdmode2 = (0
 		| ((rtt_wr & 0x3) << 9)
 		| ((srt & 0x1) << 7)
@@ -663,6 +697,165 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
 }
 
+static void set_ddr_sdram_mode_3(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts)
+{
+	u16 esdmode;		/* Extended SDRAM mode */
+	u16 sdmode;		/* SDRAM mode */
+	u32 rtt;
+
+	sdmode = ddr->ddr_sdram_mode & 0xFFFF;
+	esdmode = (ddr->ddr_sdram_mode >> 16) & 0xFFFF;
+
+	if (popts->rtt_override)
+		rtt = popts->rtt_override_value;
+	else
+		rtt = popts->cs_local_opts[1].odt_rtt_norm;
+
+	esdmode &= 0xFDBB;	/* clear bit 9,6,2 */
+	esdmode |= (0
+		| ((rtt & 0x4) << 7)   /* rtt field is split */
+		| ((rtt & 0x2) << 5)   /* rtt field is split */
+		| ((rtt & 0x1) << 2)  /* rtt field is split */
+		);
+
+	ddr->ddr_sdram_mode_3 = (0
+			       | ((esdmode & 0xFFFF) << 16)
+			       | ((sdmode & 0xFFFF) << 0)
+			       );
+	debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n", ddr->ddr_sdram_mode_3);
+}
+
+static void set_ddr_sdram_mode_4(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts)
+{
+	u16 esdmode2 = 0;	/* Extended SDRAM mode 2 */
+	u16 esdmode3 = 0;	/* Extended SDRAM mode 3 */
+	u32 rtt_wr = 0;		/* Dynamic ODT off */
+
+	esdmode2 = (ddr->ddr_sdram_mode_2 >> 16) & 0xFFFF;
+	esdmode3 = ddr->ddr_sdram_mode_2 & 0xFFFF;
+
+	if (popts->rtt_override)
+		rtt_wr = popts->rtt_wr_override_value;
+	else
+		rtt_wr = popts->cs_local_opts[1].odt_rtt_wr;
+
+	esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
+	esdmode2 |= (rtt_wr & 0x3) << 9;
+	ddr->ddr_sdram_mode_4 = (0
+				 | ((esdmode2 & 0xFFFF) << 16)
+				 | ((esdmode3 & 0xFFFF) << 0)
+				 );
+	debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n", ddr->ddr_sdram_mode_4);
+}
+
+static void set_ddr_sdram_mode_5(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts)
+{
+	u16 esdmode;		/* Extended SDRAM mode */
+	u16 sdmode;		/* SDRAM mode */
+	u32 rtt;
+
+	sdmode = ddr->ddr_sdram_mode & 0xFFFF;
+	esdmode = (ddr->ddr_sdram_mode >> 16) & 0xFFFF;
+
+	if (popts->rtt_override)
+		rtt = popts->rtt_override_value;
+	else
+		rtt = popts->cs_local_opts[2].odt_rtt_norm;
+
+	esdmode &= 0xFDBB;	/* clear bit 9,6,2 */
+	esdmode |= (0
+		| ((rtt & 0x4) << 7)   /* rtt field is split */
+		| ((rtt & 0x2) << 5)   /* rtt field is split */
+		| ((rtt & 0x1) << 2)  /* rtt field is split */
+		);
+
+	ddr->ddr_sdram_mode_5 = (0
+			       | ((esdmode & 0xFFFF) << 16)
+			       | ((sdmode & 0xFFFF) << 0)
+			       );
+	debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n", ddr->ddr_sdram_mode_5);
+}
+
+static void set_ddr_sdram_mode_6(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts)
+{
+	u16 esdmode2 = 0;	/* Extended SDRAM mode 2 */
+	u16 esdmode3 = 0;	/* Extended SDRAM mode 3 */
+	u32 rtt_wr = 0;		/* Dynamic ODT off */
+
+	esdmode2 = (ddr->ddr_sdram_mode_2 >> 16) & 0xFFFF;
+	esdmode3 = ddr->ddr_sdram_mode_2 & 0xFFFF;
+
+	if (popts->rtt_override)
+		rtt_wr = popts->rtt_wr_override_value;
+	else
+		rtt_wr = popts->cs_local_opts[2].odt_rtt_wr;
+
+	esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
+	esdmode2 |= (rtt_wr & 0x3) << 9;
+	ddr->ddr_sdram_mode_6 = (0
+				 | ((esdmode2 & 0xFFFF) << 16)
+				 | ((esdmode3 & 0xFFFF) << 0)
+				 );
+	debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n", ddr->ddr_sdram_mode_6);
+}
+
+static void set_ddr_sdram_mode_7(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts)
+{
+	u16 esdmode;		/* Extended SDRAM mode */
+	u16 sdmode;		/* SDRAM mode */
+	u32 rtt;
+
+	sdmode = ddr->ddr_sdram_mode & 0xFFFF;
+	esdmode = (ddr->ddr_sdram_mode >> 16) & 0xFFFF;
+
+	if (popts->rtt_override)
+		rtt = popts->rtt_override_value;
+	else
+		rtt = popts->cs_local_opts[3].odt_rtt_norm;
+
+	esdmode &= 0xFDBB;	/* clear bit 9,6,2 */
+	esdmode |= (0
+		| ((rtt & 0x4) << 7)   /* rtt field is split */
+		| ((rtt & 0x2) << 5)   /* rtt field is split */
+		| ((rtt & 0x1) << 2)  /* rtt field is split */
+		);
+
+	ddr->ddr_sdram_mode_7 = (0
+			       | ((esdmode & 0xFFFF) << 16)
+			       | ((sdmode & 0xFFFF) << 0)
+			       );
+	debug("FSLDDR: ddr_sdram_mode_7 = 0x%08x\n", ddr->ddr_sdram_mode_7);
+}
+
+static void set_ddr_sdram_mode_8(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts)
+{
+	u16 esdmode2 = 0;	/* Extended SDRAM mode 2 */
+	u16 esdmode3 = 0;	/* Extended SDRAM mode 3 */
+	u32 rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
+
+	esdmode2 = (ddr->ddr_sdram_mode_2 >> 16) & 0xFFFF;
+	esdmode3 = ddr->ddr_sdram_mode_2 & 0xFFFF;
+
+	if (popts->rtt_override)
+		rtt_wr = popts->rtt_wr_override_value;
+	else
+		rtt_wr = popts->cs_local_opts[3].odt_rtt_wr;
+
+	esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
+	esdmode2 |= (rtt_wr & 0x3) << 9;
+	ddr->ddr_sdram_mode_8 = (0
+				 | ((esdmode2 & 0xFFFF) << 16)
+				 | ((esdmode3 & 0xFFFF) << 0)
+				 );
+	debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n", ddr->ddr_sdram_mode_8);
+}
+
 /* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */
 static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr,
 			       const memctl_options_t *popts,
@@ -700,7 +893,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 	unsigned int rtt;
 	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
 	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
-	unsigned int dic = 1;		/* Output driver impedance, 34ohm */
+	unsigned int dic = 0;		/* Output driver impedance, 40ohm */
 	unsigned int dll_en = 0;	/* DLL Enable  0=Enable (Normal),
 						       1=Disable (Test/Debug) */
 
@@ -718,15 +911,19 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 
 	const unsigned int mclk_ps = get_memory_clk_period_ps();
 
-	rtt = fsl_ddr_get_rtt();
 	if (popts->rtt_override)
 		rtt = popts->rtt_override_value;
+	else
+		rtt = popts->cs_local_opts[0].odt_rtt_norm;
 
 	if (additive_latency == (cas_latency - 1))
 		al = 1;
 	if (additive_latency == (cas_latency - 2))
 		al = 2;
 
+	if (popts->quad_rank_present)
+		dic = 1;	/* output driver impedance 240/7 ohm */
+
 	/*
 	 * The esdmode value will also be used for writing
 	 * MR1 during write leveling for DDR3, although the
@@ -1024,7 +1221,7 @@ static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr,
 }
 
 /* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */
-static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr)
+static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency)
 {
 	unsigned int rodt_on = 0;	/* Read to ODT on */
 	unsigned int rodt_off = 0;	/* Read to ODT off */
@@ -1032,7 +1229,8 @@ static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr)
 	unsigned int wodt_off = 0;	/* Write to ODT off */
 
 #if defined(CONFIG_FSL_DDR3)
-	rodt_on = 2;	/*  2 clocks */
+	/* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
+	rodt_on = cas_latency - ((ddr->timing_cfg_2 & 0x00780000) >> 19) + 1;
 	rodt_off = 4;	/*  4 clocks */
 	wodt_on = 1;	/*  1 clocks */
 	wodt_off = 4;	/*  4 clocks */
@@ -1068,6 +1266,7 @@ static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
 			    | ((zqoper & 0xF) << 16)
 			    | ((zqcs & 0xF) << 8)
 			    );
+	debug("FSLDDR: zq_cntl = 0x%08x\n", ddr->ddr_zq_cntl);
 }
 
 /* DDR Write Leveling Control (DDR_WRLVL_CNTL) */
@@ -1113,7 +1312,8 @@ static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en,
 		/*
 		 * Write leveling start time
 		 * The value use for the DQS_ADJUST for the first sample
-		 * when write leveling is enabled.
+		 * when write leveling is enabled. It probably needs to be
+		 * overriden per platform.
 		 */
 		wrlvl_start = 0x8;
 		/*
@@ -1135,6 +1335,7 @@ static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en,
 			       | ((wrlvl_wlr & 0x7) << 8)
 			       | ((wrlvl_start & 0x1F) << 0)
 			       );
+	debug("FSLDDR: wrlvl_cntl = 0x%08x\n", ddr->ddr_wrlvl_cntl);
 }
 
 /* DDR Self Refresh Counter (DDR_SR_CNTR) */
@@ -1152,6 +1353,12 @@ static void set_ddr_eor(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
 	}
 }
 
+static void set_ddr_cdr1(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
+{
+	ddr->ddr_cdr1 = popts->ddr_cdr1;
+	debug("FSLDDR: ddr_cdr1 = 0x%08x\n", ddr->ddr_cdr1);
+}
+
 unsigned int
 check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
 {
@@ -1184,6 +1391,8 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 	unsigned int sr_it;
 	unsigned int zq_en;
 	unsigned int wrlvl_en;
+	unsigned int ip_rev = 0;
+	unsigned int unq_mrs_en = 0;
 	int cs_en = 1;
 
 	memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t));
@@ -1397,7 +1606,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 	set_ddr_eor(ddr, popts);
 
 #if !defined(CONFIG_FSL_DDR1)
-	set_timing_cfg_0(ddr);
+	set_timing_cfg_0(ddr, popts);
 #endif
 
 	set_timing_cfg_3(ddr, common_dimm, cas_latency);
@@ -1405,26 +1614,38 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 	set_timing_cfg_2(ddr, popts, common_dimm,
 				cas_latency, additive_latency);
 
+	set_ddr_cdr1(ddr, popts);
 	set_ddr_sdram_cfg(ddr, popts, common_dimm);
+	ip_rev = fsl_ddr_get_version();
+	if (ip_rev > 0x40400)
+		unq_mrs_en = 1;
 
-	set_ddr_sdram_cfg_2(ddr, popts);
+	set_ddr_sdram_cfg_2(ddr, popts, unq_mrs_en);
 	set_ddr_sdram_mode(ddr, popts, common_dimm,
 				cas_latency, additive_latency);
 	set_ddr_sdram_mode_2(ddr, popts);
+	if (unq_mrs_en) {
+		set_ddr_sdram_mode_3(ddr, popts);
+		set_ddr_sdram_mode_4(ddr, popts);
+		set_ddr_sdram_mode_5(ddr, popts);
+		set_ddr_sdram_mode_6(ddr, popts);
+		set_ddr_sdram_mode_7(ddr, popts);
+		set_ddr_sdram_mode_8(ddr, popts);
+	}
 	set_ddr_sdram_interval(ddr, popts, common_dimm);
 	set_ddr_data_init(ddr);
 	set_ddr_sdram_clk_cntl(ddr, popts);
 	set_ddr_init_addr(ddr);
 	set_ddr_init_ext_addr(ddr);
 	set_timing_cfg_4(ddr, popts);
-	set_timing_cfg_5(ddr);
+	set_timing_cfg_5(ddr, cas_latency);
 
 	set_ddr_zq_cntl(ddr, zq_en);
 	set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts);
 
 	set_ddr_sr_cntr(ddr, sr_it);
 
-	set_ddr_sdram_rcw(ddr, common_dimm);
+	set_ddr_sdram_rcw(ddr, popts, common_dimm);
 
 	return check_fsl_memctl_config_regs(ddr);
 }
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c
index f876e20..e5b04c8 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/options.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/options.c
@@ -19,23 +19,316 @@ extern void fsl_ddr_board_options(memctl_options_t *popts,
 		dimm_params_t *pdimm,
 		unsigned int ctrl_num);
 
+typedef struct {
+	unsigned int odt_rd_cfg;
+	unsigned int odt_wr_cfg;
+	unsigned int odt_rtt_norm;
+	unsigned int odt_rtt_wr;
+} dynamic_odt_t;
+
+static const dynamic_odt_t single_Q[4] = {
+	{	/* cs0 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_CS_AND_OTHER_DIMM,
+		DDR3_RTT_20_OHM,
+		DDR3_RTT_120_OHM
+	},
+	{	/* cs1 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_NEVER,	/* tied high */
+		DDR3_RTT_OFF,
+		DDR3_RTT_120_OHM
+	},
+	{	/* cs2 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_CS_AND_OTHER_DIMM,
+		DDR3_RTT_20_OHM,
+		DDR3_RTT_120_OHM
+	},
+	{	/* cs3 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_NEVER,	/* tied high */
+		DDR3_RTT_OFF,
+		DDR3_RTT_120_OHM
+	}
+};
+
+static const dynamic_odt_t single_D[4] = {
+	{	/* cs0 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_ALL,
+		DDR3_RTT_40_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs1 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_NEVER,
+		DDR3_RTT_OFF,
+		DDR3_RTT_OFF
+	},
+	{0, 0, 0, 0},
+	{0, 0, 0, 0}
+};
+
+static const dynamic_odt_t single_S[4] = {
+	{	/* cs0 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_ALL,
+		DDR3_RTT_40_OHM,
+		DDR3_RTT_OFF
+	},
+	{0, 0, 0, 0},
+	{0, 0, 0, 0},
+	{0, 0, 0, 0},
+};
+
+static const dynamic_odt_t dual_DD[4] = {
+	{	/* cs0 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_SAME_DIMM,
+		DDR3_RTT_120_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs1 */
+		FSL_DDR_ODT_OTHER_DIMM,
+		FSL_DDR_ODT_OTHER_DIMM,
+		DDR3_RTT_30_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs2 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_SAME_DIMM,
+		DDR3_RTT_120_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs3 */
+		FSL_DDR_ODT_OTHER_DIMM,
+		FSL_DDR_ODT_OTHER_DIMM,
+		DDR3_RTT_30_OHM,
+		DDR3_RTT_OFF
+	}
+};
+
+static const dynamic_odt_t dual_DS[4] = {
+	{	/* cs0 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_SAME_DIMM,
+		DDR3_RTT_120_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs1 */
+		FSL_DDR_ODT_OTHER_DIMM,
+		FSL_DDR_ODT_OTHER_DIMM,
+		DDR3_RTT_30_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs2 */
+		FSL_DDR_ODT_OTHER_DIMM,
+		FSL_DDR_ODT_ALL,
+		DDR3_RTT_20_OHM,
+		DDR3_RTT_120_OHM
+	},
+	{0, 0, 0, 0}
+};
+static const dynamic_odt_t dual_SD[4] = {
+	{	/* cs0 */
+		FSL_DDR_ODT_OTHER_DIMM,
+		FSL_DDR_ODT_ALL,
+		DDR3_RTT_20_OHM,
+		DDR3_RTT_120_OHM
+	},
+	{0, 0, 0, 0},
+	{	/* cs2 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_SAME_DIMM,
+		DDR3_RTT_120_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs3 */
+		FSL_DDR_ODT_OTHER_DIMM,
+		FSL_DDR_ODT_OTHER_DIMM,
+		DDR3_RTT_20_OHM,
+		DDR3_RTT_OFF
+	}
+};
+
+static const dynamic_odt_t dual_SS[4] = {
+	{	/* cs0 */
+		FSL_DDR_ODT_OTHER_DIMM,
+		FSL_DDR_ODT_ALL,
+		DDR3_RTT_30_OHM,
+		DDR3_RTT_120_OHM
+	},
+	{0, 0, 0, 0},
+	{	/* cs2 */
+		FSL_DDR_ODT_OTHER_DIMM,
+		FSL_DDR_ODT_ALL,
+		DDR3_RTT_30_OHM,
+		DDR3_RTT_120_OHM
+	},
+	{0, 0, 0, 0}
+};
+
+static const dynamic_odt_t dual_D0[4] = {
+	{	/* cs0 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_SAME_DIMM,
+		DDR3_RTT_40_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs1 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_NEVER,
+		DDR3_RTT_OFF,
+		DDR3_RTT_OFF
+	},
+	{0, 0, 0, 0},
+	{0, 0, 0, 0}
+};
+
+static const dynamic_odt_t dual_0D[4] = {
+	{0, 0, 0, 0},
+	{0, 0, 0, 0},
+	{	/* cs2 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_SAME_DIMM,
+		DDR3_RTT_40_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs3 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_NEVER,
+		DDR3_RTT_OFF,
+		DDR3_RTT_OFF
+	}
+};
+
+static const dynamic_odt_t dual_S0[4] = {
+	{	/* cs0 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_CS,
+		DDR3_RTT_40_OHM,
+		DDR3_RTT_OFF
+	},
+	{0, 0, 0, 0},
+	{0, 0, 0, 0},
+	{0, 0, 0, 0}
+
+};
+
+static const dynamic_odt_t dual_0S[4] = {
+	{0, 0, 0, 0},
+	{0, 0, 0, 0},
+	{	/* cs2 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_CS,
+		DDR3_RTT_40_OHM,
+		DDR3_RTT_OFF
+	},
+	{0, 0, 0, 0}
+
+};
+
+static const dynamic_odt_t odt_unknown[4] = {
+	{	/* cs0 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_CS,
+		DDR3_RTT_120_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs1 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_CS,
+		DDR3_RTT_120_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs2 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_CS,
+		DDR3_RTT_120_OHM,
+		DDR3_RTT_OFF
+	},
+	{	/* cs3 */
+		FSL_DDR_ODT_NEVER,
+		FSL_DDR_ODT_CS,
+		DDR3_RTT_120_OHM,
+		DDR3_RTT_OFF
+	}
+};
+
 unsigned int populate_memctl_options(int all_DIMMs_registered,
 			memctl_options_t *popts,
 			dimm_params_t *pdimm,
 			unsigned int ctrl_num)
 {
 	unsigned int i;
+	const dynamic_odt_t *pdodt = odt_unknown;
 
 	/* Chip select options. */
 
+	if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
+		switch (pdimm[0].n_ranks) {
+		case 1:
+			pdodt = single_S;
+			break;
+		case 2:
+			pdodt = single_D;
+			break;
+		case 4:
+			pdodt = single_Q;
+			break;
+		}
+	} else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
+		switch (pdimm[0].n_ranks) {
+		case 2:
+			switch (pdimm[1].n_ranks) {
+			case 2:
+				pdodt = dual_DD;
+				break;
+			case 1:
+				pdodt = dual_DS;
+				break;
+			case 0:
+				pdodt = dual_D0;
+				break;
+			}
+			break;
+		case 1:
+			switch (pdimm[1].n_ranks) {
+			case 2:
+				pdodt = dual_SD;
+				break;
+			case 1:
+				pdodt = dual_SS;
+				break;
+			case 0:
+				pdodt = dual_S0;
+				break;
+			}
+			break;
+		case 0:
+			switch (pdimm[1].n_ranks) {
+			case 2:
+				pdodt = dual_0D;
+				break;
+			case 1:
+				pdodt = dual_0S;
+				break;
+			}
+			break;
+		}
+	}
 	/* Pick chip-select local options. */
 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
-		/* If not DDR2, odt_rd_cfg and odt_wr_cfg need to be 0. */
-
-		/* only for single CS? */
-		popts->cs_local_opts[i].odt_rd_cfg = 0;
-
-		popts->cs_local_opts[i].odt_wr_cfg = 1;
+#if defined(CONFIG_FSL_DDR3)
+		popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg;
+		popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg;
+		popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm;
+		popts->cs_local_opts[i].odt_rtt_wr = pdodt[i].odt_rtt_wr;
+#else
+		popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
+		popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
+#endif
 		popts->cs_local_opts[i].auto_precharge = 0;
 	}
 
@@ -163,6 +456,9 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 	popts->twoT_en = 0;
 	popts->threeT_en = 0;
 
+	/* for RDIMM, address parity enable */
+	popts->ap_en = 1;
+
 	/*
 	 * BSTTOPRE precharge interval
 	 *
diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h
index 6ec95b6..cd0675f 100644
--- a/arch/powerpc/include/asm/fsl_ddr_sdram.h
+++ b/arch/powerpc/include/asm/fsl_ddr_sdram.h
@@ -24,6 +24,7 @@
 #define DDR_OTF		6	/* on-the-fly BC4 and BL8 */
 #define DDR_BL8		8	/* burst length 8 */
 
+#define DDR3_RTT_OFF		0
 #define DDR3_RTT_60_OHM		1 /* RTT_Nom = RZQ/4 */
 #define DDR3_RTT_120_OHM	2 /* RTT_Nom = RZQ/2 */
 #define DDR3_RTT_40_OHM		3 /* RTT_Nom = RZQ/6 */
@@ -50,6 +51,15 @@ typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 #endif
 #endif	/* #if defined(CONFIG_FSL_DDR1) */
 
+#define FSL_DDR_ODT_NEVER		0x0
+#define FSL_DDR_ODT_CS			0x1
+#define FSL_DDR_ODT_ALL_OTHER_CS	0x2
+#define FSL_DDR_ODT_OTHER_DIMM		0x3
+#define FSL_DDR_ODT_ALL			0x4
+#define FSL_DDR_ODT_SAME_DIMM		0x5
+#define FSL_DDR_ODT_CS_AND_OTHER_DIMM	0x6
+#define FSL_DDR_ODT_OTHER_CS_ONSAMEDIMM	0x7
+
 /* define bank(chip select) interleaving mode */
 #define FSL_DDR_CS0_CS1			0x40
 #define FSL_DDR_CS2_CS3			0x20
@@ -106,6 +116,12 @@ typedef struct fsl_ddr_cfg_regs_s {
 	unsigned int ddr_sdram_cfg_2;
 	unsigned int ddr_sdram_mode;
 	unsigned int ddr_sdram_mode_2;
+	unsigned int ddr_sdram_mode_3;
+	unsigned int ddr_sdram_mode_4;
+	unsigned int ddr_sdram_mode_5;
+	unsigned int ddr_sdram_mode_6;
+	unsigned int ddr_sdram_mode_7;
+	unsigned int ddr_sdram_mode_8;
 	unsigned int ddr_sdram_md_cntl;
 	unsigned int ddr_sdram_interval;
 	unsigned int ddr_data_init;
@@ -156,6 +172,8 @@ typedef struct memctl_options_s {
 		unsigned int auto_precharge;
 		unsigned int odt_rd_cfg;
 		unsigned int odt_wr_cfg;
+		unsigned int odt_rtt_norm;
+		unsigned int odt_rtt_wr;
 	} cs_local_opts[CONFIG_CHIP_SELECTS_PER_CTRL];
 
 	/* Special configurations for chip select */
diff --git a/board/freescale/corenet_ds/ddr.c b/board/freescale/corenet_ds/ddr.c
index 2ee0188..0eb290d 100644
--- a/board/freescale/corenet_ds/ddr.c
+++ b/board/freescale/corenet_ds/ddr.c
@@ -56,12 +56,14 @@ phys_size_t fixed_sdram(void)
 			strmhz(buf, sysinfo.freqDDRBus));
 
 	ddr_size = (phys_size_t) CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
+	ddr_cfg_regs.ddr_cdr1 = 0x80000000;
 	fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0);
 
 #if (CONFIG_NUM_DDR_CONTROLLERS == 2)
 	memcpy(&ddr_cfg_regs,
 		fixed_ddr_parm_1[i].ddr_settings,
 		sizeof(ddr_cfg_regs));
+	ddr_cfg_regs.ddr_cdr1 = 0x80000000;
 	fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 1);
 #endif
 
@@ -165,54 +167,54 @@ const board_specific_parameters_t board_specific_parameters[][30] = {
 	/* 	memory controller 0 			*/
 	/*	  lo|  hi|  num|  clk| cpo|wrdata|2T	*/
 	/*	 mhz| mhz|ranks|adjst|    | delay|	*/
-		{  0, 333,    4,    6,   7,    3,  0},
-		{334, 400,    4,    6,   9,    3,  0},
-		{401, 549,    4,    6,  11,    3,  0},
-		{550, 680,    4,    1,  10,    5,  0},
-		{681, 850,    4,    1,  12,    5,  0},
-		{851, 1050,   4,    1,  12,    5,  0},
-		{1051, 1250,  4,    1,  15,    4,  0},
-		{1251, 1350,  4,    1,  15,    4,  0},
-		{  0, 333,    2,    6,   7,    3,  0},
-		{334, 400,    2,    6,   9,    3,  0},
-		{401, 549,    2,    6,  11,    3,  0},
-		{550, 680,    2,    1,  10,    5,  0},
-		{681, 850,    2,    1,  12,    5,  0},
-		{851, 1050,   2,    1,  12,    5,  0},
-		{1051, 1250,  2,    1,  15,    4,  0},
-		{1251, 1350,  2,    1,  15,    4,  0},
-		{  0, 333,    1,    6,   7,    3,  0},
-		{334, 400,    1,    6,   9,    3,  0},
-		{401, 549,    1,    6,  11,    3,  0},
-		{550, 680,    1,    1,  10,    5,  0},
-		{681, 850,    1,    1,  12,    5,  0}
+		{  0, 333,    4,    5, 0xff,    2,  0},
+		{334, 400,    4,    5, 0xff,    2,  0},
+		{401, 549,    4,    5, 0xff,    2,  0},
+		{550, 680,    4,    5, 0xff,    2,  0},
+		{681, 850,    4,    5, 0xff,    2,  0},
+		{851, 1050,   4,    5, 0xff,    2,  0},
+		{1051, 1250,  4,    5, 0xff,    2,  0},
+		{1251, 1350,  4,    5, 0xff,    2,  0},
+		{  0, 333,    2,    5, 0xff,    2,  0},
+		{334, 400,    2,    5, 0xff,    2,  0},
+		{401, 549,    2,    5, 0xff,    2,  0},
+		{550, 680,    2,    5, 0xff,    2,  0},
+		{681, 850,    2,    5, 0xff,    2,  0},
+		{851, 1050,   2,    5, 0xff,    2,  0},
+		{1051, 1250,  2,    5, 0xff,    2,  0},
+		{1251, 1350,  2,    5, 0xff,    2,  0},
+		{  0, 333,    1,    5, 0xff,    2,  0},
+		{334, 400,    1,    5, 0xff,    2,  0},
+		{401, 549,    1,    5, 0xff,    2,  0},
+		{550, 680,    1,    5, 0xff,    2,  0},
+		{681, 850,    1,    5, 0xff,    2,  0}
 	},
 
 	{
 	/*	memory controller 1			*/
 	/*	  lo|  hi|  num|  clk| cpo|wrdata|2T	*/
 	/*	 mhz| mhz|ranks|adjst|    | delay|	*/
-		{  0, 333,    4,    6,   7,    3,  0},
-		{334, 400,    4,    6,   9,    3,  0},
-		{401, 549,    4,    6,  11,    3,  0},
-		{550, 680,    4,    1,  10,    5,  0},
-		{681, 850,    4,    1,  12,    5,  0},
-		{851, 1050,   4,    1,  12,    5,  0},
-		{1051, 1250,  4,    1,  15,    4,  0},
-		{1251, 1350,  4,    1,  15,    4,  0},
-		{  0, 333,    2,     6,  7,    3,  0},
-		{334, 400,    2,     6,  9,    3,  0},
-		{401, 549,    2,     6, 11,    3,  0},
-		{550, 680,    2,     1, 11,    6,  0},
-		{681, 850,    2,     1, 13,    6,  0},
-		{851, 1050,   2,     1, 13,    6,  0},
-		{1051, 1250,  2,     1, 15,    4,  0},
-		{1251, 1350,  2,     1, 15,    4,  0},
-		{  0, 333,    1,     6,  7,    3,  0},
-		{334, 400,    1,     6,  9,    3,  0},
-		{401, 549,    1,     6, 11,    3,  0},
-		{550, 680,    1,     1, 11,    6,  0},
-		{681, 850,    1,     1, 13,    6,  0}
+		{  0, 333,    4,    5, 0xff,    2,  0},
+		{334, 400,    4,    5, 0xff,    2,  0},
+		{401, 549,    4,    5, 0xff,    2,  0},
+		{550, 680,    4,    5, 0xff,    2,  0},
+		{681, 850,    4,    5, 0xff,    2,  0},
+		{851, 1050,   4,    5, 0xff,    2,  0},
+		{1051, 1250,  4,    5, 0xff,    2,  0},
+		{1251, 1350,  4,    5, 0xff,    2,  0},
+		{  0, 333,    2,    5, 0xff,    2,  0},
+		{334, 400,    2,    5, 0xff,    2,  0},
+		{401, 549,    2,    5, 0xff,    2,  0},
+		{550, 680,    2,    5, 0xff,    2,  0},
+		{681, 850,    2,    5, 0xff,    2,  0},
+		{851, 1050,   2,    5, 0xff,    2,  0},
+		{1051, 1250,  2,    5, 0xff,    2,  0},
+		{1251, 1350,  2,    5, 0xff,    2,  0},
+		{  0, 333,    1,    5, 0xff,    2,  0},
+		{334, 400,    1,    5, 0xff,    2,  0},
+		{401, 549,    1,    5, 0xff,    2,  0},
+		{550, 680,    1,    5, 0xff,    2,  0},
+		{681, 850,    1,    5, 0xff,    2,  0}
 	}
 };
 
@@ -227,26 +229,6 @@ void fsl_ddr_board_options(memctl_options_t *popts,
 	u32 i;
 	ulong ddr_freq;
 
-	/* set odt_rd_cfg and odt_wr_cfg. If the there is only one dimm in
-	 * that controller, set odt_wr_cfg to 4 for CS0, and 0 to CS1. If
-	 * there are two dimms in the controller, set odt_rd_cfg to 3 and
-	 * odt_wr_cfg to 3 for the even CS, 0 for the odd CS.
-	 */
-	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
-		if (i&1) {	/* odd CS */
-			popts->cs_local_opts[i].odt_rd_cfg = 0;
-			popts->cs_local_opts[i].odt_wr_cfg = 1;
-		} else {	/* even CS */
-			if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
-				popts->cs_local_opts[i].odt_rd_cfg = 0;
-				popts->cs_local_opts[i].odt_wr_cfg = 1;
-			} else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
-			popts->cs_local_opts[i].odt_rd_cfg = 3;
-			popts->cs_local_opts[i].odt_wr_cfg = 3;
-			}
-		}
-	}
-
 	/* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr
 	 * freqency and n_banks specified in board_specific_parameters table.
 	 */
@@ -255,10 +237,11 @@ void fsl_ddr_board_options(memctl_options_t *popts,
 		if (ddr_freq >= pbsp->datarate_mhz_low &&
 		    ddr_freq <= pbsp->datarate_mhz_high &&
 		    pdimm->n_ranks == pbsp->n_ranks) {
-			popts->cpo_override = 0xff; /* force auto CPO calibration */
-			popts->write_data_delay = 2;
-			popts->clk_adjust = 5; /* Force value to be 5/8 clock cycle */
+			popts->cpo_override = pbsp->cpo;
+			popts->write_data_delay = pbsp->write_data_delay;
+			popts->clk_adjust = pbsp->clk_adjust;
 			popts->twoT_en = pbsp->force_2T;
+			popts->wrlvl_start = pbsp->clk_adjust + 2;
 		}
 		pbsp++;
 	}
@@ -273,16 +256,20 @@ void fsl_ddr_board_options(memctl_options_t *popts,
 	 */
 	popts->wrlvl_override = 1;
 	popts->wrlvl_sample = 0xa;
-	popts->wrlvl_start = 0x7;
 	/*
 	 * Rtt and Rtt_WR override
 	 */
-	popts->rtt_override = 1;
-	popts->rtt_override_value = DDR3_RTT_120_OHM;
-	popts->rtt_wr_override_value = 0; /* Rtt_WR= dynamic ODT off */
+	popts->rtt_override = 0;
 
 	/* Enable ZQ calibration */
 	popts->zq_en = 1;
+
+	/* DHC_EN =1, ODT = 60 Ohm */
+	popts->ddr_cdr1 = 0x80080000;
+
+	popts->rcw_override = 1;
+	popts->rcw_1 = 0x000a5000;
+	popts->rcw_2 = 0x00100000;
 }
 
 phys_size_t initdram(int board_type)
diff --git a/doc/README.fsl-ddr b/doc/README.fsl-ddr
index 9e3c539..a7ba193 100644
--- a/doc/README.fsl-ddr
+++ b/doc/README.fsl-ddr
@@ -104,4 +104,69 @@ Combination of hwconfig
 Hwconfig can be combined with multiple parameters, for example, on a supported
 platform
 
-hwconfig=fsl_ddr:addr_hash=true,ctlr_intlv=cacheline,bank_intlv=cs0_cs1_cs2_cs3
+hwconfig=fsl_ddr:addr_hash=true,ctlr_intlv=cacheline,bank_intlv=cs0_cs1_cs2_cs3,ecc=on
+
+Table for dynamic ODT for DDR3
+==============================
+For single-slot system with quad-rank DIMM and dual-slot system, dynamic ODT may
+be needed, depending on the configuration. The numbers in the following tables are
+in Ohms.
+
+* denotes dynamic ODT
+
+Two slots system
++-----------------------+----------+---------------+-----------------------------+-----------------------------+
+|     Configuration     |          |DRAM controller|           Slot 1            |            Slot 2           |
++-----------+-----------+----------+-------+-------+--------------+--------------+--------------+--------------+
+|           |           |          |       |       |     Rank 1   |     Rank 2   |   Rank 1     |    Rank 2    |
++  Slot 1   |   Slot 2  |Write/Read| Write | Read  |-------+------+-------+------+-------+------+-------+------+
+|           |           |          |       |       | Write | Read | Write | Read | Write | Read | Write | Read |
++-----------+-----------+----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|           |           |  Slot 1  |  off  | 75    | 120   | off  | off   | off  | off   | off  | 30    | 30   |
+| Dual Rank | Dual Rank |----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|           |           |  Slot 2  |  off  | 75    | off   | off  | 30    | 30   | 120   | off  | off   | off  |
++-----------+-----------+----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|           |           |  Slot 1  |  off  | 75    | 120   | off  | off   | off  | 20    | 20   |       |      |
+| Dual Rank |Single Rank|----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|           |           |  Slot 2  |  off  | 75    | off   | off  | 20    | 20   | 120  *| off  |       |      |
++-----------+-----------+----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|           |           |  Slot 1  |  off  | 75    | 120  *| off  |       |      | off   | off  | 20    | 20   |
+|Single Rank| Dual Rank |----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|           |           |  Slot 2  |  off  | 75    | 20    | 20   |       |      | 120   | off  | off   | off  |
++-----------+-----------+----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|           |           |  Slot 1  |  off  | 75    | 120  *| off  |       |      | 30    | 30   |       |      |
+|Single Rank|Single Rank|----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|           |           |  Slot 2  |  off  | 75    | 30    | 30   |       |      | 120  *| off  |       |      |
++-----------+-----------+----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+| Dual Rank |   Empty   |  Slot 1  |  off  | 75    | 40    | off  | off   | off  |       |      |       |      |
++-----------+-----------+----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|   Empty   | Dual Rank |  Slot 2  |  off  | 75    |       |      |       |      | 40    | off  | off   | off  |
++-----------+-----------+----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|Single Rank|   Empty   |  Slot 1  |  off  | 75    | 40    | off  |       |      |       |      |       |      |
++-----------+-----------+----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|   Empty   |Single Rank|  Slot 2  |  off  | 75    |       |      |       |      | 40    | off  |       |      |
++-----------+-----------+----------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+
+Single slot system
++-------------+------------+---------------+-----------------------------+-----------------------------+
+|             |            |DRAM controller|     Rank 1   |    Rank 2    |    Rank 3    |    Rank 4    |
+|Configuration| Write/Read |-------+-------+-------+------+-------+------+-------+------+-------+------+
+|             |            | Write | Read  | Write | Read | Write | Read | Write | Read | Write | Read |
++-------------+------------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|             |   R1       | off   | 75    | 120  *| off  | off   | off  | 20    | 20   | off   | off  |
+|             |------------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|             |   R2       | off   | 75    | off   | 20   | 120   | off  | 20    | 20   | off   | off  |
+|  Quad Rank  |------------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|             |   R3       | off   | 75    | 20    | 20   | off   | off  | 120  *| off  | off   | off  |
+|             |------------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|             |   R4       | off   | 75    | 20    | 20   | off   | off  | off   | 20   | 120   | off  |
++-------------+------------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+|             |   R1       | off   | 75    | 40    | off  | off   | off  |
+|  Dual Rank  |------------+-------+-------+-------+------+-------+------+
+|             |   R2       | off   | 75    | 40    | off  | off   | off  |
++-------------+------------+-------+-------+-------+------+-------+------+
+| Single Rank |   R1       | off   | 75    | 40    | off  |
++-------------+------------+-------+-------+-------+------+
+
+Reference http://www.xrosstalkmag.com/mag_issues/xrosstalk_oct08_final.pdf
+          http://download.micron.com/pdf/technotes/ddr3/tn4108_ddr3_design_guide.pdf
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 07/10] Adding more SPD registers
  2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
                   ` (4 preceding siblings ...)
  2010-12-09  2:55 ` [U-Boot] [PATCH 06/10] Enable unique mode registers and dynamic ODT for DDR3 York Sun
@ 2010-12-09  2:55 ` York Sun
  2010-12-14  7:52   ` Wolfgang Denk
  2010-12-09  2:55 ` [U-Boot] [PATCH 08/10] Implement workaround for erratum DDRA003 York Sun
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: York Sun @ 2010-12-09  2:55 UTC (permalink / raw)
  To: u-boot

Adding byte 32 and 33

Signed-off-by: York Sun <yorksun@freescale.com>
---
 include/ddr_spd.h |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/include/ddr_spd.h b/include/ddr_spd.h
index 710e528..9fa305e 100644
--- a/include/ddr_spd.h
+++ b/include/ddr_spd.h
@@ -219,7 +219,9 @@ typedef struct ddr3_spd_eeprom_s {
 					     Delay Time*/
 	unsigned char opt_features;    /* 30 SDRAM Optional Features */
 	unsigned char therm_ref_opt;   /* 31 SDRAM Thermal and Refresh Opts */
-	unsigned char res_32_59[28];   /* 32-59 Reserved, General Section */
+	unsigned char therm_sensor;    /* 32 Module Thermal Sensor */
+	unsigned char device_type;     /* SDRAM device type */
+	unsigned char res_34_59[26];   /* 34-59 Reserved, General Section */
 
 	/* Module-Specific Section: Bytes 60-116 */
 	union {
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 08/10] Implement workaround for erratum DDRA003
  2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
                   ` (5 preceding siblings ...)
  2010-12-09  2:55 ` [U-Boot] [PATCH 07/10] Adding more SPD registers York Sun
@ 2010-12-09  2:55 ` York Sun
  2010-12-14  6:47   ` Kumar Gala
  2010-12-09  2:55 ` [U-Boot] [PATCH 09/10] Adding interactive ddr York Sun
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: York Sun @ 2010-12-09  2:55 UTC (permalink / raw)
  To: u-boot

Erratum DDRA003 requires workaround to correctly set RCW10 for registered DIMM.
Also adding polling after enabling DDR controller to ensure completion.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 arch/powerpc/cpu/mpc85xx/ddr-gen3.c |   53 ++++++++++++++++++++++++++++++++++-
 include/configs/P4080DS.h           |    1 +
 2 files changed, 53 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
index 568f9f4..0815ba4 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
@@ -108,6 +108,55 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	temp_sdram_cfg = regs->ddr_sdram_cfg;
 	temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
 	out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
+#ifdef CONFIG_SYS_P4080_ERRATUM_DDRA003
+	if (regs->ddr_sdram_rcw_2 & 0x00f00000) {
+		out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2 & 0xf07fffff);
+		out_be32(&ddr->debug[2], 0x00000400);
+		out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl & 0x7fffffff);
+		out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl & 0x7fffffff);
+		out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2 & 0xffffffeb);
+		out_be32(&ddr->mtcr, 0);
+		out_be32(&ddr->debug[12], 0x00000015);
+		out_be32(&ddr->debug[21], 0x24000000);
+		out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval & 0xffff);
+		out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_BI | SDRAM_CFG_MEM_EN);
+
+		asm volatile("sync;isync");
+		while (!(in_be32(&ddr->debug[1]) & 0x2));
+
+		switch (regs->ddr_sdram_rcw_2 & 0x00f00000) {
+		case 0x00000000:
+			out_be32(&ddr->sdram_md_cntl, 0xc4080002);
+			break;
+		case 0x00100000:
+			out_be32(&ddr->sdram_md_cntl, 0xc408000a);
+			break;
+		case 0x00200000:
+			out_be32(&ddr->sdram_md_cntl, 0xc4080012);
+			break;
+		case 0x00300000:
+			out_be32(&ddr->sdram_md_cntl, 0xc408001a);
+			break;
+		default:
+			out_be32(&ddr->sdram_md_cntl, 0xc4080002);
+			printf("Unsupported RC10\n");
+			break;
+		}
+
+		while (in_be32(&ddr->sdram_md_cntl) & 0x80000000);
+		udelay(6);
+		out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
+		out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+		out_be32(&ddr->debug[2], 0x0);
+		out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
+		out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
+		out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+		out_be32(&ddr->debug[12], 0x0);
+		out_be32(&ddr->debug[21], 0x0);
+		out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+
+	}
+#endif
 	/*
 	 * For 8572 DDR1 erratum - DDR controller may enter illegal state
 	 * when operatiing in 32-bit bus mode with 4-beat bursts,
@@ -131,8 +180,10 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	asm volatile("sync;isync");
 
 	/* Let the controller go */
-	temp_sdram_cfg = in_be32(&ddr->sdram_cfg);
+	temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
 	out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
+	asm volatile("sync;isync");
+	while (!(in_be32(&ddr->debug[1]) & 0x2));
 
 	/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done.  */
 	while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
diff --git a/include/configs/P4080DS.h b/include/configs/P4080DS.h
index d210016..c19bd39 100644
--- a/include/configs/P4080DS.h
+++ b/include/configs/P4080DS.h
@@ -45,6 +45,7 @@
 #define CONFIG_SYS_P4080_ERRATUM_CPC9
 #define CONFIG_SYS_P4080_ERRATUM_DDR1
 #define CONFIG_SYS_P4080_ERRATUM_DDR7
+#define CONFIG_SYS_P4080_ERRATUM_DDRA003
 #define CONFIG_SYS_P4080_ERRATUM_ESDHC1
 #define CONFIG_SYS_P4080_ERRATUM_ESDHC9
 #define CONFIG_SYS_P4080_ERRATUM_ESDHC11
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 09/10] Adding interactive ddr
  2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
                   ` (6 preceding siblings ...)
  2010-12-09  2:55 ` [U-Boot] [PATCH 08/10] Implement workaround for erratum DDRA003 York Sun
@ 2010-12-09  2:55 ` York Sun
  2010-12-14  5:15   ` Kumar Gala
  2010-12-14  7:47   ` Wolfgang Denk
  2010-12-09  2:55 ` [U-Boot] [PATCH 10/10] Extend board specific parameters York Sun
  2010-12-14  7:59 ` [U-Boot] [PATCH 01/10] Display RDIMM if detected Wolfgang Denk
  9 siblings, 2 replies; 28+ messages in thread
From: York Sun @ 2010-12-09  2:55 UTC (permalink / raw)
  To: u-boot

Use environment variable to active the interactive debugging.

Signed-off-by: York Sun <yorksun@freescale.com>
---
 arch/powerpc/cpu/mpc8xxx/ddr/Makefile      |    6 +-
 arch/powerpc/cpu/mpc8xxx/ddr/interactive.c | 1882 ++++++++++++++++++++++++++++
 arch/powerpc/cpu/mpc8xxx/ddr/main.c        |    8 +-
 doc/README.fsl-ddr                         |   20 +
 4 files changed, 1910 insertions(+), 6 deletions(-)
 create mode 100644 arch/powerpc/cpu/mpc8xxx/ddr/interactive.c

diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/Makefile b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
index cb7f856..4bd416a 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
@@ -11,15 +11,15 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)libddr.a
 
 COBJS-$(CONFIG_FSL_DDR1)	+= main.o util.o ctrl_regs.o options.o \
-				   lc_common_dimm_params.o
+				   lc_common_dimm_params.o interactive.o
 COBJS-$(CONFIG_FSL_DDR1)	+= ddr1_dimm_params.o
 
 COBJS-$(CONFIG_FSL_DDR2)	+= main.o util.o ctrl_regs.o options.o \
-				   lc_common_dimm_params.o
+				   lc_common_dimm_params.o interactive.o
 COBJS-$(CONFIG_FSL_DDR2)	+= ddr2_dimm_params.o
 
 COBJS-$(CONFIG_FSL_DDR3)	+= main.o util.o ctrl_regs.o options.o \
-				   lc_common_dimm_params.o
+				   lc_common_dimm_params.o interactive.o
 COBJS-$(CONFIG_FSL_DDR3)	+= ddr3_dimm_params.o
 
 SRCS	:= $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c
new file mode 100644
index 0000000..7d492a9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c
@@ -0,0 +1,1882 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+/*
+ * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ * Maintainer: York Sun <yorksun@freescale.com>
+ */
+
+#include <common.h>
+#include <linux/ctype.h>
+#include <asm/types.h>
+
+#include <asm/fsl_ddr_sdram.h>
+#include "ddr.h"
+
+/* Option parameter Structures */
+typedef struct {
+	const char *option_name;
+	size_t offset;
+} options_strings_t;
+
+int do_reset(void *cmdtp, int flag, int argc, char *argv[]);
+unsigned int check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr);
+const char *step_to_string(unsigned int step);
+
+static unsigned int picos_to_mhz(unsigned int picos)
+{
+	return 1000000 / picos;
+}
+
+static int handle_uint_option_table(const options_strings_t *table,
+			 int table_size,
+			 u32 base,
+			 const char *opt,
+			 const char *val)
+{
+	unsigned int i;
+	unsigned int value, *ptr;
+
+	for (i = 0; i < table_size; i++) {
+		if (strcmp(table[i].option_name, opt) == 0) {
+			value = simple_strtoul(val, NULL, 0);
+			ptr = (unsigned int *)(base + table[i].offset);
+			*ptr = value;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int handle_ull_option_table(const options_strings_t *table,
+			int table_size,
+			u32 base,
+			const char *opt,
+			const char *val)
+{
+	unsigned int i;
+	unsigned long long value, *ptr;
+
+	for (i = 0; i < table_size; i++) {
+		if (strcmp(table[i].option_name, opt) == 0) {
+			value = simple_strtoull(val, NULL, 0);
+			ptr = (unsigned long long *)(base + table[i].offset);
+			*ptr = value;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static void fsl_ddr_generic_edit(void *pdata,
+			   void *pend,
+			   unsigned int element_size,
+			   unsigned int element_num,
+			   unsigned int value)
+{
+	char *pcdata = (char *)pdata;		/* BIG ENDIAN ONLY */
+
+	pcdata += element_num * element_size;
+	if ((pcdata + element_size) > (char *) pend) {
+		debug("trying to write past end of data\n");
+		return;
+	}
+
+	switch (element_size) {
+	case 1:
+		__raw_writeb(value, pcdata);
+		break;
+	case 2:
+		__raw_writew(value, pcdata);
+		break;
+	case 4:
+		__raw_writel(value, pcdata);
+		break;
+	default:
+		debug("unexpected element size %u\n", element_size);
+		break;
+	}
+}
+
+static void fsl_ddr_spd_edit(fsl_ddr_info_t *pinfo,
+		       unsigned int ctrl_num,
+		       unsigned int dimm_num,
+		       unsigned int element_num,
+		       unsigned int value)
+{
+	generic_spd_eeprom_t *pspd;
+
+	pspd = &(pinfo->spd_installed_dimms[ctrl_num][dimm_num]);
+	fsl_ddr_generic_edit(pspd, pspd + 1,
+				   sizeof(char), element_num, value);
+}
+#define OPTIONS_UNIT(x) {#x, offsetof(common_timing_params_t, x)}
+static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
+					unsigned int ctrl_num,
+					const char *optname_str,
+					const char *value_str)
+{
+	common_timing_params_t *p = &pinfo->common_timing_params[ctrl_num];
+
+	static const options_strings_t options_uint[] = {
+		OPTIONS_UNIT(tCKmin_X_ps),
+		OPTIONS_UNIT(tCKmax_ps),
+		OPTIONS_UNIT(tCKmax_max_ps),
+		OPTIONS_UNIT(tRCD_ps),
+		OPTIONS_UNIT(tRP_ps),
+		OPTIONS_UNIT(tRAS_ps),
+		OPTIONS_UNIT(tWR_ps),
+		OPTIONS_UNIT(tWTR_ps),
+		OPTIONS_UNIT(tRFC_ps),
+		OPTIONS_UNIT(tRRD_ps),
+		OPTIONS_UNIT(tRC_ps),
+		OPTIONS_UNIT(refresh_rate_ps),
+		OPTIONS_UNIT(tIS_ps),
+		OPTIONS_UNIT(tIH_ps),
+		OPTIONS_UNIT(tDS_ps),
+		OPTIONS_UNIT(tDH_ps),
+		OPTIONS_UNIT(tRTP_ps),
+		OPTIONS_UNIT(tDQSQ_max_ps),
+		OPTIONS_UNIT(tQHS_ps),
+		OPTIONS_UNIT(ndimms_present),
+		OPTIONS_UNIT(lowest_common_SPD_caslat),
+		OPTIONS_UNIT(highest_common_derated_caslat),
+		OPTIONS_UNIT(additive_latency),
+		OPTIONS_UNIT(all_DIMMs_burst_lengths_bitmask),
+		OPTIONS_UNIT(all_DIMMs_registered),
+		OPTIONS_UNIT(all_DIMMs_unbuffered),
+		OPTIONS_UNIT(all_DIMMs_ECC_capable),
+	};
+
+	static const unsigned int n_uint_opts = ARRAY_SIZE(options_uint);
+
+	static const options_strings_t options_ull[] = {
+		OPTIONS_UNIT(total_mem),
+		OPTIONS_UNIT(base_address),
+	};
+
+	static const unsigned int n_ull_opts = ARRAY_SIZE(options_ull);
+
+	if (handle_uint_option_table(options_uint, n_uint_opts, (u32) p,
+				     optname_str, value_str))
+		return;
+
+	if (handle_ull_option_table(options_ull, n_ull_opts, (u32) p,
+				    optname_str, value_str))
+		return;
+
+	printf("Error: couldn't find option string %s\n", optname_str);
+}
+
+#undef OPTIONS_UNIT
+#define OPTIONS_UNIT(x) {#x, offsetof(dimm_params_t, x)}
+
+static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
+				   unsigned int ctrl_num,
+				   unsigned int dimm_num,
+				   const char *optname_str,
+				   const char *value_str)
+{
+	dimm_params_t *p = &(pinfo->dimm_params[ctrl_num][dimm_num]);
+
+	static const options_strings_t options_uint[] = {
+		OPTIONS_UNIT(n_ranks),
+		OPTIONS_UNIT(data_width),
+		OPTIONS_UNIT(primary_sdram_width),
+		OPTIONS_UNIT(ec_sdram_width),
+		OPTIONS_UNIT(registered_dimm),
+
+		OPTIONS_UNIT(n_row_addr),
+		OPTIONS_UNIT(n_col_addr),
+		OPTIONS_UNIT(edc_config),
+		OPTIONS_UNIT(n_banks_per_sdram_device),
+		OPTIONS_UNIT(burst_lengths_bitmask),
+		OPTIONS_UNIT(row_density),
+
+		OPTIONS_UNIT(tCKmin_X_ps),
+		OPTIONS_UNIT(tCKmin_X_minus_1_ps),
+		OPTIONS_UNIT(tCKmin_X_minus_2_ps),
+		OPTIONS_UNIT(tCKmax_ps),
+
+		OPTIONS_UNIT(caslat_X),
+		OPTIONS_UNIT(caslat_X_minus_1),
+		OPTIONS_UNIT(caslat_X_minus_2),
+
+		OPTIONS_UNIT(caslat_lowest_derated),
+
+		OPTIONS_UNIT(tRCD_ps),
+		OPTIONS_UNIT(tRP_ps),
+		OPTIONS_UNIT(tRAS_ps),
+		OPTIONS_UNIT(tWR_ps),
+		OPTIONS_UNIT(tWTR_ps),
+		OPTIONS_UNIT(tRFC_ps),
+		OPTIONS_UNIT(tRRD_ps),
+		OPTIONS_UNIT(tRC_ps),
+		OPTIONS_UNIT(refresh_rate_ps),
+
+		OPTIONS_UNIT(tIS_ps),
+		OPTIONS_UNIT(tIH_ps),
+		OPTIONS_UNIT(tDS_ps),
+		OPTIONS_UNIT(tDH_ps),
+		OPTIONS_UNIT(tRTP_ps),
+		OPTIONS_UNIT(tDQSQ_max_ps),
+		OPTIONS_UNIT(tQHS_ps),
+	};
+
+	static const unsigned int n_uint_opts = ARRAY_SIZE(options_uint);
+
+	static const options_strings_t options_ull[] = {
+		OPTIONS_UNIT(rank_density),
+		OPTIONS_UNIT(capacity),
+		OPTIONS_UNIT(base_address),
+	};
+
+	static const unsigned int n_ull_opts = ARRAY_SIZE(options_ull);
+
+	if (handle_uint_option_table(options_uint, n_uint_opts, (u32) p,
+				     optname_str, value_str))
+		return;
+
+	if (handle_ull_option_table(options_ull, n_ull_opts, (u32) p,
+				    optname_str, value_str))
+		return;
+
+	printf("couldn't find option string %s\n", optname_str);
+}
+
+static void print_dimm_parameters(const dimm_params_t *pdimm)
+{
+	if (pdimm->n_ranks == 0) {
+		printf("DIMM not present\n");
+		return;
+	}
+
+	printf("DIMM organization parameters:\n");
+
+	printf("module part name = %s\n", pdimm->mpart);
+	printf("n_ranks = %u\n", pdimm->n_ranks);
+	printf("rank_density = %llu bytes (%llu megabytes)\n",
+	       pdimm->rank_density, pdimm->rank_density / 0x100000);
+	printf("capacity = %llu bytes (%llu megabytes)\n",
+	       pdimm->capacity, pdimm->capacity / 0x100000);
+	printf("data_width = %u\n", pdimm->data_width);
+	printf("primary_sdram_width = %u\n", pdimm->primary_sdram_width);
+	printf("ec_sdram_width = %u\n", pdimm->ec_sdram_width);
+	printf("registered_dimm = %u\n", pdimm->registered_dimm);
+
+	printf("SDRAM device parameters:\n");
+	printf("n_row_addr = %u\n", pdimm->n_row_addr);
+	printf("n_col_addr = %u\n", pdimm->n_col_addr);
+	printf("edc_config = %u\n", pdimm->edc_config);
+	printf("n_banks_per_sdram_device = %u\n",
+	       pdimm->n_banks_per_sdram_device);
+	printf("burst_lengths_bitmask = %02X\n",
+	       pdimm->burst_lengths_bitmask);
+
+	printf("base_addresss = %llu (%08llX %08llX)\n",
+	       pdimm->base_address,
+	       (pdimm->base_address >> 32),
+	       pdimm->base_address & 0xFFFFFFFF);
+
+	printf("SDRAM clock periods:\n");
+	printf("tCKmin_X_ps = %u ps\n", pdimm->tCKmin_X_ps);
+	printf("tCKmin_X_minus_1_ps = %u ps\n", pdimm->tCKmin_X_minus_1_ps);
+	printf("tCKmin_X_minus_2_ps = %u ps\n", pdimm->tCKmin_X_minus_2_ps);
+	printf("tCKmax_ps = %u ps\n", pdimm->tCKmax_ps);
+
+	printf("SDRAM CAS latencies:\n");
+	printf("caslat_X = %u\n", pdimm->caslat_X);
+	printf("caslat_X_minus_1 = %u\n", pdimm->caslat_X_minus_1);
+	printf("caslat_X_minus_2 = %u\n", pdimm->caslat_X_minus_2);
+	printf("caslat_lowest_derated = %u\n", pdimm->caslat_lowest_derated);
+
+	printf("SDRAM timing parameters:\n");
+	printf("tRCD_ps = %u\n", pdimm->tRCD_ps);
+	printf("tRP_ps = %u\n",  pdimm->tRP_ps);
+	printf("tRAS_ps = %u\n", pdimm->tRAS_ps);
+	printf("tWR_ps = %u\n",  pdimm->tWR_ps);
+	printf("tWTR_ps = %u\n", pdimm->tWTR_ps);
+	printf("tRFC_ps = %u\n", pdimm->tRFC_ps);
+	printf("tRC_ps = %u\n",  pdimm->tRC_ps);
+	printf("tRRD_ps = %u\n", pdimm->tRRD_ps);
+	printf("refresh_rate_ps = %u\n", pdimm->refresh_rate_ps);
+
+	printf("SDRAM even more timing parameters:\n");
+	printf("tIS_ps = %u\n", pdimm->tIS_ps);
+	printf("tIH_ps = %u\n", pdimm->tIH_ps);
+	printf("tDS_ps = %u\n", pdimm->tDS_ps);
+	printf("tDH_ps = %u\n", pdimm->tDH_ps);
+	printf("tRTP_ps = %u\n", pdimm->tRTP_ps);
+	printf("tDQSQ_max_ps = %u\n", pdimm->tDQSQ_max_ps);
+	printf("tQHS_ps = %u\n", pdimm->tQHS_ps);
+}
+
+static void print_lowest_common_dimm_parameters(
+		const common_timing_params_t *plcd_dimm_params)
+{
+
+	/* Clock frequencies */
+	printf("tCKmin_X_ps = %u (%u MHz)\n",
+	       plcd_dimm_params->tCKmin_X_ps,
+	       picos_to_mhz(plcd_dimm_params->tCKmin_X_ps));
+	printf("tCKmax_ps = %u (%u MHz)\n",
+	       plcd_dimm_params->tCKmax_ps,
+	       picos_to_mhz(plcd_dimm_params->tCKmax_ps));
+	printf("tCKmax_max_ps = %u\n", plcd_dimm_params->tCKmax_max_ps);
+
+	/* Basic timing parameters */
+	printf("tRCD_ps = %u\n", plcd_dimm_params->tRCD_ps);
+	printf("tRP_ps = %u\n", plcd_dimm_params->tRP_ps);
+	printf("tRAS_ps = %u\n", plcd_dimm_params->tRAS_ps);
+
+	/* maximum = 63750 ps */
+	printf("tWR_ps = %u\n", plcd_dimm_params->tWR_ps);
+
+	/* maximum = 63750 ps */
+	printf("tWTR_ps = %u\n", plcd_dimm_params->tWTR_ps);
+
+	/* maximum = 255 ns + 256 ns + .75 ns = 511750 ps */
+	printf("tRFC_ps = %u\n", plcd_dimm_params->tRFC_ps);
+
+	/* maximum = 63750 ps */
+	printf("tRRD_ps = %u\n", plcd_dimm_params->tRRD_ps);
+
+	/* maximum = 254 ns + .75 ns = 254750 ps */
+	printf("tRC_ps = %u\n", plcd_dimm_params->tRC_ps);
+
+	printf("refresh_rate_ps = %u\n", plcd_dimm_params->refresh_rate_ps);
+
+	/* byte 32, spd->ca_setup */
+	printf("tIS_ps = %u\n", plcd_dimm_params->tIS_ps);
+	/* byte 33, spd->ca_hold */
+	printf("tIH_ps = %u\n", plcd_dimm_params->tIH_ps);
+	/* byte 34, spd->data_setup */
+	printf("tDS_ps = %u\n", plcd_dimm_params->tDS_ps);
+	/* byte 35, spd->data_hold */
+	printf("tDH_ps = %u\n", plcd_dimm_params->tDH_ps);
+	/* byte 38, spd->trtp */
+	printf("tRTP_ps = %u\n", plcd_dimm_params->tRTP_ps);
+	/* byte 44, spd->tdqsq */
+	printf("tDQSQ_max_ps = %u\n", plcd_dimm_params->tDQSQ_max_ps);
+	/* byte 45, spd->tqhs */
+	printf("tQHS_ps = %u\n", plcd_dimm_params->tQHS_ps);
+
+	printf("lowest_common_SPD_caslat = %u\n",
+	       plcd_dimm_params->lowest_common_SPD_caslat);
+	printf("highest_common_derated_caslat = %u\n",
+	       plcd_dimm_params->highest_common_derated_caslat);
+	printf("additive_latency = %u\n", plcd_dimm_params->additive_latency);
+
+	printf("ndimms_present = %u\n", plcd_dimm_params->ndimms_present);
+	printf("all_DIMMs_burst_lengths_bitmask = %02X\n",
+	       plcd_dimm_params->all_DIMMs_burst_lengths_bitmask);
+	printf("all_DIMMs_registered = %u\n",
+	       plcd_dimm_params->all_DIMMs_registered);
+	printf("all_DIMMs_unbuffered = %u\n",
+	       plcd_dimm_params->all_DIMMs_unbuffered);
+	printf("all_DIMMs_ECC_capable = %u\n",
+	       plcd_dimm_params->all_DIMMs_ECC_capable);
+
+	printf("total_mem = %llu (%llu megabytes)\n",
+	       plcd_dimm_params->total_mem,
+	       plcd_dimm_params->total_mem / 0x100000);
+	printf("base_address = %llu (%llu megabytes)\n",
+	       plcd_dimm_params->base_address,
+	       plcd_dimm_params->base_address / 0x100000);
+}
+
+#undef OPTIONS_UNIT
+#define OPTIONS_UNIT(x) {#x, offsetof(memctl_options_t, x)}
+
+static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
+			   unsigned int ctl_num,
+			   const char *optname_str,
+			   const char *value_str)
+{
+	memctl_options_t *p = &(pinfo->memctl_opts[ctl_num]);
+	/*
+	 * This array all on the stack and *computed* each time this
+	 * function is rung.
+	 */
+	static const options_strings_t options[] = {
+		{"cs0_odt_rd_cfg", offsetof(memctl_options_t, cs_local_opts[0].odt_rd_cfg)},
+		{"cs0_odt_wr_cfg", offsetof(memctl_options_t, cs_local_opts[0].odt_wr_cfg)},
+		{"cs0_odt_rtt_norm", offsetof(memctl_options_t, cs_local_opts[0].odt_rtt_norm)},
+		{"cs0_odt_rtt_wr", offsetof(memctl_options_t, cs_local_opts[0].odt_rtt_wr)},
+		{"cs1_odt_rd_cfg", offsetof(memctl_options_t, cs_local_opts[1].odt_rd_cfg)},
+		{"cs1_odt_wr_cfg", offsetof(memctl_options_t, cs_local_opts[1].odt_wr_cfg)},
+		{"cs1_odt_rtt_norm", offsetof(memctl_options_t, cs_local_opts[1].odt_rtt_norm)},
+		{"cs1_odt_rtt_wr", offsetof(memctl_options_t, cs_local_opts[1].odt_rtt_wr)},
+		{"cs2_odt_rd_cfg", offsetof(memctl_options_t, cs_local_opts[2].odt_rd_cfg)},
+		{"cs2_odt_wr_cfg", offsetof(memctl_options_t, cs_local_opts[2].odt_wr_cfg)},
+		{"cs2_odt_rtt_norm", offsetof(memctl_options_t, cs_local_opts[2].odt_rtt_norm)},
+		{"cs2_odt_rtt_wr", offsetof(memctl_options_t, cs_local_opts[2].odt_rtt_wr)},
+		{"cs3_odt_rd_cfg", offsetof(memctl_options_t, cs_local_opts[3].odt_rd_cfg)},
+		{"cs3_odt_wr_cfg", offsetof(memctl_options_t, cs_local_opts[3].odt_wr_cfg)},
+		{"cs3_odt_rtt_norm", offsetof(memctl_options_t, cs_local_opts[3].odt_rtt_norm)},
+		{"cs3_odt_rtt_wr", offsetof(memctl_options_t, cs_local_opts[3].odt_rtt_wr)},
+		OPTIONS_UNIT(memctl_interleaving),
+		OPTIONS_UNIT(memctl_interleaving_mode),
+		OPTIONS_UNIT(ba_intlv_ctl),
+		OPTIONS_UNIT(ECC_mode),
+		OPTIONS_UNIT(ECC_init_using_memctl),
+		OPTIONS_UNIT(DQS_config),
+		OPTIONS_UNIT(self_refresh_in_sleep),
+		OPTIONS_UNIT(dynamic_power),
+		OPTIONS_UNIT(data_bus_width),
+		OPTIONS_UNIT(burst_length),
+		OPTIONS_UNIT(cas_latency_override),
+		OPTIONS_UNIT(cas_latency_override_value),
+		OPTIONS_UNIT(use_derated_caslat),
+		OPTIONS_UNIT(additive_latency_override),
+		OPTIONS_UNIT(additive_latency_override_value),
+		OPTIONS_UNIT(clk_adjust),
+		OPTIONS_UNIT(cpo_override),
+		OPTIONS_UNIT(write_data_delay),
+		OPTIONS_UNIT(half_strength_driver_enable),
+
+		/*
+		 * These can probably be changed to 2T_EN and 3T_EN
+		 * (using a leading numerical character) without problem
+		 */
+		OPTIONS_UNIT(twoT_en),
+		OPTIONS_UNIT(threeT_en),
+		OPTIONS_UNIT(ap_en),
+		OPTIONS_UNIT(bstopre),
+		OPTIONS_UNIT(wrlvl_override),
+		OPTIONS_UNIT(wrlvl_sample),
+		OPTIONS_UNIT(wrlvl_start),
+		OPTIONS_UNIT(rcw_override),
+		OPTIONS_UNIT(rcw_1),
+		OPTIONS_UNIT(rcw_2),
+		OPTIONS_UNIT(tCKE_clock_pulse_width_ps),
+		OPTIONS_UNIT(tFAW_window_four_activates_ps),
+	};
+
+	static const unsigned int nopts = ARRAY_SIZE(options);
+
+	if (handle_uint_option_table(options, nopts, (u32) p,
+					optname_str, value_str))
+		return;
+
+	printf("couldn't find option string %s\n", optname_str);
+}
+
+static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned int i;
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		printf("cs%u_bnds           = %08X\n", i, ddr->cs[i].bnds);
+		printf("cs%u_config         = %08X\n", i, ddr->cs[i].config);
+		printf("cs%u_config_2       = %08X\n", i, ddr->cs[i].config_2);
+	}
+
+	printf("timing_cfg_3       = %08X\n", ddr->timing_cfg_3);
+	printf("timing_cfg_0       = %08X\n", ddr->timing_cfg_0);
+	printf("timing_cfg_1       = %08X\n", ddr->timing_cfg_1);
+	printf("timing_cfg_2       = %08X\n", ddr->timing_cfg_2);
+	printf("ddr_sdram_cfg      = %08X\n", ddr->ddr_sdram_cfg);
+	printf("ddr_sdram_cfg_2    = %08X\n", ddr->ddr_sdram_cfg_2);
+	printf("ddr_sdram_mode     = %08X\n", ddr->ddr_sdram_mode);
+	printf("ddr_sdram_mode_2   = %08X\n", ddr->ddr_sdram_mode_2);
+	printf("ddr_sdram_mode_3   = %08X\n", ddr->ddr_sdram_mode_3);
+	printf("ddr_sdram_mode_4   = %08X\n", ddr->ddr_sdram_mode_4);
+	printf("ddr_sdram_mode_5   = %08X\n", ddr->ddr_sdram_mode_5);
+	printf("ddr_sdram_mode_6   = %08X\n", ddr->ddr_sdram_mode_6);
+	printf("ddr_sdram_mode_7   = %08X\n", ddr->ddr_sdram_mode_7);
+	printf("ddr_sdram_mode_8   = %08X\n", ddr->ddr_sdram_mode_8);
+	printf("ddr_sdram_interval = %08X\n", ddr->ddr_sdram_interval);
+	printf("ddr_data_init      = %08X\n", ddr->ddr_data_init);
+	printf("ddr_sdram_clk_cntl = %08X\n", ddr->ddr_sdram_clk_cntl);
+	printf("ddr_init_addr      = %08X\n", ddr->ddr_init_addr);
+	printf("ddr_init_ext_addr  = %08X\n", ddr->ddr_init_ext_addr);
+	printf("timing_cfg_4       = %08X\n", ddr->timing_cfg_4);
+	printf("timing_cfg_5       = %08X\n", ddr->timing_cfg_5);
+	printf("ddr_zq_cntl        = %08X\n", ddr->ddr_zq_cntl);
+	printf("ddr_wrlvl_cntl     = %08X\n", ddr->ddr_wrlvl_cntl);
+	printf("ddr_sr_cntr        = %08X\n", ddr->ddr_sr_cntr);
+	printf("ddr_sdram_rcw_1    = %08X\n", ddr->ddr_sdram_rcw_1);
+	printf("ddr_sdram_rcw_2    = %08X\n", ddr->ddr_sdram_rcw_2);
+	printf("ddr_cdr1           = %08X\n", ddr->ddr_cdr1);
+	printf("ddr_cdr2           = %08X\n", ddr->ddr_cdr2);
+	printf("err_disable        = %08X\n", ddr->err_disable);
+	printf("err_int_en         = %08X\n", ddr->err_int_en);
+	for (i = 0; i < 18; i++)
+		printf("debug_%02d	= %08X\n", i+1, ddr->debug[i]);
+}
+
+static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
+			unsigned int ctrl_num,
+			const char *regname,
+			unsigned int value)
+{
+	unsigned int i;
+	fsl_ddr_cfg_regs_t *ddr;
+	char buf[20];
+
+	debug("fsl_ddr_regs_edit: ctrl_num = %u, "
+		"regname = %s, value = 0x%08X\n",
+		ctrl_num, regname, value);
+	if (ctrl_num > CONFIG_NUM_DDR_CONTROLLERS)
+		return;
+
+	/* FIXME: Change this into struct like the other editing functions */
+	ddr = &(pinfo->fsl_ddr_config_reg[ctrl_num]);
+
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		sprintf(buf, "cs%u_bnds", i);
+		if (strcmp(buf, regname) == 0) {
+			ddr->cs[i].bnds = value;
+			return;
+		}
+
+		sprintf(buf, "cs%u_config", i);
+		if (strcmp(buf, regname) == 0) {
+			ddr->cs[i].config = value;
+			return;
+		}
+
+		sprintf(buf, "cs%u_config_2", i);
+		if (strcmp(buf, regname) == 0) {
+			ddr->cs[i].config_2 = value;
+			return;
+		}
+	}
+
+	if (strcmp("timing_cfg_3", regname) == 0) {
+		ddr->timing_cfg_3 = value;
+		return;
+	}
+
+	if (strcmp("timing_cfg_0", regname) == 0) {
+		ddr->timing_cfg_0 = value;
+		return;
+	}
+
+	if (strcmp("timing_cfg_1", regname) == 0) {
+		ddr->timing_cfg_1 = value;
+		return;
+	}
+
+	if (strcmp("timing_cfg_2", regname) == 0) {
+		ddr->timing_cfg_2 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_cfg", regname) == 0) {
+		ddr->ddr_sdram_cfg = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_cfg_2", regname) == 0) {
+		ddr->ddr_sdram_cfg_2 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_mode", regname) == 0) {
+		ddr->ddr_sdram_mode = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_mode_2", regname) == 0) {
+		ddr->ddr_sdram_mode_2 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_mode_3", regname) == 0) {
+		ddr->ddr_sdram_mode_3 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_mode_4", regname) == 0) {
+		ddr->ddr_sdram_mode_4 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_mode_5", regname) == 0) {
+		ddr->ddr_sdram_mode_5 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_mode_6", regname) == 0) {
+		ddr->ddr_sdram_mode_6 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_mode_7", regname) == 0) {
+		ddr->ddr_sdram_mode_7 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_mode_8", regname) == 0) {
+		ddr->ddr_sdram_mode_8 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_interval", regname) == 0) {
+		ddr->ddr_sdram_interval = value;
+		return;
+	}
+
+	if (strcmp("ddr_data_init", regname) == 0) {
+		ddr->ddr_data_init = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_clk_cntl", regname) == 0) {
+		ddr->ddr_sdram_clk_cntl = value;
+		return;
+	}
+
+	if (strcmp("ddr_init_addr", regname) == 0) {
+		ddr->ddr_init_addr = value;
+		return;
+	}
+
+	if (strcmp("ddr_init_ext_addr", regname) == 0) {
+		ddr->ddr_init_ext_addr = value;
+		return;
+	}
+
+	if (strcmp("timing_cfg_4", regname) == 0) {
+		ddr->timing_cfg_4 = value;
+		return;
+	}
+
+	if (strcmp("timing_cfg_5", regname) == 0) {
+		ddr->timing_cfg_5 = value;
+		return;
+	}
+
+	if (strcmp("ddr_zq_cntl", regname) == 0) {
+		ddr->ddr_zq_cntl = value;
+		return;
+	}
+
+	if (strcmp("ddr_wrlvl_cntl", regname) == 0) {
+		ddr->ddr_wrlvl_cntl = value;
+		return;
+	}
+
+	if (strcmp("ddr_sr_cntr", regname) == 0) {
+		ddr->ddr_sr_cntr = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_rcw_1", regname) == 0) {
+		ddr->ddr_sdram_rcw_1 = value;
+		return;
+	}
+
+	if (strcmp("ddr_sdram_rcw_2", regname) == 0) {
+		ddr->ddr_sdram_rcw_2 = value;
+		return;
+	}
+
+	if (strcmp("ddr_cdr1", regname) == 0) {
+		ddr->ddr_cdr1 = value;
+		return;
+	}
+
+	if (strcmp("ddr_cdr2", regname) == 0) {
+		ddr->ddr_cdr2 = value;
+		return;
+	}
+
+	if (strcmp("err_disable", regname) == 0) {
+		ddr->err_disable = value;
+		return;
+	}
+
+	if (strcmp("err_int_en", regname) == 0) {
+		ddr->err_int_en = value;
+		return;
+	}
+
+	for (i = 0; i < 18; i++) {
+		sprintf(buf, "debug_%u", i + 1);
+		if (strcmp(buf, regname) == 0) {
+			ddr->debug[i] = value;
+			return;
+		}
+	}
+}
+
+static void print_memctl_options(const memctl_options_t *popts)
+{
+	int i;
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		printf("cs%d_odt_rd_cfg = %u\n", i, popts->cs_local_opts[i].odt_rd_cfg);
+		printf("cs%d_odt_wr_cfg = %u\n", i, popts->cs_local_opts[i].odt_wr_cfg);
+#if defined(CONFIG_FSL_DDR3)
+		printf("cs%d_odt_rtt_norm = %u\n", i, popts->cs_local_opts[i].odt_rtt_norm);
+		printf("cs%d_odt_rtt_wr = %u\n", i, popts->cs_local_opts[i].odt_rtt_wr);
+#endif
+	}
+	/* Special configurations for chip select */
+	printf("memctl_interleaving = %u\n", popts->memctl_interleaving);
+	printf("memctl_interleaving_mode = %u\n",
+	       popts->memctl_interleaving_mode);
+	printf("ba_intlv_ctl = 0x%02X\n", popts->ba_intlv_ctl);
+
+	printf("ECC_mode = %u\n", popts->ECC_mode);	 /* Use ECC? */
+
+	/* Initialize ECC using memory controller? */
+	printf("ECC_init_using_memctl = %u\n", popts->ECC_init_using_memctl);
+
+	/* Use DQS? maybe only with DDR2? */
+	printf("DQS_config = %u\n", popts->DQS_config);
+
+	/* SREN - self-refresh during sleep */
+	printf("self_refresh_in_sleep = %u\n", popts->self_refresh_in_sleep);
+
+	/* DYN_PWR */
+	printf("dynamic_power = %u\n", popts->dynamic_power);
+
+	/* memory data width to use (16-bit, 32-bit, 64-bit) */
+	printf("data_bus_width = %u\n", popts->data_bus_width);
+
+	/* 4, 8 */
+	printf("burst_length = %u\n", popts->burst_length);
+
+	/* Global Timing Parameters */
+	printf("cas_latency_override = %u\n", popts->cas_latency_override);
+	printf("cas_latency_override_value = %u\n",
+	       popts->cas_latency_override_value);
+	printf("use_derated_caslat = %u\n", popts->use_derated_caslat);
+	printf("additive_latency_override = %u\n",
+	       popts->additive_latency_override);
+	printf("additive_latency_override_value = %u\n",
+	       popts->additive_latency_override_value);
+	printf("clk_adjust = %u\n", popts->clk_adjust);
+	printf("cpo_override = %u\n", popts->cpo_override);
+	/* DQS adjust */
+	printf("write_data_delay = %u\n", popts->write_data_delay);
+	printf("half_strength_driver_enable = %u\n",
+	       popts->half_strength_driver_enable);
+	printf("twoT_en = %u\n", popts->twoT_en);
+	printf("threeT_en = %u\n", popts->threeT_en);
+	printf("ap_en = %u\n", popts->ap_en);
+	printf("bstopre = %u\n", popts->bstopre);
+	/* wrlvl */
+	printf("wrlvl_override = %u\n", popts->wrlvl_override);
+	printf("wrlvl_sample = %u\n", popts->wrlvl_sample);
+	printf("wrlvl_start = %u\n", popts->wrlvl_start);
+	/* rcw */
+	printf("rcw_override = %u\n", popts->rcw_override);
+	printf("rcw_1 = 0x%08x\n", popts->rcw_1);
+	printf("rcw_2 = 0x%08x\n", popts->rcw_2);
+	/* tCKE */
+	printf("tCKE_clock_pulse_width_ps = %u\n",
+	       popts->tCKE_clock_pulse_width_ps);
+	/* tFAW --  FOUR_ACT */
+	printf("tFAW_window_four_activates_ps = %u\n",
+	       popts->tFAW_window_four_activates_ps);
+}
+
+#ifdef CONFIG_FSL_DDR1
+void ddr1_spd_dump(const ddr1_spd_eeprom_t *spd)
+{
+	unsigned int i;
+
+	printf("%-3d    : %02x %s\n",
+	       0, spd->info_size,
+	       " spd->info_size,   *  0 # bytes written into serial memory *");
+	printf("%-3d    : %02x %s\n",
+	       1, spd->chip_size,
+	       " spd->chip_size,   *  1 Total # bytes of SPD memory device *");
+	printf("%-3d    : %02x %s\n",
+	       2, spd->mem_type,
+	       " spd->mem_type,    *  2 Fundamental memory type *");
+	printf("%-3d    : %02x %s\n",
+	       3, spd->nrow_addr,
+	       " spd->nrow_addr,   *  3 # of Row Addresses on this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       4, spd->ncol_addr,
+	       " spd->ncol_addr,   *  4 # of Column Addrs on this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       5, spd->nrows,
+	       " spd->nrows        *  5 # of DIMM Banks *");
+	printf("%-3d    : %02x %s\n",
+	       6, spd->dataw_lsb,
+	       " spd->dataw_lsb,   *  6 Data Width lsb of this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       7, spd->dataw_msb,
+	       " spd->dataw_msb,   *  7 Data Width msb of this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       8, spd->voltage,
+	       " spd->voltage,     *  8 Voltage intf std of this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       9, spd->clk_cycle,
+	       " spd->clk_cycle,   *  9 SDRAM Cycle time at CL=X *");
+	printf("%-3d    : %02x %s\n",
+	       10, spd->clk_access,
+	       " spd->clk_access,  * 10 SDRAM Access from Clock at CL=X *");
+	printf("%-3d    : %02x %s\n",
+	       11, spd->config,
+	       " spd->config,      * 11 DIMM Configuration type *");
+	printf("%-3d    : %02x %s\n",
+	       12, spd->refresh,
+	       " spd->refresh,     * 12 Refresh Rate/Type *");
+	printf("%-3d    : %02x %s\n",
+	       13, spd->primw,
+	       " spd->primw,       * 13 Primary SDRAM Width *");
+	printf("%-3d    : %02x %s\n",
+	       14, spd->ecw,
+	       " spd->ecw,         * 14 Error Checking SDRAM width *");
+	printf("%-3d    : %02x %s\n",
+	       15, spd->min_delay,
+	       " spd->min_delay,   * 15 Back to Back Random Access *");
+	printf("%-3d    : %02x %s\n",
+	       16, spd->burstl,
+	       " spd->burstl,      * 16 Burst Lengths Supported *");
+	printf("%-3d    : %02x %s\n",
+	       17, spd->nbanks,
+	       " spd->nbanks,      * 17 # of Banks on Each SDRAM Device *");
+	printf("%-3d    : %02x %s\n",
+	       18, spd->cas_lat,
+	       " spd->cas_lat,     * 18 CAS# Latencies Supported *");
+	printf("%-3d    : %02x %s\n",
+	       19, spd->cs_lat,
+	       " spd->cs_lat,      * 19 Chip Select Latency *");
+	printf("%-3d    : %02x %s\n",
+	       20, spd->write_lat,
+	       " spd->write_lat,   * 20 Write Latency/Recovery *");
+	printf("%-3d    : %02x %s\n",
+	       21, spd->mod_attr,
+	       " spd->mod_attr,    * 21 SDRAM Module Attributes *");
+	printf("%-3d    : %02x %s\n",
+	       22, spd->dev_attr,
+	       " spd->dev_attr,    * 22 SDRAM Device Attributes *");
+	printf("%-3d    : %02x %s\n",
+	       23, spd->clk_cycle2,
+	       " spd->clk_cycle2,  * 23 Min SDRAM Cycle time at CL=X-1 *");
+	printf("%-3d    : %02x %s\n",
+	       24, spd->clk_access2,
+	       " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *");
+	printf("%-3d    : %02x %s\n",
+	       25, spd->clk_cycle3,
+	       " spd->clk_cycle3,  * 25 Min SDRAM Cycle time at CL=X-2 *");
+	printf("%-3d    : %02x %s\n",
+	       26, spd->clk_access3,
+	       " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *");
+	printf("%-3d    : %02x %s\n",
+	       27, spd->trp,
+	       " spd->trp,         * 27 Min Row Precharge Time (tRP)*");
+	printf("%-3d    : %02x %s\n",
+	       28, spd->trrd,
+	       " spd->trrd,        * 28 Min Row Active to Row Active (tRRD) *");
+	printf("%-3d    : %02x %s\n",
+	       29, spd->trcd,
+	       " spd->trcd,        * 29 Min RAS to CAS Delay (tRCD) *");
+	printf("%-3d    : %02x %s\n",
+	       30, spd->tras,
+	       " spd->tras,        * 30 Minimum RAS Pulse Width (tRAS) *");
+	printf("%-3d    : %02x %s\n",
+	       31, spd->bank_dens,
+	       " spd->bank_dens,   * 31 Density of each bank on module *");
+	printf("%-3d    : %02x %s\n",
+	       32, spd->ca_setup,
+	       " spd->ca_setup,    * 32 Cmd + Addr signal input setup time *");
+	printf("%-3d    : %02x %s\n",
+	       33, spd->ca_hold,
+	       " spd->ca_hold,     * 33 Cmd and Addr signal input hold time *");
+	printf("%-3d    : %02x %s\n",
+	       34, spd->data_setup,
+	       " spd->data_setup,  * 34 Data signal input setup time *");
+	printf("%-3d    : %02x %s\n",
+	       35, spd->data_hold,
+	       " spd->data_hold,   * 35 Data signal input hold time *");
+	printf("%-3d    : %02x %s\n",
+	       36, spd->res_36_40[0],
+	       " spd->res_36_40[0], * 36 Reserved / tWR *");
+	printf("%-3d    : %02x %s\n",
+	       37, spd->res_36_40[1],
+	       " spd->res_36_40[1], * 37 Reserved / tWTR *");
+	printf("%-3d    : %02x %s\n",
+	       38, spd->res_36_40[2],
+	       " spd->res_36_40[2], * 38 Reserved / tRTP *");
+	printf("%-3d    : %02x %s\n",
+	       39, spd->res_36_40[3],
+	       " spd->res_36_40[3], * 39 Reserved / mem_probe *");
+	printf("%-3d    : %02x %s\n",
+	       40, spd->res_36_40[4],
+	       " spd->res_36_40[4], * 40 Reserved / trc,trfc extensions *");
+	printf("%-3d    : %02x %s\n",
+	       41, spd->trc,
+	       " spd->trc,         * 41 Min Active to Auto refresh time tRC *");
+	printf("%-3d    : %02x %s\n",
+	       42, spd->trfc,
+	       " spd->trfc,        * 42 Min Auto to Active period tRFC *");
+	printf("%-3d    : %02x %s\n",
+	       43, spd->tckmax,
+	       " spd->tckmax,      * 43 Max device cycle time tCKmax *");
+	printf("%-3d    : %02x %s\n",
+	       44, spd->tdqsq,
+	       " spd->tdqsq,       * 44 Max DQS to DQ skew *");
+	printf("%-3d    : %02x %s\n",
+	       45, spd->tqhs,
+	       " spd->tqhs,        * 45 Max Read DataHold skew tQHS *");
+	printf("%-3d    : %02x %s\n",
+	       46, spd->res_46,
+	       " spd->res_46,  * 46 Reserved/ PLL Relock time *");
+	printf("%-3d    : %02x %s\n",
+	       47, spd->dimm_height,
+	       " spd->dimm_height  * 47 SDRAM DIMM Height *");
+
+	printf("%-3d-%3d: ",  48, 61);
+
+	for (i = 0; i < 14; i++)
+		printf("%02x", spd->res_48_61[i]);
+
+	printf(" * 48-61 IDD in SPD and Reserved space *\n");
+
+	printf("%-3d    : %02x %s\n",
+	       62, spd->spd_rev,
+	       " spd->spd_rev,     * 62 SPD Data Revision Code *");
+	printf("%-3d    : %02x %s\n",
+	       63, spd->cksum,
+	       " spd->cksum,       * 63 Checksum for bytes 0-62 *");
+	printf("%-3d-%3d: ",  64, 71);
+
+	for (i = 0; i < 8; i++)
+		printf("%02x", spd->mid[i]);
+
+	printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n");
+	printf("%-3d    : %02x %s\n",
+	       72, spd->mloc,
+	       " spd->mloc,        * 72 Manufacturing Location *");
+
+	printf("%-3d-%3d: >>",  73, 90);
+
+	for (i = 0; i < 18; i++)
+		printf("%c", spd->mpart[i]);
+
+	printf("<<* 73 Manufacturer's Part Number *\n");
+
+	printf("%-3d-%3d: %02x %02x %s\n",
+	       91, 92, spd->rev[0], spd->rev[1],
+	       "* 91 Revision Code *");
+	printf("%-3d-%3d: %02x %02x %s\n",
+	       93, 94, spd->mdate[0], spd->mdate[1],
+	       "* 93 Manufacturing Date *");
+	printf("%-3d-%3d: ", 95, 98);
+
+	for (i = 0; i < 4; i++)
+		printf("%02x", spd->sernum[i]);
+
+	printf("* 95 Assembly Serial Number *\n");
+
+	printf("%-3d-%3d: ", 99, 127);
+
+	for (i = 0; i < 27; i++)
+		printf("%02x", spd->mspec[i]);
+
+	printf("* 99 Manufacturer Specific Data *\n");
+}
+#endif
+
+#ifdef CONFIG_FSL_DDR2
+void ddr2_spd_dump(const ddr2_spd_eeprom_t *spd)
+{
+	unsigned int i;
+
+	printf("%-3d    : %02x %s\n",
+	       0, spd->info_size,
+	       " spd->info_size,   *  0 # bytes written into serial memory *");
+	printf("%-3d    : %02x %s\n",
+	       1, spd->chip_size,
+	       " spd->chip_size,   *  1 Total # bytes of SPD memory device *");
+	printf("%-3d    : %02x %s\n",
+	       2, spd->mem_type,
+	       " spd->mem_type,    *  2 Fundamental memory type *");
+	printf("%-3d    : %02x %s\n",
+	       3, spd->nrow_addr,
+	       " spd->nrow_addr,   *  3 # of Row Addresses on this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       4, spd->ncol_addr,
+	       " spd->ncol_addr,   *  4 # of Column Addrs on this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       5, spd->mod_ranks,
+	       " spd->mod_ranks    *  5 # of Module Rows on this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       6, spd->dataw,
+	       " spd->dataw,       *  6 Data Width of this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       7, spd->res_7,
+	       " spd->res_7,       *  7 Reserved *");
+	printf("%-3d    : %02x %s\n",
+	       8, spd->voltage,
+	       " spd->voltage,     *  8 Voltage intf std of this assembly *");
+	printf("%-3d    : %02x %s\n",
+	       9, spd->clk_cycle,
+	       " spd->clk_cycle,   *  9 SDRAM Cycle time at CL=X *");
+	printf("%-3d    : %02x %s\n",
+	       10, spd->clk_access,
+	       " spd->clk_access,  * 10 SDRAM Access from Clock at CL=X *");
+	printf("%-3d    : %02x %s\n",
+	       11, spd->config,
+	       " spd->config,      * 11 DIMM Configuration type *");
+	printf("%-3d    : %02x %s\n",
+	       12, spd->refresh,
+	       " spd->refresh,     * 12 Refresh Rate/Type *");
+	printf("%-3d    : %02x %s\n",
+	       13, spd->primw,
+	       " spd->primw,       * 13 Primary SDRAM Width *");
+	printf("%-3d    : %02x %s\n",
+	       14, spd->ecw,
+	       " spd->ecw,         * 14 Error Checking SDRAM width *");
+	printf("%-3d    : %02x %s\n",
+	       15, spd->res_15,
+	       " spd->res_15,      * 15 Reserved *");
+	printf("%-3d    : %02x %s\n",
+	       16, spd->burstl,
+	       " spd->burstl,      * 16 Burst Lengths Supported *");
+	printf("%-3d    : %02x %s\n",
+	       17, spd->nbanks,
+	       " spd->nbanks,      * 17 # of Banks on Each SDRAM Device *");
+	printf("%-3d    : %02x %s\n",
+	       18, spd->cas_lat,
+	       " spd->cas_lat,     * 18 CAS# Latencies Supported *");
+	printf("%-3d    : %02x %s\n",
+	       19, spd->mech_char,
+	       " spd->mech_char,   * 19 Mechanical Characteristics *");
+	printf("%-3d    : %02x %s\n",
+	       20, spd->dimm_type,
+	       " spd->dimm_type,   * 20 DIMM type *");
+	printf("%-3d    : %02x %s\n",
+	       21, spd->mod_attr,
+	       " spd->mod_attr,    * 21 SDRAM Module Attributes *");
+	printf("%-3d    : %02x %s\n",
+	       22, spd->dev_attr,
+	       " spd->dev_attr,    * 22 SDRAM Device Attributes *");
+	printf("%-3d    : %02x %s\n",
+	       23, spd->clk_cycle2,
+	       " spd->clk_cycle2,  * 23 Min SDRAM Cycle time at CL=X-1 *");
+	printf("%-3d    : %02x %s\n",
+	       24, spd->clk_access2,
+	       " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *");
+	printf("%-3d    : %02x %s\n",
+	       25, spd->clk_cycle3,
+	       " spd->clk_cycle3,  * 25 Min SDRAM Cycle time at CL=X-2 *");
+	printf("%-3d    : %02x %s\n",
+	       26, spd->clk_access3,
+	       " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *");
+	printf("%-3d    : %02x %s\n",
+	       27, spd->trp,
+	       " spd->trp,         * 27 Min Row Precharge Time (tRP)*");
+	printf("%-3d    : %02x %s\n",
+	       28, spd->trrd,
+	       " spd->trrd,        * 28 Min Row Active to Row Active (tRRD) *");
+	printf("%-3d    : %02x %s\n",
+	       29, spd->trcd,
+	       " spd->trcd,        * 29 Min RAS to CAS Delay (tRCD) *");
+	printf("%-3d    : %02x %s\n",
+	       30, spd->tras,
+	       " spd->tras,        * 30 Minimum RAS Pulse Width (tRAS) *");
+	printf("%-3d    : %02x %s\n",
+	       31, spd->rank_dens,
+	       " spd->rank_dens,   * 31 Density of each rank on module *");
+	printf("%-3d    : %02x %s\n",
+	       32, spd->ca_setup,
+	       " spd->ca_setup,    * 32 Cmd + Addr signal input setup time *");
+	printf("%-3d    : %02x %s\n",
+	       33, spd->ca_hold,
+	       " spd->ca_hold,     * 33 Cmd and Addr signal input hold time *");
+	printf("%-3d    : %02x %s\n",
+	       34, spd->data_setup,
+	       " spd->data_setup,  * 34 Data signal input setup time *");
+	printf("%-3d    : %02x %s\n",
+	       35, spd->data_hold,
+	       " spd->data_hold,   * 35 Data signal input hold time *");
+	printf("%-3d    : %02x %s\n",
+	       36, spd->twr,
+	       " spd->twr,         * 36 Write Recovery time tWR *");
+	printf("%-3d    : %02x %s\n",
+	       37, spd->twtr,
+	       " spd->twtr,        * 37 Int write to read delay tWTR *");
+	printf("%-3d    : %02x %s\n",
+	       38, spd->trtp,
+	       " spd->trtp,        * 38 Int read to precharge delay tRTP *");
+	printf("%-3d    : %02x %s\n",
+	       39, spd->mem_probe,
+	       " spd->mem_probe,   * 39 Mem analysis probe characteristics *");
+	printf("%-3d    : %02x %s\n",
+	       40, spd->trctrfc_ext,
+	       " spd->trctrfc_ext, * 40 Extensions to trc and trfc *");
+	printf("%-3d    : %02x %s\n",
+	       41, spd->trc,
+	       " spd->trc,         * 41 Min Active to Auto refresh time tRC *");
+	printf("%-3d    : %02x %s\n",
+	       42, spd->trfc,
+	       " spd->trfc,        * 42 Min Auto to Active period tRFC *");
+	printf("%-3d    : %02x %s\n",
+	       43, spd->tckmax,
+	       " spd->tckmax,      * 43 Max device cycle time tCKmax *");
+	printf("%-3d    : %02x %s\n",
+	       44, spd->tdqsq,
+	       " spd->tdqsq,       * 44 Max DQS to DQ skew *");
+	printf("%-3d    : %02x %s\n",
+	       45, spd->tqhs,
+	       " spd->tqhs,        * 45 Max Read DataHold skew tQHS *");
+	printf("%-3d    : %02x %s\n",
+	       46, spd->pll_relock,
+	       " spd->pll_relock,  * 46 PLL Relock time *");
+	printf("%-3d    : %02x %s\n",
+	       47, spd->Tcasemax,
+	       " spd->Tcasemax,    * 47 Tcasemax *");
+	printf("%-3d    : %02x %s\n",
+	       48, spd->psiTAdram,
+	       " spd->psiTAdram,   * 48 Thermal Resistance of DRAM Package "
+	       "from Top (Case) to Ambient (Psi T-A DRAM) *");
+	printf("%-3d    : %02x %s\n",
+	       49, spd->dt0_mode,
+	       " spd->dt0_mode,    * 49 DRAM Case Temperature Rise from "
+	       "Ambient due to Activate-Precharge/Mode Bits "
+	       "(DT0/Mode Bits) *)");
+	printf("%-3d    : %02x %s\n",
+	       50, spd->dt2n_dt2q,
+	       " spd->dt2n_dt2q,   * 50 DRAM Case Temperature Rise from "
+	       "Ambient due to Precharge/Quiet Standby "
+	       "(DT2N/DT2Q) *");
+	printf("%-3d    : %02x %s\n",
+	       51, spd->dt2p,
+	       " spd->dt2p,        * 51 DRAM Case Temperature Rise from "
+	       "Ambient due to Precharge Power-Down (DT2P) *");
+	printf("%-3d    : %02x %s\n",
+	       52, spd->dt3n,
+	       " spd->dt3n,        * 52 DRAM Case Temperature Rise from "
+	       "Ambient due to Active Standby (DT3N) *");
+	printf("%-3d    : %02x %s\n",
+	       53, spd->dt3pfast,
+	       " spd->dt3pfast,    * 53 DRAM Case Temperature Rise from "
+	       "Ambient due to Active Power-Down with Fast PDN Exit "
+	       "(DT3Pfast) *");
+	printf("%-3d    : %02x %s\n",
+	       54, spd->dt3pslow,
+	       " spd->dt3pslow,    * 54 DRAM Case Temperature Rise from "
+	       "Ambient due to Active Power-Down with Slow PDN Exit "
+	       "(DT3Pslow) *");
+	printf("%-3d    : %02x %s\n",
+	       55, spd->dt4r_dt4r4w,
+	       " spd->dt4r_dt4r4w, * 55 DRAM Case Temperature Rise from "
+	       "Ambient due to Page Open Burst Read/DT4R4W Mode Bit "
+	       "(DT4R/DT4R4W Mode Bit) *");
+	printf("%-3d    : %02x %s\n",
+	       56, spd->dt5b,
+	       " spd->dt5b,        * 56 DRAM Case Temperature Rise from "
+	       "Ambient due to Burst Refresh (DT5B) *");
+	printf("%-3d    : %02x %s\n",
+	       57, spd->dt7,
+	       " spd->dt7,         * 57 DRAM Case Temperature Rise from "
+	       "Ambient due to Bank Interleave Reads with "
+	       "Auto-Precharge (DT7) *");
+	printf("%-3d    : %02x %s\n",
+	       58, spd->psiTApll,
+	       " spd->psiTApll,    * 58 Thermal Resistance of PLL Package form"
+	       " Top (Case) to Ambient (Psi T-A PLL) *");
+	printf("%-3d    : %02x %s\n",
+	       59, spd->psiTAreg,
+	       " spd->psiTAreg,    * 59 Thermal Reisitance of Register Package"
+	       " from Top (Case) to Ambient (Psi T-A Register) *");
+	printf("%-3d    : %02x %s\n",
+	       60, spd->dtpllactive,
+	       " spd->dtpllactive, * 60 PLL Case Temperature Rise from "
+	       "Ambient due to PLL Active (DT PLL Active) *");
+	printf("%-3d    : %02x %s\n",
+	       61, spd->dtregact,
+	       " spd->dtregact,    "
+	       "* 61 Register Case Temperature Rise from Ambient due to "
+	       "Register Active/Mode Bit (DT Register Active/Mode Bit) *");
+	printf("%-3d    : %02x %s\n",
+	       62, spd->spd_rev,
+	       " spd->spd_rev,     * 62 SPD Data Revision Code *");
+	printf("%-3d    : %02x %s\n",
+	       63, spd->cksum,
+	       " spd->cksum,       * 63 Checksum for bytes 0-62 *");
+
+	printf("%-3d-%3d: ",  64, 71);
+
+	for (i = 0; i < 8; i++)
+		printf("%02x", spd->mid[i]);
+
+	printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n");
+
+	printf("%-3d    : %02x %s\n",
+	       72, spd->mloc,
+	       " spd->mloc,        * 72 Manufacturing Location *");
+
+	printf("%-3d-%3d: >>",  73, 90);
+	for (i = 0; i < 18; i++)
+		printf("%c", spd->mpart[i]);
+
+
+	printf("<<* 73 Manufacturer's Part Number *\n");
+
+	printf("%-3d-%3d: %02x %02x %s\n",
+	       91, 92, spd->rev[0], spd->rev[1],
+	       "* 91 Revision Code *");
+	printf("%-3d-%3d: %02x %02x %s\n",
+	       93, 94, spd->mdate[0], spd->mdate[1],
+	       "* 93 Manufacturing Date *");
+	printf("%-3d-%3d: ", 95, 98);
+
+	for (i = 0; i < 4; i++)
+		printf("%02x", spd->sernum[i]);
+
+	printf("* 95 Assembly Serial Number *\n");
+
+	printf("%-3d-%3d: ", 99, 127);
+	for (i = 0; i < 27; i++)
+		printf("%02x", spd->mspec[i]);
+
+
+	printf("* 99 Manufacturer Specific Data *\n");
+}
+#endif
+
+#ifdef CONFIG_FSL_DDR3
+void ddr3_spd_dump(const ddr3_spd_eeprom_t *spd)
+{
+	unsigned int i;
+
+	/* General Section: Bytes 0-59 */
+
+#define PRINT_NXS(x, y, z) printf("%-3d    : %02x %s\n", x, y, z);
+#define PRINT_NNXXS(n0, n1, x0, x1, s) printf("%-3d-%3d: %02x %02x %s\n", n0, n1, x0, x1, s);
+#define PRINT_SNNlots(x, y, z, arr) do {printf(x); printf("%-3d-%3d: ", y, z); for (i = y; i <= z; i++) printf("%02x", arr[i - y]); } while (0)
+
+	PRINT_NXS(0, spd->info_size_crc, "info_size_crc  bytes written into serial memory, CRC coverage");
+	PRINT_NXS(1, spd->spd_rev,       "spd_rev        SPD Revision");
+	PRINT_NXS(2, spd->mem_type,      "mem_type       Key Byte / DRAM Device Type");
+	PRINT_NXS(3, spd->module_type,   "module_type    Key Byte / Module Type");
+	PRINT_NXS(4, spd->density_banks, "density_banks  SDRAM Density and Banks");
+	PRINT_NXS(5, spd->addressing,    "addressing     SDRAM Addressing");
+	PRINT_NXS(6, spd->module_vdd,    "module_vdd     Module Nominal Voltage, VDD");
+	PRINT_NXS(7, spd->organization,  "organization   Module Organization");
+	PRINT_NXS(8, spd->bus_width,     "bus_width      Module Memory Bus Width");
+	PRINT_NXS(9, spd->ftb_div,       "ftb_div        Fine Timebase (FTB) Dividend / Divisor");
+	PRINT_NXS(10, spd->mtb_dividend,  "mtb_dividend   Medium Timebase (MTB) Dividend");
+	PRINT_NXS(11, spd->mtb_divisor,   "mtb_divisor    Medium Timebase (MTB) Divisor");
+	PRINT_NXS(12, spd->tCK_min,       "tCK_min        SDRAM Minimum Cycle Time");
+	PRINT_NXS(13, spd->res_13,        "res_13         Reserved");
+	PRINT_NXS(14, spd->caslat_lsb,    "caslat_lsb     CAS Latencies Supported, LSB");
+	PRINT_NXS(15, spd->caslat_msb,    "caslat_msb     CAS Latencies Supported, MSB");
+	PRINT_NXS(16, spd->tAA_min,       "tAA_min        Min CAS Latency Time");
+	PRINT_NXS(17, spd->tWR_min,       "tWR_min        Min Write REcovery Time");
+	PRINT_NXS(18, spd->tRCD_min,      "tRCD_min       Min RAS# to CAS# Delay Time");
+	PRINT_NXS(19, spd->tRRD_min,      "tRRD_min       Min Row Active to Row Active Delay Time");
+	PRINT_NXS(20, spd->tRP_min,       "tRP_min        Min Row Precharge Delay Time");
+	PRINT_NXS(21, spd->tRAS_tRC_ext,  "tRAS_tRC_ext   Upper Nibbles for tRAS and tRC");
+	PRINT_NXS(22, spd->tRAS_min_lsb,  "tRAS_min_lsb   Min Active to Precharge Delay Time, LSB");
+	PRINT_NXS(23, spd->tRC_min_lsb,   "tRC_min_lsb    Min Active to Active/Refresh Delay Time, LSB");
+	PRINT_NXS(24, spd->tRFC_min_lsb,  "tRFC_min_lsb   Min Refresh Recovery Delay Time LSB");
+	PRINT_NXS(25, spd->tRFC_min_msb,  "tRFC_min_msb   Min Refresh Recovery Delay Time MSB");
+	PRINT_NXS(26, spd->tWTR_min,      "tWTR_min       Min Internal Write to Read Command Delay Time");
+	PRINT_NXS(27, spd->tRTP_min,      "tRTP_min       Min Internal Read to Precharge Command Delay Time");
+	PRINT_NXS(28, spd->tFAW_msb,      "tFAW_msb       Upper Nibble for tFAW");
+	PRINT_NXS(29, spd->tFAW_min,      "tFAW_min       Min Four Activate Window Delay Time");
+	PRINT_NXS(30, spd->opt_features,  "opt_features   SDRAM Optional Features");
+	PRINT_NXS(31, spd->therm_ref_opt, "therm_ref_opt  SDRAM Thermal and Refresh Opts");
+	PRINT_NXS(32, spd->therm_sensor, "therm_sensor  SDRAM Thermal Sensor");
+	PRINT_NXS(33, spd->device_type, "device_type  SDRAM Device Type");
+
+	printf("%-3d-%3d: ",  34, 59);  /* Reserved, General Section */
+
+	for (i = 34; i <= 59; i++)
+		printf("%02x", spd->res_34_59[i - 34]);
+
+	puts("\n");
+
+	switch (spd->module_type) {
+	case 0x02:  /* UDIMM */
+	case 0x03:  /* SO-DIMM */
+	case 0x04:  /* Micro-DIMM */
+	case 0x06:  /* Mini-UDIMM */
+		PRINT_NXS(60, spd->mod_section.unbuffered.mod_height,    "mod_height  	 (Unbuffered) Module Nominal Height");
+		PRINT_NXS(61, spd->mod_section.unbuffered.mod_thickness, "mod_thickness (Unbuffered) Module Maximum Thickness");
+		PRINT_NXS(62, spd->mod_section.unbuffered.ref_raw_card,  "ref_raw_card	 (Unbuffered) Reference Raw Card Used");
+		PRINT_NXS(63, spd->mod_section.unbuffered.addr_mapping,  "addr_mapping	 (Unbuffered) Address mapping from Edge Connector to DRAM");
+		break;
+	case 0x01:  /* RDIMM */
+	case 0x05:  /* Mini-RDIMM */
+		PRINT_NXS(60, spd->mod_section.registered.mod_height,    "mod_height  	 (Registered) Module Nominal Height");
+		PRINT_NXS(61, spd->mod_section.registered.mod_thickness, "mod_thickness (Registered) Module Maximum Thickness");
+		PRINT_NXS(62, spd->mod_section.registered.ref_raw_card,  "ref_raw_card	 (Registered) Reference Raw Card Used");
+		PRINT_NXS(63, spd->mod_section.registered.modu_attr,  "modu_attr	 (Registered) DIMM Module Attributes");
+		PRINT_NXS(64, spd->mod_section.registered.thermal,  "thermal	 (Registered) Thermal Heat Spreader Solution");
+		PRINT_NXS(65, spd->mod_section.registered.reg_id_lo,  "reg_id_lo	 (Registered) Register Manufacturer ID Code, LSB");
+		PRINT_NXS(66, spd->mod_section.registered.reg_id_hi,  "reg_id_hi	 (Registered) Register Manufacturer ID Code, MSB");
+		PRINT_NXS(67, spd->mod_section.registered.reg_rev,  "reg_rev	 (Registered) Register Revision Number");
+		PRINT_NXS(68, spd->mod_section.registered.reg_type,  "reg_type	 (Registered) Register Type");
+		for (i = 69; i <= 76; i++)
+			printf("%-3d    : %02x rcw[%d]\n", i, spd->mod_section.registered.rcw[i-69], i-69);
+		break;
+	default:
+		printf("%-3d-%3d: ", 60, 116);  /* Module-specific Section, Unsupported Module Type */
+
+		for (i = 60; i <= 116; i++)
+			printf("%02x", spd->mod_section.uc[i - 60]);
+
+		break;
+	}
+
+	/* Unique Module ID: Bytes 117-125 */
+	PRINT_NXS(117, spd->mmid_lsb, "Module MfgID Code LSB - JEP-106");
+	PRINT_NXS(118, spd->mmid_msb, "Module MfgID Code MSB - JEP-106");
+	PRINT_NXS(119, spd->mloc,     "Mfg Location");
+	PRINT_NNXXS(120, 121, spd->mdate[0], spd->mdate[1], "Mfg Date");
+
+	printf("122-125 Module Serial Number\n");
+	printf("%-3d-%3d: ", 122, 125);
+
+	for (i = 122; i <= 125; i++)
+		printf("%02x", spd->sernum[i - 122]);
+
+
+	/* CRC: Bytes 126-127 */
+	PRINT_NNXXS(126, 127, spd->crc[0], spd->crc[1], "SPD CRC");
+
+	/* Other Manufacturer Fields and User Space: Bytes 128-255 */
+
+	printf("128-145 Mfg's Module Part Number\n");
+	printf("%-3d-%3d: ", 128, 145);
+
+	for (i = 128; i <= 145; i++)
+		printf("%02x", spd->mpart[i - 128]);
+
+	puts("\n");
+	PRINT_NNXXS(146, 147, spd->mrev[0], spd->mrev[1], "Module Revision code");
+
+	PRINT_NXS(148, spd->dmid_lsb, "DRAM MfgID Code LSB - JEP-106");
+	PRINT_NXS(149, spd->dmid_msb, "DRAM MfgID Code MSB - JEP-106");
+
+	printf("150-175 Mfg's Specific Data\n");
+	printf("%-3d-%3d: ", 150, 175);
+
+	for (i = 150; i <= 175; i++)
+		printf("%02x", spd->msd[i - 150]);
+
+	puts("\n");
+	printf("176-255 Mfg's Specific Data\n");
+	printf("%-3d-%3d: ", 176, 255);
+	for (i = 176; i <= 255; i++)
+		printf("%02x", spd->cust[i - 176]);
+
+}
+#endif
+
+static __inline__ void generic_spd_dump(const generic_spd_eeprom_t *spd)
+{
+#if defined(CONFIG_FSL_DDR1)
+	ddr1_spd_dump(spd);
+#elif defined(CONFIG_FSL_DDR2)
+	ddr2_spd_dump(spd);
+#elif defined(CONFIG_FSL_DDR3)
+	ddr3_spd_dump(spd);
+#endif
+}
+
+static void fsl_ddr_printinfo(const fsl_ddr_info_t *pinfo,
+			unsigned int ctrl_mask,
+			unsigned int dimm_mask,
+			unsigned int do_mask)
+{
+	unsigned int i, j, retval;
+
+	/* STEP 1:  DIMM SPD data */
+	if (do_mask & STEP_GET_SPD) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+
+			/*
+			 * FIXME: find a way to make this generate more
+			 * optimal powerpc code (i.e. rlwimi.)
+			 */
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				if (!(dimm_mask & (1 << j)))
+					continue;
+
+				printf("SPD info:  Controller=%u "
+						"DIMM=%u\n", i, j);
+				generic_spd_dump(
+					&(pinfo->spd_installed_dimms[i][j]));
+				printf("\n");
+			}
+			printf("\n");
+		}
+		printf("\n");
+	}
+
+	/* STEP 2:  DIMM Parameters */
+	if (do_mask & STEP_COMPUTE_DIMM_PARMS) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				if (!(dimm_mask & (1 << j)))
+					continue;
+				printf("DIMM parameters:  Controller=%u "
+						"DIMM=%u\n", i, j);
+				print_dimm_parameters(
+					&(pinfo->dimm_params[i][j]));
+				printf("\n");
+			}
+			printf("\n");
+		}
+		printf("\n");
+	}
+
+	/* STEP 3:  Common Parameters */
+	if (do_mask & STEP_COMPUTE_COMMON_PARMS) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+			printf("\"lowest common\" DIMM parameters:  "
+					"Controller=%u\n", i);
+			print_lowest_common_dimm_parameters(
+				&pinfo->common_timing_params[i]);
+			printf("\n");
+		}
+		printf("\n");
+	}
+
+	/* STEP 4:  User Configuration Options */
+	if (do_mask & STEP_GATHER_OPTS) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+			printf("User Config Options: Controller=%u\n", i);
+			print_memctl_options(&pinfo->memctl_opts[i]);
+			printf("\n");
+		}
+		printf("\n");
+	}
+
+	/* STEP 5:  Address assignment */
+	if (do_mask & STEP_ASSIGN_ADDRESSES) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+				printf("Address Assignment: Controller=%u "
+						"DIMM=%u\n", i, j);
+				printf("Don't have this functionality yet\n");
+			}
+			printf("\n");
+		}
+		printf("\n");
+	}
+
+	/* STEP 6:  computed controller register values */
+	if (do_mask & STEP_COMPUTE_REGS) {
+		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+			if (!(ctrl_mask & (1 << i)))
+				continue;
+			printf("Computed Register Values: Controller=%u\n", i);
+			print_fsl_memctl_config_regs(
+				&pinfo->fsl_ddr_config_reg[i]);
+			retval = check_fsl_memctl_config_regs(
+				&pinfo->fsl_ddr_config_reg[i]);
+			if (retval) {
+				printf("check_fsl_memctl_config_regs "
+					"result = %u\n", retval);
+			}
+			printf("\n");
+		}
+		printf("\n");
+	}
+}
+
+phys_size_t fsl_ddr_interactive(fsl_ddr_info_t *pinfo)
+{
+	phys_size_t ddrsize;
+	const char *prompt = "FSL DDR>";
+	unsigned int len;
+	char buffer[CONFIG_SYS_CBSIZE];
+	char *argv[CONFIG_SYS_MAXARGS + 1];	/* NULL terminated */
+	int argc;
+	unsigned int next_step = STEP_GET_SPD;
+
+	/*
+	 * The strategy for next_step is that it points to the next
+	 * step in the computation process that needs to be done.
+	 */
+	while (1) {
+		/*
+		 * No need to worry for buffer overflow here in
+		 * this function;  readline() maxes out at CFG_CBSIZE
+		 */
+		len = readline_into_buffer(prompt,  buffer);
+		argc = parse_line(buffer, argv);
+		if (argc == 0)
+			continue;
+
+
+		if (strcmp(argv[0], "help") == 0) {
+
+			/*
+			 * FIXME: For some reason printing this whole
+			 * thing causes the machine to freeze.
+			 * Splitting it into two printfs seems to make
+			 * it work. Does printf() have limits on the
+			 * length of the string?
+			 */
+			printf(
+	"commands:\n"
+	"print      print SPD and intermediate computed data\n"
+	"reset      reboot machine\n"
+	"recompute  reload SPD and options to default and recompute regs\n");
+			printf(
+	"edit       modify spd, parameter, or option\n");
+			printf(
+	"compute    recompute registers from current next_step to end\n"
+	"next_step  shows current next_step\n"
+	"help       this message\n"
+	"go         program the memory controller and continue with u-boot\n");
+			continue;
+		}
+
+		if (strcmp(argv[0], "next_step") == 0) {
+			printf("next_step = 0x%02X (%s)\n",
+			       next_step,
+			       step_to_string(next_step));
+			continue;
+		}
+
+		if (strcmp(argv[0], "edit") == 0) {
+			unsigned int i;
+			unsigned int error = 0;
+			unsigned int step_mask = 0;
+			unsigned int ctlr_mask = 0;
+			unsigned int dimm_mask = 0;
+			char *p_element = NULL;
+			char *p_value = NULL;
+			unsigned int dimm_number_required = 0;
+			unsigned int ctrl_num;
+			unsigned int dimm_num;
+
+			if (argc == 1) {
+				/* Only the element and value must be last */
+				printf("edit <c#> <d#> "
+					"<spd|dimmparms|commonparms|opts|"
+					"addresses|regs> <element> <value>\n");
+				printf("for spd, specify byte number for element\n");
+				continue;
+			}
+
+			for (i = 1; i < argc - 2; i++) {
+				if (strcmp(argv[i], "spd") == 0) {
+					step_mask |= STEP_GET_SPD;
+					dimm_number_required = 1;
+					continue;
+				}
+
+				if (strcmp(argv[i], "dimmparms") == 0) {
+					step_mask |= STEP_COMPUTE_DIMM_PARMS;
+					dimm_number_required = 1;
+					continue;
+				}
+
+				if (strcmp(argv[i], "commonparms") == 0) {
+					step_mask |= STEP_COMPUTE_COMMON_PARMS;
+					continue;
+				}
+
+				if (strcmp(argv[i], "opts") == 0) {
+					step_mask |= STEP_GATHER_OPTS;
+					continue;
+				}
+
+				if (strcmp(argv[i], "addresses") == 0) {
+					step_mask |= STEP_ASSIGN_ADDRESSES;
+					/*  FIXME: not done yet */
+					continue;
+				}
+
+				if (strcmp(argv[i], "regs") == 0) {
+					step_mask |= STEP_COMPUTE_REGS;
+					continue;
+				}
+
+				if (argv[i][0] == 'c') {
+					char c = argv[i][1];
+					if (isdigit(c))
+						ctlr_mask |= 1 << (c - '0');
+					continue;
+				}
+
+				if (argv[i][0] == 'd') {
+					char c = argv[i][1];
+					if (isdigit(c))
+						dimm_mask |= 1 << (c - '0');
+					continue;
+				}
+
+				printf("unknown arg %s\n", argv[i]);
+				step_mask = 0;
+				error = 1;
+				break;
+			}
+
+
+			if (error)
+				continue;
+
+
+			/* Check arguments */
+
+			/* ERROR: If no steps were found */
+			if (step_mask == 0) {
+				printf("Error: No valid steps were specified "
+						"in argument.\n");
+				continue;
+			}
+
+			/* ERROR: If multiple steps were found */
+			if (step_mask & (step_mask - 1)) {
+				printf("Error: Multiple steps specified in "
+						"argument.\n");
+				continue;
+			}
+
+			/* ERROR: Controller not specified */
+			if (ctlr_mask == 0) {
+				printf("Error: controller number not "
+					"specified or no element and "
+					"value specified\n");
+				continue;
+			}
+
+			if (ctlr_mask & (ctlr_mask - 1)) {
+				printf("Error: multiple controllers "
+						"specified, %X\n", ctlr_mask);
+				continue;
+			}
+
+			/* ERROR: DIMM number not specified */
+			if (dimm_number_required && dimm_mask == 0) {
+				printf("Error: DIMM number number not "
+					"specified or no element and "
+					"value specified\n");
+				continue;
+			}
+
+			if (dimm_mask & (dimm_mask - 1)) {
+				printf("Error: multipled DIMMs specified\n");
+				continue;
+			}
+
+			p_element = argv[argc - 2];
+			p_value = argv[argc - 1];
+
+			ctrl_num = __ilog2(ctlr_mask);
+			dimm_num = __ilog2(dimm_mask);
+
+			switch (step_mask) {
+			case STEP_GET_SPD:
+				{
+					unsigned int element_num;
+					unsigned int value;
+
+					element_num = simple_strtoul(p_element,
+								     NULL, 0);
+					value = simple_strtoul(p_value,
+							       NULL, 0);
+					fsl_ddr_spd_edit(pinfo,
+							       ctrl_num,
+							       dimm_num,
+							       element_num,
+							       value);
+					next_step = STEP_COMPUTE_DIMM_PARMS;
+				}
+				break;
+
+			case STEP_COMPUTE_DIMM_PARMS:
+				fsl_ddr_dimm_parameters_edit(
+						 pinfo, ctrl_num, dimm_num,
+						 p_element, p_value);
+				next_step = STEP_COMPUTE_COMMON_PARMS;
+				break;
+
+			case STEP_COMPUTE_COMMON_PARMS:
+				lowest_common_dimm_parameters_edit(pinfo,
+						ctrl_num, p_element, p_value);
+				next_step = STEP_GATHER_OPTS;
+				break;
+
+			case STEP_GATHER_OPTS:
+				fsl_ddr_options_edit(pinfo, ctrl_num,
+							   p_element, p_value);
+				next_step = STEP_ASSIGN_ADDRESSES;
+				break;
+
+			case STEP_ASSIGN_ADDRESSES:
+				printf("editing of address assignment "
+						"not yet implemented\n");
+				break;
+
+			case STEP_COMPUTE_REGS:
+				{
+					unsigned int value;
+
+					value = simple_strtoul(p_value,
+							       NULL, 0);
+					fsl_ddr_regs_edit(pinfo,
+								ctrl_num,
+								p_element,
+								value);
+					next_step = STEP_PROGRAM_REGS;
+				}
+				break;
+
+			default:
+				printf("programming error\n");
+				while (1);
+				break;
+			}
+			continue;
+		}
+
+		if (strcmp(argv[0], "reset") == 0) {
+			/*
+			 * Reboot machine.
+			 * Args don't seem to matter because this
+			 * doesn't return
+			 */
+			do_reset(NULL, 0, 0, NULL);
+		}
+
+		if (strcmp(argv[0], "recompute") == 0) {
+			/*
+			 * Recalculate everything, starting with
+			 * loading SPD EEPROM from DIMMs
+			 */
+			next_step = STEP_GET_SPD;
+			ddrsize = fsl_ddr_compute(pinfo, next_step);
+			/*
+			 * FIXME: There some problems with this.
+			 * For exmaple, what happens if there is
+			 * an error inside fsl_ddr_compute?
+			 */
+			continue;
+		}
+
+		if (strcmp(argv[0], "compute") == 0) {
+			/*
+			 * Compute rest of steps starting at
+			 * the current next_step/
+			 */
+			ddrsize = fsl_ddr_compute(pinfo, next_step);
+			continue;
+		}
+
+		if (strcmp(argv[0], "print") == 0) {
+			unsigned int i;
+			unsigned int error = 0;
+			unsigned int step_mask = 0;
+			unsigned int ctlr_mask = 0;
+			unsigned int dimm_mask = 0;
+
+			if (argc == 1) {
+				printf("print [c<n>] [d<n>] [spd] [dimmparms] "
+				  "[commonparms] [opts] [addresses] [regs]\n");
+				continue;
+			}
+
+			for (i = 1; i < argc; i++) {
+				if (strcmp(argv[i], "spd") == 0) {
+					step_mask |= STEP_GET_SPD;
+					continue;
+				}
+
+				if (strcmp(argv[i], "dimmparms") == 0) {
+					step_mask |= STEP_COMPUTE_DIMM_PARMS;
+					continue;
+				}
+
+				if (strcmp(argv[i], "commonparms") == 0) {
+					step_mask |= STEP_COMPUTE_COMMON_PARMS;
+					continue;
+				}
+
+				if (strcmp(argv[i], "opts") == 0) {
+					step_mask |= STEP_GATHER_OPTS;
+					continue;
+				}
+
+				if (strcmp(argv[i], "addresses") == 0) {
+					step_mask |= STEP_ASSIGN_ADDRESSES;
+					continue;
+				}
+
+				if (strcmp(argv[i], "regs") == 0) {
+					step_mask |= STEP_COMPUTE_REGS;
+					continue;
+				}
+
+				if (argv[i][0] == 'c') {
+					char c = argv[i][1];
+					if (isdigit(c))
+						ctlr_mask |= 1 << (c - '0');
+					continue;
+				}
+
+				if (argv[i][0] == 'd') {
+					char c = argv[i][1];
+					if (isdigit(c))
+						dimm_mask |= 1 << (c - '0');
+					continue;
+				}
+
+				printf("unknown arg %s\n", argv[i]);
+				step_mask = 0;
+				error = 1;
+				break;
+			}
+
+			if (error)
+				continue;
+
+			/* If no particular controller was found, print all */
+			if (ctlr_mask == 0)
+				ctlr_mask = 0xFF;
+
+			/* If no particular dimm was found, print all dimms. */
+			if (dimm_mask == 0)
+				dimm_mask = 0xFF;
+
+			/* If no steps were found, print all steps. */
+			if (step_mask == 0)
+				step_mask = STEP_ALL;
+
+			fsl_ddr_printinfo(pinfo, ctlr_mask,
+						dimm_mask, step_mask);
+			continue;
+		}
+
+		if (strcmp(argv[0], "go") == 0) {
+			if (next_step) {
+				ddrsize = fsl_ddr_compute(pinfo, next_step);
+			}
+			break;
+		}
+
+		printf("unknown command %s\n", argv[0]);
+	}
+
+	debug("end of memory = %llu\n", (u64)ddrsize);
+
+	return ddrsize;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/main.c b/arch/powerpc/cpu/mpc8xxx/ddr/main.c
index 6d582e9..83a6dd4 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/main.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/main.c
@@ -21,6 +21,7 @@ extern void fsl_ddr_set_lawbar(
 		const common_timing_params_t *memctl_common_params,
 		unsigned int memctl_interleaved,
 		unsigned int ctrl_num);
+extern phys_size_t fsl_ddr_interactive(fsl_ddr_info_t *pinfo);
 
 /* processor specific function */
 extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
@@ -75,7 +76,6 @@ extern void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
  *				|  interleaving
  */
 
-#ifdef DEBUG
 const char *step_string_tbl[] = {
 	"STEP_GET_SPD",
 	"STEP_COMPUTE_DIMM_PARMS",
@@ -96,7 +96,6 @@ const char * step_to_string(unsigned int step) {
 
 	return step_string_tbl[s];
 }
-#endif
 
 int step_assign_addresses(fsl_ddr_info_t *pinfo,
 			  unsigned int dbw_cap_adj[],
@@ -405,7 +404,10 @@ phys_size_t fsl_ddr_sdram(void)
 	memset(&info, 0, sizeof(fsl_ddr_info_t));
 
 	/* Compute it once normally. */
-	total_memory = fsl_ddr_compute(&info, STEP_GET_SPD);
+	if (getenv("ddr_interactive"))
+		total_memory = fsl_ddr_interactive(&info);
+	else
+		total_memory = fsl_ddr_compute(&info, STEP_GET_SPD);
 
 	/* Check for memory controller interleaving. */
 	memctl_interleaved = 0;
diff --git a/doc/README.fsl-ddr b/doc/README.fsl-ddr
index a7ba193..13c9013 100644
--- a/doc/README.fsl-ddr
+++ b/doc/README.fsl-ddr
@@ -170,3 +170,23 @@ Single slot system
 
 Reference http://www.xrosstalkmag.com/mag_issues/xrosstalk_oct08_final.pdf
           http://download.micron.com/pdf/technotes/ddr3/tn4108_ddr3_design_guide.pdf
+
+
+Interactive DDR debugging
+===========================
+
+For DDR parameter tuning up and debugging, the interactive DDR debugging can
+be activated by saving an environment variable "ddr_interactive". The value
+doesn't matter. Once activated, U-boot prompts "FSL DDR>" before enabling DDR
+controller. The available commands can be seen by typing "help".
+
+The example flow of using interactive debugging is
+type command "compute" to calculate the parameters from the default
+type command "print" with arguments to show SPD, options, registers
+type command "edit" with arguments to change any if desired
+type command "go" to continue calculation and enable DDR controller
+
+Note, check "next_step" to show the flow. For example, after editing registers,
+DDR controller will be enabled with current setting without further
+calculation.
+
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 10/10] Extend board specific parameters
  2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
                   ` (7 preceding siblings ...)
  2010-12-09  2:55 ` [U-Boot] [PATCH 09/10] Adding interactive ddr York Sun
@ 2010-12-09  2:55 ` York Sun
  2010-12-14  7:50   ` Wolfgang Denk
  2010-12-14  7:59 ` [U-Boot] [PATCH 01/10] Display RDIMM if detected Wolfgang Denk
  9 siblings, 1 reply; 28+ messages in thread
From: York Sun @ 2010-12-09  2:55 UTC (permalink / raw)
  To: u-boot

Extend board specific parameters to include write leveling start override
Extend write leveling sample to 0xf
Adding rcw overrid for quad-rank RDIMMs

Signed-off-by: York Sun <yorksun@freescale.com>
---
 board/freescale/corenet_ds/ddr.c |  120 +++++++++++++++++++++-----------------
 1 files changed, 66 insertions(+), 54 deletions(-)

diff --git a/board/freescale/corenet_ds/ddr.c b/board/freescale/corenet_ds/ddr.c
index 0eb290d..74339b5 100644
--- a/board/freescale/corenet_ds/ddr.c
+++ b/board/freescale/corenet_ds/ddr.c
@@ -145,6 +145,7 @@ typedef struct {
 	u32 datarate_mhz_high;
 	u32 n_ranks;
 	u32 clk_adjust;
+	u32 wrlvl_start;
 	u32 cpo;
 	u32 write_data_delay;
 	u32 force_2T;
@@ -164,57 +165,57 @@ typedef struct {
 /* XXX: Single rank at 800 MHz is OK.  */
 const board_specific_parameters_t board_specific_parameters[][30] = {
 	{
-	/* 	memory controller 0 			*/
-	/*	  lo|  hi|  num|  clk| cpo|wrdata|2T	*/
-	/*	 mhz| mhz|ranks|adjst|    | delay|	*/
-		{  0, 333,    4,    5, 0xff,    2,  0},
-		{334, 400,    4,    5, 0xff,    2,  0},
-		{401, 549,    4,    5, 0xff,    2,  0},
-		{550, 680,    4,    5, 0xff,    2,  0},
-		{681, 850,    4,    5, 0xff,    2,  0},
-		{851, 1050,   4,    5, 0xff,    2,  0},
-		{1051, 1250,  4,    5, 0xff,    2,  0},
-		{1251, 1350,  4,    5, 0xff,    2,  0},
-		{  0, 333,    2,    5, 0xff,    2,  0},
-		{334, 400,    2,    5, 0xff,    2,  0},
-		{401, 549,    2,    5, 0xff,    2,  0},
-		{550, 680,    2,    5, 0xff,    2,  0},
-		{681, 850,    2,    5, 0xff,    2,  0},
-		{851, 1050,   2,    5, 0xff,    2,  0},
-		{1051, 1250,  2,    5, 0xff,    2,  0},
-		{1251, 1350,  2,    5, 0xff,    2,  0},
-		{  0, 333,    1,    5, 0xff,    2,  0},
-		{334, 400,    1,    5, 0xff,    2,  0},
-		{401, 549,    1,    5, 0xff,    2,  0},
-		{550, 680,    1,    5, 0xff,    2,  0},
-		{681, 850,    1,    5, 0xff,    2,  0}
+	/*	memory controller 0				*/
+	/*	 lo|  hi|  num|  clk| wrlvl | cpo  |wrdata|2T	*/
+	/*	mhz| mhz|ranks|adjst| start | delay|		*/
+		{  0, 333,    4,    5,     7,   0xff,    2,  0},
+		{334, 400,    4,    5,     7,   0xff,    2,  0},
+		{401, 549,    4,    5,     7,   0xff,    2,  0},
+		{550, 680,    4,    5,     7,   0xff,    2,  0},
+		{681, 850,    4,    5,     7,   0xff,    2,  0},
+		{851, 1050,   4,    5,     7,   0xff,    2,  0},
+		{1051, 1250,  4,    5,     8,   0xff,    2,  0},
+		{1251, 1350,  4,    5,     9,   0xff,    2,  0},
+		{  0, 333,    2,    5,     7,   0xff,    2,  0},
+		{334, 400,    2,    5,     7,   0xff,    2,  0},
+		{401, 549,    2,    5,     7,   0xff,    2,  0},
+		{550, 680,    2,    5,     7,   0xff,    2,  0},
+		{681, 850,    2,    5,     7,   0xff,    2,  0},
+		{851, 1050,   2,    5,     7,   0xff,    2,  0},
+		{1051, 1250,  2,    5,     7,   0xff,    2,  0},
+		{1251, 1350,  2,    5,     7,   0xff,    2,  0},
+		{  0, 333,    1,    5,     7,   0xff,    2,  0},
+		{334, 400,    1,    5,     7,   0xff,    2,  0},
+		{401, 549,    1,    5,     7,   0xff,    2,  0},
+		{550, 680,    1,    5,     7,   0xff,    2,  0},
+		{681, 850,    1,    5,     7,   0xff,    2,  0}
 	},
 
 	{
-	/*	memory controller 1			*/
-	/*	  lo|  hi|  num|  clk| cpo|wrdata|2T	*/
-	/*	 mhz| mhz|ranks|adjst|    | delay|	*/
-		{  0, 333,    4,    5, 0xff,    2,  0},
-		{334, 400,    4,    5, 0xff,    2,  0},
-		{401, 549,    4,    5, 0xff,    2,  0},
-		{550, 680,    4,    5, 0xff,    2,  0},
-		{681, 850,    4,    5, 0xff,    2,  0},
-		{851, 1050,   4,    5, 0xff,    2,  0},
-		{1051, 1250,  4,    5, 0xff,    2,  0},
-		{1251, 1350,  4,    5, 0xff,    2,  0},
-		{  0, 333,    2,    5, 0xff,    2,  0},
-		{334, 400,    2,    5, 0xff,    2,  0},
-		{401, 549,    2,    5, 0xff,    2,  0},
-		{550, 680,    2,    5, 0xff,    2,  0},
-		{681, 850,    2,    5, 0xff,    2,  0},
-		{851, 1050,   2,    5, 0xff,    2,  0},
-		{1051, 1250,  2,    5, 0xff,    2,  0},
-		{1251, 1350,  2,    5, 0xff,    2,  0},
-		{  0, 333,    1,    5, 0xff,    2,  0},
-		{334, 400,    1,    5, 0xff,    2,  0},
-		{401, 549,    1,    5, 0xff,    2,  0},
-		{550, 680,    1,    5, 0xff,    2,  0},
-		{681, 850,    1,    5, 0xff,    2,  0}
+	/*	memory controller 1				*/
+	/*	  lo|  hi|  num|  clk| wrlvl | cpo  |wrdata|2T	*/
+	/*	 mhz| mhz|ranks|adjst| start | delay|		*/
+		{  0, 333,    4,    5,     7,   0xff,    2,  0},
+		{334, 400,    4,    5,     7,   0xff,    2,  0},
+		{401, 549,    4,    5,     7,   0xff,    2,  0},
+		{550, 680,    4,    5,     7,   0xff,    2,  0},
+		{681, 850,    4,    5,     7,   0xff,    2,  0},
+		{851, 1050,   4,    5,     7,   0xff,    2,  0},
+		{1051, 1250,  4,    5,     8,   0xff,    2,  0},
+		{1251, 1350,  4,    5,     9,   0xff,    2,  0},
+		{  0, 333,    2,    5,     7,   0xff,    2,  0},
+		{334, 400,    2,    5,     7,   0xff,    2,  0},
+		{401, 549,    2,    5,     7,   0xff,    2,  0},
+		{550, 680,    2,    5,     7,   0xff,    2,  0},
+		{681, 850,    2,    5,     7,   0xff,    2,  0},
+		{851, 1050,   2,    5,     7,   0xff,    2,  0},
+		{1051, 1250,  2,    5,     7,   0xff,    2,  0},
+		{1251, 1350,  2,    5,     7,   0xff,    2,  0},
+		{  0, 333,    1,    5,     7,   0xff,    2,  0},
+		{334, 400,    1,    5,     7,   0xff,    2,  0},
+		{401, 549,    1,    5,     7,   0xff,    2,  0},
+		{550, 680,    1,    5,     7,   0xff,    2,  0},
+		{681, 850,    1,    5,     7,   0xff,    2,  0}
 	}
 };
 
@@ -236,12 +237,12 @@ void fsl_ddr_board_options(memctl_options_t *popts,
 	for (i = 0; i < num_params; i++) {
 		if (ddr_freq >= pbsp->datarate_mhz_low &&
 		    ddr_freq <= pbsp->datarate_mhz_high &&
-		    pdimm->n_ranks == pbsp->n_ranks) {
+		    pdimm[0].n_ranks == pbsp->n_ranks) {
 			popts->cpo_override = pbsp->cpo;
 			popts->write_data_delay = pbsp->write_data_delay;
 			popts->clk_adjust = pbsp->clk_adjust;
+			popts->wrlvl_start = pbsp->wrlvl_start;
 			popts->twoT_en = pbsp->force_2T;
-			popts->wrlvl_start = pbsp->clk_adjust + 2;
 		}
 		pbsp++;
 	}
@@ -255,7 +256,8 @@ void fsl_ddr_board_options(memctl_options_t *popts,
 	 * Write leveling override
 	 */
 	popts->wrlvl_override = 1;
-	popts->wrlvl_sample = 0xa;
+	popts->wrlvl_sample = 0xf;
+
 	/*
 	 * Rtt and Rtt_WR override
 	 */
@@ -267,9 +269,19 @@ void fsl_ddr_board_options(memctl_options_t *popts,
 	/* DHC_EN =1, ODT = 60 Ohm */
 	popts->ddr_cdr1 = 0x80080000;
 
-	popts->rcw_override = 1;
-	popts->rcw_1 = 0x000a5000;
-	popts->rcw_2 = 0x00100000;
+	/* override SPD values. rcw_2 should vary at differnt speed */
+	if (pdimm[0].n_ranks == 4) {
+		popts->rcw_override = 1;
+		popts->rcw_1 = 0x000a5a00;
+		if (ddr_freq <= 800)
+			popts->rcw_2 = 0x00000000;
+		else if (ddr_freq <= 1066)
+			popts->rcw_2 = 0x00100000;
+		else if (ddr_freq <= 1333)
+			popts->rcw_2 = 0x00200000;
+		else
+			popts->rcw_2 = 0x00300000;
+	}
 }
 
 phys_size_t initdram(int board_type)
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 02/10] make the hwconfig buffer deeper
  2010-12-09  2:55 ` [U-Boot] [PATCH 02/10] make the hwconfig buffer deeper York Sun
@ 2010-12-09 10:12   ` Wolfgang Denk
  2010-12-10 18:50     ` York Sun
  0 siblings, 1 reply; 28+ messages in thread
From: Wolfgang Denk @ 2010-12-09 10:12 UTC (permalink / raw)
  To: u-boot

Dear York Sun,

In message <1291863340-4354-2-git-send-email-yorksun@freescale.com> you wrote:
> To temporarily fix buffer issue when running at flash, use bigger buffer
> to push down the stack deeper.

What does this mean? "temporarily fix" ? Do you have another,
permanent fix in the works

> Signed-off-by: York Sun <yorksun@freescale.com>
> ---
>  common/hwconfig.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/common/hwconfig.c b/common/hwconfig.c
> index 3c9759f..1b33d95 100644
> --- a/common/hwconfig.c
> +++ b/common/hwconfig.c
> @@ -71,7 +71,7 @@ next:
>  const char *cpu_hwconfig __attribute__((weak));
>  const char *board_hwconfig __attribute__((weak));
>  
> -#define HWCONFIG_PRE_RELOC_BUF_SIZE	128
> +#define HWCONFIG_PRE_RELOC_BUF_SIZE	256

Is this really, really necessary?  Memory is a scarce resource
pre relocation.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
If it happens once, it's a bug.
If it happens twice, it's a feature.
If it happens more than twice, it's a design philosophy.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 02/10] make the hwconfig buffer deeper
  2010-12-09 10:12   ` Wolfgang Denk
@ 2010-12-10 18:50     ` York Sun
  2010-12-14  4:59       ` Kumar Gala
  0 siblings, 1 reply; 28+ messages in thread
From: York Sun @ 2010-12-10 18:50 UTC (permalink / raw)
  To: u-boot

Wolfgang,

On Thu, 2010-12-09 at 11:12 +0100, Wolfgang Denk wrote:
> Dear York Sun,
> 
> In message <1291863340-4354-2-git-send-email-yorksun@freescale.com> you wrote:
> > To temporarily fix buffer issue when running at flash, use bigger buffer
> > to push down the stack deeper.
> 
> What does this mean? "temporarily fix" ? Do you have another,
> permanent fix in the works

I am not happy with this "fix" either. Kumar changed the code to use
deeper buffer as a workaround. This is the only way I can make it work
following him.

> 
> > Signed-off-by: York Sun <yorksun@freescale.com>
> > ---
> >  common/hwconfig.c |    2 +-
> >  1 files changed, 1 insertions(+), 1 deletions(-)
> > 
> > diff --git a/common/hwconfig.c b/common/hwconfig.c
> > index 3c9759f..1b33d95 100644
> > --- a/common/hwconfig.c
> > +++ b/common/hwconfig.c
> > @@ -71,7 +71,7 @@ next:
> >  const char *cpu_hwconfig __attribute__((weak));
> >  const char *board_hwconfig __attribute__((weak));
> >  
> > -#define HWCONFIG_PRE_RELOC_BUF_SIZE	128
> > +#define HWCONFIG_PRE_RELOC_BUF_SIZE	256
> 
> Is this really, really necessary?  Memory is a scarce resource
> pre relocation.

Let me work with Kumar on this.

York

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 02/10] make the hwconfig buffer deeper
  2010-12-10 18:50     ` York Sun
@ 2010-12-14  4:59       ` Kumar Gala
  0 siblings, 0 replies; 28+ messages in thread
From: Kumar Gala @ 2010-12-14  4:59 UTC (permalink / raw)
  To: u-boot


On Dec 10, 2010, at 12:50 PM, York Sun wrote:

> Wolfgang,
> 
> On Thu, 2010-12-09 at 11:12 +0100, Wolfgang Denk wrote:
>> Dear York Sun,
>> 
>> In message <1291863340-4354-2-git-send-email-yorksun@freescale.com> you wrote:
>>> To temporarily fix buffer issue when running at flash, use bigger buffer
>>> to push down the stack deeper.
>> 
>> What does this mean? "temporarily fix" ? Do you have another,
>> permanent fix in the works
> 
> I am not happy with this "fix" either. Kumar changed the code to use
> deeper buffer as a workaround. This is the only way I can make it work
> following him.
> 
>> 
>>> Signed-off-by: York Sun <yorksun@freescale.com>
>>> ---
>>> common/hwconfig.c |    2 +-
>>> 1 files changed, 1 insertions(+), 1 deletions(-)
>>> 
>>> diff --git a/common/hwconfig.c b/common/hwconfig.c
>>> index 3c9759f..1b33d95 100644
>>> --- a/common/hwconfig.c
>>> +++ b/common/hwconfig.c
>>> @@ -71,7 +71,7 @@ next:
>>> const char *cpu_hwconfig __attribute__((weak));
>>> const char *board_hwconfig __attribute__((weak));
>>> 
>>> -#define HWCONFIG_PRE_RELOC_BUF_SIZE	128
>>> +#define HWCONFIG_PRE_RELOC_BUF_SIZE	256
>> 
>> Is this really, really necessary?  Memory is a scarce resource
>> pre relocation.
> 
> Let me work with Kumar on this.

Got any ideas?  I'm not a fan but not sure what else we can do.

- k

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 05/10] Adding more registers and options
  2010-12-09  2:55 ` [U-Boot] [PATCH 05/10] Adding more registers and options York Sun
@ 2010-12-14  5:10   ` Kumar Gala
  2010-12-14  6:30     ` York Sun
  0 siblings, 1 reply; 28+ messages in thread
From: Kumar Gala @ 2010-12-14  5:10 UTC (permalink / raw)
  To: u-boot


On Dec 8, 2010, at 8:55 PM, York Sun wrote:

> Add writing to cdr1, cdr2, err_disable, err_int_en and debug registers
> Add options to override rcw, address parity to RDIMMs.
> Use array for debug registeres.
> 
> Signed-off-by: York Sun <yorksun@freescale.com>
> ---
> arch/powerpc/cpu/mpc85xx/ddr-gen3.c      |   10 ++++++++--
> arch/powerpc/include/asm/fsl_ddr_sdram.h |   12 ++++++++++++
> arch/powerpc/include/asm/immap_85xx.h    |   19 +------------------
> 3 files changed, 21 insertions(+), 20 deletions(-)

this probably breaks boards.  Did you do a build all on 85xx and 86xx?

- k

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 06/10] Enable unique mode registers and dynamic ODT for DDR3
  2010-12-09  2:55 ` [U-Boot] [PATCH 06/10] Enable unique mode registers and dynamic ODT for DDR3 York Sun
@ 2010-12-14  5:13   ` Kumar Gala
  2010-12-14  6:33     ` York Sun
  2010-12-14  7:54   ` Wolfgang Denk
  1 sibling, 1 reply; 28+ messages in thread
From: Kumar Gala @ 2010-12-14  5:13 UTC (permalink / raw)
  To: u-boot


On Dec 8, 2010, at 8:55 PM, York Sun wrote:

> Added fsl_ddr_get_version() function to poll DDRC IP version (major, minor,
> errata) to determine if unique mode registers are available. This function may
> be needed for future other platforms if such a feature exists. If true, always
> use unique mode registers. Dynamic ODT is enabled if needed. The table is
> documented in doc/README.fsl-ddr.
> 
> Enable address parity and RCW by default for RDIMMs.
> 
> Change default output driver impedance from 34 ohm to 40ohm. Make it 34ohm for
> quad-rank RDIMMs.
> 
> Use a formula to calculate rodt_on for timing_cfg_5.
> 
> Signed-off-by: York Sun <yorksun@freescale.com>
> ---
> arch/powerpc/cpu/mpc85xx/ddr-gen3.c      |   18 ++
> arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c |  305 +++++++++++++++++++++++++----
> arch/powerpc/cpu/mpc8xxx/ddr/options.c   |  308 +++++++++++++++++++++++++++++-
> arch/powerpc/include/asm/fsl_ddr_sdram.h |   18 ++
> board/freescale/corenet_ds/ddr.c         |  125 ++++++-------

do we really need to mix corenet_ds/ddr.c in this patch?

> doc/README.fsl-ddr                       |   67 +++++++-
> 6 files changed, 723 insertions(+), 118 deletions(-)

What about other DDR3 boards like P2020DS? Are they impacted by this patch?

- k

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 09/10] Adding interactive ddr
  2010-12-09  2:55 ` [U-Boot] [PATCH 09/10] Adding interactive ddr York Sun
@ 2010-12-14  5:15   ` Kumar Gala
  2010-12-14  7:47   ` Wolfgang Denk
  1 sibling, 0 replies; 28+ messages in thread
From: Kumar Gala @ 2010-12-14  5:15 UTC (permalink / raw)
  To: u-boot


On Dec 8, 2010, at 8:55 PM, York Sun wrote:

> Use environment variable to active the interactive debugging.
> 
> Signed-off-by: York Sun <yorksun@freescale.com>
> ---
> arch/powerpc/cpu/mpc8xxx/ddr/Makefile      |    6 +-
> arch/powerpc/cpu/mpc8xxx/ddr/interactive.c | 1882 ++++++++++++++++++++++++++++
> arch/powerpc/cpu/mpc8xxx/ddr/main.c        |    8 +-
> doc/README.fsl-ddr                         |   20 +
> 4 files changed, 1910 insertions(+), 6 deletions(-)
> create mode 100644 arch/powerpc/cpu/mpc8xxx/ddr/interactive.c

Can you make this the last patch.

- k

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 05/10] Adding more registers and options
  2010-12-14  5:10   ` Kumar Gala
@ 2010-12-14  6:30     ` York Sun
  2010-12-14  6:37       ` Kumar Gala
  0 siblings, 1 reply; 28+ messages in thread
From: York Sun @ 2010-12-14  6:30 UTC (permalink / raw)
  To: u-boot

On Mon, 2010-12-13 at 23:10 -0600, Kumar Gala wrote:
> On Dec 8, 2010, at 8:55 PM, York Sun wrote:
> 
> > Add writing to cdr1, cdr2, err_disable, err_int_en and debug registers
> > Add options to override rcw, address parity to RDIMMs.
> > Use array for debug registeres.
> > 
> > Signed-off-by: York Sun <yorksun@freescale.com>
> > ---
> > arch/powerpc/cpu/mpc85xx/ddr-gen3.c      |   10 ++++++++--
> > arch/powerpc/include/asm/fsl_ddr_sdram.h |   12 ++++++++++++
> > arch/powerpc/include/asm/immap_85xx.h    |   19 +------------------
> > 3 files changed, 21 insertions(+), 20 deletions(-)
> 
> this probably breaks boards.  Did you do a build all on 85xx and 86xx?

No, I didn't try on other boards. The registers have default value of 0,
which shouldn't hurt.

York

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 06/10] Enable unique mode registers and dynamic ODT for DDR3
  2010-12-14  5:13   ` Kumar Gala
@ 2010-12-14  6:33     ` York Sun
  0 siblings, 0 replies; 28+ messages in thread
From: York Sun @ 2010-12-14  6:33 UTC (permalink / raw)
  To: u-boot

On Mon, 2010-12-13 at 23:13 -0600, Kumar Gala wrote:
> On Dec 8, 2010, at 8:55 PM, York Sun wrote:
> 
> > Added fsl_ddr_get_version() function to poll DDRC IP version (major, minor,
> > errata) to determine if unique mode registers are available. This function may
> > be needed for future other platforms if such a feature exists. If true, always
> > use unique mode registers. Dynamic ODT is enabled if needed. The table is
> > documented in doc/README.fsl-ddr.
> > 
> > Enable address parity and RCW by default for RDIMMs.
> > 
> > Change default output driver impedance from 34 ohm to 40ohm. Make it 34ohm for
> > quad-rank RDIMMs.
> > 
> > Use a formula to calculate rodt_on for timing_cfg_5.
> > 
> > Signed-off-by: York Sun <yorksun@freescale.com>
> > ---
> > arch/powerpc/cpu/mpc85xx/ddr-gen3.c      |   18 ++
> > arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c |  305 +++++++++++++++++++++++++----
> > arch/powerpc/cpu/mpc8xxx/ddr/options.c   |  308 +++++++++++++++++++++++++++++-
> > arch/powerpc/include/asm/fsl_ddr_sdram.h |   18 ++
> > board/freescale/corenet_ds/ddr.c         |  125 ++++++-------
> 
> do we really need to mix corenet_ds/ddr.c in this patch?
> 
> > doc/README.fsl-ddr                       |   67 +++++++-
> > 6 files changed, 723 insertions(+), 118 deletions(-)
> 
> What about other DDR3 boards like P2020DS? Are they impacted by this patch?

No. The unique mode registers are only used if DDRC supports it.

York

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 05/10] Adding more registers and options
  2010-12-14  6:30     ` York Sun
@ 2010-12-14  6:37       ` Kumar Gala
  2010-12-14  6:42         ` York Sun
  0 siblings, 1 reply; 28+ messages in thread
From: Kumar Gala @ 2010-12-14  6:37 UTC (permalink / raw)
  To: u-boot


On Dec 14, 2010, at 12:30 AM, York Sun wrote:

> On Mon, 2010-12-13 at 23:10 -0600, Kumar Gala wrote:
>> On Dec 8, 2010, at 8:55 PM, York Sun wrote:
>> 
>>> Add writing to cdr1, cdr2, err_disable, err_int_en and debug registers
>>> Add options to override rcw, address parity to RDIMMs.
>>> Use array for debug registeres.
>>> 
>>> Signed-off-by: York Sun <yorksun@freescale.com>
>>> ---
>>> arch/powerpc/cpu/mpc85xx/ddr-gen3.c      |   10 ++++++++--
>>> arch/powerpc/include/asm/fsl_ddr_sdram.h |   12 ++++++++++++
>>> arch/powerpc/include/asm/immap_85xx.h    |   19 +------------------
>>> 3 files changed, 21 insertions(+), 20 deletions(-)
>> 
>> this probably breaks boards.  Did you do a build all on 85xx and 86xx?
> 
> No, I didn't try on other boards. The registers have default value of 0,
> which shouldn't hurt.
> 
> York
> 

Its not that, I think we fail to even compile.

For example:

[galak at right u-boot]$ git grep debug_ board/tqc/
board/tqc/tqm85xx/sdram.c:      ddr->debug_3 |= 0x00000400;
board/tqc/tqm85xx/sdram.c:      ddr->debug_3 &= ~0x00000400;
board/tqc/tqm85xx/sdram.c:      ddr->debug_2 |= 0x00000400;
board/tqc/tqm85xx/sdram.c:      while (ddr->debug_2 & 0x00000400)

- k

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 05/10] Adding more registers and options
  2010-12-14  6:37       ` Kumar Gala
@ 2010-12-14  6:42         ` York Sun
  2010-12-14  6:43           ` Kumar Gala
  0 siblings, 1 reply; 28+ messages in thread
From: York Sun @ 2010-12-14  6:42 UTC (permalink / raw)
  To: u-boot

On Tue, 2010-12-14 at 00:37 -0600, Kumar Gala wrote:
> On Dec 14, 2010, at 12:30 AM, York Sun wrote:
> 
> > On Mon, 2010-12-13 at 23:10 -0600, Kumar Gala wrote:
> >> On Dec 8, 2010, at 8:55 PM, York Sun wrote:
> >> 
> >>> Add writing to cdr1, cdr2, err_disable, err_int_en and debug registers
> >>> Add options to override rcw, address parity to RDIMMs.
> >>> Use array for debug registeres.
> >>> 
> >>> Signed-off-by: York Sun <yorksun@freescale.com>
> >>> ---
> >>> arch/powerpc/cpu/mpc85xx/ddr-gen3.c      |   10 ++++++++--
> >>> arch/powerpc/include/asm/fsl_ddr_sdram.h |   12 ++++++++++++
> >>> arch/powerpc/include/asm/immap_85xx.h    |   19 +------------------
> >>> 3 files changed, 21 insertions(+), 20 deletions(-)
> >> 
> >> this probably breaks boards.  Did you do a build all on 85xx and 86xx?
> > 
> > No, I didn't try on other boards. The registers have default value of 0,
> > which shouldn't hurt.
> > 
> > York
> > 
> 
> Its not that, I think we fail to even compile.
> 
> For example:
> 
> [galak at right u-boot]$ git grep debug_ board/tqc/
> board/tqc/tqm85xx/sdram.c:      ddr->debug_3 |= 0x00000400;
> board/tqc/tqm85xx/sdram.c:      ddr->debug_3 &= ~0x00000400;
> board/tqc/tqm85xx/sdram.c:      ddr->debug_2 |= 0x00000400;
> board/tqc/tqm85xx/sdram.c:      while (ddr->debug_2 & 0x00000400)
> 

You are right. I didn't think there are other boards out of freescale
folder. Do you want to me revert back to debug_x or change all of them
to debug[x]?

York

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 05/10] Adding more registers and options
  2010-12-14  6:42         ` York Sun
@ 2010-12-14  6:43           ` Kumar Gala
  0 siblings, 0 replies; 28+ messages in thread
From: Kumar Gala @ 2010-12-14  6:43 UTC (permalink / raw)
  To: u-boot


On Dec 14, 2010, at 12:42 AM, York Sun wrote:

> On Tue, 2010-12-14 at 00:37 -0600, Kumar Gala wrote:
>> On Dec 14, 2010, at 12:30 AM, York Sun wrote:
>> 
>>> On Mon, 2010-12-13 at 23:10 -0600, Kumar Gala wrote:
>>>> On Dec 8, 2010, at 8:55 PM, York Sun wrote:
>>>> 
>>>>> Add writing to cdr1, cdr2, err_disable, err_int_en and debug registers
>>>>> Add options to override rcw, address parity to RDIMMs.
>>>>> Use array for debug registeres.
>>>>> 
>>>>> Signed-off-by: York Sun <yorksun@freescale.com>
>>>>> ---
>>>>> arch/powerpc/cpu/mpc85xx/ddr-gen3.c      |   10 ++++++++--
>>>>> arch/powerpc/include/asm/fsl_ddr_sdram.h |   12 ++++++++++++
>>>>> arch/powerpc/include/asm/immap_85xx.h    |   19 +------------------
>>>>> 3 files changed, 21 insertions(+), 20 deletions(-)
>>>> 
>>>> this probably breaks boards.  Did you do a build all on 85xx and 86xx?
>>> 
>>> No, I didn't try on other boards. The registers have default value of 0,
>>> which shouldn't hurt.
>>> 
>>> York
>>> 
>> 
>> Its not that, I think we fail to even compile.
>> 
>> For example:
>> 
>> [galak at right u-boot]$ git grep debug_ board/tqc/
>> board/tqc/tqm85xx/sdram.c:      ddr->debug_3 |= 0x00000400;
>> board/tqc/tqm85xx/sdram.c:      ddr->debug_3 &= ~0x00000400;
>> board/tqc/tqm85xx/sdram.c:      ddr->debug_2 |= 0x00000400;
>> board/tqc/tqm85xx/sdram.c:      while (ddr->debug_2 & 0x00000400)
>> 
> 
> You are right. I didn't think there are other boards out of freescale
> folder. Do you want to me revert back to debug_x or change all of them
> to debug[x]?

Just change to debug[x] for the other places that are impacted.

- k

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 08/10] Implement workaround for erratum DDRA003
  2010-12-09  2:55 ` [U-Boot] [PATCH 08/10] Implement workaround for erratum DDRA003 York Sun
@ 2010-12-14  6:47   ` Kumar Gala
  0 siblings, 0 replies; 28+ messages in thread
From: Kumar Gala @ 2010-12-14  6:47 UTC (permalink / raw)
  To: u-boot


On Dec 8, 2010, at 8:55 PM, York Sun wrote:

> Erratum DDRA003 requires workaround to correctly set RCW10 for registered DIMM.
> Also adding polling after enabling DDR controller to ensure completion.
> 
> Signed-off-by: York Sun <yorksun@freescale.com>
> ---
> arch/powerpc/cpu/mpc85xx/ddr-gen3.c |   53 ++++++++++++++++++++++++++++++++++-
> include/configs/P4080DS.h           |    1 +
> 2 files changed, 53 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
> index 568f9f4..0815ba4 100644
> --- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
> +++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
> @@ -108,6 +108,55 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
> 	temp_sdram_cfg = regs->ddr_sdram_cfg;
> 	temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
> 	out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
> +#ifdef CONFIG_SYS_P4080_ERRATUM_DDRA003

Name this:

#ifdef CONFIG_SYS_FSL_NMG_DDR_A003

> +	if (regs->ddr_sdram_rcw_2 & 0x00f00000) {
> +		out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2 & 0xf07fffff);
> +		out_be32(&ddr->debug[2], 0x00000400);
> +		out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl & 0x7fffffff);
> +		out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl & 0x7fffffff);
> +		out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2 & 0xffffffeb);
> +		out_be32(&ddr->mtcr, 0);
> +		out_be32(&ddr->debug[12], 0x00000015);
> +		out_be32(&ddr->debug[21], 0x24000000);
> +		out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval & 0xffff);
> +		out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_BI | SDRAM_CFG_MEM_EN);
> +
> +		asm volatile("sync;isync");
> +		while (!(in_be32(&ddr->debug[1]) & 0x2));
> +
> +		switch (regs->ddr_sdram_rcw_2 & 0x00f00000) {
> +		case 0x00000000:
> +			out_be32(&ddr->sdram_md_cntl, 0xc4080002);
> +			break;
> +		case 0x00100000:
> +			out_be32(&ddr->sdram_md_cntl, 0xc408000a);
> +			break;
> +		case 0x00200000:
> +			out_be32(&ddr->sdram_md_cntl, 0xc4080012);
> +			break;
> +		case 0x00300000:
> +			out_be32(&ddr->sdram_md_cntl, 0xc408001a);
> +			break;
> +		default:
> +			out_be32(&ddr->sdram_md_cntl, 0xc4080002);
> +			printf("Unsupported RC10\n");
> +			break;
> +		}
> +
> +		while (in_be32(&ddr->sdram_md_cntl) & 0x80000000);
> +		udelay(6);
> +		out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
> +		out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
> +		out_be32(&ddr->debug[2], 0x0);
> +		out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
> +		out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
> +		out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
> +		out_be32(&ddr->debug[12], 0x0);
> +		out_be32(&ddr->debug[21], 0x0);
> +		out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
> +
> +	}
> +#endif
> 	/*
> 	 * For 8572 DDR1 erratum - DDR controller may enter illegal state
> 	 * when operatiing in 32-bit bus mode with 4-beat bursts,
> @@ -131,8 +180,10 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
> 	asm volatile("sync;isync");
> 
> 	/* Let the controller go */
> -	temp_sdram_cfg = in_be32(&ddr->sdram_cfg);
> +	temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
> 	out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
> +	asm volatile("sync;isync");
> +	while (!(in_be32(&ddr->debug[1]) & 0x2));
> 
> 	/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done.  */
> 	while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
> diff --git a/include/configs/P4080DS.h b/include/configs/P4080DS.h
> index d210016..c19bd39 100644
> --- a/include/configs/P4080DS.h
> +++ b/include/configs/P4080DS.h
> @@ -45,6 +45,7 @@
> #define CONFIG_SYS_P4080_ERRATUM_CPC9
> #define CONFIG_SYS_P4080_ERRATUM_DDR1
> #define CONFIG_SYS_P4080_ERRATUM_DDR7
> +#define CONFIG_SYS_P4080_ERRATUM_DDRA003
> #define CONFIG_SYS_P4080_ERRATUM_ESDHC1
> #define CONFIG_SYS_P4080_ERRATUM_ESDHC9
> #define CONFIG_SYS_P4080_ERRATUM_ESDHC11
> -- 
> 1.7.0.4

You need to update arch/powerpc/cpu/mpc85xx/cmd_errata.c

- k

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 09/10] Adding interactive ddr
  2010-12-09  2:55 ` [U-Boot] [PATCH 09/10] Adding interactive ddr York Sun
  2010-12-14  5:15   ` Kumar Gala
@ 2010-12-14  7:47   ` Wolfgang Denk
  2010-12-14 15:07     ` Kumar Gala
  1 sibling, 1 reply; 28+ messages in thread
From: Wolfgang Denk @ 2010-12-14  7:47 UTC (permalink / raw)
  To: u-boot

Dear York Sun,

In message <1291863340-4354-9-git-send-email-yorksun@freescale.com> you wrote:
> Use environment variable to active the interactive debugging.
...

s/active/activate/

> diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/Makefile b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
> index cb7f856..4bd416a 100644
> --- a/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
> +++ b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
> @@ -11,15 +11,15 @@ include $(TOPDIR)/config.mk
>  LIB	= $(obj)libddr.a
>  
>  COBJS-$(CONFIG_FSL_DDR1)	+= main.o util.o ctrl_regs.o options.o \
> -				   lc_common_dimm_params.o
> +				   lc_common_dimm_params.o interactive.o
>  COBJS-$(CONFIG_FSL_DDR1)	+= ddr1_dimm_params.o
>  
>  COBJS-$(CONFIG_FSL_DDR2)	+= main.o util.o ctrl_regs.o options.o \
> -				   lc_common_dimm_params.o
> +				   lc_common_dimm_params.o interactive.o
>  COBJS-$(CONFIG_FSL_DDR2)	+= ddr2_dimm_params.o
>  
>  COBJS-$(CONFIG_FSL_DDR3)	+= main.o util.o ctrl_regs.o options.o \
> -				   lc_common_dimm_params.o
> +				   lc_common_dimm_params.o interactive.o
>  COBJS-$(CONFIG_FSL_DDR3)	+= ddr3_dimm_params.o

Building interactive.o should depend on CONFIG_FSL_DDR_INTERACTIVE
being set.

>  SRCS	:= $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
> diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c
> new file mode 100644
> index 0000000..7d492a9
> --- /dev/null
> +++ b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c
> @@ -0,0 +1,1882 @@
> +/*
> + * Copyright 2010 Freescale Semiconductor, Inc.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * Version 2 as published by the Free Software Foundation.
> + */

NAK.   V2 or later is mandatory.


> +static void fsl_ddr_generic_edit(void *pdata,
> +			   void *pend,
> +			   unsigned int element_size,
> +			   unsigned int element_num,
> +			   unsigned int value)
> +{
> +	char *pcdata = (char *)pdata;		/* BIG ENDIAN ONLY */
> +
> +	pcdata += element_num * element_size;
> +	if ((pcdata + element_size) > (char *) pend) {
> +		debug("trying to write past end of data\n");
> +		return;

Should that not be an error message that is always enabled?

> +	default:
> +		debug("unexpected element size %u\n", element_size);
> +		break;

Ditto?


> +	static const options_strings_t options[] = {
> +		{"cs0_odt_rd_cfg", offsetof(memctl_options_t, cs_local_opts[0].odt_rd_cfg)},
> +		{"cs0_odt_wr_cfg", offsetof(memctl_options_t, cs_local_opts[0].odt_wr_cfg)},
> +		{"cs0_odt_rtt_norm", offsetof(memctl_options_t, cs_local_opts[0].odt_rtt_norm)},
> +		{"cs0_odt_rtt_wr", offsetof(memctl_options_t, cs_local_opts[0].odt_rtt_wr)},
> +		{"cs1_odt_rd_cfg", offsetof(memctl_options_t, cs_local_opts[1].odt_rd_cfg)},
> +		{"cs1_odt_wr_cfg", offsetof(memctl_options_t, cs_local_opts[1].odt_wr_cfg)},
> +		{"cs1_odt_rtt_norm", offsetof(memctl_options_t, cs_local_opts[1].odt_rtt_norm)},
> +		{"cs1_odt_rtt_wr", offsetof(memctl_options_t, cs_local_opts[1].odt_rtt_wr)},
> +		{"cs2_odt_rd_cfg", offsetof(memctl_options_t, cs_local_opts[2].odt_rd_cfg)},
> +		{"cs2_odt_wr_cfg", offsetof(memctl_options_t, cs_local_opts[2].odt_wr_cfg)},
> +		{"cs2_odt_rtt_norm", offsetof(memctl_options_t, cs_local_opts[2].odt_rtt_norm)},
> +		{"cs2_odt_rtt_wr", offsetof(memctl_options_t, cs_local_opts[2].odt_rtt_wr)},
> +		{"cs3_odt_rd_cfg", offsetof(memctl_options_t, cs_local_opts[3].odt_rd_cfg)},
> +		{"cs3_odt_wr_cfg", offsetof(memctl_options_t, cs_local_opts[3].odt_wr_cfg)},
> +		{"cs3_odt_rtt_norm", offsetof(memctl_options_t, cs_local_opts[3].odt_rtt_norm)},
> +		{"cs3_odt_rtt_wr", offsetof(memctl_options_t, cs_local_opts[3].odt_rtt_wr)},

Lines too long.


> +	if (handle_uint_option_table(options, nopts, (u32) p,
> +					optname_str, value_str))
> +		return;

Please use braces for multiline statements.

> +	printf("couldn't find option string %s\n", optname_str);
> +}
> +
> +static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
> +		printf("cs%u_bnds           = %08X\n", i, ddr->cs[i].bnds);
> +		printf("cs%u_config         = %08X\n", i, ddr->cs[i].config);
> +		printf("cs%u_config_2       = %08X\n", i, ddr->cs[i].config_2);
> +	}
> +
> +	printf("timing_cfg_3       = %08X\n", ddr->timing_cfg_3);
> +	printf("timing_cfg_0       = %08X\n", ddr->timing_cfg_0);
> +	printf("timing_cfg_1       = %08X\n", ddr->timing_cfg_1);
> +	printf("timing_cfg_2       = %08X\n", ddr->timing_cfg_2);
> +	printf("ddr_sdram_cfg      = %08X\n", ddr->ddr_sdram_cfg);
> +	printf("ddr_sdram_cfg_2    = %08X\n", ddr->ddr_sdram_cfg_2);
> +	printf("ddr_sdram_mode     = %08X\n", ddr->ddr_sdram_mode);
> +	printf("ddr_sdram_mode_2   = %08X\n", ddr->ddr_sdram_mode_2);
> +	printf("ddr_sdram_mode_3   = %08X\n", ddr->ddr_sdram_mode_3);
> +	printf("ddr_sdram_mode_4   = %08X\n", ddr->ddr_sdram_mode_4);
> +	printf("ddr_sdram_mode_5   = %08X\n", ddr->ddr_sdram_mode_5);
> +	printf("ddr_sdram_mode_6   = %08X\n", ddr->ddr_sdram_mode_6);
> +	printf("ddr_sdram_mode_7   = %08X\n", ddr->ddr_sdram_mode_7);
> +	printf("ddr_sdram_mode_8   = %08X\n", ddr->ddr_sdram_mode_8);
> +	printf("ddr_sdram_interval = %08X\n", ddr->ddr_sdram_interval);
> +	printf("ddr_data_init      = %08X\n", ddr->ddr_data_init);
> +	printf("ddr_sdram_clk_cntl = %08X\n", ddr->ddr_sdram_clk_cntl);
> +	printf("ddr_init_addr      = %08X\n", ddr->ddr_init_addr);
> +	printf("ddr_init_ext_addr  = %08X\n", ddr->ddr_init_ext_addr);
> +	printf("timing_cfg_4       = %08X\n", ddr->timing_cfg_4);
> +	printf("timing_cfg_5       = %08X\n", ddr->timing_cfg_5);
> +	printf("ddr_zq_cntl        = %08X\n", ddr->ddr_zq_cntl);
> +	printf("ddr_wrlvl_cntl     = %08X\n", ddr->ddr_wrlvl_cntl);
> +	printf("ddr_sr_cntr        = %08X\n", ddr->ddr_sr_cntr);
> +	printf("ddr_sdram_rcw_1    = %08X\n", ddr->ddr_sdram_rcw_1);
> +	printf("ddr_sdram_rcw_2    = %08X\n", ddr->ddr_sdram_rcw_2);
> +	printf("ddr_cdr1           = %08X\n", ddr->ddr_cdr1);
> +	printf("ddr_cdr2           = %08X\n", ddr->ddr_cdr2);
> +	printf("err_disable        = %08X\n", ddr->err_disable);
> +	printf("err_int_en         = %08X\n", ddr->err_int_en);
> +	for (i = 0; i < 18; i++)
> +		printf("debug_%02d	= %08X\n", i+1, ddr->debug[i]);
> +}
> +
> +static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
> +			unsigned int ctrl_num,
> +			const char *regname,
> +			unsigned int value)
> +{
> +	unsigned int i;
> +	fsl_ddr_cfg_regs_t *ddr;
> +	char buf[20];
> +
> +	debug("fsl_ddr_regs_edit: ctrl_num = %u, "
> +		"regname = %s, value = 0x%08X\n",
> +		ctrl_num, regname, value);
> +	if (ctrl_num > CONFIG_NUM_DDR_CONTROLLERS)
> +		return;
> +
> +	/* FIXME: Change this into struct like the other editing functions */
> +	ddr = &(pinfo->fsl_ddr_config_reg[ctrl_num]);
> +
> +	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
> +		sprintf(buf, "cs%u_bnds", i);
> +		if (strcmp(buf, regname) == 0) {
> +			ddr->cs[i].bnds = value;
> +			return;
> +		}
> +
> +		sprintf(buf, "cs%u_config", i);
> +		if (strcmp(buf, regname) == 0) {
> +			ddr->cs[i].config = value;
> +			return;
> +		}
> +
> +		sprintf(buf, "cs%u_config_2", i);
> +		if (strcmp(buf, regname) == 0) {
> +			ddr->cs[i].config_2 = value;
> +			return;
> +		}
> +	}

Use format string / pointer table and a loop.

> +	if (strcmp("timing_cfg_3", regname) == 0) {
> +		ddr->timing_cfg_3 = value;
> +		return;
> +	}
> +
> +	if (strcmp("timing_cfg_0", regname) == 0) {
> +		ddr->timing_cfg_0 = value;
> +		return;
> +	}
> +
> +	if (strcmp("timing_cfg_1", regname) == 0) {
> +		ddr->timing_cfg_1 = value;
> +		return;
> +	}
> +
> +	if (strcmp("timing_cfg_2", regname) == 0) {
> +		ddr->timing_cfg_2 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_cfg", regname) == 0) {
> +		ddr->ddr_sdram_cfg = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_cfg_2", regname) == 0) {
> +		ddr->ddr_sdram_cfg_2 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_mode", regname) == 0) {
> +		ddr->ddr_sdram_mode = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_mode_2", regname) == 0) {
> +		ddr->ddr_sdram_mode_2 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_mode_3", regname) == 0) {
> +		ddr->ddr_sdram_mode_3 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_mode_4", regname) == 0) {
> +		ddr->ddr_sdram_mode_4 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_mode_5", regname) == 0) {
> +		ddr->ddr_sdram_mode_5 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_mode_6", regname) == 0) {
> +		ddr->ddr_sdram_mode_6 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_mode_7", regname) == 0) {
> +		ddr->ddr_sdram_mode_7 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_mode_8", regname) == 0) {
> +		ddr->ddr_sdram_mode_8 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_interval", regname) == 0) {
> +		ddr->ddr_sdram_interval = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_data_init", regname) == 0) {
> +		ddr->ddr_data_init = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_clk_cntl", regname) == 0) {
> +		ddr->ddr_sdram_clk_cntl = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_init_addr", regname) == 0) {
> +		ddr->ddr_init_addr = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_init_ext_addr", regname) == 0) {
> +		ddr->ddr_init_ext_addr = value;
> +		return;
> +	}
> +
> +	if (strcmp("timing_cfg_4", regname) == 0) {
> +		ddr->timing_cfg_4 = value;
> +		return;
> +	}
> +
> +	if (strcmp("timing_cfg_5", regname) == 0) {
> +		ddr->timing_cfg_5 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_zq_cntl", regname) == 0) {
> +		ddr->ddr_zq_cntl = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_wrlvl_cntl", regname) == 0) {
> +		ddr->ddr_wrlvl_cntl = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sr_cntr", regname) == 0) {
> +		ddr->ddr_sr_cntr = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_rcw_1", regname) == 0) {
> +		ddr->ddr_sdram_rcw_1 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_sdram_rcw_2", regname) == 0) {
> +		ddr->ddr_sdram_rcw_2 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_cdr1", regname) == 0) {
> +		ddr->ddr_cdr1 = value;
> +		return;
> +	}
> +
> +	if (strcmp("ddr_cdr2", regname) == 0) {
> +		ddr->ddr_cdr2 = value;
> +		return;
> +	}
> +
> +	if (strcmp("err_disable", regname) == 0) {
> +		ddr->err_disable = value;
> +		return;
> +	}
> +
> +	if (strcmp("err_int_en", regname) == 0) {
> +		ddr->err_int_en = value;
> +		return;
> +	}

Use string / pointer table and a loop.

...
> +#define PRINT_NXS(x, y, z) printf("%-3d    : %02x %s\n", x, y, z);
> +#define PRINT_NNXXS(n0, n1, x0, x1, s) printf("%-3d-%3d: %02x %02x %s\n", n0, n1, x0, x1, s);
> +#define PRINT_SNNlots(x, y, z, arr) do {printf(x); printf("%-3d-%3d: ", y, z); for (i = y; i <= z; i++) printf("%02x", arr[i - y]); } while (0)

Lines way too long; please fix globally.

...
> +				if (strcmp(argv[i], "dimmparms") == 0) {
> +					step_mask |= STEP_COMPUTE_DIMM_PARMS;
> +					continue;
> +				}
> +
> +				if (strcmp(argv[i], "commonparms") == 0) {
> +					step_mask |= STEP_COMPUTE_COMMON_PARMS;
> +					continue;
> +				}
> +
> +				if (strcmp(argv[i], "opts") == 0) {
> +					step_mask |= STEP_GATHER_OPTS;
> +					continue;
> +				}
> +
> +				if (strcmp(argv[i], "addresses") == 0) {
> +					step_mask |= STEP_ASSIGN_ADDRESSES;
> +					continue;
> +				}
> +
> +				if (strcmp(argv[i], "regs") == 0) {
> +					step_mask |= STEP_COMPUTE_REGS;
> +					continue;
> +				}

Here again the code could be made much smaller and easier to read by
using a data (table) driven approach and a loop through the table.
Please consider using this technique globally.


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
But it's real. And if it's real it can be affected ... we may not  be
able  to break it, but, I'll bet you credits to Navy Beans we can put
a dent in it.
	-- deSalle, "Catspaw", stardate 3018.2

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 10/10] Extend board specific parameters
  2010-12-09  2:55 ` [U-Boot] [PATCH 10/10] Extend board specific parameters York Sun
@ 2010-12-14  7:50   ` Wolfgang Denk
  0 siblings, 0 replies; 28+ messages in thread
From: Wolfgang Denk @ 2010-12-14  7:50 UTC (permalink / raw)
  To: u-boot

Dear York Sun,

In message <1291863340-4354-10-git-send-email-yorksun@freescale.com> you wrote:
> Extend board specific parameters to include write leveling start override
> Extend write leveling sample to 0xf
> Adding rcw overrid for quad-rank RDIMMs
> 
> Signed-off-by: York Sun <yorksun@freescale.com>
...

> +	/*	memory controller 0				*/
> +	/*	 lo|  hi|  num|  clk| wrlvl | cpo  |wrdata|2T	*/
> +	/*	mhz| mhz|ranks|adjst| start | delay|		*/

Incorrect multiline comment style.  Please fix globally.


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PLEASE NOTE: Some Quantum Physics Theories Suggest That When the Con-
sumer Is Not Directly Observing This Product, It May Cease  to  Exist
or Will Exist Only in a Vague and Undetermined State.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 07/10] Adding more SPD registers
  2010-12-09  2:55 ` [U-Boot] [PATCH 07/10] Adding more SPD registers York Sun
@ 2010-12-14  7:52   ` Wolfgang Denk
  0 siblings, 0 replies; 28+ messages in thread
From: Wolfgang Denk @ 2010-12-14  7:52 UTC (permalink / raw)
  To: u-boot

Dear York Sun,

In message <1291863340-4354-7-git-send-email-yorksun@freescale.com> you wrote:
> Adding byte 32 and 33
> 
> Signed-off-by: York Sun <yorksun@freescale.com>
> ---
>  include/ddr_spd.h |    4 +++-
>  1 files changed, 3 insertions(+), 1 deletions(-)
> 
> diff --git a/include/ddr_spd.h b/include/ddr_spd.h
> index 710e528..9fa305e 100644
> --- a/include/ddr_spd.h
> +++ b/include/ddr_spd.h
> @@ -219,7 +219,9 @@ typedef struct ddr3_spd_eeprom_s {
>  					     Delay Time*/
>  	unsigned char opt_features;    /* 30 SDRAM Optional Features */
>  	unsigned char therm_ref_opt;   /* 31 SDRAM Thermal and Refresh Opts */
> -	unsigned char res_32_59[28];   /* 32-59 Reserved, General Section */
> +	unsigned char therm_sensor;    /* 32 Module Thermal Sensor */
> +	unsigned char device_type;     /* SDRAM device type */

for consistency: make the comment "33 SDRAM device type".


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
We do not colonize. We conquer. We rule. There is no  other  way  for
us.
	-- Rojan, "By Any Other Name", stardate 4657.5

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 06/10] Enable unique mode registers and dynamic ODT for DDR3
  2010-12-09  2:55 ` [U-Boot] [PATCH 06/10] Enable unique mode registers and dynamic ODT for DDR3 York Sun
  2010-12-14  5:13   ` Kumar Gala
@ 2010-12-14  7:54   ` Wolfgang Denk
  1 sibling, 0 replies; 28+ messages in thread
From: Wolfgang Denk @ 2010-12-14  7:54 UTC (permalink / raw)
  To: u-boot

Dear York Sun,

In message <1291863340-4354-6-git-send-email-yorksun@freescale.com> you wrote:
> Added fsl_ddr_get_version() function to poll DDRC IP version (major, minor,
> errata) to determine if unique mode registers are available. This function may
> be needed for future other platforms if such a feature exists. If true, always

Then please resubmit when any platform gets added that actually uses
this.  Until then it would be just dead code.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Anything that is worth doing at all is worth doing well.
                                       -- Philip Earl of Chesterfield

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 01/10] Display RDIMM if detected
  2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
                   ` (8 preceding siblings ...)
  2010-12-09  2:55 ` [U-Boot] [PATCH 10/10] Extend board specific parameters York Sun
@ 2010-12-14  7:59 ` Wolfgang Denk
  9 siblings, 0 replies; 28+ messages in thread
From: Wolfgang Denk @ 2010-12-14  7:59 UTC (permalink / raw)
  To: u-boot

Dear York Sun,

In message <1291863340-4354-1-git-send-email-yorksun@freescale.com> you wrote:
> Print a message when a RDIMM is detected.

Please put an indication of affected boards / processors /
architectures in the Subject: ; like "mpc8xxx: ..."

(applies to all patches).

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Certainly there are things in life that money  can't  buy,  but  it's
very funny - Did you ever try buying them without money? - Ogden Nash

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH 09/10] Adding interactive ddr
  2010-12-14  7:47   ` Wolfgang Denk
@ 2010-12-14 15:07     ` Kumar Gala
  0 siblings, 0 replies; 28+ messages in thread
From: Kumar Gala @ 2010-12-14 15:07 UTC (permalink / raw)
  To: u-boot


On Dec 14, 2010, at 1:47 AM, Wolfgang Denk wrote:

> Dear York Sun,
> 
> In message <1291863340-4354-9-git-send-email-yorksun@freescale.com> you wrote:
>> Use environment variable to active the interactive debugging.
> ...
> 
> s/active/activate/
> 
>> diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/Makefile b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
>> index cb7f856..4bd416a 100644
>> --- a/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
>> +++ b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
>> @@ -11,15 +11,15 @@ include $(TOPDIR)/config.mk
>> LIB	= $(obj)libddr.a
>> 
>> COBJS-$(CONFIG_FSL_DDR1)	+= main.o util.o ctrl_regs.o options.o \
>> -				   lc_common_dimm_params.o
>> +				   lc_common_dimm_params.o interactive.o
>> COBJS-$(CONFIG_FSL_DDR1)	+= ddr1_dimm_params.o
>> 
>> COBJS-$(CONFIG_FSL_DDR2)	+= main.o util.o ctrl_regs.o options.o \
>> -				   lc_common_dimm_params.o
>> +				   lc_common_dimm_params.o interactive.o
>> COBJS-$(CONFIG_FSL_DDR2)	+= ddr2_dimm_params.o
>> 
>> COBJS-$(CONFIG_FSL_DDR3)	+= main.o util.o ctrl_regs.o options.o \
>> -				   lc_common_dimm_params.o
>> +				   lc_common_dimm_params.o interactive.o
>> COBJS-$(CONFIG_FSL_DDR3)	+= ddr3_dimm_params.o
> 
> Building interactive.o should depend on CONFIG_FSL_DDR_INTERACTIVE
> being set.

Agreed

> 
>> SRCS	:= $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
>> diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c
>> new file mode 100644
>> index 0000000..7d492a9
>> --- /dev/null
>> +++ b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c
>> @@ -0,0 +1,1882 @@
>> +/*
>> + * Copyright 2010 Freescale Semiconductor, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * Version 2 as published by the Free Software Foundation.
>> + */
> 
> NAK.   V2 or later is mandatory.

Yes, we will fix.

- k

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2010-12-14 15:07 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-12-09  2:55 [U-Boot] [PATCH 01/10] Display RDIMM if detected York Sun
2010-12-09  2:55 ` [U-Boot] [PATCH 02/10] make the hwconfig buffer deeper York Sun
2010-12-09 10:12   ` Wolfgang Denk
2010-12-10 18:50     ` York Sun
2010-12-14  4:59       ` Kumar Gala
2010-12-09  2:55 ` [U-Boot] [PATCH 03/10] Enable ECC on/off control in hwconfig York Sun
2010-12-09  2:55 ` [U-Boot] [PATCH 04/10] Enable ECC for corenet_ds York Sun
2010-12-09  2:55 ` [U-Boot] [PATCH 05/10] Adding more registers and options York Sun
2010-12-14  5:10   ` Kumar Gala
2010-12-14  6:30     ` York Sun
2010-12-14  6:37       ` Kumar Gala
2010-12-14  6:42         ` York Sun
2010-12-14  6:43           ` Kumar Gala
2010-12-09  2:55 ` [U-Boot] [PATCH 06/10] Enable unique mode registers and dynamic ODT for DDR3 York Sun
2010-12-14  5:13   ` Kumar Gala
2010-12-14  6:33     ` York Sun
2010-12-14  7:54   ` Wolfgang Denk
2010-12-09  2:55 ` [U-Boot] [PATCH 07/10] Adding more SPD registers York Sun
2010-12-14  7:52   ` Wolfgang Denk
2010-12-09  2:55 ` [U-Boot] [PATCH 08/10] Implement workaround for erratum DDRA003 York Sun
2010-12-14  6:47   ` Kumar Gala
2010-12-09  2:55 ` [U-Boot] [PATCH 09/10] Adding interactive ddr York Sun
2010-12-14  5:15   ` Kumar Gala
2010-12-14  7:47   ` Wolfgang Denk
2010-12-14 15:07     ` Kumar Gala
2010-12-09  2:55 ` [U-Boot] [PATCH 10/10] Extend board specific parameters York Sun
2010-12-14  7:50   ` Wolfgang Denk
2010-12-14  7:59 ` [U-Boot] [PATCH 01/10] Display RDIMM if detected Wolfgang Denk

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.