intel/gm45: Refactor DDR3 write training
Split some code in individual functions. It's the refactoring part of a bigger change, following... Change-Id: Id19be4588ad8984935040d9bcba4d7c5f2e1114f Signed-off-by: Nico Huber <nico.huber@secunet.com> Reviewed-on: http://review.coreboot.org/3255 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
35e45c0780
commit
08bee23f7e
|
@ -426,6 +426,46 @@ _bad_timing_out:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
static void write_training_find_lower(const int ch, const int group,
|
||||||
|
const address_bunch_t *const addresses,
|
||||||
|
const u32 masks[][2], const int memclk1067,
|
||||||
|
write_timing_t *const lower)
|
||||||
|
{
|
||||||
|
program_write_timing(ch, group, lower, memclk1067);
|
||||||
|
/* Coarse search for good t. */
|
||||||
|
while (!write_training_test(addresses, masks[group])) {
|
||||||
|
++lower->t;
|
||||||
|
program_write_timing(ch, group, lower, memclk1067);
|
||||||
|
}
|
||||||
|
/* Fine search for good p. */
|
||||||
|
--lower->t;
|
||||||
|
program_write_timing(ch, group, lower, memclk1067);
|
||||||
|
while (!write_training_test(addresses, masks[group])) {
|
||||||
|
++lower->p;
|
||||||
|
program_write_timing(ch, group, lower, memclk1067);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void write_training_find_upper(const int ch, const int group,
|
||||||
|
const address_bunch_t *const addresses,
|
||||||
|
const u32 masks[][2], const int memclk1067,
|
||||||
|
write_timing_t *const upper)
|
||||||
|
{
|
||||||
|
program_write_timing(ch, group, upper, memclk1067);
|
||||||
|
if (!write_training_test(addresses, masks[group]))
|
||||||
|
die("Write training failed; limits too narrow.\n");
|
||||||
|
/* Coarse search for good t. */
|
||||||
|
while (write_training_test(addresses, masks[group])) {
|
||||||
|
++upper->t;
|
||||||
|
program_write_timing(ch, group, upper, memclk1067);
|
||||||
|
}
|
||||||
|
/* Fine search for good p. */
|
||||||
|
--upper->t;
|
||||||
|
program_write_timing(ch, group, upper, memclk1067);
|
||||||
|
while (write_training_test(addresses, masks[group])) {
|
||||||
|
++upper->p;
|
||||||
|
program_write_timing(ch, group, upper, memclk1067);
|
||||||
|
}
|
||||||
|
}
|
||||||
static void write_training_per_group(const int ch, const int group,
|
static void write_training_per_group(const int ch, const int group,
|
||||||
const address_bunch_t *const addresses,
|
const address_bunch_t *const addresses,
|
||||||
const u32 masks[][2], const int memclk1067)
|
const u32 masks[][2], const int memclk1067)
|
||||||
|
@ -434,46 +474,29 @@ static void write_training_per_group(const int ch, const int group,
|
||||||
write_timing_t lower = { 0, 0, t_bound, 0 },
|
write_timing_t lower = { 0, 0, t_bound, 0 },
|
||||||
upper = { 0, 0, t_bound, 0 };
|
upper = { 0, 0, t_bound, 0 };
|
||||||
|
|
||||||
/* Search lower bound. */
|
/*** Search lower bound. ***/
|
||||||
|
|
||||||
|
/* Start at -1f from current values. */
|
||||||
const u32 reg = MCHBAR32(CxWRTy_MCHBAR(ch, group));
|
const u32 reg = MCHBAR32(CxWRTy_MCHBAR(ch, group));
|
||||||
lower.t = (reg >> 12) & 0xf;
|
lower.t = (reg >> 12) & 0xf;
|
||||||
lower.p = (reg >> 8) & 0x7;
|
lower.p = (reg >> 8) & 0x7;
|
||||||
lower.f = ((reg >> 2) & 0x3) - 1;
|
lower.f = ((reg >> 2) & 0x3) - 1;
|
||||||
program_write_timing(ch, group, &lower, memclk1067);
|
|
||||||
/* Coarse search for good t. */
|
|
||||||
while (!write_training_test(addresses, masks[group])) {
|
|
||||||
++lower.t;
|
|
||||||
program_write_timing(ch, group, &lower, memclk1067);
|
|
||||||
}
|
|
||||||
/* Fine search for good p. */
|
|
||||||
--lower.t;
|
|
||||||
program_write_timing(ch, group, &lower, memclk1067);
|
|
||||||
while (!write_training_test(addresses, masks[group])) {
|
|
||||||
++lower.p;
|
|
||||||
program_write_timing(ch, group, &lower, memclk1067);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search upper bound. */
|
write_training_find_lower(ch, group, addresses,
|
||||||
|
masks, memclk1067, &lower);
|
||||||
|
|
||||||
|
/*** Search upper bound. ***/
|
||||||
|
|
||||||
|
/* Start at lower + 3t. */
|
||||||
upper.t = lower.t + 3;
|
upper.t = lower.t + 3;
|
||||||
upper.p = lower.p;
|
upper.p = lower.p;
|
||||||
upper.f = lower.f;
|
upper.f = lower.f;
|
||||||
program_write_timing(ch, group, &upper, memclk1067);
|
|
||||||
if (!write_training_test(addresses, masks[group]))
|
|
||||||
die("Write training failed; limits too narrow.\n");
|
|
||||||
/* Coarse search for good t. */
|
|
||||||
while (write_training_test(addresses, masks[group])) {
|
|
||||||
++upper.t;
|
|
||||||
program_write_timing(ch, group, &upper, memclk1067);
|
|
||||||
}
|
|
||||||
/* Fine search for good p. */
|
|
||||||
--upper.t;
|
|
||||||
program_write_timing(ch, group, &upper, memclk1067);
|
|
||||||
while (write_training_test(addresses, masks[group])) {
|
|
||||||
++upper.p;
|
|
||||||
program_write_timing(ch, group, &upper, memclk1067);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate and program mean value. */
|
write_training_find_upper(ch, group, addresses,
|
||||||
|
masks, memclk1067, &upper);
|
||||||
|
|
||||||
|
/*** Calculate and program mean value. ***/
|
||||||
|
|
||||||
lower.t += lower.f * lower.t_bound;
|
lower.t += lower.f * lower.t_bound;
|
||||||
lower.p += lower.t << WRITE_TIMING_P_SHIFT;
|
lower.p += lower.t << WRITE_TIMING_P_SHIFT;
|
||||||
upper.t += upper.f * upper.t_bound;
|
upper.t += upper.f * upper.t_bound;
|
||||||
|
|
Loading…
Reference in New Issue