aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge/amd/amdmct/mct_ddr3/mct_d.c')
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mct_d.c186
1 files changed, 112 insertions, 74 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
index 3338ae3f28..25c4042c23 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
@@ -162,7 +162,7 @@ static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat,
static void ChangeMemClk(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat);
void SetTargetFreq(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat);
+ struct DCTStatStruc *pDCTstatA, uint8_t Node);
static u32 mct_MR1Odt_RDimm(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel);
@@ -1410,6 +1410,10 @@ static void precise_memclk_delay_fam15(struct MCTStatStruc *pMCTstat, struct DCT
memclk_freq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
+ if (fam15h_freq_tab[memclk_freq] == 0) {
+ printk(BIOS_DEBUG, "ERROR: precise_memclk_delay_fam15 for DCT %d (delay %d clocks) failed to obtain valid memory frequency!"
+ " (pDCTstat: %p pDCTstat->dev_dct: %08x memclk_freq: %02x)\n", dct, clocks, pDCTstat, pDCTstat->dev_dct, memclk_freq);
+ }
delay_ns = (((uint64_t)clocks * 1000) / fam15h_freq_tab[memclk_freq]);
precise_ndelay_fam15(pMCTstat, delay_ns);
}
@@ -2327,7 +2331,7 @@ static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
nv_DQSTrainCTL = !allow_config_restore;
mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA);
- phyAssistedMemFnceTraining(pMCTstat, pDCTstatA);
+ phyAssistedMemFnceTraining(pMCTstat, pDCTstatA, -1);
if (is_fam15h()) {
uint8_t Node;
@@ -3367,7 +3371,7 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat,
}
static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
+ struct DCTStatStruc *pDCTstat, uint8_t dct)
{
/* Initialize DCT Timing registers as per DIMM SPD.
* For primary timing (T, CL) use best case T value.
@@ -3471,7 +3475,7 @@ static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat,
}
static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat, u8 dct)
+ struct DCTStatStruc *pDCTstat, uint8_t dct)
{
/* Find the best T and CL primary timing parameter pair, per Mfg.,
* for the given set of DIMMs, and store into DCTStatStruc
@@ -3750,10 +3754,15 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
dword++;
}
- if (Status & (1 << SB_Registered))
- DramConfigLo |= 1 << ParEn; /* Registered DIMMs */
- else
- DramConfigLo |= 1 << UnBuffDimm; /* Unbuffered DIMMs */
+ if (Status & (1 << SB_Registered)) {
+ /* Registered DIMMs */
+ if (!is_fam15h()) {
+ DramConfigLo |= 1 << ParEn;
+ }
+ } else {
+ /* Unbuffered DIMMs */
+ DramConfigLo |= 1 << UnBuffDimm;
+ }
if (mctGet_NVbits(NV_ECC_CAP))
if (Status & (1 << SB_ECCDIMMs))
@@ -3771,10 +3780,11 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
DramConfigHi |= dword - offset; /* get MemClk encoding */
DramConfigHi |= 1 << MemClkFreqVal;
- if (Status & (1 << SB_Registered))
- if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0))
- /* set only if x8 Registered DIMMs in System*/
- DramConfigHi |= 1 << RDqsEn;
+ if (!is_fam15h())
+ if (Status & (1 << SB_Registered))
+ if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0))
+ /* set only if x8 Registered DIMMs in System*/
+ DramConfigHi |= 1 << RDqsEn;
if (pDCTstat->LogicalCPUID & AMD_FAM15_ALL) {
DramConfigLo |= 1 << 25; /* PendRefPaybackS3En = 1 */
@@ -3786,14 +3796,16 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
DramConfigHi |= 1 << 16;
}
- /* Control Bank Swizzle */
- if (0) /* call back not needed mctBankSwizzleControl_D()) */
- DramConfigHi &= ~(1 << BankSwizzleMode);
- else
- DramConfigHi |= 1 << BankSwizzleMode; /* recommended setting (default) */
+ if (!is_fam15h()) {
+ /* Control Bank Swizzle */
+ if (0) /* call back not needed mctBankSwizzleControl_D()) */
+ DramConfigHi &= ~(1 << BankSwizzleMode);
+ else
+ DramConfigHi |= 1 << BankSwizzleMode; /* recommended setting (default) */
+ }
/* Check for Quadrank DIMM presence */
- if ( pDCTstat->DimmQRPresent != 0) {
+ if (pDCTstat->DimmQRPresent != 0) {
byte = mctGet_NVbits(NV_4RANKType);
if (byte == 2)
DramConfigHi |= 1 << 17; /* S4 (4-Rank SO-DIMMs) */
@@ -4598,8 +4610,9 @@ static u8 mct_setMode(struct MCTStatStruc *pMCTstat,
Set_NB32(pDCTstat->dev_dct, reg, val);
}
if (byte) /* NV_Unganged */
- pDCTstat->ErrStatus &= ~(1 << SB_DimmMismatchO); /* Clear so that there is no DIMM missmatch error */
+ pDCTstat->ErrStatus &= ~(1 << SB_DimmMismatchO); /* Clear so that there is no DIMM mismatch error */
}
+
return pDCTstat->ErrCode;
}
@@ -4660,6 +4673,8 @@ void Set_NB32_index_wait(u32 dev, u32 index_reg, u32 index, u32 data)
static u8 mct_BeforePlatformSpec(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u8 dct)
{
+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
+
/* mct_checkForCxDxSupport_D */
if (pDCTstat->LogicalCPUID & AMD_DR_GT_Bx) {
/* Family 10h Errata 322: Address and Command Fine Delay Values May Be Incorrect */
@@ -4674,6 +4689,9 @@ static u8 mct_BeforePlatformSpec(struct MCTStatStruc *pMCTstat,
else
Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, 0x98, 0x0D02E001, 0x90);
}
+
+ printk(BIOS_DEBUG, "%s: Done\n", __func__);
+
return pDCTstat->ErrCode;
}
@@ -4684,6 +4702,8 @@ static u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat,
* and program them into DCT.
*/
+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
+
u32 dev = pDCTstat->dev_dct;
u32 index_reg;
u8 i, i_start, i_end;
@@ -4704,6 +4724,8 @@ static u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat,
printk(BIOS_SPEW, "Programmed DCT %d timing/termination pattern %08x %08x\n", dct, pDCTstat->CH_ADDR_TMG[i], pDCTstat->CH_ODC_CTL[i]);
}
+ printk(BIOS_DEBUG, "%s: Done\n", __func__);
+
return pDCTstat->ErrCode;
}
@@ -4715,7 +4737,8 @@ static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat)
if (pDCTstat->NodePresent) {
dev = pDCTstat->dev_dct;
- if ((pDCTstat->DIMMValidDCT[0] ) || (pDCTstat->DIMMValidDCT[1])) { /* This Node has dram */
+ if ((pDCTstat->DIMMValidDCT[0]) || (pDCTstat->DIMMValidDCT[1])) {
+ /* This Node has DRAM */
do {
val = Get_NB32(dev, 0x110);
} while (!(val & (1 << DramEnabled)));
@@ -5663,57 +5686,56 @@ static void InitDDRPhy(struct MCTStatStruc *pMCTstat,
/* Fam15h BKDG v3.14 section 2.10.5.3
* The remainder of the Phy Initialization algorithm picks up in phyAssistedMemFnceTraining
*/
- for (dct = 0; dct < 2; dct++) {
- Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000b, 0x80000000);
- Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe013, 0x00000118);
-
- /* Program desired VDDIO level */
- if (ddr_voltage_index & 0x4) {
- /* 1.25V */
- amd_voltage_level_index = 0x2;
- } else if (ddr_voltage_index & 0x2) {
- /* 1.35V */
- amd_voltage_level_index = 0x1;
- } else if (ddr_voltage_index & 0x1) {
- /* 1.50V */
- amd_voltage_level_index = 0x0;
- }
-
- /* D18F2x9C_x0D0F_0[F,8:0]1F_dct[1:0][RxVioLvl] */
- for (index = 0; index < 0x9; index++) {
- dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f001f | (index << 8));
- dword &= ~(0x3 << 3);
- dword |= (amd_voltage_level_index << 3);
- Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f001f | (index << 8), dword);
- }
-
- /* D18F2x9C_x0D0F_[C,8,2][2:0]1F_dct[1:0][RxVioLvl] */
- for (index = 0; index < 0x3; index++) {
- dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f201f | (index << 8));
- dword &= ~(0x3 << 3);
- dword |= (amd_voltage_level_index << 3);
- Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f201f | (index << 8), dword);
- }
- for (index = 0; index < 0x2; index++) {
- dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f801f | (index << 8));
- dword &= ~(0x3 << 3);
- dword |= (amd_voltage_level_index << 3);
- Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f801f | (index << 8), dword);
- }
- for (index = 0; index < 0x1; index++) {
- dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc01f | (index << 8));
- dword &= ~(0x3 << 3);
- dword |= (amd_voltage_level_index << 3);
- Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc01f | (index << 8), dword);
- }
+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000b, 0x80000000);
+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe013, 0x00000118);
- /* D18F2x9C_x0D0F_4009_dct[1:0][CmpVioLvl, ComparatorAdjust] */
- dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f4009);
- dword &= ~(0x0000c00c);
- dword |= (amd_voltage_level_index << 14);
- dword |= (amd_voltage_level_index << 2);
- Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f4009, dword);
- }
+ /* Program desired VDDIO level */
+ if (ddr_voltage_index & 0x4) {
+ /* 1.25V */
+ amd_voltage_level_index = 0x2;
+ } else if (ddr_voltage_index & 0x2) {
+ /* 1.35V */
+ amd_voltage_level_index = 0x1;
+ } else if (ddr_voltage_index & 0x1) {
+ /* 1.50V */
+ amd_voltage_level_index = 0x0;
+ }
+
+ /* D18F2x9C_x0D0F_0[F,8:0]1F_dct[1:0][RxVioLvl] */
+ for (index = 0; index < 0x9; index++) {
+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f001f | (index << 8));
+ dword &= ~(0x3 << 3);
+ dword |= (amd_voltage_level_index << 3);
+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f001f | (index << 8), dword);
+ }
+
+ /* D18F2x9C_x0D0F_[C,8,2][2:0]1F_dct[1:0][RxVioLvl] */
+ for (index = 0; index < 0x3; index++) {
+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f201f | (index << 8));
+ dword &= ~(0x3 << 3);
+ dword |= (amd_voltage_level_index << 3);
+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f201f | (index << 8), dword);
+ }
+ for (index = 0; index < 0x2; index++) {
+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f801f | (index << 8));
+ dword &= ~(0x3 << 3);
+ dword |= (amd_voltage_level_index << 3);
+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f801f | (index << 8), dword);
+ }
+ for (index = 0; index < 0x1; index++) {
+ dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc01f | (index << 8));
+ dword &= ~(0x3 << 3);
+ dword |= (amd_voltage_level_index << 3);
+ Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc01f | (index << 8), dword);
+ }
+
+ /* D18F2x9C_x0D0F_4009_dct[1:0][CmpVioLvl, ComparatorAdjust] */
+ /* NOTE: CmpVioLvl and ComparatorAdjust only take effect when set on DCT 0 */
+ dword = Get_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0f4009);
+ dword &= ~(0x0000c00c);
+ dword |= (amd_voltage_level_index << 14);
+ dword |= (amd_voltage_level_index << 2);
+ Set_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0f4009, dword);
printk(BIOS_DEBUG, "%s: Done\n", __func__);
}
@@ -5729,18 +5751,24 @@ static void InitPhyCompensation(struct MCTStatStruc *pMCTstat,
uint32_t dword;
const u8 *p;
- printk(BIOS_DEBUG, "%s: Start\n", __func__);
+ printk(BIOS_DEBUG, "%s: DCT %d: Start\n", __func__, dct);
if (is_fam15h()) {
/* Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 */
uint32_t tx_pre;
uint32_t drive_strength;
- /* Program D18F2x9C_x0D0F_E003_dct[1:0][DisAutoComp, DisablePredriverCal] */
+ /* Program D18F2x9C_x0D0F_E003_dct[1:0][DisAutoComp] */
dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003);
- dword |= (0x3 << 13);
+ dword |= (0x1 << 14);
Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003, dword);
+ /* Program D18F2x9C_x0D0F_E003_dct[1:0][DisablePredriverCal] */
+ /* NOTE: DisablePredriverCal only takes effect when set on DCT 0 */
+ dword = Get_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0fe003);
+ dword |= (0x1 << 13);
+ Set_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0fe003, dword);
+
/* Determine TxPreP/TxPreN for data lanes (Stage 1) */
dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000);
drive_strength = (dword >> 20) & 0x7; /* DqsDrvStren */
@@ -5886,12 +5914,14 @@ static void InitPhyCompensation(struct MCTStatStruc *pMCTstat,
Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0a, dword);
}
- printk(BIOS_DEBUG, "%s: Done\n", __func__);
+ printk(BIOS_DEBUG, "%s: DCT %d: Done\n", __func__, dct);
}
static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat,
struct DCTStatStruc *pDCTstat, u8 dct)
{
+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
+
if (!is_fam15h()) {
u32 reg;
u32 val;
@@ -5913,6 +5943,8 @@ static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat,
Set_NB32_DCT(dev, dct, reg, val);
}
+
+ printk(BIOS_DEBUG, "%s: Done\n", __func__);
}
static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat,
@@ -6556,6 +6588,8 @@ void mct_SetDramConfigHi_D(struct MCTStatStruc *pMCTstat,
uint32_t dword;
+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
+
if (is_fam15h()) {
/* Initial setup for frequency change
* 9C_x0000_0004 must be configured before MemClkFreqVal is set
@@ -6588,6 +6622,8 @@ void mct_SetDramConfigHi_D(struct MCTStatStruc *pMCTstat,
mct_Wait(100);
}
+ printk(BIOS_DEBUG, "mct_SetDramConfigHi_D: DramConfigHi: %08x\n", DramConfigHi);
+
/* Program the DRAM Configuration High register */
Set_NB32_DCT(dev, dct, 0x94, DramConfigHi);
@@ -6603,6 +6639,8 @@ void mct_SetDramConfigHi_D(struct MCTStatStruc *pMCTstat,
dword |= 0x0000000f;
Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, index_reg, 0x0d0fe006, dword);
}
+
+ printk(BIOS_DEBUG, "%s: Done\n", __func__);
}
static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat,