diff --git a/src/device/dram/ddr3.c b/src/device/dram/ddr3.c index 7655b32012..63ca964a5a 100644 --- a/src/device/dram/ddr3.c +++ b/src/device/dram/ddr3.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include /*============================================================================== * = DDR3 SPD decoding helpers @@ -522,6 +525,82 @@ int spd_xmp_decode_ddr3(dimm_attr *dimm, return ret; } + +/** + * Fill cbmem with information for SMBIOS type 17. + * + * @param channel Corresponding channel of provided @info + * @param slot Corresponding slot of provided @info + * @param selected_freq The actual frequency the DRAM is running on + * @param info DIMM parameters read from SPD + * + * @return CB_SUCCESS if DIMM info was written + */ +enum cb_err spd_add_smbios17(const u8 channel, const u8 slot, + const u16 selected_freq, + const dimm_attr *info) +{ + struct memory_info *mem_info; + struct dimm_info *dimm; + + /* + * Allocate CBMEM area for DIMM information used to populate SMBIOS + * table 17 + */ + mem_info = cbmem_find(CBMEM_ID_MEMINFO); + if (!mem_info) { + mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info)); + + printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", + mem_info); + if (!mem_info) + return CB_ERR; + + memset(mem_info, 0, sizeof(*mem_info)); + } + + dimm = &mem_info->dimm[mem_info->dimm_cnt]; + if (info->size_mb) { + dimm->ddr_type = MEMORY_TYPE_DDR3; + dimm->ddr_frequency = selected_freq; + dimm->dimm_size = info->size_mb; + dimm->channel_num = channel; + dimm->rank_per_dimm = info->ranks; + dimm->dimm_num = slot; + memcpy(dimm->module_part_number, info->part_number, 16); + dimm->mod_id = info->manufacturer_id; + + switch (info->dimm_type) { + case SPD_DIMM_TYPE_SO_DIMM: + dimm->mod_type = SPD_SODIMM; + break; + case SPD_DIMM_TYPE_72B_SO_CDIMM: + dimm->mod_type = SPD_72B_SO_CDIMM; + break; + case SPD_DIMM_TYPE_72B_SO_RDIMM: + dimm->mod_type = SPD_72B_SO_RDIMM; + break; + case SPD_DIMM_TYPE_UDIMM: + dimm->mod_type = SPD_UDIMM; + break; + case SPD_DIMM_TYPE_RDIMM: + dimm->mod_type = SPD_RDIMM; + break; + case SPD_DIMM_TYPE_UNDEFINED: + default: + dimm->mod_type = SPD_UNDEFINED; + break; + } + + dimm->bus_width = MEMORY_BUS_WIDTH_64; // non-ECC only + memcpy(dimm->serial, info->serial, + MIN(sizeof(dimm->serial), sizeof(info->serial))); + mem_info->dimm_cnt++; + } + + return CB_SUCCESS; +} + /* * The information printed below has a more informational character, and is not * necessarily tied in to RAM init debugging. Hence, we stop using printram(), diff --git a/src/include/device/dram/ddr3.h b/src/include/device/dram/ddr3.h index 563be10c07..5643787c01 100644 --- a/src/include/device/dram/ddr3.h +++ b/src/include/device/dram/ddr3.h @@ -32,6 +32,7 @@ #include #include #include +#include /** @@ -193,7 +194,9 @@ void dram_print_spd_ddr3(const dimm_attr *dimm); int spd_xmp_decode_ddr3(dimm_attr *dimm, spd_raw_data spd, enum ddr3_xmp_profile profile); - +enum cb_err spd_add_smbios17(const u8 channel, const u8 slot, + const u16 selected_freq, + const dimm_attr *info); /** * \brief Read double word from specified address * diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c index 4d02a64e2c..0f72d88813 100644 --- a/src/northbridge/intel/sandybridge/raminit.c +++ b/src/northbridge/intel/sandybridge/raminit.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include @@ -29,8 +28,6 @@ #include #include #include -#include -#include #include #include "raminit_native.h" #include "raminit_common.h" @@ -81,67 +78,14 @@ static void disable_channel(ramctr_timing *ctrl, int channel) { */ static void fill_smbios17(ramctr_timing *ctrl) { - struct memory_info *mem_info; int channel, slot; - struct dimm_info *dimm; - uint16_t ddr_freq; - dimm_info *info = &ctrl->info; - - ddr_freq = (1000 << 8) / ctrl->tCK; - - /* - * Allocate CBMEM area for DIMM information used to populate SMBIOS - * table 17 - */ - mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info)); - printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info); - if (!mem_info) - return; - - memset(mem_info, 0, sizeof(*mem_info)); + const u16 ddr_freq = (1000 << 8) / ctrl->tCK; FOR_ALL_CHANNELS for (slot = 0; slot < NUM_SLOTS; slot++) { - dimm = &mem_info->dimm[mem_info->dimm_cnt]; - if (info->dimm[channel][slot].size_mb) { - dimm->ddr_type = MEMORY_TYPE_DDR3; - dimm->ddr_frequency = ddr_freq; - dimm->dimm_size = info->dimm[channel][slot].size_mb; - dimm->channel_num = channel; - dimm->rank_per_dimm = info->dimm[channel][slot].ranks; - dimm->dimm_num = slot; - memcpy(dimm->module_part_number, - info->dimm[channel][slot].part_number, 16); - dimm->mod_id = info->dimm[channel][slot].manufacturer_id; - - switch (info->dimm[channel][slot].dimm_type) { - case SPD_DIMM_TYPE_SO_DIMM: - dimm->mod_type = SPD_SODIMM; - break; - case SPD_DIMM_TYPE_72B_SO_CDIMM: - dimm->mod_type = SPD_72B_SO_CDIMM; - break; - case SPD_DIMM_TYPE_72B_SO_RDIMM: - dimm->mod_type = SPD_72B_SO_RDIMM; - break; - case SPD_DIMM_TYPE_UDIMM: - dimm->mod_type = SPD_UDIMM; - break; - case SPD_DIMM_TYPE_RDIMM: - dimm->mod_type = SPD_RDIMM; - break; - case SPD_DIMM_TYPE_UNDEFINED: - default: - dimm->mod_type = SPD_UNDEFINED; - break; - } - - dimm->bus_width = MEMORY_BUS_WIDTH_64; // non-ECC only - - memcpy(dimm->serial, info->dimm[channel][slot].serial, - MIN(sizeof(dimm->serial), - sizeof(info->dimm[channel][slot].serial))); - mem_info->dimm_cnt++; - } + enum cb_err ret = spd_add_smbios17(channel, slot, ddr_freq, + &ctrl->info.dimm[channel][slot]); + if (ret != CB_SUCCESS) + printk(BIOS_ERR, "RAMINIT: Failed to add SMBIOS17\n"); } }