[coreboot-gerrit] New patch to review for coreboot: nb/amd/amdmct: Select max_lanes based on ECC presence or absence

Damien Zammit (damien@zamaudio.com) gerrit at coreboot.org
Wed Feb 17 04:38:00 CET 2016


Damien Zammit (damien at zamaudio.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/13725

-gerrit

commit e897b86da39baa10e08dc9a325e152f4a520c8ee
Author: Damien Zammit <damien at zamaudio.com>
Date:   Wed Feb 17 14:14:47 2016 +1100

    nb/amd/amdmct: Select max_lanes based on ECC presence or absence
    
    Change-Id: Ic5482dc13ab7b53ec4df408bbe32d20888ae2e12
    Signed-off-by: Damien Zammit <damien at zamaudio.com>
---
 src/northbridge/amd/amdmct/mct_ddr3/mct_d.c    | 15 +++---
 src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c | 29 ++++++++---
 src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c  | 72 +++++++++++++++++++-------
 3 files changed, 84 insertions(+), 32 deletions(-)

diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
index edb500a..9d87be6 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
@@ -2613,6 +2613,7 @@ static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat,
 	uint8_t allow_config_restore;
 
 	uint8_t s3resume = acpi_is_wakeup_s3();
+	u8 ecc_enabled = !!(pMCTstat->GStatus & 1 << GSB_ECCDIMMs);
 
 restartinit:
 	mctInitMemGPIOs_A_D();		/* Set any required GPIOs*/
@@ -2812,12 +2813,14 @@ restartinit:
 		InterleaveNodes_D(pMCTstat, pDCTstatA);
 		InterleaveChannels_D(pMCTstat, pDCTstatA);
 
-		printk(BIOS_DEBUG, "mctAutoInitMCT_D: ECCInit_D\n");
-		if (!ECCInit_D(pMCTstat, pDCTstatA)) {			/* Setup ECC control and ECC check-bits*/
-			/* Memory was not cleared during ECC setup */
-			/* mctDoWarmResetMemClr_D(); */
-			printk(BIOS_DEBUG, "mctAutoInitMCT_D: MCTMemClr_D\n");
-			MCTMemClr_D(pMCTstat,pDCTstatA);
+		if (ecc_enabled) {
+			printk(BIOS_DEBUG, "mctAutoInitMCT_D: ECCInit_D\n");
+			if (!ECCInit_D(pMCTstat, pDCTstatA)) {			/* Setup ECC control and ECC check-bits*/
+				/* Memory was not cleared during ECC setup */
+				/* mctDoWarmResetMemClr_D(); */
+				printk(BIOS_DEBUG, "mctAutoInitMCT_D: MCTMemClr_D\n");
+				MCTMemClr_D(pMCTstat,pDCTstatA);
+			}
 		}
 
 		if (is_fam15h()) {
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
index 22e9836..e02eaa5 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
@@ -942,6 +942,13 @@ static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat,
 	printk(BIOS_DEBUG, "%s: Start\n", __func__);
 #endif
 
+	u8 max_lane;
+	u8 ecc_enabled = !!(pMCTstat->GStatus & 1 << GSB_ECCDIMMs);
+	if (ecc_enabled)
+		max_lane = 9;
+	else
+		max_lane = 8;
+
 	mem_clk = Get_NB32_DCT(dev, dct, 0x94) & 0x1f;
 	if (fam15h_freq_tab[mem_clk] == 0) {
 		pDCTstat->CH_MaxRdLat[dct] = 0x55;
@@ -983,7 +990,7 @@ static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat,
 
 			read_dqs_receiver_enable_control_registers(current_phy_phase_delay, dev, dct, dimm, index_reg);
 			read_read_dqs_timing_control_registers(current_read_dqs_delay, dev, dct, dimm, index_reg);
-			for (lane = 0; lane < MAX_BYTE_LANES; lane++)
+			for (lane = 0; lane < max_lane; lane++)
 				if ((current_phy_phase_delay[lane] + current_read_dqs_delay[lane]) > max_delay)
 					max_delay = (current_phy_phase_delay[lane] + current_read_dqs_delay[lane]);
 		}
@@ -1672,6 +1679,13 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
 	uint32_t index_reg = 0x98;
 	uint32_t dev = pDCTstat->dev_dct;
 
+	u8 max_lane;
+	u8 ecc_enabled = !!(pMCTstat->GStatus & 1 << GSB_ECCDIMMs);
+	if (ecc_enabled)
+		max_lane = 9;
+	else
+		max_lane = 8;
+
 	print_debug_dqs("\nTrainDQSReceiverEnCyc: Node_ID ", pDCTstat->Node_ID, 0);
 	cr4 = read_cr4();
 	if (cr4 & (1<<9)) {
@@ -1689,7 +1703,8 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
 	_WRMSR(addr, lo, hi);	/* allow 64-bit memory references in real mode */
 
 	/* Disable ECC correction of reads on the dram bus. */
-	_DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat);
+	if (ecc_enabled)
+		_DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat);
 
 	Errors = 0;
 
@@ -1722,7 +1737,7 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
 			/* 2.10.5.8.3 (2) */
 			read_dqs_receiver_enable_control_registers(initial_phy_phase_delay, dev, dct, dimm, index_reg);
 
-			for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
+			for (lane = 0; lane < max_lane; lane++) {
 				/* Initialize variables */
 				memset(dqs_results_array, 0, sizeof(dqs_results_array));
 
@@ -1789,7 +1804,7 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
 
 #if DQS_TRAIN_DEBUG > 0
 			printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc_D_Fam15 DQS receiver enable timing: ");
-			for (lane = 0; lane < MAX_BYTE_LANES; lane++) {
+			for (lane = 0; lane < max_lane; lane++) {
 				printk(BIOS_DEBUG, " %03x", current_phy_phase_delay[lane]);
 			}
 			printk(BIOS_DEBUG, "\n");
@@ -1829,8 +1844,10 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
 
 	}
 #endif
-	if (_DisableDramECC) {
-		mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC);
+	if (ecc_enabled) {
+		if (_DisableDramECC) {
+			mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC);
+		}
 	}
 	if (!_Wrap32Dis) {
 		addr = HWCR;
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
index 2b8a997..2676c7e 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
@@ -32,7 +32,7 @@ void prepareDimms(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat,
 	u8 dct, u8 dimm, BOOL wl);
 void programODT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, u8 dimm);
 void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t pass, uint8_t nibble);
-void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, u8 targetAddr, uint8_t pass);
+void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, u8 targetAddr, uint8_t pass, u8 max_lane);
 void getWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, uint8_t pass, uint8_t nibble);
 
 static int32_t abs(int32_t val) {
@@ -77,6 +77,14 @@ uint8_t AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCT
 	u16 Addl_Data_Offset, Addl_Data_Port;
 	sMCTStruct *pMCTData = pDCTstat->C_MCTPtr;
 	sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
+	uint8_t ecc_enabled;
+	uint8_t max_lane;
+
+	ecc_enabled = !!(pMCTstat->GStatus & 1 << GSB_ECCDIMMs);
+	if (ecc_enabled)
+		max_lane = 9;
+	else
+		max_lane = 8;
 
 	pDCTData->WLPass = pass;
 	/* 1. Specify the target DIMM that is to be trained by programming
@@ -176,7 +184,7 @@ uint8_t AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCT
 		/* Read from registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52
 		 * to get the gross and fine delay settings
 		 * for the target DIMM and save these values. */
-		for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+		for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
 			getWLByteDelay(pDCTstat, dct, ByteLane, dimm, pass, nibble);
 		}
 
@@ -192,6 +200,14 @@ uint8_t AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCT
 	u8 ByteLane;
 	uint8_t status = 0;
 	sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
+	uint8_t ecc_enabled;
+	uint8_t max_lane;
+
+	ecc_enabled = !!(pMCTstat->GStatus & 1 << GSB_ECCDIMMs);
+	if (ecc_enabled)
+		max_lane = 9;
+	else
+		max_lane = 8;
 
 	if (is_fam15h()) {
 		int32_t gross_diff[MAX_BYTE_LANES];
@@ -205,7 +221,7 @@ uint8_t AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCT
 		 */
 
 		/* Calculate the Critical Gross Delay */
-		for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+		for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
 			/* Calculate the gross delay differential for this lane */
 			gross_diff[ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane] + pDCTData->WLGrossDelay[index+ByteLane];
 			gross_diff[ByteLane] -= pDCTData->WLSeedPreGrossDelay[index+ByteLane];
@@ -231,7 +247,7 @@ uint8_t AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCT
 			 * Figure out why this is and fix it, then remove the bypass code below...
 			 */
 			if (pass == FirstPass) {
-				for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+				for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
 					pDCTData->WLGrossDelay[index+ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane];
 					pDCTData->WLFineDelay[index+ByteLane] = pDCTData->WLSeedFineDelay[index+ByteLane];
 				}
@@ -240,7 +256,7 @@ uint8_t AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCT
 		}
 
 		/* Compensate for occasional noise/instability causing sporadic training failure */
-		for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+		for (ByteLane = 0; ByteLane < max_lane; 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);
@@ -278,6 +294,14 @@ uint8_t AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCT
 	u8 ByteLane;
 	sMCTStruct *pMCTData = pDCTstat->C_MCTPtr;
 	sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
+	uint8_t ecc_enabled;
+	u8 max_lane;
+
+	ecc_enabled = !!(pMCTstat->GStatus & 1 << GSB_ECCDIMMs);
+	if (ecc_enabled)
+		max_lane = 9;
+	else
+		max_lane = 8;
 
 	if (is_fam15h()) {
 		uint32_t dword;
@@ -292,7 +316,7 @@ uint8_t AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCT
 			dword |= ((abs(cgd) & 0x3) << 24);
 			Set_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8, dword);
 
-			for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+			for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
 				/* Calculate the gross delay differential for this lane */
 				gross_diff[ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane] + pDCTData->WLGrossDelay[index+ByteLane];
 				gross_diff[ByteLane] -= pDCTData->WLSeedPreGrossDelay[index+ByteLane];
@@ -313,8 +337,8 @@ uint8_t AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCT
 
 	/* Write the adjusted gross and fine delay settings
 	 * to the target DIMM. */
-	for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
-		setWLByteDelay(pDCTstat, dct, ByteLane, dimm, 1, pass);
+	for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
+		setWLByteDelay(pDCTstat, dct, ByteLane, dimm, 1, pass, max_lane);
 	}
 
 	/* 6. Configure DRAM Phy Control Register so that the phy stops driving
@@ -1006,6 +1030,14 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 	sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
 	uint16_t fam10h_freq_tab[] = {0, 0, 0, 400, 533, 667, 800};
 	uint16_t fam15h_freq_tab[] = {0, 0, 0, 0, 333, 0, 400, 0, 0, 0, 533, 0, 0, 0, 667, 0, 0, 0, 800, 0, 0, 0, 933};
+	uint8_t ecc_enabled;
+	uint8_t max_lane;
+
+	ecc_enabled = !!(pMCTstat->GStatus & 1 << GSB_ECCDIMMs);
+	if (ecc_enabled)
+		max_lane = 9;
+	else
+		max_lane = 8;
 
 	if (is_fam15h()) {
 		/* MemClkFreq: 0x4: 333MHz; 0x6: 400MHz; 0xa: 533MHz; 0xe: 667MHz; 0x12: 800MHz; 0x16: 933MHz */
@@ -1113,7 +1145,7 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 			Seed_Fine = Seed_Total & 0x1f;
 
 			/* Save seed values for later use */
-			for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+			for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
 				pDCTData->WLSeedGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Gross;
 				pDCTData->WLSeedFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
 
@@ -1150,7 +1182,7 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 				}
 			}
 		}
-		for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++)
+		for (ByteLane = 0; ByteLane < max_lane; ByteLane++)
 		{
 			/* Program an initialization value to registers F2x[1, 0]9C_x[51:50] and
 			 * F2x[1, 0]9C_x52 to set the gross and fine delay for all the byte lane fields
@@ -1194,7 +1226,7 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 				WrDqDqsEarly = 0;
 
 				/* Generate new seed values */
-				for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+				for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
 					/* Calculate adjusted seed values */
 					SeedTotal[ByteLane] = (pDCTData->WLFineDelayPrevPass[MAX_BYTE_LANES*dimm+ByteLane] & 0x1f) |
 						((pDCTData->WLGrossDelayPrevPass[MAX_BYTE_LANES*dimm+ByteLane] & 0x1f) << 5);
@@ -1204,7 +1236,7 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 				}
 
 				/* Generate register values from seeds */
-				for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+				for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
 					printk(BIOS_SPEW, "\tLane %02x scaled delay: %04x\n", ByteLane, SeedTotal[ByteLane]);
 
 					if (SeedTotal[ByteLane] >= 0) {
@@ -1243,7 +1275,7 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 				uint32_t SeedTotalPreScaling;
 				uint32_t SeedTotal;
 				uint8_t AddrCmdPrelaunch = 0;		/* TODO: Fetch the correct value from RC2[0] */
-				for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++)
+				for (ByteLane = 0; ByteLane < max_lane; ByteLane++)
 				{
 					if (pDCTData->Status[DCT_STATUS_REGISTERED]) {
 						if (AddrCmdPrelaunch == 0)
@@ -1285,7 +1317,7 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 			}
 
 			/* Save initial seeds for upper nibble pass */
-			for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+			for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
 				pDCTData->WLSeedPreGrossPrevNibble[MAX_BYTE_LANES*dimm+ByteLane] = pDCTData->WLSeedPreGrossDelay[MAX_BYTE_LANES*dimm+ByteLane];
 				pDCTData->WLSeedGrossPrevNibble[MAX_BYTE_LANES*dimm+ByteLane] = pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane];
 				pDCTData->WLSeedFinePrevNibble[MAX_BYTE_LANES*dimm+ByteLane] = pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane];
@@ -1293,7 +1325,7 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 		} else {
 			/* Restore seed values from lower nibble pass */
 			if (is_fam15h()) {
-				for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+				for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
 					pDCTData->WLSeedGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = pDCTData->WLSeedGrossPrevNibble[MAX_BYTE_LANES*dimm+ByteLane];
 					pDCTData->WLSeedFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = pDCTData->WLSeedFinePrevNibble[MAX_BYTE_LANES*dimm+ByteLane];
 					pDCTData->WLSeedPreGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = pDCTData->WLSeedPreGrossPrevNibble[MAX_BYTE_LANES*dimm+ByteLane];
@@ -1304,7 +1336,7 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 					printk(BIOS_SPEW, "\tLane %02x new seed: %04x\n", ByteLane, ((pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] & 0x1f));
 				}
 			} else {
-				for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+				for (ByteLane = 0; ByteLane < max_lane; ByteLane++) {
 					pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = pDCTData->WLSeedGrossPrevNibble[MAX_BYTE_LANES*dimm+ByteLane];
 					pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = pDCTData->WLSeedFinePrevNibble[MAX_BYTE_LANES*dimm+ByteLane];
 
@@ -1315,11 +1347,11 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 	}
 
 	pDCTData->WLPrevMemclkFreq = MemClkFreq;
-	setWLByteDelay(pDCTstat, dct, ByteLane, dimm, 0, pass);
+	setWLByteDelay(pDCTstat, dct, ByteLane, dimm, 0, pass, max_lane);
 }
 
 /*-----------------------------------------------------------------------------
- *  void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 Dimm){
+ *  void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 Dimm, u8 max_lane){
  *
  *  Description:
  *       This function writes the write levelization byte delay for the Phase
@@ -1339,7 +1371,7 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
  *
  *-----------------------------------------------------------------------------
  */
-void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, u8 targetAddr, uint8_t pass)
+void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, u8 targetAddr, uint8_t pass, u8 max_lane)
 {
 	sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
 	u8 fineStartLoc, fineEndLoc, grossStartLoc, grossEndLoc, tempB, index, offsetAddr;
@@ -1352,7 +1384,7 @@ void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8
 		ValueHigh = 0;
 		ByteLane = 0;
 		EccValue = 0;
-		while (ByteLane < MAX_BYTE_LANES)
+		while (ByteLane < max_lane)
 		{
 			if (is_fam15h()) {
 				grossDelayValue = pDCTData->WLGrossDelay[index+ByteLane];



More information about the coreboot-gerrit mailing list