soc/intel/xeon_sp: Share save_dimm_info among Xeon-SP SoCs
TEST=Build and boot on archercity CRB No changes in boot log and 'dmidecode' result under centos TEST=Build and boot on avenuecity CRB It will add DMI type 16,17,19,20 Change-Id: I2f5b7a4ffabed033d54d4724b3c41246503166fe Signed-off-by: Jincheng Li <jincheng.li@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/83325 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
		
				
					committed by
					
						 Lean Sheng Tan
						Lean Sheng Tan
					
				
			
			
				
	
			
			
			
						parent
						
							dc8123a775
						
					
				
				
					commit
					c19e32e69d
				
			| @@ -6,6 +6,7 @@ subdirs-y += ../../../../cpu/intel/turbo | ||||
| subdirs-y += ../../../../cpu/intel/microcode | ||||
|  | ||||
| romstage-y += romstage.c soc_util.c | ||||
| romstage-y += ../dimm.c | ||||
| romstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c | ||||
| romstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c | ||||
|  | ||||
|   | ||||
| @@ -22,7 +22,7 @@ void __weak mainboard_memory_init_params(FSPM_UPD *mupd) | ||||
| 	/* Default weak implementation */ | ||||
| } | ||||
|  | ||||
| static uint8_t get_error_correction_type(const uint8_t RasModesEnabled) | ||||
| uint8_t get_error_correction_type(const uint8_t RasModesEnabled) | ||||
| { | ||||
| 	switch (RasModesEnabled) { | ||||
| 	case CH_INDEPENDENT: | ||||
| @@ -41,85 +41,6 @@ static uint8_t get_error_correction_type(const uint8_t RasModesEnabled) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* 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, num_dimms = 0; | ||||
| 	uint32_t vdd_voltage; | ||||
|  | ||||
| 	hob = get_system_memory_map(); | ||||
| 	assert(hob); | ||||
|  | ||||
| 	/* | ||||
| 	 * 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) { | ||||
| 		printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n"); | ||||
| 		return; | ||||
| 	} | ||||
| 	memset(mem_info, 0, sizeof(*mem_info)); | ||||
| 	/* According to Dear Customer Letter it's 1.12 TB per processor. */ | ||||
| 	mem_info->max_capacity_mib = 1.12 * MiB * CONFIG_MAX_SOCKET; | ||||
| 	mem_info->number_of_devices = CONFIG_DIMM_MAX; | ||||
| 	mem_info->ecc_type = get_error_correction_type(hob->RasModesEnabled); | ||||
| 	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]; | ||||
| 				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, | ||||
| 					0, | ||||
| 					get_max_memory_speed(src_dimm.commonTck)); | ||||
| 				index++; | ||||
| 				num_dimms++; | ||||
| 			} else if (mainboard_dimm_slot_exists(0, ch, dimm)) { | ||||
| 				if (index >= dimm_max) { | ||||
| 					printk(BIOS_WARNING, "Too many DIMMs info for %s.\n", | ||||
| 						__func__); | ||||
| 					return; | ||||
| 				} | ||||
| 				dest_dimm = &mem_info->dimm[index]; | ||||
| 				dest_dimm->dimm_size = 0; | ||||
| 				dest_dimm->channel_num = ch; | ||||
| 				dest_dimm->dimm_num = dimm; | ||||
| 				index++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Save available DIMM slot information */ | ||||
| 	mem_info->dimm_cnt = index; | ||||
| 	printk(BIOS_DEBUG, "%d out of %d DIMMs found\n", num_dimms, mem_info->dimm_cnt); | ||||
| } | ||||
|  | ||||
| void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) | ||||
| { | ||||
| 	FSP_M_CONFIG *m_cfg = &mupd->FspmConfig; | ||||
| @@ -188,3 +109,19 @@ void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) | ||||
| 	/* Adjust the "cold boot required" flag in CMOS. */ | ||||
| 	soc_set_mrc_cold_boot_flag(!mupd->FspmArchUpd.NvsBufferPtr); | ||||
| } | ||||
|  | ||||
| uint32_t get_max_capacity_mib(void) | ||||
| { | ||||
| 	/* According to Dear Customer Letter it's 1.12 TB per processor. */ | ||||
| 	return 1.12 * MiB * CONFIG_MAX_SOCKET; | ||||
| } | ||||
|  | ||||
| uint8_t get_max_dimm_count(void) | ||||
| { | ||||
| 	return MAX_IMC; | ||||
| } | ||||
|  | ||||
| uint8_t get_dram_type(const struct SystemMemoryMapHob *hob) | ||||
| { | ||||
| 	return MEMORY_TYPE_DDR4; | ||||
| } | ||||
|   | ||||
							
								
								
									
										88
									
								
								src/soc/intel/xeon_sp/dimm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/soc/intel/xeon_sp/dimm.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||
|  | ||||
| #include <console/console.h> | ||||
| #include <smbios.h> | ||||
| #include <soc/ddr.h> | ||||
| #include <soc/intel/common/smbios.h> | ||||
| #include <soc/romstage.h> | ||||
| #include <soc/util.h> | ||||
| #include <spd.h> | ||||
|  | ||||
| void save_dimm_info(void) | ||||
| { | ||||
| 	const struct SystemMemoryMapHob *hob = get_system_memory_map(); | ||||
| 	assert(hob != NULL); | ||||
|  | ||||
| 	/* | ||||
| 	 * Allocate CBMEM area for DIMM information used to populate SMBIOS | ||||
| 	 * table 17 | ||||
| 	 */ | ||||
| 	struct memory_info *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)); | ||||
| 	mem_info->max_capacity_mib = get_max_capacity_mib(); | ||||
| 	mem_info->number_of_devices = CONFIG_DIMM_MAX; | ||||
| 	mem_info->ecc_type = get_error_correction_type(hob->RasModesEnabled); | ||||
| 	int dimm_max = ARRAY_SIZE(mem_info->dimm); | ||||
|  | ||||
| 	uint32_t vdd_voltage = get_ddr_millivolt(hob->DdrVoltage); | ||||
|  | ||||
| 	int slot_index = 0; | ||||
| 	const int max_dimm_count = get_max_dimm_count(); | ||||
| 	int dimm_num = 0; | ||||
| 	for (int skt = 0; skt < CONFIG_MAX_SOCKET; skt++) { | ||||
| 		for (int ch = 0; ch < MAX_CH; ch++) { | ||||
| 			for (int dimm = 0; dimm < max_dimm_count; dimm++) { | ||||
| 				if (slot_index >= dimm_max) { | ||||
| 					printk(BIOS_WARNING, "Too many DIMMs info for %s.\n", | ||||
| 					       __func__); | ||||
| 					return; | ||||
| 				} | ||||
|  | ||||
| 				struct dimm_info *dest_dimm; | ||||
| 				MEMMAP_DIMM_DEVICE_INFO_STRUCT src_dimm = | ||||
| 					hob->Socket[skt].ChannelInfo[ch].DimmInfo[dimm]; | ||||
|  | ||||
| 				if (src_dimm.Present) { | ||||
| 					dest_dimm = &mem_info->dimm[slot_index++]; | ||||
| 					dest_dimm->dimm_size = (src_dimm.DimmSize << 6); | ||||
| 					dest_dimm->soc_num = skt; | ||||
| 					dest_dimm->channel_num = ch; | ||||
| 					dest_dimm->dimm_num = dimm; | ||||
| 				} else if (mainboard_dimm_slot_exists(skt, ch, dimm)) { | ||||
| 					dest_dimm = &mem_info->dimm[slot_index++]; | ||||
| 					dest_dimm->dimm_size = 0; | ||||
| 					dest_dimm->soc_num = skt; | ||||
| 					dest_dimm->channel_num = ch; | ||||
| 					dest_dimm->dimm_num = dimm; | ||||
| 					continue; | ||||
| 				} else | ||||
| 					continue; | ||||
|  | ||||
| 				uint8_t mem_dev_type = get_dram_type(hob); | ||||
| 				uint16_t data_width = 64; | ||||
|  | ||||
| 				dimm_info_fill( | ||||
| 					dest_dimm, src_dimm.DimmSize << 6, mem_dev_type, | ||||
| 					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], data_width, | ||||
| 					vdd_voltage, true, /* hard-coded as ECC supported */ | ||||
| 					src_dimm.VendorID, src_dimm.actKeyByte2, 0, | ||||
| 					get_max_memory_speed(src_dimm.commonTck)); | ||||
|  | ||||
| 				dimm_num++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	mem_info->dimm_cnt = slot_index; /* Number of DIMM slots found */ | ||||
| 	printk(BIOS_DEBUG, "%d slots and %d installed DIMMs found\n", slot_index, dimm_num); | ||||
| } | ||||
| @@ -12,6 +12,7 @@ subdirs-y += ../../../../cpu/intel/microcode | ||||
| romstage-y += romstage.c | ||||
| romstage-y += soc_util.c | ||||
| romstage-y += soc_iio.c | ||||
| romstage-y += ../dimm.c | ||||
| romstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c | ||||
|  | ||||
| ramstage-y += chip.c | ||||
|   | ||||
| @@ -2,7 +2,10 @@ | ||||
|  | ||||
| #include <console/console.h> | ||||
| #include <soc/config.h> | ||||
| #include <smbios.h> | ||||
| #include <spd.h> | ||||
| #include <soc/romstage.h> | ||||
| #include <soc/soc_util.h> | ||||
|  | ||||
| static uint8_t get_mmcfg_base_upd_index(const uint64_t base_addr) | ||||
| { | ||||
| @@ -66,3 +69,28 @@ void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) | ||||
| 	/* Board level settings */ | ||||
| 	mainboard_memory_init_params(mupd); | ||||
| } | ||||
|  | ||||
| uint8_t get_error_correction_type(const uint8_t RasModesEnabled) | ||||
| { | ||||
| 	//TODO: to update later | ||||
| 	return MEMORY_ARRAY_ECC_UNKNOWN; | ||||
| } | ||||
|  | ||||
| uint32_t get_max_capacity_mib(void) | ||||
| { | ||||
| 	//TODO: to update later. | ||||
| 	return 4 * MiB * CONFIG_MAX_SOCKET; | ||||
| } | ||||
|  | ||||
| uint8_t get_max_dimm_count(void) | ||||
| { | ||||
| 	return MAX_DIMM; | ||||
| } | ||||
|  | ||||
| uint8_t get_dram_type(const struct SystemMemoryMapHob *hob) | ||||
| { | ||||
| 	if (hob->DramType == SPD_MEMORY_TYPE_DDR5_SDRAM) | ||||
| 		return MEMORY_TYPE_DDR5; | ||||
|  | ||||
| 	return MEMORY_TYPE_DDR4; | ||||
| } | ||||
|   | ||||
| @@ -4,10 +4,15 @@ | ||||
| #define _SOC_ROMSTAGE_H_ | ||||
|  | ||||
| #include <fsp/api.h> | ||||
| #include <soc/soc_util.h> | ||||
|  | ||||
| /* 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); | ||||
| uint32_t get_max_capacity_mib(void); | ||||
| uint8_t get_error_correction_type(const uint8_t RasModesEnabled); | ||||
| uint8_t get_max_dimm_count(void); | ||||
| uint8_t get_dram_type(const struct SystemMemoryMapHob *hob); | ||||
| void save_dimm_info(void); | ||||
| void mainboard_ewl_check(void); | ||||
| void mainboard_fsp_error_handle(void); | ||||
|   | ||||
| @@ -4,8 +4,12 @@ | ||||
| #include <intelblocks/rtc.h> | ||||
| #include <console/console.h> | ||||
| #include <fsp/util.h> | ||||
| #include <smbios.h> | ||||
| #include <soc/ddr.h> | ||||
| #include <soc/intel/common/smbios.h> | ||||
| #include <soc/romstage.h> | ||||
| #include <soc/util.h> | ||||
| #include <spd.h> | ||||
|  | ||||
| void mainboard_romstage_entry(void) | ||||
| { | ||||
| @@ -35,7 +39,7 @@ __weak void mainboard_memory_init_params(FSPM_UPD *mupd) | ||||
| __weak void mainboard_rtc_failed(void) | ||||
| { | ||||
| } | ||||
| __weak void save_dimm_info(void) { } | ||||
|  | ||||
| __weak void mainboard_ewl_check(void) { } | ||||
|  | ||||
| /* mainboard can override this function for their own handling, such as writing a BMC SEL. */ | ||||
|   | ||||
| @@ -24,3 +24,5 @@ void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) | ||||
| 	m_cfg->VTdConfig.CoherencySupport = config->coherency_support; | ||||
| 	m_cfg->VTdConfig.ATS = config->ats_support; | ||||
| } | ||||
|  | ||||
| void save_dimm_info(void) {} | ||||
|   | ||||
| @@ -9,6 +9,7 @@ subdirs-y += ../../../../cpu/x86/tsc | ||||
| subdirs-y += ../../../../cpu/intel/microcode | ||||
|  | ||||
| romstage-y += romstage.c soc_util.c | ||||
| romstage-y += ../dimm.c | ||||
| romstage-$(CONFIG_DISPLAY_HOBS) += hob_display.c | ||||
| romstage-$(CONFIG_DISPLAY_UPD_DATA) += upd_display.c | ||||
|  | ||||
|   | ||||
| @@ -18,7 +18,6 @@ | ||||
| #include <soc/romstage.h> | ||||
| #include <soc/pci_devs.h> | ||||
| #include <soc/soc_pch.h> | ||||
| #include <soc/intel/common/smbios.h> | ||||
| #include <string.h> | ||||
| #include <soc/config.h> | ||||
| #include <soc/soc_util.h> | ||||
| @@ -251,7 +250,7 @@ void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) | ||||
| 		pch_disable_hda(); | ||||
| } | ||||
|  | ||||
| static uint8_t get_error_correction_type(const uint8_t RasModesEnabled) | ||||
| uint8_t get_error_correction_type(const uint8_t RasModesEnabled) | ||||
| { | ||||
| 	switch (RasModesEnabled) { | ||||
| 	case CH_INDEPENDENT: | ||||
| @@ -270,94 +269,21 @@ static uint8_t get_error_correction_type(const uint8_t RasModesEnabled) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Save the DIMM information for SMBIOS table 17 */ | ||||
| void save_dimm_info(void) | ||||
| uint8_t get_max_dimm_count(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, dimm_num = 0; | ||||
| 	int index = 0; | ||||
| 	uint8_t mem_dev_type; | ||||
| 	uint16_t data_width; | ||||
| 	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)); | ||||
| 	/* According to EDS doc#611488, it's 4 TB per processor. */ | ||||
| 	mem_info->max_capacity_mib = 4 * MiB * CONFIG_MAX_SOCKET; | ||||
| 	mem_info->number_of_devices = CONFIG_DIMM_MAX; | ||||
| 	mem_info->ecc_type = get_error_correction_type(hob->RasModesEnabled); | ||||
| 	dimm_max = ARRAY_SIZE(mem_info->dimm); | ||||
| 	vdd_voltage = get_ddr_millivolt(hob->DdrVoltage); | ||||
| 	for (int soc = 0; soc < CONFIG_MAX_SOCKET; soc++) { | ||||
| 		for (int ch = 0; ch < MAX_CH; ch++) { | ||||
| 			for (int dimm = 0; dimm < MAX_DIMM; dimm++) { | ||||
| 				if (index >= dimm_max) { | ||||
| 					printk(BIOS_WARNING, "Too many DIMMs info for %s.\n", | ||||
| 					       __func__); | ||||
| 					return; | ||||
| 				} | ||||
|  | ||||
| 				src_dimm = hob->Socket[soc].ChannelInfo[ch].DimmInfo[dimm]; | ||||
| 				if (src_dimm.Present) { | ||||
| 					dest_dimm = &mem_info->dimm[index]; | ||||
| 					index++; | ||||
| 				} else if (mainboard_dimm_slot_exists(soc, ch, dimm)) { | ||||
| 					dest_dimm = &mem_info->dimm[index]; | ||||
| 					index++; | ||||
| 					/* Save DIMM Locator information for SMBIOS Type 17 */ | ||||
| 					dest_dimm->dimm_size = 0; | ||||
| 					dest_dimm->soc_num = soc; | ||||
| 					dest_dimm->channel_num = ch; | ||||
| 					dest_dimm->dimm_num = dimm; | ||||
| 					continue; | ||||
| 				} else { | ||||
| 					/* Ignore DIMM that isn't present and doesn't exist on | ||||
| 					   the board. */ | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				dest_dimm->soc_num = soc; | ||||
|  | ||||
| 				if (hob->DramType == SPD_MEMORY_TYPE_DDR5_SDRAM) { | ||||
| 					/* hard-coded memory device type as DDR5 */ | ||||
| 					mem_dev_type = 0x22; | ||||
| 					data_width = 64; | ||||
| 				} else { | ||||
| 					/* hard-coded memory device type as DDR4 */ | ||||
| 					mem_dev_type = 0x1A; | ||||
| 					data_width = 64; | ||||
| 				} | ||||
| 				dimm_info_fill( | ||||
| 					dest_dimm, src_dimm.DimmSize << 6, mem_dev_type, | ||||
| 					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], data_width, | ||||
| 					vdd_voltage, true, /* hard-coded as ECC supported */ | ||||
| 					src_dimm.VendorID, src_dimm.actKeyByte2, 0, | ||||
| 					get_max_memory_speed(src_dimm.commonTck)); | ||||
| 				dimm_num++; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	mem_info->dimm_cnt = index; /* Number of DIMM slots found */ | ||||
| 	printk(BIOS_DEBUG, "%d Installed DIMMs found\n", dimm_num); | ||||
| 	return MAX_DIMM; | ||||
| } | ||||
|  | ||||
| uint8_t get_dram_type(const struct SystemMemoryMapHob *hob) | ||||
| { | ||||
| 	if (hob->DramType == SPD_MEMORY_TYPE_DDR5_SDRAM) | ||||
| 		return MEMORY_TYPE_DDR5; | ||||
|  | ||||
| 	return MEMORY_TYPE_DDR4; | ||||
| } | ||||
|  | ||||
| uint32_t get_max_capacity_mib(void) | ||||
| { | ||||
| 	/* According to EDS doc#611488, it's 4 TB per processor. */ | ||||
| 	return 4 * MiB * CONFIG_MAX_SOCKET; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user