nb/intel/sandybridge: Compute data timings independently

Use absolute values for the Rx and Tx bus timings instead of values
relative to the CA (Command/Address) bus timing. This makes the
calculations more accurate, less complex and less error-prone.

Tested on Asus P8H61-M PRO, still boots. Training results do not seem to
be affected by this patch, and the margins roughly have the same shape.

Change-Id: I28ff1bdaadf1fcbca6a5e5ccdd456de683206410
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/47771
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Angel Pons 2020-11-19 21:50:33 +01:00 committed by Felix Held
parent 81ff33cffc
commit 075d123f6a

View file

@ -1023,71 +1023,29 @@ void program_timings(ramctr_timing *ctrl, int channel)
reg_roundtrip_latency = 0; reg_roundtrip_latency = 0;
FOR_ALL_POPULATED_RANKS { FOR_ALL_POPULATED_RANKS {
int post_timA_min_high = 7, pre_timA_min_high = 7; reg_io_latency |= ctrl->timings[channel][slotrank].io_latency << (4 * slotrank);
int post_timA_max_high = 0, pre_timA_max_high = 0;
int shift_402x = 0;
int shift = ctrl->timings[channel][slotrank].pi_coding + cmd_delay;
if (shift < 0)
shift = 0;
FOR_ALL_LANES {
post_timA_min_high = MIN(post_timA_min_high,
(ctrl->timings[channel][slotrank].lanes[lane].
timA + shift) >> 6);
pre_timA_min_high = MIN(pre_timA_min_high,
ctrl->timings[channel][slotrank].lanes[lane].
timA >> 6);
post_timA_max_high = MAX(post_timA_max_high,
(ctrl->timings[channel][slotrank].lanes[lane].
timA + shift) >> 6);
pre_timA_max_high = MAX(pre_timA_max_high,
ctrl->timings[channel][slotrank].lanes[lane].
timA >> 6);
}
if (pre_timA_max_high - pre_timA_min_high <
post_timA_max_high - post_timA_min_high)
shift_402x = +1;
else if (pre_timA_max_high - pre_timA_min_high >
post_timA_max_high - post_timA_min_high)
shift_402x = -1;
reg_io_latency |=
(ctrl->timings[channel][slotrank].io_latency + shift_402x -
post_timA_min_high) << (4 * slotrank);
reg_roundtrip_latency |= reg_roundtrip_latency |=
(ctrl->timings[channel][slotrank].roundtrip_latency + ctrl->timings[channel][slotrank].roundtrip_latency << (8 * slotrank);
shift_402x) << (8 * slotrank);
FOR_ALL_LANES { FOR_ALL_LANES {
MCHBAR32(lane_base[lane] + GDCRRX(channel, slotrank)) = MCHBAR32(lane_base[lane] + GDCRRX(channel, slotrank)) =
(((ctrl->timings[channel][slotrank].lanes[lane]. ((ctrl->timings[channel][slotrank].lanes[lane].timA & 0x3f)
timA + shift) & 0x3f)
| |
((ctrl->timings[channel][slotrank].lanes[lane]. (ctrl->timings[channel][slotrank].lanes[lane].rising << 8)
rising + shift) << 8)
| |
(((ctrl->timings[channel][slotrank].lanes[lane]. ((ctrl->timings[channel][slotrank].lanes[lane].timA & 0x1c0) << 10)
timA + shift - |
(post_timA_min_high << 6)) & 0x1c0) << 10) (ctrl->timings[channel][slotrank].lanes[lane].falling << 20));
| ((ctrl->timings[channel][slotrank].lanes[lane].
falling + shift) << 20));
MCHBAR32(lane_base[lane] + GDCRTX(channel, slotrank)) = MCHBAR32(lane_base[lane] + GDCRTX(channel, slotrank)) =
(((ctrl->timings[channel][slotrank].lanes[lane]. ((ctrl->timings[channel][slotrank].lanes[lane].timC & 0x3f)
timC + shift) & 0x3f)
| |
(((ctrl->timings[channel][slotrank].lanes[lane]. ((ctrl->timings[channel][slotrank].lanes[lane].timB & 0x3f) << 8)
timB + shift) & 0x3f) << 8)
| |
(((ctrl->timings[channel][slotrank].lanes[lane]. ((ctrl->timings[channel][slotrank].lanes[lane].timB & 0x1c0) << 9)
timB + shift) & 0x1c0) << 9)
| |
(((ctrl->timings[channel][slotrank].lanes[lane]. ((ctrl->timings[channel][slotrank].lanes[lane].timC & 0x40) << 13));
timC + shift) & 0x40) << 13));
} }
} }
MCHBAR32(SC_ROUNDT_LAT_ch(channel)) = reg_roundtrip_latency; MCHBAR32(SC_ROUNDT_LAT_ch(channel)) = reg_roundtrip_latency;