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 <siro@das-labor.org> Signed-off-by: Alexander Couzens <lynxis@fe80.eu> Signed-off-by: Felix Held <felix-coreboot@felixheld.de> Signed-off-by: Jonathan A. Kollasch <jakllsch@kollasch.net> Reviewed-on: https://review.coreboot.org/c/coreboot/+/22214 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
parent
48d5b8d463
commit
05d4bf7ea7
|
@ -214,6 +214,23 @@ static void save_timings(ramctr_timing *ctrl)
|
||||||
mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, ctrl, sizeof(*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)
|
static void init_dram_ddr3(int min_tck, int s3resume, const u32 cpuid)
|
||||||
{
|
{
|
||||||
int me_uma_size, cbmem_was_inited, fast_boot, err;
|
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) {
|
if (!fast_boot) {
|
||||||
/* Reset internal state */
|
/* Reset internal state */
|
||||||
memset(&ctrl, 0, sizeof(ctrl));
|
reinit_ctrl(&ctrl, min_tck, cpuid);
|
||||||
ctrl.tCK = min_tck;
|
|
||||||
|
|
||||||
/* Get architecture */
|
printk(BIOS_INFO, "ECC RAM %s.\n", ctrl.ecc_forced ? "required" :
|
||||||
ctrl.cpu = cpuid;
|
ctrl.ecc_supported ? "supported" : "unsupported");
|
||||||
|
|
||||||
/* Get DDR3 SPD data */
|
/* Get DDR3 SPD data */
|
||||||
memset(spds, 0, sizeof(spds));
|
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");
|
printram("Disable failing channel.\n");
|
||||||
|
|
||||||
/* Reset internal state */
|
/* Reset internal state */
|
||||||
memset(&ctrl, 0, sizeof(ctrl));
|
reinit_ctrl(&ctrl, min_tck, cpuid);
|
||||||
ctrl.tCK = min_tck;
|
|
||||||
|
|
||||||
/* Get architecture */
|
|
||||||
ctrl.cpu = cpuid;
|
|
||||||
|
|
||||||
/* Reset DDR3 frequency */
|
/* Reset DDR3 frequency */
|
||||||
dram_find_spds_ddr3(spds, &ctrl);
|
dram_find_spds_ddr3(spds, &ctrl);
|
||||||
|
|
|
@ -437,6 +437,32 @@ static unsigned int get_mmio_size(void)
|
||||||
return cfg->pci_mmio_size;
|
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)
|
void dram_memorymap(ramctr_timing *ctrl, int me_uma_size)
|
||||||
{
|
{
|
||||||
u32 reg, val, reclaim, tom, gfxstolen, gttsize;
|
u32 reg, val, reclaim, tom, gfxstolen, gttsize;
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
/*
|
/*
|
||||||
* WARNING: Do not forget to increase MRC_CACHE_VERSION when the saved data is changed!
|
* 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 {
|
typedef struct odtmap_st {
|
||||||
u16 rttwr;
|
u16 rttwr;
|
||||||
|
@ -132,6 +132,8 @@ typedef struct ramctr_timing_st {
|
||||||
int pi_code_offset;
|
int pi_code_offset;
|
||||||
int pi_coding_threshold;
|
int pi_coding_threshold;
|
||||||
|
|
||||||
|
bool ecc_supported;
|
||||||
|
bool ecc_forced;
|
||||||
int edge_offset[3];
|
int edge_offset[3];
|
||||||
int timC_offset[3];
|
int timC_offset[3];
|
||||||
|
|
||||||
|
@ -191,4 +193,7 @@ void final_registers(ramctr_timing *ctrl);
|
||||||
void restore_timings(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);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue