diff options
Diffstat (limited to 'src/northbridge')
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 259 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mct_d.h | 1 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c | 44 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c | 3 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c | 3 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/wrappers/mcti_d.c | 2 |
6 files changed, 291 insertions, 21 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c index cbe75b60d4..4615dd2ed0 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c @@ -241,6 +241,9 @@ static const u8 Tab_C32CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0 /* G34: Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */ 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}; /* ========================================================================================== */ @@ -311,6 +314,21 @@ static uint16_t fam10h_mhz_to_memclk_config(uint16_t 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) { if (is_fam15h()) @@ -686,6 +704,19 @@ static uint32_t fam15h_phy_predriver_calibration_code(struct DCTStatStruc *pDCTs 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 { /* 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 { /* TODO * 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 { /* TODO * 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 { /* TODO * 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 { /* TODO * 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 { /* TODO * Other socket support unimplemented @@ -4971,6 +5180,8 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat, p = Tab_C32CLKDis; else if (byte == PT_GR) p = Tab_G34CLKDis; + else if (byte == PT_FM2) + p = Tab_FM2CLKDis; else p = Tab_S1CLKDis; @@ -6527,20 +6738,23 @@ void mct_ForceNBPState0_En_Fam15(struct MCTStatStruc *pMCTstat, dword |= ((dword & 0x3) << 3); Set_NB32(pDCTstat->dev_nbctl, 0x170, dword); - /* Wait until CurNbPState == NbPstateLo */ - do { - dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174); - } while (((dword2 << 19) & 0x7) != (dword & 0x3)); - + if (!is_model10_1f()) { + /* Wait until CurNbPState == NbPstateLo */ + do { + dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174); + } while (((dword2 << 19) & 0x7) != (dword & 0x3)); + } dword = Get_NB32(pDCTstat->dev_nbctl, 0x170); dword &= ~(0x3 << 6); /* NbPstateHi = 0 */ dword |= (0x3 << 14); /* SwNbPstateLoDis = 1 */ Set_NB32(pDCTstat->dev_nbctl, 0x170, dword); - /* Wait until CurNbPState == 0 */ - do { - dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174); - } while (((dword2 << 19) & 0x7) != 0); + if (!is_model10_1f()) { + /* Wait until CurNbPState == 0 */ + do { + 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); Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2202, dword); - /* Be extra safe and wait for the predriver calibration to be applied - * to the hardware. The BKDG does not require this, but it does take - * some time for the data to propagate, so it's probably a good idea. - */ - uint8_t predriver_cal_pending = 1; - printk(BIOS_DEBUG, "Waiting for predriver calibration to be applied..."); - while (predriver_cal_pending) { - predriver_cal_pending = 0; - for (index = 0; index < 0x9; index++) { - if (Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0002 | (index << 8)) & 0x8000) - predriver_cal_pending = 1; + if (!is_model10_1f()) { + /* Be extra safe and wait for the predriver calibration + * to be applied to the hardware. The BKDG does not + * require this, but it does take some time for the + * data to propagate, so it's probably a good idea. + */ + uint8_t predriver_cal_pending = 1; + printk(BIOS_DEBUG, "Waiting for predriver calibration to be applied..."); + while (predriver_cal_pending) { + predriver_cal_pending = 0; + 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 { dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00); dword = 0; diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h index 91843d05be..654acc0b32 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h @@ -31,6 +31,7 @@ #define PT_GR 3 #define PT_AS 4 #define PT_C3 5 +#define PT_FM2 6 #define J_MIN 0 /* j loop constraint. 1=CL 2.0 T*/ #define J_MAX 5 /* j loop constraint. 5=CL 7.0 T*/ diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c index d8da16b4fe..670d640a6c 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c @@ -239,6 +239,19 @@ static uint8_t fam15_rttwr(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t d 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 { /* TODO * 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 { /* TODO * Other sockets unimplemented diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c index d316d27ea4..b8d89fe675 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c @@ -225,6 +225,9 @@ static uint16_t fam15_receiver_enable_training_seed(struct DCTStatStruc *pDCTsta } else if (package_type == PT_M2) { /* Socket AM3: Fam15h BKDG v3.14 Table 101 */ seed = 0x3a; + } else if (package_type == PT_FM2) { + /* Socket FM2: Fam15h Model10 BKDG 3.12 Table 43 */ + seed = 0x32; } } diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c index f5bf9e3e6c..2b8a997b0c 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c @@ -1098,6 +1098,9 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui } else if (package_type == PT_M2) { /* Socket AM3: Fam15h BKDG v3.14 Table 98 */ 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]) Seed_Total += ((AddrCmdPrelaunch)?0x10:0x0); diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c b/src/northbridge/amd/amdmct/wrappers/mcti_d.c index dc4186e86e..12115c5aaf 100644 --- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c +++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c @@ -59,6 +59,8 @@ static u16 mctGet_NVbits(u8 index) val = 5; #elif CONFIG_CPU_SOCKET_TYPE == 0x15 /* G34 */ val = 3; +#elif CONFIG_CPU_SOCKET_TYPE == 0x16 /* FM2 */ + val = 6; //#elif SYSTEM_TYPE == MOBILE // val = 2; #endif |