aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/intel/gm45/raminit_rcomp_calibration.c
diff options
context:
space:
mode:
authorPatrick Georgi <patrick.georgi@secunet.com>2012-11-06 11:03:53 +0100
committerPatrick Georgi <patrick@georgi-clan.de>2012-11-27 09:16:18 +0100
commit2efc8808b8bfaee0a0e8f3ee387ecd9a3f049705 (patch)
treec486b184f7609b42b3de3d5cd5d213226820a278 /src/northbridge/intel/gm45/raminit_rcomp_calibration.c
parentacd7d952514485dbc41fa04b0d16be4002e31019 (diff)
intel/gm45: new northbridge
The code supports DDR3 boards only. RAM init for DDR2 is sufficiently different that it requires separate code, and we have no boards to test that. Change-Id: I9076546faf8a2033c89eb95f5eec524439ab9fe1 Signed-off-by: Patrick Georgi <patrick.georgi@secunet.com> Signed-off-by: Nico Huber <nico.huber@secunet.com> Reviewed-on: http://review.coreboot.org/1689 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/northbridge/intel/gm45/raminit_rcomp_calibration.c')
-rw-r--r--src/northbridge/intel/gm45/raminit_rcomp_calibration.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/src/northbridge/intel/gm45/raminit_rcomp_calibration.c b/src/northbridge/intel/gm45/raminit_rcomp_calibration.c
new file mode 100644
index 0000000000..5a560ac85a
--- /dev/null
+++ b/src/northbridge/intel/gm45/raminit_rcomp_calibration.c
@@ -0,0 +1,252 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 secunet Security Networks AG
+ * (Written by Nico Huber <nico.huber@secunet.com> for secunet)
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <delay.h>
+#include <console/console.h>
+#include "gm45.h"
+
+static const int ddr3_lookup_schedule[6][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 4, 5 }, { 6, 7 }, { 6, 7 }
+};
+/* Look-up table:
+ * a1step X idx X (group || pull-up/-down)
+ */
+static const u8 ddr3_lut[2][64][8] = {
+ { /* Stepping B3 and below. */
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 8, 8, 3, 3, 3, 3, 5, 7 },
+ { 9, 9, 3, 3, 3, 3, 6, 7 },
+ { 9, 9, 3, 3, 3, 3, 6, 7 },
+ { 10, 10, 3, 3, 3, 3, 7, 8 },
+ { 11, 10, 3, 3, 3, 3, 7, 8 },
+ { 12, 11, 3, 3, 3, 3, 8, 9 },
+ { 13, 11, 3, 3, 3, 3, 9, 9 },
+ { 14, 12, 3, 3, 3, 3, 9, 10 },
+ { 15, 13, 3, 3, 3, 3, 9, 10 },
+ { 16, 14, 3, 3, 3, 3, 9, 11 },
+ { 18, 16, 3, 3, 3, 3, 10, 12 },
+ { 20, 18, 4, 3, 4, 4, 10, 12 },
+ { 22, 22, 4, 4, 4, 4, 11, 12 },
+ { 24, 24, 4, 4, 4, 4, 11, 12 },
+ { 28, 26, 4, 4, 4, 4, 12, 12 },
+ { 32, 28, 5, 4, 5, 5, 12, 12 },
+ { 36, 32, 5, 5, 5, 5, 13, 13 },
+ { 40, 36, 5, 5, 5, 5, 14, 13 },
+ { 43, 40, 5, 5, 5, 5, 15, 14 },
+ { 43, 43, 5, 5, 6, 5, 15, 14 },
+ { 43, 43, 6, 5, 6, 5, 15, 15 },
+ { 43, 43, 6, 5, 6, 6, 15, 15 },
+ { 43, 43, 6, 6, 6, 6, 15, 15 },
+ { 43, 43, 6, 6, 7, 6, 15, 15 },
+ { 43, 43, 7, 6, 7, 6, 15, 15 },
+ { 43, 43, 7, 7, 7, 7, 15, 15 },
+ { 43, 43, 7, 7, 7, 7, 15, 15 },
+ { 43, 43, 7, 7, 7, 7, 15, 15 },
+ { 43, 43, 8, 7, 8, 7, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ },
+ { /* Stepping A1 and above. */
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 8, 8, 3, 3, 3, 3, 5, 5 },
+ { 9, 9, 3, 3, 3, 3, 6, 6 },
+ { 9, 9, 3, 3, 3, 3, 6, 6 },
+ { 10, 10, 3, 3, 3, 3, 7, 7 },
+ { 10, 10, 3, 3, 3, 3, 7, 7 },
+ { 12, 11, 3, 3, 3, 3, 8, 8 },
+ { 13, 11, 3, 3, 3, 3, 9, 9 },
+ { 14, 12, 3, 3, 3, 3, 9, 9 },
+ { 15, 13, 3, 3, 3, 3, 9, 9 },
+ { 16, 14, 3, 3, 3, 3, 9, 9 },
+ { 18, 16, 3, 3, 3, 3, 10, 10 },
+ { 20, 18, 4, 3, 4, 4, 10, 10 },
+ { 22, 22, 4, 4, 4, 4, 11, 11 },
+ { 24, 24, 4, 4, 4, 4, 11, 11 },
+ { 28, 26, 4, 4, 4, 4, 12, 12 },
+ { 32, 28, 5, 4, 5, 5, 12, 12 },
+ { 36, 32, 5, 5, 5, 5, 13, 13 },
+ { 40, 36, 5, 5, 5, 5, 14, 14 },
+ { 43, 40, 5, 5, 5, 5, 15, 15 },
+ { 43, 43, 5, 5, 6, 5, 15, 15 },
+ { 43, 43, 6, 5, 6, 5, 15, 15 },
+ { 43, 43, 6, 5, 6, 6, 15, 15 },
+ { 43, 43, 6, 6, 6, 6, 15, 15 },
+ { 43, 43, 6, 6, 7, 6, 15, 15 },
+ { 43, 43, 7, 6, 7, 6, 15, 15 },
+ { 43, 43, 7, 7, 7, 7, 15, 15 },
+ { 43, 43, 7, 7, 7, 7, 15, 15 },
+ { 43, 43, 7, 7, 7, 7, 15, 15 },
+ { 43, 43, 8, 7, 8, 7, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ { 43, 43, 8, 8, 8, 8, 15, 15 },
+ }
+};
+static void lookup_and_write(const int a1step,
+ const int row, const int col,
+ unsigned int mchbar)
+{
+ int i;
+
+ /* Write 4 32-bit registers, 4 values each. */
+ for (i = row; i < row + 16; i += 4) {
+ MCHBAR32(mchbar) =
+ ((ddr3_lut[a1step][i + 0][col] & 0x3f) << 0) |
+ ((ddr3_lut[a1step][i + 1][col] & 0x3f) << 8) |
+ ((ddr3_lut[a1step][i + 2][col] & 0x3f) << 16) |
+ ((ddr3_lut[a1step][i + 3][col] & 0x3f) << 24);
+ mchbar += 4;
+ }
+}
+void raminit_rcomp_calibration(const stepping_t stepping) {
+ const int a1step = stepping >= STEPPING_CONVERSION_A1;
+
+ int i;
+
+ enum {
+ PULL_UP = 0,
+ PULL_DOWN = 1,
+ };
+ /* channel X group X pull-up/-down */
+ char lut_idx[2][6][2];
+ for (i = 0; i < 2 * 6 * 2; ++i)
+ ((char *)lut_idx)[i] = -1;
+
+ MCHBAR32(0x400) |= (1 << 2);
+ MCHBAR32(0x418) |= (1 << 17);
+ MCHBAR32(0x40c) &= ~(1 << 23);
+ MCHBAR32(0x41c) &= ~((1 << 7) | (1 << 3));
+ MCHBAR32(0x400) |= 1;
+
+ /* Read lookup indices. */
+ for (i = 0; i < 12; ++i) {
+ do {
+ MCHBAR32(0x400) |= (1 << 3);
+ udelay(10);
+ MCHBAR32(0x400) &= ~(1 << 3);
+ } while ((MCHBAR32(0x530) & 0x7) != 0x4);
+ u32 reg = MCHBAR32(0x400);
+ const unsigned int group = (reg >> 13) & 0x7;
+ const unsigned int channel = (reg >> 12) & 0x1;
+ if (group > 5)
+ break;
+ reg = MCHBAR32(0x518);
+ lut_idx[channel][group][PULL_UP] = (reg >> 24) & 0x7f;
+ lut_idx[channel][group][PULL_DOWN] = (reg >> 16) & 0x7f;
+ }
+ /* Cleanup? */
+ MCHBAR32(0x400) |= (1 << 3);
+ udelay(10);
+ MCHBAR32(0x400) &= ~(1 << 3);
+ MCHBAR32(0x400) &= ~(1 << 2);
+
+ /* Check for consistency. */
+ for (i = 0; i < 2 * 6 * 2; ++i) {
+ const char idx = ((char *)lut_idx)[i];
+ if ((idx < 7) || (idx > 55))
+ die("Bad RCOMP calibration lookup index.\n");
+ }
+
+ /* Lookup values and fill registers. */
+ int channel, group, pu_pd;
+ unsigned int mchbar = 0x0680;
+ for (channel = 0; channel < 2; ++channel) {
+ for (group = 0; group < 6; ++group) {
+ for (pu_pd = PULL_DOWN; pu_pd >= PULL_UP; --pu_pd) {
+ lookup_and_write(
+ a1step,
+ lut_idx[channel][group][pu_pd] - 7,
+ ddr3_lookup_schedule[group][pu_pd],
+ mchbar);
+ mchbar += 0x0018;
+ }
+ mchbar += 0x0010;
+ /* Channel B knows only the first two groups. */
+ if ((1 == channel) && (1 == group))
+ break;
+ }
+ mchbar += 0x0040;
+ }
+}
+