aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c')
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
index 22e9836757..19a7acb329 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
@@ -1664,8 +1664,10 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
uint8_t lane;
uint32_t dword;
uint32_t rx_en_offset;
+ uint8_t dct_training_success;
uint16_t initial_phy_phase_delay[MAX_BYTE_LANES];
uint16_t current_phy_phase_delay[MAX_BYTE_LANES];
+ uint8_t lane_training_success[MAX_BYTE_LANES];
uint8_t dqs_results_array[1024];
uint16_t ren_step = 0x40;
@@ -1709,6 +1711,8 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
/* 2.10.5.8.3 */
Receiver = mct_InitReceiver_D(pDCTstat, dct);
+ dct_training_success = 1;
+
/* There are four receiver pairs, loosely associated with chipselects.
* This is essentially looping over each DIMM.
*/
@@ -1719,6 +1723,9 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
continue;
}
+ for (lane = 0; lane < MAX_BYTE_LANES; lane++)
+ lane_training_success[lane] = 0;
+
/* 2.10.5.8.3 (2) */
read_dqs_receiver_enable_control_registers(initial_phy_phase_delay, dev, dct, dimm, index_reg);
@@ -1753,10 +1760,24 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
dqs_results_array[current_phy_phase_delay[lane]] = TrainDQSRdWrPos_D_Fam15(pMCTstat, pDCTstat, dct, Receiver, Receiver + 2, lane, lane + 1);
}
+ uint16_t phase_delay;
+ for (phase_delay = 0; phase_delay < 0x3ff; phase_delay++)
+ if (dqs_results_array[phase_delay])
+ lane_training_success[lane] = 1;
+
+ if (!lane_training_success[lane]) {
+ if (pDCTstat->tcwl_delay[dct] >= 1) {
+ Errors |= 1 << SB_FatalError;
+ printk(BIOS_ERR, "%s: lane %d failed to train! "
+ "Training for receiver %d on DCT %d aborted\n",
+ __func__, lane, Receiver, dct);
+ }
+ break;
+ }
+
#ifdef PRINT_PASS_FAIL_BITMAPS
- uint16_t iter;
- for (iter = 0; iter < 0x3ff; iter++) {
- if (dqs_results_array[iter])
+ for (phase_delay = 0; phase_delay < 0x3ff; phase_delay++) {
+ if (dqs_results_array[phase_delay])
printk(BIOS_DEBUG, "+");
else
printk(BIOS_DEBUG, ".");
@@ -1787,6 +1808,13 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8), dword);
}
+ for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
+ if (!lane_training_success[lane]) {
+ dct_training_success = 0;
+ Errors |= 1 << SB_NODQSPOS;
+ }
+ }
+
#if DQS_TRAIN_DEBUG > 0
printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc_D_Fam15 DQS receiver enable timing: ");
for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
@@ -1795,6 +1823,15 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
printk(BIOS_DEBUG, "\n");
#endif
}
+
+ if (!dct_training_success) {
+ if (pDCTstat->tcwl_delay[dct] < 1) {
+ /* Increase TCWL */
+ pDCTstat->tcwl_delay[dct]++;
+ /* Request retraining */
+ Errors |= 1 << SB_RetryConfigTrain;
+ }
+ }
}
pDCTstat->TrainErrors |= Errors;