[coreboot-gerrit] Patch set updated for coreboot: nb/intel/x4x: Fix raminit on reset path

Arthur Heymans (arthur@aheymans.xyz) gerrit at coreboot.org
Mon Jan 2 14:40:44 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/18009

-gerrit

commit a1db9fb8ceb3f302f80e3c3e0ca9da4f10b92b2a
Author: Arthur Heymans <arthur at aheymans.xyz>
Date:   Wed Nov 30 18:40:38 2016 +0100

    nb/intel/x4x: Fix raminit on reset path
    
    If the system undergoes a hot reset some steps in raminit
    must not be done.
    
    Change-Id: I6601dd90aebd071a0de7cec070487b0f9845bc30
    Signed-off-by: Arthur Heymans <arthur at aheymans.xyz>
---
 src/mainboard/gigabyte/ga-g41m-es2l/cmos.layout |   1 +
 src/mainboard/gigabyte/ga-g41m-es2l/romstage.c  |   7 +-
 src/northbridge/intel/x4x/raminit_ddr2.c        | 134 ++++++++++++++++++++----
 src/northbridge/intel/x4x/x4x.h                 |   3 +
 4 files changed, 122 insertions(+), 23 deletions(-)

diff --git a/src/mainboard/gigabyte/ga-g41m-es2l/cmos.layout b/src/mainboard/gigabyte/ga-g41m-es2l/cmos.layout
index 3138479..946d1a1 100644
--- a/src/mainboard/gigabyte/ga-g41m-es2l/cmos.layout
+++ b/src/mainboard/gigabyte/ga-g41m-es2l/cmos.layout
@@ -68,6 +68,7 @@ entries
 # coreboot config options: check sums
 984         16       h       0        check_sum
 
+1024        256       r       0        recv_enable_results
 # -----------------------------------------------------------------
 
 enumerations
diff --git a/src/mainboard/gigabyte/ga-g41m-es2l/romstage.c b/src/mainboard/gigabyte/ga-g41m-es2l/romstage.c
index 2503db9..da51ea0 100644
--- a/src/mainboard/gigabyte/ga-g41m-es2l/romstage.c
+++ b/src/mainboard/gigabyte/ga-g41m-es2l/romstage.c
@@ -29,6 +29,7 @@
 #include <lib.h>
 #include <arch/stages.h>
 #include <cbmem.h>
+#include <northbridge/intel/x4x/iomap.h>
 
 #define SERIAL_DEV PNP_DEV(0x2e, IT8718F_SP1)
 #define GPIO_DEV PNP_DEV(0x2e, IT8718F_GPIO)
@@ -136,6 +137,7 @@ void mainboard_romstage_entry(unsigned long bist)
 {
 	//                          ch0      ch1
 	const u8 spd_addrmap[4] = { 0x50, 0, 0x52, 0 };
+	u8 boot_path = 0;
 
 	/* Disable watchdog timer */
 	RCBA32(0x3410) = RCBA32(0x3410) | 0x20;
@@ -155,8 +157,11 @@ void mainboard_romstage_entry(unsigned long bist)
 
 	x4x_early_init();
 
+	if (MCHBAR32(0xf14) & (1 << 8))
+		boot_path = BOOT_PATH_RESET;
+
 	printk(BIOS_DEBUG, "Initializing memory\n");
-	sdram_initialize(0, spd_addrmap);
+	sdram_initialize(boot_path, spd_addrmap);
 	quick_ram_check();
 	cbmem_initialize_empty();
 	printk(BIOS_DEBUG, "Memory initialized\n");
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index b3ee34a..9026a33 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -20,6 +20,9 @@
 #include <console/console.h>
 #include <commonlib/helpers.h>
 #include <delay.h>
+#include <pc80/mc146818rtc.h>
+/* only Needed for RCBA32 so it's ok to only include ICH7 function */
+#include <southbridge/intel/i82801gx/i82801gx.h>
 #include "iomap.h"
 #include "x4x.h"
 
@@ -258,10 +261,13 @@ static void checkreset_ddr2(struct sysinfo *s)
 {
 	u8 pmcon2;
 	u8 reset = 0;
+	u32 pmir;
 
+	pmir = pci_read_config32(PCI_DEV(0, 0x1f, 0), 0xac);
 	pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
-	if (!(pmcon2 & 0x80)) {
-		pmcon2 |= 0x80;
+
+	if (pmcon2 & 0x80) {
+		pmcon2 &= ~0x80;
 		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
 		reset = 1;
 
@@ -273,10 +279,16 @@ static void checkreset_ddr2(struct sysinfo *s)
 	}
 	if (reset) {
 		printk(BIOS_DEBUG, "Reset...\n");
+		/* Do a global reset. only useful on ICH10 */
+		pmir |= (1 << 20);
+		pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xac, pmir);
 		outb(0xe, 0xcf9);
 		asm ("hlt");
 	}
-	pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2 | 0x80);
+	pmir &= ~(1 << 20);
+	pmcon2 |= 0x80;
+	pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
+	pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xac, pmir);
 }
 
 static void setioclk_ddr2(struct sysinfo *s)
@@ -1486,6 +1498,76 @@ static void rcven_ddr2(struct sysinfo *s)
 	printk(BIOS_DEBUG, "End rcven\n");
 }
 
+static void sdram_save_receive_enable(void)
+{
+	int i = 0, j;
+	u32 reg32;
+	u16 reg16;
+	u8 values[32];
+	u8 lane, ch;
+
+	FOR_EACH_CHANNEL(ch) {
+		for (lane = 0; lane < 8; lane++)
+			values[i++] = MCHBAR8(0x400*ch + 0x560 + (lane*4));
+		reg32 = MCHBAR32(0x400*ch + 0x248);
+		for (j = 0; j < 4; j++)
+			values[i++] = (reg32 >> (j * 8)) & 0xff;
+		reg16 = MCHBAR16(0x400*ch + 0x5fa);
+		for (j = 0; j < 2; j++)
+			values[i++] = (reg16 >> (j * 8)) & 0xff;
+		reg16 = MCHBAR16(0x400*ch + 0x58c);
+		for (j = 0; j < 2; j++)
+			values[i++] = (reg16 >> (j * 8)) & 0xff;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(values); i++)
+		cmos_write(values[i], 128 + i);
+}
+
+static void sdram_recover_receive_enable(void)
+{
+	u8 i, j;
+	u32 reg32 = 0;
+	u16 reg16 = 0;
+	u8 values[32];
+	u8 ch, lane;
+
+	for (i = 0; i < ARRAY_SIZE(values); i++)
+		values[i] = cmos_read(128 + i);
+
+	i = 0;
+	FOR_EACH_CHANNEL(ch) {
+		for (lane = 0; lane < 8; lane++)
+			MCHBAR8(0x400*ch + 0x560 + (lane*4)) = values[i++];
+		for (j = 0; j < 4; j++)
+			reg32 |= (values[i++] << (j * 8));
+		MCHBAR32(0x400*ch + 0x248) = reg32;
+		reg32 = 0;
+		for (j = 0; j < 2; j++)
+			reg16 |= (values[i++] << (j * 8));
+		MCHBAR16(0x400*ch + 0x5fa) = reg16;
+		reg16 = 0;
+		for (j = 0; j < 2; j++)
+			reg16 |= (values[i++] << (j * 8));
+		MCHBAR16(0x400*ch + 0x58c) = reg16;
+		reg16 = 0;
+	}
+}
+
+static void sdram_program_receive_enable(struct sysinfo *s)
+{
+	/* enable upper CMOS */
+	RCBA32(0x3400) = (1 << 2);
+
+	/* Program Receive Enable Timings */
+	if (s->boot_path == BOOT_PATH_RESET) {
+		sdram_recover_receive_enable();
+	} else {
+		rcven_ddr2(s);
+		sdram_save_receive_enable();
+	}
+}
+
 static void dradrb_ddr2(struct sysinfo *s)
 {
 	u8 map, i, ch, r, rankpop0, rankpop1;
@@ -1860,22 +1942,23 @@ void raminit_ddr2(struct sysinfo *s)
 	checkreset_ddr2(s);
 
 	// Clear self refresh
-	MCHBAR32(0xf14) = MCHBAR32(0xf14) | 0x3;
+	if (s->boot_path != BOOT_PATH_RESET) {
+		MCHBAR32(0xf14) = MCHBAR32(0xf14) | 0x3;
 
-	// Clear host clk gate reg
-	MCHBAR32(0x1c) = MCHBAR32(0x1c) | 0xffffffff;
+		// Clear host clk gate reg
+		MCHBAR32(0x1c) = MCHBAR32(0x1c) | 0xffffffff;
 
-	// Select DDR2
-	MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x4;
+		// Select DDR2
+		MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x4;
 
-	// Set freq
-	MCHBAR32(0xc00) = (MCHBAR32(0xc00) & ~0x70) |
-		(s->selected_timings.mem_clk << 4) | (1 << 10);
+		// Set freq
+		MCHBAR32(0xc00) = (MCHBAR32(0xc00) & ~0x70) |
+			(s->selected_timings.mem_clk << 4) | (1 << 10);
 
-	// Overwrite freq if chipset rejects it
-	s->selected_timings.mem_clk = (MCHBAR8(0xc00) & 0x70) >> 4;
-	if (s->selected_timings.mem_clk > (s->max_fsb + 3)) {
-		die("Error: DDR is faster than FSB, halt\n");
+		// Overwrite freq if chipset rejects it
+		s->selected_timings.mem_clk = (MCHBAR8(0xc00) & 0x70) >> 4;
+		if (s->selected_timings.mem_clk > (s->max_fsb + 3))
+			die("Error: DDR is faster than FSB, halt\n");
 	}
 
 	udelay(250000);
@@ -1885,8 +1968,10 @@ void raminit_ddr2(struct sysinfo *s)
 	printk(BIOS_DEBUG, "Done clk crossing\n");
 
 	// DDR2 IO
-	setioclk_ddr2(s);
-	printk(BIOS_DEBUG, "Done I/O clk\n");
+	if (s->boot_path != BOOT_PATH_RESET) {
+		setioclk_ddr2(s);
+		printk(BIOS_DEBUG, "Done I/O clk\n");
+	}
 
 	// Grant to launch
 	launch_ddr2(s);
@@ -1900,16 +1985,21 @@ void raminit_ddr2(struct sysinfo *s)
 	dll_ddr2(s);
 
 	// RCOMP
-	rcomp_ddr2(s);
-	printk(BIOS_DEBUG, "RCOMP\n");
+	if (s->boot_path != BOOT_PATH_RESET) {
+		rcomp_ddr2(s);
+		printk(BIOS_DEBUG, "RCOMP\n");
+	}
 
 	// ODT
 	odt_ddr2(s);
 	printk(BIOS_DEBUG, "Done ODT\n");
 
 	// RCOMP update
-	while ((MCHBAR8(0x130) & 1) != 0 );
-	printk(BIOS_DEBUG, "Done RCOMP update\n");
+	if (s->boot_path != BOOT_PATH_RESET) {
+		while ((MCHBAR8(0x130) & 1) != 0)
+			;
+		printk(BIOS_DEBUG, "Done RCOMP update\n");
+	}
 
 	// Set defaults
 	MCHBAR32(0x260) = (MCHBAR32(0x260) & ~1) | 0xf00000;
@@ -1989,7 +2079,7 @@ void raminit_ddr2(struct sysinfo *s)
 	}
 
 	// Receive enable
-	rcven_ddr2(s);
+	sdram_program_receive_enable(s);
 	printk(BIOS_DEBUG, "Done rcven\n");
 
 	// Finish rcven
diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h
index 7ca634f..f86d1cc 100644
--- a/src/northbridge/intel/x4x/x4x.h
+++ b/src/northbridge/intel/x4x/x4x.h
@@ -290,6 +290,9 @@ struct sysinfo {
 	struct dimminfo	dimms[4];
 	u8		spd_map[4];
 };
+#define BOOT_PATH_NORMAL	0
+#define BOOT_PATH_RESET		1
+#define BOOT_PATH_RESUME	2
 
 enum ddr2_signals {
 	CLKSET0 = 0,



More information about the coreboot-gerrit mailing list