aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/intel/x4x/raminit_ddr2.c
diff options
context:
space:
mode:
authorArthur Heymans <arthur@aheymans.xyz>2017-11-04 08:07:06 +0100
committerFelix Held <felix-coreboot@felixheld.de>2018-05-01 17:41:31 +0000
commit95c48cbbb5b679ddbc2bd115becc04454e4adffd (patch)
tree157499d58c0e29f26d2cac53407bf37cf838bf3f /src/northbridge/intel/x4x/raminit_ddr2.c
parent66f1bd208550e5c35f27679d8d8c48f50c6958e7 (diff)
nb/intel/x4x: Implement both read and write training
This training find the optimal write DQ delay and read DQS delay settings. It does so on all lanes at the same time, like vendor (training each lane individually has poor results). The results are stored in the sysinfo struct and restored on next boots and S3 resume. This potentially increases stability as optimal settings are chosen and is more necessary for DDR3 raminit where the write DQS delays are leveled/variable due to the flyby topology. TESTED on Intel DG43GT with (2G + 1G) on each channel, see that the results are quite close to the safe original ones (that previous worked fine) and tested with memtest86+. Change-Id: Iacdc63b91b4705d1a80437314bfe55385ea5b6c1 Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/22329 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Diffstat (limited to 'src/northbridge/intel/x4x/raminit_ddr2.c')
-rw-r--r--src/northbridge/intel/x4x/raminit_ddr2.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index b9675836e2..a36242b2d8 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -293,7 +293,7 @@ static void cmdset(u8 ch, const struct dll_setting *setting)
* All finer DQ and DQS DLL settings are set to the same value
* for each rank in a channel, while coarse is common.
*/
-static void dqsset(u8 ch, u8 lane, const struct dll_setting *setting)
+void dqsset(u8 ch, u8 lane, const struct dll_setting *setting)
{
int rank;
@@ -320,7 +320,7 @@ static void dqsset(u8 ch, u8 lane, const struct dll_setting *setting)
}
}
-static void dqset(u8 ch, u8 lane, const struct dll_setting *setting)
+void dqset(u8 ch, u8 lane, const struct dll_setting *setting)
{
int rank;
MCHBAR32(0x400 * ch + 0x5fc) = (MCHBAR32(0x400 * ch + 0x5fc)
@@ -346,12 +346,12 @@ static void dqset(u8 ch, u8 lane, const struct dll_setting *setting)
}
}
-static void rt_set_dqs(u8 channel, u8 lane, u8 rank,
+void rt_set_dqs(u8 channel, u8 lane, u8 rank,
struct rt_dqs_setting *dqs_setting)
{
u16 saved_tap = MCHBAR16(0x540 + 0x400 * channel + lane * 4);
u16 saved_pi = MCHBAR16(0x542 + 0x400 * channel + lane * 4);
- printk(RAM_SPEW, "RT DQS: ch%d, L%d, %d.%d\n", channel, lane,
+ printk(RAM_SPEW, "RT DQS: ch%d, r%d, L%d: %d.%d\n", channel, rank, lane,
dqs_setting->tap,
dqs_setting->pi);
@@ -1680,9 +1680,14 @@ void raminit_ddr2(struct sysinfo *s, int fast_boot)
// XXX tRD
- // XXX Write training
-
- // XXX Read training
+ if (!fast_boot) {
+ if (s->selected_timings.mem_clk > MEM_CLOCK_667MHz) {
+ if(do_write_training(s))
+ die("DQ write training failed!");
+ }
+ if (do_read_training(s))
+ die("DQS read training failed!");
+ }
// DRADRB
dradrb_ddr2(s);