All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot-Users] [PATCH 3/3]Add DDR2 controller fixed/SPD Init for MPC83xx
       [not found]   ` <1170844727.13827.27.camel@localhost.localdomain>
@ 2007-02-14 10:27     ` Xie Xiaobo
  2007-03-09 11:08       ` [U-Boot-Users] [PATCH]Fix two bugs for MPC83xx DDR2 controller SPD Init Xie Xiaobo
  0 siblings, 1 reply; 2+ messages in thread
From: Xie Xiaobo @ 2007-02-14 10:27 UTC (permalink / raw)
  To: u-boot

The code supply fixed and SPD initialization for MPC83xx DDR2 Controller.
it pass DDR/DDR2 compliance tests.

Signed-off-by: Xie Xiaobo<X.Xie@freescale.com>

---
This patch applies to the mpc83xx branch of the opensource.freescale.com u-boot-83xx.git tree

 board/mpc8349emds/mpc8349emds.c |   17 ++-
 board/mpc8360emds/mpc8360emds.c |   15 ++
 cpu/mpc83xx/spd_sdram.c         |  384 ++++++++++++++++++++++++++++++++------
 3 files changed, 354 insertions(+), 62 deletions(-)

diff --git a/board/mpc8349emds/mpc8349emds.c b/board/mpc8349emds/mpc8349emds.c
index 873bdd0..071591e 100644
--- a/board/mpc8349emds/mpc8349emds.c
+++ b/board/mpc8349emds/mpc8349emds.c
@@ -119,6 +119,20 @@ int fixed_sdram(void)
 #if (CFG_DDR_SIZE != 256)
 #warning Currenly any ddr size other than 256 is not supported
 #endif
+#ifdef CONFIG_DDR_II
+	im->ddr.csbnds[2].csbnds = CFG_DDR_CS2_BNDS;
+	im->ddr.cs_config[2] = CFG_DDR_CS2_CONFIG;
+	im->ddr.timing_cfg_0 = CFG_DDR_TIMING_0;
+	im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1;
+	im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2;
+	im->ddr.timing_cfg_3 = CFG_DDR_TIMING_3;
+	im->ddr.sdram_cfg = CFG_DDR_SDRAM_CFG;
+	im->ddr.sdram_cfg2 = CFG_DDR_SDRAM_CFG2;
+	im->ddr.sdram_mode = CFG_DDR_MODE;
+	im->ddr.sdram_mode2 = CFG_DDR_MODE2;
+	im->ddr.sdram_interval = CFG_DDR_INTERVAL;
+	im->ddr.sdram_clk_cntl = CFG_DDR_CLK_CNTL;
+#else
 	im->ddr.csbnds[2].csbnds = 0x0000000f;
 	im->ddr.cs_config[2] = CFG_DDR_CONFIG;
 
@@ -143,6 +157,7 @@ int fixed_sdram(void)
 	im->ddr.sdram_mode = CFG_DDR_MODE;
 
 	im->ddr.sdram_interval = CFG_DDR_INTERVAL;
+#endif
 	udelay(200);
 
 	/* enable DDR controller */
@@ -239,7 +254,7 @@ void sdram_init(void)
 #else
 void sdram_init(void)
 {
-	put("SDRAM on Local Bus is NOT available!\n");
+	puts("   SDRAM on Local Bus is NOT available!\n");
 }
 #endif
 
diff --git a/board/mpc8360emds/mpc8360emds.c b/board/mpc8360emds/mpc8360emds.c
index ddc1047..54b9acc 100644
--- a/board/mpc8360emds/mpc8360emds.c
+++ b/board/mpc8360emds/mpc8360emds.c
@@ -158,6 +158,20 @@ int fixed_sdram(void)
 #if (CFG_DDR_SIZE != 256)
 #warning Currenly any ddr size other than 256 is not supported
 #endif
+#ifdef CONFIG_DDR_II
+	im->ddr.csbnds[0].csbnds = CFG_DDR_CS0_BNDS;
+	im->ddr.cs_config[0] = CFG_DDR_CS0_CONFIG;
+	im->ddr.timing_cfg_0 = CFG_DDR_TIMING_0;
+	im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1;
+	im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2;
+	im->ddr.timing_cfg_3 = CFG_DDR_TIMING_3;
+	im->ddr.sdram_cfg = CFG_DDR_SDRAM_CFG;
+	im->ddr.sdram_cfg2 = CFG_DDR_SDRAM_CFG2;
+	im->ddr.sdram_mode = CFG_DDR_MODE;
+	im->ddr.sdram_mode2 = CFG_DDR_MODE2;
+	im->ddr.sdram_interval = CFG_DDR_INTERVAL;
+	im->ddr.sdram_clk_cntl = CFG_DDR_CLK_CNTL;
+#else
 	im->ddr.csbnds[0].csbnds = 0x00000007;
 	im->ddr.csbnds[1].csbnds = 0x0008000f;
 
@@ -170,6 +184,7 @@ int fixed_sdram(void)
 
 	im->ddr.sdram_mode = CFG_DDR_MODE;
 	im->ddr.sdram_interval = CFG_DDR_INTERVAL;
+#endif
 	udelay(200);
 	im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN;
 
diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c
index 108328a..d9b8753 100644
--- a/cpu/mpc83xx/spd_sdram.c
+++ b/cpu/mpc83xx/spd_sdram.c
@@ -106,16 +106,29 @@ long int spd_sdram()
 	volatile ddr83xx_t *ddr = &immap->ddr;
 	volatile law83xx_t *ecm = &immap->sysconf.ddrlaw[0];
 	spd_eeprom_t spd;
+	unsigned int n_ranks;
+	unsigned int odt_rd_cfg, odt_wr_cfg;
+	unsigned char twr_clk, twtr_clk;
+	unsigned char sdram_type;
 	unsigned int memsize;
 	unsigned int law_size;
 	unsigned char caslat, caslat_ctrl;
+	unsigned int trfc, trfc_clk, trfc_low, trfc_high;
+	unsigned int trcd_clk, trtp_clk;
+	unsigned char cke_min_clk;
+	unsigned char add_lat, wr_lat;
+	unsigned char wr_data_delay;
+	unsigned char four_act;
+	unsigned char cpo;
 	unsigned char burstlen;
+	unsigned char odt_cfg, mode_odt_enable;
 	unsigned int max_bus_clk;
 	unsigned int max_data_rate, effective_data_rate;
 	unsigned int ddrc_clk;
 	unsigned int refresh_clk;
-	unsigned sdram_cfg;
+	unsigned int sdram_cfg;
 	unsigned int ddrc_ecc_enable;
+	unsigned int pvr = get_pvr();
 
 	/* Read SPD parameters with I2C */
 	CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd));
@@ -123,19 +136,25 @@ long int spd_sdram()
 	spd_debug(&spd);
 #endif
 	/* Check the memory type */
-	if (spd.mem_type != SPD_MEMTYPE_DDR) {
+	if (spd.mem_type != SPD_MEMTYPE_DDR && spd.mem_type != SPD_MEMTYPE_DDR2) {
 		printf("DDR: Module mem type is %02X\n", spd.mem_type);
 		return 0;
 	}
 
 	/* Check the number of physical bank */
-	if (spd.nrows > 2) {
-		printf("DDR: The number of physical bank is %02X\n", spd.nrows);
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		n_ranks = spd.nrows;
+	} else {
+		n_ranks = (spd.nrows & 0x7) + 1;
+	}
+
+	if (n_ranks > 2) {
+		printf("DDR: The number of physical bank is %02X\n", n_ranks);
 		return 0;
 	}
 
 	/* Check if the number of row of the module is in the range of DDRC */
-	if (spd.nrow_addr < 12 || spd.nrow_addr > 14) {
+	if (spd.nrow_addr < 12 || spd.nrow_addr > 15) {
 		printf("DDR: Row number is out of range of DDRC, row=%02X\n",
 							 spd.nrow_addr);
 		return 0;
@@ -147,20 +166,43 @@ long int spd_sdram()
 							 spd.ncol_addr);
 		return 0;
 	}
+
+#ifdef CFG_DDRCDR_VALUE
+	/*
+	 * Adjust DDR II IO voltage biasing.  It just makes it work.
+	 */
+	if(spd.mem_type == SPD_MEMTYPE_DDR2) {
+		immap->sysconf.ddrcdr = CFG_DDRCDR_VALUE;
+	}
+#endif
+
+	/*
+	 * ODT configuration recommendation from DDR Controller Chapter.
+	 */
+	odt_rd_cfg = 0;			/* Never assert ODT */
+	odt_wr_cfg = 0;			/* Never assert ODT */
+	if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+		odt_wr_cfg = 1;		/* Assert ODT on writes to CSn */
+	}
+
 	/* Setup DDR chip select register */
 #ifdef CFG_83XX_DDR_USES_CS0
 	ddr->csbnds[0].csbnds = (banksize(spd.row_dens) >> 24) - 1;
 	ddr->cs_config[0] = ( 1 << 31
+			    | (odt_rd_cfg << 20)
+			    | (odt_wr_cfg << 16)
 			    | (spd.nrow_addr - 12) << 8
 			    | (spd.ncol_addr - 8) );
 	debug("\n");
 	debug("cs0_bnds = 0x%08x\n",ddr->csbnds[0].csbnds);
 	debug("cs0_config = 0x%08x\n",ddr->cs_config[0]);
 
-	if (spd.nrows == 2) {
+	if (n_ranks == 2) {
 		ddr->csbnds[1].csbnds = ( (banksize(spd.row_dens) >> 8)
 				  | ((banksize(spd.row_dens) >> 23) - 1) );
 		ddr->cs_config[1] = ( 1<<31
+				    | (odt_rd_cfg << 20)
+				    | (odt_wr_cfg << 16)
 				    | (spd.nrow_addr-12) << 8
 				    | (spd.ncol_addr-8) );
 		debug("cs1_bnds = 0x%08x\n",ddr->csbnds[1].csbnds);
@@ -170,16 +212,20 @@ long int spd_sdram()
 #else
 	ddr->csbnds[2].csbnds = (banksize(spd.row_dens) >> 24) - 1;
 	ddr->cs_config[2] = ( 1 << 31
+			    | (odt_rd_cfg << 20)
+			    | (odt_wr_cfg << 16)
 			    | (spd.nrow_addr - 12) << 8
 			    | (spd.ncol_addr - 8) );
 	debug("\n");
 	debug("cs2_bnds = 0x%08x\n",ddr->csbnds[2].csbnds);
 	debug("cs2_config = 0x%08x\n",ddr->cs_config[2]);
 
-	if (spd.nrows == 2) {
+	if (n_ranks == 2) {
 		ddr->csbnds[3].csbnds = ( (banksize(spd.row_dens) >> 8)
 				  | ((banksize(spd.row_dens) >> 23) - 1) );
 		ddr->cs_config[3] = ( 1<<31
+				    | (odt_rd_cfg << 20)
+				    | (odt_wr_cfg << 16)
 				    | (spd.nrow_addr-12) << 8
 				    | (spd.ncol_addr-8) );
 		debug("cs3_bnds = 0x%08x\n",ddr->csbnds[3].csbnds);
@@ -187,15 +233,10 @@ long int spd_sdram()
 	}
 #endif
 
-	if (spd.mem_type != 0x07) {
-		puts("No DDR module found!\n");
-		return 0;
-	}
-
 	/*
 	 * Figure out memory size in Megabytes.
 	 */
-	memsize = spd.nrows * banksize(spd.row_dens) / 0x100000;
+	memsize = n_ranks * banksize(spd.row_dens) / 0x100000;
 
 	/*
 	 * First supported LAW size is 16M, at LAWAR_SIZE_16M == 23.
@@ -215,24 +256,32 @@ long int spd_sdram()
 	 * in the spd.cas_lat field.  Translate it to a DDR
 	 * controller field value:
 	 *
-	 *	CAS Lat	 DDR I	   Ctrl
-	 *	Clocks	 SPD Bit   Value
-	 *	-------+--------+---------
-	 *	1.0	   0	    001
-	 *	1.5	   1	    010
-	 *	2.0	   2	    011
-	 *	2.5	   3	    100
-	 *	3.0	   4	    101
-	 *	3.5	   5	    110
-	 *	4.0	   6	    111
+	 *	CAS Lat	DDR I	DDR II	Ctrl
+	 *	Clocks	SPD Bit	SPD Bit	Value
+	 *	-------	-------	-------	-----
+	 *	1.0	0		0001
+	 *	1.5	1		0010
+	 *	2.0	2	2	0011
+	 *	2.5	3		0100
+	 *	3.0	4	3	0101
+	 *	3.5	5		0110
+	 *	4.0	6	4	0111
+	 *	4.5			1000
+	 *	5.0		5	1001
 	 */
 	caslat = __ilog2(spd.cas_lat);
-
-	if (caslat > 6 ) {
-		printf("DDR: Invalid SPD CAS Latency, caslat=%02X\n",
-			spd.cas_lat);
+	if ((spd.mem_type == SPD_MEMTYPE_DDR)
+	    && (caslat > 6)) {
+		printf("DDR I: Invalid SPD CAS Latency: 0x%x.\n", spd.cas_lat);
+		return 0;
+	} else if (spd.mem_type == SPD_MEMTYPE_DDR2
+		   && (caslat < 2 || caslat > 5)) {
+		printf("DDR II: Invalid SPD CAS Latency: 0x%x.\n",
+		       spd.cas_lat);
 		return 0;
 	}
+	debug("DDR: caslat SPD bit is %d\n", caslat);
+
 	max_bus_clk = 1000 *10 / (((spd.clk_cycle & 0xF0) >> 4) * 10
 			+ (spd.clk_cycle & 0x0f));
 	max_data_rate = max_bus_clk * 2;
@@ -240,10 +289,11 @@ long int spd_sdram()
 	debug("DDR:Module maximum data rate is: %dMhz\n", max_data_rate);
 
 	ddrc_clk = gd->ddr_clk / 1000000;
+	effective_data_rate = 0;
 
-	if (max_data_rate >= 390) { /* it is DDR 400 */
-		if (ddrc_clk <= 410 && ddrc_clk > 350) {
-			/* DDR controller clk at 350~410 */
+	if (max_data_rate >= 390 && max_data_rate < 460) { /* it is DDR 400 */
+		if (ddrc_clk <= 460 && ddrc_clk > 350) {
+			/* DDR controller clk at 350~460 */
 			effective_data_rate = 400; /* 5ns */
 			caslat = caslat;
 		} else if (ddrc_clk <= 350 && ddrc_clk > 280) {
@@ -258,16 +308,16 @@ long int spd_sdram()
 			effective_data_rate = 266; /* 7.5ns */
 			if (spd.clk_cycle3 == 0x75)
 				caslat = caslat - 2;
-			else if (spd.clk_cycle2 == 0x60)
+			else if (spd.clk_cycle2 == 0x75)
 				caslat = caslat - 1;
 			else
 				caslat = caslat;
 		} else if (ddrc_clk <= 230 && ddrc_clk > 90) {
 			/* DDR controller clk at 90~230 */
 			effective_data_rate = 200; /* 10ns */
-			if (spd.clk_cycle3 == 0x75)
+			if (spd.clk_cycle3 == 0xa0)
 				caslat = caslat - 2;
-			else if (spd.clk_cycle2 == 0x60)
+			else if (spd.clk_cycle2 == 0xa0)
 				caslat = caslat - 1;
 			else
 				caslat = caslat;
@@ -289,7 +339,7 @@ long int spd_sdram()
 			effective_data_rate = 200; /* 10ns */
 			if (spd.clk_cycle3 == 0xa0)
 				caslat = caslat - 2;
-			else if (spd.clk_cycle2 == 0x75)
+			else if (spd.clk_cycle2 == 0xa0)
 				caslat = caslat - 1;
 			else
 				caslat = caslat;
@@ -330,41 +380,197 @@ long int spd_sdram()
 	 * Errata DDR6 work around: input enable 2 cycles earlier.
 	 * including MPC834x Rev1.0/1.1 and MPC8360 Rev1.1/1.2.
 	 */
-	if (caslat == 2)
-		ddr->debug_reg = 0x201c0000; /* CL=2 */
-	else if (caslat == 3)
-		ddr->debug_reg = 0x202c0000; /* CL=2.5 */
-	else if (caslat == 4)
-		ddr->debug_reg = 0x202c0000; /* CL=3.0 */
+	if(PVR_MAJ(pvr) <= 1 && spd.mem_type == SPD_MEMTYPE_DDR){
+		if (caslat == 2)
+			ddr->debug_reg = 0x201c0000; /* CL=2 */
+		else if (caslat == 3)
+			ddr->debug_reg = 0x202c0000; /* CL=2.5 */
+		else if (caslat == 4)
+			ddr->debug_reg = 0x202c0000; /* CL=3.0 */
 
-	__asm__ __volatile__ ("sync");
+		__asm__ __volatile__ ("sync");
 
-	debug("Errata DDR6 (debug_reg=0x%08x)\n", ddr->debug_reg);
+		debug("Errata DDR6 (debug_reg=0x%08x)\n", ddr->debug_reg);
+	}
 
 	/*
-	 * note: caslat must also be programmed into ddr->sdram_mode
-	 * register.
-	 *
-	 * note: WRREC(Twr) and WRTORD(Twtr) are not in SPD,
-	 * use conservative value here.
+	 * Convert caslat clocks to DDR controller value.
+	 * Force caslat_ctrl to be DDR Controller field-sized.
 	 */
-	caslat_ctrl = (caslat + 1) & 0x07; /* see as above */
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		caslat_ctrl = (caslat + 1) & 0x07;
+	} else {
+		caslat_ctrl =  (2 * caslat - 1) & 0x0f;
+	}
+
+	debug("DDR: effective data rate is %d MHz\n", effective_data_rate);
+	debug("DDR: caslat SPD bit is %d, controller field is 0x%x\n",
+	      caslat, caslat_ctrl);
+
+	/*
+	 * Timing Config 0.
+	 * Avoid writing for DDR I.
+	 */
+	if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+		unsigned char taxpd_clk = 8;		/* By the book. */
+		unsigned char tmrd_clk = 2;		/* By the book. */
+		unsigned char act_pd_exit = 2;		/* Empirical? */
+		unsigned char pre_pd_exit = 6;		/* Empirical? */
+
+		ddr->timing_cfg_0 = (0
+			| ((act_pd_exit & 0x7) << 20)	/* ACT_PD_EXIT */
+			| ((pre_pd_exit & 0x7) << 16)	/* PRE_PD_EXIT */
+			| ((taxpd_clk & 0xf) << 8)	/* ODT_PD_EXIT */
+			| ((tmrd_clk & 0xf) << 0)	/* MRS_CYC */
+			);
+		debug("DDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
+	}
+
+	/*
+	 * For DDR I, WRREC(Twr) and WRTORD(Twtr) are not in SPD,
+	 * use conservative value.
+	 * For DDR II, they are bytes 36 and 37, in quarter nanos.
+	 */
+
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		twr_clk = 3;	/* Clocks */
+		twtr_clk = 1;	/* Clocks */
+	} else {
+		twr_clk = picos_to_clk(spd.twr * 250);
+		twtr_clk = picos_to_clk(spd.twtr * 250);
+	}
+
+	/*
+	 * Calculate Trfc, in picos.
+	 * DDR I:  Byte 42 straight up in ns.
+	 * DDR II: Byte 40 and 42 swizzled some, in ns.
+	 */
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		trfc = spd.trfc * 1000;		/* up to ps */
+	} else {
+		unsigned int byte40_table_ps[8] = {
+			0,
+			250,
+			330,
+			500,
+			660,
+			750,
+			0,
+			0
+		};
+
+		trfc = (((spd.trctrfc_ext & 0x1) * 256) + spd.trfc) * 1000
+			+ byte40_table_ps[(spd.trctrfc_ext >> 1) & 0x7];
+	}
+	trfc_clk = picos_to_clk(trfc);
+
+	/*
+	 * Trcd, Byte 29, from quarter nanos to ps and clocks.
+	 */
+	trcd_clk = picos_to_clk(spd.trcd * 250) & 0x7;
+
+	/*
+	 * Convert trfc_clk to DDR controller fields.  DDR I should
+	 * fit in the REFREC field (16-19) of TIMING_CFG_1, but the
+	 * 83xx controller has an extended REFREC field of three bits.
+	 * The controller automatically adds 8 clocks to this value,
+	 * so preadjust it down 8 first before splitting it up.
+	 */
+	trfc_low = (trfc_clk - 8) & 0xf;
+	trfc_high = ((trfc_clk - 8) >> 4) & 0x3;
 
 	ddr->timing_cfg_1 =
-	    (((picos_to_clk(spd.trp * 250) & 0x07) << 28 ) |
-	     ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24 ) |
-	     ((picos_to_clk(spd.trcd * 250) & 0x07) << 20 ) |
-	     ((caslat_ctrl & 0x07) << 16 ) |
-	     (((picos_to_clk(spd.trfc * 1000) - 8) & 0x0f) << 12 ) |
-	     ( 0x300 ) |
-	     ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) | 1);
+	    (((picos_to_clk(spd.trp * 250) & 0x07) << 28 ) |	/* PRETOACT */
+	     ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24 ) | /* ACTTOPRE */
+	     (trcd_clk << 20 ) |  				/* ACTTORW */
+	     (caslat_ctrl << 16 ) |				/* CASLAT */
+	     (trfc_low << 12 ) |				/* REFEC */
+	     ((twr_clk & 0x07) << 8) |				/* WRRREC */
+	     ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) |	/* ACTTOACT */
+	     ((twtr_clk & 0x07) << 0)				/* WRTORD */
+	    );
+
+	/*
+	 * Additive Latency
+	 * For DDR I, 0.
+	 * For DDR II, with ODT enabled, use "a value" less than ACTTORW,
+	 * which comes from Trcd, and also note that:
+	 *	add_lat + caslat must be >= 4
+	 */
+	add_lat = 0;
+	if (spd.mem_type == SPD_MEMTYPE_DDR2
+	    && (odt_wr_cfg || odt_rd_cfg)
+	    && (caslat < 4)) {
+		add_lat = trcd_clk - 1;
+		if ((add_lat + caslat) < 4) {
+			add_lat = 0;
+		}
+	}
+
+	/*
+	 * Write Data Delay
+	 * Historically 0x2 == 4/8 clock delay.
+	 * Empirically, 0x3 == 6/8 clock delay is suggested for DDR I 266.
+	 */
+	wr_data_delay = 2;
+
+	/*
+	 * Write Latency
+	 * Read to Precharge
+	 * Minimum CKE Pulse Width.
+	 * Four Activate Window
+	 */
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		/*
+		 * This is a lie.  It should really be 1, but if it is
+		 * set to 1, bits overlap into the old controller's
+		 * otherwise unused ACSM field.  If we leave it 0, then
+		 * the HW will magically treat it as 1 for DDR 1.  Oh Yea.
+		 */
+		wr_lat = 0;
+
+		trtp_clk = 2;		/* By the book. */
+		cke_min_clk = 1;	/* By the book. */
+		four_act = 1;		/* By the book. */
+
+	} else {
+		wr_lat = caslat - 1;
+
+		/* Convert SPD value from quarter nanos to picos. */
+		trtp_clk = picos_to_clk(spd.trtp * 250);
 
-	ddr->timing_cfg_2 = 0x00000800;
+		cke_min_clk = 3;	/* By the book. */
+		four_act = picos_to_clk(37500);	/* By the book. 1k pages? */
+	}
+
+	/*
+	 * Empirically set ~MCAS-to-preamble override for DDR 2.
+	 * Your milage will vary.
+	 */
+	cpo = 0;
+	if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+		if (effective_data_rate == 266 || effective_data_rate == 333) {
+			cpo = 0x7;		/* READ_LAT + 5/4 */
+		} else if (effective_data_rate == 400) {
+			cpo = 0x9;		/* READ_LAT + 7/4 */
+		} else {
+			/* Automatic calibration */
+			cpo = 0x1f;
+		}
+	}
+
+	ddr->timing_cfg_2 = (0
+		| ((add_lat & 0x7) << 28)		/* ADD_LAT */
+		| ((cpo & 0x1f) << 23)			/* CPO */
+		| ((wr_lat & 0x7) << 19)		/* WR_LAT */
+		| ((trtp_clk & 0x7) << 13)		/* RD_TO_PRE */
+		| ((wr_data_delay & 0x7) << 10)		/* WR_DATA_DELAY */
+		| ((cke_min_clk & 0x7) << 6)		/* CKE_PLS */
+		| ((four_act & 0x1f) << 0)		/* FOUR_ACT */
+		);
 
 	debug("DDR:timing_cfg_1=0x%08x\n", ddr->timing_cfg_1);
 	debug("DDR:timing_cfg_2=0x%08x\n", ddr->timing_cfg_2);
-	/* Setup init value, but not enable */
-	ddr->sdram_cfg = 0x42000000;
 
 	/* Check DIMM data bus width */
 	if (spd.dataw_lsb == 0x20) {
@@ -384,7 +590,8 @@ long int spd_sdram()
 	/* Burst length is always 4 for 64 bit data bus, 8 for 32 bit data bus,
 	   Burst type is sequential
 	 */
-	switch (caslat) {
+	if (spd.mem_type == SPD_MEMTYPE_DDR) {
+		switch (caslat) {
 		case 1:
 			ddr->sdram_mode = 0x50 | burstlen; /* CL=1.5 */
 			break;
@@ -400,9 +607,36 @@ long int spd_sdram()
 		default:
 			printf("DDR:only CL 1.5, 2.0, 2.5, 3.0 is supported\n");
 			return 0;
+		}
+	} else {
+		mode_odt_enable = 0x0;                  /* Default disabled */
+		if (odt_wr_cfg || odt_rd_cfg) {
+			/*
+			 * Bits 6 and 2 in Extended MRS(1)
+			 * Bit 2 == 0x04 == 75 Ohm, with 2 DIMM modules.
+			 * Bit 6 == 0x40 == 150 Ohm, with 1 DIMM module.
+			 */
+			mode_odt_enable = 0x40;         /* 150 Ohm */
+		}
+
+		ddr->sdram_mode =
+			(0
+			 | (1 << (16 + 10))             /* DQS Differential disable */
+			 | (add_lat << (16 + 3))        /* Additive Latency in EMRS1 */
+			 | (mode_odt_enable << 16)      /* ODT Enable in EMRS1 */
+			 | ((twr_clk >> 1) << 9)        /* Write Recovery Autopre */
+			 | (caslat << 4)                /* caslat */
+			 | (burstlen << 0)              /* Burst length */
+			);
 	}
 	debug("DDR:sdram_mode=0x%08x\n", ddr->sdram_mode);
 
+	/*
+	 * Clear EMRS2 and EMRS3.
+	 */
+	ddr->sdram_mode2 = 0;
+	debug("DDR: sdram_mode2 = 0x%08x\n", ddr->sdram_mode2);
+
 	switch (spd.refresh) {
 		case 0x00:
 		case 0x80:
@@ -440,6 +674,23 @@ long int spd_sdram()
 	ddr->sdram_interval = ((refresh_clk & 0x3fff) << 16) | 0x100;
 	debug("DDR:sdram_interval=0x%08x\n", ddr->sdram_interval);
 
+	/*
+	 * SDRAM Cfg 2
+	 */
+	odt_cfg = 0;
+	if (odt_rd_cfg | odt_wr_cfg) {
+		odt_cfg = 0x2;		/* ODT to IOs during reads */
+	}
+	if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+		ddr->sdram_cfg2 = (0
+			    | (0 << 26)	/* True DQS */
+			    | (odt_cfg << 21)	/* ODT only read */
+			    | (1 << 12)	/* 1 refresh@a time */
+			    );
+
+		debug("DDR: sdram_cfg2  = 0x%08x\n", ddr->sdram_cfg2);
+	}
+
 #ifdef CFG_DDR_SDRAM_CLK_CNTL	/* Optional platform specific value */
 	ddr->sdram_clk_cntl = CFG_DDR_SDRAM_CLK_CNTL;
 #else
@@ -462,11 +713,22 @@ long int spd_sdram()
 	 *
 	 * sdram_cfg[0]   = 1 (ddr sdram logic enable)
 	 * sdram_cfg[1]   = 1 (self-refresh-enable)
-	 * sdram_cfg[6:7] = 2 (SDRAM type = DDR SDRAM)
+	 * sdram_cfg[5:7] = (SDRAM type = DDR SDRAM)
+	 *			010 DDR 1 SDRAM
+	 *			011 DDR 2 SDRAM
 	 * sdram_cfg[12] = 0 (32_BE =0 , 64 bit bus mode)
 	 * sdram_cfg[13] = 0 (8_BE =0, 4-beat bursts)
 	 */
-	sdram_cfg = 0xC2000000;
+	if (spd.mem_type == SPD_MEMTYPE_DDR)
+		sdram_type = 2;
+	else
+		sdram_type = 3;
+
+	sdram_cfg = (0
+		     | (1 << 31)			/* DDR enable */
+		     | (1 << 30)			/* Self refresh */
+		     | (sdram_type << 24)		/* SDRAM type */
+		     );
 
 	/* sdram_cfg[3] = RD_EN - registered DIMM enable */
 	if (spd.mod_attr & 0x02)
-- 
1.4.4.1

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

* [U-Boot-Users] [PATCH]Fix two bugs for MPC83xx DDR2 controller SPD Init
  2007-02-14 10:27     ` [U-Boot-Users] [PATCH 3/3]Add DDR2 controller fixed/SPD Init for MPC83xx Xie Xiaobo
@ 2007-03-09 11:08       ` Xie Xiaobo
  0 siblings, 0 replies; 2+ messages in thread
From: Xie Xiaobo @ 2007-03-09 11:08 UTC (permalink / raw)
  To: u-boot

There are a few bugs in the cpu/mpc83xx/spd_sdram.c
the first bug is that the picos_to_clk routine introduces a huge 
rounding error in 83xx.
the second bug is that the mode register write recovery field is
tWR-1, not tWR >> 1. 

---
This patch applies to the mpc83xx branch of the opensource.freescale.com u-boot-83xx.git tree

 cpu/mpc83xx/spd_sdram.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c
index d9b8753..869dab4 100644
--- a/cpu/mpc83xx/spd_sdram.c
+++ b/cpu/mpc83xx/spd_sdram.c
@@ -58,8 +58,8 @@ picos_to_clk(int picos)
 	int clks;
 
 	ddr_bus_clk = gd->ddr_clk >> 1;
-	clks = picos / ((1000000000 / ddr_bus_clk) * 1000);
-	if (picos % ((1000000000 / ddr_bus_clk) * 1000) != 0)
+	clks = picos / (1000000000 / (ddr_bus_clk / 1000));
+	if (picos % (1000000000 / (ddr_bus_clk / 1000)) != 0)
 		clks++;
 
 	return clks;
@@ -624,7 +624,7 @@ long int spd_sdram()
 			 | (1 << (16 + 10))             /* DQS Differential disable */
 			 | (add_lat << (16 + 3))        /* Additive Latency in EMRS1 */
 			 | (mode_odt_enable << 16)      /* ODT Enable in EMRS1 */
-			 | ((twr_clk >> 1) << 9)        /* Write Recovery Autopre */
+			 | ((twr_clk - 1) << 9)         /* Write Recovery Autopre */
 			 | (caslat << 4)                /* caslat */
 			 | (burstlen << 0)              /* Burst length */
 			);
-- 
1.4.4.1

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

end of thread, other threads:[~2007-03-09 11:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1169810886.11635.38.camel@localhost.localdomain>
     [not found] ` <1170756162.10272.33.camel@localhost.localdomain>
     [not found]   ` <1170844727.13827.27.camel@localhost.localdomain>
2007-02-14 10:27     ` [U-Boot-Users] [PATCH 3/3]Add DDR2 controller fixed/SPD Init for MPC83xx Xie Xiaobo
2007-03-09 11:08       ` [U-Boot-Users] [PATCH]Fix two bugs for MPC83xx DDR2 controller SPD Init Xie Xiaobo

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.