nb/intel/sandybridge/raminit: Fix dual DIMM command rate

On boards that are able to take two DIMMs per channel the
command rate should be 2T. It is possible to use 1T with
load reduced "1T" DIMMs, but it's not clear how to detect
those DIMMs. Raminit might fail for those who do not have
such DIMMS installed.

Hardcode command rate of 2T to make sure raminit works on
dual DIMM per channel boards (currently only desktop boards).

The command rate of 1T is still tested if only 1 DIMM per
channel is present.

Will decrease performance on quad slot mainboards, if two DIMMs
are installed in one channel and previously 1T have been selected.

Tested on ASRock B75 Pro3-M.

Change-Id: I029d01092fd0e11390cebcd94ca6f23bf0ee2cab
Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-on: https://review.coreboot.org/20270
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
Patrick Rudolph 2017-06-19 19:33:12 +02:00 committed by Martin Roth
parent acac02d5d2
commit 58d16af918
1 changed files with 28 additions and 11 deletions

View File

@ -2342,7 +2342,6 @@ static int try_cmd_stretch(ramctr_timing *ctrl, int channel, int cmd_stretch)
int command_training(ramctr_timing *ctrl) int command_training(ramctr_timing *ctrl)
{ {
int channel; int channel;
int err;
FOR_ALL_POPULATED_CHANNELS { FOR_ALL_POPULATED_CHANNELS {
fill_pattern5(ctrl, channel, 0); fill_pattern5(ctrl, channel, 0);
@ -2350,17 +2349,35 @@ int command_training(ramctr_timing *ctrl)
} }
FOR_ALL_POPULATED_CHANNELS { FOR_ALL_POPULATED_CHANNELS {
/* try command rate 1T and 2T */ int cmdrate, err;
err = try_cmd_stretch(ctrl, channel, 0);
if (err) { /*
err = try_cmd_stretch(ctrl, channel, 2); * Dual DIMM per channel:
* Issue: While c320c discovery seems to succeed raminit
* will fail in write training.
* Workaround: Skip 1T in dual DIMM mode, that's only
* supported by a few DIMMs.
* TODO: How to detect "1T" DIMMs ?
*
* Single DIMM per channel:
* Try command rate 1T and 2T
*/
cmdrate = ((ctrl->rankmap[channel] & 0x5) == 0x5);
for(; cmdrate < 2; cmdrate++) {
err = try_cmd_stretch(ctrl, channel, cmdrate << 1);
if (!err)
break;
}
if (err) { if (err) {
printk(BIOS_EMERG, "c320c discovery failed\n"); printk(BIOS_EMERG, "c320c discovery failed\n");
return err; return err;
} }
printram("Using CMD rate 2T on channel %u\n", channel);
} else printram("Using CMD rate %uT on channel %u\n",
printram("Using CMD rate 1T on channel %u\n", channel); cmdrate + 1, channel);
} }
FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_CHANNELS