summaryrefslogtreecommitdiff
path: root/src/soc/intel/xeon_sp/dimm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/xeon_sp/dimm.c')
-rw-r--r--src/soc/intel/xeon_sp/dimm.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/soc/intel/xeon_sp/dimm.c b/src/soc/intel/xeon_sp/dimm.c
new file mode 100644
index 0000000000..c02678a8ac
--- /dev/null
+++ b/src/soc/intel/xeon_sp/dimm.c
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <console/console.h>
+#include <smbios.h>
+#include <soc/ddr.h>
+#include <soc/intel/common/smbios.h>
+#include <soc/romstage.h>
+#include <soc/util.h>
+#include <spd.h>
+
+void save_dimm_info(void)
+{
+ const struct SystemMemoryMapHob *hob = get_system_memory_map();
+ assert(hob != NULL);
+
+ /*
+ * Allocate CBMEM area for DIMM information used to populate SMBIOS
+ * table 17
+ */
+ struct memory_info *mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
+ if (mem_info == NULL) {
+ printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n");
+ return;
+ }
+ memset(mem_info, 0, sizeof(*mem_info));
+ mem_info->max_capacity_mib = get_max_capacity_mib();
+ mem_info->number_of_devices = CONFIG_DIMM_MAX;
+ mem_info->ecc_type = get_error_correction_type(hob->RasModesEnabled);
+ int dimm_max = ARRAY_SIZE(mem_info->dimm);
+
+ uint32_t vdd_voltage = get_ddr_millivolt(hob->DdrVoltage);
+
+ int slot_index = 0;
+ const int max_dimm_count = get_max_dimm_count();
+ int dimm_num = 0;
+ for (int skt = 0; skt < CONFIG_MAX_SOCKET; skt++) {
+ for (int ch = 0; ch < MAX_CH; ch++) {
+ for (int dimm = 0; dimm < max_dimm_count; dimm++) {
+ if (slot_index >= dimm_max) {
+ printk(BIOS_WARNING, "Too many DIMMs info for %s.\n",
+ __func__);
+ return;
+ }
+
+ struct dimm_info *dest_dimm;
+ MEMMAP_DIMM_DEVICE_INFO_STRUCT src_dimm =
+ hob->Socket[skt].ChannelInfo[ch].DimmInfo[dimm];
+
+ if (src_dimm.Present) {
+ dest_dimm = &mem_info->dimm[slot_index++];
+ dest_dimm->dimm_size = (src_dimm.DimmSize << 6);
+ dest_dimm->soc_num = skt;
+ dest_dimm->channel_num = ch;
+ dest_dimm->dimm_num = dimm;
+ } else if (mainboard_dimm_slot_exists(skt, ch, dimm)) {
+ dest_dimm = &mem_info->dimm[slot_index++];
+ dest_dimm->dimm_size = 0;
+ dest_dimm->soc_num = skt;
+ dest_dimm->channel_num = ch;
+ dest_dimm->dimm_num = dimm;
+ continue;
+ } else
+ continue;
+
+ uint8_t mem_dev_type = get_dram_type(hob);
+ uint16_t data_width = 64;
+
+ dimm_info_fill(
+ dest_dimm, src_dimm.DimmSize << 6, mem_dev_type,
+ hob->memFreq, /* replaced by configured_speed_mts */
+ src_dimm.NumRanks,
+ ch, /* for mainboard locator string override */
+ dimm, /* for mainboard locator string override */
+ (const char *)&src_dimm.PartNumber[0],
+ sizeof(src_dimm.PartNumber),
+ (const uint8_t *)&src_dimm.serialNumber[0], data_width,
+ vdd_voltage, true, /* hard-coded as ECC supported */
+ src_dimm.VendorID, src_dimm.actKeyByte2, 0,
+ get_max_memory_speed(src_dimm.commonTck));
+
+ dimm_num++;
+ }
+ }
+ }
+
+ mem_info->dimm_cnt = slot_index; /* Number of DIMM slots found */
+ printk(BIOS_DEBUG, "%d slots and %d installed DIMMs found\n", slot_index, dimm_num);
+}