[U-Boot] [PATCH 1/1] ppc4xx: Autocalibration can set RDCC to over aggressive value.

Adam Graham agraham at amcc.com
Thu Dec 18 21:55:39 CET 2008


The criteria of the AMCC SDRAM Controller DDR autocalibration U-Boot code is to pick the largest passing write/read/compare window that also has the smallest SDRAM_RDCC.[RDSS] Read Sample Cycle Select value.

On some Kilauea boards the DDR autocalibration algorithm can find a large passing write/read/compare window with a small SDRAM_RDCC.[RDSS] aggressive value of Read Sample Cycle Select value "T1 Sample".

This SDRAM_RDCC.[RDSS] Read Sample Cycle Select value of "T1 Sample" proves to be to aggressive when later on U-Boot relocates into DDR memory and executes.

The memory traces on the Kilauea board are short so on some Kilauea boards the SDRAM_RDCC.[RDSS] Read Sample Cycle Select value of "T1 Sample" shows up as a potentially valid value for the DDR autocalibratiion algorithm.

The fix is to define a weak default function which provides the minimum SDRAM_RDCC.[RDSS] Read Sample Cycle Select value to accept for DDR autocalibration.  The default will be the "T2 Sample" value.  A board developer who has a well defined board and chooses to be more aggressive can always provide their own board specific string function with the more aggressive "T1 Sample" value or stick with the default minimum SDRAM_RDCC.[RDSS] value of "T2".

Also put in a autocalibration loop fix for case where a current write/read/compare passing window size is the same as a prior window size, then in this case choose the write/read/compare result that has the associated smallest RDCC T-Sample value.

Signed-off-by: Adam Graham <agraham at amcc.com>
---
 cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c |  130 ++++++++++++++++++++++------------
 include/configs/kilauea.h           |    7 --
 2 files changed, 84 insertions(+), 53 deletions(-)

diff --git a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
index 1e3e20d..896a4d9 100644
--- a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
+++ b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
@@ -147,6 +147,12 @@ ulong __ddr_scan_option(ulong default_val)
 }
 ulong ddr_scan_option(ulong) __attribute__((weak, alias("__ddr_scan_option")));
 
+u32 __ddr_rdss_opt(u32 default_val)
+{
+	return default_val;
+}
+u32 ddr_rdss_opt(ulong) __attribute__((weak, alias("__ddr_rdss_opt")));
+
 static u32 *get_membase(int bxcr_num)
 {
 	ulong bxcf;
@@ -341,6 +347,7 @@ static int short_mem_test(u32 *base_address)
 			ppcDcbf((ulong)&(base_address[j]));
 		}
 		sync();
+		iobarrier_rw();
 		for (l = 0; l < NUMLOOPS; l++) {
 			for (j = 0; j < NUMMEMWORDS; j++) {
 				if (base_address[j] != test[i][j]) {
@@ -355,6 +362,7 @@ static int short_mem_test(u32 *base_address)
 				ppcDcbf((u32)&(base_address[j]));
 			} /* for (j = 0; j < NUMMEMWORDS; j++) */
 			sync();
+			iobarrier_rw();
 		} /* for (l=0; l<NUMLOOPS; l++) */
 	}
 
@@ -447,7 +455,8 @@ static u32 DQS_calibration_methodA(struct ddrautocal *cal)
 	 * Program RDCC register
 	 * Read sample cycle auto-update enable
 	 */
-	mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T1 | SDRAM_RDCC_RSAE_ENABLE);
+	mtsdram(SDRAM_RDCC,
+		ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE);
 
 #ifdef DEBUG
 	mfsdram(SDRAM_RDCC, temp);
@@ -633,7 +642,8 @@ static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal)
 	 * Program RDCC register
 	 * Read sample cycle auto-update enable
 	 */
-	mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T2 | SDRAM_RDCC_RSAE_ENABLE);
+	mtsdram(SDRAM_RDCC,
+		ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE);
 
 #ifdef DEBUG
 	mfsdram(SDRAM_RDCC, temp);
@@ -1101,58 +1111,86 @@ u32 DQS_autocalibration(void)
 			 * Save the SDRAM_WRDTR and SDRAM_CLKTR
 			 * settings for the largest returned
 			 * RFFD passing window size.
+			 *
+			 * Always choose the result that has the largest
+			 * write/read/compare passing window size - this
+			 * represents the most stable memory autocalibration
+			 * settings.
 			 */
-			if (result > best_result) {
+			if (result >= best_result) {
 				/*
 				 * want the lowest Read Sample Cycle Select
 				 */
 				val = (val & SDRAM_RDCC_RDSS_MASK) >> 30;
 				debug("*** (%d) (%d) current_rdcc, best_rdcc\n",
 							val, best_rdcc);
-				if (val <= best_rdcc) {
-					best_rdcc = val;
-					tcal.clocks.wrdtr = wdtr;
-					tcal.clocks.clktr = clkp;
-					tcal.clocks.rdcc = (val << 30);
-					tcal.autocal.rqfd = ddrcal.rqfd;
-					tcal.autocal.rffd = ddrcal.rffd;
-					best_result = result;
-
-					if (verbose_lvl > 2) {
-						printf("** (%d)(%d)  "
-						       "best result: 0x%04x\n",
-							wdtr, clkp,
-							best_result);
-						printf("** (%d)(%d)  "
-						       "best WRDTR: 0x%04x\n",
-							wdtr, clkp,
-							tcal.clocks.wrdtr);
-						printf("** (%d)(%d)  "
-						       "best CLKTR: 0x%04x\n",
-							wdtr, clkp,
-							tcal.clocks.clktr);
-						printf("** (%d)(%d)  "
-						       "best RQDC: 0x%04x\n",
-							wdtr, clkp,
-							tcal.autocal.rqfd);
-						printf("** (%d)(%d)  "
-						       "best RFDC: 0x%04x\n",
-							wdtr, clkp,
-							tcal.autocal.rffd);
-						printf("** (%d)(%d)  "
-						       "best RDCC: 0x%08x\n",
-							wdtr, clkp,
-							(u32)tcal.clocks.rdcc);
-						mfsdram(SDRAM_RTSR, val);
-						printf("** (%d)(%d)  best "
-						       "loop RTSR: 0x%08x\n",
-							wdtr, clkp, val);
-						mfsdram(SDRAM_FCSR, val);
-						printf("** (%d)(%d)  best "
-						       "loop FCSR: 0x%08x\n",
-							wdtr, clkp, val);
+				if (val >=
+				    (ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) >> 30)) {
+					/*
+					 * In the case of a current write/read/
+					 * compare passing window size tie with
+					 * a prior result, then choose the
+					 * result that has the associated
+					 * smallest RDCC T-Sample value.
+					 */
+					if (((result == best_result) &&
+					     (val < best_rdcc)) ||
+					    ((result > best_result) &&
+					     (val <= best_rdcc))) {
+						best_rdcc = val;
+						tcal.clocks.wrdtr = wdtr;
+						tcal.clocks.clktr = clkp;
+						tcal.clocks.rdcc = (val << 30);
+						tcal.autocal.rqfd = ddrcal.rqfd;
+						tcal.autocal.rffd = ddrcal.rffd;
+						best_result = result;
+
+						if (verbose_lvl > 2) {
+							printf("** (%d)(%d)  "
+							    "best result: "
+							    "0x%04x\n",
+							    wdtr, clkp,
+							    best_result);
+							printf("** (%d)(%d)  "
+							    "best WRDTR: "
+							    "0x%04x\n",
+							    wdtr, clkp,
+							    tcal.clocks.wrdtr);
+							printf("** (%d)(%d)  "
+							    "best CLKTR: "
+							    "0x%04x\n",
+							    wdtr, clkp,
+							    tcal.clocks.clktr);
+							printf("** (%d)(%d)  "
+							    "best RQDC: "
+							    "0x%04x\n",
+							    wdtr, clkp,
+							    tcal.autocal.rqfd);
+							printf("** (%d)(%d)  "
+							    "best RFDC: "
+							    "0x%04x\n",
+							    wdtr, clkp,
+							    tcal.autocal.rffd);
+							printf("** (%d)(%d)  "
+							    "best RDCC: "
+							    "0x%08x\n",
+							    wdtr, clkp,
+							    tcal.clocks.rdcc);
+							mfsdram(SDRAM_RTSR,
+								val);
+							printf("** (%d)(%d)  "
+							    "best loop RTSR: "
+							    "0x%08x\n",
+							    wdtr, clkp, val);
+							mfsdram(SDRAM_FCSR,
+								val);
+							printf("** (%d)(%d)  "
+							    "best loop FCSR: "
+							    "0x%08x\n",
+							    wdtr, clkp, val);
+						}
 					}
-				} /* if (val <= best_rdcc) */
+				} /* if (val > ddr_rdss_opt) */
 			} /* if (result >= best_result) */
 		} /* if (result != 0) */
 		scan_list++;
diff --git a/include/configs/kilauea.h b/include/configs/kilauea.h
index b943f31..237a9c5 100644
--- a/include/configs/kilauea.h
+++ b/include/configs/kilauea.h
@@ -235,16 +235,9 @@
  *
  * DDR Autocalibration Method_B is the default.
  */
-#if 0
-/*
- * Needs FIX!!!
- * Disable autocalibration for now, because of the unresolved problem
- * with kilauea board using 200MHz PLB/DDR2 frequency
- */
 #define	CONFIG_PPC4xx_DDR_AUTOCALIBRATION	/* IBM DDR autocalibration */
 #define	DEBUG_PPC4xx_DDR_AUTOCALIBRATION	/* dynamic DDR autocal debug */
 #undef	CONFIG_PPC4xx_DDR_METHOD_A
-#endif
 
 #define	CONFIG_SYS_SDRAM0_MB0CF_BASE	((  0 << 20) + CONFIG_SYS_SDRAM_BASE)
 
-- 
1.5.5



More information about the U-Boot mailing list