diff options
Diffstat (limited to 'src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c')
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c index 48b72caf36..496803e94b 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c @@ -50,7 +50,7 @@ static int32_t abs(int32_t val) { */ /*----------------------------------------------------------------------------- - * void AgesaHwWlPhase1(SPDStruct *SPDData,MCTStruct *MCTData, DCTStruct *DCTData, + * uint8_t AgesaHwWlPhase1(SPDStruct *SPDData,MCTStruct *MCTData, DCTStruct *DCTData, * u8 Dimm, u8 Pass) * * Description: @@ -67,7 +67,7 @@ static int32_t abs(int32_t val) { * OUT *----------------------------------------------------------------------------- */ -void AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, +uint8_t AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct, u8 dimm, u8 pass) { u8 ByteLane; @@ -170,12 +170,15 @@ void AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTsta } pDCTData->WLCriticalGrossDelayPrevPass = 0x1f; + + return 0; } -void AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, +uint8_t AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct, u8 dimm, u8 pass) { u8 ByteLane; + uint8_t status = 0; sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; if (is_fam15h()) { @@ -202,19 +205,38 @@ void AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTsta /* Compensate for occasional noise/instability causing sporadic training failure */ for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) { + uint8_t faulty_value_detected = 0; uint16_t total_delay_seed = ((pDCTData->WLSeedGrossDelay[index+ByteLane] & 0x1f) << 5) | (pDCTData->WLSeedFineDelay[index+ByteLane] & 0x1f); uint16_t total_delay_phy = ((pDCTData->WLGrossDelay[index+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[index+ByteLane] & 0x1f); - if (abs(total_delay_phy - total_delay_seed) > 0x20) { - printk(BIOS_DEBUG, "%s: overriding faulty phy value (seed: %04x phy: %04x step: %04x)\n", __func__, + if (pass == FirstPass) { + /* Allow a somewhat higher step threshold on the first pass + * For the most part, as long as the phy isn't stepping + * several clocks at once the values are probably valid. + */ + if (abs(total_delay_phy - total_delay_seed) > 0x30) + faulty_value_detected = 1; + } else { + /* Stepping memory clocks between adjacent allowed frequencies + * should not yield large phy value differences... + */ + + if (abs(total_delay_phy - total_delay_seed) > 0x20) + faulty_value_detected = 1; + } + if (faulty_value_detected) { + printk(BIOS_INFO, "%s: overriding faulty phy value (seed: %04x phy: %04x step: %04x)\n", __func__, total_delay_seed, total_delay_phy, abs(total_delay_phy - total_delay_seed)); pDCTData->WLGrossDelay[index+ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane]; pDCTData->WLFineDelay[index+ByteLane] = pDCTData->WLSeedFineDelay[index+ByteLane]; + status = 1; } } } + + return status; } -void AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, +uint8_t AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct, u8 dimm, u8 pass) { u8 ByteLane; @@ -281,6 +303,8 @@ void AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTsta * to the normal operating termination: */ prepareDimms(pMCTstat, pDCTstat, dct, dimm, FALSE); + + return 0; } /*---------------------------------------------------------------------------- |