[coreboot-gerrit] Patch set updated for coreboot: nb/intel/x4x: Implement resume from S3 suspend

Arthur Heymans (arthur@aheymans.xyz) gerrit at coreboot.org
Tue Jan 24 18:07:10 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/17998

-gerrit

commit 8275301688634a46cf830f6f849eb1000a6716f2
Author: Arthur Heymans <arthur at aheymans.xyz>
Date:   Fri Dec 30 21:07:18 2016 +0100

    nb/intel/x4x: Implement resume from S3 suspend
    
    It rewrites the results of receive enable stored in the upper nvram
    region, to avoid running receive enable again.
    
    Some debug info is also printed about the self-refresh registers.
    (Not enforcing a reset here, since 0 does not necessarily mean it's
    not in self-refresh).
    
    Change-Id: Ib54bc5c7b0fed6d975ffc31f037b5179d9e5600b
    Signed-off-by: Arthur Heymans <arthur at aheymans.xyz>
---
 src/mainboard/gigabyte/ga-g41m-es2l/Kconfig    |   1 +
 src/mainboard/gigabyte/ga-g41m-es2l/romstage.c |   7 +-
 src/northbridge/intel/x4x/Makefile.inc         |   1 -
 src/northbridge/intel/x4x/early_init.c         | 179 +++++++++++++++++++++++
 src/northbridge/intel/x4x/pcie.c               | 191 -------------------------
 src/northbridge/intel/x4x/raminit_ddr2.c       |  18 ++-
 src/northbridge/intel/x4x/x4x.h                |   2 +-
 7 files changed, 201 insertions(+), 198 deletions(-)

diff --git a/src/mainboard/gigabyte/ga-g41m-es2l/Kconfig b/src/mainboard/gigabyte/ga-g41m-es2l/Kconfig
index 3d2a892..ae57e5b 100644
--- a/src/mainboard/gigabyte/ga-g41m-es2l/Kconfig
+++ b/src/mainboard/gigabyte/ga-g41m-es2l/Kconfig
@@ -33,6 +33,7 @@ config BOARD_SPECIFIC_OPTIONS
 	select REALTEK_8168_RESET
 	select HAVE_OPTION_TABLE
 	select HAVE_CMOS_DEFAULT
+	select HAVE_ACPI_RESUME
 
 config MMCONF_BASE_ADDRESS
 	hex
diff --git a/src/mainboard/gigabyte/ga-g41m-es2l/romstage.c b/src/mainboard/gigabyte/ga-g41m-es2l/romstage.c
index d76fbb2..0a1470b 100644
--- a/src/mainboard/gigabyte/ga-g41m-es2l/romstage.c
+++ b/src/mainboard/gigabyte/ga-g41m-es2l/romstage.c
@@ -132,6 +132,7 @@ void mainboard_romstage_entry(unsigned long bist)
 	//                          ch0      ch1
 	const u8 spd_addrmap[4] = { 0x50, 0, 0x52, 0 };
 	u8 boot_path = 0;
+	u8 s3_resume;
 
 	/* Disable watchdog timer */
 	RCBA32(0x3410) = RCBA32(0x3410) | 0x20;
@@ -151,16 +152,18 @@ void mainboard_romstage_entry(unsigned long bist)
 
 	x4x_early_init();
 
+	s3_resume = southbridge_detect_s3_resume();
+	if (s3_resume)
+		boot_path = BOOT_PATH_RESUME;
 	if (MCHBAR32(PMSTS_MCHBAR) & PMSTS_WARM_RESET)
 		boot_path = BOOT_PATH_WARM_RESET;
 
 	printk(BIOS_DEBUG, "Initializing memory\n");
 	sdram_initialize(boot_path, spd_addrmap);
 	quick_ram_check();
-	cbmem_initialize_empty();
 	printk(BIOS_DEBUG, "Memory initialized\n");
 
-	x4x_late_init();
+	x4x_late_init(s3_resume);
 
 	printk(BIOS_DEBUG, "x4x late init complete\n");
 
diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc
index 3520944..34d9b0f 100644
--- a/src/northbridge/intel/x4x/Makefile.inc
+++ b/src/northbridge/intel/x4x/Makefile.inc
@@ -20,7 +20,6 @@ romstage-y += early_init.c
 romstage-y += raminit.c
 romstage-y += raminit_ddr2.c
 romstage-y += ram_calc.c
-romstage-y += pcie.c
 
 ramstage-y += acpi.c
 ramstage-y += ram_calc.c
diff --git a/src/northbridge/intel/x4x/early_init.c b/src/northbridge/intel/x4x/early_init.c
index 1b0d4f9..7d6afc9 100644
--- a/src/northbridge/intel/x4x/early_init.c
+++ b/src/northbridge/intel/x4x/early_init.c
@@ -20,6 +20,10 @@
 #include <southbridge/intel/i82801gx/i82801gx.h> /* DEFAULT_PMBASE */
 #include <pc80/mc146818rtc.h>
 #include "x4x.h"
+#include <cbmem.h>
+#include <console/console.h>
+#include <halt.h>
+#include <romstage_handoff.h>
 
 void x4x_early_init(void)
 {
@@ -61,3 +65,178 @@ void x4x_early_init(void)
 	}
 	pci_write_config16(d0f0, D0F0_GGC, 0x0100 | ((gfxsize + 1) << 4));
 }
+
+static void init_egress(void)
+{
+	u32 reg32;
+
+	/* VC0: TC0 only */
+	EPBAR8(0x14) = 1;
+	EPBAR8(0x4) = 1;
+
+	switch (MCHBAR32(0xc00) & 0x7) {
+	case 0x0:
+		/* FSB 1066 */
+		EPBAR32(0x2c) = 0x0001a6db;
+		break;
+	case 0x2:
+		/* FSB 800 */
+		EPBAR32(0x2c) = 0x00014514;
+		break;
+	default:
+	case 0x4:
+		/* FSB 1333 */
+		EPBAR32(0x2c) = 0x00022861;
+		break;
+	}
+	EPBAR32(0x28) = 0x0a0a0a0a;
+	EPBAR8(0xc) = (EPBAR8(0xc) & ~0xe) | 2;
+	EPBAR32(0x1c) = (EPBAR32(0x1c) & ~0x7f0000) | 0x0a0000;
+	MCHBAR8(0x3c) = MCHBAR8(0x3c) | 0x7;
+
+	/* VC1: ID1, TC7 */
+	reg32 = (EPBAR32(0x20) & ~(7 << 24)) | (1 << 24);
+	reg32 = (reg32 & ~0xfe) | (1 << 7);
+	EPBAR32(0x20) = reg32;
+
+	/* Init VC1 port arbitration table */
+	EPBAR32(0x100) = 0x001000001;
+	EPBAR32(0x104) = 0x000040000;
+	EPBAR32(0x108) = 0x000001000;
+	EPBAR32(0x10c) = 0x000000040;
+	EPBAR32(0x110) = 0x001000001;
+	EPBAR32(0x114) = 0x000040000;
+	EPBAR32(0x118) = 0x000001000;
+	EPBAR32(0x11c) = 0x000000040;
+
+	/* Load table */
+	reg32 = EPBAR32(0x20) | (1 << 16);
+	EPBAR32(0x20) = reg32;
+	asm("nop");
+	EPBAR32(0x20) = reg32;
+
+	/* Wait for table load */
+	while ((EPBAR8(0x26) & (1 << 0)) != 0);
+
+	/* VC1: enable */
+	EPBAR32(0x20) |= 1 << 31;
+
+	/* Wait for VC1 */
+	while ((EPBAR8(0x26) & (1 << 1)) != 0);
+
+	printk(BIOS_DEBUG, "Done Egress Port\n");
+}
+
+static void init_dmi(void)
+{
+	u32 reg32;
+	u16 reg16;
+
+	/* Assume IGD present */
+
+	/* Clear error status */
+	DMIBAR32(0x1c4) = 0xffffffff;
+	DMIBAR32(0x1d0) = 0xffffffff;
+
+	/* VC0: TC0 only */
+	DMIBAR8(DMIVC0RCTL) = 1;
+	DMIBAR8(0x4) = 1;
+
+	/* VC1: ID1, TC7 */
+	reg32 = (DMIBAR32(DMIVC1RCTL) & ~(7 << 24)) | (1 << 24);
+	reg32 = (reg32 & ~0xff) | 1 << 7;
+
+	/* VC1: enable */
+	reg32 |= 1 << 31;
+	reg32 = (reg32 & ~(0x7 << 17)) | (0x4 << 17);
+
+	DMIBAR32(DMIVC1RCTL) = reg32;
+
+	/* Set up VCs in southbridge RCBA */
+	RCBA8(0x3022) &= ~1;
+
+	reg32 = (0x5 << 28) | (1 << 6); /* PCIe x4 */
+	RCBA32(0x2020) = (RCBA32(0x2020) & ~((0xf << 28) | (0x7 << 6))) | reg32;
+
+	/* Assign VC1 id 1 */
+	RCBA32(0x20) = (RCBA32(0x20) & ~(0x7 << 24)) | (1 << 24);
+
+	/* Map TC7 to VC1 */
+	RCBA8(0x20) &= 1;
+	RCBA8(0x20) |= 1 << 7;
+
+	/* Map TC0 to VC0 */
+	RCBA8(0x14) &= 1;
+
+	/* Init DMI VC1 port arbitration table */
+	RCBA32(0x20) &= 0xfff1ffff;
+	RCBA32(0x20) |= 1 << 19;
+
+	RCBA32(0x30) = 0x0000000f;
+	RCBA32(0x34) = 0x000f0000;
+	RCBA32(0x38) = 0;
+	RCBA32(0x3c) = 0x000000f0;
+	RCBA32(0x40) = 0x0f000000;
+	RCBA32(0x44) = 0;
+	RCBA32(0x48) = 0x0000f000;
+	RCBA32(0x4c) = 0;
+	RCBA32(0x50) = 0x0000000f;
+	RCBA32(0x54) = 0x000f0000;
+	RCBA32(0x58) = 0;
+	RCBA32(0x5c) = 0x000000f0;
+	RCBA32(0x60) = 0x0f000000;
+	RCBA32(0x64) = 0;
+	RCBA32(0x68) = 0x0000f000;
+	RCBA32(0x6c) = 0;
+
+	RCBA32(0x20) |= 1 << 16;
+
+	/* Enable VC1 */
+	RCBA32(0x20) |= 1 << 31;
+
+	/* Wait for VC1 */
+	while ((RCBA8(0x26) & (1 << 1)) != 0);
+
+	/* Wait for table load */
+	while ((RCBA8(0x26) & (1 << 0)) != 0);
+
+	/* ASPM on DMI link */
+	RCBA16(0x1a8) &= ~0x3;
+	reg16 = RCBA16(0x1a8);
+	RCBA32(0x2010) = (RCBA32(0x2010) & ~(0x3 << 10)) | (1 << 10);
+	reg32 = RCBA32(0x2010);
+
+	/* Set up VC1 max time */
+	RCBA32(0x1c) = (RCBA32(0x1c) & ~0x7f0000) | 0x120000;
+
+	while ((DMIBAR32(0x26) & (1 << 1)) != 0);
+	printk(BIOS_DEBUG, "Done DMI setup\n");
+
+	/* ASPM on DMI */
+	DMIBAR32(0x200) &= ~(0x3 << 26);
+	DMIBAR16(0x210) = (DMIBAR16(0x210) & ~(0xff7)) | 0x101;
+	DMIBAR32(0x88) &= ~0x3;
+	DMIBAR32(0x88) |= 0x3;
+	reg16 = DMIBAR16(0x88);
+}
+
+static void x4x_prepare_resume(int s3resume)
+{
+	int cbmem_recovered;
+
+	cbmem_recovered = !cbmem_recovery(s3resume);
+	if (!cbmem_recovered && s3resume) {
+		/* Failed S3 resume, reset to come up cleanly */
+		outb(0x6, 0xcf9);
+		halt();
+	}
+
+	romstage_handoff_init(s3resume);
+}
+
+void x4x_late_init(int s3resume)
+{
+	init_egress();
+	init_dmi();
+	x4x_prepare_resume(s3resume);
+}
diff --git a/src/northbridge/intel/x4x/pcie.c b/src/northbridge/intel/x4x/pcie.c
deleted file mode 100644
index f03869e..0000000
--- a/src/northbridge/intel/x4x/pcie.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2016 Damien Zammit <damien at zamaudio.com>
- *
- * 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.
- */
-
-#include <stdint.h>
-#include <stddef.h>
-#include <string.h>
-#include <arch/io.h>
-#include <device/pci_def.h>
-#include <device/pnp_def.h>
-#include <console/console.h>
-
-#include "iomap.h"
-#include "x4x.h"
-
-#define DEFAULT_RCBA	0xfed1c000
-#define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBA + x))
-#define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBA + x))
-#define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBA + x))
-
-static void init_egress(void)
-{
-	u32 reg32;
-
-	/* VC0: TC0 only */
-	EPBAR8(0x14) = 1;
-	EPBAR8(0x4) = 1;
-
-	switch (MCHBAR32(0xc00) & 0x7) {
-	case 0x0:
-		/* FSB 1066 */
-		EPBAR32(0x2c) = 0x0001a6db;
-		break;
-	case 0x2:
-		/* FSB 800 */
-		EPBAR32(0x2c) = 0x00014514;
-		break;
-	default:
-	case 0x4:
-		/* FSB 1333 */
-		EPBAR32(0x2c) = 0x00022861;
-		break;
-	}
-	EPBAR32(0x28) = 0x0a0a0a0a;
-	EPBAR8(0xc) = (EPBAR8(0xc) & ~0xe) | 2;
-	EPBAR32(0x1c) = (EPBAR32(0x1c) & ~0x7f0000) | 0x0a0000;
-	MCHBAR8(0x3c) = MCHBAR8(0x3c) | 0x7;
-
-	/* VC1: ID1, TC7 */
-	reg32 = (EPBAR32(0x20) & ~(7 << 24)) | (1 << 24);
-	reg32 = (reg32 & ~0xfe) | (1 << 7);
-	EPBAR32(0x20) = reg32;
-
-	/* Init VC1 port arbitration table */
-	EPBAR32(0x100) = 0x001000001;
-	EPBAR32(0x104) = 0x000040000;
-	EPBAR32(0x108) = 0x000001000;
-	EPBAR32(0x10c) = 0x000000040;
-	EPBAR32(0x110) = 0x001000001;
-	EPBAR32(0x114) = 0x000040000;
-	EPBAR32(0x118) = 0x000001000;
-	EPBAR32(0x11c) = 0x000000040;
-
-	/* Load table */
-	reg32 = EPBAR32(0x20) | (1 << 16);
-	EPBAR32(0x20) = reg32;
-	asm("nop");
-	EPBAR32(0x20) = reg32;
-
-	/* Wait for table load */
-	while ((EPBAR8(0x26) & (1 << 0)) != 0);
-
-	/* VC1: enable */
-	EPBAR32(0x20) |= 1 << 31;
-
-	/* Wait for VC1 */
-	while ((EPBAR8(0x26) & (1 << 1)) != 0);
-
-	printk(BIOS_DEBUG, "Done Egress Port\n");
-}
-
-static void init_dmi(void)
-{
-	u32 reg32;
-	u16 reg16;
-
-	/* Assume IGD present */
-
-	/* Clear error status */
-	DMIBAR32(0x1c4) = 0xffffffff;
-	DMIBAR32(0x1d0) = 0xffffffff;
-
-	/* VC0: TC0 only */
-	DMIBAR8(DMIVC0RCTL) = 1;
-	DMIBAR8(0x4) = 1;
-
-	/* VC1: ID1, TC7 */
-	reg32 = (DMIBAR32(DMIVC1RCTL) & ~(7 << 24)) | (1 << 24);
-	reg32 = (reg32 & ~0xff) | 1 << 7;
-
-	/* VC1: enable */
-	reg32 |= 1 << 31;
-	reg32 = (reg32 & ~(0x7 << 17)) | (0x4 << 17);
-
-	DMIBAR32(DMIVC1RCTL) = reg32;
-
-	/* Set up VCs in southbridge RCBA */
-	RCBA8(0x3022) &= ~1;
-
-	reg32 = (0x5 << 28) | (1 << 6); /* PCIe x4 */
-	RCBA32(0x2020) = (RCBA32(0x2020) & ~((0xf << 28) | (0x7 << 6))) | reg32;
-
-	/* Assign VC1 id 1 */
-	RCBA32(0x20) = (RCBA32(0x20) & ~(0x7 << 24)) | (1 << 24);
-
-	/* Map TC7 to VC1 */
-	RCBA8(0x20) &= 1;
-	RCBA8(0x20) |= 1 << 7;
-
-	/* Map TC0 to VC0 */
-	RCBA8(0x14) &= 1;
-
-	/* Init DMI VC1 port arbitration table */
-	RCBA32(0x20) &= 0xfff1ffff;
-	RCBA32(0x20) |= 1 << 19;
-
-	RCBA32(0x30) = 0x0000000f;
-	RCBA32(0x34) = 0x000f0000;
-	RCBA32(0x38) = 0;
-	RCBA32(0x3c) = 0x000000f0;
-	RCBA32(0x40) = 0x0f000000;
-	RCBA32(0x44) = 0;
-	RCBA32(0x48) = 0x0000f000;
-	RCBA32(0x4c) = 0;
-	RCBA32(0x50) = 0x0000000f;
-	RCBA32(0x54) = 0x000f0000;
-	RCBA32(0x58) = 0;
-	RCBA32(0x5c) = 0x000000f0;
-	RCBA32(0x60) = 0x0f000000;
-	RCBA32(0x64) = 0;
-	RCBA32(0x68) = 0x0000f000;
-	RCBA32(0x6c) = 0;
-
-	RCBA32(0x20) |= 1 << 16;
-
-	/* Enable VC1 */
-	RCBA32(0x20) |= 1 << 31;
-
-	/* Wait for VC1 */
-	while ((RCBA8(0x26) & (1 << 1)) != 0);
-
-	/* Wait for table load */
-	while ((RCBA8(0x26) & (1 << 0)) != 0);
-
-	/* ASPM on DMI link */
-	RCBA16(0x1a8) &= ~0x3;
-	reg16 = RCBA16(0x1a8);
-	RCBA32(0x2010) = (RCBA32(0x2010) & ~(0x3 << 10)) | (1 << 10);
-	reg32 = RCBA32(0x2010);
-
-	/* Set up VC1 max time */
-	RCBA32(0x1c) = (RCBA32(0x1c) & ~0x7f0000) | 0x120000;
-
-	while ((DMIBAR32(0x26) & (1 << 1)) != 0);
-	printk(BIOS_DEBUG, "Done DMI setup\n");
-
-	/* ASPM on DMI */
-	DMIBAR32(0x200) &= ~(0x3 << 26);
-	DMIBAR16(0x210) = (DMIBAR16(0x210) & ~(0xff7)) | 0x101;
-	DMIBAR32(0x88) &= ~0x3;
-	DMIBAR32(0x88) |= 0x3;
-	reg16 = DMIBAR16(0x88);
-}
-
-void x4x_late_init(void)
-{
-	init_egress();
-	init_dmi();
-}
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index 8a9cb01..32bc8fd 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -262,6 +262,17 @@ static void clkcross_ddr2(struct sysinfo *s)
 static void checkreset_ddr2(struct sysinfo *s)
 {
 	u8 pmcon2;
+	u32 pmsts;
+
+	if (s->boot_path >= 1) {
+		pmsts = MCHBAR32(PMSTS_MCHBAR);
+		if (!(pmsts & 1))
+			printk(BIOS_DEBUG,
+				"Channel 0 possibly not in self refresh\n");
+		if (!(pmsts & 2))
+			printk(BIOS_DEBUG,
+				"Channel 1 possibly not in self refresh\n");
+	}
 
 	pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
 
@@ -1476,7 +1487,6 @@ static void rcven_ddr2(struct sysinfo *s)
 		readdelay[ch] = MCHBAR16(0x400*ch + 0x588);
 	} // END EACH POPULATED CHANNEL
 
-	/* TODO: Resume support using this */
 	FOR_EACH_CHANNEL(ch) {
 		for (lane = 0; lane < 8; lane++) {
 			MCHBAR8(0x400*ch + 0x560 + (lane*4)) =
@@ -1556,7 +1566,8 @@ static void sdram_program_receive_enable(struct sysinfo *s)
 	RCBA32(0x3400) = (1 << 2);
 
 	/* Program Receive Enable Timings */
-	if (s->boot_path == BOOT_PATH_WARM_RESET) {
+	if ((s->boot_path == BOOT_PATH_WARM_RESET)
+		|| (s->boot_path == BOOT_PATH_RESUME)) {
 		sdram_recover_receive_enable();
 	} else {
 		rcven_ddr2(s);
@@ -2044,7 +2055,8 @@ void raminit_ddr2(struct sysinfo *s)
 	printk(BIOS_DEBUG, "Done pre-jedec\n");
 
 	// JEDEC reset
-	jedec_ddr2(s);
+	if (s->boot_path != BOOT_PATH_RESUME)
+		jedec_ddr2(s);
 
 	printk(BIOS_DEBUG, "Done jedec steps\n");
 
diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h
index 66d765a..faae775 100644
--- a/src/northbridge/intel/x4x/x4x.h
+++ b/src/northbridge/intel/x4x/x4x.h
@@ -322,7 +322,7 @@ enum ddr2_signals {
 
 #ifndef __BOOTBLOCK__
 void x4x_early_init(void);
-void x4x_late_init(void);
+void x4x_late_init(int s3resume);
 u32 decode_igd_memory_size(u32 gms);
 u32 decode_igd_gtt_size(u32 gsm);
 u8 decode_pciebar(u32 *const base, u32 *const len);



More information about the coreboot-gerrit mailing list