<p>Patrick Rudolph has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/22215">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">[WIP]nb/intel/sandybridge/raminit: Add ECC support<br><br>Add ECC support for IvyBridge.<br><br>Change-Id: I1206746332c9939a78b67e7b48d3098bdef8a2ed<br>Signed-off-by: Patrick Rudolph <siro@das-labor.org><br>---<br>M src/northbridge/intel/sandybridge/Kconfig<br>M src/northbridge/intel/sandybridge/raminit.c<br>M src/northbridge/intel/sandybridge/raminit_common.c<br>M src/northbridge/intel/sandybridge/raminit_common.h<br>M src/northbridge/intel/sandybridge/raminit_ivy.c<br>5 files changed, 73 insertions(+), 3 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/15/22215/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig<br>index c7e6e46..97042b2 100644<br>--- a/src/northbridge/intel/sandybridge/Kconfig<br>+++ b/src/northbridge/intel/sandybridge/Kconfig<br>@@ -117,6 +117,12 @@<br> Run extended memtest over all usable memory below 4GiB.<br> This will delay raminit training by several microseconds.<br> <br>+config RAMINIT_ENABLE_ECC<br>+ bool "Enable ECC if supported"<br>+ default y<br>+ help<br>+ Enable ECC if supported by both, host and RAM.<br>+<br> endif # USE_NATIVE_RAMINIT<br> <br> if !USE_NATIVE_RAMINIT<br>diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c<br>index 8e8c457..cd5c9f0 100644<br>--- a/src/northbridge/intel/sandybridge/raminit.c<br>+++ b/src/northbridge/intel/sandybridge/raminit.c<br>@@ -35,7 +35,6 @@<br> #include "raminit_common.h"<br> #include "sandybridge.h"<br> <br>-/* FIXME: no ECC support. */<br> /* FIXME: no support for 3-channel chipsets. */<br> <br> static const char *ecc_decoder[] = {<br>@@ -195,6 +194,7 @@<br> {<br> int dimms = 0, dimms_on_channel;<br> int channel, slot, spd_slot;<br>+ size_t supports_ecc = 1;<br> dimm_info *dimm = &ctrl->info;<br> <br> memset (ctrl->rankmap, 0, sizeof(ctrl->rankmap));<br>@@ -259,6 +259,9 @@<br> ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;<br> ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;<br> <br>+ if (!dimm->dimm[channel][slot]->flags.is_ecc)<br>+ supports_ecc = 0;<br>+<br> ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;<br> ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;<br> <br>@@ -282,6 +285,17 @@<br> ctrl->ref_card_offset[channel] = 0;<br> }<br> <br>+ if (ctrl->ecc_supported) {<br>+ if (ctrl->ecc_forced && !supports_ecc)<br>+ die("ECC mode forced but non ECC DIMM installed !");<br>+ ctrl->ecc_enabled = ctrl->ecc_forced ||<br>+ IS_ENALBED(CONFIG_RAMINIT_ENABLE_ECC);<br>+ printk(BIOS_DEBUG, "ECC mode %s\n",<br>+ ctrl->ecc_enabled ? "on" : "off");<br>+ }<br>+<br>+ ctrl->lanes = ctrl->ecc_enabled ? 9 : 8;<br>+<br> if (!dimms)<br> die("No DIMMs were found");<br> }<br>diff --git a/src/northbridge/intel/sandybridge/raminit_common.c b/src/northbridge/intel/sandybridge/raminit_common.c<br>index 00bb513..8569d7e 100644<br>--- a/src/northbridge/intel/sandybridge/raminit_common.c<br>+++ b/src/northbridge/intel/sandybridge/raminit_common.c<br>@@ -328,6 +328,9 @@<br> reg |= 1 << 21; /* rank interleave */<br> reg |= 1 << 22; /* enhanced interleave */<br> <br>+ if (ctrl->ecc_enabled)<br>+ reg |= 3 << 24;<br>+<br> if ((dimmA && (dimmA->ranks > 0))<br> || (dimmB && (dimmB->ranks > 0))) {<br> ctrl->mad_dimm[channel] = reg;<br>@@ -343,6 +346,8 @@<br> FOR_ALL_CHANNELS {<br> MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];<br> }<br>+<br>+ udelay(10);<br> }<br> <br> void dram_zones(ramctr_timing * ctrl, int training)<br>@@ -3118,6 +3123,45 @@<br> return 0;<br> }<br> <br>+void channel_scrub(ramctr_timing *ctrl)<br>+{<br>+ int channel, slotrank, lane, bank, row;<br>+ int rowsize;<br>+<br>+ FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {<br>+ rowsize = 1 << ctrl->info.dimm[channel][slotrank>>1].row_bits;<br>+ for (bank = 0; bank < 8; bank++) {<br>+ for (row = 0; row < rowsize; row += 16) {<br>+<br>+ wait_428c(channel);<br>+ /* DRAM command ACT */<br>+ write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);<br>+ write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10),<br>+ (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)<br>+ | 1 | (ctrl->tRCD << 16));<br>+ write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),<br>+ row | 0x00060000 | (slotrank << 24));<br>+ write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000241);<br>+ /* DRAM command WR */<br>+ write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);<br>+ write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281081);<br>+ write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),<br>+ row | (slotrank << 24));<br>+ write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);<br>+ /* DRAM command PRE */<br>+ write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f002);<br>+ write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x00280c01);<br>+ write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),<br>+ 0x00060400 | (slotrank << 24));<br>+ write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000240);<br>+<br>+ write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x00080001);<br>+ wait_428c(channel);<br>+ }<br>+ }<br>+ }<br>+}<br>+<br> void set_scrambling_seed(ramctr_timing * ctrl)<br> {<br> int channel;<br>diff --git a/src/northbridge/intel/sandybridge/raminit_common.h b/src/northbridge/intel/sandybridge/raminit_common.h<br>index cd8310d..dc485d6 100644<br>--- a/src/northbridge/intel/sandybridge/raminit_common.h<br>+++ b/src/northbridge/intel/sandybridge/raminit_common.h<br>@@ -36,7 +36,7 @@<br> #define NUM_CHANNELS 2<br> #define NUM_SLOTRANKS 4<br> #define NUM_SLOTS 2<br>-#define NUM_LANES 8<br>+#define NUM_LANES 9<br> <br> /* FIXME: Vendor BIOS uses 64 but our algorithms are less<br> performant and even 1 seems to be enough in practice. */<br>@@ -121,6 +121,8 @@<br> <br> int ecc_supported;<br> int ecc_forced;<br>+ int ecc_enabled;<br>+ int lanes; /* active lanes: 8 or 9 */<br> int edge_offset[3];<br> int timC_offset[3];<br> <br>@@ -136,7 +138,7 @@<br> <br> #define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)<br> #define NORTHBRIDGE PCI_DEV(0, 0x0, 0)<br>-#define FOR_ALL_LANES for (lane = 0; lane < NUM_LANES; lane++)<br>+#define FOR_ALL_LANES for (lane = 0; lane < ctrl->lanes; lane++)<br> #define FOR_ALL_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++)<br> #define FOR_ALL_POPULATED_RANKS for (slotrank = 0; slotrank < NUM_SLOTRANKS; slotrank++) if (ctrl->rankmap[channel] & (1 << slotrank))<br> #define FOR_ALL_POPULATED_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) if (ctrl->rankmap[channel])<br>@@ -181,6 +183,7 @@<br> void set_42a0(ramctr_timing * ctrl);<br> void final_registers(ramctr_timing * ctrl);<br> void restore_timings(ramctr_timing * ctrl);<br>+void channel_scrub(ramctr_timing *ctrl);<br> <br> int try_init_dram_ddr3_sandy(ramctr_timing *ctrl, int fast_boot,<br> int s3_resume, int me_uma_size);<br>diff --git a/src/northbridge/intel/sandybridge/raminit_ivy.c b/src/northbridge/intel/sandybridge/raminit_ivy.c<br>index 675ac71..5d375b9 100644<br>--- a/src/northbridge/intel/sandybridge/raminit_ivy.c<br>+++ b/src/northbridge/intel/sandybridge/raminit_ivy.c<br>@@ -747,6 +747,9 @@<br> err = channel_test(ctrl);<br> if (err)<br> return err;<br>+<br>+ if (ctrl->ecc_enabled)<br>+ channel_scrub(ctrl);<br> }<br> <br> return 0;<br></pre><p>To view, visit <a href="https://review.coreboot.org/22215">change 22215</a>. To unsubscribe, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/22215"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I1206746332c9939a78b67e7b48d3098bdef8a2ed </div>
<div style="display:none"> Gerrit-Change-Number: 22215 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <siro@das-labor.org> </div>