soc/intel/common: Improve Type16 SMBIOS tables
Use CAPID0_A to provide information closer to reality. * Correctly advertise ECC support, max DIMM count and max capacity * CAPID0_A hasn't changed since SNB, but most EDS mark the bits as reserved even though they are still used by FSP. * Assume the same bits for Tiger Lake as for Ice Lake * Assume the same bits for Skylake as for Coffee Lake * Add CAPID0_A to Icelake headers The lastest complete documentation can be found in Document: 341078-002. Change-Id: I0d8fbb512fccbd99a6cfdacadc496d8266ae4cc7 Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/41334 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: Christian Walter <christian.walter@9elements.com> Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
This commit is contained in:
parent
78e8db1eeb
commit
bf72dcbd2f
9 changed files with 99 additions and 4 deletions
|
@ -88,3 +88,9 @@ int soc_get_uncore_prmmr_base_and_mask(uint64_t *prmrr_base,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz)
|
||||
{
|
||||
/* Max 4GiB per rank, 2 ranks per channel. Intel Document: 332092-002 */
|
||||
return 8192;
|
||||
}
|
||||
|
|
|
@ -73,3 +73,17 @@ void soc_systemagent_init(struct device *dev)
|
|||
soc_config = &config->power_limits_config;
|
||||
set_power_limits(MOBILE_SKU_PL1_TIME_SEC, soc_config);
|
||||
}
|
||||
|
||||
uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz)
|
||||
{
|
||||
switch (capid0_a_ddrsz) {
|
||||
case 1:
|
||||
return 8192;
|
||||
case 2:
|
||||
return 4096;
|
||||
case 3:
|
||||
return 2048;
|
||||
default:
|
||||
return 32768;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,4 +90,8 @@ void soc_add_fixed_mmio_resources(struct device *dev, int *resource_cnt);
|
|||
/* SoC specific APIs to get UNCORE PRMRR base and mask values
|
||||
* returns 0, if able to get base and mask values; otherwise returns -1 */
|
||||
int soc_get_uncore_prmmr_base_and_mask(uint64_t *base, uint64_t *mask);
|
||||
|
||||
/* Returns the maximum supported capacity of a channel as encoded by DDRSZ in MiB */
|
||||
uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz);
|
||||
|
||||
#endif /* SOC_INTEL_COMMON_BLOCK_SA_H */
|
||||
|
|
|
@ -41,6 +41,11 @@ __weak unsigned long sa_write_acpi_tables(const struct device *dev,
|
|||
return current;
|
||||
}
|
||||
|
||||
__weak uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz)
|
||||
{
|
||||
return 32768; /* 32 GiB per channel */
|
||||
}
|
||||
|
||||
/*
|
||||
* Add all known fixed MMIO ranges that hang off the host bridge/memory
|
||||
* controller device.
|
||||
|
@ -258,11 +263,27 @@ static void systemagent_read_resources(struct device *dev)
|
|||
}
|
||||
|
||||
#if CONFIG(GENERATE_SMBIOS_TABLES)
|
||||
static bool sa_supports_ecc(const uint32_t capida)
|
||||
{
|
||||
return !(capida & CAPID_ECCDIS);
|
||||
}
|
||||
|
||||
static size_t sa_slots_per_channel(const uint32_t capida)
|
||||
{
|
||||
return !(capida & CAPID_DDPCD) + 1;
|
||||
}
|
||||
|
||||
static size_t sa_number_of_channels(const uint32_t capida)
|
||||
{
|
||||
return !(capida & CAPID_PDCD) + 1;
|
||||
}
|
||||
|
||||
static int sa_smbios_write_type_16(struct device *dev, int *handle,
|
||||
unsigned long *current)
|
||||
{
|
||||
struct smbios_type16 *t = (struct smbios_type16 *)*current;
|
||||
int len = sizeof(struct smbios_type16);
|
||||
const uint32_t capida = pci_read_config32(dev, CAPID0_A);
|
||||
|
||||
struct memory_info *meminfo;
|
||||
meminfo = cbmem_find(CBMEM_ID_MEMINFO);
|
||||
|
@ -275,12 +296,14 @@ static int sa_smbios_write_type_16(struct device *dev, int *handle,
|
|||
t->length = len - 2;
|
||||
t->location = MEMORY_ARRAY_LOCATION_SYSTEM_BOARD;
|
||||
t->use = MEMORY_ARRAY_USE_SYSTEM;
|
||||
/* TBD, meminfo hob have information about ECC */
|
||||
t->memory_error_correction = MEMORY_ARRAY_ECC_NONE;
|
||||
t->memory_error_correction = sa_supports_ecc(capida) ? MEMORY_ARRAY_ECC_SINGLE_BIT :
|
||||
MEMORY_ARRAY_ECC_NONE;
|
||||
/* no error information handle available */
|
||||
t->memory_error_information_handle = 0xFFFE;
|
||||
t->maximum_capacity = 32 * (GiB / KiB); /* 32GB as default */
|
||||
t->number_of_memory_devices = meminfo->dimm_cnt;
|
||||
t->maximum_capacity = soc_systemagent_max_chan_capacity_mib(CAPID_DDRSZ(capida)) *
|
||||
sa_number_of_channels(capida) * (MiB / KiB);
|
||||
t->number_of_memory_devices = sa_slots_per_channel(capida) *
|
||||
sa_number_of_channels(capida);
|
||||
|
||||
*current += len;
|
||||
*handle += 1;
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
#define DPR_EPM (1 << 2)
|
||||
#define DPR_PRS (1 << 1)
|
||||
#define DPR_SIZE_MASK 0xff0
|
||||
/* CAPID0_A */
|
||||
#define CAPID_ECCDIS (1 << 25)
|
||||
#define CAPID_DDPCD (1 << 14)
|
||||
#define CAPID_PDCD (1 << 12)
|
||||
#define CAPID_DDRSZ(x) (((x) >> 19) & 0x3)
|
||||
|
||||
#define PCIEXBAR_LENGTH_64MB 2
|
||||
#define PCIEXBAR_LENGTH_128MB 1
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#define D_LCK (1 << 4)
|
||||
#define G_SMRAME (1 << 3)
|
||||
#define C_BASE_SEG ((0 << 2) | (1 << 1) | (0 << 0))
|
||||
#define CAPID0_A 0xe4
|
||||
|
||||
#define BIOS_RESET_CPL 0x5da8
|
||||
#define EDRAMBAR 0x5408
|
||||
|
|
|
@ -52,3 +52,17 @@ void soc_systemagent_init(struct device *dev)
|
|||
/* Enable BIOS Reset CPL */
|
||||
enable_bios_reset_cpl();
|
||||
}
|
||||
|
||||
uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz)
|
||||
{
|
||||
switch (capid0_a_ddrsz) {
|
||||
case 1:
|
||||
return 8192;
|
||||
case 2:
|
||||
return 4096;
|
||||
case 3:
|
||||
return 2048;
|
||||
default:
|
||||
return 65536;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,3 +87,17 @@ int soc_get_uncore_prmmr_base_and_mask(uint64_t *prmrr_base,
|
|||
*prmrr_mask = (uint64_t) msr.hi << 32 | msr.lo;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz)
|
||||
{
|
||||
switch (capid0_a_ddrsz) {
|
||||
case 1:
|
||||
return 8192;
|
||||
case 2:
|
||||
return 4096;
|
||||
case 3:
|
||||
return 2048;
|
||||
default:
|
||||
return 32768;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,3 +67,17 @@ void soc_systemagent_init(struct device *dev)
|
|||
soc_config = &config->power_limits_config;
|
||||
set_power_limits(MOBILE_SKU_PL1_TIME_SEC, soc_config);
|
||||
}
|
||||
|
||||
uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz)
|
||||
{
|
||||
switch (capid0_a_ddrsz) {
|
||||
case 1:
|
||||
return 8192;
|
||||
case 2:
|
||||
return 4096;
|
||||
case 3:
|
||||
return 2048;
|
||||
default:
|
||||
return 65536;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue