blob: 326e716cbc870f52a0a5a23ffe00168b54ac71af [file] [log] [blame]
Angel Pons80d92382020-04-05 15:47:00 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Julien Viard de Galbert2d0aaa72018-02-26 18:32:59 +01002
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 */
14void 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 */
Julius Wernercd49cce2019-03-05 16:53:33 -080032 if (CONFIG(DISPLAY_HOBS))
Julien Viard de Galbert2d0aaa72018-02-26 18:32:59 +010033 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));
Julius Werner540a9802019-12-09 13:03:29 -080040 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: %p\n", mem_info);
Julien Viard de Galbert2d0aaa72018-02-26 18:32:59 +010041 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 */
115__attribute__((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}