1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <console/console.h>
6 #include <soc/intel/common/smbios.h>
7 #include <soc/romstage.h>
11 void save_dimm_info(void)
13 const struct SystemMemoryMapHob
*hob
= get_system_memory_map();
17 * Allocate CBMEM area for DIMM information used to populate SMBIOS
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");
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
);
34 const int max_dimm_count
= get_max_dimm_count();
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",
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
;
65 uint8_t mem_dev_type
= get_dram_type(hob
);
66 uint16_t data_width
= 64;
69 dest_dimm
, src_dimm
.DimmSize
<< 6, mem_dev_type
,
70 hob
->memFreq
, /* replaced by configured_speed_mts */
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
));
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
);