summaryrefslogtreecommitdiff
path: root/src/northbridge
diff options
context:
space:
mode:
authorPatrick Rudolph <siro@das-labor.org>2016-01-26 08:45:21 +0100
committerMartin Roth <martinroth@google.com>2016-02-20 05:11:37 +0100
commitbd1fdc6e84cae1f3fa705ae229a6b8ab67f2960a (patch)
tree49928772522c5a8e4c0206e7b6940548539784fe /src/northbridge
parentc3b0b7281326de836890fdb16eb92737f44b4e59 (diff)
nb/intel/sandybridge/raminit: Add XMP support
Some vendors store lower frequency profiles in the regular SPD, if the SPD contains a XMP profile. To make use of the board's and DIMM's maximum supported DRAM frequency, try to parse the XMP profile and use it instead. Validate the XMP profile to make sure that the installed DIMM count per channel is supported and the requested voltage is supported. To reduce complexity only XMP Profile 1 is read. Allows my DRAM to run at 800Mhz instead of 666Mhz as encoded in the default SPD. Test system: * Gigabyte GA-B75M-D3H * Intel Pentium CPU G2130 Change-Id: Ib4dd68debfdcfdce138e813ad5b0e8e2ce3a40b2 Signed-off-by: Patrick Rudolph <siro@das-labor.org> Reviewed-on: https://review.coreboot.org/13486 Reviewed-by: Martin Roth <martinroth@google.com> Tested-by: build bot (Jenkins)
Diffstat (limited to 'src/northbridge')
-rw-r--r--src/northbridge/intel/sandybridge/raminit.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c
index 59f3b3b834..40089e2cdb 100644
--- a/src/northbridge/intel/sandybridge/raminit.c
+++ b/src/northbridge/intel/sandybridge/raminit.c
@@ -284,7 +284,7 @@ void read_spd(spd_raw_data * spd, u8 addr)
static void dram_find_spds_ddr3(spd_raw_data * spd, dimm_info * dimm,
ramctr_timing * ctrl)
{
- int dimms = 0;
+ int dimms = 0, dimms_on_channel;
int channel, slot, spd_slot;
memset (ctrl->rankmap, 0, sizeof (ctrl->rankmap));
@@ -295,9 +295,37 @@ static void dram_find_spds_ddr3(spd_raw_data * spd, dimm_info * dimm,
FOR_ALL_CHANNELS {
ctrl->channel_size_mb[channel] = 0;
+ dimms_on_channel = 0;
+ /* count dimms on channel */
for (slot = 0; slot < NUM_SLOTS; slot++) {
spd_slot = 2 * channel + slot;
spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
+ if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
+ dimms_on_channel++;
+ }
+
+ for (slot = 0; slot < NUM_SLOTS; slot++) {
+ spd_slot = 2 * channel + slot;
+ /* search for XMP profile */
+ spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
+ spd[spd_slot],
+ DDR3_XMP_PROFILE_1);
+
+ if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
+ printram("No valid XMP profile found.\n");
+ spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
+ } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
+ printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
+ dimm->dimm[channel][slot].dimms_per_channel,
+ dimms_on_channel);
+ spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
+ } else if (dimm->dimm[channel][slot].voltage != 1500) {
+ /* TODO: support other DDR3 voltage than 1500mV */
+ printram("XMP profile's requested %u mV is unsupported.\n",
+ dimm->dimm[channel][slot].voltage);
+ spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
+ }
+
if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
// set dimm invalid
dimm->dimm[channel][slot].ranks = 0;