From 84da72c988955c7bdeccf889b1f682582a428752 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 7 May 2016 17:26:40 -0500 Subject: [PATCH] nb/amd/mct_ddr3: Report correct DIMM size in SMBIOS structure The existing DIMM size calculation for DDR3 was incorrect. Use the recommended calculation from the DDR3 SPD specification. Change-Id: Id6a39e2b38b5d9f483341ebef8f2960ae52bda6c Signed-off-by: Timothy Pearson Reviewed-on: https://review.coreboot.org/14739 Tested-by: build bot (Jenkins) Tested-by: Raptor Engineering Automated Test Stand Reviewed-by: Stefan Reinauer --- src/northbridge/amd/amdfam10/northbridge.c | 21 ++++++++++++++++++--- src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 2 ++ src/northbridge/amd/amdmct/mct_ddr3/mct_d.h | 2 ++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c index da93175b21..19acab61db 100644 --- a/src/northbridge/amd/amdfam10/northbridge.c +++ b/src/northbridge/amd/amdfam10/northbridge.c @@ -1199,12 +1199,27 @@ static int amdfam10_get_smbios_data17(int* count, int handle, int parent_handle, * Primary data width * 2^(#rows) * 2^(#cols) * #banks * #ranks */ uint8_t width, rows, cols, banks, ranks; - width = 8; + uint64_t chip_size; + uint32_t chip_width; rows = mem_info->dct_stat[node].DimmRows[slot]; cols = mem_info->dct_stat[node].DimmCols[slot]; ranks = mem_info->dct_stat[node].DimmRanks[slot]; banks = mem_info->dct_stat[node].DimmBanks[slot]; - uint64_t dimm_size_bytes = width * (1ULL << rows) * (1ULL << cols) * banks * ranks; +#if IS_ENABLED(CONFIG_DIMM_DDR3) + chip_size = mem_info->dct_stat[node].DimmChipSize[slot]; + chip_width = mem_info->dct_stat[node].DimmChipWidth[slot]; +#else + chip_size = 0; + chip_width = 0; +#endif + uint64_t dimm_size_bytes; + if (IS_ENABLED(CONFIG_DIMM_DDR3)) { + width = mem_info->dct_stat[node].DimmWidth[slot]; + dimm_size_bytes = ((width / chip_width) * chip_size * ranks) / 8; + } else { + width = 8; + dimm_size_bytes = width * (1ULL << rows) * (1ULL << cols) * banks * ranks; + } memset(t, 0, sizeof(struct smbios_type17)); t->type = SMBIOS_MEMORY_DEVICE; @@ -1213,7 +1228,7 @@ static int amdfam10_get_smbios_data17(int* count, int handle, int parent_handle, t->length = sizeof(struct smbios_type17) - 2; if (dimm_size_bytes > 0x800000000) { t->size = 0x7FFF; - t->extended_size = dimm_size_bytes; + t->extended_size = dimm_size_bytes >> 16; } else { t->size = dimm_size_bytes / (1024*1024); t->size &= (~0x8000); /* size specified in megabytes */ diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c index 1e1ef188c8..4fa7e66ae3 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c @@ -5706,6 +5706,8 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat, pDCTstat->DimmRanks[i] = ((pDCTstat->spd_data.spd_bytes[i][SPD_Organization] & 0x38) >> 3) + 1; pDCTstat->DimmBanks[i] = 1ULL << (((pDCTstat->spd_data.spd_bytes[i][SPD_Density] & 0x70) >> 4) + 3); pDCTstat->DimmWidth[i] = 1ULL << ((pDCTstat->spd_data.spd_bytes[i][SPD_BusWidth] & 0x7) + 3); + pDCTstat->DimmChipSize[i] = 1ULL << ((pDCTstat->spd_data.spd_bytes[i][SPD_Density] & 0xf) + 28); + pDCTstat->DimmChipWidth[i] = 1ULL << ((pDCTstat->spd_data.spd_bytes[i][SPD_Organization] & 0x7) + 2); } /* Check supported voltage(s) */ pDCTstat->DimmSupportedVoltages[i] = pDCTstat->spd_data.spd_bytes[i][SPD_Voltage] & 0x7; diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h index a5a3d88044..e1d9da53fb 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h @@ -621,6 +621,8 @@ struct DCTStatStruc { /* A per Node structure*/ uint8_t DimmRanks[MAX_DIMMS_SUPPORTED]; uint8_t DimmBanks[MAX_DIMMS_SUPPORTED]; uint8_t DimmWidth[MAX_DIMMS_SUPPORTED]; + uint64_t DimmChipSize[MAX_DIMMS_SUPPORTED]; + uint32_t DimmChipWidth[MAX_DIMMS_SUPPORTED]; uint8_t DimmRegistered[MAX_DIMMS_SUPPORTED]; uint8_t DimmLoadReduced[MAX_DIMMS_SUPPORTED];