blob: 6cdae6b5ab40c1fa2b5fdd332462039c822e1394 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
/* This file is part of the coreboot project. */
#include <arch/acpi.h>
#include <bootstate.h>
#include <cbmem.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <dimm_info_util.h>
#include <memory_info.h>
#include <lib.h>
#include <string.h>
#include <amdblocks/agesawrapper.h>
#include <amdblocks/agesawrapper_call.h>
/**
* Populate dimm_info using AGESA TYPE17_DMI_INFO.
*/
static void transfer_memory_info(TYPE17_DMI_INFO *dmi17,
struct dimm_info *dimm)
{
hexstrtobin(dmi17->SerialNumber, dimm->serial, sizeof(dimm->serial));
dimm->dimm_size =
smbios_memory_size_to_mib(dmi17->MemorySize, dmi17->ExtSize);
dimm->ddr_type = dmi17->MemoryType;
/*
* dimm_info uses ddr_frequency for setting both config speed and max
* speed. Lets use config speed so we don't get the false impression
* that the RAM is running faster than it actually is.
*/
dimm->ddr_frequency = dmi17->ConfigSpeed;
dimm->rank_per_dimm = dmi17->Attributes;
dimm->mod_type = smbios_form_factor_to_spd_mod_type(dmi17->FormFactor);
dimm->bus_width =
smbios_bus_width_to_spd_width(dmi17->TotalWidth, dmi17->DataWidth);
dimm->mod_id = dmi17->ManufacturerIdCode;
dimm->bank_locator = 0;
strncpy((char *)dimm->module_part_number, dmi17->PartNumber,
sizeof(dimm->module_part_number) - 1);
}
static void print_dimm_info(const struct dimm_info *dimm)
{
printk(RAM_SPEW,
"CBMEM_ID_MEMINFO:\n"
" dimm_size: %u\n"
" ddr_type: 0x%hx\n"
" ddr_frequency: %hu\n"
" rank_per_dimm: %hhu\n"
" channel_num: %hhu\n"
" dimm_num: %hhu\n"
" bank_locator: %hhu\n"
" mod_id: %hu\n"
" mod_type: 0x%hhx\n"
" bus_width: %hhu\n"
" serial: %02hhx%02hhx%02hhx%02hhx\n"
" module_part_number(%zu): %s\n",
dimm->dimm_size,
dimm->ddr_type,
dimm->ddr_frequency,
dimm->rank_per_dimm,
dimm->channel_num,
dimm->dimm_num,
dimm->bank_locator,
dimm->mod_id,
dimm->mod_type,
dimm->bus_width,
dimm->serial[0],
dimm->serial[1],
dimm->serial[2],
dimm->serial[3],
strlen((char *) dimm->module_part_number),
(char *) dimm->module_part_number
);
}
static void print_dmi_info(const TYPE17_DMI_INFO *dmi17)
{
printk(RAM_SPEW,
"AGESA TYPE 17 DMI INFO:\n"
" Handle: %hu\n"
" TotalWidth: %hu\n"
" DataWidth: %hu\n"
" MemorySize: %hu\n"
" DeviceSet: %hhu\n"
" Speed: %hu\n"
" ManufacturerIdCode: %llu\n"
" Attributes: %hhu\n"
" ExtSize: %u\n"
" ConfigSpeed: %hu\n"
" MemoryType: 0x%x\n"
" FormFactor: 0x%x\n"
" DeviceLocator: %8s\n"
" BankLocator: %10s\n"
" SerialNumber(%zu): %9s\n"
" PartNumber(%zu): %19s\n",
dmi17->Handle,
dmi17->TotalWidth,
dmi17->DataWidth,
dmi17->MemorySize,
dmi17->DeviceSet,
dmi17->Speed,
dmi17->ManufacturerIdCode,
dmi17->Attributes,
dmi17->ExtSize,
dmi17->ConfigSpeed,
dmi17->MemoryType,
dmi17->FormFactor,
dmi17->DeviceLocator,
dmi17->BankLocator,
strlen((char *) dmi17->SerialNumber),
dmi17->SerialNumber,
strlen((char *) dmi17->PartNumber),
dmi17->PartNumber
);
}
static void prepare_dmi_17(void *unused)
{
DMI_INFO *DmiTable;
TYPE17_DMI_INFO *address;
struct memory_info *mem_info;
struct dimm_info *dimm;
int i, j, dimm_cnt = 0;
mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(struct memory_info));
if (!mem_info) {
printk(BIOS_NOTICE, "Failed to add memory info to CBMEM.\n");
return;
}
memset(mem_info, 0, sizeof(struct memory_info));
DmiTable = agesawrapper_getlateinitptr(PICK_DMI);
for (i = 0; i < MAX_CHANNELS_PER_SOCKET; i++) {
for (j = 0; j < MAX_DIMMS_PER_CHANNEL; j++) {
address = &DmiTable->T17[0][i][j];
if (address->Handle > 0) {
dimm = &mem_info->dimm[dimm_cnt];
dimm->channel_num = i;
dimm->dimm_num = j;
transfer_memory_info(address, dimm);
print_dmi_info(address);
print_dimm_info(dimm);
dimm_cnt++;
}
}
}
mem_info->dimm_cnt = dimm_cnt;
}
BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, prepare_dmi_17, NULL);
static void agesawrapper_post_device(void *unused)
{
if (acpi_is_wakeup_s3())
return;
do_agesawrapper(AMD_INIT_LATE, "amdinitlate");
if (!acpi_s3_resume_allowed())
return;
do_agesawrapper(AMD_INIT_RTB, "amdinitrtb");
}
BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, agesawrapper_post_device,
NULL);