diff options
| author | Dave Liu <daveliu@freescale.com> | 2009-03-14 12:48:30 +0800 | 
|---|---|---|
| committer | Kumar Gala <galak@kernel.crashing.org> | 2009-03-30 13:33:50 -0500 | 
| commit | c360ceac0286159f94d9d1a9496fc9858c8d9bec (patch) | |
| tree | fdd1868af478993fdb547171665c5c517ee6c071 | |
| parent | 6a8197836702991468cead5ead073f589e2623ad (diff) | |
| download | olio-uboot-2014.01-c360ceac0286159f94d9d1a9496fc9858c8d9bec.tar.xz olio-uboot-2014.01-c360ceac0286159f94d9d1a9496fc9858c8d9bec.zip | |
fsl-ddr: add the DDR3 SPD infrastructure
- 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@freescale.com>
Signed-off-by: Travis Wheatley <travis.wheatley@freescale.com>
| -rw-r--r-- | common/ddr_spd.c | 53 | ||||
| -rw-r--r-- | cpu/mpc85xx/ddr-gen3.c | 6 | ||||
| -rw-r--r-- | cpu/mpc8xxx/ddr/Makefile | 4 | ||||
| -rw-r--r-- | cpu/mpc8xxx/ddr/ctrl_regs.c | 380 | ||||
| -rw-r--r-- | cpu/mpc8xxx/ddr/ddr3_dimm_params.c | 314 | ||||
| -rw-r--r-- | cpu/mpc8xxx/ddr/lc_common_dimm_params.c | 74 | ||||
| -rw-r--r-- | cpu/mpc8xxx/ddr/options.c | 28 | ||||
| -rw-r--r-- | include/asm-ppc/fsl_ddr_dimm_params.h | 7 | ||||
| -rw-r--r-- | include/asm-ppc/fsl_ddr_sdram.h | 31 | ||||
| -rw-r--r-- | include/ddr_spd.h | 13 | 
10 files changed, 860 insertions, 50 deletions
| diff --git a/common/ddr_spd.c b/common/ddr_spd.c index 78e3c5d9f..c058e4f18 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 99c325a4f..8ac3d5fbe 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 b7f8d8cf5..cb7f85655 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 4c1498c8c..490e3dc88 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 000000000..ca4be78ef --- /dev/null +++ b/cpu/mpc8xxx/ddr/ddr3_dimm_params.c @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2008 Freescale Semiconductor, Inc. + *	Dave Liu <daveliu@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 fbeb236d9..e888e3ea5 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,12 +99,14 @@ 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; +#if !defined(CONFIG_FSL_DDR3)  	const unsigned int mclk_ps = get_memory_clk_period_ps(); +	unsigned int lowest_good_caslat;  	unsigned int not_ok;  	debug("using mclk_ps = %u\n", mclk_ps); +#endif  	temp1 = 0;  	for (i = 0; i < number_of_dimms; i++) { @@ -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 29d414343..db442918e 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 c794eedfe..55923e09b 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 6e3b2559c..c2e5aeebc 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 6fdcef0c0..10402c5bb 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_ */ |