diff options
author | Matt DeVillier <matt.devillier@gmail.com> | 2016-09-02 13:29:17 -0500 |
---|---|---|
committer | Martin Roth <martinroth@google.com> | 2017-06-16 16:08:24 +0200 |
commit | 5aaa8ce21c85a41c313c18ca7a4e41a25ab711d9 (patch) | |
tree | 9978466f54e34641cc94a428cad2a4f56abd9ca8 | |
parent | f739e7f56a237556240a46ade476f75ed41d4fc1 (diff) |
haswell: add CBMEM_MEMINFO table when initing RAM
Populate a memory_info struct with PEI and SPD data,
in order to inject the CBMEM_INFO table necessary to
populate a type17 SMBIOS table.
On Broadwell, this is done by the MRC binary, but the older
Haswell MRC binary doesn't populate the pei_data struct with
all the info needed, so we have to pull it from the SPD.
Some values are hardcoded based on platform specifications.
Change-Id: Iea837d23f2c9c1c943e0db28cf81b265f054e9d1
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/19958
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
-rw-r--r-- | src/cpu/intel/haswell/romstage.c | 2 | ||||
-rw-r--r-- | src/include/device/dram/ddr3.h | 13 | ||||
-rw-r--r-- | src/northbridge/intel/haswell/raminit.c | 55 | ||||
-rw-r--r-- | src/northbridge/intel/haswell/raminit.h | 1 |
4 files changed, 71 insertions, 0 deletions
diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c index c6765c757c..ac45ee62ad 100644 --- a/src/cpu/intel/haswell/romstage.c +++ b/src/cpu/intel/haswell/romstage.c @@ -245,6 +245,8 @@ void romstage_common(const struct romstage_params *params) #endif } + setup_sdram_meminfo(params->pei_data); + romstage_handoff_init(wake_from_s3); post_code(0x3f); diff --git a/src/include/device/dram/ddr3.h b/src/include/device/dram/ddr3.h index 9597a3140b..5961f4106b 100644 --- a/src/include/device/dram/ddr3.h +++ b/src/include/device/dram/ddr3.h @@ -33,6 +33,19 @@ #include <spd.h> /** + * Convenience definitions for SPD offsets + * + * @{ + */ +#define SPD_DIMM_MOD_ID1 117 +#define SPD_DIMM_MOD_ID2 118 +#define SPD_DIMM_SERIAL_NUM 122 +#define SPD_DIMM_SERIAL_LEN 4 +#define SPD_DIMM_PART_NUM 128 +#define SPD_DIMM_PART_LEN 18 +/** @} */ + +/** * \brief Convenience definitions for TCK values * * Different values for tCK, representing standard DDR3 frequencies. diff --git a/src/northbridge/intel/haswell/raminit.c b/src/northbridge/intel/haswell/raminit.c index 469c4f2fa0..50443aa94c 100644 --- a/src/northbridge/intel/haswell/raminit.c +++ b/src/northbridge/intel/haswell/raminit.c @@ -21,9 +21,13 @@ #include <cbfs.h> #include <halt.h> #include <ip_checksum.h> +#include <memory_info.h> #include <northbridge/intel/common/mrc_cache.h> #include <pc80/mc146818rtc.h> #include <device/pci_def.h> +#include <device/dram/ddr3.h> +#include <smbios.h> +#include <spd.h> #include <vboot/vboot_common.h> #include "raminit.h" #include "pei_data.h" @@ -171,3 +175,54 @@ void sdram_initialize(struct pei_data *pei_data) report_memory_config(); } + +void setup_sdram_meminfo(struct pei_data *pei_data) +{ + u32 addr_decoder_common, addr_decode_ch[2]; + struct memory_info* mem_info; + struct dimm_info *dimm; + int ddr_frequency; + int dimm_size; + int ch, d_num; + int dimm_cnt = 0; + + mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(struct memory_info)); + memset(mem_info, 0, sizeof(struct memory_info)); + + addr_decoder_common = MCHBAR32(0x5000); + addr_decode_ch[0] = MCHBAR32(0x5004); + addr_decode_ch[1] = MCHBAR32(0x5008); + + ddr_frequency = (MCHBAR32(0x5e04) * 13333 * 2 + 50) / 100; + + for (ch = 0; ch < ARRAY_SIZE(addr_decode_ch); ch++) { + u32 ch_conf = addr_decode_ch[ch]; + /* DIMMs A/B */ + for (d_num = 0; d_num < 2; d_num++) { + dimm_size = ((ch_conf >> (d_num * 8)) & 0xff) * 256; + if (dimm_size) { + dimm = &mem_info->dimm[dimm_cnt]; + dimm->dimm_size = dimm_size; + dimm->ddr_type = MEMORY_TYPE_DDR3; + dimm->ddr_frequency = ddr_frequency; + dimm->rank_per_dimm = 1 + ((ch_conf >> (17 + d_num)) & 1); + dimm->channel_num = ch; + dimm->dimm_num = d_num; + dimm->bank_locator = ch * 2; + memcpy(dimm->serial, + &pei_data->spd_data[dimm_cnt][SPD_DIMM_SERIAL_NUM], + SPD_DIMM_SERIAL_LEN); + memcpy(dimm->module_part_number, + &pei_data->spd_data[dimm_cnt][SPD_DIMM_PART_NUM], + SPD_DIMM_PART_LEN); + dimm->mod_id = + (pei_data->spd_data[dimm_cnt][SPD_DIMM_MOD_ID2] << 8) | + (pei_data->spd_data[dimm_cnt][SPD_DIMM_MOD_ID1] & 0xFF); + dimm->mod_type = SPD_SODIMM; + dimm->bus_width = 0x3; /* 64-bit */ + dimm_cnt++; + } + } + } + mem_info->dimm_cnt = dimm_cnt; +} diff --git a/src/northbridge/intel/haswell/raminit.h b/src/northbridge/intel/haswell/raminit.h index d02b72dac2..b42fcf87d6 100644 --- a/src/northbridge/intel/haswell/raminit.h +++ b/src/northbridge/intel/haswell/raminit.h @@ -19,6 +19,7 @@ #include "pei_data.h" void sdram_initialize(struct pei_data *pei_data); +void setup_sdram_meminfo(struct pei_data *pei_data); int fixup_haswell_errata(void); /* save_mrc_data() must be called after cbmem has been initialized. */ void save_mrc_data(struct pei_data *pei_data); |