From 25c45012232e0d380d5f847d3942a15a4c05bfd8 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Fri, 5 Dec 2025 13:46:47 +0100 Subject: [PATCH] device/dram/ddr3: Fill in voltage fields for SMBIOS type 17 Parse the supported voltages from the DDR3 SPD and populate the corresponding fields in CBMEM_ID_MEMINFO to make sure the SMBIOS type 17 tables report the actual supported voltages of the DIMM. Change-Id: I35af7c23f285af10b607a80eab7f4d9df664b3fd Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/90395 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/device/dram/ddr3.c | 16 ++++++++++++++++ src/include/device/dram/ddr3.h | 4 ++++ .../intel/sandybridge/raminit_common.h | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/device/dram/ddr3.c b/src/device/dram/ddr3.c index 30dbe83753..c99255ba5a 100644 --- a/src/device/dram/ddr3.c +++ b/src/device/dram/ddr3.c @@ -173,20 +173,29 @@ int spd_decode_ddr3(struct dimm_attr_ddr3_st *dimm, spd_ddr3_raw_data spd) /* Module nominal voltage */ reg8 = spd[6]; + dimm->min_voltage = UINT16_MAX; + dimm->max_voltage = 0; + printram(" Supported voltages :"); if (reg8 & (1 << 2)) { dimm->flags.operable_1_25V = 1; dimm->voltage = 1250; + dimm->max_voltage = MAX(dimm->voltage, dimm->max_voltage); + dimm->min_voltage = MIN(dimm->min_voltage, dimm->voltage); printram(" 1.25V"); } if (reg8 & (1 << 1)) { dimm->flags.operable_1_35V = 1; dimm->voltage = 1300; + dimm->max_voltage = MAX(dimm->voltage, dimm->max_voltage); + dimm->min_voltage = MIN(dimm->min_voltage, dimm->voltage); printram(" 1.35V"); } if (!(reg8 & (1 << 0))) { dimm->flags.operable_1_50V = 1; dimm->voltage = 1500; + dimm->max_voltage = MAX(dimm->voltage, dimm->max_voltage); + dimm->min_voltage = MIN(dimm->min_voltage, dimm->voltage); printram(" 1.5V"); } printram("\n"); @@ -454,6 +463,8 @@ int spd_xmp_decode_ddr3(struct dimm_attr_ddr3_st *dimm, spd_ddr3_raw_data spd, dimm->voltage = (xmp[0] & 1) * 50; dimm->voltage += ((xmp[0] >> 1) & 0xf) * 100; dimm->voltage += ((xmp[0] >> 5) & 0x3) * 1000; + dimm->max_voltage = MAX(dimm->voltage, dimm->max_voltage); + dimm->min_voltage = MIN(dimm->min_voltage, dimm->voltage); printram(" Requested voltage : %u mV\n", dimm->voltage); @@ -535,6 +546,9 @@ enum cb_err spd_add_smbios17(const u8 channel, const u8 slot, const u16 selected dimm->channel_num = channel; dimm->rank_per_dimm = info->ranks; dimm->dimm_num = slot; + dimm->vdd_voltage = info->voltage; + dimm->vdd_min_voltage = info->min_voltage; + dimm->vdd_max_voltage = info->max_voltage; memcpy(dimm->module_part_number, info->part_number, 16); dimm->mod_id = info->manufacturer_id; dimm->mod_type = info->dimm_type; @@ -579,6 +593,8 @@ void dram_print_spd_ddr3(const struct dimm_attr_ddr3_st *dimm) printk(BIOS_INFO, " Column addr bits : %u\n", dimm->col_bits); printk(BIOS_INFO, " Number of ranks : %u\n", dimm->ranks); printk(BIOS_INFO, " DIMM Capacity : %u MB\n", dimm->size_mb); + printk(BIOS_INFO, " Vdd Min : %u mV\n", dimm->min_voltage); + printk(BIOS_INFO, " Vdd Max : %u mV\n", dimm->max_voltage); /* CAS Latencies Supported */ val16 = dimm->cas_supported; diff --git a/src/include/device/dram/ddr3.h b/src/include/device/dram/ddr3.h index 2f8766be8a..e752e0e060 100644 --- a/src/include/device/dram/ddr3.h +++ b/src/include/device/dram/ddr3.h @@ -138,6 +138,10 @@ struct dimm_attr_ddr3_st { u8 reference_card; /* XMP: Module voltage in mV */ u16 voltage; + /* Maximum voltage the DIMM supports in mV */ + u16 max_voltage; + /* Minimum voltage the DIMM supports in mV */ + u16 min_voltage; /* XMP: max DIMMs per channel supported (1-4) */ u8 dimms_per_channel; /* Manufacturer ID */ diff --git a/src/northbridge/intel/sandybridge/raminit_common.h b/src/northbridge/intel/sandybridge/raminit_common.h index 202f67a78a..aa88a27616 100644 --- a/src/northbridge/intel/sandybridge/raminit_common.h +++ b/src/northbridge/intel/sandybridge/raminit_common.h @@ -305,7 +305,7 @@ void iosav_write_memory_test_sequence(ramctr_timing *ctrl, int channel, int slot /* * WARNING: Do not forget to increase MRC_CACHE_VERSION when the saved data is changed! */ -#define MRC_CACHE_VERSION 5 +#define MRC_CACHE_VERSION 6 enum power_down_mode { PDM_NONE = 0,