xref: /aosp_15_r20/external/coreboot/src/northbridge/intel/gm45/raminit_rcomp_calibration.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdint.h>
4 #include <delay.h>
5 #include <console/console.h>
6 #include "gm45.h"
7 
8 static const int ddr3_lookup_schedule[6][2] = {
9 	{ 0, 1 }, { 2, 3 }, { 4, 5 }, { 4, 5 }, { 6, 7 }, { 6, 7 }
10 };
11 /* Look-up table:
12  *   a1step X idx X (group || pull-up/-down)
13  */
14 static const u8 ddr3_lut[2][64][8] = {
15 	{	/* Stepping B3 and below. */
16 		{   8,  8,  3,  3,  3,  3,  5,  7  },
17 		{   8,  8,  3,  3,  3,  3,  5,  7  },
18 		{   8,  8,  3,  3,  3,  3,  5,  7  },
19 		{   8,  8,  3,  3,  3,  3,  5,  7  },
20 		{   8,  8,  3,  3,  3,  3,  5,  7  },
21 		{   8,  8,  3,  3,  3,  3,  5,  7  },
22 		{   8,  8,  3,  3,  3,  3,  5,  7  },
23 		{   8,  8,  3,  3,  3,  3,  5,  7  },
24 		{   8,  8,  3,  3,  3,  3,  5,  7  },
25 		{   8,  8,  3,  3,  3,  3,  5,  7  },
26 		{   8,  8,  3,  3,  3,  3,  5,  7  },
27 		{   8,  8,  3,  3,  3,  3,  5,  7  },
28 		{   8,  8,  3,  3,  3,  3,  5,  7  },
29 		{   8,  8,  3,  3,  3,  3,  5,  7  },
30 		{   8,  8,  3,  3,  3,  3,  5,  7  },
31 		{   8,  8,  3,  3,  3,  3,  5,  7  },
32 		{   8,  8,  3,  3,  3,  3,  5,  7  },
33 		{   8,  8,  3,  3,  3,  3,  5,  7  },
34 		{   8,  8,  3,  3,  3,  3,  5,  7  },
35 		{   8,  8,  3,  3,  3,  3,  5,  7  },
36 		{   8,  8,  3,  3,  3,  3,  5,  7  },
37 		{   8,  8,  3,  3,  3,  3,  5,  7  },
38 		{   8,  8,  3,  3,  3,  3,  5,  7  },
39 		{   8,  8,  3,  3,  3,  3,  5,  7  },
40 		{   8,  8,  3,  3,  3,  3,  5,  7  },
41 		{   8,  8,  3,  3,  3,  3,  5,  7  },
42 		{   9,  9,  3,  3,  3,  3,  6,  7  },
43 		{   9,  9,  3,  3,  3,  3,  6,  7  },
44 		{  10, 10,  3,  3,  3,  3,  7,  8  },
45 		{  11, 10,  3,  3,  3,  3,  7,  8  },
46 		{  12, 11,  3,  3,  3,  3,  8,  9  },
47 		{  13, 11,  3,  3,  3,  3,  9,  9  },
48 		{  14, 12,  3,  3,  3,  3,  9, 10  },
49 		{  15, 13,  3,  3,  3,  3,  9, 10  },
50 		{  16, 14,  3,  3,  3,  3,  9, 11  },
51 		{  18, 16,  3,  3,  3,  3, 10, 12  },
52 		{  20, 18,  4,  3,  4,  4, 10, 12  },
53 		{  22, 22,  4,  4,  4,  4, 11, 12  },
54 		{  24, 24,  4,  4,  4,  4, 11, 12  },
55 		{  28, 26,  4,  4,  4,  4, 12, 12  },
56 		{  32, 28,  5,  4,  5,  5, 12, 12  },
57 		{  36, 32,  5,  5,  5,  5, 13, 13  },
58 		{  40, 36,  5,  5,  5,  5, 14, 13  },
59 		{  43, 40,  5,  5,  5,  5, 15, 14  },
60 		{  43, 43,  5,  5,  6,  5, 15, 14  },
61 		{  43, 43,  6,  5,  6,  5, 15, 15  },
62 		{  43, 43,  6,  5,  6,  6, 15, 15  },
63 		{  43, 43,  6,  6,  6,  6, 15, 15  },
64 		{  43, 43,  6,  6,  7,  6, 15, 15  },
65 		{  43, 43,  7,  6,  7,  6, 15, 15  },
66 		{  43, 43,  7,  7,  7,  7, 15, 15  },
67 		{  43, 43,  7,  7,  7,  7, 15, 15  },
68 		{  43, 43,  7,  7,  7,  7, 15, 15  },
69 		{  43, 43,  8,  7,  8,  7, 15, 15  },
70 		{  43, 43,  8,  8,  8,  8, 15, 15  },
71 		{  43, 43,  8,  8,  8,  8, 15, 15  },
72 		{  43, 43,  8,  8,  8,  8, 15, 15  },
73 		{  43, 43,  8,  8,  8,  8, 15, 15  },
74 		{  43, 43,  8,  8,  8,  8, 15, 15  },
75 		{  43, 43,  8,  8,  8,  8, 15, 15  },
76 		{  43, 43,  8,  8,  8,  8, 15, 15  },
77 		{  43, 43,  8,  8,  8,  8, 15, 15  },
78 		{  43, 43,  8,  8,  8,  8, 15, 15  },
79 		{  43, 43,  8,  8,  8,  8, 15, 15  },
80 	},
81 	{	/* Stepping A1 and above. */
82 		{   8,  8,  3,  3,  3,  3,  5,  5  },
83 		{   8,  8,  3,  3,  3,  3,  5,  5  },
84 		{   8,  8,  3,  3,  3,  3,  5,  5  },
85 		{   8,  8,  3,  3,  3,  3,  5,  5  },
86 		{   8,  8,  3,  3,  3,  3,  5,  5  },
87 		{   8,  8,  3,  3,  3,  3,  5,  5  },
88 		{   8,  8,  3,  3,  3,  3,  5,  5  },
89 		{   8,  8,  3,  3,  3,  3,  5,  5  },
90 		{   8,  8,  3,  3,  3,  3,  5,  5  },
91 		{   8,  8,  3,  3,  3,  3,  5,  5  },
92 		{   8,  8,  3,  3,  3,  3,  5,  5  },
93 		{   8,  8,  3,  3,  3,  3,  5,  5  },
94 		{   8,  8,  3,  3,  3,  3,  5,  5  },
95 		{   8,  8,  3,  3,  3,  3,  5,  5  },
96 		{   8,  8,  3,  3,  3,  3,  5,  5  },
97 		{   8,  8,  3,  3,  3,  3,  5,  5  },
98 		{   8,  8,  3,  3,  3,  3,  5,  5  },
99 		{   8,  8,  3,  3,  3,  3,  5,  5  },
100 		{   8,  8,  3,  3,  3,  3,  5,  5  },
101 		{   8,  8,  3,  3,  3,  3,  5,  5  },
102 		{   8,  8,  3,  3,  3,  3,  5,  5  },
103 		{   8,  8,  3,  3,  3,  3,  5,  5  },
104 		{   8,  8,  3,  3,  3,  3,  5,  5  },
105 		{   8,  8,  3,  3,  3,  3,  5,  5  },
106 		{   8,  8,  3,  3,  3,  3,  5,  5  },
107 		{   8,  8,  3,  3,  3,  3,  5,  5  },
108 		{   9,  9,  3,  3,  3,  3,  6,  6  },
109 		{   9,  9,  3,  3,  3,  3,  6,  6  },
110 		{  10, 10,  3,  3,  3,  3,  7,  7  },
111 		{  10, 10,  3,  3,  3,  3,  7,  7  },
112 		{  12, 11,  3,  3,  3,  3,  8,  8  },
113 		{  13, 11,  3,  3,  3,  3,  9,  9  },
114 		{  14, 12,  3,  3,  3,  3,  9,  9  },
115 		{  15, 13,  3,  3,  3,  3,  9,  9  },
116 		{  16, 14,  3,  3,  3,  3,  9,  9  },
117 		{  18, 16,  3,  3,  3,  3, 10, 10  },
118 		{  20, 18,  4,  3,  4,  4, 10, 10  },
119 		{  22, 22,  4,  4,  4,  4, 11, 11  },
120 		{  24, 24,  4,  4,  4,  4, 11, 11  },
121 		{  28, 26,  4,  4,  4,  4, 12, 12  },
122 		{  32, 28,  5,  4,  5,  5, 12, 12  },
123 		{  36, 32,  5,  5,  5,  5, 13, 13  },
124 		{  40, 36,  5,  5,  5,  5, 14, 14  },
125 		{  43, 40,  5,  5,  5,  5, 15, 15  },
126 		{  43, 43,  5,  5,  6,  5, 15, 15  },
127 		{  43, 43,  6,  5,  6,  5, 15, 15  },
128 		{  43, 43,  6,  5,  6,  6, 15, 15  },
129 		{  43, 43,  6,  6,  6,  6, 15, 15  },
130 		{  43, 43,  6,  6,  7,  6, 15, 15  },
131 		{  43, 43,  7,  6,  7,  6, 15, 15  },
132 		{  43, 43,  7,  7,  7,  7, 15, 15  },
133 		{  43, 43,  7,  7,  7,  7, 15, 15  },
134 		{  43, 43,  7,  7,  7,  7, 15, 15  },
135 		{  43, 43,  8,  7,  8,  7, 15, 15  },
136 		{  43, 43,  8,  8,  8,  8, 15, 15  },
137 		{  43, 43,  8,  8,  8,  8, 15, 15  },
138 		{  43, 43,  8,  8,  8,  8, 15, 15  },
139 		{  43, 43,  8,  8,  8,  8, 15, 15  },
140 		{  43, 43,  8,  8,  8,  8, 15, 15  },
141 		{  43, 43,  8,  8,  8,  8, 15, 15  },
142 		{  43, 43,  8,  8,  8,  8, 15, 15  },
143 		{  43, 43,  8,  8,  8,  8, 15, 15  },
144 		{  43, 43,  8,  8,  8,  8, 15, 15  },
145 		{  43, 43,  8,  8,  8,  8, 15, 15  },
146 	}
147 };
lookup_and_write(const int a1step,const int row,const int col,unsigned int mchbar)148 static void lookup_and_write(const int a1step,
149 				    const int row, const int col,
150 				    unsigned int mchbar)
151 {
152 	int i;
153 
154 	/* Write 4 32-bit registers, 4 values each. */
155 	for (i = row; i < row + 16; i += 4) {
156 		mchbar_write32(mchbar,
157 			(ddr3_lut[a1step][i + 0][col] & 0x3f) <<  0 |
158 			(ddr3_lut[a1step][i + 1][col] & 0x3f) <<  8 |
159 			(ddr3_lut[a1step][i + 2][col] & 0x3f) << 16 |
160 			(ddr3_lut[a1step][i + 3][col] & 0x3f) << 24);
161 		mchbar += 4;
162 	}
163 }
raminit_rcomp_calibration(const stepping_t stepping)164 void raminit_rcomp_calibration(const stepping_t stepping) {
165 	const int a1step = stepping >= STEPPING_CONVERSION_A1;
166 
167 	int i;
168 
169 	enum {
170 		PULL_UP = 0,
171 		PULL_DOWN = 1,
172 	};
173 	/* channel X group X pull-up/-down */
174 	char lut_idx[2][6][2];
175 	for (i = 0; i < 2 * 6 * 2; ++i)
176 		((char *)lut_idx)[i] = -1;
177 
178 	mchbar_setbits32(0x400, 1 << 2);
179 	mchbar_setbits32(0x418, 1 << 17);
180 	mchbar_clrbits32(0x40c, 1 << 23);
181 	mchbar_clrbits32(0x41c, 1 << 7 | 1 << 3);
182 	mchbar_setbits32(0x400, 1 << 0);
183 
184 	/* Read lookup indices. */
185 	for (i = 0; i < 12; ++i) {
186 		do {
187 			mchbar_setbits32(0x400, 1 << 3);
188 			udelay(10);
189 			mchbar_clrbits32(0x400, 1 << 3);
190 		} while ((mchbar_read32(0x530) & 0x7) != 0x4);
191 		u32 reg = mchbar_read32(0x400);
192 		const unsigned int group = (reg >> 13) & 0x7;
193 		const unsigned int channel = (reg >> 12) & 0x1;
194 		if (group > 5)
195 			break;
196 		reg = mchbar_read32(0x518);
197 		lut_idx[channel][group][PULL_UP] = (reg >> 24) & 0x7f;
198 		lut_idx[channel][group][PULL_DOWN] = (reg >> 16) & 0x7f;
199 	}
200 	/* Cleanup? */
201 	mchbar_setbits32(0x400, 1 << 3);
202 	udelay(10);
203 	mchbar_clrbits32(0x400, 1 << 3);
204 	mchbar_clrbits32(0x400, 1 << 2);
205 
206 	/* Check for consistency. */
207 	for (i = 0; i < 2 * 6 * 2; ++i) {
208 		const char idx = ((char *)lut_idx)[i];
209 		if ((idx < 7) || (idx > 55))
210 			die("Bad RCOMP calibration lookup index.\n");
211 	}
212 
213 	/* Lookup values and fill registers. */
214 	int channel, group, pu_pd;
215 	unsigned int mchbar = 0x0680;
216 	for (channel = 0; channel < 2; ++channel) {
217 		for (group = 0; group < 6; ++group) {
218 			for (pu_pd = PULL_DOWN; pu_pd >= PULL_UP; --pu_pd) {
219 				lookup_and_write(
220 					a1step,
221 					lut_idx[channel][group][pu_pd] - 7,
222 					ddr3_lookup_schedule[group][pu_pd],
223 					mchbar);
224 				mchbar += 0x0018;
225 			}
226 			mchbar += 0x0010;
227 			/* Channel B knows only the first two groups. */
228 			if ((1 == channel) && (1 == group))
229 				break;
230 		}
231 		mchbar += 0x0040;
232 	}
233 }
234