MAINTAINERS: Add Yuchi and Vasiliy for Intel Atom Snow Ridge SoC
[coreboot.git] / src / soc / intel / xeon_sp / dimm.c
blobc02678a8accc69e28a77ee08cbf7478a420aba43
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <console/console.h>
4 #include <smbios.h>
5 #include <soc/ddr.h>
6 #include <soc/intel/common/smbios.h>
7 #include <soc/romstage.h>
8 #include <soc/util.h>
9 #include <spd.h>
11 void save_dimm_info(void)
13 const struct SystemMemoryMapHob *hob = get_system_memory_map();
14 assert(hob != NULL);
17 * Allocate CBMEM area for DIMM information used to populate SMBIOS
18 * table 17
20 struct memory_info *mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
21 if (mem_info == NULL) {
22 printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n");
23 return;
25 memset(mem_info, 0, sizeof(*mem_info));
26 mem_info->max_capacity_mib = get_max_capacity_mib();
27 mem_info->number_of_devices = CONFIG_DIMM_MAX;
28 mem_info->ecc_type = get_error_correction_type(hob->RasModesEnabled);
29 int dimm_max = ARRAY_SIZE(mem_info->dimm);
31 uint32_t vdd_voltage = get_ddr_millivolt(hob->DdrVoltage);
33 int slot_index = 0;
34 const int max_dimm_count = get_max_dimm_count();
35 int dimm_num = 0;
36 for (int skt = 0; skt < CONFIG_MAX_SOCKET; skt++) {
37 for (int ch = 0; ch < MAX_CH; ch++) {
38 for (int dimm = 0; dimm < max_dimm_count; dimm++) {
39 if (slot_index >= dimm_max) {
40 printk(BIOS_WARNING, "Too many DIMMs info for %s.\n",
41 __func__);
42 return;
45 struct dimm_info *dest_dimm;
46 MEMMAP_DIMM_DEVICE_INFO_STRUCT src_dimm =
47 hob->Socket[skt].ChannelInfo[ch].DimmInfo[dimm];
49 if (src_dimm.Present) {
50 dest_dimm = &mem_info->dimm[slot_index++];
51 dest_dimm->dimm_size = (src_dimm.DimmSize << 6);
52 dest_dimm->soc_num = skt;
53 dest_dimm->channel_num = ch;
54 dest_dimm->dimm_num = dimm;
55 } else if (mainboard_dimm_slot_exists(skt, ch, dimm)) {
56 dest_dimm = &mem_info->dimm[slot_index++];
57 dest_dimm->dimm_size = 0;
58 dest_dimm->soc_num = skt;
59 dest_dimm->channel_num = ch;
60 dest_dimm->dimm_num = dimm;
61 continue;
62 } else
63 continue;
65 uint8_t mem_dev_type = get_dram_type(hob);
66 uint16_t data_width = 64;
68 dimm_info_fill(
69 dest_dimm, src_dimm.DimmSize << 6, mem_dev_type,
70 hob->memFreq, /* replaced by configured_speed_mts */
71 src_dimm.NumRanks,
72 ch, /* for mainboard locator string override */
73 dimm, /* for mainboard locator string override */
74 (const char *)&src_dimm.PartNumber[0],
75 sizeof(src_dimm.PartNumber),
76 (const uint8_t *)&src_dimm.serialNumber[0], data_width,
77 vdd_voltage, true, /* hard-coded as ECC supported */
78 src_dimm.VendorID, src_dimm.actKeyByte2, 0,
79 get_max_memory_speed(src_dimm.commonTck));
81 dimm_num++;
86 mem_info->dimm_cnt = slot_index; /* Number of DIMM slots found */
87 printk(BIOS_DEBUG, "%d slots and %d installed DIMMs found\n", slot_index, dimm_num);