From ff1ef8db4a383ff04d6ca4c4c464a06055f51137 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Sat, 24 Dec 2016 15:36:24 -0600 Subject: [PATCH] nb/intel/sandybridge: Populate meminfo when using MRC 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 Sandy Bridge 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: I15e00a01121150b778cfa684b9147d0cac97beb8 Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/58188 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/northbridge/intel/sandybridge/raminit.h | 1 + .../intel/sandybridge/raminit_mrc.c | 76 +++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/northbridge/intel/sandybridge/raminit.h b/src/northbridge/intel/sandybridge/raminit.h index c5d881a196..dd4e572119 100644 --- a/src/northbridge/intel/sandybridge/raminit.h +++ b/src/northbridge/intel/sandybridge/raminit.h @@ -13,5 +13,6 @@ void sdram_initialize(struct pei_data *pei_data); void save_mrc_data(struct pei_data *pei_data); void mainboard_fill_pei_data(struct pei_data *pei_data); int fixup_sandybridge_errata(void); +void setup_sdram_meminfo(struct pei_data *pei_data); #endif /* RAMINIT_H */ diff --git a/src/northbridge/intel/sandybridge/raminit_mrc.c b/src/northbridge/intel/sandybridge/raminit_mrc.c index fc143f67a6..ee5f1c94fa 100644 --- a/src/northbridge/intel/sandybridge/raminit_mrc.c +++ b/src/northbridge/intel/sandybridge/raminit_mrc.c @@ -23,6 +23,7 @@ #include "chip.h" #include #include +#include /* Management Engine is in the southbridge */ #include @@ -382,4 +383,79 @@ void perform_raminit(int s3resume) /* Failed S3 resume, reset to come up cleanly */ system_reset(); } + setup_sdram_meminfo(&pei_data); +} + +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 dimm_size; + int i; + 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 = mchbar_read32(MAD_CHNL); + addr_decode_ch[0] = mchbar_read32(MAD_DIMM_CH0); + addr_decode_ch[1] = mchbar_read32(MAD_DIMM_CH1); + + const int refclk = mchbar_read32(MC_BIOS_REQ) & 0x100 ? 100 : 133; + const int ddr_frequency = (mchbar_read32(MC_BIOS_DATA) * refclk * 100 * 2 + 50) / 100; + + for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) { + u32 ch_conf = addr_decode_ch[i]; + + /* DIMM-A */ + dimm_size = ((ch_conf >> 0) & 0xff) * 256; + if (dimm_size) { + dimm = &mem_info->dimm[dimm_cnt]; + dimm->dimm_size = dimm_size; + dimm->ddr_type = 0x18; /* DDR3 */ + dimm->ddr_frequency = ddr_frequency; + dimm->rank_per_dimm = 1 + ((ch_conf >> 17) & 1); + dimm->channel_num = i; + dimm->dimm_num = 0; + dimm->bank_locator = i * 2; + memcpy(dimm->serial, /* bytes 122-125 */ + &pei_data->spd_data[0][122], + sizeof(uint8_t) * 4); + memcpy(dimm->module_part_number, /* bytes 128-145 */ + &pei_data->spd_data[0][128], + sizeof(uint8_t) * 18); + dimm->mod_id = /* bytes 117/118 */ + (pei_data->spd_data[0][118] << 8) | + (pei_data->spd_data[0][117] & 0xFF); + dimm->mod_type = 3; /* SPD_SODIMM */ + dimm->bus_width = 0x3; /* 64-bit */ + dimm_cnt++; + } + /* DIMM-B */ + dimm_size = ((ch_conf >> 8) & 0xff) * 256; + if (dimm_size) { + dimm = &mem_info->dimm[dimm_cnt]; + dimm->dimm_size = dimm_size; + dimm->ddr_type = 0x18; /* DDR3 */ + dimm->ddr_frequency = ddr_frequency; + dimm->rank_per_dimm = 1 + ((ch_conf >> 18) & 1); + dimm->channel_num = i; + dimm->dimm_num = 1; + dimm->bank_locator = i * 2; + memcpy(dimm->serial, /* bytes 122-125 */ + &pei_data->spd_data[0][122], + sizeof(uint8_t) * 4); + memcpy(dimm->module_part_number, /* bytes 128-145 */ + &pei_data->spd_data[0][128], + sizeof(uint8_t) * 18); + dimm->mod_id = /* bytes 117/118 */ + (pei_data->spd_data[0][118] << 8) | + (pei_data->spd_data[0][117] & 0xFF); + dimm->mod_type = 3; /* SPD_SODIMM */ + dimm->bus_width = 0x3; /* 64-bit */ + dimm_cnt++; + } + } + mem_info->dimm_cnt = dimm_cnt; }