xref: /aosp_15_r20/external/coreboot/src/soc/amd/common/pi/amd_late_init.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi.h>
4 #include <bootstate.h>
5 #include <cbmem.h>
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <device/pci_def.h>
9 #include <dimm_info_util.h>
10 #include <memory_info.h>
11 #include <lib.h>
12 #include <string.h>
13 
14 #include <amdblocks/agesawrapper.h>
15 #include <amdblocks/agesawrapper_call.h>
16 
17 /**
18  * Populate dimm_info using AGESA TYPE17_DMI_INFO.
19  */
transfer_memory_info(TYPE17_DMI_INFO * dmi17,struct dimm_info * dimm)20 static void transfer_memory_info(TYPE17_DMI_INFO *dmi17,
21 				 struct dimm_info *dimm)
22 {
23 	hexstrtobin(dmi17->SerialNumber, dimm->serial, sizeof(dimm->serial));
24 
25 	dimm->dimm_size =
26 	    smbios_memory_size_to_mib(dmi17->MemorySize, dmi17->ExtSize);
27 
28 	dimm->ddr_type = dmi17->MemoryType;
29 
30 	/*
31 	 * dimm_info uses ddr_frequency for setting both config speed and max
32 	 * speed. Lets use config speed so we don't get the false impression
33 	 * that the RAM is running faster than it actually is.
34 	 */
35 	dimm->ddr_frequency = dmi17->ConfigSpeed;
36 
37 	dimm->rank_per_dimm = dmi17->Attributes;
38 
39 	dimm->mod_type = smbios_form_factor_to_spd_mod_type(
40 		(smbios_memory_type)dmi17->MemoryType,
41 		(smbios_memory_form_factor)dmi17->FormFactor);
42 
43 	dimm->bus_width = smbios_bus_width_to_spd_width(dmi17->MemoryType, dmi17->TotalWidth,
44 						dmi17->DataWidth);
45 
46 	dimm->mod_id = dmi17->ManufacturerIdCode;
47 
48 	dimm->bank_locator = 0;
49 
50 	strncpy((char *)dimm->module_part_number, dmi17->PartNumber,
51 				sizeof(dimm->module_part_number) - 1);
52 }
53 
print_dimm_info(const struct dimm_info * dimm)54 static void print_dimm_info(const struct dimm_info *dimm)
55 {
56 	printk(RAM_SPEW,
57 	       "CBMEM_ID_MEMINFO:\n"
58 	       "  dimm_size: %u\n"
59 	       "  ddr_type: 0x%hx\n"
60 	       "  ddr_frequency: %hu\n"
61 	       "  rank_per_dimm: %hhu\n"
62 	       "  channel_num: %hhu\n"
63 	       "  dimm_num: %hhu\n"
64 	       "  bank_locator: %hhu\n"
65 	       "  mod_id: %hu\n"
66 	       "  mod_type: 0x%hhx\n"
67 	       "  bus_width: %hhu\n"
68 	       "  serial: %02hhx%02hhx%02hhx%02hhx\n"
69 	       "  module_part_number(%zu): %s\n",
70 	       dimm->dimm_size,
71 	       dimm->ddr_type,
72 	       dimm->ddr_frequency,
73 	       dimm->rank_per_dimm,
74 	       dimm->channel_num,
75 	       dimm->dimm_num,
76 	       dimm->bank_locator,
77 	       dimm->mod_id,
78 	       dimm->mod_type,
79 	       dimm->bus_width,
80 	       dimm->serial[0],
81 	       dimm->serial[1],
82 	       dimm->serial[2],
83 	       dimm->serial[3],
84 	       strlen((char *)dimm->module_part_number),
85 	       (char *)dimm->module_part_number
86 	);
87 }
88 
print_dmi_info(const TYPE17_DMI_INFO * dmi17)89 static void print_dmi_info(const TYPE17_DMI_INFO *dmi17)
90 {
91 	printk(RAM_SPEW,
92 	       "AGESA TYPE 17 DMI INFO:\n"
93 	       "  Handle: %hu\n"
94 	       "  TotalWidth: %hu\n"
95 	       "  DataWidth: %hu\n"
96 	       "  MemorySize: %hu\n"
97 	       "  DeviceSet: %hhu\n"
98 	       "  Speed: %hu\n"
99 	       "  ManufacturerIdCode: %llu\n"
100 	       "  Attributes: %hhu\n"
101 	       "  ExtSize: %u\n"
102 	       "  ConfigSpeed: %hu\n"
103 	       "  MemoryType: 0x%x\n"
104 	       "  FormFactor: 0x%x\n"
105 	       "  DeviceLocator: %8s\n"
106 	       "  BankLocator: %10s\n"
107 	       "  SerialNumber(%zu): %9s\n"
108 	       "  PartNumber(%zu): %19s\n",
109 	       dmi17->Handle,
110 	       dmi17->TotalWidth,
111 	       dmi17->DataWidth,
112 	       dmi17->MemorySize,
113 	       dmi17->DeviceSet,
114 	       dmi17->Speed,
115 	       dmi17->ManufacturerIdCode,
116 	       dmi17->Attributes,
117 	       dmi17->ExtSize,
118 	       dmi17->ConfigSpeed,
119 	       dmi17->MemoryType,
120 	       dmi17->FormFactor,
121 	       dmi17->DeviceLocator,
122 	       dmi17->BankLocator,
123 	       strlen((char *)dmi17->SerialNumber),
124 	       dmi17->SerialNumber,
125 	       strlen((char *)dmi17->PartNumber),
126 	       dmi17->PartNumber
127 	);
128 }
129 
prepare_dmi_17(void * unused)130 static void prepare_dmi_17(void *unused)
131 {
132 	DMI_INFO *DmiTable;
133 	TYPE17_DMI_INFO *address;
134 	struct memory_info *mem_info;
135 	struct dimm_info *dimm;
136 	int i, j, dimm_cnt = 0;
137 
138 	mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(struct memory_info));
139 	if (!mem_info) {
140 		printk(BIOS_NOTICE, "Failed to add memory info to CBMEM.\n");
141 		return;
142 	}
143 	memset(mem_info, 0, sizeof(struct memory_info));
144 
145 	DmiTable = agesawrapper_getlateinitptr(PICK_DMI);
146 	for (i = 0; i < MAX_CHANNELS_PER_SOCKET; i++) {
147 		for (j = 0; j < MAX_DIMMS_PER_CHANNEL; j++) {
148 			address = &DmiTable->T17[0][i][j];
149 			if (address->Handle > 0) {
150 				dimm = &mem_info->dimm[dimm_cnt];
151 				dimm->channel_num = i;
152 				dimm->dimm_num = j;
153 				transfer_memory_info(address, dimm);
154 				print_dmi_info(address);
155 				print_dimm_info(dimm);
156 				dimm_cnt++;
157 			}
158 		}
159 	}
160 	mem_info->dimm_cnt = dimm_cnt;
161 }
162 
163 BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, prepare_dmi_17, NULL);
164 
agesawrapper_post_device(void * unused)165 static void agesawrapper_post_device(void *unused)
166 {
167 	if (acpi_is_wakeup_s3())
168 		return;
169 
170 	do_agesawrapper(AMD_INIT_LATE, "amdinitlate");
171 
172 	if (!acpi_s3_resume_allowed())
173 		return;
174 
175 	do_agesawrapper(AMD_INIT_RTB, "amdinitrtb");
176 }
177 
178 BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, agesawrapper_post_device,
179 		      NULL);
180