summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngel Pons <th3fanbus@gmail.com>2020-12-10 22:11:27 +0100
committerAngel Pons <th3fanbus@gmail.com>2020-12-12 14:22:27 +0000
commit927b1c01611663545da6d2d9048ce1f37bc04dcf (patch)
tree7eb75d0ffa0746c4c5b28ab789c0e693299796a2
parent33cd957866ca8d8c7d86b7cfa50f926c40e8d540 (diff)
nb/intel/sandybridge: Fix blunder in MR2 shadow code
Commit 7f1363d9b4 (nb/intel/sandybridge: Program MR2 shadow register) has a bug where the system locks up and power cycles when booting Linux, but is still able to pass memtest86+ with flying colors. The issue will occur when the following conditions are true: - CPU is Ivy Bridge - Memory speed is not greater than 1066 MHz (DDR3-2133 or slower) - System contains dual-rank DIMMs - The second rank of the dual-rank DIMMs is mirrored - All DIMMs support Extended Temperature Range - At least one of the DIMMs does not support Auto Self-Refresh If all of these conditions are met, the final value of the MR2 Shadow registers configures the memory controller to issue a MRS command to update MR2 before entering self-refresh mode, but indicates that rank mirroring is not required (the first rank on a DIMM is never mirrored). Before the memory controller enters self-refresh, it sends MRS commands to all ranks to update MR2, but the missing address and bank mirroring means DRAM chips on mirrored ranks instead clobber MR1 with junk data. With garbage in MR1, the mirrored ranks no longer function properly, which ultimately leads to all hell breaking loose (undefined behavior). The condition is backwards, since only odd ranks can be mirrored. To avoid this problem completely, simply remove the condition. The final register value will still be correct, since the bits are always ORed. Tested on Asus P8Z77-V LX2, fixes booting Linux with dual-rank DIMMs. Change-Id: Iceff741eb85fab0ae846e50af0080e5ff405404c Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/48550 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nico Huber <nico.h@gmx.de> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-by: Patrick Rudolph <siro@das-labor.org>
-rw-r--r--src/northbridge/intel/sandybridge/raminit_common.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/src/northbridge/intel/sandybridge/raminit_common.c b/src/northbridge/intel/sandybridge/raminit_common.c
index 399ba5a16d..80c5186ead 100644
--- a/src/northbridge/intel/sandybridge/raminit_common.c
+++ b/src/northbridge/intel/sandybridge/raminit_common.c
@@ -815,13 +815,12 @@ static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
reg32 |= mr2reg & ~(3 << 6);
- if (rank & 1) {
- if (srt)
- reg32 |= 1 << (rank / 2 + 6);
- } else {
- if (ctrl->rank_mirror[channel][rank])
- reg32 |= 1 << (rank / 2 + 14);
- }
+ if (srt)
+ reg32 |= 1 << (rank / 2 + 6);
+
+ if (ctrl->rank_mirror[channel][rank])
+ reg32 |= 1 << (rank / 2 + 14);
+
MCHBAR32(TC_MR2_SHADOW_ch(channel)) = reg32;
}