[coreboot-gerrit] Change in coreboot[master]: nb/intel/x4x/raminit: Support programming initials DD3 DLL s...

Arthur Heymans (Code Review) gerrit at coreboot.org
Wed May 24 22:10:36 CEST 2017


Arthur Heymans has uploaded a new change for review. ( https://review.coreboot.org/19874 )

Change subject: nb/intel/x4x/raminit: Support programming initials DD3 DLL setting
......................................................................

nb/intel/x4x/raminit: Support programming initials DD3 DLL setting

Due to shear amount of tables for default DLL settings used, they are
mostly pushed to a new file to avoid cluttering up the raminit.

Change-Id: Ia79b216ad69a02d4706ffc74f867a85db3eb2d6c
Signed-off-by: Arthur Heymans <arthur at aheymans.xyz>
---
M src/northbridge/intel/x4x/Makefile.inc
M src/northbridge/intel/x4x/raminit_ddr23.c
A src/northbridge/intel/x4x/raminit_tables.c
M src/northbridge/intel/x4x/x4x.h
4 files changed, 470 insertions(+), 136 deletions(-)


  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/74/19874/1

diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc
index ae8d388..8b59dbf 100644
--- a/src/northbridge/intel/x4x/Makefile.inc
+++ b/src/northbridge/intel/x4x/Makefile.inc
@@ -22,6 +22,7 @@
 romstage-y += ram_calc.c
 romstage-y += spd_ddr2_decode.c
 romstage-y += spd_ddr3_decode.c
+romstage-y += raminit_tables.c
 
 ramstage-y += acpi.c
 ramstage-y += ram_calc.c
diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c
index 4db29f5..673ebad 100644
--- a/src/northbridge/intel/x4x/raminit_ddr23.c
+++ b/src/northbridge/intel/x4x/raminit_ddr23.c
@@ -367,9 +367,10 @@
 		setting->tap;
 }
 
-static void dqsset(u8 ch, u8 lane, const struct dll_setting *setting)
+void dqsset(u8 ch, u8 lane, const struct dll_setting *setting)
 {
-	MCHBAR32(0x400*ch + 0x5fc) = MCHBAR32(0x400*ch + 0x5fc) & ~(2 << (lane*4));
+	MCHBAR32(0x400*ch + 0x5fc) = (MCHBAR32(0x400*ch + 0x5fc) & ~(2 << (lane*4)))
+		| (setting->coarse << ((lane * 4) + 1));
 
 	MCHBAR32(0x400*ch + 0x5b4) = (MCHBAR32(0x400*ch + 0x5b4) & ~(0x201 << lane)) |
 		(setting->db_en << (9 + lane)) |
@@ -411,10 +412,10 @@
 		setting->tap;
 }
 
-static void dqset(u8 ch, u8 lane, const struct dll_setting *setting)
+void dqset(u8 ch, u8 lane, const struct dll_setting *setting)
 {
-	MCHBAR32(0x400*ch + 0x5fc) = MCHBAR32(0x400*ch + 0x5fc) & ~(1 << (lane*4));
-
+	MCHBAR32(0x400*ch + 0x5fc) = (MCHBAR32(0x400*ch + 0x5fc) & ~(1 << (lane*4))) |
+				(setting->coarse << (lane * 4));
 	MCHBAR32(0x400*ch + 0x5a4) = (MCHBAR32(0x400*ch + 0x5a4) & ~(0x201 << lane)) |
 		(setting->db_en << (9 + lane)) |
 		(setting->db_sel << lane);
@@ -615,7 +616,12 @@
 		MCHBAR16(0x400*i + 0x25b) = ((s->selected_timings.tRP + trpmod) << 9) |
 			s->selected_timings.tRFC;
 
-		MCHBAR16(0x400*i + 0x260) = (MCHBAR16(0x400*i + 0x260) & ~0x3fe) | (100 << 1);
+		if (s->spd_type == DDR2)
+			MCHBAR16(0x400*i + 0x260) =
+				(MCHBAR16(0x400*i + 0x260) & ~0x3fe) | (100 << 1);
+		else
+			MCHBAR16(0x400*i + 0x260) =
+				(MCHBAR16(0x400*i + 0x260) & ~0x3fe) | (256 << 1);
 		MCHBAR8(0x400*i + 0x264) = 0xff;
 		MCHBAR8(0x400*i + 0x25d) = (MCHBAR8(0x400*i + 0x25d) & ~0x3f) |
 			s->selected_timings.tRAS;
@@ -668,17 +674,30 @@
 		MCHBAR8(0x400*i + 0x24c) = MCHBAR8(0x400*i + 0x24c) & ~0x3;
 
 		reg16 = 0;
-		switch (s->selected_timings.mem_clk) {
-		default:
-		case MEM_CLOCK_667MHz:
-			reg16 = 0x99;
-			break;
-		case MEM_CLOCK_800MHz:
-			if (s->selected_timings.CAS == 5)
-				reg16 = 0x19a;
-			else if (s->selected_timings.CAS == 6)
-				reg16 = 0x9a;
-			break;
+		if (s->spd_type == DDR2) {
+			switch (s->selected_timings.mem_clk) {
+			default:
+			case MEM_CLOCK_667MHz:
+				reg16 = 0x99;
+				break;
+			case MEM_CLOCK_800MHz:
+				if (s->selected_timings.CAS == 5)
+					reg16 = 0x19a;
+				else if (s->selected_timings.CAS == 6)
+					reg16 = 0x9a;
+				break;
+			}
+		} else { /* DDR3 */
+			switch (s->selected_timings.mem_clk) {
+			default:
+			case MEM_CLOCK_800MHz:
+			case MEM_CLOCK_1066MHz:
+				reg16 = 1;
+				break;
+			case MEM_CLOCK_1333MHz:
+				reg16 = 2;
+				break;
+			}
 		}
 		reg16 &= 0x7;
 		reg16 += twl + 9;
@@ -715,8 +734,37 @@
 	MCHBAR8(0x12d) = (MCHBAR8(0x12d) & ~0xf) | reg8;
 	MCHBAR8(0x12f) = 0x4c;
 	reg32 = (1 << 31) | (0x80 << 14) | (1 << 13) | (0xa << 9);
+	if (s->spd_type == DDR3) {
+		MCHBAR8(0x114) = 0x42;
+		reg16 = (512 - MAX(5, s->selected_timings.tRFC +
+				10000 / ddr2ps[s->selected_timings.mem_clk])) / 2;
+		reg16 &= 0x1ff;
+		reg32 = (reg16 << 22) | (0x80 << 14) | (0xa << 9);
+	}
 	MCHBAR32(0x6c0) = (MCHBAR32(0x6c0) & ~0xffffff00) | reg32;
 	MCHBAR8(0x6c4) = (MCHBAR8(0x6c4) & ~0x7) | 0x2;
+}
+
+static void program_dll_clk_ctrl(int channel, const struct dll_setting *dll_settings)
+{
+	clkset0(channel, &dll_settings[CLKSET0]);
+	clkset1(channel, &dll_settings[CLKSET1]);
+	ctrlset0(channel, &dll_settings[CTRL0]);
+	ctrlset1(channel, &dll_settings[CTRL1]);
+	ctrlset2(channel, &dll_settings[CTRL2]);
+	ctrlset3(channel, &dll_settings[CTRL3]);
+	cmdset(channel, &dll_settings[CMD]);
+}
+
+static void program_dq_dqs(u8 channel, const struct dll_setting dll_setting[23])
+{
+	int lane;
+	for (lane = 0; lane < 8; lane++) {
+		dqsset(channel, lane, &dll_setting[DQS1 + lane]);
+	}
+	for (lane = 0; lane < 8; lane++) {
+		dqset(channel, lane, &dll_setting[DQ1 + lane]);
+	}
 }
 
 static void program_dll(struct sysinfo *s)
@@ -726,6 +774,9 @@
 	u32 reg32 = 0;
 	u8 lane;
 
+	const u8 rank2clken[8] = { 0x04, 0x01, 0x20, 0x08, 0x01, 0x04,
+				   0x08, 0x10 };
+
 	MCHBAR16(0x180) = (MCHBAR16(0x180) & ~0x7e06) | 0xc04;
 	MCHBAR16(0x182) = (MCHBAR16(0x182) & ~0x3ff) | 0xc8;
 	MCHBAR16(0x18a) = (MCHBAR16(0x18a) & ~0x1f1f) | 0x0f0f;
@@ -734,10 +785,14 @@
 	switch (s->selected_timings.mem_clk) {
 	default:
 	case MEM_CLOCK_667MHz:
+	case MEM_CLOCK_1333MHz:
 		reg16 = (0xa << 9) | 0xa;
 		break;
 	case MEM_CLOCK_800MHz:
 		reg16 = (0x9 << 9) | 0x9;
+		break;
+	case MEM_CLOCK_1066MHz:
+		reg16 = (0x7 << 9) | 0x7;
 		break;
 	}
 	MCHBAR16(0x19c) = (MCHBAR16(0x19c) & ~0x1e0f) | reg16;
@@ -762,14 +817,29 @@
 	udelay(1); // 533ns
 
 	// ME related
-	MCHBAR32(0x1a0) = (MCHBAR32(0x1a0) & ~0x7ffffff) | 0x551803;
+	if (s->spd_type == DDR2)
+		MCHBAR32(0x1a0) = (MCHBAR32(0x1a0) & ~0x7ffffff) | 0x551803;
+	else /* DDR3 */
+		MCHBAR32(0x1a0) = (MCHBAR32(0x1a0) & ~0x7ffffff) | 0x555801;
 
 	MCHBAR16(0x1b4) = MCHBAR16(0x1b4) & ~0x800;
-	MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0xf0;
+	if (s->spd_type == DDR2) {
+		MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0xf0;
+	} else { /* DDR3 */
+		reg8 = 0x9; /* 0x9 << 4 ?? */
+		if (s->dimms[0].ranks == 2)
+			reg8 &= ~0x80;
+		if (s->dimms[3].ranks == 2)
+			reg8 &= ~0x10;
+		MCHBAR8(0x1a8) = (MCHBAR8(0x1a8) & ~0xf0) | reg8;
+	}
+
 
 	FOR_EACH_CHANNEL(i) {
 		reg16 = 0;
-		MCHBAR16(0x400*i + 0x59c) = MCHBAR16(0x400*i + 0x59c) & ~0x3000;
+		if ((s->spd_type == DDR3) && (i == 0))
+			reg16 = (0x3 << 12);
+		MCHBAR16(0x400*i + 0x59c) = (MCHBAR16(0x400*i + 0x59c) & ~0x3000) | reg16;
 
 		reg32 = 0;
 		FOR_EACH_RANK_IN_CHANNEL(r) {
@@ -780,114 +850,82 @@
 		MCHBAR32(0x400*i + 0x59c) = (MCHBAR32(0x400*i + 0x59c) & ~0xfff) | reg32;
 		MCHBAR8(0x400*i + 0x594) = MCHBAR8(0x400*i + 0x594) & ~1;
 
-		if (!CHANNEL_IS_POPULATED(s->dimms, i)) {
-			printk(BIOS_DEBUG, "No dimms in channel %d\n", i);
-			reg8 = 0x3f;
-		} else if (ONLY_DIMMA_IS_POPULATED(s->dimms, i)) {
-			printk(BIOS_DEBUG, "DimmA populated only in channel %d\n", i);
-			reg8 = 0x38;
-		} else if (ONLY_DIMMB_IS_POPULATED(s->dimms, i)) {
-			printk(BIOS_DEBUG, "DimmB populated only in channel %d\n", i);
-			reg8 =  0x7;
-		} else if (BOTH_DIMMS_ARE_POPULATED(s->dimms, i)) {
-			printk(BIOS_DEBUG, "Both dimms populated in channel %d\n", i);
-			reg8 = 0;
-		} else {
-			die("Unhandled case\n");
-		}
-
-		//reg8 = 0x00; // FIXME don't switch on all clocks anyway
-
-		MCHBAR32(0x400*i + 0x5a0) = (MCHBAR32(0x400*i + 0x5a0) & ~0x3f000000) |
+		if (s->spd_type == DDR2) {
+			if (!CHANNEL_IS_POPULATED(s->dimms, i)) {
+				printk(BIOS_DEBUG, "No dimms in channel %d\n", i);
+				reg8 = 0x3f;
+			} else if (ONLY_DIMMA_IS_POPULATED(s->dimms, i)) {
+				printk(BIOS_DEBUG, "DimmA populated only in channel %d\n", i);
+				reg8 = 0x38;
+			} else if (ONLY_DIMMB_IS_POPULATED(s->dimms, i)) {
+				printk(BIOS_DEBUG, "DimmB populated only in channel %d\n", i);
+				reg8 =  0x7;
+			} else if (BOTH_DIMMS_ARE_POPULATED(s->dimms, i)) {
+				printk(BIOS_DEBUG, "Both dimms populated in channel %d\n", i);
+				reg8 = 0;
+			} else {
+				die("Unhandled case\n");
+			}
+			MCHBAR32(0x400*i + 0x5a0) = (MCHBAR32(0x400*i + 0x5a0) & ~0x3f000000) |
 			((u32)(reg8 << 24));
+		} else { /* DDR3 */
+			FOR_EACH_RANK_IN_CHANNEL(r) {
+				if (RANK_IS_POPULATED(s->dimms, i, r)) {
+					MCHBAR8(0x400 * i + 0x5a0 + 3) = MCHBAR8(0x400 * i + 0x5a0 + 3)
+						& ~rank2clken[r + i * 4];
+				}
+			}
+		}
 	} // END EACH CHANNEL
 
-	MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 1;
-	MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x4;
+	if (s->spd_type == DDR2) {
+		MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 1;
+		MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x4;
+	} else { /* DDR3 */
+		MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~1;
+		MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0x4;
+	}
 
 	// Update DLL timing
 	MCHBAR8(0x1a4) = MCHBAR8(0x1a4) & ~0x80;
 	MCHBAR8(0x1a4) = MCHBAR8(0x1a4) | 0x40;
 	MCHBAR16(0x5f0) = (MCHBAR16(0x5f0) & ~0x400) | 0x400;
 
-	const struct dll_setting dll_setting_667[23] = {
-	//	tap  pi db  delay
-		{13, 0, 1, 0, 0},
-		{4,  1, 0, 0, 0},
-		{13, 0, 1, 0, 0},
-		{4,  5, 0, 0, 0},
-		{4,  1, 0, 0, 0},
-		{4,  1, 0, 0, 0},
-		{4,  1, 0, 0, 0},
-		{1,  5, 1, 1, 1},
-		{1,  6, 1, 1, 1},
-		{2,  0, 1, 1, 1},
-		{2,  1, 1, 1, 1},
-		{2,  1, 1, 1, 1},
-		{14, 6, 1, 0, 0},
-		{14, 3, 1, 0, 0},
-		{14, 0, 1, 0, 0},
-		{9,  0, 0, 0, 1},
-		{9,  1, 0, 0, 1},
-		{9,  2, 0, 0, 1},
-		{9,  2, 0, 0, 1},
-		{9,  1, 0, 0, 1},
-		{6,  4, 0, 0, 1},
-		{6,  2, 0, 0, 1},
-		{5,  4, 0, 0, 1}
-	};
-
-	const struct dll_setting dll_setting_800[23] = {
-	//	tap  pi db  delay
-		{11, 5, 1, 0, 0},
-		{0,  5, 1, 1, 0},
-		{11, 5, 1, 0, 0},
-		{1,  4, 1, 1, 0},
-		{0,  5, 1, 1, 0},
-		{0,  5, 1, 1, 0},
-		{0,  5, 1, 1, 0},
-		{2,  5, 1, 1, 1},
-		{2,  6, 1, 1, 1},
-		{3,  0, 1, 1, 1},
-		{3,  0, 1, 1, 1},
-		{3,  3, 1, 1, 1},
-		{2,  0, 1, 1, 1},
-		{1,  3, 1, 1, 1},
-		{0,  3, 1, 1, 1},
-		{9,  3, 0, 0, 1},
-		{9,  4, 0, 0, 1},
-		{9,  5, 0, 0, 1},
-		{9,  6, 0, 0, 1},
-		{10, 0, 0, 0, 1},
-		{8,  1, 0, 0, 1},
-		{7,  5, 0, 0, 1},
-		{6,  2, 0, 0, 1}
-	};
-
 	FOR_EACH_POPULATED_CHANNEL(s->dimms, i) {
 		MCHBAR16(0x400*i + 0x5f0) = (MCHBAR16(0x400*i + 0x5f0) & ~0x3fc) | 0x3fc;
 		MCHBAR32(0x400*i + 0x5fc) = MCHBAR32(0x400*i + 0x5fc) & ~0xcccccccc;
-		MCHBAR8(0x400*i + 0x5d9) = (MCHBAR8(0x400*i + 0x5d9) & ~0xf0) | 0x70;
-		MCHBAR16(0x400*i + 0x590) = (MCHBAR16(0x400*i + 0x590) & ~0xffff) | 0x5555;
+		if (s->spd_type == DDR2) {
+			MCHBAR8(0x400*i + 0x5d9) = (MCHBAR8(0x400*i + 0x5d9)
+						& ~0xf0) | 0x70;
+			MCHBAR16(0x400*i + 0x590) = (MCHBAR16(0x400*i + 0x590)
+						& ~0xffff) | 0x5555;
+		} else {
+			MCHBAR8(0x400*i + 0x5d9) = (MCHBAR8(0x400*i + 0x5d9)
+						& ~0xf0) | 0x60;
+			MCHBAR16(0x400*i + 0x590) = (MCHBAR16(0x400*i + 0x590)
+						& ~0xffff) | 0xa955;
+		}
 	}
 
 	FOR_EACH_POPULATED_CHANNEL(s->dimms, i) {
-		if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz) {
-			clkset0(i, &dll_setting_667[CLKSET0]);
-			clkset1(i, &dll_setting_667[CLKSET1]);
-			ctrlset0(i, &dll_setting_667[CTRL0]);
-			ctrlset1(i, &dll_setting_667[CTRL1]);
-			ctrlset2(i, &dll_setting_667[CTRL2]);
-			ctrlset3(i, &dll_setting_667[CTRL3]);
-			cmdset(i, &dll_setting_667[CMD]);
-		} else {
-			clkset0(i, &dll_setting_800[CLKSET0]);
-			clkset1(i, &dll_setting_800[CLKSET1]);
-			ctrlset0(i, &dll_setting_800[CTRL0]);
-			ctrlset1(i, &dll_setting_800[CTRL1]);
-			ctrlset2(i, &dll_setting_800[CTRL2]);
-			ctrlset3(i, &dll_setting_800[CTRL3]);
-			cmdset(i, &dll_setting_800[CMD]);
+		if (s->spd_type == DDR2) {
+			if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz)
+				program_dll_clk_ctrl(i, ddr2_dll_setting_667);
+			else
+				program_dll_clk_ctrl(i, ddr2_dll_setting_800);
+		} else { /* DDR3 */
+			switch (s->selected_timings.mem_clk) {
+			default:
+			case MEM_CLOCK_800MHz:
+				program_dll_clk_ctrl(i, ddr3_dll_setting_800[s->nmode - 1]);
+				break;
+			case MEM_CLOCK_1066MHz:
+				program_dll_clk_ctrl(i, ddr3_dll_setting_1066[s->nmode - 1]);
+				break;
+			case MEM_CLOCK_1333MHz:
+				program_dll_clk_ctrl(i, ddr3_dll_setting_1333[s->nmode - 1]);
+				break;
+			}
 		}
 	}
 
@@ -954,23 +992,38 @@
 	}
 
 	clk = 0x1a;
+	if (s->selected_timings.mem_clk == MEM_CLOCK_1333MHz)
+		clk = 0x18;
 	if (async != 1) {
 		reg8 = MCHBAR8(0x188) & 0x1e;
-		if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz &&
-			s->selected_timings.fsb_clk == FSB_CLOCK_800MHz) {
-			clk = 0x10;
-		} else if (s->selected_timings.mem_clk == MEM_CLOCK_800MHz) {
-			clk = 0x10;
-		} else {
+		switch (s->selected_timings.mem_clk) {
+		case MEM_CLOCK_667MHz:
 			clk = 0x1a;
+			if (s->selected_timings.fsb_clk == FSB_CLOCK_800MHz)
+				clk = 0x10;
+			break;
+		case MEM_CLOCK_800MHz:
+		case MEM_CLOCK_1066MHz:
+			clk = 0x10;
+			break;
+		case MEM_CLOCK_1333MHz:
+			clk = 0x18;
+			break;
+		default:
+			clk = 0x1a;
+			break;
 		}
 	}
 	MCHBAR8(0x180) = MCHBAR8(0x180) & ~0x80;
 
-	if ((s->selected_timings.fsb_clk == FSB_CLOCK_800MHz) &&
-	    (s->selected_timings.mem_clk == MEM_CLOCK_667MHz)) {
+	if ((s->spd_type == DDR3 && s->selected_timings.mem_clk == MEM_CLOCK_1066MHz)
+		|| (s->spd_type == DDR2 && s->selected_timings.fsb_clk == FSB_CLOCK_800MHz
+			&& s->selected_timings.mem_clk == MEM_CLOCK_667MHz)) {
 		i = MCHBAR8(0x180) & 0xf;
-		i = (i + 10) % 14;
+		if (s->spd_type == DDR2)
+			i = (i + 10) % 14;
+		else /* DDR3 */
+			i = (i + 3) % 12;
 		MCHBAR8(0x1c8) = (MCHBAR8(0x1c8) & ~0x1f) | i;
 		MCHBAR8(0x180) = MCHBAR8(0x180) | 0x10;
 		while (MCHBAR8(0x180) & 0x10)
@@ -991,11 +1044,26 @@
 	// Program DQ/DQS dll settings
 	reg32 = 0;
 	FOR_EACH_POPULATED_CHANNEL(s->dimms, i) {
-		for (lane = 0; lane < 8; lane++) {
-			if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz)
-				reg32 = 0x06db7777;
-			else if (s->selected_timings.mem_clk == MEM_CLOCK_800MHz)
+		switch (s->selected_timings.mem_clk) {
+		default: /* Should not happen */
+			break;
+		case MEM_CLOCK_667MHz:
+			reg32 = 0x06db7777;
+			break;
+		case MEM_CLOCK_800MHz:
+			if (s->spd_type == DDR2)
 				reg32 = 0x00007777;
+			else /* DDR3 */
+				reg32 = 0x06db6666;
+			break;
+		case MEM_CLOCK_1066MHz:
+			reg32 = 0x06db5555;
+			break;
+		case MEM_CLOCK_1333MHz:
+			reg32 = 0x00007777;
+			break;
+		}
+		for (lane = 0; lane < 8; lane++) {
 			MCHBAR32(0x400*i + 0x540 + lane*4) =
 				(MCHBAR32(0x400*i + 0x540 + lane*4) & 0x0fffffff) |
 				reg32;
@@ -1003,16 +1071,24 @@
 	}
 
 	FOR_EACH_POPULATED_CHANNEL(s->dimms, i) {
-		if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz) {
-			for (lane = 0; lane < 8; lane++)
-				dqsset(i, lane, &dll_setting_667[DQS1+lane]);
-			for (lane = 0; lane < 8; lane++)
-				dqset(i, lane, &dll_setting_667[DQ1+lane]);
-		} else {
-			for (lane = 0; lane < 8; lane++)
-				dqsset(i, lane, &dll_setting_800[DQS1+lane]);
-			for (lane = 0; lane < 8; lane++)
-				dqset(i, lane, &dll_setting_800[DQ1+lane]);
+		switch (s->selected_timings.mem_clk) {
+		default: /* Should not happen */
+			break;
+		case MEM_CLOCK_667MHz:
+			program_dq_dqs(i, ddr2_dll_setting_667);
+			break;
+		case MEM_CLOCK_800MHz:
+			if (s->spd_type == DDR2)
+				program_dq_dqs(i, ddr2_dll_setting_800);
+			else /* DDR3 */
+				program_dq_dqs(i, ddr3_dll_setting_800[s->nmode - 1]);
+			break;
+		case MEM_CLOCK_1066MHz:
+			program_dq_dqs(i, ddr3_dll_setting_1066[s->nmode - 1]);
+			break;
+		case MEM_CLOCK_1333MHz:
+			program_dq_dqs(i, ddr3_dll_setting_1333[s->nmode - 1]);
+			break;
 		}
 	}
 }
diff --git a/src/northbridge/intel/x4x/raminit_tables.c b/src/northbridge/intel/x4x/raminit_tables.c
new file mode 100644
index 0000000..3349f62
--- /dev/null
+++ b/src/northbridge/intel/x4x/raminit_tables.c
@@ -0,0 +1,248 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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 "x4x.h"
+
+const struct dll_setting ddr2_dll_setting_667[23] = {
+	/* tap  pi db  delay */
+	{13, 0, 1, 0, 0, 0},
+	{4,  1, 0, 0, 0, 0},
+	{13, 0, 1, 0, 0, 0},
+	{4,  5, 0, 0, 0, 0},
+	{4,  1, 0, 0, 0, 0},
+	{4,  1, 0, 0, 0, 0},
+	{4,  1, 0, 0, 0, 0},
+	{1,  5, 1, 1, 1, 0},
+	{1,  6, 1, 1, 1, 0},
+	{2,  0, 1, 1, 1, 0},
+	{2,  1, 1, 1, 1, 0},
+	{2,  1, 1, 1, 1, 0},
+	{14, 6, 1, 0, 0, 0},
+	{14, 3, 1, 0, 0, 0},
+	{14, 0, 1, 0, 0, 0},
+	{9,  0, 0, 0, 1, 0},
+	{9,  1, 0, 0, 1, 0},
+	{9,  2, 0, 0, 1, 0},
+	{9,  2, 0, 0, 1, 0},
+	{9,  1, 0, 0, 1, 0},
+	{6,  4, 0, 0, 1, 0},
+	{6,  2, 0, 0, 1, 0},
+	{5,  4, 0, 0, 1, 0}
+};
+
+const struct dll_setting ddr2_dll_setting_800[23] = {
+	/* tap  pi db  delay */
+	{11, 5, 1, 0, 0, 0},
+	{0,  5, 1, 1, 0, 0},
+	{11, 5, 1, 0, 0, 0},
+	{1,  4, 1, 1, 0, 0},
+	{0,  5, 1, 1, 0, 0},
+	{0,  5, 1, 1, 0, 0},
+	{0,  5, 1, 1, 0, 0},
+	{2,  5, 1, 1, 1, 0},
+	{2,  6, 1, 1, 1, 0},
+	{3,  0, 1, 1, 1, 0},
+	{3,  0, 1, 1, 1, 0},
+	{3,  3, 1, 1, 1, 0},
+	{2,  0, 1, 1, 1, 0},
+	{1,  3, 1, 1, 1, 0},
+	{0,  3, 1, 1, 1, 0},
+	{9,  3, 0, 0, 1, 0},
+	{9,  4, 0, 0, 1, 0},
+	{9,  5, 0, 0, 1, 0},
+	{9,  6, 0, 0, 1, 0},
+	{10, 0, 0, 0, 1, 0},
+	{8,  1, 0, 0, 1, 0},
+	{7,  5, 0, 0, 1, 0},
+	{6,  2, 0, 0, 1, 0}
+};
+
+const struct dll_setting ddr3_dll_setting_800[2][23] = {
+	{ /* 1N */
+		/* tap  pi db(2)  delay coarse */
+		{8, 2, 0, 0, 0, 0},
+		{8, 4, 0, 0, 0, 0},
+		{9, 5, 0, 0, 0, 0},
+		{6, 1, 0, 0, 0, 0},
+		{8, 4, 0, 0, 0, 0},
+		{10, 0, 0, 0, 0, 0},
+		{10, 0, 0, 0, 0, 0},
+		{12, 0, 1, 0, 0, 0},
+		{1, 1, 1, 1, 1, 0},
+		{2, 4, 1, 1, 1, 0},
+		{3, 5, 0, 0, 1, 0},
+		{4, 3, 0, 0, 1, 0},
+		{5, 2, 0, 0, 1, 0},
+		{6, 1, 0, 0, 1, 0},
+		{6, 4, 0, 0, 1, 0},
+		{4, 1, 0, 0, 1, 0},
+		{6, 4, 0, 0, 1, 0},
+		{8, 1, 0, 0, 1, 0},
+		{8, 6, 0, 0, 1, 0},
+		{9, 5, 0, 0, 1, 0},
+		{10, 2, 0, 0, 1, 0},
+		{10, 6, 1, 0, 1, 0},
+		{11, 4, 1, 0, 1, 0} },
+	{ /* 2N */
+		{2, 2, 1, 1, 0, 0},
+		{2, 4, 1, 1, 0, 0},
+		{3, 5, 0, 0, 0, 0},
+		{3, 2, 1, 1, 0, 0},
+		{2, 4, 1, 1, 0, 0},
+		{3, 6, 0, 0, 0, 0},
+		{3, 6, 0, 0, 0, 0},
+		{5, 6, 0, 0, 0, 0},
+		{8, 0, 0, 0, 0, 0},
+		{9, 4, 0, 0, 0, 0},
+		{10, 4, 1, 0, 0, 0},
+		{11, 3, 1, 0, 0, 0},
+		{12, 1, 1, 0, 0, 0},
+		{0, 1, 1, 1, 1, 0},
+		{0, 3, 1, 1, 1, 0},
+		{11, 0, 1, 0, 0, 0},
+		{0, 3, 1, 1, 1, 0},
+		{2, 1, 1, 1, 1, 0},
+		{2, 5, 1, 1, 1, 0},
+		{3, 5, 0, 0, 1, 0},
+		{4, 2, 0, 0, 1, 0},
+		{4, 6, 0, 0, 1, 0},
+		{5, 4, 0, 0, 1, 0}
+	}
+};
+
+const struct dll_setting ddr3_dll_setting_1066[2][23] = {
+	{ /* 1N */
+		{8, 5, 0, 0, 0, 0},
+		{7, 6, 0, 0, 0, 0},
+		{10, 2, 1, 0, 0, 0},
+		{0, 4, 4, 0, 0, 0},
+		{7, 6, 0, 0, 0, 0},
+		{9, 2, 1, 0, 0, 0},
+		{9, 2, 1, 0, 0, 0},
+		{2, 5, 1, 1, 1, 0},
+		{5, 1, 0, 0, 1, 0},
+		{6, 6, 0, 0, 1, 0},
+		{8, 0, 0, 0, 1, 0},
+		{8, 6, 0, 0, 1, 0},
+		{9, 6, 1, 0, 1, 0},
+		{10, 6, 1, 0, 1, 0},
+		{0, 1, 1, 1, 0, 0},
+		{6, 5, 0, 0, 1, 0},
+		{9, 3, 1, 0, 1, 0},
+		{0, 2, 1, 1, 0, 1},
+		{1, 0, 1, 1, 0, 1},
+		{2, 0, 1, 1, 0, 1},
+		{2, 5, 1, 1, 0, 1},
+		{3, 2, 0, 0, 0, 1},
+		{4, 1, 0, 0, 0, 1}, },
+	{ /* 2N */
+		{1, 5, 1, 1, 0, 0},
+		{0, 6, 1, 1, 0, 0},
+		{3, 2, 0, 0, 0, 0},
+		{2, 6, 1, 1, 0, 0},
+		{0, 6, 1, 1, 0, 0},
+		{2, 2, 1, 1, 0, 0},
+		{2, 2, 1, 1, 0, 0},
+		{6, 4, 0, 0, 0, 0},
+		{9, 1, 1, 0, 0, 0},
+		{10, 6, 1, 0, 0, 0},
+		{1, 0, 1, 1, 1, 0},
+		{1, 6, 1, 1, 1, 0},
+		{2, 5, 1, 1, 1, 0},
+		{3, 5, 0, 0, 1, 0},
+		{4, 1, 0, 0, 1, 0},
+		{10, 5, 1, 0, 0, 0},
+		{2, 3, 1, 1, 1, 0},
+		{4, 1, 0, 0, 1, 0},
+		{5, 0, 0, 0, 1, 0},
+		{6, 0, 0, 0, 1, 0},
+		{6, 5, 0, 0, 1, 0},
+		{7, 2, 0, 0, 1, 0},
+		{8, 1, 0, 0, 1, 0},
+	}
+};
+const struct dll_setting ddr3_dll_setting_1333[2][23] = {
+	{ /* 1N */
+		{8, 5, 0, 0, 0, 0},
+		{9, 0, 1, 0, 0, 0},
+		{10, 2, 1, 0, 0, 0},
+		{0, 0, 1, 1, 0, 0},
+		{9, 0, 1, 0, 0, 0},
+		{10, 4, 1, 0, 0, 0},
+		{10, 4, 1, 0, 0, 0},
+		{2, 4, 1, 1, 1, 0},
+		{5, 1, 0, 0, 1, 0},
+		{6, 6, 0, 0, 1, 0},
+		{8, 0, 0, 0, 1, 0},
+		{8, 6, 0, 0, 1, 0},
+		{9, 5, 1, 0, 1, 0},
+		{10, 6, 1, 0, 1, 0},
+		{0, 1, 1, 1, 0, 1},
+		{6, 5, 0, 0, 1, 0},
+		{9, 3, 1, 0, 1, 0},
+		{0, 2, 1, 1, 0, 1},
+		{1, 0, 1, 1, 0, 1},
+		{2, 0, 1, 1, 0, 1},
+		{2, 5, 1, 1, 0, 1},
+		{3, 2, 0, 0, 0, 1},
+		{4, 1, 0, 0, 0, 1}, },
+	{ /* 2N */
+		{1, 6, 1, 1, 0, 0},
+		{2, 2, 1, 1, 0, 0},
+		{4, 2, 0, 0, 0, 0},
+		{3, 1, 1, 1, 0, 0},
+		{2, 2, 1, 1, 0, 0},
+		{4, 5, 0, 0, 0, 0},
+		{4, 5, 0, 0, 0, 0},
+		{10, 4, 0, 0, 0, 0},
+		{0, 3, 1, 1, 1, 0},
+		{3, 2, 1, 1, 1, 0},
+		{5, 0, 0, 0, 1, 0},
+		{6, 1, 0, 0, 1, 0},
+		{7, 4, 0, 0, 1, 0},
+		{9, 2, 0, 0, 1, 0},
+		{9, 6, 0, 0, 1, 0},
+		{1, 3, 1, 1, 1, 0},
+		{5, 6, 0, 0, 1, 0},
+		{8, 5, 0, 0, 1, 0},
+		{10, 2, 0, 0, 1, 0},
+		{11, 1, 0, 0, 1, 0},
+		{12, 3, 1, 0, 1, 0},
+		{13, 6, 1, 0, 1, 0},
+		{0, 3, 1, 1, 0, 1}
+	}
+};
+
+const u8 ddr3_emrs1_config[16][4] = {  /* [Config][Rank] */
+	{0x00, 0x00, 0x00, 0x00},	/* NC_NC */
+	{0x11, 0x00, 0x00, 0x00},	/* 8S_NC */
+	{0x11, 0x11, 0x00, 0x00},	/* 8D_NC */
+	{0x11, 0x00, 0x00, 0x00},	/* 16S_NC */
+	{0x00, 0x00, 0x11, 0x00},	/* NC_8S */
+	{0x81, 0x00, 0x81, 0x00},	/* 8S_8S */
+	{0x81, 0x81, 0x81, 0x00},	/* 8D_8S */
+	{0x81, 0x00, 0x81, 0x00},	/* 16S_8S */
+	{0x00, 0x00, 0x11, 0x11},	/* NC_8D */
+	{0x81, 0x00, 0x81, 0x81},	/* 8S_8D */
+	{0x81, 0x81, 0x81, 0x81},	/* 8D_8D */
+	{0x81, 0x00, 0x81, 0x81},	/* 16S_8D */
+	{0x00, 0x00, 0x11, 0x00},	/* NC_16S */
+	{0x81, 0x00, 0x81, 0x00},	/* 8S_16S */
+	{0x81, 0x81, 0x81, 0x00},	/* 8D_16S */
+	{0x81, 0x00, 0x81, 0x00},	/* 16S_16S */
+};
diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h
index 34fef93..9ef07b3 100644
--- a/src/northbridge/intel/x4x/x4x.h
+++ b/src/northbridge/intel/x4x/x4x.h
@@ -355,6 +355,15 @@
 			struct abs_timings *saved_timings);
 int ddr3_save_dimminfo(u8 dimm_idx, u8 *raw_spd,
 		struct abs_timings *saved_timings, struct sysinfo *s);
+void dqsset(u8 ch, u8 lane, const struct dll_setting *setting);
+void dqset(u8 ch, u8 lane, const struct dll_setting *setting);
+
+/* Look up tables Tables */
+extern const struct dll_setting ddr2_dll_setting_667[23];
+extern const struct dll_setting ddr2_dll_setting_800[23];
+extern const struct dll_setting ddr3_dll_setting_800[2][23];
+extern const struct dll_setting ddr3_dll_setting_1066[2][23];
+extern const struct dll_setting ddr3_dll_setting_1333[2][23];
 
 
 struct acpi_rsdp;

-- 
To view, visit https://review.coreboot.org/19874
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia79b216ad69a02d4706ffc74f867a85db3eb2d6c
Gerrit-PatchSet: 1
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Owner: Arthur Heymans <arthur at aheymans.xyz>



More information about the coreboot-gerrit mailing list