1 /* SPDX-License-Identifier: GPL-2.0-only */
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>
14 #include <amdblocks/agesawrapper.h>
15 #include <amdblocks/agesawrapper_call.h>
18 * Populate dimm_info using AGESA TYPE17_DMI_INFO.
20 static void transfer_memory_info(TYPE17_DMI_INFO
*dmi17
,
21 struct dimm_info
*dimm
)
23 hexstrtobin(dmi17
->SerialNumber
, dimm
->serial
, sizeof(dimm
->serial
));
26 smbios_memory_size_to_mib(dmi17
->MemorySize
, dmi17
->ExtSize
);
28 dimm
->ddr_type
= dmi17
->MemoryType
;
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.
35 dimm
->ddr_frequency
= dmi17
->ConfigSpeed
;
37 dimm
->rank_per_dimm
= dmi17
->Attributes
;
39 dimm
->mod_type
= smbios_form_factor_to_spd_mod_type(
40 (smbios_memory_type
)dmi17
->MemoryType
,
41 (smbios_memory_form_factor
)dmi17
->FormFactor
);
43 dimm
->bus_width
= smbios_bus_width_to_spd_width(dmi17
->MemoryType
, dmi17
->TotalWidth
,
46 dimm
->mod_id
= dmi17
->ManufacturerIdCode
;
48 dimm
->bank_locator
= 0;
50 strncpy((char *)dimm
->module_part_number
, dmi17
->PartNumber
,
51 sizeof(dimm
->module_part_number
) - 1);
54 static void print_dimm_info(const struct dimm_info
*dimm
)
60 " ddr_frequency: %hu\n"
61 " rank_per_dimm: %hhu\n"
62 " channel_num: %hhu\n"
64 " bank_locator: %hhu\n"
68 " serial: %02hhx%02hhx%02hhx%02hhx\n"
69 " module_part_number(%zu): %s\n",
84 strlen((char *)dimm
->module_part_number
),
85 (char *)dimm
->module_part_number
89 static void print_dmi_info(const TYPE17_DMI_INFO
*dmi17
)
92 "AGESA TYPE 17 DMI INFO:\n"
99 " ManufacturerIdCode: %llu\n"
100 " Attributes: %hhu\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",
115 dmi17
->ManufacturerIdCode
,
121 dmi17
->DeviceLocator
,
123 strlen((char *)dmi17
->SerialNumber
),
125 strlen((char *)dmi17
->PartNumber
),
130 static void prepare_dmi_17(void *unused
)
133 TYPE17_DMI_INFO
*address
;
134 struct memory_info
*mem_info
;
135 struct dimm_info
*dimm
;
136 int i
, j
, dimm_cnt
= 0;
138 mem_info
= cbmem_add(CBMEM_ID_MEMINFO
, sizeof(struct memory_info
));
140 printk(BIOS_NOTICE
, "Failed to add memory info to CBMEM.\n");
143 memset(mem_info
, 0, sizeof(struct memory_info
));
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
;
153 transfer_memory_info(address
, dimm
);
154 print_dmi_info(address
);
155 print_dimm_info(dimm
);
160 mem_info
->dimm_cnt
= dimm_cnt
;
163 BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES
, BS_ON_ENTRY
, prepare_dmi_17
, NULL
);
165 static void agesawrapper_post_device(void *unused
)
167 if (acpi_is_wakeup_s3())
170 do_agesawrapper(AMD_INIT_LATE
, "amdinitlate");
172 if (!acpi_s3_resume_allowed())
175 do_agesawrapper(AMD_INIT_RTB
, "amdinitrtb");
178 BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE
, BS_ON_EXIT
, agesawrapper_post_device
,