From 05d4bf7ea76114dcbd21f8302e7152f40d806f18 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Sat, 28 Oct 2017 16:36:09 +0200 Subject: nb/intel/sandybridge/raminit: Add ECC detection support Add support for detection ECC capability and forced ECC mode. Print the ECC mode in verbose debugging mode. Change-Id: I5b7599746195cfa996a48320404a8dbe6820483a Signed-off-by: Patrick Rudolph Signed-off-by: Alexander Couzens Signed-off-by: Felix Held Signed-off-by: Jonathan A. Kollasch Reviewed-on: https://review.coreboot.org/c/coreboot/+/22214 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/northbridge/intel/sandybridge/raminit.c | 30 +++++++++++++++------- src/northbridge/intel/sandybridge/raminit_common.c | 26 +++++++++++++++++++ src/northbridge/intel/sandybridge/raminit_common.h | 7 ++++- 3 files changed, 53 insertions(+), 10 deletions(-) (limited to 'src/northbridge/intel/sandybridge') diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c index b096a11bf2..a938a49172 100644 --- a/src/northbridge/intel/sandybridge/raminit.c +++ b/src/northbridge/intel/sandybridge/raminit.c @@ -214,6 +214,23 @@ static void save_timings(ramctr_timing *ctrl) mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, ctrl, sizeof(*ctrl)); } +static void reinit_ctrl(ramctr_timing *ctrl, int min_tck, const u32 cpuid) +{ + /* Reset internal state */ + memset(ctrl, 0, sizeof(*ctrl)); + ctrl->tCK = min_tck; + + /* Get architecture */ + ctrl->cpu = cpuid; + + /* Get ECC support and mode */ + ctrl->ecc_forced = get_host_ecc_forced(); + ctrl->ecc_supported = ctrl->ecc_forced || get_host_ecc_cap(); + printk(BIOS_DEBUG, "ECC supported: %s ECC forced: %s\n", + ctrl->ecc_supported ? "yes" : "no", + ctrl->ecc_forced ? "yes" : "no"); +} + static void init_dram_ddr3(int min_tck, int s3resume, const u32 cpuid) { int me_uma_size, cbmem_was_inited, fast_boot, err; @@ -300,11 +317,10 @@ static void init_dram_ddr3(int min_tck, int s3resume, const u32 cpuid) } if (!fast_boot) { /* Reset internal state */ - memset(&ctrl, 0, sizeof(ctrl)); - ctrl.tCK = min_tck; + reinit_ctrl(&ctrl, min_tck, cpuid); - /* Get architecture */ - ctrl.cpu = cpuid; + printk(BIOS_INFO, "ECC RAM %s.\n", ctrl.ecc_forced ? "required" : + ctrl.ecc_supported ? "supported" : "unsupported"); /* Get DDR3 SPD data */ memset(spds, 0, sizeof(spds)); @@ -320,11 +336,7 @@ static void init_dram_ddr3(int min_tck, int s3resume, const u32 cpuid) printram("Disable failing channel.\n"); /* Reset internal state */ - memset(&ctrl, 0, sizeof(ctrl)); - ctrl.tCK = min_tck; - - /* Get architecture */ - ctrl.cpu = cpuid; + reinit_ctrl(&ctrl, min_tck, cpuid); /* Reset DDR3 frequency */ dram_find_spds_ddr3(spds, &ctrl); diff --git a/src/northbridge/intel/sandybridge/raminit_common.c b/src/northbridge/intel/sandybridge/raminit_common.c index 4ba5b5900f..9642a55b31 100644 --- a/src/northbridge/intel/sandybridge/raminit_common.c +++ b/src/northbridge/intel/sandybridge/raminit_common.c @@ -437,6 +437,32 @@ static unsigned int get_mmio_size(void) return cfg->pci_mmio_size; } +/* + * Returns the ECC mode the NB is running at. It takes precedence over ECC capability. + * The ME/PCU/.. has the ability to change this. + * Return 0: ECC is optional + * Return 1: ECC is forced + */ +bool get_host_ecc_forced(void) +{ + /* read Capabilities A Register */ + const u32 reg32 = pci_read_config32(HOST_BRIDGE, CAPID0_A); + return !!(reg32 & (1 << 24)); +} + +/* + * Returns the ECC capability. + * The ME/PCU/.. has the ability to change this. + * Return 0: ECC is disabled + * Return 1: ECC is possible + */ +bool get_host_ecc_cap(void) +{ + /* read Capabilities A Register */ + const u32 reg32 = pci_read_config32(HOST_BRIDGE, CAPID0_A); + return !(reg32 & (1 << 25)); +} + void dram_memorymap(ramctr_timing *ctrl, int me_uma_size) { u32 reg, val, reclaim, tom, gfxstolen, gttsize; diff --git a/src/northbridge/intel/sandybridge/raminit_common.h b/src/northbridge/intel/sandybridge/raminit_common.h index fef4419ffc..ea3d66687e 100644 --- a/src/northbridge/intel/sandybridge/raminit_common.h +++ b/src/northbridge/intel/sandybridge/raminit_common.h @@ -43,7 +43,7 @@ /* * WARNING: Do not forget to increase MRC_CACHE_VERSION when the saved data is changed! */ -#define MRC_CACHE_VERSION 3 +#define MRC_CACHE_VERSION 4 typedef struct odtmap_st { u16 rttwr; @@ -132,6 +132,8 @@ typedef struct ramctr_timing_st { int pi_code_offset; int pi_coding_threshold; + bool ecc_supported; + bool ecc_forced; int edge_offset[3]; int timC_offset[3]; @@ -191,4 +193,7 @@ void final_registers(ramctr_timing *ctrl); void restore_timings(ramctr_timing *ctrl); int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot, int s3resume, int me_uma_size); +bool get_host_ecc_cap(void); +bool get_host_ecc_forced(void); + #endif -- cgit v1.2.3