From 6f45e9f8fbf2fe7c3dcd3ee5db6a1f09505f8c11 Mon Sep 17 00:00:00 2001
From: Timothy Pearson <tpearson@raptorengineeringinc.com>
Date: Thu, 27 Aug 2015 15:10:19 -0500
Subject: [PATCH 128/143] northbridge/amd/amdmct/mct_ddr3: Use antiphase to
 better center DQS window

Change-Id: I1d85fddd45197ca82dcaa46fe863e64589712d1f
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
---
 src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c |   57 +++++++++++++++++-------
 1 file changed, 40 insertions(+), 17 deletions(-)

diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
index 739a893..d870f17 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
@@ -1304,7 +1304,7 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
 	uint16_t current_read_dqs_delay[MAX_BYTE_LANES];
 	uint16_t current_write_dqs_delay[MAX_BYTE_LANES];
 	uint8_t passing_dqs_delay_found[MAX_BYTE_LANES];
-	uint8_t dqs_results_array[2][(lane_end - lane_start)][32][32];		/* [rank][lane][write step][read step] */
+	uint8_t dqs_results_array[2][(lane_end - lane_start)][32][48];		/* [rank][lane][write step][read step + 16] */
 
 	uint8_t last_pos = 0;
 	uint8_t cur_count = 0;
@@ -1404,16 +1404,24 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
 					 */
 					dword = Get_NB32_DCT(dev, dct, 0x268) & 0x3ffff;
 					if (dword & (0x3 << (lane * 2)))
-						dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][current_read_dqs_delay[lane] >> 1] = 0;	/* Fail */
+						dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][(current_read_dqs_delay[lane] >> 1) + 16] = 0;	/* Fail */
 					else
-						dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][current_read_dqs_delay[lane] >> 1] = 1;	/* Pass */
+						dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][(current_read_dqs_delay[lane] >> 1) + 16] = 1;	/* Pass */
+					if ((current_read_dqs_delay[lane] >> 1) >= (32 - 16)) {
+						/* Check antiphase results */
+						dword = Get_NB32_DCT(dev, dct, 0x26c) & 0x3ffff;
+						if (dword & (0x3 << (lane * 2)))
+							dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][16 - (32 - (current_read_dqs_delay[lane] >> 1))] = 0;	/* Fail */
+						else
+							dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][16 - (32 - (current_read_dqs_delay[lane] >> 1))] = 1;	/* Pass */
+					}
 				}
 			}
 
 			if (dual_rank && (Receiver & 0x1)) {
 				/* Overlay the previous rank test results with the current rank */
 				for (write_iter = 0; write_iter < 32; write_iter++) {
-					for (read_iter = 0; read_iter < 32; read_iter++) {
+					for (read_iter = 0; read_iter < 48; read_iter++) {
 						if ((dqs_results_array[0][lane - lane_start][write_iter][read_iter])
 							&& (dqs_results_array[1][lane - lane_start][write_iter][read_iter]))
 							dqs_results_array[1][lane - lane_start][write_iter][read_iter] = 1;
@@ -1431,8 +1439,8 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
 			best_pos = 0;
 			best_count = 0;
 			for (write_iter = 0; write_iter < 32; write_iter++) {
-				for (read_iter = 0; read_iter < 32; read_iter++) {
-					if ((dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) && (read_iter < 31)) {
+				for (read_iter = 0; read_iter < 48; read_iter++) {
+					if ((dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) && (read_iter < 47)) {
 						/* Pass */
 						cur_count++;
 					} else {
@@ -1442,18 +1450,28 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
 							best_pos = last_pos;
 						}
 						cur_count = 0;
-						last_pos = read_iter;
+						last_pos = read_iter + 1;
 					}
 				}
 				last_pos = 0;
 			}
 
 			if (best_count > 2) {
+				uint16_t region_center = (best_pos + (best_count / 2));
+
+				if (region_center < 16) {
+					printk(BIOS_WARNING, "TrainDQSRdWrPos: negative DQS recovery delay detected!"
+							"  Attempting to continue but your system may be unstable...\n");
+					region_center = 0;
+				} else {
+					region_center -= 16;
+				}
+
 				/* Restore current settings of other (previously trained) lanes to the active array */
 				memcpy(current_read_dqs_delay, initial_read_dqs_delay, sizeof(current_read_dqs_delay));
 
 				/* Program the Read DQS Timing Control register with the center of the passing window */
-				current_read_dqs_delay[lane] = ((best_pos << 1) + ((best_count << 1) / 2));
+				current_read_dqs_delay[lane] = region_center << 1;
 				passing_dqs_delay_found[lane] = 1;
 
 				/* Commit the current Read DQS Timing Control settings to the hardware registers */
@@ -1464,6 +1482,7 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
 
 				print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 142 largest read passing region ", best_count, 4);
 				print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 143 largest read passing region start ", best_pos, 4);
+				print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 144 largest read passing region center (raw hardware value) ", region_center, 4);
 			} else {
 				/* Reprogram the Read DQS Timing Control register with the original settings */
 				write_dqs_read_data_timing_registers(initial_read_dqs_delay, dev, dct, dimm, index_reg);
@@ -1476,7 +1495,7 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
 			cur_count = 0;
 			best_pos = 0;
 			best_count = 0;
-			for (read_iter = 0; read_iter < 32; read_iter++) {
+			for (read_iter = 0; read_iter < 48; read_iter++) {
 				for (write_iter = 0; write_iter < 32; write_iter++) {
 					if ((dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) && (write_iter < 31)) {
 						/* Pass */
@@ -1488,7 +1507,7 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
 							best_pos = last_pos;
 						}
 						cur_count = 0;
-						last_pos = write_iter;
+						last_pos = write_iter + 1;
 					}
 				}
 				last_pos = 0;
@@ -1511,8 +1530,8 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
 				/* Save the final Write Data Timing settings for later use */
 				pDCTstat->CH_D_DIR_B_DQS[dct][Receiver >> 1][DQS_WRITEDIR][lane] = current_write_dqs_delay[lane];
 
-				print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 144 largest write passing region ", best_count, 4);
-				print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 145 largest write passing region start ", best_pos, 4);
+				print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 145 largest write passing region ", best_count, 4);
+				print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 146 largest write passing region start ", best_pos, 4);
 			} else {
 				/* Reprogram the Write DQS Timing Control register with the original settings */
 				write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, dct, dimm, index_reg);
@@ -1521,12 +1540,16 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
 
 #ifdef PRINT_PASS_FAIL_BITMAPS
 		for (lane = lane_start; lane < lane_end; lane++) {
-			for (read_iter = 0; read_iter < 32; read_iter++) {
-				for (write_iter = 0; write_iter < 32; write_iter++) {
-					if (dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter])
+			for (write_iter = 0; write_iter < 32; write_iter++) {
+				for (read_iter = 0; read_iter < 48; read_iter++) {
+					if (dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) {
 						printk(BIOS_DEBUG, "+");
-					else
-						printk(BIOS_DEBUG, ".");
+					} else {
+						if (read_iter < 16)
+							printk(BIOS_DEBUG, "°");
+						else
+							printk(BIOS_DEBUG, ".");
+					}
 				}
 				printk(BIOS_DEBUG, "\n");
 			}
-- 
1.7.9.5

