nb/intel/sandybridge/raminit: Add ECC support
Add ECC support for native raminit on SandyBridge/IvyBridge. Change-Id: I1206746332c9939a78b67e7b48d3098bdef8a2ed Signed-off-by: Patrick Rudolph <siro@das-labor.org>
This commit is contained in:
parent
8bd589d1b5
commit
edc51a9af2
|
@ -119,6 +119,12 @@ config DCACHE_RAM_MRC_VAR_SIZE
|
|||
hex
|
||||
default 0x0
|
||||
|
||||
config RAMINIT_ENABLE_ECC
|
||||
bool "Enable ECC if supported"
|
||||
default y
|
||||
help
|
||||
Enable ECC if supported by both, host and RAM.
|
||||
|
||||
config RAMINIT_EXTENDED_MEMTEST
|
||||
bool "Run extended memtest on raminit"
|
||||
default n
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "raminit_common.h"
|
||||
#include "sandybridge.h"
|
||||
|
||||
/* FIXME: no ECC support. */
|
||||
/* FIXME: no support for 3-channel chipsets. */
|
||||
|
||||
static const char *ecc_decoder[] = {
|
||||
|
@ -195,6 +194,7 @@ static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
|
|||
{
|
||||
int dimms = 0, dimms_on_channel;
|
||||
int channel, slot, spd_slot;
|
||||
size_t supports_ecc = 1;
|
||||
dimm_info *dimm = &ctrl->info;
|
||||
|
||||
memset (ctrl->rankmap, 0, sizeof(ctrl->rankmap));
|
||||
|
@ -262,6 +262,9 @@ static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
|
|||
ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
|
||||
ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
|
||||
|
||||
if (!dimm->dimm[channel][slot].flags.is_ecc)
|
||||
supports_ecc = 0;
|
||||
|
||||
ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
|
||||
ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
|
||||
|
||||
|
@ -285,6 +288,19 @@ static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
|
|||
ctrl->ref_card_offset[channel] = 0;
|
||||
}
|
||||
|
||||
if (ctrl->ecc_supported) {
|
||||
if (ctrl->ecc_forced && !supports_ecc)
|
||||
die("ECC mode forced but non ECC DIMM installed !");
|
||||
|
||||
if (ctrl->ecc_forced ||
|
||||
(IS_ENABLED(CONFIG_RAMINIT_ENABLE_ECC) && supports_ecc))
|
||||
ctrl->ecc_enabled = 1;
|
||||
}
|
||||
printk(BIOS_DEBUG, "ECC is %s\n",
|
||||
ctrl->ecc_enabled ? "enabled" : "disabled");
|
||||
|
||||
ctrl->lanes = ctrl->ecc_enabled ? 9 : 8;
|
||||
|
||||
if (!dimms)
|
||||
die("No DIMMs were found");
|
||||
}
|
||||
|
|
|
@ -337,12 +337,21 @@ void dram_dimm_mapping(ramctr_timing *ctrl)
|
|||
}
|
||||
}
|
||||
|
||||
void dram_dimm_set_mapping(ramctr_timing * ctrl)
|
||||
void dram_dimm_set_mapping(ramctr_timing *ctrl, int training)
|
||||
{
|
||||
int channel;
|
||||
u32 ecc;
|
||||
|
||||
if (ctrl->ecc_enabled)
|
||||
ecc = training ? (1 << 24) : (3 << 24);
|
||||
else
|
||||
ecc = 0;
|
||||
|
||||
FOR_ALL_CHANNELS {
|
||||
MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
|
||||
MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel] | ecc;
|
||||
}
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
void dram_zones(ramctr_timing * ctrl, int training)
|
||||
|
@ -2190,13 +2199,13 @@ static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
|
|||
lanes_ok |= 1 << lane;
|
||||
}
|
||||
ctr++;
|
||||
if (lanes_ok == ((1 << NUM_LANES) - 1))
|
||||
if (lanes_ok == ((1 << ctrl->lanes) - 1))
|
||||
break;
|
||||
}
|
||||
|
||||
ctrl->timings[channel][slotrank] = saved_rt;
|
||||
|
||||
return lanes_ok != ((1 << NUM_LANES) - 1);
|
||||
return lanes_ok != ((1 << ctrl->lanes) - 1);
|
||||
}
|
||||
|
||||
#include "raminit_patterns.h"
|
||||
|
@ -3110,6 +3119,47 @@ int channel_test(ramctr_timing *ctrl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void channel_scrub(ramctr_timing *ctrl)
|
||||
{
|
||||
|
||||
int channel, slotrank, bank, row;
|
||||
int rowsize;
|
||||
|
||||
FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
|
||||
rowsize = 1 << ctrl->info.dimm[channel][slotrank>>1].row_bits;
|
||||
for (bank = 0; bank < 8; bank++) {
|
||||
for (row = 0; row < rowsize; row += 16) {
|
||||
|
||||
wait_428c(channel);
|
||||
/* DRAM command ACT */
|
||||
write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
|
||||
write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10),
|
||||
(max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
|
||||
| 1 | (ctrl->tRCD << 16));
|
||||
write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
|
||||
row | 0x00060000 | (slotrank << 24));
|
||||
write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000241);
|
||||
/* DRAM command WR */
|
||||
write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
|
||||
write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281081);
|
||||
write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
|
||||
row | (slotrank << 24));
|
||||
write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
|
||||
/* DRAM command PRE */
|
||||
write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f002);
|
||||
write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x00280c01);
|
||||
write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
|
||||
0x00060400 | (slotrank << 24));
|
||||
write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000240);
|
||||
|
||||
write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x00080001);
|
||||
wait_428c(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void set_scrambling_seed(ramctr_timing * ctrl)
|
||||
{
|
||||
int channel;
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#define NUM_CHANNELS 2
|
||||
#define NUM_SLOTRANKS 4
|
||||
#define NUM_SLOTS 2
|
||||
#define NUM_LANES 8
|
||||
#define NUM_LANES 9
|
||||
|
||||
/* FIXME: Vendor BIOS uses 64 but our algorithms are less
|
||||
performant and even 1 seems to be enough in practice. */
|
||||
|
@ -121,6 +121,8 @@ typedef struct ramctr_timing_st {
|
|||
|
||||
int ecc_supported;
|
||||
int ecc_forced;
|
||||
int ecc_enabled;
|
||||
int lanes; /* active lanes: 8 or 9 */
|
||||
int edge_offset[3];
|
||||
int timC_offset[3];
|
||||
|
||||
|
@ -136,7 +138,7 @@ typedef struct ramctr_timing_st {
|
|||
|
||||
#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
|
||||
#define NORTHBRIDGE PCI_DEV(0, 0x0, 0)
|
||||
#define FOR_ALL_LANES for (lane = 0; lane < NUM_LANES; lane++)
|
||||
#define FOR_ALL_LANES for (lane = 0; lane < ctrl->lanes; lane++)
|
||||
#define FOR_ALL_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++)
|
||||
#define FOR_ALL_POPULATED_RANKS for (slotrank = 0; slotrank < NUM_SLOTRANKS; slotrank++) if (ctrl->rankmap[channel] & (1 << slotrank))
|
||||
#define FOR_ALL_POPULATED_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) if (ctrl->rankmap[channel])
|
||||
|
@ -160,7 +162,7 @@ void dram_find_common_params(ramctr_timing *ctrl);
|
|||
void dram_xover(ramctr_timing * ctrl);
|
||||
void dram_timing_regs(ramctr_timing * ctrl);
|
||||
void dram_dimm_mapping(ramctr_timing *ctrl);
|
||||
void dram_dimm_set_mapping(ramctr_timing * ctrl);
|
||||
void dram_dimm_set_mapping(ramctr_timing *ctrl, int training);
|
||||
void dram_zones(ramctr_timing * ctrl, int training);
|
||||
unsigned int get_mem_min_tck(void);
|
||||
void dram_memorymap(ramctr_timing * ctrl, int me_uma_size);
|
||||
|
@ -181,6 +183,7 @@ void set_4008c(ramctr_timing * ctrl);
|
|||
void set_42a0(ramctr_timing * ctrl);
|
||||
void final_registers(ramctr_timing * ctrl);
|
||||
void restore_timings(ramctr_timing * ctrl);
|
||||
void channel_scrub(ramctr_timing *ctrl);
|
||||
|
||||
int try_init_dram_ddr3_sandy(ramctr_timing *ctrl, int fast_boot,
|
||||
int s3_resume, int me_uma_size);
|
||||
|
|
|
@ -676,7 +676,7 @@ int try_init_dram_ddr3_ivy(ramctr_timing *ctrl, int fast_boot,
|
|||
MCHBAR32(0x5030) &= ~0x20;
|
||||
|
||||
/* Set MAD-DIMM registers */
|
||||
dram_dimm_set_mapping(ctrl);
|
||||
dram_dimm_set_mapping(ctrl, 1);
|
||||
printk(BIOS_DEBUG, "Done dimm mapping\n");
|
||||
|
||||
/* Zone config */
|
||||
|
@ -747,7 +747,13 @@ int try_init_dram_ddr3_ivy(ramctr_timing *ctrl, int fast_boot,
|
|||
err = channel_test(ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ctrl->ecc_enabled)
|
||||
channel_scrub(ctrl);
|
||||
}
|
||||
|
||||
/* Set MAD-DIMM registers */
|
||||
dram_dimm_set_mapping(ctrl, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -446,7 +446,7 @@ int try_init_dram_ddr3_sandy(ramctr_timing *ctrl, int fast_boot,
|
|||
MCHBAR32(0x5030) &= ~0x20;
|
||||
|
||||
/* Set MAD-DIMM registers */
|
||||
dram_dimm_set_mapping(ctrl);
|
||||
dram_dimm_set_mapping(ctrl, 1);
|
||||
printk(BIOS_DEBUG, "Done dimm mapping\n");
|
||||
|
||||
/* Zone config */
|
||||
|
@ -517,7 +517,13 @@ int try_init_dram_ddr3_sandy(ramctr_timing *ctrl, int fast_boot,
|
|||
err = channel_test(ctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ctrl->ecc_enabled)
|
||||
channel_scrub(ctrl);
|
||||
}
|
||||
|
||||
/* Set MAD-DIMM registers */
|
||||
dram_dimm_set_mapping(ctrl, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue