nb/intel/sandybridge: Encapsulate JEDEC write leveling
Create and rename a few functions to contain the entire JEDEC write leveling algorithm. Not all write training is JEDEC write leveling. Tested on Asus P8H61-M PRO, still boots. Change-Id: Ie9c6315340164029e30354723b4103d906633602 Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/47617 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
parent
c6d2feaee5
commit
820bce7322
|
@ -1696,7 +1696,7 @@ static void precharge(ramctr_timing *ctrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
|
static int write_level_rank(ramctr_timing *ctrl, int channel, int slotrank)
|
||||||
{
|
{
|
||||||
int timB;
|
int timB;
|
||||||
int statistics[NUM_LANES][128];
|
int statistics[NUM_LANES][128];
|
||||||
|
@ -1767,14 +1767,12 @@ static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_timB_high_adjust(u64 val)
|
static int get_dqs_flyby_adjust(u64 val)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* DQS is good enough */
|
/* DQS is good enough */
|
||||||
if (val == 0xffffffffffffffffLL)
|
if (val == 0xffffffffffffffffLL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (val >= 0xf000000000000000LL) {
|
if (val >= 0xf000000000000000LL) {
|
||||||
/* DQS is late, needs negative adjustment */
|
/* DQS is late, needs negative adjustment */
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
|
@ -1889,9 +1887,10 @@ static void train_write_flyby(ramctr_timing *ctrl)
|
||||||
u64 res = MCHBAR32(lane_base[lane] + GDCRTRAININGRESULT1(channel));
|
u64 res = MCHBAR32(lane_base[lane] + GDCRTRAININGRESULT1(channel));
|
||||||
res |= ((u64) MCHBAR32(lane_base[lane] +
|
res |= ((u64) MCHBAR32(lane_base[lane] +
|
||||||
GDCRTRAININGRESULT2(channel))) << 32;
|
GDCRTRAININGRESULT2(channel))) << 32;
|
||||||
|
|
||||||
old = ctrl->timings[channel][slotrank].lanes[lane].timB;
|
old = ctrl->timings[channel][slotrank].lanes[lane].timB;
|
||||||
ctrl->timings[channel][slotrank].lanes[lane].timB +=
|
ctrl->timings[channel][slotrank].lanes[lane].timB +=
|
||||||
get_timB_high_adjust(res) * 64;
|
get_dqs_flyby_adjust(res) * 64;
|
||||||
|
|
||||||
printram("High adjust %d:%016llx\n", lane, res);
|
printram("High adjust %d:%016llx\n", lane, res);
|
||||||
printram("Bval+: %d, %d, %d, %x -> %x\n", channel, slotrank, lane,
|
printram("Bval+: %d, %d, %d, %x -> %x\n", channel, slotrank, lane,
|
||||||
|
@ -1942,13 +1941,9 @@ static void disable_refresh_machine(ramctr_timing *ctrl)
|
||||||
* the DRAM-chip samples the CLK on every DQS edge and feeds back the sampled value on the data
|
* the DRAM-chip samples the CLK on every DQS edge and feeds back the sampled value on the data
|
||||||
* lanes (DQ).
|
* lanes (DQ).
|
||||||
*/
|
*/
|
||||||
int write_training(ramctr_timing *ctrl)
|
static int jedec_write_leveling(ramctr_timing *ctrl)
|
||||||
{
|
{
|
||||||
int channel, slotrank, lane;
|
int channel, slotrank;
|
||||||
int err;
|
|
||||||
|
|
||||||
FOR_ALL_POPULATED_CHANNELS
|
|
||||||
MCHBAR32_OR(TC_RWP_ch(channel), 1 << 27);
|
|
||||||
|
|
||||||
disable_refresh_machine(ctrl);
|
disable_refresh_machine(ctrl);
|
||||||
|
|
||||||
|
@ -1971,7 +1966,7 @@ int write_training(ramctr_timing *ctrl)
|
||||||
|
|
||||||
/* Set any valid value for timB, it gets corrected later */
|
/* Set any valid value for timB, it gets corrected later */
|
||||||
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
|
FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
|
||||||
err = discover_timB(ctrl, channel, slotrank);
|
const int err = write_level_rank(ctrl, channel, slotrank);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -2003,6 +1998,21 @@ int write_training(ramctr_timing *ctrl)
|
||||||
|
|
||||||
toggle_io_reset();
|
toggle_io_reset();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_training(ramctr_timing *ctrl)
|
||||||
|
{
|
||||||
|
int channel, slotrank, lane;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
FOR_ALL_POPULATED_CHANNELS
|
||||||
|
MCHBAR32_OR(TC_RWP_ch(channel), 1 << 27);
|
||||||
|
|
||||||
|
err = jedec_write_leveling(ctrl);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
printram("CPE\n");
|
printram("CPE\n");
|
||||||
precharge(ctrl);
|
precharge(ctrl);
|
||||||
printram("CPF\n");
|
printram("CPF\n");
|
||||||
|
|
Loading…
Reference in New Issue