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/x86/tsc
|
||||||
subdirs-y += ../../../../cpu/intel/microcode
|
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_UPD_DATA) += upd_display.c
|
||||||
romstage-$(CONFIG_DISPLAY_HOBS) += hob_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 */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <arch/romstage.h>
|
#include <arch/romstage.h>
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <cbmem.h>
|
||||||
#include <fsp/api.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/romstage.h>
|
||||||
#include <soc/pci_devs.h>
|
#include <soc/pci_devs.h>
|
||||||
|
#include <soc/intel/common/smbios.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "chip.h"
|
#include "chip.h"
|
||||||
|
|
||||||
void __weak mainboard_memory_init_params(FSPM_UPD *mupd)
|
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 */
|
/* 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)
|
void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)
|
||||||
{
|
{
|
||||||
FSPM_CONFIG *m_cfg = &mupd->FspmConfig;
|
FSPM_CONFIG *m_cfg = &mupd->FspmConfig;
|
||||||
|
@@ -8,5 +8,5 @@
|
|||||||
/* These functions are weak and can be overridden by a mainboard functions. */
|
/* These functions are weak and can be overridden by a mainboard functions. */
|
||||||
void mainboard_memory_init_params(FSPM_UPD * mupd);
|
void mainboard_memory_init_params(FSPM_UPD * mupd);
|
||||||
void mainboard_rtc_failed(void);
|
void mainboard_rtc_failed(void);
|
||||||
|
void save_dimm_info(void);
|
||||||
#endif /* _SOC_ROMSTAGE_H_ */
|
#endif /* _SOC_ROMSTAGE_H_ */
|
||||||
|
@@ -41,7 +41,7 @@ asmlinkage void car_stage_entry(void)
|
|||||||
|
|
||||||
/* Cache the memory-mapped boot media. */
|
/* Cache the memory-mapped boot media. */
|
||||||
postcar_frame_add_romcache(&pcf, MTRR_TYPE_WRPROT);
|
postcar_frame_add_romcache(&pcf, MTRR_TYPE_WRPROT);
|
||||||
|
save_dimm_info();
|
||||||
run_postcar_phase(&pcf);
|
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