aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/intel/gm45/raminit_read_write_training.c
diff options
context:
space:
mode:
authorNico Huber <nico.huber@secunet.com>2013-05-14 11:58:44 +0200
committerStefan Reinauer <stefan.reinauer@coreboot.org>2013-05-22 18:04:11 +0200
commit08bee23f7eb31cce4746c51cfde3a7017e0e8b8e (patch)
tree53d1e22e71ec63ae1e888cc2312f1ac53b8c3508 /src/northbridge/intel/gm45/raminit_read_write_training.c
parent35e45c078054a7bd64ba54b8b84b07602e8dd4ff (diff)
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>
Diffstat (limited to 'src/northbridge/intel/gm45/raminit_read_write_training.c')
-rw-r--r--src/northbridge/intel/gm45/raminit_read_write_training.c85
1 files changed, 54 insertions, 31 deletions
diff --git a/src/northbridge/intel/gm45/raminit_read_write_training.c b/src/northbridge/intel/gm45/raminit_read_write_training.c
index f13cde8e93..72c83a7275 100644
--- a/src/northbridge/intel/gm45/raminit_read_write_training.c
+++ b/src/northbridge/intel/gm45/raminit_read_write_training.c
@@ -426,6 +426,46 @@ _bad_timing_out:
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,
const address_bunch_t *const addresses,
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 },
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));
lower.t = (reg >> 12) & 0xf;
lower.p = (reg >> 8) & 0x7;
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.p = lower.p;
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.p += lower.t << WRITE_TIMING_P_SHIFT;
upper.t += upper.f * upper.t_bound;