The code is tested on my board with register DIMMs. More tests need to be
done. Please send the testing report. Note: The pDCTstat->PresetmaxFreq in mctGet_MaxLoadFreq() should be set to a higher limit, otherwise the frequnce will be set as 400MHz. Signed-off-by: Zheng Bao <zheng.bao@amd.com> Acked-by: Scott Duplichan <scott@notabs.org> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6258 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
a1125235ec
commit
a7296e74f1
|
@ -342,7 +342,21 @@ void SetTargetFreq(struct MCTStatStruc *pMCTstat,
|
||||||
mct_Wait(250);
|
mct_Wait(250);
|
||||||
|
|
||||||
if (pDCTstat->Status & (1 << SB_Registered)) {
|
if (pDCTstat->Status & (1 << SB_Registered)) {
|
||||||
/* TODO: Assuming the dct==0. The agesa here is confusing. */
|
u8 DCT0Present, DCT1Present;
|
||||||
|
|
||||||
|
DCT0Present = pDCTstat->DIMMValidDCT[0];
|
||||||
|
if (pDCTstat->GangedMode)
|
||||||
|
DCT1Present = 0;
|
||||||
|
else
|
||||||
|
DCT1Present = pDCTstat->DIMMValidDCT[1];
|
||||||
|
|
||||||
|
if (!DCT1Present)
|
||||||
|
pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
|
||||||
|
else if (pDCTstat->GangedMode) {
|
||||||
|
pDCTstat->CSPresent = 0;
|
||||||
|
} else
|
||||||
|
pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[1];
|
||||||
|
|
||||||
FreqChgCtrlWrd(pMCTstat, pDCTstat);
|
FreqChgCtrlWrd(pMCTstat, pDCTstat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ void AgesaHwWlPhase1(sMCTStruct *pMCTData, sDCTStruct *pDCTData,
|
||||||
procConifg(pMCTData,pDCTData, dimm, pass);
|
procConifg(pMCTData,pDCTData, dimm, pass);
|
||||||
/* 5. Begin write levelization training:
|
/* 5. Begin write levelization training:
|
||||||
* Program F2x[1, 0]9C_x08[WrtLevelTrEn]=1. */
|
* Program F2x[1, 0]9C_x08[WrtLevelTrEn]=1. */
|
||||||
if (pDCTData->LogicalCPUID & AMD_DR_Cx)
|
if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx))
|
||||||
set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
|
set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
|
||||||
DRAM_ADD_DCT_PHY_CONTROL_REG, WrtLvTrEn, WrtLvTrEn, 1);
|
DRAM_ADD_DCT_PHY_CONTROL_REG, WrtLvTrEn, WrtLvTrEn, 1);
|
||||||
else
|
else
|
||||||
|
@ -656,9 +656,9 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass)
|
||||||
programODT(pMCTData, pDCTData, dimm);
|
programODT(pMCTData, pDCTData, dimm);
|
||||||
|
|
||||||
/* Program F2x[1,0]9C_x08[WrLvOdtEn]=1 */
|
/* Program F2x[1,0]9C_x08[WrLvOdtEn]=1 */
|
||||||
if (pDCTData->LogicalCPUID & AMD_DR_Cx)
|
if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx))
|
||||||
set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
|
set_DCT_ADDR_Bits(pDCTData, pDCTData->DctTrain, pDCTData->NodeId, FUN_DCT,
|
||||||
DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, WrLvOdtEn,(u32) 1);
|
DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, WrLvOdtEn, (u32)1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Program WrLvOdtEn=1 through set bit 12 of D3CSODT reg offset 0 for Rev.B*/
|
/* Program WrLvOdtEn=1 through set bit 12 of D3CSODT reg offset 0 for Rev.B*/
|
||||||
|
@ -722,7 +722,36 @@ void procConifg(sMCTStruct *pMCTData,sDCTStruct *pDCTData, u8 dimm, u8 pass)
|
||||||
pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
|
pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
|
||||||
ByteLane++;
|
ByteLane++;
|
||||||
}
|
}
|
||||||
|
} else if (pDCTData->Status[DCT_STATUS_REGISTERED]) { /* For Pass 2 */
|
||||||
|
/* From BKDG, Write Leveling Seed Value. */
|
||||||
|
/* TODO: The unbuffered DIMMs are unstable on the code below. So temporarily it is
|
||||||
|
* only for registered DIMMs. */
|
||||||
|
u32 RegisterDelay, SeedTotal;
|
||||||
|
u8 MemClkFreq;
|
||||||
|
u16 freq_tab[] = {400, 533, 667, 800};
|
||||||
|
while(ByteLane < MAX_BYTE_LANES)
|
||||||
|
{
|
||||||
|
MemClkFreq = get_Bits(pDCTData, pDCTData->CurrDct, pDCTData->NodeId,
|
||||||
|
FUN_DCT, DRAM_CONFIG_HIGH, 0, 2);
|
||||||
|
if (pDCTData->Status[DCT_STATUS_REGISTERED])
|
||||||
|
RegisterDelay = 0x20; /* TODO: ((RCW2 & BIT0) == 0) ? 0x20 : 0x30; */
|
||||||
|
else
|
||||||
|
RegisterDelay = 0;
|
||||||
|
SeedTotal = (pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] & 0x1F) |
|
||||||
|
pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] << 5;
|
||||||
|
/* SeedTotalPreScaling = (the total delay value in F2x[1, 0]9C_x[4A:30] from pass 1 of write levelization
|
||||||
|
training) - RegisterDelay. */
|
||||||
|
/* MemClkFreq: 3: 400Mhz; 4: 533Mhz; 5: 667Mhz; 6: 800Mhz */
|
||||||
|
SeedTotal = (u16) (RegisterDelay + ((((u32) SeedTotal - RegisterDelay) *
|
||||||
|
freq_tab[MemClkFreq-3]) / 400));
|
||||||
|
Seed_Gross = (SeedTotal & 0x20) != 0 ? 1 : 2;
|
||||||
|
Seed_Fine = SeedTotal & 0x1F;
|
||||||
|
pDCTData->WLGrossDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Gross;
|
||||||
|
pDCTData->WLFineDelay[MAX_BYTE_LANES*dimm+ByteLane] = Seed_Fine;
|
||||||
|
ByteLane ++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setWLByteDelay(pDCTData, ByteLane, dimm, 0);
|
setWLByteDelay(pDCTData, ByteLane, dimm, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue