[coreboot-gerrit] Change in coreboot[master]: [WIP]nb/intel/sandybridge/raminit: Add ECC support
Patrick Rudolph (Code Review)
gerrit at coreboot.org
Sat Oct 28 18:25:59 CEST 2017
Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/22215
Change subject: [WIP]nb/intel/sandybridge/raminit: Add ECC support
......................................................................
[WIP]nb/intel/sandybridge/raminit: Add ECC support
Add ECC support for IvyBridge.
Change-Id: I1206746332c9939a78b67e7b48d3098bdef8a2ed
Signed-off-by: Patrick Rudolph <siro at das-labor.org>
---
M src/northbridge/intel/sandybridge/Kconfig
M src/northbridge/intel/sandybridge/raminit.c
M src/northbridge/intel/sandybridge/raminit_common.c
M src/northbridge/intel/sandybridge/raminit_common.h
M src/northbridge/intel/sandybridge/raminit_ivy.c
5 files changed, 73 insertions(+), 3 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/15/22215/1
diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig
index c7e6e46..97042b2 100644
--- a/src/northbridge/intel/sandybridge/Kconfig
+++ b/src/northbridge/intel/sandybridge/Kconfig
@@ -117,6 +117,12 @@
Run extended memtest over all usable memory below 4GiB.
This will delay raminit training by several microseconds.
+config RAMINIT_ENABLE_ECC
+ bool "Enable ECC if supported"
+ default y
+ help
+ Enable ECC if supported by both, host and RAM.
+
endif # USE_NATIVE_RAMINIT
if !USE_NATIVE_RAMINIT
diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c
index 8e8c457..cd5c9f0 100644
--- a/src/northbridge/intel/sandybridge/raminit.c
+++ b/src/northbridge/intel/sandybridge/raminit.c
@@ -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 @@
{
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));
@@ -259,6 +259,9 @@
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;
@@ -282,6 +285,17 @@
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 !");
+ ctrl->ecc_enabled = ctrl->ecc_forced ||
+ IS_ENALBED(CONFIG_RAMINIT_ENABLE_ECC);
+ printk(BIOS_DEBUG, "ECC mode %s\n",
+ ctrl->ecc_enabled ? "on" : "off");
+ }
+
+ ctrl->lanes = ctrl->ecc_enabled ? 9 : 8;
+
if (!dimms)
die("No DIMMs were found");
}
diff --git a/src/northbridge/intel/sandybridge/raminit_common.c b/src/northbridge/intel/sandybridge/raminit_common.c
index 00bb513..8569d7e 100644
--- a/src/northbridge/intel/sandybridge/raminit_common.c
+++ b/src/northbridge/intel/sandybridge/raminit_common.c
@@ -328,6 +328,9 @@
reg |= 1 << 21; /* rank interleave */
reg |= 1 << 22; /* enhanced interleave */
+ if (ctrl->ecc_enabled)
+ reg |= 3 << 24;
+
if ((dimmA && (dimmA->ranks > 0))
|| (dimmB && (dimmB->ranks > 0))) {
ctrl->mad_dimm[channel] = reg;
@@ -343,6 +346,8 @@
FOR_ALL_CHANNELS {
MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
}
+
+ udelay(10);
}
void dram_zones(ramctr_timing * ctrl, int training)
@@ -3118,6 +3123,45 @@
return 0;
}
+void channel_scrub(ramctr_timing *ctrl)
+{
+ int channel, slotrank, lane, 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;
diff --git a/src/northbridge/intel/sandybridge/raminit_common.h b/src/northbridge/intel/sandybridge/raminit_common.h
index cd8310d..dc485d6 100644
--- a/src/northbridge/intel/sandybridge/raminit_common.h
+++ b/src/northbridge/intel/sandybridge/raminit_common.h
@@ -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 @@
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 @@
#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])
@@ -181,6 +183,7 @@
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);
diff --git a/src/northbridge/intel/sandybridge/raminit_ivy.c b/src/northbridge/intel/sandybridge/raminit_ivy.c
index 675ac71..5d375b9 100644
--- a/src/northbridge/intel/sandybridge/raminit_ivy.c
+++ b/src/northbridge/intel/sandybridge/raminit_ivy.c
@@ -747,6 +747,9 @@
err = channel_test(ctrl);
if (err)
return err;
+
+ if (ctrl->ecc_enabled)
+ channel_scrub(ctrl);
}
return 0;
--
To view, visit https://review.coreboot.org/22215
To unsubscribe, visit https://review.coreboot.org/settings
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I1206746332c9939a78b67e7b48d3098bdef8a2ed
Gerrit-Change-Number: 22215
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <siro at das-labor.org>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20171028/6f7c46cd/attachment.html>
More information about the coreboot-gerrit
mailing list