[coreboot-gerrit] Patch set updated for coreboot: [WIP] nb/intel/x4x/raminit: Refactor receive enable calibration
Arthur Heymans (arthur@aheymans.xyz)
gerrit at coreboot.org
Thu Mar 9 01:38:29 CET 2017
Arthur Heymans (arthur at aheymans.xyz) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18692
-gerrit
commit 6b8726daf71550186fe240aaefdecd8d4dd362ab
Author: Arthur Heymans <arthur at aheymans.xyz>
Date: Tue Mar 7 20:48:14 2017 +0100
[WIP] nb/intel/x4x/raminit: Refactor receive enable calibration
Moves receive enable calibration to a separate file to lighten
raminit.c a bit.
Receive enable calibration is quite similar to gm45 so it reuses some
of it function names.
UNTESTED
Change-Id: I0c970455e609d3ce96a262cbf110336a2079da4d
Signed-off-by: Arthur Heymans <arthur at aheymans.xyz>
---
src/northbridge/intel/x4x/Makefile.inc | 1 +
src/northbridge/intel/x4x/raminit_ddr2.c | 278 +---------------------------
src/northbridge/intel/x4x/rcven.c | 302 +++++++++++++++++++++++++++++++
src/northbridge/intel/x4x/x4x.h | 1 +
4 files changed, 305 insertions(+), 277 deletions(-)
diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc
index 34d9b0f..5c64ca7 100644
--- a/src/northbridge/intel/x4x/Makefile.inc
+++ b/src/northbridge/intel/x4x/Makefile.inc
@@ -20,6 +20,7 @@ romstage-y += early_init.c
romstage-y += raminit.c
romstage-y += raminit_ddr2.c
romstage-y += ram_calc.c
+romstage-y += rcven.c
ramstage-y += acpi.c
ramstage-y += ram_calc.c
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index 9c414e2..40903ba 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -30,11 +30,6 @@
#define ME_UMA_SIZEMB 0
-static inline void barrier(void)
-{
- asm volatile("mfence":::);
-}
-
static u32 fsb2mhz(u32 speed)
{
return (speed * 267) + 800;
@@ -1233,277 +1228,6 @@ static void jedec_ddr2(struct sysinfo *s)
printk(BIOS_DEBUG, "MRS done\n");
}
-static u8 sampledqs(u16 mchloc, u32 addr, u8 hilow, u8 repeat)
-{
- u8 dqsmatch = 1;
- volatile u32 strobe;
-
- while (repeat-- > 0) {
- MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0x2;
- udelay(2);
- MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
- udelay(2);
- MCHBAR8(0x9d8) = MCHBAR8(0x9d8) & ~0x2;
- udelay(2);
- MCHBAR8(0x9d8) = MCHBAR8(0x9d8) | 0x2;
- udelay(2);
- barrier();
- strobe = read32((u32 *)addr);
- barrier();
- if (((MCHBAR32(mchloc) & 0x40) >> 6) != hilow) {
- dqsmatch = 0;
- }
- }
- return dqsmatch;
-}
-
-static void rcven_ddr2(struct sysinfo *s)
-{
- u8 i, reg8, ch, lane;
- u32 addr;
- u8 tap = 0;
- u8 savecc, savemedium, savetap, coarsecommon, medium;
- u8 lanecoarse[8] = {0};
- u8 mincoarse = 0xff;
- u8 pitap[2][8];
- u16 coarsectrl[2];
- u16 coarsedelay[2];
- u16 mediumphase[2];
- u16 readdelay[2];
- u16 mchbar;
- MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xc;
- MCHBAR8(0x9d8) = MCHBAR8(0x9d8) & ~0xc;
- MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
-
- FOR_EACH_POPULATED_CHANNEL(s->dimms, ch) {
- addr = (ch << 29);
- for (i = 0; !RANK_IS_POPULATED(s->dimms, ch, i); i++) {
- addr += 128*1024*1024;
- }
- for (lane = 0; lane < 8; lane++) {
- printk(BIOS_DEBUG, "Channel %d, Lane %d addr=0x%08x\n", ch, lane, addr);
- coarsecommon = (s->selected_timings.CAS - 1);
- switch (lane) {
- case 0: case 1: medium = 0; break;
- case 2: case 3: medium = 1; break;
- case 4: case 5: medium = 2; break;
- case 6: case 7: medium = 3; break;
- default: medium = 0; break;
- }
- mchbar = 0x400*ch + 0x561 + (lane << 2);
- tap = 0;
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) & ~0xf0000) |
- (coarsecommon << 16);
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) & ~(3 << (lane*2))) |
- (medium << (lane*2));
- MCHBAR8(0x400*ch + 0x560 + lane*4) = MCHBAR8(0x400*ch + 0x560 + lane*4) & ~0xf;
- MCHBAR8(0x400*ch + 0x560 + lane*4) = MCHBAR8(0x400*ch + 0x560 + lane*4) & ~0x70;
- savecc = coarsecommon;
- savemedium = medium;
- savetap = 0;
-
- MCHBAR16(0x400*ch + 0x588) = (MCHBAR16(0x400*ch + 0x588) & ~(3 << (lane*2))) |
- (1 << (lane*2));
-
- printk(BIOS_DEBUG, "rcven 0.1 coarse=%d\n", coarsecommon);
- while (sampledqs(mchbar, addr, 1, 1) == 1) {
- if (medium < 3) {
- medium++;
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
- } else {
- medium = 0;
- coarsecommon++;
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) &
- ~0xf0000) | (coarsecommon << 16);
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
- }
- if (coarsecommon > 16) {
- die("Coarse > 16: DQS tuning failed, halt\n");
- break;
- }
- }
- printk(BIOS_DEBUG, " GOT IT (high -> low transition) coarse=%d medium=%d\n", coarsecommon, medium);
-
- savemedium = medium;
- savecc = coarsecommon;
- if (medium < 3) {
- medium++;
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
- } else {
- medium = 0;
- coarsecommon++;
-
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) & ~0xf0000) |
- (coarsecommon << 16);
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) & ~(3 << (lane*2))) |
- (medium << (lane*2));
- }
-
- printk(BIOS_DEBUG, "rcven 0.2\n");
- while (sampledqs(mchbar, addr, 0, 1) == 1) {
- savemedium = medium;
- savecc = coarsecommon;
- if (medium < 3) {
- medium++;
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
- } else {
- medium = 0;
- coarsecommon++;
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) &
- ~0xf0000) | (coarsecommon << 16);
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
- }
- if (coarsecommon > 16) {
- die("Coarse DQS tuning 2 failed, halt\n");
- break;
- }
- }
- printk(BIOS_DEBUG, " GOT IT (low -> high transition) coarse=%d medium=%d\n", coarsecommon, medium);
-
-
- coarsecommon = savecc;
- medium = savemedium;
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) &
- ~0xf0000) | (coarsecommon << 16);
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
-
- printk(BIOS_DEBUG, "rcven 0.3\n");
- tap = 0;
- while (sampledqs(mchbar, addr, 1, 1) == 0) {
- savetap = tap;
- tap++;
- if (tap > 14) {
- break;
- }
- MCHBAR8(0x400*ch + 0x560 + (lane*4)) =
- (MCHBAR8(0x400*ch + 0x560 + (lane*4)) & ~0xf) | tap;
- }
-
- tap = savetap;
- MCHBAR8(0x400*ch + 0x560 + (lane*4)) =
- (MCHBAR8(0x400*ch + 0x560 + (lane*4)) & ~0xf) | tap;
- MCHBAR8(0x400*ch + 0x560 + (lane*4)) =
- (MCHBAR8(0x400*ch + 0x560 + (lane*4)) & ~0x70) | 0x30;
- if (medium < 3) {
- medium++;
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
- } else {
- medium = 0;
- coarsecommon++;
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) &
- ~0xf0000) | (coarsecommon << 16);
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
- }
- if (sampledqs(mchbar, addr, 1, 1) == 0) {
- die("Not at DQS high, doh\n");
- }
-
- printk(BIOS_DEBUG, "rcven 0.4\n");
- while (sampledqs(mchbar, addr, 1, 1) == 1) {
- coarsecommon--;
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) &
- ~0xf0000) | (coarsecommon << 16);
- if (coarsecommon == 0) {
- die("Couldn't find DQS-high 0 indicator, halt\n");
- break;
- }
- }
- printk(BIOS_DEBUG, " GOT IT (high -> low transition) coarse=%d medium=%d\n", coarsecommon, medium);
-
- printk(BIOS_DEBUG, "rcven 0.5\n");
- while (sampledqs(mchbar, addr, 0, 1) == 1) {
- savemedium = medium;
- savecc = coarsecommon;
- if (medium < 3) {
- medium++;
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
- } else {
- medium = 0;
- coarsecommon++;
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) &
- ~0xf0000) | (coarsecommon << 16);
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
- }
- if (coarsecommon > 16) {
- die("Coarse DQS tuning 5 failed, halt\n");
- break;
- }
- }
- printk(BIOS_DEBUG, " GOT IT (low -> high transition) coarse=%d medium=%d\n", coarsecommon, medium);
-
- printk(BIOS_DEBUG, "rcven 0.6\n");
- coarsecommon = savecc;
- medium = savemedium;
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) &
- ~0xf0000) | (coarsecommon << 16);
- MCHBAR16(0x400*ch + 0x58c) = (MCHBAR16(0x400*ch + 0x58c) &
- ~(3 << (lane*2))) | (medium << (lane*2));
- while (sampledqs(mchbar, addr, 1, 1) == 0) {
- savetap = tap;
- tap++;
- if (tap > 14) {
- break;
- }
- MCHBAR8(0x400*ch + 0x560 + lane*4) =
- (MCHBAR8(0x400*ch + 0x560 + lane*4) & ~0xf) | tap;
- }
- tap = savetap;
- MCHBAR8(0x400*ch + 0x560 + lane*4) =
- (MCHBAR8(0x400*ch + 0x560 + lane*4) & ~0xf) | tap;
- MCHBAR8(0x400*ch + 0x560 + lane*4) =
- (MCHBAR8(0x400*ch + 0x560 + lane*4) & ~0x70) | 0x70;
-
- pitap[ch][lane] = 0x70 | tap;
-
- MCHBAR16(0x400*ch + 0x588) = MCHBAR16(0x400*ch + 0x588) & ~(3 << (lane*2));
- lanecoarse[lane] = coarsecommon;
- printk(BIOS_DEBUG, "rcven 0.7\n");
- } // END EACH LANE
-
- // Find minimum coarse value
- for (lane = 0; lane < 8; lane++) {
- if (mincoarse > lanecoarse[lane]) {
- mincoarse = lanecoarse[lane];
- }
- }
-
- printk(BIOS_DEBUG, "Found min coarse value = %d\n", mincoarse);
-
- for (lane = 0; lane < 8; lane++) {
- reg8 = (lanecoarse[lane] == 0) ? 0 : lanecoarse[lane] - mincoarse;
- MCHBAR16(0x400*ch + 0x5fa) = (MCHBAR16(0x400*ch + 0x5fa) & ~(3 << (lane*2))) |
- (reg8 << (lane*2));
- }
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) & ~0xf0000) | (mincoarse << 16);
- coarsectrl[ch] = mincoarse;
- coarsedelay[ch] = MCHBAR16(0x400*ch + 0x5fa);
- mediumphase[ch] = MCHBAR16(0x400*ch + 0x58c);
- readdelay[ch] = MCHBAR16(0x400*ch + 0x588);
- } // END EACH POPULATED CHANNEL
-
- FOR_EACH_CHANNEL(ch) {
- for (lane = 0; lane < 8; lane++) {
- MCHBAR8(0x400*ch + 0x560 + (lane*4)) =
- (MCHBAR8(0x400*ch + 0x560 + (lane*4)) & ~0xf) | pitap[ch][lane];
- }
- MCHBAR32(0x400*ch + 0x248) = (MCHBAR32(0x400*ch + 0x248) & ~0xf0000) |
- (coarsectrl[ch] << 16);
- MCHBAR16(0x400*ch + 0x5fa) = coarsedelay[ch];
- MCHBAR16(0x400*ch + 0x58c) = mediumphase[ch];
- }
- printk(BIOS_DEBUG, "End rcven\n");
-}
-
static void sdram_save_receive_enable(void)
{
int i = 0;
@@ -1572,7 +1296,7 @@ static void sdram_program_receive_enable(struct sysinfo *s)
|| (s->boot_path == BOOT_PATH_RESUME)) {
sdram_recover_receive_enable();
} else {
- rcven_ddr2(s);
+ rcven(s);
sdram_save_receive_enable();
}
}
diff --git a/src/northbridge/intel/x4x/rcven.c b/src/northbridge/intel/x4x/rcven.c
new file mode 100644
index 0000000..b5267ec
--- /dev/null
+++ b/src/northbridge/intel/x4x/rcven.c
@@ -0,0 +1,302 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Damien Zammit <damien at zamaudio.com>
+ * Copyright (C) 2017 Arthur Heymans <arthur at aheymans.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <stdint.h>
+#include <console/console.h>
+#include <delay.h>
+#include "iomap.h"
+#include "x4x.h"
+
+#define MAX_COARSE 16
+#define DQS_HIGH 1
+#define DQS_LOW 0
+#define MATCH 1
+#define NOT_MATCH 0
+
+typedef struct {
+ int medium;
+ int coarse;
+ int pi;
+ int tap;
+} rec_timing_t;
+
+static inline void barrier(void)
+{
+ asm volatile("mfence":::);
+}
+
+static u8 sampledqs(u16 mchloc, u32 addr, u8 hilow)
+{
+ u8 dqsmatch = MATCH;
+ volatile u32 strobe;
+
+ MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0x2;
+ udelay(2);
+ MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
+ udelay(2);
+ MCHBAR8(0x9d8) = MCHBAR8(0x9d8) & ~0x2;
+ udelay(2);
+ MCHBAR8(0x9d8) = MCHBAR8(0x9d8) | 0x2;
+ udelay(2);
+ barrier();
+ strobe = read32((u32 *)addr);
+ barrier();
+ if (((MCHBAR32(mchloc) & 0x40) >> 6) != hilow)
+ dqsmatch = NOT_MATCH;
+ return dqsmatch;
+}
+
+static void program_timing(rec_timing_t *timing, u8 channel, u8 lane)
+{
+ u32 reg32;
+ u16 reg16;
+ u8 reg8;
+
+ reg32 = MCHBAR32(0x400 * channel + 0x248);
+ reg32 &= ~0xf0000;
+ reg32 |= timing->coarse << 16;
+ MCHBAR32(0x400 * channel + 0x248);
+
+ reg16 = MCHBAR16(0x400 * channel + 0x58c);
+ reg16 &= ~(3 << (lane * 2));
+ reg16 |= (timing->medium << (lane * 2));
+ MCHBAR16(0x400 * channel + 0x58c) = reg16;
+
+ reg8 = MCHBAR8(0x400 * channel + 0x560 + lane * 4);
+ reg8 &= ~0x7f;
+ reg8 |= (timing->tap & 0xf) | ((timing->pi & 7) << 4);
+ MCHBAR8(0x400 * channel + 0x560 + lane * 4) = reg8;
+}
+
+static void increase_medium(rec_timing_t *timing)
+{
+ if (timing->medium < 3) {
+ timing->medium++;
+ } else {
+ timing->medium = 0;
+ timing->coarse++;
+ }
+}
+
+static void decrease_medium(rec_timing_t *timing)
+{
+ if (timing->medium == 0) {
+ timing->medium = 0;
+ timing->coarse--;
+ } else {
+ timing->medium--;
+ }
+}
+
+static int decr_coarse_low(u32 mchbar, u8 channel, u8 lane, u32 addr,
+ rec_timing_t *timing)
+{
+ printk(BIOS_DEBUG, "Decreasing coarse until high to low transition is found\n");
+ while (sampledqs(mchbar, addr, DQS_HIGH) == MATCH) {
+ timing->coarse--;
+ program_timing(timing, channel, lane);
+ if (timing->coarse == 0) {
+ printk(BIOS_DEBUG, "Couldn't find DQS-high 0 indicator, halt\n");
+ return -1;
+ }
+ }
+ printk(BIOS_DEBUG, " high -> low transition at coarse=%d medium=%d\n",
+ timing->coarse, timing->medium);
+ return 0;
+}
+
+static void fine_search_dqs_high(u32 mchbar, u8 addr, u8 channel, u8 lane,
+ rec_timing_t *timing)
+{
+ printk(BIOS_DEBUG, "Increasing TAP until high to low transition is found\n");
+ while (sampledqs(mchbar, addr, DQS_HIGH) == NOT_MATCH) {
+ timing->tap++;
+ if (timing->tap > 14)
+ return;
+ program_timing(timing, channel, lane);
+ }
+}
+
+static int find_dqs_low(u32 mchbar, u8 channel, u8 lane, u32 addr,
+ rec_timing_t *timing)
+{
+ /* Look for DQS low, using quarter steps. */
+ printk(BIOS_DEBUG, "Increasing medium until DQS LOW is found\n");
+ while (sampledqs(mchbar, addr, DQS_HIGH) == MATCH) {
+ increase_medium(timing);
+ program_timing(timing, channel, lane);
+ if (timing->coarse > MAX_COARSE) {
+ printk(BIOS_DEBUG, "Coarse > 16: DQS tuning failed, halt\n");
+ return -1;
+ }
+ }
+ printk(BIOS_DEBUG, " high -> low transition at coarse=%d medium=%d\n",
+ timing->coarse, timing->medium);
+ return 0;
+}
+static int find_dqs_high(u32 mchbar, u8 channel, u8 lane, u32 addr,
+ rec_timing_t *timing)
+{
+ /* Look for DQS low, using quarter steps. */
+ printk(BIOS_DEBUG, "Increasing medium until DQS HIGH is found\n");
+ while (sampledqs(mchbar, addr, DQS_LOW) == MATCH) {
+ increase_medium(timing);
+ program_timing(timing, channel, lane);
+ if (timing->coarse > MAX_COARSE) {
+ printk(BIOS_DEBUG, "Coarse > 16: DQS tuning failed, halt\n");
+ return -1;
+ }
+ }
+ printk(BIOS_DEBUG, " low -> high transition at coarse=%d medium=%d\n",
+ timing->coarse, timing->medium);
+ return 0;
+}
+
+static int find_dqs_edge_lowhigh(u32 mchbar, u8 channel, u8 lane, u32 addr,
+ rec_timing_t *timing)
+{
+ /* Advance beyond previous high to low transition. */
+ increase_medium(timing);
+ program_timing(timing, channel, lane);
+
+ /* Coarsely look for DQS high. */
+ if (find_dqs_high(mchbar, channel, lane, addr, timing))
+ return -1;
+
+ /* Go back and perform finer search. */
+ decrease_medium(timing);
+ program_timing(timing, channel, lane);
+ fine_search_dqs_high(mchbar, channel, lane, addr, timing);
+
+ /* Go back on fine search */
+ timing->tap--;
+ program_timing(timing, channel, lane);
+ return 0;
+
+}
+
+static int find_preamble(u32 mchbar, u8 channel, u8 lane, u32 addr,
+ rec_timing_t *timing)
+{
+ /* Add a quarter step */
+ increase_medium(timing);
+ program_timing(timing, channel, lane);
+ /* Verify we are at high */
+ if (sampledqs(mchbar, addr, DQS_HIGH) == NOT_MATCH) {
+ printk(BIOS_DEBUG, "Not at DQS high, doh\n");
+ return -1;
+ }
+
+ /* Decrease coarse until LOW is found */
+ if (decr_coarse_low(mchbar, channel, lane, addr, timing))
+ return -1;
+ return 0;
+}
+
+static int calibrate_receive_enable(u8 channel, u8 lane,
+ u32 addr, rec_timing_t *timing)
+{
+ u32 mchbar = 0x400 * channel + 0x561 + (lane << 2);
+
+ program_timing(timing, channel, lane);
+ /* Set receive enable bit */
+ MCHBAR16(0x400 * channel + 0x588) = (MCHBAR16(0x400 * channel + 0x588)
+ & ~(3 << (lane * 2))) | (1 << (lane * 2));
+
+ if (find_dqs_low(mchbar, addr, channel, lane, timing))
+ return -1;
+
+ if (find_dqs_edge_lowhigh(mchbar, addr, channel, lane, timing))
+ return -1;
+ timing->pi = 3;
+ program_timing(timing, channel, lane);
+
+ if (find_preamble(mchbar, addr, channel, lane, timing))
+ return -1;
+
+ if (find_dqs_edge_lowhigh(mchbar, addr, channel, lane, timing))
+ return -1;
+ timing->pi = 7;
+ program_timing(timing, channel, lane);
+
+ /* Unset receive enable bit */
+ MCHBAR16(0x400 * channel + 0x588) = MCHBAR16(0x400 * channel + 0x588) &
+ ~(3 << (lane * 2));
+ return 0;
+}
+
+void rcven(struct sysinfo *s)
+{
+ int i;
+ u8 channel, lane, reg8;
+ u32 addr;
+ rec_timing_t timing[8];
+ u8 mincoarse;
+
+ MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xc;
+ MCHBAR8(0x9d8) = MCHBAR8(0x9d8) & ~0xc;
+ MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
+ FOR_EACH_POPULATED_CHANNEL(s->dimms, channel) {
+ addr = (channel << 29);
+ mincoarse = 0xff;
+ for (i = 0; !RANK_IS_POPULATED(s->dimms, channel, i); i++)
+ addr += 128*1024*1024;
+ for (lane = 0; lane < 8; lane++) {
+ timing[lane].coarse = (s->selected_timings.CAS - 1);
+ switch (lane) {
+ default:
+ case 0:
+ case 1:
+ timing[lane].medium = 0;
+ break;
+ case 2:
+ case 3:
+ timing[lane].medium = 1;
+ break;
+ case 4:
+ case 5:
+ timing[lane].medium = 2;
+ break;
+ case 6:
+ case 7:
+ timing[lane].medium = 3;
+ break;
+ }
+ timing[lane].tap = 0;
+ timing[lane].pi = 0;
+
+ if (calibrate_receive_enable(channel, lane, addr, &timing[lane]))
+ die("Receive enable calibration failed");
+ if (mincoarse > timing[lane].coarse)
+ mincoarse = timing[lane].coarse;
+ printk(BIOS_DEBUG, "Found min coarse value = %d\n", mincoarse);
+ }
+ /* Normalise coarse */
+ for (lane = 0; lane < 8; lane++) {
+ if (timing[lane].coarse == 0)
+ reg8 = 0;
+ else
+ reg8 = timing[lane].coarse - mincoarse;
+ MCHBAR16(0x400 * channel + 0x5fa) &=
+ ~(3 << (lane * 2)) | (reg8 << (lane * 2));
+ }
+ /* simply use timing[0] to program to program mincoarse */
+ timing[0].coarse = mincoarse;
+ program_timing(&timing[0], channel, 0);
+ }
+}
diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h
index faae775..57ff2d5 100644
--- a/src/northbridge/intel/x4x/x4x.h
+++ b/src/northbridge/intel/x4x/x4x.h
@@ -328,6 +328,7 @@ u32 decode_igd_gtt_size(u32 gsm);
u8 decode_pciebar(u32 *const base, u32 *const len);
void sdram_initialize(int boot_path, const u8 *spd_map);
void raminit_ddr2(struct sysinfo *);
+void rcven(struct sysinfo *s);
struct acpi_rsdp;
#ifndef __SIMPLE_DEVICE__
More information about the coreboot-gerrit
mailing list