blob: aac852ab11d30cf47e7481e0935537de000539fb [file] [log] [blame]
Angel Pons7a87c922021-01-15 22:50:41 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
Yidi Lin2751d292023-10-31 17:15:50 +08003#include <commonlib/bsd/gcd.h>
Angel Pons7a87c922021-01-15 22:50:41 +01004#include <console/console.h>
Angel Ponsfa5ed052021-12-18 22:25:07 +01005#include <cpu/intel/model_2065x/model_2065x.h>
6#include <cpu/x86/msr.h>
Angel Pons7a87c922021-01-15 22:50:41 +01007#include <delay.h>
8#include <device/pci_def.h>
9#include <device/pci_ops.h>
10#include <northbridge/intel/ironlake/raminit.h>
11#include <types.h>
12
13#define NORTHBRIDGE PCI_DEV(0, 0, 0)
14
Angel Pons7a87c922021-01-15 22:50:41 +010015static inline int div_roundup(int a, int b)
16{
17 return DIV_ROUND_UP(a, b);
18}
19
Yidi Lin2751d292023-10-31 17:15:50 +080020static u32 lcm(u32 a, u32 b)
Angel Pons7a87c922021-01-15 22:50:41 +010021{
Julius Wernerb5060202024-02-06 22:38:14 -080022 return (a * b) / gcd(a, b);
Angel Pons7a87c922021-01-15 22:50:41 +010023}
24
25struct stru1 {
26 u8 freqs_reversed;
27 u8 freq_diff_reduced;
28 u8 freq_min_reduced;
29 u8 divisor_f4_to_fmax;
30 u8 divisor_f3_to_fmax;
31 u8 freq4_to_max_remainder;
32 u8 freq3_to_2_remainder;
33 u8 freq3_to_2_remaindera;
34 u8 freq4_to_2_remainder;
35 int divisor_f3_to_f1, divisor_f4_to_f2;
36 int common_time_unit_ps;
37 int freq_max_reduced;
38};
39
40static void
41compute_frequence_ratios(struct raminfo *info, u16 freq1, u16 freq2,
42 int num_cycles_2, int num_cycles_1, int round_it,
43 int add_freqs, struct stru1 *result)
44{
45 int g;
46 int common_time_unit_ps;
47 int freq1_reduced, freq2_reduced;
48 int freq_min_reduced;
49 int freq_max_reduced;
50 int freq3, freq4;
51
Julius Wernerb5060202024-02-06 22:38:14 -080052 g = gcd(freq1, freq2);
Angel Pons7a87c922021-01-15 22:50:41 +010053 freq1_reduced = freq1 / g;
54 freq2_reduced = freq2 / g;
55 freq_min_reduced = MIN(freq1_reduced, freq2_reduced);
56 freq_max_reduced = MAX(freq1_reduced, freq2_reduced);
57
58 common_time_unit_ps = div_roundup(900000, lcm(freq1, freq2));
59 freq3 = div_roundup(num_cycles_2, common_time_unit_ps) - 1;
60 freq4 = div_roundup(num_cycles_1, common_time_unit_ps) - 1;
61 if (add_freqs) {
62 freq3 += freq2_reduced;
63 freq4 += freq1_reduced;
64 }
65
66 if (round_it) {
67 result->freq3_to_2_remainder = 0;
68 result->freq3_to_2_remaindera = 0;
69 result->freq4_to_max_remainder = 0;
70 result->divisor_f4_to_f2 = 0;
71 result->divisor_f3_to_f1 = 0;
72 } else {
73 if (freq2_reduced < freq1_reduced) {
74 result->freq3_to_2_remainder =
75 result->freq3_to_2_remaindera =
76 freq3 % freq1_reduced - freq1_reduced + 1;
77 result->freq4_to_max_remainder =
78 -(freq4 % freq1_reduced);
79 result->divisor_f3_to_f1 = freq3 / freq1_reduced;
80 result->divisor_f4_to_f2 =
81 (freq4 -
82 (freq1_reduced - freq2_reduced)) / freq2_reduced;
83 result->freq4_to_2_remainder =
84 -(char)((freq1_reduced - freq2_reduced) +
Elyes Haouas3a998072022-11-18 15:11:02 +010085 ((u8)freq4 -
Angel Pons7a87c922021-01-15 22:50:41 +010086 (freq1_reduced -
Elyes Haouas3a998072022-11-18 15:11:02 +010087 freq2_reduced)) % (u8)freq2_reduced);
Angel Pons7a87c922021-01-15 22:50:41 +010088 } else {
89 if (freq2_reduced > freq1_reduced) {
90 result->freq4_to_max_remainder =
91 (freq4 % freq2_reduced) - freq2_reduced + 1;
92 result->freq4_to_2_remainder =
93 freq4 % freq_max_reduced -
94 freq_max_reduced + 1;
95 } else {
96 result->freq4_to_max_remainder =
97 -(freq4 % freq2_reduced);
98 result->freq4_to_2_remainder =
99 -(char)(freq4 % freq_max_reduced);
100 }
101 result->divisor_f4_to_f2 = freq4 / freq2_reduced;
102 result->divisor_f3_to_f1 =
103 (freq3 -
104 (freq2_reduced - freq1_reduced)) / freq1_reduced;
105 result->freq3_to_2_remainder = -(freq3 % freq2_reduced);
106 result->freq3_to_2_remaindera =
107 -(char)((freq_max_reduced - freq_min_reduced) +
108 (freq3 -
109 (freq_max_reduced -
110 freq_min_reduced)) % freq1_reduced);
111 }
112 }
113 result->divisor_f3_to_fmax = freq3 / freq_max_reduced;
114 result->divisor_f4_to_fmax = freq4 / freq_max_reduced;
115 if (round_it) {
116 if (freq2_reduced > freq1_reduced) {
117 if (freq3 % freq_max_reduced)
118 result->divisor_f3_to_fmax++;
119 }
120 if (freq2_reduced < freq1_reduced) {
121 if (freq4 % freq_max_reduced)
122 result->divisor_f4_to_fmax++;
123 }
124 }
125 result->freqs_reversed = (freq2_reduced < freq1_reduced);
126 result->freq_diff_reduced = freq_max_reduced - freq_min_reduced;
127 result->freq_min_reduced = freq_min_reduced;
128 result->common_time_unit_ps = common_time_unit_ps;
129 result->freq_max_reduced = freq_max_reduced;
130}
131
Angel Pons0a8b1132021-01-15 23:13:00 +0100132static void compute_274265(struct raminfo *info)
Angel Pons7a87c922021-01-15 22:50:41 +0100133{
134 int delay_a_ps, delay_b_ps, delay_c_ps, delay_d_ps;
135 int delay_e_ps, delay_e_cycles, delay_f_cycles;
136 int delay_e_over_cycle_ps;
137 int cycletime_ps;
138 int channel;
139
140 delay_a_ps = 4 * halfcycle_ps(info) + 6 * fsbcycle_ps(info);
141 info->training.reg2ca9_bit0 = 0;
142 for (channel = 0; channel < NUM_CHANNELS; channel++) {
143 cycletime_ps =
144 900000 / lcm(2 * info->fsb_frequency, frequency_11(info));
145 delay_d_ps =
146 (halfcycle_ps(info) * get_max_timing(info, channel) >> 6)
147 - info->some_delay_3_ps_rounded + 200;
148 if (!
149 ((info->silicon_revision == 0
150 || info->silicon_revision == 1)
151 && (info->revision >= 8)))
152 delay_d_ps += halfcycle_ps(info) * 2;
153 delay_d_ps +=
154 halfcycle_ps(info) * (!info->revision_flag_1 +
155 info->some_delay_2_halfcycles_ceil +
156 2 * info->some_delay_1_cycle_floor +
157 info->clock_speed_index +
158 2 * info->cas_latency - 7 + 11);
159 delay_d_ps += info->revision >= 8 ? 2758 : 4428;
160
Angel Ponsdea722b2021-03-26 14:11:12 +0100161 mchbar_clrsetbits32(0x140, 7 << 24, 2 << 24);
162 mchbar_clrsetbits32(0x138, 7 << 24, 2 << 24);
163 if ((mchbar_read8(0x144) & 0x1f) > 0x13)
Angel Pons7a87c922021-01-15 22:50:41 +0100164 delay_d_ps += 650;
165 delay_c_ps = delay_d_ps + 1800;
166 if (delay_c_ps <= delay_a_ps)
167 delay_e_ps = 0;
168 else
169 delay_e_ps =
170 cycletime_ps * div_roundup(delay_c_ps - delay_a_ps,
171 cycletime_ps);
172
173 delay_e_over_cycle_ps = delay_e_ps % (2 * halfcycle_ps(info));
174 delay_e_cycles = delay_e_ps / (2 * halfcycle_ps(info));
175 delay_f_cycles =
176 div_roundup(2500 - delay_e_over_cycle_ps,
177 2 * halfcycle_ps(info));
178 if (delay_f_cycles > delay_e_cycles) {
179 info->delay46_ps[channel] = delay_e_ps;
180 delay_e_cycles = 0;
181 } else {
182 info->delay46_ps[channel] =
183 delay_e_over_cycle_ps +
184 2 * halfcycle_ps(info) * delay_f_cycles;
185 delay_e_cycles -= delay_f_cycles;
186 }
187
188 if (info->delay46_ps[channel] < 2500) {
189 info->delay46_ps[channel] = 2500;
190 info->training.reg2ca9_bit0 = 1;
191 }
192 delay_b_ps = halfcycle_ps(info) + delay_c_ps;
193 if (delay_b_ps <= delay_a_ps)
194 delay_b_ps = 0;
195 else
196 delay_b_ps -= delay_a_ps;
197 info->delay54_ps[channel] =
198 cycletime_ps * div_roundup(delay_b_ps,
199 cycletime_ps) -
200 2 * halfcycle_ps(info) * delay_e_cycles;
201 if (info->delay54_ps[channel] < 2500)
202 info->delay54_ps[channel] = 2500;
203 info->training.reg274265[channel][0] = delay_e_cycles;
204 if (delay_d_ps + 7 * halfcycle_ps(info) <=
205 24 * halfcycle_ps(info))
206 info->training.reg274265[channel][1] = 0;
207 else
208 info->training.reg274265[channel][1] =
209 div_roundup(delay_d_ps + 7 * halfcycle_ps(info),
210 4 * halfcycle_ps(info)) - 6;
Angel Pons7a87c922021-01-15 22:50:41 +0100211 info->training.reg274265[channel][2] =
212 div_roundup(delay_c_ps + 3 * fsbcycle_ps(info),
213 4 * halfcycle_ps(info)) + 1;
Angel Pons7a87c922021-01-15 22:50:41 +0100214 }
Angel Pons7a87c922021-01-15 22:50:41 +0100215}
216
Angel Pons0a8b1132021-01-15 23:13:00 +0100217static void program_274265(const struct ram_training *const training)
Angel Pons7a87c922021-01-15 22:50:41 +0100218{
219 int channel;
220
221 for (channel = 0; channel < NUM_CHANNELS; channel++) {
Angel Ponsdea722b2021-03-26 14:11:12 +0100222 mchbar_write32((channel << 10) + 0x274,
Angel Pons0a8b1132021-01-15 23:13:00 +0100223 (training->reg274265[channel][0] << 16) |
Angel Ponsdea722b2021-03-26 14:11:12 +0100224 training->reg274265[channel][1]);
225 mchbar_write16((channel << 10) + 0x265,
226 training->reg274265[channel][2] << 8);
Angel Pons7a87c922021-01-15 22:50:41 +0100227 }
Angel Pons0a8b1132021-01-15 23:13:00 +0100228 if (training->reg2ca9_bit0)
Angel Ponsdea722b2021-03-26 14:11:12 +0100229 mchbar_setbits8(0x2ca9, 1 << 0);
Angel Pons7a87c922021-01-15 22:50:41 +0100230 else
Angel Ponsdea722b2021-03-26 14:11:12 +0100231 mchbar_clrbits8(0x2ca9, 1 << 0);
Angel Pons0a8b1132021-01-15 23:13:00 +0100232
233 printk(RAM_SPEW, "reg2ca9_bit0 = %x\n", training->reg2ca9_bit0);
234
235 for (int i = 0; i < 2; i++)
236 for (int j = 0; j < 3; j++)
237 printk(RAM_SPEW, "reg274265[%d][%d] = %x\n",
238 i, j, training->reg274265[i][j]);
Angel Pons7a87c922021-01-15 22:50:41 +0100239}
240
241static void
242set_2d5x_reg(struct raminfo *info, u16 reg, u16 freq1, u16 freq2,
243 int num_cycles_2, int num_cycles_1, int num_cycles_3,
244 int num_cycles_4, int reverse)
245{
246 struct stru1 vv;
247 char multiplier;
248
249 compute_frequence_ratios(info, freq1, freq2, num_cycles_2, num_cycles_1,
250 0, 1, &vv);
251
252 multiplier =
253 div_roundup(MAX
254 (div_roundup(num_cycles_2, vv.common_time_unit_ps) +
255 div_roundup(num_cycles_3, vv.common_time_unit_ps),
256 div_roundup(num_cycles_1,
257 vv.common_time_unit_ps) +
258 div_roundup(num_cycles_4, vv.common_time_unit_ps))
259 + vv.freq_min_reduced - 1, vv.freq_max_reduced) - 1;
260
261 u32 y =
Elyes Haouas3a998072022-11-18 15:11:02 +0100262 (u8)((vv.freq_max_reduced - vv.freq_min_reduced) +
Angel Pons7a87c922021-01-15 22:50:41 +0100263 vv.freq_max_reduced * multiplier)
264 | (vv.
Elyes Haouas3a998072022-11-18 15:11:02 +0100265 freqs_reversed << 8) | ((u8)(vv.freq_min_reduced *
266 multiplier) << 16) | ((u8)(vv.
Angel Pons7a87c922021-01-15 22:50:41 +0100267 freq_min_reduced
268 *
269 multiplier)
270 << 24);
271 u32 x =
272 vv.freq3_to_2_remaindera | (vv.freq4_to_2_remainder << 8) | (vv.
273 divisor_f3_to_f1
274 << 16)
275 | (vv.divisor_f4_to_f2 << 20) | (vv.freq_min_reduced << 24);
276 if (reverse) {
Angel Ponsdea722b2021-03-26 14:11:12 +0100277 mchbar_write32(reg + 0, y);
278 mchbar_write32(reg + 4, x);
Angel Pons7a87c922021-01-15 22:50:41 +0100279 } else {
Angel Ponsdea722b2021-03-26 14:11:12 +0100280 mchbar_write32(reg + 4, y);
281 mchbar_write32(reg + 0, x);
Angel Pons7a87c922021-01-15 22:50:41 +0100282 }
283}
284
285static void
286set_6d_reg(struct raminfo *info, u16 reg, u16 freq1, u16 freq2,
287 int num_cycles_1, int num_cycles_2, int num_cycles_3,
288 int num_cycles_4)
289{
290 struct stru1 ratios1;
291 struct stru1 ratios2;
292
293 compute_frequence_ratios(info, freq1, freq2, num_cycles_1, num_cycles_2,
294 0, 1, &ratios2);
295 compute_frequence_ratios(info, freq1, freq2, num_cycles_3, num_cycles_4,
296 0, 1, &ratios1);
297 printk(RAM_SPEW, "[%x] <= %x\n", reg,
298 ratios1.freq4_to_max_remainder | (ratios2.
299 freq4_to_max_remainder
300 << 8)
301 | (ratios1.divisor_f4_to_fmax << 16) | (ratios2.
302 divisor_f4_to_fmax
303 << 20));
Angel Ponsdea722b2021-03-26 14:11:12 +0100304 mchbar_write32(reg, ratios1.freq4_to_max_remainder |
305 ratios2.freq4_to_max_remainder << 8 |
306 ratios1.divisor_f4_to_fmax << 16 |
307 ratios2.divisor_f4_to_fmax << 20);
Angel Pons7a87c922021-01-15 22:50:41 +0100308}
309
310static void
311set_2dx8_reg(struct raminfo *info, u16 reg, u8 mode, u16 freq1, u16 freq2,
312 int num_cycles_2, int num_cycles_1, int round_it, int add_freqs)
313{
314 struct stru1 ratios;
315
316 compute_frequence_ratios(info, freq1, freq2, num_cycles_2, num_cycles_1,
317 round_it, add_freqs, &ratios);
318 switch (mode) {
319 case 0:
Angel Ponsdea722b2021-03-26 14:11:12 +0100320 mchbar_write32(reg + 4,
321 ratios.freq_diff_reduced |
322 ratios.freqs_reversed << 8);
323 mchbar_write32(reg,
324 ratios.freq3_to_2_remainder |
325 ratios.freq4_to_max_remainder << 8 |
326 ratios.divisor_f3_to_fmax << 16 |
327 ratios.divisor_f4_to_fmax << 20 |
328 ratios.freq_min_reduced << 24);
Angel Pons7a87c922021-01-15 22:50:41 +0100329 break;
330
331 case 1:
Angel Ponsdea722b2021-03-26 14:11:12 +0100332 mchbar_write32(reg,
333 ratios.freq3_to_2_remainder |
334 ratios.divisor_f3_to_fmax << 16);
Angel Pons7a87c922021-01-15 22:50:41 +0100335 break;
336
337 case 2:
Angel Ponsdea722b2021-03-26 14:11:12 +0100338 mchbar_write32(reg,
339 ratios.freq3_to_2_remainder |
340 ratios.freq4_to_max_remainder << 8 |
341 ratios.divisor_f3_to_fmax << 16 |
342 ratios.divisor_f4_to_fmax << 20);
Angel Pons7a87c922021-01-15 22:50:41 +0100343 break;
344
345 case 4:
Angel Ponsdea722b2021-03-26 14:11:12 +0100346 mchbar_write32(reg,
347 ratios.divisor_f3_to_fmax << 4 |
348 ratios.divisor_f4_to_fmax << 8 |
349 ratios.freqs_reversed << 12 |
350 ratios.freq_min_reduced << 16 |
351 ratios.freq_diff_reduced << 24);
Angel Pons7a87c922021-01-15 22:50:41 +0100352 break;
353 }
354}
355
356static void set_2dxx_series(struct raminfo *info, int s3resume)
357{
358 set_2dx8_reg(info, 0x2d00, 0, 0x78, frequency_11(info) / 2, 1359, 1005,
359 0, 1);
360 set_2dx8_reg(info, 0x2d08, 0, 0x78, 0x78, 3273, 5033, 1, 1);
361 set_2dx8_reg(info, 0x2d10, 0, 0x78, info->fsb_frequency, 1475, 1131, 0,
362 1);
363 set_2dx8_reg(info, 0x2d18, 0, 2 * info->fsb_frequency,
364 frequency_11(info), 1231, 1524, 0, 1);
365 set_2dx8_reg(info, 0x2d20, 0, 2 * info->fsb_frequency,
366 frequency_11(info) / 2, 1278, 2008, 0, 1);
367 set_2dx8_reg(info, 0x2d28, 0, info->fsb_frequency, frequency_11(info),
368 1167, 1539, 0, 1);
369 set_2dx8_reg(info, 0x2d30, 0, info->fsb_frequency,
370 frequency_11(info) / 2, 1403, 1318, 0, 1);
371 set_2dx8_reg(info, 0x2d38, 0, info->fsb_frequency, 0x78, 3460, 5363, 1,
372 1);
373 set_2dx8_reg(info, 0x2d40, 0, info->fsb_frequency, 0x3c, 2792, 5178, 1,
374 1);
375 set_2dx8_reg(info, 0x2d48, 0, 2 * info->fsb_frequency, 0x78, 2738, 4610,
376 1, 1);
377 set_2dx8_reg(info, 0x2d50, 0, info->fsb_frequency, 0x78, 2819, 5932, 1,
378 1);
379 set_2dx8_reg(info, 0x6d4, 1, info->fsb_frequency,
380 frequency_11(info) / 2, 4000, 0, 0, 0);
381 set_2dx8_reg(info, 0x6d8, 2, info->fsb_frequency,
382 frequency_11(info) / 2, 4000, 4000, 0, 0);
383
384 if (s3resume) {
385 printk(RAM_SPEW, "[6dc] <= %x\n",
386 info->cached_training->reg_6dc);
Angel Ponsdea722b2021-03-26 14:11:12 +0100387 mchbar_write32(0x6dc, info->cached_training->reg_6dc);
Angel Pons7a87c922021-01-15 22:50:41 +0100388 } else
389 set_6d_reg(info, 0x6dc, 2 * info->fsb_frequency, frequency_11(info), 0,
390 info->delay46_ps[0], 0,
391 info->delay54_ps[0]);
392 set_2dx8_reg(info, 0x6e0, 1, 2 * info->fsb_frequency,
393 frequency_11(info), 2500, 0, 0, 0);
394 set_2dx8_reg(info, 0x6e4, 1, 2 * info->fsb_frequency,
395 frequency_11(info) / 2, 3500, 0, 0, 0);
396 if (s3resume) {
397 printk(RAM_SPEW, "[6e8] <= %x\n",
398 info->cached_training->reg_6e8);
Angel Ponsdea722b2021-03-26 14:11:12 +0100399 mchbar_write32(0x6e8, info->cached_training->reg_6e8);
Angel Pons7a87c922021-01-15 22:50:41 +0100400 } else
401 set_6d_reg(info, 0x6e8, 2 * info->fsb_frequency, frequency_11(info), 0,
402 info->delay46_ps[1], 0,
403 info->delay54_ps[1]);
404 set_2d5x_reg(info, 0x2d58, 0x78, 0x78, 864, 1195, 762, 786, 0);
405 set_2d5x_reg(info, 0x2d60, 0x195, info->fsb_frequency, 1352, 725, 455,
406 470, 0);
407 set_2d5x_reg(info, 0x2d68, 0x195, 0x3c, 2707, 5632, 3277, 2207, 0);
408 set_2d5x_reg(info, 0x2d70, 0x195, frequency_11(info) / 2, 1276, 758,
409 454, 459, 0);
410 set_2d5x_reg(info, 0x2d78, 0x195, 0x78, 1021, 799, 510, 513, 0);
411 set_2d5x_reg(info, 0x2d80, info->fsb_frequency, 0xe1, 0, 2862, 2579,
412 2588, 0);
413 set_2d5x_reg(info, 0x2d88, info->fsb_frequency, 0xe1, 0, 2690, 2405,
414 2405, 0);
415 set_2d5x_reg(info, 0x2da0, 0x78, 0xe1, 0, 2560, 2264, 2251, 0);
416 set_2d5x_reg(info, 0x2da8, 0x195, frequency_11(info), 1060, 775, 484,
417 480, 0);
418 set_2d5x_reg(info, 0x2db0, 0x195, 0x78, 4183, 6023, 2217, 2048, 0);
Angel Ponsdea722b2021-03-26 14:11:12 +0100419 mchbar_write32(0x2dbc, ((frequency_11(info) / 2) - 1) | 0xe00000);
420 mchbar_write32(0x2db8, (info->fsb_frequency - 1) << 16 | 0x77);
Angel Pons7a87c922021-01-15 22:50:41 +0100421}
422
Angel Pons56823f52021-01-16 11:27:33 +0100423static u16 quickpath_configure_pll_ratio(struct raminfo *info, const u8 x2ca8)
Angel Ponsa8b82712021-01-15 23:39:02 +0100424{
Angel Ponsdea722b2021-03-26 14:11:12 +0100425 mchbar_setbits32(0x18b4, 1 << 21 | 1 << 16);
426 mchbar_setbits32(0x1890, 1 << 25);
427 mchbar_setbits32(0x18b4, 1 << 15);
Angel Ponsa8b82712021-01-15 23:39:02 +0100428
Angel Pons56823f52021-01-16 11:27:33 +0100429 /* Get maximum supported PLL ratio */
430 u16 qpi_pll_ratio = (pci_read_config32(QPI_PHY_0, QPI_PLL_STATUS) >> 24 & 0x7f);
Angel Ponsa8b82712021-01-15 23:39:02 +0100431
Angel Pons56823f52021-01-16 11:27:33 +0100432 /* Adjust value if invalid */
433 if (qpi_pll_ratio == 0 || qpi_pll_ratio > 40)
434 qpi_pll_ratio = 40;
435
436 if (qpi_pll_ratio == 16)
437 qpi_pll_ratio = 12;
438
439 while (qpi_pll_ratio >= 12) {
440 if (qpi_pll_ratio <= (info->clock_speed_index + 3) * 8)
441 break;
442
443 qpi_pll_ratio -= 2;
444 }
445
446 /* Finally, program the ratio */
447 pci_write_config8(QPI_PHY_0, QPI_PLL_RATIO, qpi_pll_ratio);
448
Angel Ponsdea722b2021-03-26 14:11:12 +0100449 const u16 csipll0 = mchbar_read16(0x2c10);
450 mchbar_write16(0x2c10, (qpi_pll_ratio > 26) << 11 | 1 << 10 | qpi_pll_ratio);
Angel Pons56823f52021-01-16 11:27:33 +0100451
Angel Ponsdea722b2021-03-26 14:11:12 +0100452 if (csipll0 != mchbar_read16(0x2c10) && x2ca8 == 0)
453 mchbar_setbits8(0x2ca8, 1 << 0);
Angel Pons56823f52021-01-16 11:27:33 +0100454
Angel Ponsdea722b2021-03-26 14:11:12 +0100455 mchbar_setbits16(0x2c12, 1 << 8);
Angel Ponsa8b82712021-01-15 23:39:02 +0100456
Angel Pons56823f52021-01-16 11:27:33 +0100457 return qpi_pll_ratio;
458}
459
460void early_quickpath_init(struct raminfo *info, const u8 x2ca8)
461{
462 u8 reg8;
463 u32 reg32;
464
465 /* Initialize DDR MPLL first */
466 if (x2ca8 == 0) {
Angel Ponsdea722b2021-03-26 14:11:12 +0100467 mchbar_clrsetbits8(0x164, 0x26, info->clock_speed_index == 0 ? 0x24 : 0x26);
Angel Pons56823f52021-01-16 11:27:33 +0100468
469 /* Program DDR MPLL feedback divider ratio */
Angel Ponsdea722b2021-03-26 14:11:12 +0100470 mchbar_write16(0x2c20, (info->clock_speed_index + 3) * 4);
Angel Pons56823f52021-01-16 11:27:33 +0100471 }
472
473 const u16 qpi_pll_ratio = quickpath_configure_pll_ratio(info, x2ca8);
474
Angel Ponsdea722b2021-03-26 14:11:12 +0100475 mchbar_clrsetbits32(0x1804, 0x3, 0x8400080);
Angel Pons56823f52021-01-16 11:27:33 +0100476 pci_update_config32(QPI_PHY_0, QPI_PHY_CONTROL, 0xfffffffc, 0x400080);
Angel Ponsa8b82712021-01-15 23:39:02 +0100477
Angel Ponsdea722b2021-03-26 14:11:12 +0100478 const u32 x1c04 = mchbar_read32(0x1c04) & 0xc01080;
479 const u32 x1804 = mchbar_read32(0x1804) & 0xc01080;
Angel Ponsa8b82712021-01-15 23:39:02 +0100480
Angel Pons56823f52021-01-16 11:27:33 +0100481 if (x1c04 != x1804 && x2ca8 == 0)
Angel Ponsdea722b2021-03-26 14:11:12 +0100482 mchbar_setbits8(0x2ca8, 1 << 0);
Angel Ponsa8b82712021-01-15 23:39:02 +0100483
Angel Ponsfa5ed052021-12-18 22:25:07 +0100484 reg32 = 0x3000000;
485 if (info->revision >= 0x18 && qpi_pll_ratio <= 12) {
486 /* Get TDP limit in 1/8W units */
487 const msr_t msr = rdmsr(MSR_TURBO_POWER_CURRENT_LIMIT);
488 if ((msr.lo & 0x7fff) <= 90)
489 reg32 = 0;
490 }
Angel Ponsdea722b2021-03-26 14:11:12 +0100491 mchbar_write32(0x18d8, 0x120000);
Angel Ponsfa5ed052021-12-18 22:25:07 +0100492 mchbar_write32(0x18dc, reg32 | 0xa484a);
493
494 reg32 = qpi_pll_ratio > 20 ? 8 : 16;
Angel Ponsa8b82712021-01-15 23:39:02 +0100495 pci_write_config32(QPI_PHY_0, QPI_PHY_EP_SELECT, 0x0);
Angel Ponsfa5ed052021-12-18 22:25:07 +0100496 pci_write_config32(QPI_PHY_0, QPI_PHY_EP_MCTR, 0x9404a | reg32 << 7);
497
Angel Ponsdea722b2021-03-26 14:11:12 +0100498 mchbar_write32(0x18d8, 0x40000);
499 mchbar_write32(0x18dc, 0xb000000);
Angel Ponsa8b82712021-01-15 23:39:02 +0100500 pci_write_config32(QPI_PHY_0, QPI_PHY_EP_SELECT, 0x60000);
501 pci_write_config32(QPI_PHY_0, QPI_PHY_EP_MCTR, 0x0);
Angel Ponsdea722b2021-03-26 14:11:12 +0100502 mchbar_write32(0x18d8, 0x180000);
503 mchbar_write32(0x18dc, 0xc0000142);
Angel Ponsa8b82712021-01-15 23:39:02 +0100504 pci_write_config32(QPI_PHY_0, QPI_PHY_EP_SELECT, 0x20000);
505 pci_write_config32(QPI_PHY_0, QPI_PHY_EP_MCTR, 0x142);
Angel Ponsdea722b2021-03-26 14:11:12 +0100506 mchbar_write32(0x18d8, 0x1e0000);
Angel Ponsa8b82712021-01-15 23:39:02 +0100507
Angel Ponsdea722b2021-03-26 14:11:12 +0100508 const u32 x18dc = mchbar_read32(0x18dc);
509 mchbar_write32(0x18dc, qpi_pll_ratio < 18 ? 2 : 3);
Angel Ponsa8b82712021-01-15 23:39:02 +0100510
Angel Ponsdea722b2021-03-26 14:11:12 +0100511 if (x18dc != mchbar_read32(0x18dc) && x2ca8 == 0)
512 mchbar_setbits8(0x2ca8, 1 << 0);
Angel Ponsa8b82712021-01-15 23:39:02 +0100513
Angel Pons56823f52021-01-16 11:27:33 +0100514 reg8 = qpi_pll_ratio > 20 ? 10 : 9;
515
Angel Ponsdea722b2021-03-26 14:11:12 +0100516 mchbar_write32(0x188c, 0x20bc00 | reg8);
Angel Pons56823f52021-01-16 11:27:33 +0100517 pci_write_config32(QPI_PHY_0, QPI_PHY_PWR_MGMT, 0x40b0c00 | reg8);
518
519 if (qpi_pll_ratio <= 14)
520 reg8 = 0x33;
Angel Ponsfa5ed052021-12-18 22:25:07 +0100521 else if (qpi_pll_ratio <= 22)
Angel Pons56823f52021-01-16 11:27:33 +0100522 reg8 = 0x42;
523 else
524 reg8 = 0x51;
525
Angel Ponsfa5ed052021-12-18 22:25:07 +0100526 info->fsb_frequency = qpi_pll_ratio * 15;
527 mchbar_write32(0x1a10, reg8 << 24 | info->fsb_frequency);
528
529 if (info->silicon_revision == 2 || info->silicon_revision == 3) {
530 mchbar_setbits32(0x18b8, 0x200);
531 mchbar_setbits32(0x1918, 0x300);
532 }
Angel Ponsa8b82712021-01-15 23:39:02 +0100533
Angel Pons56823f52021-01-16 11:27:33 +0100534 if (info->revision > 0x17)
Angel Ponsdea722b2021-03-26 14:11:12 +0100535 mchbar_setbits32(0x18b8, 0xc00);
Angel Pons56823f52021-01-16 11:27:33 +0100536
537 reg32 = ((qpi_pll_ratio > 20) + 1) << 16;
538
Angel Ponsdea722b2021-03-26 14:11:12 +0100539 mchbar_clrsetbits32(0x182c, ~0xfff0f0ff, reg32 | 0x200);
Angel Pons56823f52021-01-16 11:27:33 +0100540 pci_update_config32(QPI_PHY_0, QPI_PHY_PRIM_TIMEOUT, 0xfff0f0ff, reg32 | 0x200);
Angel Ponsdea722b2021-03-26 14:11:12 +0100541 mchbar_clrbits32(0x1a1c, 7 << 28);
542 mchbar_setbits32(0x1a70, 1 << 20);
Angel Ponsa8b82712021-01-15 23:39:02 +0100543
Angel Ponsdea722b2021-03-26 14:11:12 +0100544 mchbar_clrbits32(0x18b4, 1 << 15);
545 mchbar_clrsetbits32(0x1a68, 0x00143fc0, 0x143800);
Angel Ponsa8b82712021-01-15 23:39:02 +0100546
Angel Ponsdea722b2021-03-26 14:11:12 +0100547 const u32 x1e68 = mchbar_read32(0x1e68) & 0x143fc0;
548 const u32 x1a68 = mchbar_read32(0x1a68) & 0x143fc0;
Angel Ponsa8b82712021-01-15 23:39:02 +0100549
Angel Pons56823f52021-01-16 11:27:33 +0100550 if (x1e68 != x1a68 && x2ca8 == 0)
Angel Ponsdea722b2021-03-26 14:11:12 +0100551 mchbar_setbits8(0x2ca8, 1 << 0);
Angel Ponsa8b82712021-01-15 23:39:02 +0100552
Angel Pons56823f52021-01-16 11:27:33 +0100553 pci_update_config32(QPI_LINK_0, QPI_QPILCL, 0xffffff3f, 0x140000);
Angel Ponsa8b82712021-01-15 23:39:02 +0100554
Angel Pons56823f52021-01-16 11:27:33 +0100555 reg32 = pci_read_config32(QPI_LINK_0, QPI_DEF_RMT_VN_CREDITS);
556 pci_write_config32(QPI_LINK_0, QPI_DEF_RMT_VN_CREDITS, (reg32 & 0xfffe4555) | 0x64555);
557
558 if (reg32 != pci_read_config32(QPI_LINK_0, QPI_DEF_RMT_VN_CREDITS) && x2ca8 == 0)
Angel Ponsdea722b2021-03-26 14:11:12 +0100559 mchbar_setbits8(0x2ca8, 1 << 0);
Angel Pons56823f52021-01-16 11:27:33 +0100560
561 pci_update_config32(QPI_NON_CORE, MIRROR_PORT_CTL, ~3, 0x80 * 3);
562
Angel Ponsdea722b2021-03-26 14:11:12 +0100563 reg32 = mchbar_read32(0x1af0);
564 mchbar_write32(0x1af0, (reg32 & 0xfdffcf) | 0x1f020000);
Angel Pons56823f52021-01-16 11:27:33 +0100565
Angel Ponsdea722b2021-03-26 14:11:12 +0100566 if (reg32 != mchbar_read32(0x1af0) && x2ca8 == 0)
567 mchbar_setbits8(0x2ca8, 1 << 0);
Angel Pons56823f52021-01-16 11:27:33 +0100568
Angel Ponsdea722b2021-03-26 14:11:12 +0100569 mchbar_clrbits32(0x1890, 1 << 25);
570 mchbar_clrsetbits32(0x18b4, 0xf << 12, 0x6 << 12);
571 mchbar_write32(0x18a4, 0x22222222);
572 mchbar_write32(0x18a8, 0x22222222);
573 mchbar_write32(0x18ac, 0x22222);
Angel Ponsa8b82712021-01-15 23:39:02 +0100574}
575
Angel Pons7a87c922021-01-15 22:50:41 +0100576void late_quickpath_init(struct raminfo *info, const int s3resume)
577{
578 const u16 deven = pci_read_config16(NORTHBRIDGE, DEVEN);
579
Angel Pons7a87c922021-01-15 22:50:41 +0100580 if (s3resume && info->cached_training) {
Angel Pons0a8b1132021-01-15 23:13:00 +0100581 program_274265(info->cached_training);
Angel Pons7a87c922021-01-15 22:50:41 +0100582 } else {
Angel Pons0a8b1132021-01-15 23:13:00 +0100583 compute_274265(info);
584 program_274265(&info->training);
Angel Pons7a87c922021-01-15 22:50:41 +0100585 }
586
587 set_2dxx_series(info, s3resume);
588
589 if (!(deven & 8)) {
Angel Ponsdea722b2021-03-26 14:11:12 +0100590 mchbar_clrsetbits32(0x2cb0, ~0, 0x40);
Angel Pons7a87c922021-01-15 22:50:41 +0100591 }
592
593 udelay(1000);
594
595 if (deven & 8) {
Angel Ponsdea722b2021-03-26 14:11:12 +0100596 mchbar_setbits32(0xff8, 3 << 11);
597 mchbar_clrbits32(0x2cb0, ~0);
Elyes Haouas9d450b22023-09-10 10:30:29 +0200598 pci_read_config8(PCI_DEV(0, 0x2, 0x0), 0x4c);
599 pci_read_config8(PCI_DEV(0, 0x2, 0x0), 0x4c);
600 pci_read_config8(PCI_DEV(0, 0x2, 0x0), 0x4e);
Angel Pons7a87c922021-01-15 22:50:41 +0100601
Angel Ponsdea722b2021-03-26 14:11:12 +0100602 mchbar_read8(0x1150);
603 mchbar_read8(0x1151);
604 mchbar_read8(0x1022);
605 mchbar_read8(0x16d0);
606 mchbar_write32(0x1300, 0x60606060);
607 mchbar_write32(0x1304, 0x60606060);
608 mchbar_write32(0x1308, 0x78797a7b);
609 mchbar_write32(0x130c, 0x7c7d7e7f);
610 mchbar_write32(0x1310, 0x60606060);
611 mchbar_write32(0x1314, 0x60606060);
612 mchbar_write32(0x1318, 0x60606060);
613 mchbar_write32(0x131c, 0x60606060);
614 mchbar_write32(0x1320, 0x50515253);
615 mchbar_write32(0x1324, 0x54555657);
616 mchbar_write32(0x1328, 0x58595a5b);
617 mchbar_write32(0x132c, 0x5c5d5e5f);
618 mchbar_write32(0x1330, 0x40414243);
619 mchbar_write32(0x1334, 0x44454647);
620 mchbar_write32(0x1338, 0x48494a4b);
621 mchbar_write32(0x133c, 0x4c4d4e4f);
622 mchbar_write32(0x1340, 0x30313233);
623 mchbar_write32(0x1344, 0x34353637);
624 mchbar_write32(0x1348, 0x38393a3b);
625 mchbar_write32(0x134c, 0x3c3d3e3f);
626 mchbar_write32(0x1350, 0x20212223);
627 mchbar_write32(0x1354, 0x24252627);
628 mchbar_write32(0x1358, 0x28292a2b);
629 mchbar_write32(0x135c, 0x2c2d2e2f);
630 mchbar_write32(0x1360, 0x10111213);
631 mchbar_write32(0x1364, 0x14151617);
632 mchbar_write32(0x1368, 0x18191a1b);
633 mchbar_write32(0x136c, 0x1c1d1e1f);
634 mchbar_write32(0x1370, 0x10203);
635 mchbar_write32(0x1374, 0x4050607);
636 mchbar_write32(0x1378, 0x8090a0b);
637 mchbar_write32(0x137c, 0xc0d0e0f);
638 mchbar_write8(0x11cc, 0x4e);
639 mchbar_write32(0x1110, 0x73970404);
640 mchbar_write32(0x1114, 0x72960404);
641 mchbar_write32(0x1118, 0x6f950404);
642 mchbar_write32(0x111c, 0x6d940404);
643 mchbar_write32(0x1120, 0x6a930404);
644 mchbar_write32(0x1124, 0x68a41404);
645 mchbar_write32(0x1128, 0x66a21404);
646 mchbar_write32(0x112c, 0x63a01404);
647 mchbar_write32(0x1130, 0x609e1404);
648 mchbar_write32(0x1134, 0x5f9c1404);
649 mchbar_write32(0x1138, 0x5c961404);
650 mchbar_write32(0x113c, 0x58a02404);
651 mchbar_write32(0x1140, 0x54942404);
652 mchbar_write32(0x1190, 0x900080a);
653 mchbar_write16(0x11c0, 0xc40b);
654 mchbar_write16(0x11c2, 0x303);
655 mchbar_write16(0x11c4, 0x301);
656 mchbar_clrsetbits32(0x1190, ~0, 0x8900080a);
657 mchbar_write32(0x11b8, 0x70c3000);
658 mchbar_write8(0x11ec, 0xa);
659 mchbar_write16(0x1100, 0x800);
660 mchbar_clrsetbits32(0x11bc, ~0, 0x1e84800);
661 mchbar_write16(0x11ca, 0xfa);
662 mchbar_write32(0x11e4, 0x4e20);
663 mchbar_write8(0x11bc, 0xf);
664 mchbar_write16(0x11da, 0x19);
665 mchbar_write16(0x11ba, 0x470c);
666 mchbar_write32(0x1680, 0xe6ffe4ff);
667 mchbar_write32(0x1684, 0xdeffdaff);
668 mchbar_write32(0x1688, 0xd4ffd0ff);
669 mchbar_write32(0x168c, 0xccffc6ff);
670 mchbar_write32(0x1690, 0xc0ffbeff);
671 mchbar_write32(0x1694, 0xb8ffb0ff);
672 mchbar_write32(0x1698, 0xa8ff0000);
673 mchbar_write32(0x169c, 0xc00);
674 mchbar_write32(0x1290, 0x5000000);
Angel Pons7a87c922021-01-15 22:50:41 +0100675 }
676
Angel Ponsdea722b2021-03-26 14:11:12 +0100677 mchbar_write32(0x124c, 0x15040d00);
678 mchbar_write32(0x1250, 0x7f0000);
679 mchbar_write32(0x1254, 0x1e220004);
680 mchbar_write32(0x1258, 0x4000004);
681 mchbar_write32(0x1278, 0x0);
682 mchbar_write32(0x125c, 0x0);
683 mchbar_write32(0x1260, 0x0);
684 mchbar_write32(0x1264, 0x0);
685 mchbar_write32(0x1268, 0x0);
686 mchbar_write32(0x126c, 0x0);
687 mchbar_write32(0x1270, 0x0);
688 mchbar_write32(0x1274, 0x0);
Angel Pons7a87c922021-01-15 22:50:41 +0100689
690 if (deven & 8) {
Angel Ponsdea722b2021-03-26 14:11:12 +0100691 mchbar_write16(0x1214, 0x320);
692 mchbar_write32(0x1600, 0x40000000);
693 mchbar_clrsetbits32(0x11f4, ~0, 1 << 28);
694 mchbar_clrsetbits16(0x1230, ~0, 1 << 15);
695 mchbar_write32(0x1400, 0x13040020);
696 mchbar_write32(0x1404, 0xe090120);
697 mchbar_write32(0x1408, 0x5120220);
698 mchbar_write32(0x140c, 0x5120330);
699 mchbar_write32(0x1410, 0xe090220);
700 mchbar_write32(0x1414, 0x1010001);
701 mchbar_write32(0x1418, 0x1110000);
702 mchbar_write32(0x141c, 0x9020020);
703 mchbar_write32(0x1420, 0xd090220);
704 mchbar_write32(0x1424, 0x2090220);
705 mchbar_write32(0x1428, 0x2090330);
706 mchbar_write32(0x142c, 0xd090220);
707 mchbar_write32(0x1430, 0x1010001);
708 mchbar_write32(0x1434, 0x1110000);
709 mchbar_write32(0x1438, 0x11040020);
710 mchbar_write32(0x143c, 0x4030220);
711 mchbar_write32(0x1440, 0x1060220);
712 mchbar_write32(0x1444, 0x1060330);
713 mchbar_write32(0x1448, 0x4030220);
714 mchbar_write32(0x144c, 0x1010001);
715 mchbar_write32(0x1450, 0x1110000);
716 mchbar_write32(0x1454, 0x4010020);
717 mchbar_write32(0x1458, 0xb090220);
718 mchbar_write32(0x145c, 0x1090220);
719 mchbar_write32(0x1460, 0x1090330);
720 mchbar_write32(0x1464, 0xb090220);
721 mchbar_write32(0x1468, 0x1010001);
722 mchbar_write32(0x146c, 0x1110000);
723 mchbar_write32(0x1470, 0xf040020);
724 mchbar_write32(0x1474, 0xa090220);
725 mchbar_write32(0x1478, 0x1120220);
726 mchbar_write32(0x147c, 0x1120330);
727 mchbar_write32(0x1480, 0xa090220);
728 mchbar_write32(0x1484, 0x1010001);
729 mchbar_write32(0x1488, 0x1110000);
730 mchbar_write32(0x148c, 0x7020020);
731 mchbar_write32(0x1490, 0x1010220);
732 mchbar_write32(0x1494, 0x10210);
733 mchbar_write32(0x1498, 0x10320);
734 mchbar_write32(0x149c, 0x1010220);
735 mchbar_write32(0x14a0, 0x1010001);
736 mchbar_write32(0x14a4, 0x1110000);
737 mchbar_write32(0x14a8, 0xd040020);
738 mchbar_write32(0x14ac, 0x8090220);
739 mchbar_write32(0x14b0, 0x1111310);
740 mchbar_write32(0x14b4, 0x1111420);
741 mchbar_write32(0x14b8, 0x8090220);
742 mchbar_write32(0x14bc, 0x1010001);
743 mchbar_write32(0x14c0, 0x1110000);
744 mchbar_write32(0x14c4, 0x3010020);
745 mchbar_write32(0x14c8, 0x7090220);
746 mchbar_write32(0x14cc, 0x1081310);
747 mchbar_write32(0x14d0, 0x1081420);
748 mchbar_write32(0x14d4, 0x7090220);
749 mchbar_write32(0x14d8, 0x1010001);
750 mchbar_write32(0x14dc, 0x1110000);
751 mchbar_write32(0x14e0, 0xb040020);
752 mchbar_write32(0x14e4, 0x2030220);
753 mchbar_write32(0x14e8, 0x1051310);
754 mchbar_write32(0x14ec, 0x1051420);
755 mchbar_write32(0x14f0, 0x2030220);
756 mchbar_write32(0x14f4, 0x1010001);
757 mchbar_write32(0x14f8, 0x1110000);
758 mchbar_write32(0x14fc, 0x5020020);
759 mchbar_write32(0x1500, 0x5090220);
760 mchbar_write32(0x1504, 0x2071310);
761 mchbar_write32(0x1508, 0x2071420);
762 mchbar_write32(0x150c, 0x5090220);
763 mchbar_write32(0x1510, 0x1010001);
764 mchbar_write32(0x1514, 0x1110000);
765 mchbar_write32(0x1518, 0x7040120);
766 mchbar_write32(0x151c, 0x2090220);
767 mchbar_write32(0x1520, 0x70b1210);
768 mchbar_write32(0x1524, 0x70b1310);
769 mchbar_write32(0x1528, 0x2090220);
770 mchbar_write32(0x152c, 0x1010001);
771 mchbar_write32(0x1530, 0x1110000);
772 mchbar_write32(0x1534, 0x1010110);
773 mchbar_write32(0x1538, 0x1081310);
774 mchbar_write32(0x153c, 0x5041200);
775 mchbar_write32(0x1540, 0x5041310);
776 mchbar_write32(0x1544, 0x1081310);
777 mchbar_write32(0x1548, 0x1010001);
778 mchbar_write32(0x154c, 0x1110000);
779 mchbar_write32(0x1550, 0x1040120);
780 mchbar_write32(0x1554, 0x4051210);
781 mchbar_write32(0x1558, 0xd051200);
782 mchbar_write32(0x155c, 0xd051200);
783 mchbar_write32(0x1560, 0x4051210);
784 mchbar_write32(0x1564, 0x1010001);
785 mchbar_write32(0x1568, 0x1110000);
786 mchbar_write16(0x1222, 0x220a);
787 mchbar_write16(0x123c, 0x1fc0);
788 mchbar_write16(0x1220, 0x1388);
Angel Pons7a87c922021-01-15 22:50:41 +0100789 }
790}