northbridge/amd/amdmct: Verify MCT NVRAM options before skipping training
Change-Id: If26e5d148a906d63bd1407b8ffa58f08ae6b4275 Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> Reviewed-on: http://review.coreboot.org/11986 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
ab87c4db30
commit
f70946ff4d
|
@ -4134,7 +4134,7 @@ static void mct_preInitDCT(struct MCTStatStruc *pMCTstat,
|
||||||
#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
|
#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
|
||||||
calculate_and_store_spd_hashes(pMCTstat, pDCTstat);
|
calculate_and_store_spd_hashes(pMCTstat, pDCTstat);
|
||||||
|
|
||||||
if (load_spd_hashes_from_nvram(pDCTstat) < 0) {
|
if (load_spd_hashes_from_nvram(pMCTstat, pDCTstat) < 0) {
|
||||||
pDCTstat->spd_data.nvram_spd_match = 0;
|
pDCTstat->spd_data.nvram_spd_match = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4149,6 +4149,13 @@ static void mct_preInitDCT(struct MCTStatStruc *pMCTstat,
|
||||||
if (get_option(&nvram, "allow_spd_nvram_cache_restore") == CB_SUCCESS)
|
if (get_option(&nvram, "allow_spd_nvram_cache_restore") == CB_SUCCESS)
|
||||||
allow_config_restore = !!nvram;
|
allow_config_restore = !!nvram;
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
|
||||||
|
if (pMCTstat->nvram_checksum != calculate_nvram_mct_hash())
|
||||||
|
allow_config_restore = 0;
|
||||||
|
#else
|
||||||
|
allow_config_restore = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!allow_config_restore)
|
if (!allow_config_restore)
|
||||||
pDCTstat->spd_data.nvram_spd_match = 0;
|
pDCTstat->spd_data.nvram_spd_match = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,6 +297,7 @@ struct MCTStatStruc {
|
||||||
u32 Sub4GCacheTop; /* If not zero, the 32-bit top of cacheable memory.*/
|
u32 Sub4GCacheTop; /* If not zero, the 32-bit top of cacheable memory.*/
|
||||||
u32 SysLimit; /* LIMIT[39:8] (system address)*/
|
u32 SysLimit; /* LIMIT[39:8] (system address)*/
|
||||||
uint32_t TSCFreq;
|
uint32_t TSCFreq;
|
||||||
|
uint16_t nvram_checksum;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/*=============================================================================
|
/*=============================================================================
|
||||||
|
@ -792,6 +793,7 @@ struct amd_s3_persistent_node_data {
|
||||||
|
|
||||||
struct amd_s3_persistent_data {
|
struct amd_s3_persistent_data {
|
||||||
struct amd_s3_persistent_node_data node[MAX_NODES_SUPPORTED];
|
struct amd_s3_persistent_node_data node[MAX_NODES_SUPPORTED];
|
||||||
|
uint16_t nvram_checksum;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/*===============================================================================
|
/*===============================================================================
|
||||||
|
|
|
@ -139,6 +139,36 @@ void calculate_spd_hash(uint8_t *spd_data, uint64_t *spd_hash)
|
||||||
*spd_hash = *spd_hash ^ (*spd_hash << 37);
|
*spd_hash = *spd_hash ^ (*spd_hash << 37);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t calculate_nvram_mct_hash(void)
|
||||||
|
{
|
||||||
|
uint32_t nvram;
|
||||||
|
uint16_t ret;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
if (get_option(&nvram, "max_mem_clock") == CB_SUCCESS)
|
||||||
|
ret |= nvram & 0xf;
|
||||||
|
if (get_option(&nvram, "minimum_memory_voltage") == CB_SUCCESS)
|
||||||
|
ret |= (nvram & 0x3) << 4;
|
||||||
|
if (get_option(&nvram, "ECC_memory") == CB_SUCCESS)
|
||||||
|
ret |= (nvram & 0x1) << 6;
|
||||||
|
if (get_option(&nvram, "ECC_redirection") == CB_SUCCESS)
|
||||||
|
ret |= (nvram & 0x1) << 7;
|
||||||
|
if (get_option(&nvram, "ecc_scrub_rate") == CB_SUCCESS)
|
||||||
|
ret |= (nvram & 0x1) << 8;
|
||||||
|
if (get_option(&nvram, "interleave_chip_selects") == CB_SUCCESS)
|
||||||
|
ret |= (nvram & 0x1) << 9;
|
||||||
|
if (get_option(&nvram, "interleave_nodes") == CB_SUCCESS)
|
||||||
|
ret |= (nvram & 0x1) << 10;
|
||||||
|
if (get_option(&nvram, "interleave_memory_channels") == CB_SUCCESS)
|
||||||
|
ret |= (nvram & 0x1) << 11;
|
||||||
|
if (get_option(&nvram, "cpu_c_states") == CB_SUCCESS)
|
||||||
|
ret |= (nvram & 0x1) << 12;
|
||||||
|
if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS)
|
||||||
|
ret |= (nvram & 0x1) << 13;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static struct amd_s3_persistent_data * map_s3nv_in_nvram(void)
|
static struct amd_s3_persistent_data * map_s3nv_in_nvram(void)
|
||||||
{
|
{
|
||||||
ssize_t s3nv_offset;
|
ssize_t s3nv_offset;
|
||||||
|
@ -169,7 +199,7 @@ static struct amd_s3_persistent_data * map_s3nv_in_nvram(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __PRE_RAM__
|
#ifdef __PRE_RAM__
|
||||||
int8_t load_spd_hashes_from_nvram(struct DCTStatStruc *pDCTstat)
|
int8_t load_spd_hashes_from_nvram(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
|
||||||
{
|
{
|
||||||
struct amd_s3_persistent_data *persistent_data;
|
struct amd_s3_persistent_data *persistent_data;
|
||||||
|
|
||||||
|
@ -180,6 +210,8 @@ int8_t load_spd_hashes_from_nvram(struct DCTStatStruc *pDCTstat)
|
||||||
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_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));
|
memcpy(pDCTstat->spd_data.nvram_memclk, persistent_data->node[pDCTstat->Node_ID].memclk, sizeof(pDCTstat->spd_data.nvram_memclk));
|
||||||
|
|
||||||
|
pMCTstat->nvram_checksum = persistent_data->nvram_checksum;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -233,6 +265,8 @@ static void copy_cbmem_spd_data_to_save_variable(struct amd_s3_persistent_data*
|
||||||
for (channel = 0; channel < 2; channel++)
|
for (channel = 0; channel < 2; channel++)
|
||||||
persistent_data->node[node].memclk[channel] = mem_info->dct_stat[node].Speed;
|
persistent_data->node[node].memclk[channel] = mem_info->dct_stat[node].Speed;
|
||||||
|
|
||||||
|
persistent_data->nvram_checksum = calculate_nvram_mct_hash();
|
||||||
|
|
||||||
if (restored) {
|
if (restored) {
|
||||||
if (mem_info->mct_stat.GStatus & (1 << GSB_ConfigRestored))
|
if (mem_info->mct_stat.GStatus & (1 << GSB_ConfigRestored))
|
||||||
*restored = 1;
|
*restored = 1;
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
#include "mct_d.h"
|
#include "mct_d.h"
|
||||||
|
|
||||||
void calculate_spd_hash(uint8_t *spd_data, uint64_t *spd_hash);
|
void calculate_spd_hash(uint8_t *spd_data, uint64_t *spd_hash);
|
||||||
|
uint16_t calculate_nvram_mct_hash(void);
|
||||||
|
|
||||||
#ifdef __PRE_RAM__
|
#ifdef __PRE_RAM__
|
||||||
int8_t load_spd_hashes_from_nvram(struct DCTStatStruc *pDCTstat);
|
int8_t load_spd_hashes_from_nvram(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __RAMSTAGE__
|
#ifdef __RAMSTAGE__
|
||||||
|
|
Loading…
Reference in New Issue