summaryrefslogtreecommitdiff
path: root/config/coreboot/default
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2023-10-29 12:06:07 +0000
committerLeah Rowe <leah@libreboot.org>2023-10-29 12:06:07 +0000
commit34f5685337bb94751d36786467a0027b526f6346 (patch)
treed67c5ae48294651c1df91f4532bc876b7a02cf92 /config/coreboot/default
parent27efbc6f54292807250f126bd0aa16316f3f1cdf (diff)
fix raminit/coldboot on dell e6400
the patch included in this revision is pulled from: https://review.coreboot.org/c/coreboot/+/54024/2 contrary to hell's assertion of "not for merge", this does in fact work nicely on a dell e6400; nicholas chin tested on e6400 and found that those RCOMP values are the same nicholas was testing some errant modules that seemed to fail raminit in coreboot. in some cases, dell e6400 would regularly fail coldboot even though reboot was ok; this was therefore the cause of suspicioun for it being raminit-related with this patch from hell (Angel Pons, but knows as hell on IRC) it should fix boot issue on Dell Latitude E6400 Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'config/coreboot/default')
-rw-r--r--config/coreboot/default/patches/0027-nb-intel-gm45-Make-DDR2-raminit-work.patch216
1 files changed, 216 insertions, 0 deletions
diff --git a/config/coreboot/default/patches/0027-nb-intel-gm45-Make-DDR2-raminit-work.patch b/config/coreboot/default/patches/0027-nb-intel-gm45-Make-DDR2-raminit-work.patch
new file mode 100644
index 00000000..454e3e7b
--- /dev/null
+++ b/config/coreboot/default/patches/0027-nb-intel-gm45-Make-DDR2-raminit-work.patch
@@ -0,0 +1,216 @@
+From e047dc3c95063f27517cd6754e9cbe496ac9313d Mon Sep 17 00:00:00 2001
+From: Angel Pons <th3fanbus@gmail.com>
+Date: Mon, 10 May 2021 22:40:59 +0200
+Subject: [PATCH] [NOT FOR MERGE] nb/intel/gm45: Make DDR2 raminit work
+
+List of changes:
+ - Update some timing and ODT values
+ - Patch RCOMP calibration to better match what MRC binaries do
+ - Replay a hardcoded list of RCOMP codes after RcvEn
+
+This makes raminit work at DDR2-800 speeds and fixes S3 resume as well.
+Tested on Toshiba Satellite A300-1ME with two 2 GiB DDR2-800 SO-DIMMs.
+
+Change-Id: Ibaee524b8ff652ddadd66cb0eb680401b988ff7c
+Signed-off-by: Angel Pons <th3fanbus@gmail.com>
+---
+
+diff --git a/src/northbridge/intel/gm45/gm45.h b/src/northbridge/intel/gm45/gm45.h
+index f28c6d1..bdf0432 100644
+--- a/src/northbridge/intel/gm45/gm45.h
++++ b/src/northbridge/intel/gm45/gm45.h
+@@ -419,7 +419,7 @@
+ int raminit_read_vco_index(void);
+ u32 raminit_get_rank_addr(unsigned int channel, unsigned int rank);
+
+-void raminit_rcomp_calibration(stepping_t stepping);
++void raminit_rcomp_calibration(int ddr_type, stepping_t stepping);
+ void raminit_reset_readwrite_pointers(void);
+ void raminit_receive_enable_calibration(int ddr_type, const timings_t *, const dimminfo_t *);
+ void raminit_write_training(const mem_clock_t, const dimminfo_t *, int s3resume);
+diff --git a/src/northbridge/intel/gm45/raminit.c b/src/northbridge/intel/gm45/raminit.c
+index ecada7b..2b8c44e 100644
+--- a/src/northbridge/intel/gm45/raminit.c
++++ b/src/northbridge/intel/gm45/raminit.c
+@@ -1049,7 +1049,7 @@
+ }
+
+ /* Perform RCOMP calibration for DDR3. */
+- raminit_rcomp_calibration(stepping);
++ raminit_rcomp_calibration(spd_type, stepping);
+
+ /* Run initial RCOMP. */
+ mchbar_setbits32(0x418, 1 << 17);
+@@ -1119,7 +1119,7 @@
+ reg = (reg & ~(0xf << 10)) | (2 << 10);
+ else
+ reg = (reg & ~(0xf << 10)) | (3 << 10);
+- reg = (reg & ~(0x7 << 5)) | (3 << 5);
++ reg = (reg & ~(0x7 << 5)) | (2 << 5);
+ } else if (timings->mem_clock != MEM_CLOCK_1067MT) {
+ reg = (reg & ~(0x7 << 15)) | ((9 - timings->CAS) << 15);
+ reg = (reg & ~(0xf << 10)) | ((timings->CAS - 3) << 10);
+@@ -1288,11 +1288,11 @@
+ reg = (reg & ~(0xf << (44 - 32))) | (8 << (44 - 32));
+ reg = (reg & ~(0xf << (40 - 32))) | (7 << (40 - 32));
+ if (timings->mem_clock == MEM_CLOCK_667MT) {
+- reg = (reg & ~(0xf << (36 - 32))) | (4 << (36 - 32));
+- reg = (reg & ~(0xf << (32 - 32))) | (4 << (32 - 32));
++ reg = (reg & ~(0xf << (36 - 32))) | (8 << (36 - 32));
++ reg = (reg & ~(0xf << (32 - 32))) | (8 << (32 - 32));
+ } else {
+- reg = (reg & ~(0xf << (36 - 32))) | (5 << (36 - 32));
+- reg = (reg & ~(0xf << (32 - 32))) | (5 << (32 - 32));
++ reg = (reg & ~(0xf << (36 - 32))) | (9 << (36 - 32));
++ reg = (reg & ~(0xf << (32 - 32))) | (9 << (32 - 32));
+ }
+ mchbar_write32(CxODT_HIGH(ch), reg);
+
+@@ -2217,6 +2217,84 @@
+ raminit_write_training(timings->mem_clock, dimms, s3resume);
+ }
+
++ /*
++ * Program hardcoded DDR2-800 RCOMP SRAM codes. This must be done
++ * after receiver enable calibration, otherwise raminit sometimes
++ * completes with non-working memory.
++ */
++ mchbar_write32(0x0530, 0x06060005);
++ mchbar_write32(0x0680, 0x06060606);
++ mchbar_write32(0x0684, 0x08070606);
++ mchbar_write32(0x0688, 0x0e0e0c0a);
++ mchbar_write32(0x068c, 0x0e0e0e0e);
++ mchbar_write32(0x0698, 0x06060606);
++ mchbar_write32(0x069c, 0x08070606);
++ mchbar_write32(0x06a0, 0x0c0c0b0a);
++ mchbar_write32(0x06a4, 0x0c0c0c0c);
++
++ mchbar_write32(0x06c0, 0x02020202);
++ mchbar_write32(0x06c4, 0x03020202);
++ mchbar_write32(0x06c8, 0x04040403);
++ mchbar_write32(0x06cc, 0x04040404);
++ mchbar_write32(0x06d8, 0x02020202);
++ mchbar_write32(0x06dc, 0x03020202);
++ mchbar_write32(0x06e0, 0x04040403);
++ mchbar_write32(0x06e4, 0x04040404);
++
++ mchbar_write32(0x0700, 0x02020202);
++ mchbar_write32(0x0704, 0x03020202);
++ mchbar_write32(0x0708, 0x04040403);
++ mchbar_write32(0x070c, 0x04040404);
++ mchbar_write32(0x0718, 0x02020202);
++ mchbar_write32(0x071c, 0x03020202);
++ mchbar_write32(0x0720, 0x04040403);
++ mchbar_write32(0x0724, 0x04040404);
++
++ mchbar_write32(0x0740, 0x02020202);
++ mchbar_write32(0x0744, 0x03020202);
++ mchbar_write32(0x0748, 0x04040403);
++ mchbar_write32(0x074c, 0x04040404);
++ mchbar_write32(0x0758, 0x02020202);
++ mchbar_write32(0x075c, 0x03020202);
++ mchbar_write32(0x0760, 0x04040403);
++ mchbar_write32(0x0764, 0x04040404);
++
++ mchbar_write32(0x0780, 0x06060606);
++ mchbar_write32(0x0784, 0x09070606);
++ mchbar_write32(0x0788, 0x0e0e0c0b);
++ mchbar_write32(0x078c, 0x0e0e0e0e);
++ mchbar_write32(0x0798, 0x06060606);
++ mchbar_write32(0x079c, 0x09070606);
++ mchbar_write32(0x07a0, 0x0d0d0c0b);
++ mchbar_write32(0x07a4, 0x0d0d0d0d);
++
++ mchbar_write32(0x07c0, 0x06060606);
++ mchbar_write32(0x07c4, 0x09070606);
++ mchbar_write32(0x07c8, 0x0e0e0c0b);
++ mchbar_write32(0x07cc, 0x0e0e0e0e);
++ mchbar_write32(0x07d8, 0x06060606);
++ mchbar_write32(0x07dc, 0x09070606);
++ mchbar_write32(0x07e0, 0x0d0d0c0b);
++ mchbar_write32(0x07e4, 0x0d0d0d0d);
++
++ mchbar_write32(0x0840, 0x06060606);
++ mchbar_write32(0x0844, 0x08070606);
++ mchbar_write32(0x0848, 0x0e0e0c0a);
++ mchbar_write32(0x084c, 0x0e0e0e0e);
++ mchbar_write32(0x0858, 0x06060606);
++ mchbar_write32(0x085c, 0x08070606);
++ mchbar_write32(0x0860, 0x0c0c0b0a);
++ mchbar_write32(0x0864, 0x0c0c0c0c);
++
++ mchbar_write32(0x0880, 0x02020202);
++ mchbar_write32(0x0884, 0x03020202);
++ mchbar_write32(0x0888, 0x04040403);
++ mchbar_write32(0x088c, 0x04040404);
++ mchbar_write32(0x0898, 0x02020202);
++ mchbar_write32(0x089c, 0x03020202);
++ mchbar_write32(0x08a0, 0x04040403);
++ mchbar_write32(0x08a4, 0x04040404);
++
+ igd_compute_ggc(sysinfo);
+
+ /* Program final memory map (with real values). */
+diff --git a/src/northbridge/intel/gm45/raminit_rcomp_calibration.c b/src/northbridge/intel/gm45/raminit_rcomp_calibration.c
+index aef863f..b74765f 100644
+--- a/src/northbridge/intel/gm45/raminit_rcomp_calibration.c
++++ b/src/northbridge/intel/gm45/raminit_rcomp_calibration.c
+@@ -161,11 +161,13 @@
+ mchbar += 4;
+ }
+ }
+-void raminit_rcomp_calibration(const stepping_t stepping) {
++void raminit_rcomp_calibration(int ddr_type, const stepping_t stepping) {
+ const int a1step = stepping >= STEPPING_CONVERSION_A1;
+
+ int i;
+
++ char magic_comp[2] = {0};
++
+ enum {
+ PULL_UP = 0,
+ PULL_DOWN = 1,
+@@ -196,6 +198,10 @@
+ reg = mchbar_read32(0x518);
+ lut_idx[channel][group][PULL_UP] = (reg >> 24) & 0x7f;
+ lut_idx[channel][group][PULL_DOWN] = (reg >> 16) & 0x7f;
++ if (i == 1) {
++ magic_comp[0] = (reg >> 8) & 0x3f;
++ magic_comp[1] = (reg >> 0) & 0x3f;
++ }
+ }
+ /* Cleanup? */
+ mchbar_setbits32(0x400, 1 << 3);
+@@ -216,13 +222,19 @@
+ for (channel = 0; channel < 2; ++channel) {
+ for (group = 0; group < 6; ++group) {
+ for (pu_pd = PULL_DOWN; pu_pd >= PULL_UP; --pu_pd) {
+- lookup_and_write(
+- a1step,
+- lut_idx[channel][group][pu_pd] - 7,
+- ddr3_lookup_schedule[group][pu_pd],
+- mchbar);
++ if (ddr_type == DDR3) {
++ lookup_and_write(
++ a1step,
++ lut_idx[channel][group][pu_pd] - 7,
++ ddr3_lookup_schedule[group][pu_pd],
++ mchbar);
++ }
+ mchbar += 0x0018;
+ }
++ if (ddr_type == DDR2) {
++ mchbar_clrsetbits32(mchbar + 0, 0x7f << 24, lut_idx[channel][group][PULL_DOWN] << 24);
++ mchbar_clrsetbits32(mchbar + 4, 0x7f << 0, lut_idx[channel][group][PULL_UP] << 0);
++ }
+ mchbar += 0x0010;
+ /* Channel B knows only the first two groups. */
+ if ((1 == channel) && (1 == group))
+@@ -230,4 +242,7 @@
+ }
+ mchbar += 0x0040;
+ }
++
++ mchbar_clrsetbits32(0x4d0, 0x3f << 26, magic_comp[0] << 26);
++ mchbar_clrsetbits32(0x4d0, 0x3f << 20, magic_comp[1] << 20);
+ }