summaryrefslogtreecommitdiffstats
path: root/resources/libreboot/patch/kgpe-d16/0045-amd-amdmct-mct_ddr3-Use-training-values-from-previou.patch
diff options
context:
space:
mode:
authorFrancis Rowe <info@gluglug.org.uk>2015-10-18 19:12:53 (EDT)
committer Francis Rowe <info@gluglug.org.uk>2015-10-18 21:32:36 (EDT)
commit0622df6194dbb1b2120743c0fd1cc5e72c380128 (patch)
tree4c858b8c5667fe001a9907ae0578b4ec28a8f513 /resources/libreboot/patch/kgpe-d16/0045-amd-amdmct-mct_ddr3-Use-training-values-from-previou.patch
parent5999dba5f71f1c05040a551d2420ab8c7f3a9da4 (diff)
downloadlibreboot-0622df6194dbb1b2120743c0fd1cc5e72c380128.zip
libreboot-0622df6194dbb1b2120743c0fd1cc5e72c380128.tar.gz
libreboot-0622df6194dbb1b2120743c0fd1cc5e72c380128.tar.bz2
KGPE-D16: update patch set (also update coreboot and vboot)
Also contains other fixes from coreboot, like: * 551cff0 Derive lvds_dual_channel from EDID timings. ^ makes single/dual channel LVDS selection on GM45 automatic * 26fc544 lenovo/t60: Enable native intel gfx init. ^ was being maintained in libreboot, now upstreamed so not needed Framebuffer mode was disabled for the KGPE-D16, because only text-mode works at the moment.
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0045-amd-amdmct-mct_ddr3-Use-training-values-from-previou.patch')
-rw-r--r--resources/libreboot/patch/kgpe-d16/0045-amd-amdmct-mct_ddr3-Use-training-values-from-previou.patch769
1 files changed, 0 insertions, 769 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0045-amd-amdmct-mct_ddr3-Use-training-values-from-previou.patch b/resources/libreboot/patch/kgpe-d16/0045-amd-amdmct-mct_ddr3-Use-training-values-from-previou.patch
deleted file mode 100644
index 52ba598..0000000
--- a/resources/libreboot/patch/kgpe-d16/0045-amd-amdmct-mct_ddr3-Use-training-values-from-previou.patch
+++ /dev/null
@@ -1,769 +0,0 @@
-From 9874b958db2c994d3827af323bd6ab4c7306da23 Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <kb9vqf@pearsoncomputing.net>
-Date: Thu, 4 Jun 2015 00:11:03 -0500
-Subject: [PATCH 045/146] amd/amdmct/mct_ddr3: Use training values from
- previous boot if possible
-
-DRAM training accounts for most of the romstage startup time, yet
-if the hardware configuration has not changed from the previous boot
-the previously discovered training values are still valid. Use them
-if the DIMM configuration has not changed since the last boot.
----
- src/mainboard/asus/kgpe-d16/cmos.layout | 1 +
- src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 202 ++++++++++++++++---------
- src/northbridge/amd/amdmct/mct_ddr3/mct_d.h | 6 +
- src/northbridge/amd/amdmct/mct_ddr3/s3utils.c | 173 ++++++++++++++++++---
- src/northbridge/amd/amdmct/mct_ddr3/s3utils.h | 10 +-
- src/northbridge/amd/amdmct/wrappers/mcti_d.c | 10 --
- 6 files changed, 299 insertions(+), 103 deletions(-)
-
-diff --git a/src/mainboard/asus/kgpe-d16/cmos.layout b/src/mainboard/asus/kgpe-d16/cmos.layout
-index e55edc4..7944631 100644
---- a/src/mainboard/asus/kgpe-d16/cmos.layout
-+++ b/src/mainboard/asus/kgpe-d16/cmos.layout
-@@ -43,6 +43,7 @@ entries
- 458 4 e 11 hypertransport_speed_limit
- 462 2 e 12 minimum_memory_voltage
- 464 1 e 2 compute_unit_siblings
-+465 1 r 0 allow_spd_nvram_cache_restore
- 477 1 e 1 ieee1394
- 728 256 h 0 user_data
- 984 16 h 0 check_sum
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
-index 771d743..779d9ad 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
-@@ -39,7 +39,8 @@
- static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstatA);
- static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
-- struct DCTStatStruc *pDCTstatA);
-+ struct DCTStatStruc *pDCTstatA,
-+ uint8_t allow_config_restore);
- static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstatA);
- static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat,
-@@ -355,8 +356,7 @@ static uint32_t fam15h_phy_predriver_calibration_code(struct DCTStatStruc *pDCTs
- else if (drive_strength == 0x3)
- calibration_code = 0xfff;
- }
-- }
-- else if (ddr_voltage_index & 0x2) {
-+ } else if (ddr_voltage_index & 0x2) {
- /* 1.35V */
- /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 42 */
- if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-@@ -390,8 +390,7 @@ static uint32_t fam15h_phy_predriver_calibration_code(struct DCTStatStruc *pDCTs
- else if (drive_strength == 0x3)
- calibration_code = 0xdb6;
- }
-- }
-- else if (ddr_voltage_index & 0x1) {
-+ } else if (ddr_voltage_index & 0x1) {
- /* 1.5V */
- /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 41 */
- if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-@@ -426,8 +425,7 @@ static uint32_t fam15h_phy_predriver_calibration_code(struct DCTStatStruc *pDCTs
- calibration_code = 0xb6d;
- }
- }
-- }
-- else if (package_type == PT_C3) {
-+ } else if (package_type == PT_C3) {
- /* Socket C32 */
- if (ddr_voltage_index & 0x4) {
- /* 1.25V */
-@@ -473,8 +471,7 @@ static uint32_t fam15h_phy_predriver_calibration_code(struct DCTStatStruc *pDCTs
- else if (drive_strength == 0x3)
- calibration_code = 0xfff;
- }
-- }
-- else if (ddr_voltage_index & 0x2) {
-+ } else if (ddr_voltage_index & 0x2) {
- /* 1.35V */
- /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 45 */
- if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-@@ -518,8 +515,7 @@ static uint32_t fam15h_phy_predriver_calibration_code(struct DCTStatStruc *pDCTs
- else if (drive_strength == 0x3)
- calibration_code = 0xdb6;
- }
-- }
-- else if (ddr_voltage_index & 0x1) {
-+ } else if (ddr_voltage_index & 0x1) {
- /* 1.5V */
- /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 44 */
- if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-@@ -619,8 +615,7 @@ static uint32_t fam15h_phy_predriver_cmd_addr_calibration_code(struct DCTStatStr
- else if (drive_strength == 0x3)
- calibration_code = 0xb64;
- }
-- }
-- else if (ddr_voltage_index & 0x2) {
-+ } else if (ddr_voltage_index & 0x2) {
- /* 1.35V */
- /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 51 */
- if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-@@ -654,8 +649,7 @@ static uint32_t fam15h_phy_predriver_cmd_addr_calibration_code(struct DCTStatStr
- else if (drive_strength == 0x3)
- calibration_code = 0x924;
- }
-- }
-- else if (ddr_voltage_index & 0x1) {
-+ } else if (ddr_voltage_index & 0x1) {
- /* 1.5V */
- /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 50 */
- if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-@@ -736,8 +730,7 @@ static uint32_t fam15h_phy_predriver_clk_calibration_code(struct DCTStatStruc *p
- else if (drive_strength == 0x3)
- calibration_code = 0xff6;
- }
-- }
-- else if (ddr_voltage_index & 0x2) {
-+ } else if (ddr_voltage_index & 0x2) {
- /* 1.35V */
- /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 54 */
- if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-@@ -771,8 +764,7 @@ static uint32_t fam15h_phy_predriver_clk_calibration_code(struct DCTStatStruc *p
- else if (drive_strength == 0x3)
- calibration_code = 0xdad;
- }
-- }
-- else if (ddr_voltage_index & 0x1) {
-+ } else if (ddr_voltage_index & 0x1) {
- /* 1.5V */
- /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 53 */
- if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
-@@ -841,16 +833,13 @@ static uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCT
- else if (MemClkFreq == 0x6) {
- /* DDR3-800 */
- calibration_code = 0x10112222;
-- }
-- else if (MemClkFreq == 0xa) {
-+ } else if (MemClkFreq == 0xa) {
- /* DDR3-1066 */
- calibration_code = 0x20112222;
-- }
-- else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) {
-+ } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) {
- /* DDR3-1333 - DDR3-1600 */
- calibration_code = 0x30112222;
-- }
-- else if (MemClkFreq == 0x16) {
-+ } else if (MemClkFreq == 0x16) {
- /* DDR3-1866 */
- calibration_code = 0x30332222;
- }
-@@ -860,16 +849,13 @@ static uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCT
- if (MemClkFreq == 0x4) {
- /* DDR3-667 */
- calibration_code = 0x00112222;
-- }
-- else if (MemClkFreq == 0x6) {
-+ } else if (MemClkFreq == 0x6) {
- /* DDR3-800 */
- calibration_code = 0x10112222;
-- }
-- else if (MemClkFreq == 0xa) {
-+ } else if (MemClkFreq == 0xa) {
- /* DDR3-1066 */
- calibration_code = 0x20112222;
-- }
-- else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) {
-+ } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) {
- /* DDR3-1333 - DDR3-1600 */
- calibration_code = 0x30112222;
- }
-@@ -881,20 +867,16 @@ static uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCT
- if (MemClkFreq == 0x4) {
- /* DDR3-667 */
- calibration_code = 0x10222222;
-- }
-- else if (MemClkFreq == 0x6) {
-+ } else if (MemClkFreq == 0x6) {
- /* DDR3-800 */
- calibration_code = 0x20222222;
-- }
-- else if (MemClkFreq == 0xa) {
-+ } else if (MemClkFreq == 0xa) {
- /* DDR3-1066 */
- calibration_code = 0x30222222;
-- }
-- else if (MemClkFreq == 0xe) {
-+ } else if (MemClkFreq == 0xe) {
- /* DDR3-1333 */
- calibration_code = 0x30222222;
-- }
-- else if (MemClkFreq == 0x12) {
-+ } else if (MemClkFreq == 0x12) {
- /* DDR3-1600 */
- if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1))
- calibration_code = 0x30222222;
-@@ -1081,8 +1063,7 @@ static uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dc
- || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) {
- /* DDR3-667 - DDR3-1333 */
- slow_access = 0;
-- }
-- else if (MemClkFreq == 0x12) {
-+ } else if (MemClkFreq == 0x12) {
- /* DDR3-1600 */
- if (rank_count_dimm0 == 1)
- slow_access = 0;
-@@ -1098,8 +1079,7 @@ static uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dc
- || (MemClkFreq == 0xa)) {
- /* DDR3-667 - DDR3-1066 */
- slow_access = 0;
-- }
-- else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) {
-+ } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) {
- /* DDR3-1333 - DDR3-1600 */
- slow_access = 1;
- }
-@@ -1184,6 +1164,28 @@ static void read_spd_bytes(struct MCTStatStruc *pMCTstat,
- }
- }
-
-+static void calculate_and_store_spd_hashes(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat)
-+{
-+ uint8_t dimm;
-+
-+ for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) {
-+ calculate_spd_hash(pDCTstat->spd_data.spd_bytes[dimm], &pDCTstat->spd_data.spd_hash[dimm]);
-+ }
-+}
-+
-+static void compare_nvram_spd_hashes(struct MCTStatStruc *pMCTstat,
-+ struct DCTStatStruc *pDCTstat)
-+{
-+ uint8_t dimm;
-+
-+ pDCTstat->spd_data.nvram_spd_match = 1;
-+ for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) {
-+ if (pDCTstat->spd_data.spd_hash[dimm] != pDCTstat->spd_data.nvram_spd_hash[dimm])
-+ pDCTstat->spd_data.nvram_spd_match = 0;
-+ }
-+}
-+
- static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstatA)
- {
-@@ -1232,6 +1234,8 @@ static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat,
- */
- u8 Node, NodesWmem;
- u32 node_sys_base;
-+ uint8_t nvram;
-+ uint8_t allow_config_restore;
-
- uint8_t s3resume = acpi_is_wakeup_s3();
-
-@@ -1247,7 +1251,7 @@ restartinit:
- }
-
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: Restoring DCT configuration from NVRAM\n");
-- restore_mct_information_from_nvram();
-+ restore_mct_information_from_nvram(0);
-
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_Dis_Fam15\n");
- for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-@@ -1296,9 +1300,24 @@ restartinit:
- node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F;
- }
-
-+ /* If the boot fails make sure training is attempted after reset */
-+ nvram = 0;
-+ set_option("allow_spd_nvram_cache_restore", &nvram);
-+
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: DIMMSetVoltage\n");
- DIMMSetVoltages(pMCTstat, pDCTstatA); /* Set the DIMM voltages (mainboard specific) */
-
-+ /* If DIMM configuration has not changed since last boot restore training values */
-+ allow_config_restore = 1;
-+ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-+ struct DCTStatStruc *pDCTstat;
-+ pDCTstat = pDCTstatA + Node;
-+
-+ if (pDCTstat->NodePresent)
-+ if (!pDCTstat->spd_data.nvram_spd_match)
-+ allow_config_restore = 0;
-+ }
-+
- for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
- struct DCTStatStruc *pDCTstat;
- pDCTstat = pDCTstatA + Node;
-@@ -1332,14 +1351,33 @@ restartinit:
- CPUMemTyping_D(pMCTstat, pDCTstatA); /* Map dram into WB/UC CPU cacheability */
- mctHookAfterCPU(); /* Setup external northbridge(s) */
-
-+ /* FIXME
-+ * Previous training values should only be used if the current desired
-+ * speed is the same as the speed used in the previous boot.
-+ * How to get the desired speed at this point in the code?
-+ */
-+#if 0
-+ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-+ struct DCTStatStruc *pDCTstat;
-+ pDCTstat = pDCTstatA + Node;
-+
-+ if (pDCTstat->NodePresent) {
-+ if (pDCTstat->spd_data.nvram_memclk[0] != pDCTstat->DIMMAutoSpeed)
-+ allow_config_restore = 0;
-+ }
-+ }
-+#endif
-+
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: DQSTiming_D\n");
-- DQSTiming_D(pMCTstat, pDCTstatA); /* Get Receiver Enable and DQS signal timing*/
-+ DQSTiming_D(pMCTstat, pDCTstatA, allow_config_restore); /* Get Receiver Enable and DQS signal timing*/
-
- printk(BIOS_DEBUG, "mctAutoInitMCT_D: UMAMemTyping_D\n");
- UMAMemTyping_D(pMCTstat, pDCTstatA); /* Fix up for UMA sizing */
-
-- printk(BIOS_DEBUG, "mctAutoInitMCT_D: :OtherTiming\n");
-- mct_OtherTiming(pMCTstat, pDCTstatA);
-+ if (!allow_config_restore) {
-+ printk(BIOS_DEBUG, "mctAutoInitMCT_D: :OtherTiming\n");
-+ mct_OtherTiming(pMCTstat, pDCTstatA);
-+ }
-
- if (ReconfigureDIMMspare_D(pMCTstat, pDCTstatA)) { /* RESET# if 1st pass of DIMM spare enabled*/
- goto restartinit;
-@@ -1822,7 +1860,7 @@ static void exit_training_mode_fam15(struct MCTStatStruc *pMCTstat,
- }
-
- static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
-- struct DCTStatStruc *pDCTstatA)
-+ struct DCTStatStruc *pDCTstatA, uint8_t allow_config_restore)
- {
- u8 nv_DQSTrainCTL;
-
-@@ -1830,9 +1868,8 @@ static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
- return;
- }
-
-- nv_DQSTrainCTL = mctGet_NVbits(NV_DQSTrainCTL);
-- /* FIXME: BOZO- DQS training every time*/
-- nv_DQSTrainCTL = 1;
-+ // nv_DQSTrainCTL = mctGet_NVbits(NV_DQSTrainCTL);
-+ nv_DQSTrainCTL = !allow_config_restore;
-
- mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA);
- phyAssistedMemFnceTraining(pMCTstat, pDCTstatA);
-@@ -1851,15 +1888,16 @@ static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
- }
- }
-
-+ mctHookBeforeAnyTraining(pMCTstat, pDCTstatA);
-+ if (!is_fam15h()) {
-+ /* TODO: should be in mctHookBeforeAnyTraining */
-+ _WRMSR(0x26C, 0x04040404, 0x04040404);
-+ _WRMSR(0x26D, 0x04040404, 0x04040404);
-+ _WRMSR(0x26E, 0x04040404, 0x04040404);
-+ _WRMSR(0x26F, 0x04040404, 0x04040404);
-+ }
-+
- if (nv_DQSTrainCTL) {
-- mctHookBeforeAnyTraining(pMCTstat, pDCTstatA);
-- if (!is_fam15h()) {
-- /* TODO: should be in mctHookBeforeAnyTraining */
-- _WRMSR(0x26C, 0x04040404, 0x04040404);
-- _WRMSR(0x26D, 0x04040404, 0x04040404);
-- _WRMSR(0x26E, 0x04040404, 0x04040404);
-- _WRMSR(0x26F, 0x04040404, 0x04040404);
-- }
- mct_WriteLevelization_HW(pMCTstat, pDCTstatA, FirstPass);
-
- if (is_fam15h()) {
-@@ -1889,18 +1927,23 @@ static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
- exit_training_mode_fam15(pMCTstat, pDCTstatA);
- else
- mctSetEccDQSRcvrEn_D(pMCTstat, pDCTstatA);
-+ } else {
-+ mct_WriteLevelization_HW(pMCTstat, pDCTstatA, FirstPass);
-
-- /* FIXME - currently uses calculated value TrainMaxReadLatency_D(pMCTstat, pDCTstatA); */
-- mctHookAfterAnyTraining();
-- mctSaveDQSSigTmg_D();
-+ mct_WriteLevelization_HW(pMCTstat, pDCTstatA, SecondPass);
-
-- MCTMemClr_D(pMCTstat, pDCTstatA);
-- } else {
-- mctGetDQSSigTmg_D(); /* get values into data structure */
-- LoadDQSSigTmgRegs_D(pMCTstat, pDCTstatA); /* load values into registers.*/
-- /* mctDoWarmResetMemClr_D(); */
-- MCTMemClr_D(pMCTstat, pDCTstatA);
-+ printk(BIOS_DEBUG, "mctAutoInitMCT_D: Restoring DIMM training configuration from NVRAM\n");
-+ restore_mct_information_from_nvram(1);
-+
-+ if (is_fam15h())
-+ exit_training_mode_fam15(pMCTstat, pDCTstatA);
- }
-+
-+ /* FIXME - currently uses calculated value TrainMaxReadLatency_D(pMCTstat, pDCTstatA); */
-+ mctHookAfterAnyTraining();
-+
-+ /* mctDoWarmResetMemClr_D(); */
-+ MCTMemClr_D(pMCTstat, pDCTstatA);
- }
-
- static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
-@@ -3910,6 +3953,8 @@ static void mct_preInitDCT(struct MCTStatStruc *pMCTstat,
- struct DCTStatStruc *pDCTstat)
- {
- u8 err_code;
-+ uint8_t nvram;
-+ uint8_t allow_config_restore;
-
- /* Preconfigure DCT0 */
- DCTPreInit_D(pMCTstat, pDCTstat, 0);
-@@ -3924,6 +3969,27 @@ static void mct_preInitDCT(struct MCTStatStruc *pMCTstat,
- pDCTstat->ErrCode = err_code; /* Using DCT0 Error code to update pDCTstat.ErrCode */
- }
- }
-+
-+ calculate_and_store_spd_hashes(pMCTstat, pDCTstat);
-+
-+#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
-+ if (load_spd_hashes_from_nvram(pDCTstat) < 0) {
-+ pDCTstat->spd_data.nvram_spd_match = 0;
-+ }
-+ else {
-+ compare_nvram_spd_hashes(pMCTstat, pDCTstat);
-+ }
-+#else
-+ pDCTstat->spd_data.nvram_spd_match = 0;
-+#endif
-+
-+ /* Check to see if restoration of SPD data from NVRAM is allowed */
-+ allow_config_restore = 0;
-+ if (get_option(&nvram, "allow_spd_nvram_cache_restore") == CB_SUCCESS)
-+ allow_config_restore = !!nvram;
-+
-+ if (!allow_config_restore)
-+ pDCTstat->spd_data.nvram_spd_match = 0;
- }
-
- static void mct_initDCT(struct MCTStatStruc *pMCTstat,
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
-index 5bb09b4..539ecc3 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
-@@ -325,6 +325,10 @@ struct MCTStatStruc {
- struct amd_spd_node_data {
- uint8_t spd_bytes[MAX_DIMMS_SUPPORTED][256]; /* [DIMM][byte] */
- uint8_t spd_address[MAX_DIMMS_SUPPORTED]; /* [DIMM] */
-+ uint64_t spd_hash[MAX_DIMMS_SUPPORTED]; /* [DIMM] */
-+ uint64_t nvram_spd_hash[MAX_DIMMS_SUPPORTED]; /* [DIMM] */
-+ uint8_t nvram_spd_match;
-+ uint8_t nvram_memclk[2]; /* [channel] */
- } __attribute__((packed));
-
- struct DCTStatStruc { /* A per Node structure*/
-@@ -784,6 +788,8 @@ struct amd_s3_persistent_mct_channel_data {
-
- struct amd_s3_persistent_node_data {
- uint32_t node_present;
-+ uint64_t spd_hash[MAX_DIMMS_SUPPORTED];
-+ uint8_t memclk[2];
- struct amd_s3_persistent_mct_channel_data channel[2];
- } __attribute__((packed));
-
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c
-index aa23951..5cdeeb0 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c
-@@ -26,8 +26,10 @@
- #include <device/pci_ops.h>
- #include <console/console.h>
- #include <cbfs.h>
-+#include <cbmem.h>
- #include <spi-generic.h>
- #include <spi_flash.h>
-+#include <pc80/mc146818rtc.h>
-
- #include "s3utils.h"
-
-@@ -124,6 +126,68 @@ static uint32_t read_amd_dct_index_register_dct(device_t dev, uint8_t node, uint
- return read_amd_dct_index_register(dev, index_ctl_reg, index);
- }
-
-+/* Non-cryptographic 64-bit hash function taken from Stack Overflow:
-+ * http://stackoverflow.com/a/13326345
-+ * Any 64-bit hash with sufficiently low collision potential
-+ * could be used instead.
-+ */
-+void calculate_spd_hash(uint8_t *spd_data, uint64_t *spd_hash)
-+{
-+ const unsigned long long prime = 2654435789ULL;
-+ uint16_t byte;
-+ *spd_hash = 104395301;
-+
-+ for (byte = 0; byte < 256; byte++)
-+ *spd_hash += (spd_data[byte] * prime) ^ (*spd_hash >> 23);
-+
-+ *spd_hash = *spd_hash ^ (*spd_hash << 37);
-+}
-+
-+static struct amd_s3_persistent_data * map_s3nv_in_nvram(void)
-+{
-+ ssize_t s3nv_offset;
-+ ssize_t s3nv_file_offset;
-+ void * s3nv_cbfs_file_ptr;
-+ struct amd_s3_persistent_data *persistent_data;
-+
-+ /* Obtain CBFS file offset */
-+ s3nv_offset = get_s3nv_file_offset();
-+ if (s3nv_offset == -1)
-+ return NULL;
-+
-+ /* Align flash pointer to nearest boundary */
-+ s3nv_file_offset = s3nv_offset;
-+ s3nv_offset &= ~(CONFIG_S3_DATA_SIZE-1);
-+ s3nv_offset += CONFIG_S3_DATA_SIZE;
-+ s3nv_file_offset = s3nv_offset - s3nv_file_offset;
-+
-+ /* Map data structure in CBFS and restore settings */
-+ s3nv_cbfs_file_ptr = cbfs_boot_map_with_leak(S3NV_FILE_NAME, CBFS_TYPE_RAW, NULL);
-+ if (!s3nv_cbfs_file_ptr) {
-+ printk(BIOS_DEBUG, "S3 state file could not be mapped: %s\n", S3NV_FILE_NAME);
-+ return NULL;
-+ }
-+ persistent_data = (s3nv_cbfs_file_ptr + s3nv_file_offset);
-+
-+ return persistent_data;
-+}
-+
-+#ifdef __PRE_RAM__
-+int8_t load_spd_hashes_from_nvram(struct DCTStatStruc *pDCTstat)
-+{
-+ struct amd_s3_persistent_data *persistent_data;
-+
-+ persistent_data = map_s3nv_in_nvram();
-+ if (!persistent_data)
-+ return -1;
-+
-+ memcpy(pDCTstat->spd_data.nvram_spd_hash, persistent_data->node[pDCTstat->Node_ID].spd_hash, sizeof(pDCTstat->spd_data.nvram_spd_hash));
-+ memcpy(pDCTstat->spd_data.nvram_memclk, persistent_data->node[pDCTstat->Node_ID].memclk, sizeof(pDCTstat->spd_data.nvram_memclk));
-+
-+ return 0;
-+}
-+#endif
-+
- #ifdef __RAMSTAGE__
- static uint64_t rdmsr_uint64_t(unsigned long index) {
- msr_t msr = rdmsr(index);
-@@ -149,6 +213,31 @@ static uint32_t read_config32_dct_nbpstate(device_t dev, uint8_t node, uint8_t d
- return pci_read_config32(dev, reg);
- }
-
-+static void copy_cbmem_spd_data_to_save_variable(struct amd_s3_persistent_data* persistent_data)
-+{
-+ uint8_t node;
-+ uint8_t dimm;
-+ uint8_t channel;
-+ struct amdmct_memory_info *mem_info;
-+ mem_info = cbmem_find(CBMEM_ID_AMDMCT_MEMINFO);
-+ if (mem_info == NULL) {
-+ /* can't find amdmct information in cbmem */
-+ for (node = 0; node < MAX_NODES_SUPPORTED; node++)
-+ for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++)
-+ persistent_data->node[node].spd_hash[dimm] = 0xffffffffffffffffULL;
-+
-+ return;
-+ }
-+
-+ for (node = 0; node < MAX_NODES_SUPPORTED; node++)
-+ for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++)
-+ calculate_spd_hash(mem_info->dct_stat[node].spd_data.spd_bytes[dimm], &persistent_data->node[node].spd_hash[dimm]);
-+
-+ for (node = 0; node < MAX_NODES_SUPPORTED; node++)
-+ for (channel = 0; channel < 2; channel++)
-+ persistent_data->node[node].memclk[channel] = mem_info->dct_stat[node].Speed;
-+}
-+
- void copy_mct_data_to_save_variable(struct amd_s3_persistent_data* persistent_data)
- {
- uint8_t i;
-@@ -441,7 +530,7 @@ static void wrmsr_uint64_t(unsigned long index, uint64_t value) {
- wrmsr(index, msr);
- }
-
--void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persistent_data)
-+void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persistent_data, uint8_t training_only)
- {
- uint8_t i;
- uint8_t j;
-@@ -451,6 +540,51 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- uint8_t dct_enabled;
- uint32_t dword;
-
-+ if (training_only) {
-+ /* Only restore the Receiver Enable and DQS training registers */
-+ for (node = 0; node < MAX_NODES_SUPPORTED; node++) {
-+ for (channel = 0; channel < 2; channel++) {
-+ struct amd_s3_persistent_mct_channel_data* data = &persistent_data->node[node].channel[channel];
-+ if (!persistent_data->node[node].node_present)
-+ continue;
-+
-+ /* Restore training parameters */
-+ for (i=0; i<4; i++)
-+ for (j=0; j<3; j++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, (0x01 + i) + (0x100 * j), data->f2x9cx3_0_0_3_1[i][j]);
-+ for (i=0; i<4; i++)
-+ for (j=0; j<3; j++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, (0x05 + i) + (0x100 * j), data->f2x9cx3_0_0_7_5[i][j]);
-+
-+ for (i=0; i<12; i++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x10 + i, data->f2x9cx10[i]);
-+ for (i=0; i<12; i++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x20 + i, data->f2x9cx20[i]);
-+
-+ if (IS_ENABLED(CONFIG_DIMM_DDR3)) {
-+ for (i=0; i<12; i++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x30 + i, data->f2x9cx30[i]);
-+ for (i=0; i<12; i++)
-+ write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x40 + i, data->f2x9cx40[i]);
-+ }
-+
-+ /* Restore MaxRdLatency */
-+ if (is_fam15h()) {
-+ for (i=0; i<4; i++)
-+ write_config32_dct_nbpstate(PCI_DEV(0, 0x18 + node, 2), node, channel, i, 0x210, data->f2x210[i]);
-+ }
-+ else {
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x78, data->f2x78);
-+ }
-+
-+ /* Other timing control registers */
-+ write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x8c, data->f2x8c);
-+ }
-+ }
-+
-+ return;
-+ }
-+
- /* Load data from data structure into DCTs */
- /* Stage 1 */
- for (node = 0; node < MAX_NODES_SUPPORTED; node++) {
-@@ -501,7 +635,8 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- wrmsr_uint64_t(0x00000250, data->msr00000250);
- wrmsr_uint64_t(0x00000258, data->msr00000258);
- /* FIXME
-- * Restoring these MSRs causes a hang on resume
-+ * Restoring these MSRs causes a hang on resume due to
-+ * destroying CAR while still executing from CAR!
- * For now, skip restoration...
- */
- // for (i=0; i<8; i++)
-@@ -890,6 +1025,8 @@ void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persiste
- #ifdef __RAMSTAGE__
- int8_t save_mct_information_to_nvram(void)
- {
-+ uint8_t nvram;
-+
- if (acpi_is_wakeup_s3())
- return 0;
-
-@@ -909,6 +1046,9 @@ int8_t save_mct_information_to_nvram(void)
- /* Obtain MCT configuration data */
- copy_mct_data_to_save_variable(persistent_data);
-
-+ /* Save RAM SPD data at the same time */
-+ copy_cbmem_spd_data_to_save_variable(persistent_data);
-+
- /* Obtain CBFS file offset */
- s3nv_offset = get_s3nv_file_offset();
- if (s3nv_offset == -1)
-@@ -949,36 +1089,23 @@ int8_t save_mct_information_to_nvram(void)
- /* Restore SPI MMIO address */
- pci_write_config32(lpc_dev, 0xa0, spi_mmio_prev);
-
-+ /* Allow training bypass if DIMM configuration is unchanged on next boot */
-+ nvram = 1;
-+ set_option("allow_spd_nvram_cache_restore", &nvram);
-+
- return 0;
- }
- #endif
-
--int8_t restore_mct_information_from_nvram(void)
-+int8_t restore_mct_information_from_nvram(uint8_t training_only)
- {
-- ssize_t s3nv_offset;
-- ssize_t s3nv_file_offset;
-- void * s3nv_cbfs_file_ptr;
- struct amd_s3_persistent_data *persistent_data;
-
-- /* Obtain CBFS file offset */
-- s3nv_offset = get_s3nv_file_offset();
-- if (s3nv_offset == -1)
-+ persistent_data = map_s3nv_in_nvram();
-+ if (!persistent_data)
- return -1;
-
-- /* Align flash pointer to nearest boundary */
-- s3nv_file_offset = s3nv_offset;
-- s3nv_offset &= ~(CONFIG_S3_DATA_SIZE-1);
-- s3nv_offset += CONFIG_S3_DATA_SIZE;
-- s3nv_file_offset = s3nv_offset - s3nv_file_offset;
--
-- /* Map data structure in CBFS and restore settings */
-- s3nv_cbfs_file_ptr = cbfs_boot_map_with_leak(S3NV_FILE_NAME, CBFS_TYPE_RAW, NULL);
-- if (!s3nv_cbfs_file_ptr) {
-- printk(BIOS_DEBUG, "S3 state file could not be mapped: %s\n", S3NV_FILE_NAME);
-- return -1;
-- }
-- persistent_data = (s3nv_cbfs_file_ptr + s3nv_file_offset);
-- restore_mct_data_from_save_variable(persistent_data);
-+ restore_mct_data_from_save_variable(persistent_data, training_only);
-
- return 0;
- }
-\ No newline at end of file
-diff --git a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h
-index dcddcad..82f73a7 100644
---- a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h
-+++ b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h
-@@ -20,9 +20,15 @@
- #include "../wrappers/mcti.h"
- #include "mct_d.h"
-
-+void calculate_spd_hash(uint8_t *spd_data, uint64_t *spd_hash);
-+
-+#ifdef __PRE_RAM__
-+int8_t load_spd_hashes_from_nvram(struct DCTStatStruc *pDCTstat);
-+#endif
-+
- #ifdef __RAMSTAGE__
- int8_t save_mct_information_to_nvram(void);
- #endif
--int8_t restore_mct_information_from_nvram(void);
-+int8_t restore_mct_information_from_nvram(uint8_t training_only);
- void copy_mct_data_to_save_variable(struct amd_s3_persistent_data* persistent_data);
--void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persistent_data);
-\ No newline at end of file
-+void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persistent_data, uint8_t training_only);
-\ No newline at end of file
-diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-index 1d4eade..2e53f0b 100644
---- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-+++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
-@@ -399,16 +399,6 @@ static void mctHookAfterCPU(void)
- }
-
-
--static void mctSaveDQSSigTmg_D(void)
--{
--}
--
--
--static void mctGetDQSSigTmg_D(void)
--{
--}
--
--
- static void mctHookBeforeECC(void)
- {
- }
---
-1.7.9.5
-