1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
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
|