xref: /aosp_15_r20/external/coreboot/src/soc/intel/denverton_ns/hob_mem.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <cbmem.h>
4 #include <console/console.h>
5 #include <string.h>
6 
7 #include <soc/hob_mem.h>
8 
9 #include <smbios.h>
10 #include <memory_info.h>
11 #include <soc/ramstage.h>
12 
13 /* Save the DIMM information for SMBIOS table 17 */
soc_save_dimm_info(void)14 void soc_save_dimm_info(void)
15 {
16 	int channel;
17 	const CHANNEL_INFO *channel_info;
18 	int dimm;
19 	const DIMM_INFO *dimm_info;
20 	int dimm_max;
21 	int index;
22 	struct memory_info *mem_info;
23 	const FSP_SMBIOS_MEMORY_INFO *memory_info_hob;
24 
25 	/* Get the memory info HOB */
26 	memory_info_hob = soc_get_fsp_smbios_memory_info_hob();
27 
28 	if (memory_info_hob == NULL)
29 		return;
30 
31 	/* Display the data in the FSP_SMBIOS_MEMORY_INFO HOB */
32 	if (CONFIG(DISPLAY_HOBS))
33 		soc_display_fsp_smbios_memory_info_hob(memory_info_hob);
34 
35 	/*
36 	 * Allocate CBMEM area for DIMM information used to populate SMBIOS
37 	 * table 17
38 	 */
39 	mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
40 	printk(BIOS_DEBUG, "CBMEM entry for DIMM info: %p\n", mem_info);
41 	if (mem_info == NULL)
42 		return;
43 	memset(mem_info, 0, sizeof(*mem_info));
44 
45 	/* Describe the first N DIMMs in the system */
46 	index = 0;
47 	dimm_max = ARRAY_SIZE(mem_info->dimm);
48 	for (channel = 0; channel < memory_info_hob->ChannelCount; channel++) {
49 		if (index >= dimm_max)
50 			break;
51 		channel_info = &memory_info_hob->ChannelInfo[channel];
52 		for (dimm = 0; dimm < channel_info->DimmCount; dimm++) {
53 			if (index >= dimm_max)
54 				break;
55 			dimm_info = &channel_info->DimmInfo[dimm];
56 
57 			/* Populate the DIMM information */
58 			if (!dimm_info->SizeInMb)
59 				continue;
60 
61 			mem_info->dimm[index].dimm_size =
62 				dimm_info->SizeInMb;
63 			mem_info->dimm[index].ddr_type =
64 				memory_info_hob->MemoryType;
65 			mem_info->dimm[index].ddr_frequency =
66 				memory_info_hob->MemoryFrequencyInMHz;
67 			mem_info->dimm[index].channel_num =
68 				channel_info->ChannelId;
69 			mem_info->dimm[index].dimm_num =
70 				dimm_info->DimmId;
71 
72 			strncpy((char *)
73 				mem_info->dimm[index].module_part_number,
74 				(char *)dimm_info->ModulePartNum, 18);
75 			mem_info->dimm[index].mod_id =
76 				dimm_info->MfgId;
77 			switch (memory_info_hob->DataWidth) {
78 			default:
79 			case 8:
80 				mem_info->dimm[index].bus_width =
81 					MEMORY_BUS_WIDTH_8;
82 				break;
83 
84 			case 16:
85 				mem_info->dimm[index].bus_width =
86 					MEMORY_BUS_WIDTH_16;
87 				break;
88 
89 			case 32:
90 				mem_info->dimm[index].bus_width =
91 					MEMORY_BUS_WIDTH_32;
92 				break;
93 
94 			case 64:
95 				mem_info->dimm[index].bus_width =
96 					MEMORY_BUS_WIDTH_64;
97 				break;
98 
99 			case 128:
100 				mem_info->dimm[index].bus_width =
101 					MEMORY_BUS_WIDTH_128;
102 				break;
103 			}
104 
105 			/* Add any mainboard specific information */
106 			mainboard_add_dimm_info(mem_info, channel, dimm, index);
107 			index++;
108 		}
109 	}
110 	mem_info->dimm_cnt = index;
111 	printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
112 }
113 
114 /* Add any mainboard specific information */
mainboard_add_dimm_info(struct memory_info * mem_info,int channel,int dimm,int index)115 __weak void mainboard_add_dimm_info(struct memory_info *mem_info,
116 						   int channel, int dimm,
117 						   int index)
118 {
119 	printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
120 }
121