aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/intel/x4x/raminit_ddr23.c
diff options
context:
space:
mode:
authorArthur Heymans <arthur@aheymans.xyz>2017-12-25 20:13:28 +0100
committerMartin Roth <martinroth@google.com>2018-05-24 13:03:45 +0000
commitb5170c3e92b3f0cbce292f3414375b1326f4dd12 (patch)
tree8dd7d72aaa67d9727813f70445b667bf526b41a9 /src/northbridge/intel/x4x/raminit_ddr23.c
parentf1287266ab7587672080aed2ddbc272a95fba9a3 (diff)
nb/intel/x4x: Implement write leveling
DDR3 adapted a fly-by topology which allows for better signal integrity but at the same time requires additional calibration. This is done by settings the targeted rank in write leveling mode while disabling output buffer on the other ranks. After that the DQS signal gets sampled over DQ until a transition from high to low is found. Change-Id: I695969868b4534f87dd1f37244fdfac891a417f0 Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/22995 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_ddr23.c')
-rw-r--r--src/northbridge/intel/x4x/raminit_ddr23.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c
index 6d6111c5c4..618e21215c 100644
--- a/src/northbridge/intel/x4x/raminit_ddr23.c
+++ b/src/northbridge/intel/x4x/raminit_ddr23.c
@@ -1361,8 +1361,7 @@ static u32 mirror_shift_bit(const u32 data, u8 bit)
return (data & ~(3 << bit)) | temp0 | temp1;
}
-static void send_jedec_cmd(const struct sysinfo *s, u8 r,
- u8 ch, u8 cmd, u32 val)
+void send_jedec_cmd(const struct sysinfo *s, u8 r, u8 ch, u8 cmd, u32 val)
{
u32 addr = test_address(ch, r);
volatile u32 rubbish;
@@ -1933,6 +1932,24 @@ static void power_settings(struct sysinfo *s)
MCHBAR8(0x561 + (lane << 2)) = MCHBAR8(0x561 + (lane << 2)) & ~(1 << 3);
}
+static void software_ddr3_reset(struct sysinfo *s)
+{
+ printk(BIOS_DEBUG, "Software initiated DDR3 reset.\n");
+ MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0x02;
+ MCHBAR8(0x5da) = MCHBAR8(0x5da) & ~0x80;
+ MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x02;
+ MCHBAR8(0x5da) = (MCHBAR8(0x5da) & ~0x03) | 1;
+ udelay(200);
+ MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x02;
+ MCHBAR8(0x5da) = MCHBAR8(0x5da) | 0x80;
+ MCHBAR8(0x5da) = MCHBAR8(0x5da) & ~0x80;
+ udelay(500);
+ MCHBAR8(0x5da) = MCHBAR8(0x5da) | 0x03;
+ MCHBAR8(0x5da) = MCHBAR8(0x5da) & ~0x03;
+ /* After write leveling the dram needs to be reset and reinitialised */
+ jedec_ddr3(s);
+}
+
void do_raminit(struct sysinfo *s, int fast_boot)
{
u8 ch;
@@ -2019,6 +2036,17 @@ void do_raminit(struct sysinfo *s, int fast_boot)
MCHBAR8(0x9d8) = MCHBAR8(0x9d8) | 0x7;
}
+ /* DDR3 reset */
+ if ((s->spd_type == DDR3) && (s->boot_path != BOOT_PATH_RESUME)) {
+ printk(BIOS_DEBUG, "DDR3 Reset.\n");
+ MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x2;
+ MCHBAR8(0x5da) = MCHBAR8(0x5da) | 0x80;
+ udelay(500);
+ MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x2;
+ MCHBAR8(0x5da) = MCHBAR8(0x5da) & ~0x80;
+ udelay(500);
+ }
+
// Pre jedec
MCHBAR8(0x40) = MCHBAR8(0x40) | 0x2;
FOR_EACH_POPULATED_CHANNEL(s->dimms, ch) {
@@ -2038,6 +2066,13 @@ void do_raminit(struct sysinfo *s, int fast_boot)
printk(BIOS_DEBUG, "Done jedec steps\n");
+ if (s->spd_type == DDR3) {
+ if (!fast_boot)
+ search_write_leveling(s);
+ if (s->boot_path == BOOT_PATH_NORMAL)
+ software_ddr3_reset(s);
+ }
+
// After JEDEC reset
MCHBAR8(0x40) = MCHBAR8(0x40) & ~0x2;
FOR_EACH_POPULATED_CHANNEL(s->dimms, ch) {