summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mct_d.c259
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mct_d.h1
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c44
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c3
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c3
-rw-r--r--src/northbridge/amd/amdmct/wrappers/mcti_d.c2
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