meminit_util_glk.c
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <cbmem.h> 4 #include <console/console.h> 5 #include <fsp/util.h> 6 #include <memory_info.h> 7 #include <soc/intel/common/smbios.h> 8 #include <soc/meminit.h> 9 #include <string.h> 10 11 #define FSP_SMBIOS_MEMORY_INFO_GUID \ 12 { \ 13 0x8c, 0x10, 0xa1, 0x01, 0xee, 0x9d, 0x84, 0x49, \ 14 0x88, 0xc3, 0xee, 0xe8, 0xc4, 0x9e, 0xfb, 0x89 \ 15 } 16 17 void save_lpddr4_dimm_info_part_num(const char *dram_part_num) 18 { 19 int channel, dimm, dimm_max, index, node; 20 size_t hob_size; 21 const DIMM_INFO *src_dimm; 22 struct dimm_info *dest_dimm; 23 struct memory_info *mem_info; 24 const CHANNEL_INFO *channel_info; 25 const FSP_SMBIOS_MEMORY_INFO *memory_info_hob; 26 const CONTROLLER_INFO *ctrl_info; 27 const uint8_t smbios_memory_info_guid[16] = 28 FSP_SMBIOS_MEMORY_INFO_GUID; 29 30 if (!dram_part_num) 31 dram_part_num = "Unknown"; 32 33 /* Locate the memory info HOB */ 34 memory_info_hob = fsp_find_extension_hob_by_guid( 35 smbios_memory_info_guid, 36 &hob_size); 37 38 if (memory_info_hob == NULL || hob_size == 0) { 39 printk(BIOS_ERR, "SMBIOS memory info HOB is missing\n"); 40 return; 41 } 42 43 /* 44 * Allocate CBMEM area for DIMM information used to populate SMBIOS 45 * table 17 46 */ 47 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info)); 48 if (mem_info == NULL) { 49 printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n"); 50 return; 51 } 52 memset(mem_info, 0, sizeof(*mem_info)); 53 54 /* Describe the first N DIMMs in the system */ 55 index = 0; 56 dimm_max = ARRAY_SIZE(mem_info->dimm); 57 58 for (node = 0; node < MAX_NODE_NUM; node++) { 59 ctrl_info = &memory_info_hob->Controller[node]; 60 for (channel = 0; channel < ctrl_info->ChannelCount; 61 channel++) { 62 if (index >= dimm_max) 63 break; 64 65 channel_info = &ctrl_info->ChannelInfo[channel]; 66 67 for (dimm = 0; dimm < channel_info->DimmCount; dimm++) { 68 if (index >= dimm_max) 69 break; 70 src_dimm = &channel_info->DimmInfo[dimm]; 71 dest_dimm = &mem_info->dimm[index]; 72 73 if (!src_dimm->DimmCapacity) 74 continue; 75 76 /* Populate the DIMM information */ 77 dimm_info_fill(dest_dimm, 78 src_dimm->DimmCapacity, 79 memory_info_hob->MemoryType, 80 memory_info_hob->ConfiguredMemoryClockSpeed, 81 src_dimm->RankInDimm, 82 channel_info->ChannelId, 83 src_dimm->DimmId, 84 dram_part_num, 85 strlen(dram_part_num), 86 src_dimm->SpdSave + SPD_SAVE_OFFSET_SERIAL, 87 memory_info_hob->DataWidth, 88 0, 89 0, 90 src_dimm->MfgId, 91 src_dimm->SpdModuleType, 92 node, 93 memory_info_hob->MaximumMemoryClockSpeed); 94 index++; 95 } 96 } 97 } 98 mem_info->dimm_cnt = index; 99 printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt); 100 } 101 102 void save_lpddr4_dimm_info(const struct lpddr4_cfg *lp4cfg, size_t mem_sku) 103 { 104 const char *part_num = NULL; 105 106 if (mem_sku >= lp4cfg->num_skus) { 107 printk(BIOS_ERR, "Too few LPDDR4 SKUs: 0x%zx/0x%zx\n", 108 mem_sku, lp4cfg->num_skus); 109 } else { 110 part_num = lp4cfg->skus[mem_sku].part_num; 111 } 112 113 save_lpddr4_dimm_info_part_num(part_num); 114 }