Barnali Sarkar (barnali.sarkar@intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18275
-gerrit
commit 1164fb2c5f6dfa7fd6cce6e9ee0f1c13229d5163 Author: Barnali Sarkar barnali.sarkar@intel.com Date: Wed Feb 1 16:25:04 2017 +0530
Kabylake: [WIP] Save Memory Info HOB data in SMBIOS Table
Extract SMBIOS memory information from FSP SMBIOS_MEM_INFO_HOB and save in cbmem. Add the MemInfoHob.h provided by FSP for aid in parsing the HOB.
BUG=chrome-os-partner:61729 BRANCH=none TEST=Build and boot KBLRVP
Change-Id: I593d4ccb0d4866e99913a73c49b2f000b51827d1 Signed-off-by: Barnali Sarkar barnali.sarkar@intel.com Signed-off-by: Rizwan Qureshi rizwan.qureshi@intel.com --- src/soc/intel/skylake/include/fsp20/soc/romstage.h | 5 + src/soc/intel/skylake/romstage/romstage_fsp20.c | 86 ++++++- .../intel/fsp/fsp2_0/skykabylake/MemInfoHob.h | 254 +++++++++++++++++++++ 3 files changed, 344 insertions(+), 1 deletion(-)
diff --git a/src/soc/intel/skylake/include/fsp20/soc/romstage.h b/src/soc/intel/skylake/include/fsp20/soc/romstage.h index 41658e1..3db3a53 100644 --- a/src/soc/intel/skylake/include/fsp20/soc/romstage.h +++ b/src/soc/intel/skylake/include/fsp20/soc/romstage.h @@ -20,11 +20,16 @@ #include <arch/cpu.h> #include <fsp/api.h>
+#pragma pack(push) +#include <MemInfoHob.h> +#pragma pack(pop) + asmlinkage void *car_stage_c_entry(void); void mainboard_memory_init_params(FSPM_UPD *mupd); void systemagent_early_init(void); int smbus_read_byte(unsigned device, unsigned address); int early_spi_read_wpsr(u8 *sr); +void save_dimm_info(void); /* Board type */ enum board_type { BOARD_TYPE_MOBILE = 0, diff --git a/src/soc/intel/skylake/romstage/romstage_fsp20.c b/src/soc/intel/skylake/romstage/romstage_fsp20.c index e478890..175b386 100644 --- a/src/soc/intel/skylake/romstage/romstage_fsp20.c +++ b/src/soc/intel/skylake/romstage/romstage_fsp20.c @@ -26,10 +26,13 @@ #include <device/pci_def.h> #include <fsp/util.h> #include <fsp/memmap.h> +#include <memory_info.h> +#include <smbios.h> #include <soc/msr.h> #include <soc/pci_devs.h> #include <soc/pm.h> #include <soc/romstage.h> +#include <string.h> #include <timestamp.h> #include <vboot/vboot_common.h>
@@ -56,7 +59,7 @@ asmlinkage void *car_stage_c_entry(void) s3wake = ps->prev_sleep_state == ACPI_S3; fsp_memory_init(s3wake); pmc_set_disb(); - + save_dimm_info(); if (postcar_frame_init(&pcf, ROMSTAGE_RAM_STACK_SIZE)) die("Unable to initialize postcar frame.\n");
@@ -187,3 +190,84 @@ __attribute__((weak)) void mainboard_memory_init_params(FSPM_UPD *mupd) { /* Do nothing */ } + +/* Save the DIMM information for SMBIOS table 17 */ +void save_dimm_info(void) +{ + int channel, dimm, dimm_max, index; + size_t hob_size; + const CONTROLLER_INFO *ctrlr_info; + const CHANNEL_INFO *channel_info; + const DIMM_INFO *src_dimm; + struct dimm_info *dest_dimm; + struct memory_info *mem_info; + const MEMORY_INFO_DATA_HOB *memory_info_hob; + + /* Locate the memory info HOB, presence validated by raminit */ + memory_info_hob = fsp_find_smbios_memory_info(&hob_size); + + /* + * 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)); + + /* Describe the first N DIMMs in the system */ + index = 0; + dimm_max = ARRAY_SIZE(mem_info->dimm); + ctrlr_info = &memory_info_hob->Controller[0]; + for (channel = 0; channel < ctrlr_info->ChannelCount; channel++) { + if (index >= dimm_max) + break; + channel_info = &ctrlr_info->Channel[channel]; + for (dimm = 0; dimm < channel_info->DimmCount; dimm++) { + if (index >= dimm_max) + break; + src_dimm = &channel_info->Dimm[dimm]; + dest_dimm = &mem_info->dimm[index]; + + if (!src_dimm->DimmCapacity) + continue; + + /* Populate the DIMM information */ + dest_dimm->dimm_size = src_dimm->DimmCapacity; + dest_dimm->ddr_type = memory_info_hob->DdrType; + dest_dimm->ddr_frequency = + memory_info_hob->Frequency; + dest_dimm->channel_num = channel_info->ChannelId; + dest_dimm->dimm_num = src_dimm->DimmId; + strncpy((char *)dest_dimm->module_part_number, + (char *)src_dimm->ModulePartNum, + sizeof(dest_dimm->module_part_number)); + + switch (memory_info_hob->DataWidth) { + case 8: + dest_dimm->bus_width = MEMORY_BUS_WIDTH_8; + break; + case 16: + dest_dimm->bus_width = MEMORY_BUS_WIDTH_16; + break; + case 32: + dest_dimm->bus_width = MEMORY_BUS_WIDTH_32; + break; + case 64: + dest_dimm->bus_width = MEMORY_BUS_WIDTH_64; + break; + case 128: + dest_dimm->bus_width = MEMORY_BUS_WIDTH_128; + break; + default: + printk(BIOS_ERR, "Incorrect DIMM Data Width"); + } + index++; + } + } + mem_info->dimm_cnt = index; + printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt); +} + diff --git a/src/vendorcode/intel/fsp/fsp2_0/skykabylake/MemInfoHob.h b/src/vendorcode/intel/fsp/fsp2_0/skykabylake/MemInfoHob.h new file mode 100644 index 0000000..bdaf39b --- /dev/null +++ b/src/vendorcode/intel/fsp/fsp2_0/skykabylake/MemInfoHob.h @@ -0,0 +1,254 @@ +/** @file + This file contains definitions required for creation of + Memory S3 Save data, Memory Info data and Memory Platform + data hobs. + + @copyright + INTEL CONFIDENTIAL + Copyright 1999 - 2016 Intel Corporation. + + The source code contained or described herein and all documents related to the + source code ("Material") are owned by Intel Corporation or its suppliers or + licensors. Title to the Material remains with Intel Corporation or its suppliers + and licensors. The Material may contain trade secrets and proprietary and + confidential information of Intel Corporation and its suppliers and licensors, + and is protected by worldwide copyright and trade secret laws and treaty + provisions. No part of the Material may be used, copied, reproduced, modified, + published, uploaded, posted, transmitted, distributed, or disclosed in any way + without Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other intellectual + property right is granted to or conferred upon you by disclosure or delivery + of the Materials, either expressly, by implication, inducement, estoppel or + otherwise. Any license under such intellectual property rights must be + express and approved by Intel in writing. + + Unless otherwise agreed by Intel in writing, you may not remove or alter + this notice or any other notice embedded in Materials by Intel or + Intel's suppliers or licensors in any way. + + This file contains an 'Intel Peripheral Driver' and is uniquely identified as + "Intel Reference Module" and is licensed for Intel CPUs and chipsets under + the terms of your license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the license agreement. + +@par Specification Reference: +**/ +#ifndef _MEM_INFO_HOB_H_ +#define _MEM_INFO_HOB_H_ + +#pragma pack (push, 1) + +extern EFI_GUID gSiMemoryS3DataGuid; +extern EFI_GUID gSiMemoryInfoDataGuid; +extern EFI_GUID gSiMemoryPlatformDataGuid; + +#define MAX_NODE 1 +#define MAX_CH 2 +#define MAX_DIMM 2 + +/// +/// Host reset states from MRC. +/// +#define WARM_BOOT 2 + +#define R_MC_CHNL_RANK_PRESENT 0x7C +#define B_RANK0_PRS BIT0 +#define B_RANK1_PRS BIT1 +#define B_RANK2_PRS BIT4 +#define B_RANK3_PRS BIT5 + +// @todo remove and use the MdePkg\Include\Pi\PiHob.h +#if !defined(_PEI_HOB_H_) && !defined(__PI_HOB_H__) +#ifndef __HOB__H__ +typedef struct _EFI_HOB_GENERIC_HEADER { + UINT16 HobType; + UINT16 HobLength; + UINT32 Reserved; +} EFI_HOB_GENERIC_HEADER; + +typedef struct _EFI_HOB_GUID_TYPE { + EFI_HOB_GENERIC_HEADER Header; + EFI_GUID Name; + /// + /// Guid specific data goes here + /// +} EFI_HOB_GUID_TYPE; +#endif +#endif + +/// +/// Defines taken from MRC so avoid having to include MrcInterface.h +/// + +// +// Matches MAX_SPD_SAVE define in MRC +// +#ifndef MAX_SPD_SAVE +#define MAX_SPD_SAVE 29 +#endif + +// +// MRC version description. +// +typedef struct { + UINT8 Major; ///< Major version number + UINT8 Minor; ///< Minor version number + UINT8 Rev; ///< Revision number + UINT8 Build; ///< Build number +} SiMrcVersion; + +// +// Matches MrcDimmSts enum in MRC +// +#ifndef DIMM_ENABLED +#define DIMM_ENABLED 0 // DIMM/rank Pair is enabled, presence will be detected. +#endif +#ifndef DIMM_DISABLED +#define DIMM_DISABLED 1 // DIMM/rank Pair is disabled, regardless of presence. +#endif +#ifndef DIMM_PRESENT +#define DIMM_PRESENT 2 // There is a DIMM present in the slot/rank pair and it will be used. +#endif +#ifndef DIMM_NOT_PRESENT +#define DIMM_NOT_PRESENT 3 // There is no DIMM present in the slot/rank pair. +#endif + +// +// Matches MrcBootMode enum in MRC +// +#ifndef bmCold +#define bmCold 0 // Cold boot +#endif +#ifndef bmWarm +#define bmWarm 1 // Warm boot +#endif +#ifndef bmS3 +#define bmS3 2 // S3 resume +#endif +#ifndef bmFast +#define bmFast 3 // Fast boot +#endif + +// +// Matches MrcDdrType enum in MRC +// +#ifndef MRC_DDR_TYPE_DDR4 +#define MRC_DDR_TYPE_DDR4 0 +#endif +#ifndef MRC_DDR_TYPE_DDR3 +#define MRC_DDR_TYPE_DDR3 1 +#endif +#ifndef MRC_DDR_TYPE_LPDDR3 +#define MRC_DDR_TYPE_LPDDR3 2 +#endif +#ifndef MRC_DDR_TYPE_UNKNOWN +#define MRC_DDR_TYPE_UNKNOWN 3 +#endif + +#define MAX_PROFILE_NUM 4 // number of memory profiles supported +#define MAX_XMP_PROFILE_NUM 2 // number of XMP profiles supported + +// +// DIMM timings +// +typedef struct { + UINT32 tCK; ///< Memory cycle time, in femtoseconds. + UINT16 NMode; ///< Number of tCK cycles for the channel DIMM's command rate mode. + UINT16 tCL; ///< Number of tCK cycles for the channel DIMM's CAS latency. + UINT16 tCWL; ///< Number of tCK cycles for the channel DIMM's minimum CAS write latency time. + UINT16 tFAW; ///< Number of tCK cycles for the channel DIMM's minimum four activate window delay time. + UINT16 tRAS; ///< Number of tCK cycles for the channel DIMM's minimum active to precharge delay time. + UINT16 tRCDtRP; ///< Number of tCK cycles for the channel DIMM's minimum RAS# to CAS# delay time and Row Precharge delay time. + UINT16 tREFI; ///< Number of tCK cycles for the channel DIMM's minimum Average Periodic Refresh Interval. + UINT16 tRFC; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time. + UINT16 tRFC2; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time. + UINT16 tRFC4; ///< Number of tCK cycles for the channel DIMM's minimum refresh recovery delay time. + UINT16 tRPab; ///< Number of tCK cycles for the channel DIMM's minimum row precharge delay time for all banks. + UINT16 tRRD; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time. + UINT16 tRRD_L; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for same bank groups. + UINT16 tRRD_S; ///< Number of tCK cycles for the channel DIMM's minimum row active to row active delay time for different bank groups. + UINT16 tRTP; ///< Number of tCK cycles for the channel DIMM's minimum internal read to precharge command delay time. + UINT16 tWR; ///< Number of tCK cycles for the channel DIMM's minimum write recovery time. + UINT16 tWTR; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time. + UINT16 tWTR_L; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for same bank groups. + UINT16 tWTR_S; ///< Number of tCK cycles for the channel DIMM's minimum internal write to read command delay time for different bank groups. +} MRC_CH_TIMING; + +/// +/// Memory SMBIOS & OC Memory Data Hob +/// +typedef struct { + UINT8 Status; ///< See MrcDimmStatus for the definition of this field. + UINT8 DimmId; + UINT32 DimmCapacity; ///< DIMM size in MBytes. + UINT16 MfgId; + UINT8 ModulePartNum[20]; ///< Module part number for DDR3 is 18 bytes however for DRR4 20 bytes as per JEDEC Spec, so reserving 20 bytes + UINT8 RankInDimm; ///< The number of ranks in this DIMM. + UINT8 SpdDramDeviceType; ///< Save SPD DramDeviceType information needed for SMBIOS structure creation. + UINT8 SpdModuleType; ///< Save SPD ModuleType information needed for SMBIOS structure creation. + UINT8 SpdModuleMemoryBusWidth; ///< Save SPD ModuleMemoryBusWidth information needed for SMBIOS structure creation. + UINT8 SpdSave[MAX_SPD_SAVE]; ///< Save SPD Manufacturing information needed for SMBIOS structure creation. +} DIMM_INFO; + +typedef struct { + UINT8 Status; ///< Indicates whether this channel should be used. + UINT8 ChannelId; + UINT8 DimmCount; ///< Number of valid DIMMs that exist in the channel. + MRC_CH_TIMING Timing[MAX_PROFILE_NUM]; ///< The channel timing values. + DIMM_INFO Dimm[MAX_DIMM]; ///< Save the DIMM output characteristics. +} CHANNEL_INFO; + +typedef struct { + UINT8 Status; ///< Indicates whether this controller should be used. + UINT16 DeviceId; ///< The PCI device id of this memory controller. + UINT8 RevisionId; ///< The PCI revision id of this memory controller. + UINT8 ChannelCount; ///< Number of valid channels that exist on the controller. + CHANNEL_INFO Channel[MAX_CH]; ///< The following are channel level definitions. +} CONTROLLER_INFO; + +typedef struct { + EFI_HOB_GUID_TYPE EfiHobGuidType; + UINT8 Revision; + UINT16 DataWidth; + /** As defined in SMBIOS 3.0 spec + Section 7.18.2 and Table 75 + **/ + UINT8 DdrType; ///< DDR type: DDR3, DDR4, or LPDDR3 + UINT32 Frequency; ///< The system's common memory controller frequency in MT/s. + /** As defined in SMBIOS 3.0 spec + Section 7.17.3 and Table 72 + **/ + UINT8 ErrorCorrectionType; + + SiMrcVersion Version; + UINT32 FreqMax; + BOOLEAN EccSupport; + UINT8 MemoryProfile; + UINT32 TotalPhysicalMemorySize; + UINT32 DefaultXmptCK[MAX_XMP_PROFILE_NUM]; // Stores the tCK value read from SPD XMP profiles if they exist. + UINT8 XmpProfileEnable; // If XMP capable DIMMs are detected, this will indicate which XMP Profiles are common among all DIMMs. + UINT8 Ratio; + UINT8 RefClk; + UINT32 VddVoltage[MAX_PROFILE_NUM]; + CONTROLLER_INFO Controller[MAX_NODE]; +} MEMORY_INFO_DATA_HOB; + +/// +/// Memory Platform Data Hob +/// +typedef struct { + UINT8 Revision; + UINT8 Reserved[3]; + UINT32 BootMode; + UINT32 TsegSize; +} MEMORY_PLATFORM_DATA; + +typedef struct { + EFI_HOB_GUID_TYPE EfiHobGuidType; + MEMORY_PLATFORM_DATA Data; + UINT8 *Buffer; +} MEMORY_PLATFORM_DATA_HOB; +#pragma pack (pop) + +#endif // _MEM_INFO_HOB_H_