[U-Boot] [PATCH 2/2] fsl-ddr: add the DDR3 SPD infrastructure

Dave Liu daveliu at freescale.com
Sat Mar 14 05:48:30 CET 2009


- support mirrored DIMMs, not support register DIMMs
- test passed on P2020DS board with MT9JSF12872AY-1G1D1
- test passed on MPC8569MDS board with MT8JSF12864HY-1G1D1

Signed-off-by: Dave Liu <daveliu at freescale.com>
Signed-off-by: Travis Wheatley <travis.wheatley at freescale.com>
---
 common/ddr_spd.c                        |   53 +++++
 cpu/mpc85xx/ddr-gen3.c                  |    6 +-
 cpu/mpc8xxx/ddr/Makefile                |    4 +
 cpu/mpc8xxx/ddr/ctrl_regs.c             |  380 ++++++++++++++++++++++++++++---
 cpu/mpc8xxx/ddr/ddr3_dimm_params.c      |  314 +++++++++++++++++++++++++
 cpu/mpc8xxx/ddr/lc_common_dimm_params.c |   74 ++++++-
 cpu/mpc8xxx/ddr/options.c               |   28 ++-
 include/asm-ppc/fsl_ddr_dimm_params.h   |    7 +
 include/asm-ppc/fsl_ddr_sdram.h         |   31 +++-
 include/ddr_spd.h                       |   13 +-
 10 files changed, 860 insertions(+), 50 deletions(-)
 create mode 100644 cpu/mpc8xxx/ddr/ddr3_dimm_params.c

diff --git a/common/ddr_spd.c b/common/ddr_spd.c
index 78e3c5d..c058e4f 100644
--- a/common/ddr_spd.c
+++ b/common/ddr_spd.c
@@ -59,3 +59,56 @@ ddr2_spd_check(const ddr2_spd_eeprom_t *spd)
 
 	return spd_check(p, spd->spd_rev, spd->cksum);
 }
+
+/*
+ * CRC16 compute for DDR3 SPD
+ * Copied from DDR3 SPD spec.
+ */
+static int
+crc16(char *ptr, int count)
+{
+	int crc, i;
+
+	crc = 0;
+	while (--count >= 0) {
+		crc = crc ^ (int)*ptr++ << 8;
+		for (i = 0; i < 8; ++i)
+			if (crc & 0x8000)
+				crc = crc << 1 ^ 0x1021;
+			else
+				crc = crc << 1;
+	}
+	return crc & 0xffff;
+}
+
+unsigned int
+ddr3_spd_check(const ddr3_spd_eeprom_t *spd)
+{
+	char *p = (char *)spd;
+	int csum16;
+	int len;
+	char crc_lsb;	/* byte 126 */
+	char crc_msb;	/* byte 127 */
+
+	/*
+	 * SPD byte0[7] - CRC coverage
+	 * 0 = CRC covers bytes 0~125
+	 * 1 = CRC covers bytes 0~116
+	 */
+
+	len = !(spd->info_size_crc & 0x80) ? 126 : 117;
+	csum16 = crc16(p, len);
+
+	crc_lsb = (char) (csum16 & 0xff);
+	crc_msb = (char) (csum16 >> 8);
+
+	if (spd->crc[0] == crc_lsb && spd->crc[1] == crc_msb) {
+		return 0;
+	} else {
+		printf("SPD checksum unexpected.\n"
+			"Checksum lsb in SPD = %02X, computed SPD = %02X\n"
+			"Checksum msb in SPD = %02X, computed SPD = %02X\n",
+			spd->crc[0], crc_lsb, spd->crc[1], crc_msb);
+		return 1;
+	}
+}
diff --git a/cpu/mpc85xx/ddr-gen3.c b/cpu/mpc85xx/ddr-gen3.c
index 99c325a..8ac3d5f 100644
--- a/cpu/mpc85xx/ddr-gen3.c
+++ b/cpu/mpc85xx/ddr-gen3.c
@@ -98,10 +98,12 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 #endif
 
 	/*
-	 * 200 painful micro-seconds must elapse between
+	 * 500 painful micro-seconds must elapse between
 	 * the DDR clock setup and the DDR config enable.
+	 * DDR2 need 200 us, and DDR3 need 500 us from spec,
+	 * we choose the max, that is 500 us for all of case.
 	 */
-	udelay(200);
+	udelay(500);
 	asm volatile("sync;isync");
 
 	/* Let the controller go */
diff --git a/cpu/mpc8xxx/ddr/Makefile b/cpu/mpc8xxx/ddr/Makefile
index b7f8d8c..cb7f856 100644
--- a/cpu/mpc8xxx/ddr/Makefile
+++ b/cpu/mpc8xxx/ddr/Makefile
@@ -18,6 +18,10 @@ COBJS-$(CONFIG_FSL_DDR2)	+= main.o util.o ctrl_regs.o options.o \
 				   lc_common_dimm_params.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
+COBJS-$(CONFIG_FSL_DDR3)	+= ddr3_dimm_params.o
+
 SRCS	:= $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
 
diff --git a/cpu/mpc8xxx/ddr/ctrl_regs.c b/cpu/mpc8xxx/ddr/ctrl_regs.c
index 4c1498c..490e3dc 100644
--- a/cpu/mpc8xxx/ddr/ctrl_regs.c
+++ b/cpu/mpc8xxx/ddr/ctrl_regs.c
@@ -23,11 +23,18 @@ extern unsigned int picos_to_mclk(unsigned int picos);
  *
  * This should likely be either board or controller specific.
  *
- * Rtt(nominal):
+ * Rtt(nominal) - DDR2:
  *	0 = Rtt disabled
  *	1 = 75 ohm
  *	2 = 150 ohm
  *	3 = 50 ohm
+ * Rtt(nominal) - DDR3:
+ *	0 = Rtt disabled
+ *	1 = 60 ohm
+ *	2 = 120 ohm
+ *	3 = 40 ohm
+ *	4 = 20 ohm
+ *	5 = 30 ohm
  *
  * FIXME: Apparently 8641 needs a value of 2
  * FIXME: Old code seys if 667 MHz or higher, use 3 on 8572
@@ -53,12 +60,37 @@ static inline int fsl_ddr_get_rtt(void)
 #elif defined(CONFIG_FSL_DDR2)
 	rtt = 3;
 #else
-#error "Need Rtt value for DDR3"
+	rtt = 0;
 #endif
 
 	return rtt;
 }
 
+/*
+ * compute the CAS write latency according to DDR3 spec
+ * CWL = 5 if tCK >= 2.5ns
+ *       6 if 2.5ns > tCK >= 1.875ns
+ *       7 if 1.875ns > tCK >= 1.5ns
+ *       8 if 1.5ns > tCK >= 1.25ns
+ */
+static inline unsigned int compute_cas_write_latency(void)
+{
+	unsigned int cwl;
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+	if (mclk_ps >= 2500)
+		cwl = 5;
+	else if (mclk_ps >= 1875)
+		cwl = 6;
+	else if (mclk_ps >= 1500)
+		cwl = 7;
+	else if (mclk_ps >= 1250)
+		cwl = 8;
+	else
+		cwl = 8;
+	return cwl;
+}
+
 /* Chip Select Configuration (CSn_CONFIG) */
 static void set_csn_config(int i, fsl_ddr_cfg_regs_t *ddr,
 			       const memctl_options_t *popts,
@@ -126,7 +158,7 @@ static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)
 
 /* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */
 
-#if defined(CONFIG_FSL_DDR2)
+#if !defined(CONFIG_FSL_DDR1)
 /*
  * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0)
  *
@@ -150,16 +182,32 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr)
 	/* Mode register set cycle time (tMRD). */
 	unsigned char tmrd_mclk;
 
-	/* (tXARD and tXARDS). Empirical? */
-	act_pd_exit_mclk = 2;
-
-	/* XXX:  tXARD = 2, tXARDS = 7 - AL. * Empirical? */
+#if defined(CONFIG_FSL_DDR3)
+	/*
+	 * (tXARD and tXARDS). Empirical?
+	 * The DDR3 spec has not tXARD,
+	 * we use the tXP instead of it.
+	 * tXP=max(3nCK, 7.5ns) for DDR3.
+	 * we use the tXP=6
+	 * spec has not the tAXPD, we use
+	 * tAXPD=8, need design to confirm.
+	 */
+	act_pd_exit_mclk = 6;
 	pre_pd_exit_mclk = 6;
-
-	/* FIXME:  tXP = 2 on Micron 667 MHz DIMM */
 	taxpd_mclk = 8;
-
+	tmrd_mclk = 4;
+#else /* CONFIG_FSL_DDR2 */
+	/*
+	 * (tXARD and tXARDS). Empirical?
+	 * tXARD = 2 for DDR2
+	 * tXP=2
+	 * tAXPD=8
+	 */
+	act_pd_exit_mclk = 2;
+	pre_pd_exit_mclk = 2;
+	taxpd_mclk = 8;
 	tmrd_mclk = 2;
+#endif
 
 	ddr->timing_cfg_0 = (0
 		| ((trwt_mclk & 0x3) << 30)	/* RWT */
@@ -177,7 +225,8 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr)
 
 /* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */
 static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr,
-			       const common_timing_params_t *common_dimm)
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency)
 {
 	/* Extended Activate to precharge interval (tRAS) */
 	unsigned int ext_acttopre = 0;
@@ -190,6 +239,11 @@ static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr,
 		ext_acttopre = 1;
 
 	ext_refrec = (picos_to_mclk(common_dimm->tRFC_ps) - 8) >> 4;
+
+	/* If the CAS latency more than 8, use the ext mode */
+	if (cas_latency > 8)
+		ext_caslat = 1;
+
 	ddr->timing_cfg_3 = (0
 		| ((ext_acttopre & 0x1) << 24)
 		| ((ext_refrec & 0xF) << 16)
@@ -201,6 +255,7 @@ static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr,
 
 /* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */
 static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
 			       const common_timing_params_t *common_dimm,
 			       unsigned int cas_latency)
 {
@@ -246,13 +301,42 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
 #elif defined(CONFIG_FSL_DDR2)
 	caslat_ctrl = 2 * cas_latency - 1;
 #else
-#error "Need CAS Latency help for DDR3 in fsl_ddr_sdram.c"
+	/*
+	 * if the CAS latency more than 8 cycle,
+	 * we need set extend bit for it at
+	 * TIMING_CFG_3[EXT_CASLAT]
+	 */
+	if (cas_latency > 8)
+		cas_latency -= 8;
+	caslat_ctrl = 2 * cas_latency - 1;
 #endif
 
 	refrec_ctrl = picos_to_mclk(common_dimm->tRFC_ps) - 8;
 	wrrec_mclk = picos_to_mclk(common_dimm->tWR_ps);
+	if (popts->OTF_burst_chop_en)
+		wrrec_mclk += 2;
+
 	acttoact_mclk = picos_to_mclk(common_dimm->tRRD_ps);
+	/*
+	 * JEDEC has min requirement for tRRD
+	 */
+#if defined(CONFIG_FSL_DDR3)
+	if (acttoact_mclk < 4)
+		acttoact_mclk = 4;
+#endif
 	wrtord_mclk = picos_to_mclk(common_dimm->tWTR_ps);
+	/*
+	 * JEDEC has some min requirements for tWTR
+	 */
+#if defined(CONFIG_FSL_DDR2)
+	if (wrtord_mclk < 2)
+		wrtord_mclk = 2;
+#elif defined(CONFIG_FSL_DDR3)
+	if (wrtord_mclk < 4)
+		wrtord_mclk = 4;
+#endif
+	if (popts->OTF_burst_chop_en)
+		wrtord_mclk += 2;
 
 	ddr->timing_cfg_1 = (0
 		| ((pretoact_mclk & 0x0F) << 28)
@@ -304,13 +388,25 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 #elif defined(CONFIG_FSL_DDR2)
 	wr_lat = cas_latency - 1;
 #else
-#error "Fix WR_LAT for DDR3"
+	wr_lat = compute_cas_write_latency();
 #endif
 
 	rd_to_pre = picos_to_mclk(common_dimm->tRTP_ps);
+	/*
+	 * JEDEC has some min requirements for tRTP
+	 */
 #if defined(CONFIG_FSL_DDR2)
-	rd_to_pre += additive_latency;
+	if (rd_to_pre  < 2)
+		rd_to_pre  = 2;
+#elif defined(CONFIG_FSL_DDR3)
+	if (rd_to_pre < 4)
+		rd_to_pre = 4;
 #endif
+	if (additive_latency)
+		rd_to_pre += additive_latency;
+	if (popts->OTF_burst_chop_en)
+		rd_to_pre += 2; /* according to UM */
+
 	wr_data_delay = popts->write_data_delay;
 	cke_pls = picos_to_mclk(popts->tCKE_clock_pulse_width_ps);
 	four_act = picos_to_mclk(popts->tFAW_window_four_activates_ps);
@@ -319,8 +415,8 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 		| ((add_lat_mclk & 0xf) << 28)
 		| ((cpo & 0x1f) << 23)
 		| ((wr_lat & 0xf) << 19)
-		| ((rd_to_pre & 0x7) << 13)
-		| ((wr_data_delay & 0x7) << 10)
+		| ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT)
+		| ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT)
 		| ((cke_pls & 0x7) << 6)
 		| ((four_act & 0x3f) << 0)
 		);
@@ -366,9 +462,19 @@ static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
 
 	dyn_pwr = popts->dynamic_power;
 	dbw = popts->data_bus_width;
-	/* DDR3 must use 8-beat bursts when using 32-bit bus mode */
-	if ((sdram_type == SDRAM_TYPE_DDR3) && (dbw == 0x1))
-		eight_be = 1;
+	/* 8-beat burst enable DDR-III case
+	 * we must clear it when use the on-the-fly mode,
+	 * must set it when use the 32-bits bus mode.
+	 */
+	if (sdram_type == SDRAM_TYPE_DDR3) {
+		if (popts->burst_length == DDR_BL8)
+			eight_be = 1;
+		if (popts->burst_length == DDR_OTF)
+			eight_be = 0;
+		if (dbw == 0x1)
+			eight_be = 1;
+	}
+
 	threeT_en = popts->threeT_en;
 	twoT_en = popts->twoT_en;
 	ba_intlv_ctl = popts->ba_intlv_ctl;
@@ -431,8 +537,12 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 	 *        * ({EXT_REFREC || REFREC} + 8 + 2)]}
 	 *      << DDR_SDRAM_INTERVAL[REFINT]
 	 */
+#if defined(CONFIG_FSL_DDR3)
+	obc_cfg = popts->OTF_burst_chop_en;
+#else
+	obc_cfg = 0;
+#endif
 
-	obc_cfg = 0;	/* Make this configurable? */
 	ap_en = 0;	/* Make this configurable? */
 
 #if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
@@ -445,6 +555,9 @@ static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 	d_init = 0;
 #endif
 
+#if defined(CONFIG_FSL_DDR3)
+	md_en = popts->mirrored_dimm;
+#endif
 	ddr->ddr_sdram_cfg_2 = (0
 		| ((frc_sr & 0x1) << 31)
 		| ((sr_ie & 0x1) << 30)
@@ -467,6 +580,20 @@ static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr)
 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
 
+#if defined(CONFIG_FSL_DDR3)
+	unsigned int rtt_wr = 2;	/* 120 ohm Rtt_WR */
+	unsigned int srt = 0;	/* self-refresh temerature, normal range */
+	unsigned int asr = 0;	/* auto self-refresh disable */
+	unsigned int cwl = compute_cas_write_latency() - 5;
+	unsigned int pasr = 0;	/* partial array self refresh disable */
+
+	esdmode2 = (0
+		| ((rtt_wr & 0x3) << 9)
+		| ((srt & 0x1) << 7)
+		| ((asr & 0x1) << 6)
+		| ((cwl & 0x7) << 3)
+		| ((pasr & 0x7) << 0));
+#endif
 	ddr->ddr_sdram_mode_2 = (0
 				 | ((esdmode2 & 0xFFFF) << 16)
 				 | ((esdmode3 & 0xFFFF) << 0)
@@ -494,6 +621,139 @@ static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr,
 	debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval);
 }
 
+#if defined(CONFIG_FSL_DDR3)
+/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
+static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency,
+			       unsigned int additive_latency)
+{
+	unsigned short esdmode;		/* Extended SDRAM mode */
+	unsigned short sdmode;		/* SDRAM mode */
+
+	/* Mode Register - MR1 */
+	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
+	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
+	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 dll_en = 0;	/* DLL Enable  0=Enable (Normal),
+						       1=Disable (Test/Debug) */
+
+	/* Mode Register - MR0 */
+	unsigned int dll_on;	/* DLL control for precharge PD, 0=off, 1=on */
+	unsigned int wr;	/* Write Recovery */
+	unsigned int dll_rst;	/* DLL Reset */
+	unsigned int mode;	/* Normal=0 or Test=1 */
+	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
+	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
+	unsigned int bt;
+	unsigned int bl;	/* BL: Burst Length */
+
+	unsigned int wr_mclk;
+
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+	rtt = fsl_ddr_get_rtt();
+	if (popts->rtt_override)
+		rtt = popts->rtt_override_value;
+
+	if (additive_latency == (cas_latency - 1))
+		al = 1;
+	if (additive_latency == (cas_latency - 2))
+		al = 2;
+
+	/*
+	 * The esdmode value will also be used for writing
+	 * MR1 during write leveling for DDR3, although the
+	 * bits specifically related to the write leveling
+	 * scheme will be handled automatically by the DDR
+	 * controller. so we set the wrlvl_en = 0 here.
+	 */
+	esdmode = (0
+		| ((qoff & 0x1) << 12)
+		| ((tdqs_en & 0x1) << 11)
+		| ((rtt & 0x4) << 9)   /* rtt field is split */
+		| ((wrlvl_en & 0x1) << 7)
+		| ((rtt & 0x2) << 6)   /* rtt field is split */
+		| ((dic & 0x2) << 5)   /* DIC field is split */
+		| ((al & 0x3) << 3)
+		| ((rtt & 0x1) << 2)   /* rtt field is split */
+		| ((dic & 0x1) << 1)   /* DIC field is split */
+		| ((dll_en & 0x1) << 0)
+		);
+
+	/*
+	 * DLL control for precharge PD
+	 * 0=slow exit DLL off (tXPDLL)
+	 * 1=fast exit DLL on (tXP)
+	 */
+	dll_on = 1;
+	wr_mclk = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps;
+	if (wr_mclk >= 12)
+		wr = 6;
+	else if (wr_mclk >= 9)
+		wr = 5;
+	else
+		wr = wr_mclk - 4;
+	dll_rst = 0;	/* dll no reset */
+	mode = 0;	/* normal mode */
+
+	/* look up table to get the cas latency bits */
+	if (cas_latency >= 5 && cas_latency <= 11) {
+		unsigned char cas_latency_table[7] = {
+			0x2,	/* 5 clocks */
+			0x4,	/* 6 clocks */
+			0x6,	/* 7 clocks */
+			0x8,	/* 8 clocks */
+			0xa,	/* 9 clocks */
+			0xc,	/* 10 clocks */
+			0xe	/* 11 clocks */
+		};
+		caslat = cas_latency_table[cas_latency - 5];
+	}
+	bt = 0;	/* Nibble sequential */
+
+	switch (popts->burst_length) {
+	case DDR_BL8:
+		bl = 0;
+		break;
+	case DDR_OTF:
+		bl = 1;
+		break;
+	case DDR_BC4:
+		bl = 2;
+		break;
+	default:
+		printf("Error: invalid burst length of %u specified. "
+			" Defaulting to on-the-fly BC4 or BL8 beats.\n",
+			popts->burst_length);
+		bl = 1;
+		break;
+	}
+
+	sdmode = (0
+		  | ((dll_on & 0x1) << 12)
+		  | ((wr & 0x7) << 9)
+		  | ((dll_rst & 0x1) << 8)
+		  | ((mode & 0x1) << 7)
+		  | (((caslat >> 1) & 0x7) << 4)
+		  | ((bt & 0x1) << 3)
+		  | ((bl & 0x3) << 0)
+		  );
+
+	ddr->ddr_sdram_mode = (0
+			       | ((esdmode & 0xFFFF) << 16)
+			       | ((sdmode & 0xFFFF) << 0)
+			       );
+
+	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
+}
+
+#else /* !CONFIG_FSL_DDR3 */
+
 /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
 static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 			       const memctl_options_t *popts,
@@ -570,8 +830,6 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 	wr = 0;       /* Historical */
 #elif defined(CONFIG_FSL_DDR2)
 	wr = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps - 1;
-#else
-#error "Write tWR_auto for DDR3"
 #endif
 	dll_res = 0;
 	mode = 0;
@@ -590,16 +848,14 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 	}
 #elif defined(CONFIG_FSL_DDR2)
 	caslat = cas_latency;
-#else
-#error "Fix the mode CAS Latency for DDR3"
 #endif
 	bt = 0;
 
 	switch (popts->burst_length) {
-	case 4:
+	case DDR_BL4:
 		bl = 2;
 		break;
-	case 8:
+	case DDR_BL8:
 		bl = 3;
 		break;
 	default:
@@ -627,7 +883,7 @@ static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 			       );
 	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
 }
-
+#endif
 
 /* DDR SDRAM Data Initialization (DDR_DATA_INIT) */
 static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr)
@@ -681,6 +937,12 @@ static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr)
 	unsigned int wwt = 0; /* Write-to-write turnaround for same CS */
 	unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */
 
+#if defined(CONFIG_FSL_DDR3)
+	/* We need set BL/2 + 4 for BC4 or OTF */
+	rrt = 4;	/* BL/2 + 4 clocks */
+	wwt = 4;	/* BL/2 + 4 clocks */
+	dll_lock = 1;	/* tDLLK = 512 clocks from spec */
+#endif
 	ddr->timing_cfg_4 = (0
 			     | ((rwt & 0xf) << 28)
 			     | ((wrt & 0xf) << 24)
@@ -699,6 +961,13 @@ static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr)
 	unsigned int wodt_on = 0;	/* Write to ODT on */
 	unsigned int wodt_off = 0;	/* Write to ODT off */
 
+#if defined(CONFIG_FSL_DDR3)
+	rodt_on = 3;	/*  2 clocks */
+	rodt_off = 4;	/*  4 clocks */
+	wodt_on = 2;	/*  1 clocks */
+	wodt_off = 4;	/*  4 clocks */
+#endif
+
 	ddr->timing_cfg_5 = (0
 			     | ((rodt_on & 0x1f) << 24)
 			     | ((rodt_off & 0x7) << 20)
@@ -709,15 +978,20 @@ static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr)
 }
 
 /* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */
-static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr)
+static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
 {
-	unsigned int zq_en = 0;	/* ZQ Calibration Enable */
 	unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */
 	/* Normal Operation Full Calibration Time (tZQoper) */
 	unsigned int zqoper = 0;
 	/* Normal Operation Short Calibration Time (tZQCS) */
 	unsigned int zqcs = 0;
 
+	if (zq_en) {
+		zqinit = 9;	/* 512 clocks */
+		zqoper = 8;	/* 256 clocks */
+		zqcs = 6;	/* 64 clocks */
+	}
+
 	ddr->ddr_zq_cntl = (0
 			    | ((zq_en & 0x1) << 31)
 			    | ((zqinit & 0xF) << 24)
@@ -727,9 +1001,9 @@ static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr)
 }
 
 /* DDR Write Leveling Control (DDR_WRLVL_CNTL) */
-static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr)
+static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr,
+			       unsigned int wrlvl_en)
 {
-	unsigned int wrlvl_en = 0; /* Write Leveling Enable */
 	/*
 	 * First DQS pulse rising edge after margining mode
 	 * is programmed (tWL_MRD)
@@ -746,6 +1020,34 @@ static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr)
 	/* WRLVL_START: Write leveling start time */
 	unsigned int wrlvl_start = 0;
 
+	/* suggest enable write leveling for DDR3 due to fly-by topology */
+	if (wrlvl_en) {
+		/* tWL_MRD min = 40 nCK, we set it 64 */
+		wrlvl_mrd = 0x6;
+		/* tWL_ODTEN 128 */
+		wrlvl_odten = 0x7;
+		/* tWL_DQSEN min = 25 nCK, we set it 32 */
+		wrlvl_dqsen = 0x5;
+		/*
+		 * Write leveling sample time at least need 14 clocks
+		 * due to tWLO = 9, we set it 15 clocks
+		 */
+		wrlvl_smpl = 0xf;
+		/*
+		 * Write leveling repetition time
+		 * at least tWLO + 6 clocks clocks
+		 * we set it 32
+		 */
+		wrlvl_wlr = 0x5;
+		/*
+		 * Write leveling start time
+		 * The value use for the DQS_ADJUST for the first sample
+		 * when write leveling is enabled.
+		 * we set it 1 clock delay
+		 */
+		wrlvl_start = 0x8;
+	}
+
 	ddr->ddr_wrlvl_cntl = (0
 			       | ((wrlvl_en & 0x1) << 31)
 			       | ((wrlvl_mrd & 0x7) << 24)
@@ -864,6 +1166,8 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 	unsigned int cas_latency;
 	unsigned int additive_latency;
 	unsigned int sr_it;
+	unsigned int zq_en;
+	unsigned int wrlvl_en;
 
 	memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t));
 
@@ -888,6 +1192,10 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 	sr_it = (popts->auto_self_refresh_en)
 		? popts->sr_it
 		: 0;
+	/* ZQ calibration */
+	zq_en = (popts->zq_en) ? 1 : 0;
+	/* write leveling */
+	wrlvl_en = (popts->wrlvl_en) ? 1 : 0;
 
 	/* Chip Select Memory Bounds (CSn_BNDS) */
 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
@@ -1022,12 +1330,12 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 		set_csn_config_2(i, ddr);
 	}
 
-#if defined(CONFIG_FSL_DDR2)
+#if !defined(CONFIG_FSL_DDR1)
 	set_timing_cfg_0(ddr);
 #endif
 
-	set_timing_cfg_3(ddr, common_dimm);
-	set_timing_cfg_1(ddr, common_dimm, cas_latency);
+	set_timing_cfg_3(ddr, common_dimm, cas_latency);
+	set_timing_cfg_1(ddr, popts, common_dimm, cas_latency);
 	set_timing_cfg_2(ddr, popts, common_dimm,
 				cas_latency, additive_latency);
 
@@ -1045,8 +1353,8 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 	set_timing_cfg_4(ddr);
 	set_timing_cfg_5(ddr);
 
-	set_ddr_zq_cntl(ddr);
-	set_ddr_wrlvl_cntl(ddr);
+	set_ddr_zq_cntl(ddr, zq_en);
+	set_ddr_wrlvl_cntl(ddr, wrlvl_en);
 
 	set_ddr_pd_cntl(ddr);
 	set_ddr_sr_cntr(ddr, sr_it);
diff --git a/cpu/mpc8xxx/ddr/ddr3_dimm_params.c b/cpu/mpc8xxx/ddr/ddr3_dimm_params.c
new file mode 100644
index 0000000..ca4be78
--- /dev/null
+++ b/cpu/mpc8xxx/ddr/ddr3_dimm_params.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2008 Freescale Semiconductor, Inc.
+ *	Dave Liu <daveliu at freescale.com>
+ *
+ * calculate the organization and timing parameter
+ * from ddr3 spd, please refer to the spec
+ * JEDEC standard No.21-C 4_01_02_11R18.pdf
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * each rank size =
+ * sdram capacity(bit) / 8 * primary bus width / sdram width
+ *
+ * where: sdram capacity  = spd byte4[3:0]
+ *        primary bus width = spd byte8[2:0]
+ *        sdram width = spd byte7[2:0]
+ *
+ * SPD byte4 - sdram density and banks
+ *	bit[3:0]	size(bit)	size(byte)
+ *	0000		256Mb		32MB
+ *	0001		512Mb		64MB
+ *	0010		1Gb		128MB
+ *	0011		2Gb		256MB
+ *	0100		4Gb		512MB
+ *	0101		8Gb		1GB
+ *	0110		16Gb		2GB
+ *
+ * SPD byte8 - module memory bus width
+ * 	bit[2:0]	primary bus width
+ *	000		8bits
+ * 	001		16bits
+ * 	010		32bits
+ * 	011		64bits
+ *
+ * SPD byte7 - module organiztion
+ * 	bit[2:0]	sdram device width
+ * 	000		4bits
+ * 	001		8bits
+ * 	010		16bits
+ * 	011		32bits
+ *
+ */
+static phys_size_t
+compute_ranksize(const ddr3_spd_eeprom_t *spd)
+{
+	phys_size_t bsize;
+
+	int nbit_sdram_cap_bsize = 0;
+	int nbit_primary_bus_width = 0;
+	int nbit_sdram_width = 0;
+
+	if ((spd->density_banks & 0xf) < 7)
+		nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28;
+	if ((spd->bus_width & 0x7) < 4)
+		nbit_primary_bus_width = (spd->bus_width & 0x7) + 3;
+	if ((spd->organization & 0x7) < 4)
+		nbit_sdram_width = (spd->organization & 0x7) + 2;
+
+	bsize = 1 << (nbit_sdram_cap_bsize - 3
+		    + nbit_primary_bus_width - nbit_sdram_width);
+
+	debug("DDR: DDR III rank density = 0x%08x\n", bsize);
+
+	return bsize;
+}
+
+/*
+ * ddr_compute_dimm_parameters for DDR3 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ */
+unsigned int
+ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd,
+			     dimm_params_t *pdimm,
+			     unsigned int dimm_number)
+{
+	unsigned int retval;
+	unsigned int mtb_ps;
+
+	if (spd->mem_type) {
+		if (spd->mem_type != SPD_MEMTYPE_DDR3) {
+			printf("DIMM %u: is not a DDR3 SPD.\n", dimm_number);
+			return 1;
+		}
+	} else {
+		memset(pdimm, 0, sizeof(dimm_params_t));
+		return 1;
+	}
+
+	retval = ddr3_spd_check(spd);
+	if (retval) {
+		printf("DIMM %u: failed checksum\n", dimm_number);
+		return 2;
+	}
+
+	/*
+	 * The part name in ASCII in the SPD EEPROM is not null terminated.
+	 * Guarantee null termination here by presetting all bytes to 0
+	 * and copying the part name in ASCII from the SPD onto it
+	 */
+	memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+	memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+	/* DIMM organization parameters */
+	pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1;
+	pdimm->rank_density = compute_ranksize(spd);
+	pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+	pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7));
+	if ((spd->bus_width >> 3) & 0x3)
+		pdimm->ec_sdram_width = 8;
+	else
+		pdimm->ec_sdram_width = 0;
+	pdimm->data_width = pdimm->primary_sdram_width
+			  + pdimm->ec_sdram_width;
+
+	switch (spd->module_type & 0xf) {
+	case 0x01:	/* RDIMM */
+	case 0x05:	/* Mini-RDIMM */
+		pdimm->registered_dimm = 1; /* register buffered */
+		break;
+
+	case 0x02:	/* UDIMM */
+	case 0x03:	/* SO-DIMM */
+	case 0x04:	/* Micro-DIMM */
+	case 0x06:	/* Mini-UDIMM */
+		pdimm->registered_dimm = 0;	/* unbuffered */
+		break;
+
+	default:
+		printf("unknown dimm_type 0x%02X\n", spd->module_type);
+		return 1;
+	}
+
+	/* SDRAM device parameters */
+	pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12;
+	pdimm->n_col_addr = (spd->addressing & 0x7) + 9;
+	pdimm->n_banks_per_sdram_device = 8 << ((spd->density_banks >> 4) & 0x7);
+
+	/*
+	 * The SPD spec has not the ECC bit,
+	 * We consider the DIMM as ECC capability
+	 * when the extension bus exist
+	 */
+	if (pdimm->ec_sdram_width)
+		pdimm->edc_config = 0x02;
+	else
+		pdimm->edc_config = 0x00;
+
+	/*
+	 * The SPD spec has not the burst length byte
+	 * but DDR3 spec has nature BL8 and BC4,
+	 * BL8 -bit3, BC4 -bit2
+	 */
+	pdimm->burst_lengths_bitmask = 0x0c;
+	pdimm->row_density = __ilog2(pdimm->rank_density);
+
+	/* MTB - medium timebase
+	 * The unit in the SPD spec is ns,
+	 * We convert it to ps.
+	 * eg: MTB = 0.125ns (125ps)
+	 */
+	mtb_ps = (spd->mtb_dividend * 1000) /spd->mtb_divisor;
+	pdimm->mtb_ps = mtb_ps;
+
+	/*
+	 * sdram minimum cycle time
+	 * we assume the MTB is 0.125ns
+	 * eg:
+	 * tCK_min=15 MTB (1.875ns) ->DDR3-1066
+	 *        =12 MTB (1.5ns) ->DDR3-1333
+	 *        =10 MTB (1.25ns) ->DDR3-1600
+	 */
+	pdimm->tCKmin_X_ps = spd->tCK_min * mtb_ps;
+
+	/*
+	 * CAS latency supported
+	 * bit4 - CL4
+	 * bit5 - CL5
+	 * bit18 - CL18
+	 */
+	pdimm->caslat_X  = ((spd->caslat_msb << 8) | spd->caslat_lsb) << 4;
+
+	/*
+	 * min CAS latency time
+	 * eg: tAA_min =
+	 * DDR3-800D	100 MTB (12.5ns)
+	 * DDR3-1066F	105 MTB (13.125ns)
+	 * DDR3-1333H	108 MTB (13.5ns)
+	 * DDR3-1600H	90 MTB (11.25ns)
+	 */
+	pdimm->tAA_ps = spd->tAA_min * mtb_ps;
+
+	/*
+	 * min write recovery time
+	 * eg:
+	 * tWR_min = 120 MTB (15ns) -> all speed grades.
+	 */
+	pdimm->tWR_ps = spd->tWR_min * mtb_ps;
+
+	/*
+	 * min RAS to CAS delay time
+	 * eg: tRCD_min =
+	 * DDR3-800	100 MTB (12.5ns)
+	 * DDR3-1066F	105 MTB (13.125ns)
+	 * DDR3-1333H	108 MTB (13.5ns)
+	 * DDR3-1600H	90 MTB (11.25)
+	 */
+	pdimm->tRCD_ps = spd->tRCD_min * mtb_ps;
+
+	/*
+	 * min row active to row active delay time
+	 * eg: tRRD_min =
+	 * DDR3-800(1KB page)	80 MTB (10ns)
+	 * DDR3-1333(1KB page)	48 MTB (6ns)
+	 */
+	pdimm->tRRD_ps = spd->tRRD_min * mtb_ps;
+
+	/*
+	 * min row precharge delay time
+	 * eg: tRP_min =
+	 * DDR3-800D	100 MTB (12.5ns)
+	 * DDR3-1066F	105 MTB (13.125ns)
+	 * DDR3-1333H	108 MTB (13.5ns)
+	 * DDR3-1600H	90 MTB (11.25ns)
+	 */
+	pdimm->tRP_ps = spd->tRP_min * mtb_ps;
+
+	/* min active to precharge delay time
+	 * eg: tRAS_min =
+	 * DDR3-800D	300 MTB (37.5ns)
+	 * DDR3-1066F	300 MTB (37.5ns)
+	 * DDR3-1333H	288 MTB (36ns)
+	 * DDR3-1600H	280 MTB (35ns)
+	 */
+	pdimm->tRAS_ps = (((spd->tRAS_tRC_ext & 0xf) << 8) | spd->tRAS_min_lsb)
+			* mtb_ps;
+	/*
+	 * min active to actice/refresh delay time
+	 * eg: tRC_min =
+	 * DDR3-800D	400 MTB (50ns)
+	 * DDR3-1066F	405 MTB (50.625ns)
+	 * DDR3-1333H	396 MTB (49.5ns)
+	 * DDR3-1600H	370 MTB (46.25ns)
+	 */
+	pdimm->tRC_ps = (((spd->tRAS_tRC_ext & 0xf0) << 4) | spd->tRC_min_lsb)
+			* mtb_ps;
+	/*
+	 * min refresh recovery delay time
+	 * eg: tRFC_min =
+	 * 512Mb	720 MTB (90ns)
+	 * 1Gb		880 MTB (110ns)
+	 * 2Gb		1280 MTB (160ns)
+	 */
+	pdimm->tRFC_ps = ((spd->tRFC_min_msb << 8) | spd->tRFC_min_lsb)
+			* mtb_ps;
+	/*
+	 * min internal write to read command delay time
+	 * eg: tWTR_min = 40 MTB (7.5ns) - all speed bins.
+	 * tWRT is at least 4 mclk independent of operating freq.
+	 */
+	pdimm->tWTR_ps = spd->tWTR_min * mtb_ps;
+
+	/*
+	 * min internal read to precharge command delay time
+	 * eg: tRTP_min = 40 MTB (7.5ns) - all speed bins.
+	 * tRTP is at least 4 mclk independent of operating freq.
+	 */
+	pdimm->tRTP_ps = spd->tRTP_min * mtb_ps;
+
+	/*
+	 * Average periodic refresh interval
+	 * tREFI = 7.8 us at normal temperature range
+	 *       = 3.9 us at ext temperature range
+	 */
+	pdimm->refresh_rate_ps = 7800000;
+
+	/*
+	 * min four active window delay time
+	 * eg: tFAW_min =
+	 * DDR3-800(1KB page)	320 MTB (40ns)
+	 * DDR3-1066(1KB page)	300 MTB (37.5ns)
+	 * DDR3-1333(1KB page)	240 MTB (30ns)
+	 * DDR3-1600(1KB page)	240 MTB (30ns)
+	 */
+	pdimm->tFAW_ps = (((spd->tFAW_msb & 0xf) << 8) | spd->tFAW_min)
+			* mtb_ps;
+
+	/*
+	 * We need check the address mirror for unbuffered DIMM
+	 * If SPD indicate the address map mirror, The DDR controller
+	 * need care it.
+	 */
+	if ((spd->module_type == SPD_MODULETYPE_UDIMM) ||
+	    (spd->module_type == SPD_MODULETYPE_SODIMM) ||
+	    (spd->module_type == SPD_MODULETYPE_MICRODIMM) ||
+	    (spd->module_type == SPD_MODULETYPE_MINIUDIMM))
+		pdimm->mirrored_dimm = spd->mod_section.unbuffered.addr_mapping & 0x1;
+
+	return 0;
+}
diff --git a/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
index fbeb236..a845a89 100644
--- a/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
+++ b/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
@@ -11,6 +11,59 @@
 
 #include "ddr.h"
 
+unsigned int
+compute_cas_latency_ddr3(const dimm_params_t *dimm_params,
+			 common_timing_params_t *outpdimm,
+			 unsigned int number_of_dimms)
+{
+	unsigned int i;
+	unsigned int tAAmin_ps = 0;
+	unsigned int tCKmin_X_ps = 0;
+	unsigned int common_caslat;
+	unsigned int caslat_actual;
+	unsigned int retry = 16;
+	unsigned int tmp;
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+	/* compute the common CAS latency supported between slots */
+	tmp = dimm_params[0].caslat_X;
+	for (i = 1; i < number_of_dimms; i++)
+		 tmp &= dimm_params[i].caslat_X;
+	common_caslat = tmp;
+
+	/* compute the max tAAmin tCKmin between slots */
+	for (i = 0; i < number_of_dimms; i++) {
+		tAAmin_ps = max(tAAmin_ps, dimm_params[i].tAA_ps);
+		tCKmin_X_ps = max(tCKmin_X_ps, dimm_params[i].tCKmin_X_ps);
+	}
+	/* validate if the memory clk is in the range of dimms */
+	if (mclk_ps < tCKmin_X_ps) {
+		printf("The DIMM max tCKmin is %d ps,"
+			"doesn't support the MCLK cycle %d ps\n",
+			tCKmin_X_ps, mclk_ps);
+		return 1;
+	}
+	/* determine the acutal cas latency */
+	caslat_actual = (tAAmin_ps + mclk_ps - 1) / mclk_ps;
+	/* check if the dimms support the CAS latency */
+	while (!(common_caslat & (1 << caslat_actual)) && retry > 0) {
+		caslat_actual++;
+		retry--;
+	}
+	/* once the caculation of caslat_actual is completed
+	 * we must verify that this CAS latency value does not
+	 * exceed tAAmax, which is 20 ns for all DDR3 speed grades
+	 */
+	if (caslat_actual * mclk_ps > 20000) {
+		printf("The choosen cas latency %d is too large\n",
+			caslat_actual);
+		return 1;
+	}
+	outpdimm->lowest_common_SPD_caslat = caslat_actual;
+
+	return 0;
+}
+
 /*
  * compute_lowest_common_dimm_parameters()
  *
@@ -46,10 +99,12 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	unsigned int tQHS_ps = 0;
 
 	unsigned int temp1, temp2;
-	unsigned int lowest_good_caslat;
 	unsigned int additive_latency = 0;
 	const unsigned int mclk_ps = get_memory_clk_period_ps();
+#if !defined(CONFIG_FSL_DDR3)
+	unsigned int lowest_good_caslat;
 	unsigned int not_ok;
+#endif
 
 	debug("using mclk_ps = %u\n", mclk_ps);
 
@@ -164,6 +219,10 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 				"DIMMs detected!\n");
 	}
 
+#if defined(CONFIG_FSL_DDR3)
+	if (compute_cas_latency_ddr3(dimm_params, outpdimm, number_of_dimms))
+		return 1;
+#else
 	/*
 	 * Compute a CAS latency suitable for all DIMMs
 	 *
@@ -281,6 +340,7 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	}
 	outpdimm->highest_common_derated_caslat = temp1;
 	debug("highest common dereated CAS latency = %u\n", temp1);
+#endif /* #if defined(CONFIG_FSL_DDR3) */
 
 	/* Determine if all DIMMs ECC capable. */
 	temp1 = 1;
@@ -297,14 +357,14 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	}
 	outpdimm->all_DIMMs_ECC_capable = temp1;
 
-
+#ifndef CONFIG_FSL_DDR3
 	/* FIXME: move to somewhere else to validate. */
 	if (mclk_ps > tCKmax_max_ps) {
 		printf("Warning: some of the installed DIMMs "
 				"can not operate this slowly.\n");
 		return 1;
 	}
-
+#endif
 	/*
 	 * Compute additive latency.
 	 *
@@ -314,7 +374,7 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	 *	which comes from Trcd, and also note that:
 	 *	    add_lat + caslat must be >= 4
 	 *
-	 * For DDR3, FIXME additive latency determination
+	 * For DDR3, we use the AL=0
 	 *
 	 * When to use additive latency for DDR2:
 	 *
@@ -371,7 +431,11 @@ compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	}
 
 #elif defined(CONFIG_FSL_DDR3)
-error "FIXME determine additive latency for DDR3"
+	/*
+	 * The system will not use the global auto-precharge mode.
+	 * However, it uses the page mode, so we set AL=0
+	 */
+	additive_latency = 0;
 #endif
 
 	/*
diff --git a/cpu/mpc8xxx/ddr/options.c b/cpu/mpc8xxx/ddr/options.c
index 29d4143..db44291 100644
--- a/cpu/mpc8xxx/ddr/options.c
+++ b/cpu/mpc8xxx/ddr/options.c
@@ -96,10 +96,8 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 	 */
 #if defined(CONFIG_FSL_DDR1)
 	popts->DQS_config = 0;
-#elif defined(CONFIG_FSL_DDR2)
+#elif defined(CONFIG_FSL_DDR2) || defined(CONFIG_FSL_DDR3)
 	popts->DQS_config = 1;
-#else
-#error "Fix DQS for DDR3"
 #endif
 
 	/* Choose self-refresh during sleep. */
@@ -112,7 +110,17 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 	popts->data_bus_width = 0;
 
 	/* Choose burst length. */
-	popts->burst_length = 4;	/* has to be 4 for DDR2 */
+#if defined(CONFIG_FSL_DDR3)
+	popts->OTF_burst_chop_en = 1;	/* on-the-fly burst chop */
+	popts->burst_length = DDR_OTF;	/* on-the-fly BC4 and BL8 */
+#else
+	popts->burst_length = DDR_BL4;	/* has to be 4 for DDR2 */
+#endif
+
+	/* Choose ddr controller address mirror mode */
+#if defined(CONFIG_FSL_DDR3)
+	popts->mirrored_dimm = pdimm[0].mirrored_dimm;
+#endif
 
 	/* Global Timing Parameters. */
 	debug("mclk_ps = %u ps\n", get_memory_clk_period_ps());
@@ -181,7 +189,17 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 	popts->tFAW_window_four_activates_ps = 37500;
 
 #elif defined(CONFIG_FSL_DDR3)
-#error "FIXME determine four activates for DDR3"
+	popts->tFAW_window_four_activates_ps = pdimm[0].tFAW_ps;
+#endif
+	popts->zq_en = 0;
+	popts->wrlvl_en = 0;
+#if defined(CONFIG_FSL_DDR3)
+	/*
+	 * due to ddr3 dimm is fly-by topology
+	 * we suggest to enable write leveling to
+	 * meet the tQDSS under different loading.
+	 */
+	popts->wrlvl_en = 1;
 #endif
 
 	/*
diff --git a/include/asm-ppc/fsl_ddr_dimm_params.h b/include/asm-ppc/fsl_ddr_dimm_params.h
index c794eed..55923e0 100644
--- a/include/asm-ppc/fsl_ddr_dimm_params.h
+++ b/include/asm-ppc/fsl_ddr_dimm_params.h
@@ -33,9 +33,15 @@ typedef struct dimm_params_s {
 
 	/* used in computing base address of DIMMs */
 	unsigned long long base_address;
+	/* mirrored DIMMs */
+	unsigned int mirrored_dimm;	/* only for ddr3 */
 
 	/* DIMM timing parameters */
 
+	unsigned int mtb_ps;	/* medium timebase ps, only for ddr3 */
+	unsigned int tAA_ps;	/* minimum CAS latency time, only for ddr3 */
+	unsigned int tFAW_ps;	/* four active window delay, only for ddr3 */
+
 	/*
 	 * SDRAM clock periods
 	 * The range for these are 1000-10000 so a short should be sufficient
@@ -67,6 +73,7 @@ typedef struct dimm_params_s {
 
 	unsigned int refresh_rate_ps;
 
+	/* DDR3 doesn't need these as below */
 	unsigned int tIS_ps;	/* byte 32, spd->ca_setup */
 	unsigned int tIH_ps;	/* byte 33, spd->ca_hold */
 	unsigned int tDS_ps;	/* byte 34, spd->data_setup */
diff --git a/include/asm-ppc/fsl_ddr_sdram.h b/include/asm-ppc/fsl_ddr_sdram.h
index 6e3b255..c2e5aee 100644
--- a/include/asm-ppc/fsl_ddr_sdram.h
+++ b/include/asm-ppc/fsl_ddr_sdram.h
@@ -19,6 +19,11 @@
 #define SDRAM_TYPE_LPDDR1  6
 #define SDRAM_TYPE_DDR3    7
 
+#define DDR_BL4		4	/* burst length 4 */
+#define DDR_BC4		DDR_BL4	/* burst chop for ddr3 */
+#define DDR_OTF		6	/* on-the-fly BC4 and BL8 */
+#define DDR_BL8		8	/* burst length 8 */
+
 #if defined(CONFIG_FSL_DDR1)
 #define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR	(1)
 typedef ddr1_spd_eeprom_t generic_spd_eeprom_t;
@@ -68,6 +73,18 @@ typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 #define SDRAM_CFG_2T_EN			0x00008000
 #define SDRAM_CFG_BI			0x00000001
 
+#if defined(CONFIG_P4080)
+#define RD_TO_PRE_MASK		0xf
+#define RD_TO_PRE_SHIFT		13
+#define WR_DATA_DELAY_MASK	0xf
+#define WR_DATA_DELAY_SHIFT	9
+#else
+#define RD_TO_PRE_MASK		0x7
+#define RD_TO_PRE_SHIFT		13
+#define WR_DATA_DELAY_MASK	0x7
+#define WR_DATA_DELAY_SHIFT	10
+#endif
+
 /* Record of register values computed */
 typedef struct fsl_ddr_cfg_regs_s {
 	struct {
@@ -145,7 +162,11 @@ typedef struct memctl_options_s {
 	unsigned int dynamic_power;	/* DYN_PWR */
 	/* memory data width to use (16-bit, 32-bit, 64-bit) */
 	unsigned int data_bus_width;
-	unsigned int burst_length;	/* 4, 8 */
+	unsigned int burst_length;	/* BL4, OTF and BL8 */
+	/* On-The-Fly Burst Chop enable */
+	unsigned int OTF_burst_chop_en;
+	/* mirrior DIMMs for DDR3 */
+	unsigned int mirrored_dimm;
 
 	/* Global Timing Parameters */
 	unsigned int cas_latency_override;
@@ -164,9 +185,17 @@ typedef struct memctl_options_s {
 	unsigned int tCKE_clock_pulse_width_ps;	/* tCKE */
 	unsigned int tFAW_window_four_activates_ps;	/* tFAW --  FOUR_ACT */
 
+	/* Rtt impedance */
+	unsigned int rtt_override;		/* rtt_override enable */
+	unsigned int rtt_override_value;	/* that is Rtt_Nom for DDR3 */
+
 	/* Automatic self refresh */
 	unsigned int auto_self_refresh_en;
 	unsigned int sr_it;
+	/* ZQ calibration */
+	unsigned int zq_en;
+	/* Write leveling */
+	unsigned int wrlvl_en;
 } memctl_options_t;
 
 extern phys_size_t fsl_ddr_sdram(void);
diff --git a/include/ddr_spd.h b/include/ddr_spd.h
index 6fdcef0..10402c5 100644
--- a/include/ddr_spd.h
+++ b/include/ddr_spd.h
@@ -184,7 +184,7 @@ typedef struct ddr3_spd_eeprom_s {
 	unsigned char module_type;     /*  3 Key Byte / Module Type */
 	unsigned char density_banks;   /*  4 SDRAM Density and Banks */
 	unsigned char addressing;      /*  5 SDRAM Addressing */
-	unsigned char res_6;           /*  6 Reserved */
+	unsigned char module_vdd;      /*  6 Module nominal voltage, VDD */
 	unsigned char organization;    /*  7 Module Organization */
 	unsigned char bus_width;       /*  8 Module Memory Bus Width */
 	unsigned char ftb_div;         /*  9 Fine Timebase (FTB)
@@ -273,6 +273,7 @@ extern unsigned int ddr1_spd_check(const ddr1_spd_eeprom_t *spd);
 extern void ddr1_spd_dump(const ddr1_spd_eeprom_t *spd);
 extern unsigned int ddr2_spd_check(const ddr2_spd_eeprom_t *spd);
 extern void ddr2_spd_dump(const ddr2_spd_eeprom_t *spd);
+extern unsigned int ddr3_spd_check(const ddr3_spd_eeprom_t *spd);
 
 /*
  * Byte 2 Fundamental Memory Types.
@@ -289,4 +290,14 @@ extern void ddr2_spd_dump(const ddr2_spd_eeprom_t *spd);
 #define SPD_MEMTYPE_DDR2_FBDIMM_PROBE	(0x0A)
 #define SPD_MEMTYPE_DDR3	(0x0B)
 
+/*
+ * Byte 3 Key Byte / Module Type for DDR3 SPD
+ */
+#define SPD_MODULETYPE_RDIMM		(0x01)
+#define SPD_MODULETYPE_UDIMM		(0x02)
+#define SPD_MODULETYPE_SODIMM		(0x03)
+#define SPD_MODULETYPE_MICRODIMM	(0x04)
+#define SPD_MODULETYPE_MINIRDIMM	(0x05)
+#define SPD_MODULETYPE_MINIUDIMM	(0x06)
+
 #endif /* _DDR_SPD_H_ */
-- 
1.5.4



More information about the U-Boot mailing list