summaryrefslogtreecommitdiff
path: root/config/coreboot/default/patches/0027-nb-intel-gm45-Make-DDR2-raminit-work.patch
blob: 454e3e7b7ddb0c3cd81f997b4922988070372cc4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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);
 }