[coreboot-gerrit] Change in coreboot[master]: nb/intel/x4x: Use SPI flash to cache raminit results
Arthur Heymans (Code Review)
gerrit at coreboot.org
Mon Sep 25 12:53:22 CEST 2017
Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/21677
Change subject: nb/intel/x4x: Use SPI flash to cache raminit results
......................................................................
nb/intel/x4x: Use SPI flash to cache raminit results
Stores information obtained from decoding dimms and receive enable
results for future use.
Depreciates using rtc nvram to store receive enable settings.
A notable change is that receive enable results are always reused, not
just on a resume from S3.
TODO: With dimms with a working SPD chip with invalid content this
patch will result in normal boot each time except on resume from S3.
TESTED on Intel DG43GT with W25Q128.V.
Change-Id: I042dc5c52615d40781d9ef7ecd657ad0bf3ed08f
Signed-off-by: Arthur Heymans <arthur at aheymans.xyz>
---
M src/northbridge/intel/x4x/Kconfig
M src/northbridge/intel/x4x/Makefile.inc
M src/northbridge/intel/x4x/early_init.c
M src/northbridge/intel/x4x/raminit.c
M src/northbridge/intel/x4x/raminit_ddr2.c
M src/northbridge/intel/x4x/rcven.c
M src/northbridge/intel/x4x/x4x.h
7 files changed, 153 insertions(+), 87 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/77/21677/1
diff --git a/src/northbridge/intel/x4x/Kconfig b/src/northbridge/intel/x4x/Kconfig
index 9239637..23c20b5 100644
--- a/src/northbridge/intel/x4x/Kconfig
+++ b/src/northbridge/intel/x4x/Kconfig
@@ -28,6 +28,7 @@
select RELOCATABLE_RAMSTAGE
select HAVE_LINEAR_FRAMEBUFFER if MAINBOARD_DO_NATIVE_VGA_INIT
select HAVE_VGA_TEXT_FRAMEBUFFER if MAINBOARD_DO_NATIVE_VGA_INIT
+ select NORTHBRIDGE_INTEL_COMMON_MRC_CACHE
config CBFS_SIZE
hex
@@ -45,4 +46,8 @@
hex
default 0xe0000000
+config MRC_CACHE_SIZE
+ hex
+ default 0x10000
+
endif
diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc
index 5c64ca7..7661ec3 100644
--- a/src/northbridge/intel/x4x/Makefile.inc
+++ b/src/northbridge/intel/x4x/Makefile.inc
@@ -27,4 +27,15 @@
ramstage-y += gma.c
ramstage-y += northbridge.c
+$(obj)/mrc.cache: $(obj)/config.h
+ dd if=/dev/zero count=1 \
+ bs=$(shell printf "%d" $(CONFIG_MRC_CACHE_SIZE) ) | \
+ tr '\000' '\377' > $@
+
+cbfs-files-y += mrc.cache
+mrc.cache-file := $(obj)/mrc.cache
+mrc.cache-align := 0x10000
+mrc.cache-type := mrc_cache
+
+
endif
diff --git a/src/northbridge/intel/x4x/early_init.c b/src/northbridge/intel/x4x/early_init.c
index 27fe916..f463840 100644
--- a/src/northbridge/intel/x4x/early_init.c
+++ b/src/northbridge/intel/x4x/early_init.c
@@ -235,15 +235,6 @@
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);
}
diff --git a/src/northbridge/intel/x4x/raminit.c b/src/northbridge/intel/x4x/raminit.c
index d5298f6..ac8b576 100644
--- a/src/northbridge/intel/x4x/raminit.c
+++ b/src/northbridge/intel/x4x/raminit.c
@@ -33,10 +33,38 @@
#include <spd.h>
#include <string.h>
#include <device/dram/ddr2.h>
+#include <northbridge/intel/common/mrc_cache.h>
static inline int spd_read_byte(unsigned int device, unsigned int address)
{
return smbus_read_byte(device, address);
+}
+
+static int verify_spds(const u8 *spd_map, struct sysinfo *ctrl_cached)
+{
+ int i;
+ int checksum;
+
+ for (i = 0; i < TOTAL_DIMMS; i++) {
+ checksum = 0;
+ if (!(spd_map[i]))
+ continue;
+ if (ctrl_cached->spd_type == DDR2) {
+ checksum = spd_read_byte(spd_map[i], 63);
+ } else { /* DDR3 */
+ checksum = spd_read_byte(spd_map[i], 126);
+ checksum |= spd_read_byte(spd_map[i], 127) << 8;
+ }
+ if (checksum < 0 && ctrl_cached->dimms[i].card_type
+ == RAW_CARD_UNPOPULATED)
+ continue;
+ if (checksum > 0 && ctrl_cached->dimms[i].card_type
+ == RAW_CARD_UNPOPULATED)
+ return CB_ERR;
+ if ((checksum & 0xffff) != ctrl_cached->dimms[i].checksum)
+ return CB_ERR;
+ }
+ return CB_SUCCESS;
}
struct abs_timings {
@@ -190,6 +218,7 @@
MAX(saved_timings->min_tCLK_cas[i],
decoded_dimm.cycle_time[i]);
}
+ s->dimms[dimm_idx].checksum = decoded_dimm.checksum;
return CB_SUCCESS;
}
@@ -380,8 +409,10 @@
*/
void sdram_initialize(int boot_path, const u8 *spd_map)
{
- struct sysinfo s;
+ struct sysinfo s, *ctrl_cached;
u8 reg8;
+ int fast_boot, cbmem_was_inited;
+ struct mrc_data_container *mrc_cache;
printk(BIOS_DEBUG, "Setting up RAM controller.\n");
@@ -389,28 +420,60 @@
memset(&s, 0, sizeof(struct sysinfo));
- s.boot_path = boot_path;
- s.spd_map[0] = spd_map[0];
- s.spd_map[1] = spd_map[1];
- s.spd_map[2] = spd_map[2];
- s.spd_map[3] = spd_map[3];
+ mrc_cache = find_current_mrc_cache();
+ if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(s))) {
+ if (boot_path == BOOT_PATH_RESUME) {
+ /* Failed S3 resume, reset to come up cleanly */
+ outb(0x6, 0xcf9);
+ halt();
+ }
+ ctrl_cached = NULL;
+ } else {
+ ctrl_cached = (struct sysinfo *)mrc_cache->mrc_data;
+ }
- checkreset_ddr2(s.boot_path);
+ /* verify MRC cache for fast boot */
+ if (boot_path != BOOT_PATH_RESUME && ctrl_cached) {
+ /* check SPD checksum to make sure the DIMMs haven't been
+ * replaced */
+ fast_boot = verify_spds(spd_map, ctrl_cached) == CB_SUCCESS;
+ if (!fast_boot)
+ printk(BIOS_DEBUG, "SPD checksums don't match,"
+ " dimm's have been replaced\n");
+ } else {
+ fast_boot = boot_path == BOOT_PATH_RESUME;
+ }
- /* Detect dimms per channel */
- reg8 = pci_read_config8(PCI_DEV(0, 0, 0), 0xe9);
- printk(BIOS_DEBUG, "Dimms per channel: %d\n", (reg8 & 0x10) ? 1 : 2);
+ if (fast_boot) {
+ printk(BIOS_DEBUG, "Using cached raminit settings\n");
+ memcpy(&s, ctrl_cached, sizeof(s));
+ s.boot_path = boot_path;
+ mchinfo_ddr2(&s);
+ print_selected_timings(&s);
+ } else {
+ s.boot_path = boot_path;
+ s.spd_map[0] = spd_map[0];
+ s.spd_map[1] = spd_map[1];
+ s.spd_map[2] = spd_map[2];
+ s.spd_map[3] = spd_map[3];
+ checkreset_ddr2(s.boot_path);
- mchinfo_ddr2(&s);
+ /* Detect dimms per channel */
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 0), 0xe9);
+ printk(BIOS_DEBUG, "Dimms per channel: %d\n",
+ (reg8 & 0x10) ? 1 : 2);
- find_fsb_speed(&s);
- decode_spd_select_timings(&s);
- print_selected_timings(&s);
- find_dimm_config(&s);
+ mchinfo_ddr2(&s);
+
+ find_fsb_speed(&s);
+ decode_spd_select_timings(&s);
+ print_selected_timings(&s);
+ find_dimm_config(&s);
+ }
switch (s.spd_type) {
case DDR2:
- raminit_ddr2(&s);
+ raminit_ddr2(&s, fast_boot);
break;
case DDR3:
// FIXME Add: raminit_ddr3(&s);
@@ -426,4 +489,13 @@
reg8 = pci_read_config8(PCI_DEV(0, 0, 0), 0xf4);
pci_write_config8(PCI_DEV(0, 0, 0), 0xf4, reg8 | 1);
printk(BIOS_DEBUG, "RAM initialization finished.\n");
+
+ cbmem_was_inited = !cbmem_recovery(s.boot_path == BOOT_PATH_RESUME);
+ if (!fast_boot)
+ store_current_mrc_cache(&s, sizeof(s));
+ if (s.boot_path == BOOT_PATH_RESUME && !cbmem_was_inited) {
+ /* Failed S3 resume, reset to come up cleanly */
+ outb(0x6, 0xcf9);
+ halt();
+ }
}
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index 079dcde..b9f11ab 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -1048,77 +1048,49 @@
printk(BIOS_DEBUG, "MRS done\n");
}
-static void sdram_save_receive_enable(void)
+static void sdram_recover_receive_enable(struct sysinfo *s)
{
- int i = 0;
- u16 reg16;
- u8 values[18];
- u8 lane, ch;
-
- FOR_EACH_CHANNEL(ch) {
- lane = 0;
- while (lane < 8) {
- values[i] = (MCHBAR8(0x400*ch + 0x560 + lane++ * 4) & 0xf);
- values[i++] |= (MCHBAR8(0x400*ch + 0x560 + lane++ * 4) & 0xf) << 4;
- }
- values[i++] = (MCHBAR32(0x400*ch + 0x248) >> 16) & 0xf;
- reg16 = MCHBAR16(0x400*ch + 0x5fa);
- values[i++] = reg16 & 0xff;
- values[i++] = (reg16 >> 8) & 0xff;
- reg16 = MCHBAR16(0x400*ch + 0x58c);
- values[i++] = reg16 & 0xff;
- values[i++] = (reg16 >> 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;
u32 reg32;
- u16 reg16;
- u8 values[18];
- u8 ch, lane;
+ u16 medium, coarse_offset;
+ u8 pitap;
+ int lane, channel;
- for (i = 0; i < ARRAY_SIZE(values); i++)
- values[i] = cmos_read(128 + i);
+ FOR_EACH_POPULATED_CHANNEL(s->dimms, channel) {
+ medium = 0;
+ coarse_offset = 0;
+ reg32 = MCHBAR32(0x400 * channel + 0x248);
+ reg32 &= ~0xf0000;
+ reg32 |= s->rcven_t[channel].min_common_coarse << 16;
+ MCHBAR32(0x400 * channel + 0x248) = reg32;
- i = 0;
- FOR_EACH_CHANNEL(ch) {
- lane = 0;
- while (lane < 8) {
- MCHBAR8(0x400*ch + 0x560 + lane++ * 4) = 0x70 |
- (values[i] & 0xf);
- MCHBAR8(0x400*ch + 0x560 + lane++ * 4) = 0x70 |
- ((values[i++] >> 4) & 0xf);
+ for (lane = 0; lane < 8; lane++) {
+ medium |= s->rcven_t[channel].medium[lane]
+ << (lane * 2);
+ coarse_offset |=
+ (s->rcven_t[channel].coarse_offset[lane] & 0x3)
+ << (lane * 2);
+
+ pitap = MCHBAR8(0x400 * channel + 0x560 + lane * 4);
+ pitap &= ~0x7f;
+ pitap |= s->rcven_t[channel].tap[lane];
+ pitap |= s->rcven_t[channel].pi[lane];
+ MCHBAR8(0x400 * channel + 0x560 + lane * 4) = pitap;
}
- reg32 = (MCHBAR32(0x400*ch + 0x248) & ~0xf0000)
- | ((values[i++] & 0xf) << 16);
- MCHBAR32(0x400*ch + 0x248) = reg32;
- reg16 = values[i++];
- reg16 |= values[i++] << 8;
- MCHBAR16(0x400*ch + 0x5fa) = reg16;
- reg16 = values[i++];
- reg16 |= values[i++] << 8;
- MCHBAR16(0x400*ch + 0x58c) = reg16;
+ MCHBAR16(0x400 * channel + 0x58c) = medium;
+ MCHBAR16(0x400 * channel + 0x5fa) = coarse_offset;
}
}
-static void sdram_program_receive_enable(struct sysinfo *s)
+static void sdram_program_receive_enable(struct sysinfo *s, int fast_boot)
{
/* enable upper CMOS */
RCBA32(0x3400) = (1 << 2);
/* Program Receive Enable Timings */
- if ((s->boot_path == BOOT_PATH_WARM_RESET)
- || (s->boot_path == BOOT_PATH_RESUME)) {
- sdram_recover_receive_enable();
- } else {
+ if (fast_boot)
+ sdram_recover_receive_enable(s);
+ else
rcven(s);
- sdram_save_receive_enable();
- }
}
static void dradrb_ddr2(struct sysinfo *s)
@@ -1473,7 +1445,7 @@
MCHBAR8(0x561 + (lane << 2)) = MCHBAR8(0x561 + (lane << 2)) & ~(1 << 3);
}
-void raminit_ddr2(struct sysinfo *s)
+void raminit_ddr2(struct sysinfo *s, int fast_boot)
{
u8 ch;
u8 r, bank;
@@ -1616,7 +1588,7 @@
}
// Receive enable
- sdram_program_receive_enable(s);
+ sdram_program_receive_enable(s, fast_boot);
printk(BIOS_DEBUG, "Done rcven\n");
// Finish rcven
diff --git a/src/northbridge/intel/x4x/rcven.c b/src/northbridge/intel/x4x/rcven.c
index 23f8d52..7ad1e0a 100644
--- a/src/northbridge/intel/x4x/rcven.c
+++ b/src/northbridge/intel/x4x/rcven.c
@@ -304,7 +304,7 @@
return 0;
}
-void rcven(const struct sysinfo *s)
+void rcven(struct sysinfo *s)
{
int i;
u8 channel, lane, reg8;
@@ -354,6 +354,7 @@
mincoarse = timing[lane].coarse;
}
printk(BIOS_DEBUG, "Found min coarse value = %d\n", mincoarse);
+ s->rcven_t[channel].min_common_coarse = mincoarse;
printk(BIOS_DEBUG, "Receive enable, final timings:\n");
/* Normalise coarse */
for (lane = 0; lane < 8; lane++) {
@@ -365,6 +366,10 @@
"medium: %d; tap: %d\n",
channel, lane, reg8, timing[lane].medium,
timing[lane].tap);
+ s->rcven_t[channel].coarse_offset[lane] = reg8;
+ s->rcven_t[channel].medium[lane] = timing[lane].medium;
+ s->rcven_t[channel].tap[lane] = timing[lane].tap;
+ s->rcven_t[channel].pi[lane] = timing[lane].pi;
MCHBAR16(0x400 * channel + 0x5fa) &=
~(3 << (lane * 2)) | (reg8 << (lane * 2));
}
diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h
index e4147a1..2fffe8b 100644
--- a/src/northbridge/intel/x4x/x4x.h
+++ b/src/northbridge/intel/x4x/x4x.h
@@ -276,6 +276,15 @@
unsigned int ranks;
unsigned int rows;
unsigned int cols;
+ u16 checksum;
+};
+
+struct rcven_timings {
+ u8 min_common_coarse;
+ u8 coarse_offset[8];
+ u8 medium[8];
+ u8 tap[8];
+ u8 pi[8];
};
/* The setup is up to two DIMMs per channel */
@@ -290,6 +299,7 @@
struct timings selected_timings;
struct dimminfo dimms[4];
u8 spd_map[4];
+ struct rcven_timings rcven_t[TOTAL_CHANNELS];
};
#define BOOT_PATH_NORMAL 0
#define BOOT_PATH_WARM_RESET 1
@@ -328,8 +338,8 @@
u32 decode_igd_gtt_size(u32 gsm);
u8 decode_pciebar(u32 *const base, u32 *const len);
void sdram_initialize(int boot_path, const u8 *spd_map);
-void raminit_ddr2(struct sysinfo *);
-void rcven(const struct sysinfo *);
+void raminit_ddr2(struct sysinfo *s, int fast_boot);
+void rcven(struct sysinfo *s);
u32 fsb2mhz(u32 speed);
u32 ddr2mhz(u32 speed);
--
To view, visit https://review.coreboot.org/21677
To unsubscribe, visit https://review.coreboot.org/settings
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I042dc5c52615d40781d9ef7ecd657ad0bf3ed08f
Gerrit-Change-Number: 21677
Gerrit-PatchSet: 1
Gerrit-Owner: Arthur Heymans <arthur at aheymans.xyz>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20170925/1f1dc2d0/attachment-0001.html>
More information about the coreboot-gerrit
mailing list