aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
diff options
context:
space:
mode:
authorTimothy Pearson <tpearson@raptorengineeringinc.com>2015-08-07 19:05:29 -0500
committerStefan Reinauer <stefan.reinauer@coreboot.org>2015-11-23 18:36:44 +0100
commit845b00ce3344d1483d98cddcf59f317a1b96da64 (patch)
tree032d4c7d733897f213655420124946da785ed775 /src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
parent7e1465431a7869656026f435d7ad2b30f4e8e359 (diff)
amd/amdmct/mct_ddr3: Fix poor performance on Family 15h CPUs
Change-Id: Ib6bc197e43e40ba2b923b1eb1229bacafc8be360 Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> Reviewed-on: http://review.coreboot.org/12029 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c')
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c65
1 files changed, 51 insertions, 14 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
index 3615616cd5..06597e23bb 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
@@ -20,6 +20,9 @@ static void write_dqs_receiver_enable_control_registers(uint16_t* current_total_
static void read_read_dqs_timing_control_registers(uint16_t* current_total_delay,
uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg);
+static void dqsTrainMaxRdLatency_SW_Fam15(struct MCTStatStruc *pMCTstat,
+ struct DCTStatStruc *pDCTstat);
+
static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u16 like,
u8 scale, u8 ChipSel);
@@ -214,6 +217,27 @@ void TrainReceiverEn_D(struct MCTStatStruc *pMCTstat,
}
}
+void TrainMaxRdLatency_En_D(struct MCTStatStruc *pMCTstat,
+ struct DCTStatStruc *pDCTstatA)
+{
+ uint8_t node;
+ struct DCTStatStruc *pDCTstat;
+
+ for (node = 0; node < MAX_NODES_SUPPORTED; node++) {
+ pDCTstat = pDCTstatA + node;
+
+ if (pDCTstat->DCTSysLimit) {
+ if (is_fam15h()) {
+ dqsTrainMaxRdLatency_SW_Fam15(pMCTstat, pDCTstat);
+ } else {
+ /* FIXME
+ * Implement Family 10h MaxRdLatency training
+ */
+ }
+ }
+ }
+}
+
static void SetEccDQSRdWrPos_D_Fam10(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u8 ChipSel)
{
@@ -894,7 +918,7 @@ static void TrainDQSRdWrPos_D_Fam10(struct MCTStatStruc *pMCTstat,
* Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.8.5
*/
static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, uint8_t dct)
+ struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t calc_min)
{
uint8_t dimm;
uint8_t lane;
@@ -938,7 +962,8 @@ static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat,
p += (9 - dword);
/* 2.10.5.8.5 (4) */
- p += 5;
+ if (!calc_min)
+ p += 5;
/* 2.10.5.8.5 (5) */
dword = Get_NB32_DCT(dev, dct, 0xa8);
@@ -965,7 +990,8 @@ static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat,
p += (max_delay >> 5);
/* 2.10.5.8.5 (8) */
- p += 5;
+ if (!calc_min)
+ p += 5;
/* 2.10.5.8.5 (9) */
t += 800;
@@ -976,13 +1002,16 @@ static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat,
n = (((((uint64_t)p * 1000000000000ULL)/(((uint64_t)fam15h_freq_tab[mem_clk] * 1000000ULL) * 2)) + ((uint64_t)t)) * ((uint64_t)nb_clk * 1000)) / 1000000000ULL;
/* 2.10.5.8.5 (11) */
- n -= 1;
+ if (!calc_min)
+ n -= 1;
/* 2.10.5.8.5 (12) */
- dword = Get_NB32_DCT_NBPstate(dev, dct, nb_pstate, 0x210);
- dword &= ~(0x3ff << 22);
- dword |= (((n - 1) & 0x3ff) << 22);
- Set_NB32_DCT_NBPstate(dev, dct, nb_pstate, 0x210, dword);
+ if (!calc_min) {
+ dword = Get_NB32_DCT_NBPstate(dev, dct, nb_pstate, 0x210);
+ dword &= ~(0x3ff << 22);
+ dword |= (((n - 1) & 0x3ff) << 22);
+ Set_NB32_DCT_NBPstate(dev, dct, nb_pstate, 0x210, dword);
+ }
/* Save result for later use */
pDCTstat->CH_MaxRdLat[dct] = n - 1;
@@ -1103,6 +1132,9 @@ static void read_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
} else if (lane < 8) {
Set_NB32_DCT(dev, dct, 0x274, ~0x0);
Set_NB32_DCT(dev, dct, 0x278, ~(0xff << (lane * 8)));
+ } else if (lane == 0xff) {
+ Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff);
+ Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff);
} else {
Set_NB32_DCT(dev, dct, 0x274, ~0x0);
Set_NB32_DCT(dev, dct, 0x278, ~0x0);
@@ -1110,8 +1142,9 @@ static void read_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
dword = Get_NB32_DCT(dev, dct, 0x27c);
dword &= ~(0xff); /* EccMask = 0 */
- if ((lane != 8) || (pDCTstat->DimmECCPresent == 0))
- dword |= 0xff; /* EccMask = 0xff */
+ if (lane != 0xff)
+ if ((lane != 8) || (pDCTstat->DimmECCPresent == 0))
+ dword |= 0xff; /* EccMask = 0xff */
Set_NB32_DCT(dev, dct, 0x27c, dword);
dword = Get_NB32_DCT(dev, dct, 0x270);
@@ -1180,6 +1213,9 @@ static void write_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
} else if (lane < 8) {
Set_NB32_DCT(dev, dct, 0x274, ~0x0);
Set_NB32_DCT(dev, dct, 0x278, ~(0xff << (lane * 8)));
+ } else if (lane == 0xff) {
+ Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff);
+ Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff);
} else {
Set_NB32_DCT(dev, dct, 0x274, ~0x0);
Set_NB32_DCT(dev, dct, 0x278, ~0x0);
@@ -1187,8 +1223,9 @@ static void write_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
dword = Get_NB32_DCT(dev, dct, 0x27c);
dword &= ~(0xff); /* EccMask = 0 */
- if ((lane != 8) || (pDCTstat->DimmECCPresent == 0))
- dword |= 0xff; /* EccMask = 0xff */
+ if (lane != 0xff)
+ if ((lane != 8) || (pDCTstat->DimmECCPresent == 0))
+ dword |= 0xff; /* EccMask = 0xff */
Set_NB32_DCT(dev, dct, 0x27c, dword);
dword = Get_NB32_DCT(dev, dct, 0x270);
@@ -1274,7 +1311,7 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat,
uint32_t dev = pDCTstat->dev_dct;
/* Calculate and program MaxRdLatency */
- Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct);
+ Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct, 0);
Errors = 0;
dual_rank = 0;
@@ -1632,7 +1669,7 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
write_dqs_receiver_enable_control_registers(current_phy_phase_delay, dev, dct, dimm, index_reg);
/* Calculate and program MaxRdLatency */
- Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct);
+ Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct, 0);
/* 2.10.5.8.3 (4 B) */
dqs_results_array[current_phy_phase_delay[lane]] = TrainDQSRdWrPos_D_Fam15(pMCTstat, pDCTstat, dct, Receiver, Receiver + 2, lane, lane + 1);