nb/amd/amdmct: Add socket specific configuration for FM2

Change-Id: I1088064e5f84fcabcd51e0eaaedfb5074f7fb2b5
Signed-off-by: Damien Zammit <damien@zamaudio.com>
Reviewed-on: https://review.coreboot.org/13709
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
Tested-by: Raptor Engineering Automated Test Stand <noreply@raptorengineeringinc.com>
This commit is contained in:
Damien Zammit 2016-02-13 16:53:34 +11:00 committed by Martin Roth
parent a649a543ba
commit 41462bd0c3
6 changed files with 291 additions and 21 deletions

View File

@ -241,6 +241,9 @@ static const u8 Tab_C32CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0
/* G34: Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */ /* G34: Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */
static const u8 Tab_G34CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; static const u8 Tab_G34CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00};
/* FM2: Enable all the clocks for the dimms */
static const u8 Tab_FM2CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00};
static const u8 Tab_ManualCLKDis[]= {0x10, 0x04, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00}; static const u8 Tab_ManualCLKDis[]= {0x10, 0x04, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00};
/* ========================================================================================== */ /* ========================================================================================== */
@ -311,6 +314,21 @@ static uint16_t fam10h_mhz_to_memclk_config(uint16_t freq)
return freq; return freq;
} }
static inline uint8_t is_model10_1f(void)
{
uint8_t model101f = 0;
uint32_t family;
family = cpuid_eax(0x80000001);
family = ((family & 0x0ff000) >> 12);
if (family >= 0x10 && family <= 0x1f)
/* Model 0x10 to 0x1f */
model101f = 1;
return model101f;
}
static uint16_t mhz_to_memclk_config(uint16_t freq) static uint16_t mhz_to_memclk_config(uint16_t freq)
{ {
if (is_fam15h()) if (is_fam15h())
@ -686,6 +704,19 @@ static uint32_t fam15h_phy_predriver_calibration_code(struct DCTStatStruc *pDCTs
calibration_code = 0xb6d; calibration_code = 0xb6d;
} }
} }
} else if (package_type == PT_FM2) {
/* Socket FM2 */
if (ddr_voltage_index & 0x1) {
/* 1.5V */
/* Fam15h BKDG Rev. 3.12 section 2.9.5.4.4 Table 22 */
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
/* DDR3-667 - DDR3-800 */
calibration_code = 0xb24;
} else if (MemClkFreq >= 0xa) {
/* DDR3-1066 or higher */
calibration_code = 0xff6;
}
}
} }
} else { } else {
/* LRDIMM */ /* LRDIMM */
@ -1242,6 +1273,66 @@ static uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCT
*/ */
} }
} }
} else if (package_type == PT_FM2) {
/* Socket FM2 */
/* Assume UDIMM */
/* Fam15h Model10h BKDG Rev. 3.12 section 2.9.5.6.6 Table 32 */
if (MaxDimmsInstallable == 1) {
rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
if (MemClkFreq == 0x4) {
/* DDR3-667 */
calibration_code = 0x00112222;
} else if (MemClkFreq == 0x6) {
/* DDR3-800 */
calibration_code = 0x10112222;
} else if (MemClkFreq == 0xa) {
/* DDR3-1066 */
calibration_code = 0x20112222;
} else if (MemClkFreq >= 0xe) {
/* DDR3-1333 or higher */
calibration_code = 0x30112222;
}
} else if (MaxDimmsInstallable == 2) {
rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
if (dimm_count == 1) {
/* 1 DIMM detected */
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
/* DDR3-667 or DDR3-800 */
calibration_code = 0x00112222;
} else if (MemClkFreq == 0xa) {
/* DDR3-1066 */
calibration_code = 0x10112222;
} else if (MemClkFreq == 0xe) {
/* DDR3-1333 */
calibration_code = 0x20112222;
} else if (MemClkFreq >= 0x12) {
/* DDR3-1600 or higher */
calibration_code = 0x30112222;
}
} else if (dimm_count == 2) {
/* 2 DIMMs detected */
rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
if (MemClkFreq == 0x4) {
/* DDR3-667 */
calibration_code = 0x10222322;
} else if (MemClkFreq == 0x6) {
/* DDR3-800 */
calibration_code = 0x20222322;
} else if (MemClkFreq >= 0xa) {
/* DDR3-1066 or higher */
calibration_code = 0x30222322;
}
}
} else if (MaxDimmsInstallable == 3) {
/* TODO
* 3 DIMM/channel support unimplemented
*/
}
} else { } else {
/* TODO /* TODO
* Other socket support unimplemented * Other socket support unimplemented
@ -1574,6 +1665,63 @@ static uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDC
*/ */
} }
} }
} else if (package_type == PT_FM2) {
/* Socket FM2 */
/* Assume UDIMM */
/* Fam15h Model10h BKDG Rev. 3.12 section 2.9.5.6.6 Table 32 */
if (dimm_count == 1) {
/* 1 DIMM detected */
rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
/* DDR3-667 or DDR3-800 */
if (rank_count_dimm0 == 1)
calibration_code = 0x00000000;
else
calibration_code = 0x003b0000;
} else if (MemClkFreq == 0xa) {
/* DDR3-1066 */
if (rank_count_dimm0 == 1)
calibration_code = 0x00000000;
else
calibration_code = 0x00380000;
} else if (MemClkFreq == 0xe) {
/* DDR3-1333 */
if (rank_count_dimm0 == 1)
calibration_code = 0x00000000;
else
calibration_code = 0x00360000;
} else if (MemClkFreq >= 0x12) {
/* DDR3-1600 or higher */
calibration_code = 0x00000000;
}
} else if (dimm_count == 2) {
/* 2 DIMMs detected */
rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
/* DDR3-667 or DDR3-800 */
calibration_code = 0x00390039;
} else if (MemClkFreq == 0xa) {
/* DDR3-1066 */
calibration_code = 0x00350037;
} else if (MemClkFreq == 0xe) {
/* DDR3-1333 */
calibration_code = 0x00000035;
} else if (MemClkFreq == 0x12) {
/* DDR3-1600 */
calibration_code = 0x0000002b;
} else if (MemClkFreq > 0x12) {
/* DDR3-1866 or greater */
calibration_code = 0x00000031;
}
} else if (MaxDimmsInstallable == 3) {
/* TODO
* 3 DIMM/channel support unimplemented
*/
}
} else { } else {
/* TODO /* TODO
* Other socket support unimplemented * Other socket support unimplemented
@ -1724,6 +1872,59 @@ static uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dc
*/ */
} }
} }
} else if (package_type == PT_FM2) {
/* Socket FM2 */
/* UDIMM */
/* Fam15h Model10 BKDG Rev. 3.12 section 2.9.5.6.6 Table 32 */
if (MaxDimmsInstallable == 1) {
rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)
|| (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) {
/* DDR3-667 - DDR3-1333 */
slow_access = 0;
} else if (MemClkFreq >= 0x12) {
/* DDR3-1600 or higher */
if (rank_count_dimm0 == 1)
slow_access = 0;
else
slow_access = 1;
}
} else if (MaxDimmsInstallable == 2) {
if (dimm_count == 1) {
/* 1 DIMM detected */
rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)
|| (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) {
/* DDR3-667 - DDR3-1333 */
slow_access = 0;
} else if (MemClkFreq >= 0x12) {
/* DDR3-1600 or higher */
if (rank_count_dimm0 == 1)
slow_access = 0;
else
slow_access = 1;
}
} else if (dimm_count == 2) {
/* 2 DIMMs detected */
rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)
|| (MemClkFreq == 0xa)) {
/* DDR3-667 - DDR3-1066 */
slow_access = 0;
} else if (MemClkFreq >= 0xe) {
/* DDR3-1333 or higher */
slow_access = 1;
}
}
} else if (MaxDimmsInstallable == 3) {
/* TODO
* 3 DIMM/channel support unimplemented
*/
}
} else { } else {
/* TODO /* TODO
* Other socket support unimplemented * Other socket support unimplemented
@ -1919,6 +2120,10 @@ static uint8_t fam15h_odt_tristate_enable_code(struct DCTStatStruc *pDCTstat, ui
*/ */
} }
} }
} else if (package_type == PT_FM2) {
/* Socket FM2 */
/* UDIMM */
odt_tristate_code = 0x0;
} else { } else {
/* TODO /* TODO
* Other socket support unimplemented * Other socket support unimplemented
@ -2114,6 +2319,10 @@ static uint8_t fam15h_cs_tristate_enable_code(struct DCTStatStruc *pDCTstat, uin
*/ */
} }
} }
} else if (package_type == PT_FM2) {
/* Socket FM2 */
/* UDIMM */
cs_tristate_code = 0x0;
} else { } else {
/* TODO /* TODO
* Other socket support unimplemented * Other socket support unimplemented
@ -4971,6 +5180,8 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat,
p = Tab_C32CLKDis; p = Tab_C32CLKDis;
else if (byte == PT_GR) else if (byte == PT_GR)
p = Tab_G34CLKDis; p = Tab_G34CLKDis;
else if (byte == PT_FM2)
p = Tab_FM2CLKDis;
else else
p = Tab_S1CLKDis; p = Tab_S1CLKDis;
@ -6527,20 +6738,23 @@ void mct_ForceNBPState0_En_Fam15(struct MCTStatStruc *pMCTstat,
dword |= ((dword & 0x3) << 3); dword |= ((dword & 0x3) << 3);
Set_NB32(pDCTstat->dev_nbctl, 0x170, dword); Set_NB32(pDCTstat->dev_nbctl, 0x170, dword);
/* Wait until CurNbPState == NbPstateLo */ if (!is_model10_1f()) {
do { /* Wait until CurNbPState == NbPstateLo */
dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174); do {
} while (((dword2 << 19) & 0x7) != (dword & 0x3)); dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174);
} while (((dword2 << 19) & 0x7) != (dword & 0x3));
}
dword = Get_NB32(pDCTstat->dev_nbctl, 0x170); dword = Get_NB32(pDCTstat->dev_nbctl, 0x170);
dword &= ~(0x3 << 6); /* NbPstateHi = 0 */ dword &= ~(0x3 << 6); /* NbPstateHi = 0 */
dword |= (0x3 << 14); /* SwNbPstateLoDis = 1 */ dword |= (0x3 << 14); /* SwNbPstateLoDis = 1 */
Set_NB32(pDCTstat->dev_nbctl, 0x170, dword); Set_NB32(pDCTstat->dev_nbctl, 0x170, dword);
/* Wait until CurNbPState == 0 */ if (!is_model10_1f()) {
do { /* Wait until CurNbPState == 0 */
dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174); do {
} while (((dword2 << 19) & 0x7) != 0); dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174);
} while (((dword2 << 19) & 0x7) != 0);
}
} }
} }
@ -7022,20 +7236,23 @@ static void InitPhyCompensation(struct MCTStatStruc *pMCTstat,
dword |= (0x8000 | tx_pre); dword |= (0x8000 | tx_pre);
Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2202, dword); Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2202, dword);
/* Be extra safe and wait for the predriver calibration to be applied if (!is_model10_1f()) {
* to the hardware. The BKDG does not require this, but it does take /* Be extra safe and wait for the predriver calibration
* some time for the data to propagate, so it's probably a good idea. * to be applied to the hardware. The BKDG does not
*/ * require this, but it does take some time for the
uint8_t predriver_cal_pending = 1; * data to propagate, so it's probably a good idea.
printk(BIOS_DEBUG, "Waiting for predriver calibration to be applied..."); */
while (predriver_cal_pending) { uint8_t predriver_cal_pending = 1;
predriver_cal_pending = 0; printk(BIOS_DEBUG, "Waiting for predriver calibration to be applied...");
for (index = 0; index < 0x9; index++) { while (predriver_cal_pending) {
if (Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0002 | (index << 8)) & 0x8000) predriver_cal_pending = 0;
predriver_cal_pending = 1; for (index = 0; index < 0x9; index++) {
if (Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0002 | (index << 8)) & 0x8000)
predriver_cal_pending = 1;
}
} }
printk(BIOS_DEBUG, "done!\n");
} }
printk(BIOS_DEBUG, "done!\n");
} else { } else {
dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00); dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00);
dword = 0; dword = 0;

View File

@ -31,6 +31,7 @@
#define PT_GR 3 #define PT_GR 3
#define PT_AS 4 #define PT_AS 4
#define PT_C3 5 #define PT_C3 5
#define PT_FM2 6
#define J_MIN 0 /* j loop constraint. 1=CL 2.0 T*/ #define J_MIN 0 /* j loop constraint. 1=CL 2.0 T*/
#define J_MAX 5 /* j loop constraint. 5=CL 7.0 T*/ #define J_MAX 5 /* j loop constraint. 5=CL 7.0 T*/

View File

@ -239,6 +239,19 @@ static uint8_t fam15_rttwr(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t d
term = 0x2; term = 0x2;
} }
} }
} else if (package_type == PT_FM2) {
/* Socket FM2: Fam15h Model10 BKDG 3.12 Table 32 */
if (MaxDimmsInstallable == 1) {
term = 0x0;
} else if (MaxDimmsInstallable == 2) {
if ((number_of_dimms == 2) && (frequency_index >= 0x12)) {
term = 0x1;
} else if (number_of_dimms == 1) {
term = 0x0;
} else {
term = 0x2;
}
}
} else { } else {
/* TODO /* TODO
* Other sockets unimplemented * Other sockets unimplemented
@ -606,6 +619,37 @@ static uint8_t fam15_rttnom(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t
} }
} }
} }
} else if (package_type == PT_FM2) {
/* Socket FM2: Fam15h Model10 BKDG 3.12 Table 32 */
if (MaxDimmsInstallable == 1) {
if ((frequency_index == 0x4)
|| (frequency_index == 0x6)
|| (frequency_index == 0xa))
term = 0x4;
else if (frequency_index == 0xe)
term = 0x3;
else if (frequency_index >= 0x12)
term = 0x2;
}
if (MaxDimmsInstallable == 2) {
if (number_of_dimms == 1) {
if (frequency_index <= 0xa) {
term = 0x4;
} else if (frequency_index <= 0xe) {
term = 0x3;
} else {
term = 0x2;
}
} else {
if (frequency_index <= 0xa) {
term = 0x2;
} else if (frequency_index <= 0xe) {
term = 0x1;
} else {
term = 0x0;
}
}
}
} else { } else {
/* TODO /* TODO
* Other sockets unimplemented * Other sockets unimplemented

View File

@ -225,6 +225,9 @@ static uint16_t fam15_receiver_enable_training_seed(struct DCTStatStruc *pDCTsta
} else if (package_type == PT_M2) { } else if (package_type == PT_M2) {
/* Socket AM3: Fam15h BKDG v3.14 Table 101 */ /* Socket AM3: Fam15h BKDG v3.14 Table 101 */
seed = 0x3a; seed = 0x3a;
} else if (package_type == PT_FM2) {
/* Socket FM2: Fam15h Model10 BKDG 3.12 Table 43 */
seed = 0x32;
} }
} }

View File

@ -1098,6 +1098,9 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
} else if (package_type == PT_M2) { } else if (package_type == PT_M2) {
/* Socket AM3: Fam15h BKDG v3.14 Table 98 */ /* Socket AM3: Fam15h BKDG v3.14 Table 98 */
Seed_Total = 0xf; Seed_Total = 0xf;
} else if (package_type == PT_FM2) {
/* Socket FM2: Fam15h M10 BKDG 3.12 Table 42 */
Seed_Total = 0x15;
} }
if (pDCTData->Status[DCT_STATUS_REGISTERED]) if (pDCTData->Status[DCT_STATUS_REGISTERED])
Seed_Total += ((AddrCmdPrelaunch)?0x10:0x0); Seed_Total += ((AddrCmdPrelaunch)?0x10:0x0);

View File

@ -59,6 +59,8 @@ static u16 mctGet_NVbits(u8 index)
val = 5; val = 5;
#elif CONFIG_CPU_SOCKET_TYPE == 0x15 /* G34 */ #elif CONFIG_CPU_SOCKET_TYPE == 0x15 /* G34 */
val = 3; val = 3;
#elif CONFIG_CPU_SOCKET_TYPE == 0x16 /* FM2 */
val = 6;
//#elif SYSTEM_TYPE == MOBILE //#elif SYSTEM_TYPE == MOBILE
// val = 2; // val = 2;
#endif #endif