diff options
Diffstat (limited to 'src/northbridge')
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 145 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/mct_d.h | 6 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/s3utils.c | 175 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/mct_ddr3/s3utils.h | 10 | ||||
-rw-r--r-- | src/northbridge/amd/amdmct/wrappers/mcti_d.c | 4 |
5 files changed, 288 insertions, 52 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c index 0718477872..ad0e6e807b 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c @@ -35,7 +35,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, @@ -1169,6 +1170,30 @@ static void read_spd_bytes(struct MCTStatStruc *pMCTstat, } } +#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) +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; + } +} +#endif + static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) { @@ -1217,6 +1242,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(); @@ -1233,7 +1260,8 @@ restartinit: #if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) printk(BIOS_DEBUG, "mctAutoInitMCT_D: Restoring DCT configuration from NVRAM\n"); - restore_mct_information_from_nvram(); + if (restore_mct_information_from_nvram(0) != 0) + printk(BIOS_CRIT, "%s: ERROR: Unable to restore DCT configuration from NVRAM\n", __func__); #endif printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_Dis_Fam15\n"); @@ -1283,11 +1311,26 @@ 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); + #if IS_ENABLED(DIMM_VOLTAGE_SET_SUPPORT) printk(BIOS_DEBUG, "%s: DIMMSetVoltage\n", __func__); DIMMSetVoltages(pMCTstat, pDCTstatA); /* Set the DIMM voltages (mainboard specific) */ #endif + /* 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; @@ -1321,14 +1364,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; @@ -1810,7 +1872,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; @@ -1818,9 +1880,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); @@ -1839,15 +1900,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()) { @@ -1877,18 +1939,26 @@ 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); +#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) + printk(BIOS_DEBUG, "mctAutoInitMCT_D: Restoring DIMM training configuration from NVRAM\n"); + if (restore_mct_information_from_nvram(1) != 0) + printk(BIOS_CRIT, "%s: ERROR: Unable to restore DCT configuration from NVRAM\n", __func__); +#endif + + 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, @@ -3898,6 +3968,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); @@ -3912,6 +3984,27 @@ static void mct_preInitDCT(struct MCTStatStruc *pMCTstat, pDCTstat->ErrCode = err_code; /* Using DCT0 Error code to update pDCTstat.ErrCode */ } } + +#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) + calculate_and_store_spd_hashes(pMCTstat, pDCTstat); + + 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 e6b427ed7b..1ac7bbfe62 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h @@ -321,6 +321,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*/ @@ -780,6 +784,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 3c2043be54..c4410443e0 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c @@ -22,8 +22,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" @@ -120,6 +122,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); @@ -145,6 +209,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; @@ -437,7 +526,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; @@ -447,6 +536,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++) { @@ -497,7 +631,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++) @@ -886,6 +1021,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; @@ -905,6 +1042,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) @@ -945,36 +1085,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 5370496615..56e627e413 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h +++ b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h @@ -16,9 +16,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); diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c b/src/northbridge/amd/amdmct/wrappers/mcti_d.c index 48ab8007ab..a030f71e95 100644 --- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c +++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c @@ -396,14 +396,18 @@ static void mctHookAfterCPU(void) } +#if IS_ENABLED(CONFIG_DIMM_DDR2) static void mctSaveDQSSigTmg_D(void) { } +#endif +#if IS_ENABLED(CONFIG_DIMM_DDR2) static void mctGetDQSSigTmg_D(void) { } +#endif static void mctHookBeforeECC(void) |