soc/intel/xeon_sp/cpx: Add save_dimm_info for SMBIOS type 17
For now only implement for one socket and some of the fields are hard-coded for DDR4 including memory device type, data width and ECC support. Change-Id: I3cb72d18027d972140828970206834ff55b72022 Signed-off-by: Johnny Lin <johnny_lin@wiwynn.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/45798 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Jonathan Zhang <jonzhang@fb.com> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
@@ -8,7 +8,7 @@ subdirs-y += ../../../../cpu/x86/mtrr
|
||||
subdirs-y += ../../../../cpu/x86/tsc
|
||||
subdirs-y += ../../../../cpu/intel/microcode
|
||||
|
||||
romstage-y += romstage.c
|
||||
romstage-y += romstage.c ddr.c
|
||||
romstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c
|
||||
romstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c
|
||||
|
||||
|
84
src/soc/intel/xeon_sp/cpx/ddr.c
Normal file
84
src/soc/intel/xeon_sp/cpx/ddr.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <soc/ddr.h>
|
||||
|
||||
uint32_t get_ddr_voltage(uint8_t DdrVoltage)
|
||||
{
|
||||
/* SPD Byte 11: Module Nominal Voltage, currently DDR4 only supports 1.2V.
|
||||
Either Bit 0 or Bit 1 is set, return 1.2V */
|
||||
if (DdrVoltage & 0x3)
|
||||
return 1200;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t get_max_memory_speed(uint32_t commonTck)
|
||||
{
|
||||
if (commonTck <= DDR_8400_TCK_MIN)
|
||||
return 8400;
|
||||
else if (commonTck <= DDR_6400_TCK_MIN)
|
||||
return 6400;
|
||||
else if (commonTck <= DDR_6000_TCK_MIN)
|
||||
return 6000;
|
||||
else if (commonTck <= DDR_5600_TCK_MIN)
|
||||
return 5600;
|
||||
else if (commonTck <= DDR_5200_TCK_MIN)
|
||||
return 5200;
|
||||
else if (commonTck <= DDR_4800_TCK_MIN)
|
||||
return 4800;
|
||||
else if (commonTck <= DDR_4400_TCK_MIN)
|
||||
return 4400;
|
||||
else if (commonTck <= DDR_4266_TCK_MIN)
|
||||
return 4266;
|
||||
else if (commonTck <= DDR_4200_TCK_MIN)
|
||||
return 4200;
|
||||
else if (commonTck <= DDR_4000_TCK_MIN)
|
||||
return 4000;
|
||||
else if (commonTck <= DDR_3800_TCK_MIN)
|
||||
return 3800;
|
||||
else if (commonTck <= DDR_3733_TCK_MIN)
|
||||
return 3733;
|
||||
else if (commonTck <= DDR_3600_TCK_MIN)
|
||||
return 3600;
|
||||
else if (commonTck <= DDR_3466_TCK_MIN)
|
||||
return 3466;
|
||||
else if (commonTck <= DDR_3400_TCK_MIN)
|
||||
return 3400;
|
||||
else if (commonTck <= DDR_3200_TCK_MIN)
|
||||
return 3200;
|
||||
else if (commonTck <= DDR_3000_TCK_MIN)
|
||||
return 3000;
|
||||
else if (commonTck <= DDR_2933_TCK_MIN)
|
||||
return 2933;
|
||||
else if (commonTck <= DDR_2800_TCK_MIN)
|
||||
return 2800;
|
||||
else if (commonTck <= DDR_2666_TCK_MIN)
|
||||
return 2666;
|
||||
else if (commonTck <= DDR_2600_TCK_MIN)
|
||||
return 2600;
|
||||
else if (commonTck <= DDR_2400_TCK_MIN)
|
||||
return 2400;
|
||||
else if (commonTck <= DDR_2200_TCK_MIN)
|
||||
return 2200;
|
||||
else if (commonTck <= DDR_2133_TCK_MIN)
|
||||
return 2133;
|
||||
else if (commonTck <= DDR_2000_TCK_MIN)
|
||||
return 2000;
|
||||
else if (commonTck <= DDR_1866_TCK_MIN)
|
||||
return 1866;
|
||||
else if (commonTck <= DDR_1800_TCK_MIN)
|
||||
return 1800;
|
||||
else if (commonTck <= DDR_1600_TCK_MIN)
|
||||
return 1600;
|
||||
else if (commonTck <= DDR_1400_TCK_MIN)
|
||||
return 1400;
|
||||
else if (commonTck <= DDR_1333_TCK_MIN)
|
||||
return 1333;
|
||||
else if (commonTck <= DDR_1200_TCK_MIN)
|
||||
return 1200;
|
||||
else if (commonTck <= DDR_1066_TCK_MIN)
|
||||
return 1066;
|
||||
else if (commonTck <= DDR_1000_TCK_MIN)
|
||||
return 1000;
|
||||
else
|
||||
return 800;
|
||||
}
|
51
src/soc/intel/xeon_sp/cpx/include/soc/ddr.h
Normal file
51
src/soc/intel/xeon_sp/cpx/include/soc/ddr.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef _CPX_DDR_H_
|
||||
#define _CPX_DDR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* DDR_*_TCK_MIN are in picoseconds */
|
||||
#define DDR_800_TCK_MIN 2500
|
||||
#define DDR_1000_TCK_MIN 2000
|
||||
#define DDR_1066_TCK_MIN 1875
|
||||
#define DDR_1200_TCK_MIN 1667
|
||||
#define DDR_1333_TCK_MIN 1500
|
||||
#define DDR_1400_TCK_MIN 1429
|
||||
#define DDR_1600_TCK_MIN 1250
|
||||
#define DDR_1800_TCK_MIN 1110
|
||||
#define DDR_1866_TCK_MIN 1071
|
||||
#define DDR_2000_TCK_MIN 1000
|
||||
#define DDR_2133_TCK_MIN 938
|
||||
#define DDR_2200_TCK_MIN 909
|
||||
#define DDR_2400_TCK_MIN 833
|
||||
#define DDR_2600_TCK_MIN 769
|
||||
#define DDR_2666_TCK_MIN 750
|
||||
#define DDR_2800_TCK_MIN 714
|
||||
#define DDR_2933_TCK_MIN 682
|
||||
#define DDR_3000_TCK_MIN 667
|
||||
#define DDR_3200_TCK_MIN 625
|
||||
#define DDR_3400_TCK_MIN 589
|
||||
#define DDR_3466_TCK_MIN 577
|
||||
#define DDR_3600_TCK_MIN 556
|
||||
#define DDR_3733_TCK_MIN 536
|
||||
#define DDR_3800_TCK_MIN 527
|
||||
#define DDR_4000_TCK_MIN 500
|
||||
#define DDR_4200_TCK_MIN 477
|
||||
#define DDR_4266_TCK_MIN 469
|
||||
#define DDR_4400_TCK_MIN 455
|
||||
#define DDR_4800_TCK_MIN 417
|
||||
#define DDR_5200_TCK_MIN 385
|
||||
#define DDR_5600_TCK_MIN 358
|
||||
#define DDR_6000_TCK_MIN 334
|
||||
#define DDR_6400_TCK_MIN 313
|
||||
#define DDR_6800_TCK_MIN 295
|
||||
#define DDR_7200_TCK_MIN 278
|
||||
#define DDR_7600_TCK_MIN 264
|
||||
#define DDR_8000_TCK_MIN 250
|
||||
#define DDR_8400_TCK_MIN 239
|
||||
|
||||
uint16_t get_max_memory_speed(uint32_t commonTck);
|
||||
uint32_t get_ddr_voltage(uint8_t DdrVoltage);
|
||||
|
||||
#endif /* _CPX_DDR_H_ */
|
@@ -1,9 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <assert.h>
|
||||
#include <arch/romstage.h>
|
||||
#include <console/console.h>
|
||||
#include <cbmem.h>
|
||||
#include <fsp/api.h>
|
||||
#include <fsp/util.h>
|
||||
#include <hob_iiouds.h>
|
||||
#include <hob_memmap.h>
|
||||
#include <soc/ddr.h>
|
||||
#include <soc/romstage.h>
|
||||
#include <soc/pci_devs.h>
|
||||
#include <soc/intel/common/smbios.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
void __weak mainboard_memory_init_params(FSPM_UPD *mupd)
|
||||
@@ -11,6 +21,86 @@ void __weak mainboard_memory_init_params(FSPM_UPD *mupd)
|
||||
/* Default weak implementation */
|
||||
}
|
||||
|
||||
static const struct SystemMemoryMapHob *get_system_memory_map(void)
|
||||
{
|
||||
size_t hob_size;
|
||||
const uint8_t mem_hob_guid[16] = FSP_SYSTEM_MEMORYMAP_HOB_GUID;
|
||||
const struct SystemMemoryMapHob **memmap_addr;
|
||||
|
||||
memmap_addr = (const struct SystemMemoryMapHob **)
|
||||
fsp_find_extension_hob_by_guid(mem_hob_guid, &hob_size);
|
||||
/* hob_size is the size of the 8-byte address not the hob data */
|
||||
assert(memmap_addr != NULL && hob_size != 0);
|
||||
/* assert the pointer to the hob is not NULL */
|
||||
assert(*memmap_addr != NULL);
|
||||
|
||||
return *memmap_addr;
|
||||
}
|
||||
|
||||
/* Save the DIMM information for SMBIOS table 17 */
|
||||
void save_dimm_info(void)
|
||||
{
|
||||
struct dimm_info *dest_dimm;
|
||||
struct memory_info *mem_info;
|
||||
const struct SystemMemoryMapHob *hob;
|
||||
MEMMAP_DIMM_DEVICE_INFO_STRUCT src_dimm;
|
||||
int dimm_max, index = 0;
|
||||
uint32_t vdd_voltage;
|
||||
|
||||
hob = get_system_memory_map();
|
||||
assert(hob != NULL);
|
||||
|
||||
/*
|
||||
* Allocate CBMEM area for DIMM information used to populate SMBIOS
|
||||
* table 17
|
||||
*/
|
||||
mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
|
||||
if (mem_info == NULL) {
|
||||
printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n");
|
||||
return;
|
||||
}
|
||||
memset(mem_info, 0, sizeof(*mem_info));
|
||||
dimm_max = ARRAY_SIZE(mem_info->dimm);
|
||||
vdd_voltage = get_ddr_voltage(hob->DdrVoltage);
|
||||
/* For now only implement for one socket and hard-coded for DDR4 */
|
||||
for (int ch = 0; ch < MAX_CH; ch++) {
|
||||
for (int dimm = 0; dimm < MAX_IMC; dimm++) {
|
||||
src_dimm = hob->Socket[0].ChannelInfo[ch].DimmInfo[dimm];
|
||||
if (src_dimm.Present) {
|
||||
if (index >= dimm_max) {
|
||||
printk(BIOS_WARNING, "Too many DIMMs info for %s.\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
dest_dimm = &mem_info->dimm[index];
|
||||
dest_dimm->max_speed_mts =
|
||||
get_max_memory_speed(src_dimm.commonTck);
|
||||
dest_dimm->configured_speed_mts = hob->memFreq;
|
||||
dimm_info_fill(dest_dimm,
|
||||
src_dimm.DimmSize << 6,
|
||||
0x1a, /* hard-coded memory device type as DDR4 */
|
||||
hob->memFreq, /* replaced by configured_speed_mts */
|
||||
src_dimm.NumRanks,
|
||||
ch, /* for mainboard locator string override */
|
||||
dimm, /* for mainboard locator string override */
|
||||
(const char *)&src_dimm.PartNumber[0],
|
||||
sizeof(src_dimm.PartNumber),
|
||||
(const uint8_t *)&src_dimm.serialNumber[0],
|
||||
64, /* hard-coded for DDR4 data width */
|
||||
vdd_voltage,
|
||||
true, /* hard-coded as ECC supported */
|
||||
src_dimm.VendorID,
|
||||
src_dimm.actKeyByte2);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Save available DIMM information */
|
||||
mem_info->dimm_cnt = index;
|
||||
printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt);
|
||||
}
|
||||
|
||||
void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)
|
||||
{
|
||||
FSPM_CONFIG *m_cfg = &mupd->FspmConfig;
|
||||
|
@@ -8,5 +8,5 @@
|
||||
/* These functions are weak and can be overridden by a mainboard functions. */
|
||||
void mainboard_memory_init_params(FSPM_UPD * mupd);
|
||||
void mainboard_rtc_failed(void);
|
||||
|
||||
void save_dimm_info(void);
|
||||
#endif /* _SOC_ROMSTAGE_H_ */
|
||||
|
@@ -41,7 +41,7 @@ asmlinkage void car_stage_entry(void)
|
||||
|
||||
/* Cache the memory-mapped boot media. */
|
||||
postcar_frame_add_romcache(&pcf, MTRR_TYPE_WRPROT);
|
||||
|
||||
save_dimm_info();
|
||||
run_postcar_phase(&pcf);
|
||||
}
|
||||
|
||||
@@ -54,3 +54,4 @@ __weak void mainboard_rtc_failed(void)
|
||||
{
|
||||
|
||||
}
|
||||
__weak void save_dimm_info(void) { }
|
||||
|
Reference in New Issue
Block a user