Arthur Heymans (arthur@aheymans.xyz) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17998
-gerrit
commit 01aafc2b8d33dd26519c1deb91339837fe78471b Author: Arthur Heymans arthur@aheymans.xyz Date: Fri Dec 30 21:07:18 2016 +0100
nb/intel/x4x: Implement resume from S3 suspend
It stores the results of receive enable in 256 bits in the unused upper 1024 bits sized region of nvram.
Change-Id: Ib54bc5c7b0fed6d975ffc31f037b5179d9e5600b Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- src/mainboard/gigabyte/ga-g41m-es2l/Kconfig | 1 + src/mainboard/gigabyte/ga-g41m-es2l/cmos.layout | 1 + src/mainboard/gigabyte/ga-g41m-es2l/romstage.c | 8 +- src/northbridge/intel/x4x/pcie.c | 15 +++- src/northbridge/intel/x4x/raminit_ddr2.c | 102 +++++++++++++++++++++--- src/northbridge/intel/x4x/x4x.h | 5 +- 6 files changed, 114 insertions(+), 18 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/cmos.layout b/src/mainboard/gigabyte/ga-g41m-es2l/cmos.layout index 3138479..cee6fe9 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 h 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..dd2fab6 100644 --- a/src/mainboard/gigabyte/ga-g41m-es2l/romstage.c +++ b/src/mainboard/gigabyte/ga-g41m-es2l/romstage.c @@ -136,6 +136,7 @@ void mainboard_romstage_entry(unsigned long bist) { // ch0 ch1 const u8 spd_addrmap[4] = { 0x50, 0, 0x52, 0 }; + u8 s3resume = 0;
/* Disable watchdog timer */ RCBA32(0x3410) = RCBA32(0x3410) | 0x20; @@ -155,13 +156,14 @@ void mainboard_romstage_entry(unsigned long bist)
x4x_early_init();
+ s3resume = southbridge_detect_s3_resume(); + printk(BIOS_DEBUG, "Initializing memory\n"); - sdram_initialize(0, spd_addrmap); + sdram_initialize(s3resume ? 2 : 0, spd_addrmap); quick_ram_check(); - cbmem_initialize_empty(); printk(BIOS_DEBUG, "Memory initialized\n");
- x4x_late_init(); + x4x_late_init(s3resume);
printk(BIOS_DEBUG, "x4x late init complete\n");
diff --git a/src/northbridge/intel/x4x/pcie.c b/src/northbridge/intel/x4x/pcie.c index f03869e..648f10d 100644 --- a/src/northbridge/intel/x4x/pcie.c +++ b/src/northbridge/intel/x4x/pcie.c @@ -18,10 +18,11 @@ #include <stddef.h> #include <string.h> #include <arch/io.h> +#include <cbmem.h> #include <device/pci_def.h> #include <device/pnp_def.h> #include <console/console.h> - +#include <romstage_handoff.h> #include "iomap.h" #include "x4x.h"
@@ -184,8 +185,18 @@ static void init_dmi(void) reg16 = DMIBAR16(0x88); }
-void x4x_late_init(void) +static void x4x_prepare_resume(int s3resume) +{ + int cbmem_was_initted; + + cbmem_was_initted = !cbmem_recovery(s3resume); + + romstage_handoff_init(cbmem_was_initted && s3resume); +} + +void x4x_late_init(int s3resume) { init_egress(); init_dmi(); + x4x_prepare_resume(s3resume); } diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c index de62517..eff0333 100644 --- a/src/northbridge/intel/x4x/raminit_ddr2.c +++ b/src/northbridge/intel/x4x/raminit_ddr2.c @@ -20,6 +20,8 @@ #include <console/console.h> #include <commonlib/helpers.h> #include <delay.h> +#include <pc80/mc146818rtc.h> +#include <southbridge/intel/i82801ix/i82801ix.h> #include "iomap.h" #include "x4x.h"
@@ -1502,6 +1504,79 @@ 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_RESUME) { + 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; @@ -1973,7 +2048,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_NORMAL) + jedec_ddr2(s);
printk(BIOS_DEBUG, "Done jedec steps\n");
@@ -2005,7 +2081,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 @@ -2020,16 +2096,18 @@ void raminit_ddr2(struct sysinfo *s) MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
// Dummy writes / reads - volatile u32 data; - FOR_EACH_POPULATED_RANK(s->dimms, ch, r) { - for (bank = 0; bank < 4; bank++) { - reg32 = (ch << 29) | (r*0x8000000) | (bank << 12); - write32((u32 *)reg32, 0xffffffff); - data = read32((u32 *)reg32); - printk(BIOS_DEBUG, "Wrote ones, Read: [0x%08x]=0x%08x\n", reg32, data); - write32((u32 *)reg32, 0x00000000); - data = read32((u32 *)reg32); - printk(BIOS_DEBUG, "Wrote zeros, Read: [0x%08x]=0x%08x\n", reg32, data); + if (s->boot_path == BOOT_PATH_NORMAL) { + volatile u32 data; + FOR_EACH_POPULATED_RANK(s->dimms, ch, r) { + for (bank = 0; bank < 4; bank++) { + reg32 = (ch << 29) | (r*0x8000000) | (bank << 12); + write32((u32 *)reg32, 0xffffffff); + data = read32((u32 *)reg32); + printk(BIOS_DEBUG, "Wrote ones, Read: [0x%08x]=0x%08x\n", reg32, data); + write32((u32 *)reg32, 0x00000000); + data = read32((u32 *)reg32); + printk(BIOS_DEBUG, "Wrote zeros, Read: [0x%08x]=0x%08x\n", reg32, data); + } } } printk(BIOS_DEBUG, "Done dummy reads\n"); diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index 7ca634f..ce4463e 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, @@ -319,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);