Arthur Heymans (arthur@aheymans.xyz) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18009
-gerrit
commit 0ac270af783d0d113848b18f6be86e577039f039 Author: Arthur Heymans arthur@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@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..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..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,