blob: ee19b61841145f2da6551a4854139e172da51755 [file] [log] [blame]
Damien Zammit003d15c2015-11-20 17:17:51 +11001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2015 Damien Zammit <damien@zamaudio.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <arch/io.h>
Damien Zammit003d15c2015-11-20 17:17:51 +110018#include <console/console.h>
19#include <cpu/x86/cache.h>
Damien Zammit003d15c2015-11-20 17:17:51 +110020#include <delay.h>
21#include <halt.h>
22#include <lib.h>
23#include "pineview.h"
24#include "raminit.h"
Damien Zammit003d15c2015-11-20 17:17:51 +110025#include <spd.h>
26#include <string.h>
27
28/* Debugging macros. */
Martin Roth33232602017-06-24 14:48:50 -060029#if IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)
Damien Zammit003d15c2015-11-20 17:17:51 +110030#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
31#else
32#define PRINTK_DEBUG(x...)
33#endif
34
35#define MAX_TCLK_667 0x30
36#define MAX_TCLK_800 0x25
37#define MAX_TAC_667 0x45
38#define MAX_TAC_800 0x40
39
40#define NOP_CMD (1 << 1)
41#define PRE_CHARGE_CMD (1 << 2)
42#define MRS_CMD ((1 << 2) | (1 << 1))
43#define EMRS_CMD (1 << 3)
44#define EMRS1_CMD (EMRS_CMD | (1 << 4))
45#define EMRS2_CMD (EMRS_CMD | (1 << 5))
46#define EMRS3_CMD (EMRS_CMD | (1 << 5) | (1 << 4))
47#define ZQCAL_CMD ((1 << 3) | (1 << 1))
48#define CBR_CMD ((1 << 3) | (1 << 2))
49#define NORMAL_OP_CMD ((1 << 3) | (1 << 2) | (1 << 1))
50
51#define UBDIMM 1
52#define SODIMM 2
53
54#define TOTAL_CHANNELS 1
55#define TOTAL_DIMMS 2
56
57#define DIMM_IS_POPULATED(dimms, idx) (dimms[idx].card_type != 0)
58#define IF_DIMM_POPULATED(dimms, idx) if (dimms[idx].card_type != 0)
Elyes HAOUASa342f392018-10-17 10:56:26 +020059#define ONLY_DIMMA_IS_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110060 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
61 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3)))
Elyes HAOUASa342f392018-10-17 10:56:26 +020062#define ONLY_DIMMB_IS_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110063 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3) && \
64 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2)))
Elyes HAOUASa342f392018-10-17 10:56:26 +020065#define BOTH_DIMMS_ARE_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110066 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
67 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3))))
68#define FOR_EACH_DIMM(idx) \
69 for (idx = 0; idx < TOTAL_DIMMS; ++idx)
70#define FOR_EACH_POPULATED_DIMM(dimms, idx) \
71 FOR_EACH_DIMM(idx) IF_DIMM_POPULATED(dimms, idx)
72#define CHANNEL_IS_POPULATED(dimms, idx) ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0))
73#define CHANNEL_IS_CARDF(dimms, idx) ((dimms[idx<<1].card_type == 0xf) || (dimms[(idx<<1) + 1].card_type == 0xf))
74#define IF_CHANNEL_POPULATED(dimms, idx) if ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0))
75#define FOR_EACH_CHANNEL(idx) \
76 for (idx = 0; idx < TOTAL_CHANNELS; ++idx)
77#define FOR_EACH_POPULATED_CHANNEL(dimms, idx) \
78 FOR_EACH_CHANNEL(idx) IF_CHANNEL_POPULATED(dimms, idx)
79
80#define RANKS_PER_CHANNEL 4
81
82#define FOR_EACH_RANK_IN_CHANNEL(r) \
83 for (r = 0; r < RANKS_PER_CHANNEL; ++r)
84#define FOR_EACH_POPULATED_RANK_IN_CHANNEL(dimms, ch, r) \
85 FOR_EACH_RANK_IN_CHANNEL(r) if (rank_is_populated(dimms, ch, r))
86#define FOR_EACH_RANK(ch, r) \
87 FOR_EACH_CHANNEL(ch) FOR_EACH_RANK_IN_CHANNEL(r)
88#define FOR_EACH_POPULATED_RANK(dimms, ch, r) \
89 FOR_EACH_RANK(ch, r) if (rank_is_populated(dimms, ch, r))
90
91static bool rank_is_populated(struct dimminfo dimms[], u8 ch, u8 r)
92{
93 return ((dimms[ch<<1].card_type && ((r) < dimms[ch<<1].ranks))
94 || (dimms[(ch<<1) + 1].card_type
95 && ((r) >= 2)
96 && ((r) < (dimms[(ch<<1) + 1].ranks + 2))));
97}
98
99static inline void barrier(void)
100{
101 __asm__ __volatile__("": : :"memory");
102}
103
Elyes HAOUASb60920d2018-09-20 17:38:38 +0200104static inline int spd_read_byte(unsigned int device, unsigned int address)
Damien Zammit003d15c2015-11-20 17:17:51 +1100105{
106 return smbus_read_byte(device, address);
107}
108
Arthur Heymans097d7532017-04-17 10:14:32 +0200109static int decode_spd(struct dimminfo *d, int i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100110{
111 d->type = 0;
112 if (d->spd_data[20] == 0x2) {
113 d->type = UBDIMM;
114 } else if (d->spd_data[20] == 0x4) {
115 d->type = SODIMM;
116 }
117 d->sides = (d->spd_data[5] & 0x7) + 1;
118 d->banks = (d->spd_data[17] >> 2) - 1;
119 d->chip_capacity = d->banks;
120 d->rows = d->spd_data[3];// - 12;
121 d->cols = d->spd_data[4];// - 9;
122 d->cas_latencies = 0x78;
123 d->cas_latencies &= d->spd_data[18];
124 if (d->cas_latencies == 0)
125 d->cas_latencies = 7;
126 d->tAAmin = d->spd_data[26];
127 d->tCKmin = d->spd_data[25];
128 d->width = (d->spd_data[13] >> 3) - 1;
129 d->page_size = (d->width+1) * (1 << d->cols); // Bytes
130 d->tRAS = d->spd_data[30];
131 d->tRP = d->spd_data[27];
132 d->tRCD = d->spd_data[29];
133 d->tWR = d->spd_data[36];
134 d->ranks = d->sides; // XXX
Martin Roth33232602017-06-24 14:48:50 -0600135#if IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)
Arthur Heymans097d7532017-04-17 10:14:32 +0200136 const char *ubso[2] = { "UB", "SO" };
Damien Zammit003d15c2015-11-20 17:17:51 +1100137#endif
138 PRINTK_DEBUG("%s-DIMM %d\n", &ubso[d->type][0], i);
139 PRINTK_DEBUG(" Sides : %d\n", d->sides);
140 PRINTK_DEBUG(" Banks : %d\n", d->banks);
141 PRINTK_DEBUG(" Ranks : %d\n", d->ranks);
142 PRINTK_DEBUG(" Rows : %d\n", d->rows);
143 PRINTK_DEBUG(" Cols : %d\n", d->cols);
144 PRINTK_DEBUG(" Page size : %d\n", d->page_size);
145 PRINTK_DEBUG(" Width : %d\n", (d->width + 1) * 8);
146
147 return 0;
148}
149
150/* Ram Config: DIMMB-DIMMA
151 * 0 EMPTY-EMPTY
152 * 1 EMPTY-x16SS
153 * 2 EMPTY-x16DS
154 * 3 x16SS-x16SS
155 * 4 x16DS-x16DS
156 * 5 EMPTY- x8DS
157 * 6 x8DS - x8DS
158 */
159static void find_ramconfig(struct sysinfo *s, u32 chan)
160{
161 if (s->dimms[chan>>1].sides == 0) {
162 // NC
163 if (s->dimms[(chan>>1) + 1].sides == 0) {
164 // NC/NC
165 s->dimm_config[chan] = 0;
166 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
167 // NC/SS
168 if (s->dimms[(chan>>1) + 1].width == 0) {
169 // NC/8SS
170 s->dimm_config[chan] = 1;
171 } else {
172 // NC/16SS
173 s->dimm_config[chan] = 1;
174 }
175 } else {
176 // NC/DS
177 if (s->dimms[(chan>>1) + 1].width == 0) {
178 // NC/8DS
179 s->dimm_config[chan] = 5;
180 } else {
181 // NC/16DS
182 s->dimm_config[chan] = 2;
183 }
184 }
185 } else if (s->dimms[chan>>1].sides == 1) {
186 // SS
187 if (s->dimms[(chan>>1) + 1].sides == 0) {
188 // SS/NC
189 if (s->dimms[chan>>1].width == 0) {
190 // 8SS/NC
191 s->dimm_config[chan] = 1;
192 } else {
193 // 16SS/NC
194 s->dimm_config[chan] = 1;
195 }
196 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
197 // SS/SS
198 if (s->dimms[chan>>1].width == 0) {
199 if (s->dimms[(chan>>1) + 1].width == 0) {
200 // 8SS/8SS
201 s->dimm_config[chan] = 3;
202 } else {
203 // 8SS/16SS
204 die("Mixed Not supported\n");
205 }
206 } else {
207 if (s->dimms[(chan>>1) + 1].width == 0) {
208 // 16SS/8SS
209 die("Mixed Not supported\n");
210 } else {
211 // 16SS/16SS
212 s->dimm_config[chan] = 3;
213 }
214 }
215 } else {
216 // SS/DS
217 if (s->dimms[chan>>1].width == 0) {
218 if (s->dimms[(chan>>1) + 1].width == 0) {
219 // 8SS/8DS
220 die("Mixed Not supported\n");
221 } else {
222 die("Mixed Not supported\n");
223 }
224 } else {
225 if (s->dimms[(chan>>1) + 1].width == 0) {
226 // 16SS/8DS
227 die("Mixed Not supported\n");
228 } else {
229 die("Mixed Not supported\n");
230 }
231 }
232 }
233 } else {
234 // DS
235 if (s->dimms[(chan>>1) + 1].sides == 0) {
236 // DS/NC
237 if (s->dimms[chan>>1].width == 0) {
238 // 8DS/NC
239 s->dimm_config[chan] = 5;
240 } else {
241 s->dimm_config[chan] = 4;
242 }
243 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
244 // DS/SS
245 if (s->dimms[chan>>1].width == 0) {
246 if (s->dimms[(chan>>1) + 1].width == 0) {
247 // 8DS/8SS
248 die("Mixed Not supported\n");
249 } else {
250 // 8DS/16SS
251 die("Mixed Not supported\n");
252 }
253 } else {
254 if (s->dimms[(chan>>1) + 1].width == 0) {
255 die("Mixed Not supported\n");
256 } else {
257 // 16DS/16DS
258 s->dimm_config[chan] = 4;
259 }
260 }
261 } else {
262 // DS/DS
263 if (s->dimms[chan>>1].width == 0 && s->dimms[(chan>>1)+1].width == 0) {
264 // 8DS/8DS
265 s->dimm_config[chan] = 6;
266 }
267 }
268 }
269}
270
271static void sdram_read_spds(struct sysinfo *s)
272{
Arthur Heymans1f6369e2018-08-20 11:27:41 +0200273 u8 i, chan;
Damien Zammit003d15c2015-11-20 17:17:51 +1100274 s->dt0mode = 0;
275 FOR_EACH_DIMM(i) {
Arthur Heymans1f6369e2018-08-20 11:27:41 +0200276 if (i2c_block_read(s->spd_map[i], 0, 64, s->dimms[i].spd_data) != 64)
277 s->dimms[i].card_type = 0;
278
279 s->dimms[i].card_type = s->dimms[i].spd_data[62] & 0x1f;
Damien Zammit003d15c2015-11-20 17:17:51 +1100280 hexdump(s->dimms[i].spd_data, 64);
281 }
282
283 s->spd_type = 0;
284 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
285 switch (s->dimms[i].spd_data[2]) {
286 case 0x8:
287 s->spd_type = DDR2;
288 break;
289 case 0xb:
290 default:
291 die("DIMM type mismatch\n");
292 break;
293 }
294 }
295
296 int err = 1;
297 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Arthur Heymans097d7532017-04-17 10:14:32 +0200298 err = decode_spd(&s->dimms[i], i);
Damien Zammit003d15c2015-11-20 17:17:51 +1100299 s->dt0mode |= (s->dimms[i].spd_data[49] & 0x2) >> 1;
300 }
301 if (err) {
302 die("No memory dimms, halt\n");
303 }
304
305 FOR_EACH_POPULATED_CHANNEL(s->dimms, chan) {
306 find_ramconfig(s, chan);
307 PRINTK_DEBUG(" Config[CH%d] : %d\n",
308 chan, s->dimm_config[chan]);
309 }
310}
311
Martin Roth33232602017-06-24 14:48:50 -0600312#if IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)
Damien Zammit003d15c2015-11-20 17:17:51 +1100313static u32 fsb_reg_to_mhz(u32 speed)
314{
315 return (speed * 133) + 667;
316}
317
318static u32 ddr_reg_to_mhz(u32 speed)
319{
320 u32 mhz;
321 mhz = (speed == 0) ? 667 :
322 (speed == 1) ? 800 :
323 0;
324 return mhz;
325}
326#endif
327
328static u8 lsbpos(u8 val) //Forward
329{
330 u8 i;
331 for (i = 0; (i < 8) && ((val & (1 << i)) == 0); i++);
332 return i;
333}
334
335static u8 msbpos(u8 val) //Reverse
336{
337 u8 i;
338 for (i = 7; (i >= 0) && ((val & (1 << i)) == 0); i--);
339 return i;
340}
341
342static void sdram_detect_smallest_params(struct sysinfo *s)
343{
Arthur Heymans6bf13012017-06-10 12:03:27 +0200344 static const u16 mult[6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100345 3000, // 667
346 2500, // 800
347 };
348
349 u8 i;
Damien Zammit003d15c2015-11-20 17:17:51 +1100350 u32 maxtras = 0;
351 u32 maxtrp = 0;
352 u32 maxtrcd = 0;
353 u32 maxtwr = 0;
354 u32 maxtrfc = 0;
355 u32 maxtwtr = 0;
356 u32 maxtrrd = 0;
357 u32 maxtrtp = 0;
358
359 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
360 maxtras = max(maxtras, s->dimms[i].spd_data[30] * 1000);
361 maxtrp = max(maxtrp, (s->dimms[i].spd_data[27] * 1000) >> 2);
362 maxtrcd = max(maxtrcd, (s->dimms[i].spd_data[29] * 1000) >> 2);
363 maxtwr = max(maxtwr, (s->dimms[i].spd_data[36] * 1000) >> 2);
364 maxtrfc = max(maxtrfc, s->dimms[i].spd_data[42] * 1000 +
365 (s->dimms[i].spd_data[40] & 0xf));
366 maxtwtr = max(maxtwtr, (s->dimms[i].spd_data[37] * 1000) >> 2);
367 maxtrrd = max(maxtrrd, (s->dimms[i].spd_data[28] * 1000) >> 2);
368 maxtrtp = max(maxtrtp, (s->dimms[i].spd_data[38] * 1000) >> 2);
369 }
Arthur Heymans12a4e982017-04-28 20:53:05 +0200370 /*
371 * TODO: on ddr3 there might be some minimal required values for some
372 * Timings: MIN_TRAS = 9, MIN_TRP = 3, MIN_TRCD = 3, MIN_TWR = 3,
373 * MIN_TWTR = 4, MIN_TRRD = 2, MIN_TRTP = 4
374 */
375 s->selected_timings.tRAS = MIN(24, DIV_ROUND_UP(maxtras,
376 mult[s->selected_timings.mem_clock]));
377 s->selected_timings.tRP = MIN(10, DIV_ROUND_UP(maxtrp,
378 mult[s->selected_timings.mem_clock]));
379 s->selected_timings.tRCD = MIN(10, DIV_ROUND_UP(maxtrcd,
380 mult[s->selected_timings.mem_clock]));
381 s->selected_timings.tWR = MIN(15, DIV_ROUND_UP(maxtwr,
382 mult[s->selected_timings.mem_clock]));
383 /* Needs to be even */
384 s->selected_timings.tRFC = 0xfe & (MIN(78, DIV_ROUND_UP(maxtrfc,
385 mult[s->selected_timings.mem_clock])) + 1);
386 s->selected_timings.tWTR = MIN(15, DIV_ROUND_UP(maxtwtr,
387 mult[s->selected_timings.mem_clock]));
388 s->selected_timings.tRRD = MIN(15, DIV_ROUND_UP(maxtrrd,
389 mult[s->selected_timings.mem_clock]));
Arthur Heymans5bb27b72017-08-26 21:24:21 +0200390 s->selected_timings.tRTP = MIN(15, DIV_ROUND_UP(maxtrtp,
Arthur Heymans12a4e982017-04-28 20:53:05 +0200391 mult[s->selected_timings.mem_clock]));
Damien Zammit003d15c2015-11-20 17:17:51 +1100392
393 PRINTK_DEBUG("Selected timings:\n");
394 PRINTK_DEBUG("\tFSB: %dMHz\n", fsb_reg_to_mhz(s->selected_timings.fsb_clock));
395 PRINTK_DEBUG("\tDDR: %dMHz\n", ddr_reg_to_mhz(s->selected_timings.mem_clock));
396
397 PRINTK_DEBUG("\tCAS: %d\n", s->selected_timings.CAS);
398 PRINTK_DEBUG("\ttRAS: %d\n", s->selected_timings.tRAS);
399 PRINTK_DEBUG("\ttRP: %d\n", s->selected_timings.tRP);
400 PRINTK_DEBUG("\ttRCD: %d\n", s->selected_timings.tRCD);
401 PRINTK_DEBUG("\ttWR: %d\n", s->selected_timings.tWR);
402 PRINTK_DEBUG("\ttRFC: %d\n", s->selected_timings.tRFC);
403 PRINTK_DEBUG("\ttWTR: %d\n", s->selected_timings.tWTR);
404 PRINTK_DEBUG("\ttRRD: %d\n", s->selected_timings.tRRD);
405 PRINTK_DEBUG("\ttRTP: %d\n", s->selected_timings.tRTP);
406}
407
408static void sdram_detect_ram_speed(struct sysinfo *s)
409{
410 u8 cas, reg8;
411 u32 reg32;
412 u32 freq = 0;
413 u32 fsb = 0;
414 u8 i;
415 u8 commoncas = 0;
416 u8 highcas = 0;
417 u8 lowcas = 0;
418
419 // Core frequency
420 fsb = (pci_read_config8(PCI_DEV(0,0,0), 0xe3) & 0x70) >> 4;
421 if (fsb) {
422 fsb = 5 - fsb;
423 } else {
424 fsb = FSB_CLOCK_800MHz;
425 }
426
427 // DDR frequency
428 freq = (pci_read_config8(PCI_DEV(0,0,0), 0xe3) & 0x80) >> 7;
429 freq |= (pci_read_config8(PCI_DEV(0,0,0), 0xe4) & 0x3) << 1;
430 if (freq) {
431 freq = 6 - freq;
432 } else {
433 freq = MEM_CLOCK_800MHz;
434 }
435
436 // Detect a common CAS latency
437 commoncas = 0xff;
438 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
439 commoncas &= s->dimms[i].spd_data[18];
440 }
441 if (commoncas == 0) {
442 die("No common CAS among dimms\n");
443 }
444
445 // Start with fastest common CAS
446 cas = 0;
447 highcas = msbpos(commoncas);
448 lowcas = max(lsbpos(commoncas), 5);
449
450 while (cas == 0 && highcas >= lowcas) {
451 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
452 switch (freq) {
453 case MEM_CLOCK_800MHz:
454 if ((s->dimms[i].spd_data[9] > 0x25) ||
455 (s->dimms[i].spd_data[10] > 0x40)) {
456 // CAS too fast, lower it
457 highcas--;
458 break;
459 } else {
460 cas = highcas;
461 }
462 break;
463 case MEM_CLOCK_667MHz:
464 default:
465 if ((s->dimms[i].spd_data[9] > 0x30) ||
466 (s->dimms[i].spd_data[10] > 0x45)) {
467 // CAS too fast, lower it
468 highcas--;
469 break;
470 } else {
471 cas = highcas;
472 }
473 break;
474 }
475 }
476 }
477 if (highcas < lowcas) {
478 // Timings not supported by MCH, lower the frequency
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200479 if (freq == MEM_CLOCK_800MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +1100480 freq--;
481 PRINTK_DEBUG("Run DDR clock speed reduced due to timings\n");
482 } else {
483 die("Timings not supported by MCH\n");
484 }
485 cas = 0;
486 highcas = msbpos(commoncas);
487 lowcas = lsbpos(commoncas);
488 while (cas == 0 && highcas >= lowcas) {
489 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
490 switch (freq) {
491 case MEM_CLOCK_800MHz:
492 if ((s->dimms[i].spd_data[9] > 0x25) ||
493 (s->dimms[i].spd_data[10] > 0x40)) {
494 // CAS too fast, lower it
495 highcas--;
496 break;
497 } else {
498 cas = highcas;
499 }
500 break;
501 case MEM_CLOCK_667MHz:
502 default:
503 if ((s->dimms[i].spd_data[9] > 0x30) ||
504 (s->dimms[i].spd_data[10] > 0x45)) {
505 // CAS too fast, lower it
506 highcas--;
507 break;
508 } else {
509 cas = highcas;
510 }
511 break;
512 }
513 }
514 }
515 if (cas == 0) {
516 die("Unsupported dimms\n");
517 }
518 }
519
520 s->selected_timings.CAS = cas;
521 s->selected_timings.mem_clock = freq;
522 s->selected_timings.fsb_clock = fsb;
523
524 PRINTK_DEBUG("Drive Memory at %dMHz with CAS = %d clocks\n", ddr_reg_to_mhz(s->selected_timings.mem_clock), s->selected_timings.CAS);
525
526 // Set memory frequency
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200527 if (s->boot_path == BOOT_PATH_RESET)
528 return;
Damien Zammit003d15c2015-11-20 17:17:51 +1100529 MCHBAR32(0xf14) = MCHBAR32(0xf14) | 0x1;
530 reg32 = (MCHBAR32(0xc00) & (~0x70)) | (1 << 10);
531 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
532 reg8 = 3;
533 } else {
534 reg8 = 2;
535 }
536 reg32 |= reg8 << 4;
537 MCHBAR32(0xc00) = reg32;
538 s->selected_timings.mem_clock = ((MCHBAR32(0xc00) >> 4) & 0x7) - 2;
539 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
540 PRINTK_DEBUG("MCH validated at 800MHz\n");
541 s->nodll = 0;
542 s->maxpi = 63;
543 s->pioffset = 0;
544 } else if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
545 PRINTK_DEBUG("MCH validated at 667MHz\n");
546 s->nodll = 1;
547 s->maxpi = 15;
548 s->pioffset = 1;
549 } else {
550 PRINTK_DEBUG("MCH set to unknown (%02x)\n",
551 (uint8_t) s->selected_timings.mem_clock & 0xff);
552 }
553}
554
555#define HPET_BASE 0xfed00000
556#define HPET32(x) *((volatile u32 *)(HPET_BASE + x))
557static void enable_hpet(void)
558{
559 u32 reg32;
560 reg32 = RCBA32(0x3404);
561 reg32 &= ~0x3;
562 reg32 |= (1 << 7);
563 RCBA32(0x3404) = reg32;
564 HPET32(0x10) = HPET32(0x10) | 1;
565}
566
567static void sdram_clk_crossing(struct sysinfo *s)
568{
569 u8 clk_idx, fsb_idx;
Arthur Heymans6bf13012017-06-10 12:03:27 +0200570 static const u32 clkcross[2][2][4] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100571 {
572 {0xFFFFFFFF, 0x05030305, 0x0000FFFF, 0x00000000}, //667 667
573 {0x1F1F1F1F, 0x2A1F1FA5, 0x00000000, 0x05000002}, //667 800
574 },
575 {
576 {0x1F1F1F1F, 0x0D07070B, 0x00000000, 0x00000000}, //800 667
577 {0xFFFFFFFF, 0x05030305, 0x0000FFFF, 0x00000000}, //800 800
578 }
579 };
580 clk_idx = s->selected_timings.mem_clock;
581 fsb_idx = s->selected_timings.fsb_clock;
582
583 MCHBAR32(0xc04) = clkcross[fsb_idx][clk_idx][0];
584 MCHBAR32(0xc50) = clkcross[fsb_idx][clk_idx][1];
585 MCHBAR32(0xc54) = clkcross[fsb_idx][clk_idx][2];
586 MCHBAR32(0xc28) = 0;
587 MCHBAR32(0xc2c) = clkcross[fsb_idx][clk_idx][3];
588 MCHBAR32(0xc08) = MCHBAR32(0xc08) | (1 << 7);
589
590 if ((fsb_idx == 0) && (clk_idx == 1)) {
591 MCHBAR8(0x6d4) = 0;
592 MCHBAR32(0x700) = 0;
593 MCHBAR32(0x704) = 0;
594 }
595
Arthur Heymans6bf13012017-06-10 12:03:27 +0200596 static const u32 clkcross2[2][2][8] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100597 {
598 { 0, 0x08010204, 0, 0x08010204, 0, 0, 0, 0x04080102}, // 667 667
599 { 0x04080000, 0x10010002, 0x10000000, 0x20010208, 0, 0x00000004, 0x02040000, 0x08100102}, // 667 800
600 },
601 {
602 { 0x10000000, 0x20010208, 0x04080000, 0x10010002, 0, 0, 0x08000000, 0x10200204}, // 800 667
603 { 0x00000000, 0x08010204, 0, 0x08010204, 0, 0, 0, 0x04080102}, // 800 800
604 }
605 };
606
607 MCHBAR32(0x6d8) = clkcross2[fsb_idx][clk_idx][0];
608 MCHBAR32(0x6e0) = clkcross2[fsb_idx][clk_idx][0];
609 MCHBAR32(0x6e8) = clkcross2[fsb_idx][clk_idx][0];
610 MCHBAR32(0x6d8+4) = clkcross2[fsb_idx][clk_idx][1];
611 MCHBAR32(0x6e0+4) = clkcross2[fsb_idx][clk_idx][1];
612 MCHBAR32(0x6e8+4) = clkcross2[fsb_idx][clk_idx][1];
613 MCHBAR32(0x6f0) = clkcross2[fsb_idx][clk_idx][2];
614 MCHBAR32(0x6f4) = clkcross2[fsb_idx][clk_idx][3];
615 MCHBAR32(0x6f8) = clkcross2[fsb_idx][clk_idx][4];
616 MCHBAR32(0x6fc) = clkcross2[fsb_idx][clk_idx][5];
617 MCHBAR32(0x708) = clkcross2[fsb_idx][clk_idx][6];
618 MCHBAR32(0x70c) = clkcross2[fsb_idx][clk_idx][7];
619}
620
621static void sdram_clkmode(struct sysinfo *s)
622{
623 u8 reg8;
624 u16 reg16;
625
626 MCHBAR16(0x1b6) = MCHBAR16(0x1b6) & ~(1 << 8);
627 MCHBAR8(0x1b6) = MCHBAR8(0x1b6) & ~0x3f;
628
629 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
630 reg8 = 0;
631 reg16 = 1;
632 } else {
633 reg8 = 1;
634 reg16 = (1 << 8) | (1 << 5);
635 }
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200636 if (s->boot_path != BOOT_PATH_RESET)
637 MCHBAR16(0x1c0) = (MCHBAR16(0x1c0) & ~(0x033f)) | reg16;
Damien Zammit003d15c2015-11-20 17:17:51 +1100638
639 MCHBAR32(0x220) = 0x58001117;
640 MCHBAR32(0x248) = (MCHBAR32(0x248) | (1 << 23));
641
642 const u32 cas_to_reg[2][4] = {
643 {0x00000000, 0x00030100, 0x0C240201, 0x00000000}, // 667
644 {0x00000000, 0x00030100, 0x0C240201, 0x10450302} // 800
645 };
646
647 MCHBAR32(0x224) = cas_to_reg[reg8][s->selected_timings.CAS - 3];
648}
649
650static void sdram_timings(struct sysinfo *s)
651{
652 u8 i, j, ch, r, ta1, ta2, ta3, ta4, trp, bank, page, flag;
653 u8 reg8, wl;
654 u16 reg16;
655 u32 reg32, reg2;
Arthur Heymans6bf13012017-06-10 12:03:27 +0200656 static const u8 pagetab[2][2] = {{0xe, 0x12}, {0x10, 0x14}};
Damien Zammit003d15c2015-11-20 17:17:51 +1100657
658 // Only consider DDR2
659 wl = s->selected_timings.CAS - 1;
660 ta1 = ta2 = 6;
661 ta3 = s->selected_timings.CAS;
662 ta4 = 8;
663 s->selected_timings.tRFC = (s->selected_timings.tRFC + 1) & 0xfe;
664 trp = 0;
665 bank = 1;
666 page = 0;
667
668 MCHBAR8(0x240) = ((wl - 3) << 4) | (s->selected_timings.CAS - 3);
669
670 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
671 i = ch << 1;
672 if (s->dimms[i].banks == 1) {
673 trp = 1;
674 bank = 0;
675 }
676 if (s->dimms[i].page_size == 2048) {
677 page = 1;
678 }
679 }
680 PRINTK_DEBUG("trp=%d bank=%d page=%d\n",trp, bank, page);
681
682 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
683 flag = 0;
684 } else {
685 flag = 1;
686 }
687
688 MCHBAR8(0x26f) = MCHBAR8(0x26f) | 0x3;
689 MCHBAR16(0x250) = ((wl + 4 + s->selected_timings.tWR) << 6) |
690 ((2 + MAX(s->selected_timings.tRTP, 2)) << 2) | 1;
691 reg32 = (bank << 21) | (s->selected_timings.tRRD << 17) |
692 (s->selected_timings.tRP << 13) |
693 ((s->selected_timings.tRP + trp) << 9) |
694 s->selected_timings.tRFC;
695 if (bank == 0) {
696 reg32 |= (pagetab[flag][page] << 22);
697 }
698 MCHBAR16(0x252) = (u16) reg32;
699 MCHBAR16(0x254) = (u16) (reg32 >> 16);
700
701 reg16 = (MCHBAR16(0x254) & 0xfc0) >> 6;
702 MCHBAR16(0x62c) = (MCHBAR16(0x62c) & ~0x1f80) | (reg16 << 7);
703
704 reg16 = (s->selected_timings.tRCD << 12) | (4 << 8) | (ta2 << 4) | ta4;
705 MCHBAR16(0x256) = reg16;
706
707 reg32 = (s->selected_timings.tRCD << 17) |
708 ((wl + 4 + s->selected_timings.tWTR) << 12) |
709 (ta3 << 8) | (4 << 4) | ta1;
710 MCHBAR32(0x258) = reg32;
711
712 reg16 = ((s->selected_timings.tRP + trp) << 9) |
713 s->selected_timings.tRFC;
714 MCHBAR8(0x25b) = (u8) reg16;
715 MCHBAR8(0x25c) = (u8) (reg16 >> 8);
716
717 MCHBAR16(0x260) = (MCHBAR16(0x260) & ~0x3fe) | (100 << 1);
718 MCHBAR8(0x25d) = (MCHBAR8(0x25d) & ~0x3f) | s->selected_timings.tRAS;
719 MCHBAR16(0x244) = 0x2310;
720
721 MCHBAR8(0x246) = (MCHBAR8(0x246) & ~0x1f) | 1;
722
723 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
724 reg32 = 3000;
725 } else {
726 reg32 = 2500;
727 }
728 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
729 reg2 = 6000;
730 } else {
731 reg2 = 5000;
732 }
733 reg16 = (u16)((((s->selected_timings.CAS + 7)*(reg32)) / reg2) << 8);
734 MCHBAR16(0x248) = (MCHBAR16(0x248) & ~0x1f00) | reg16;
735
736 flag = 0;
737 if (wl > 2) {
738 flag = 1;
739 }
740 reg16 = (u8) (wl - 1 - flag);
741 reg16 |= reg16 << 4;
742 reg16 |= flag << 8;
743 MCHBAR16(0x24d) = (MCHBAR16(0x24d) & ~0x1ff) | reg16;
744
745 MCHBAR16(0x25e) = 0x1585;
746 MCHBAR8(0x265) = MCHBAR8(0x265) & ~0x1f;
747 MCHBAR16(0x265) = (MCHBAR16(0x265) & ~0x3f00) |
748 ((s->selected_timings.CAS + 9) << 8);
749
750 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
751 reg16 = 0x514;
752 reg32 = 0xa28;
753 } else {
754 reg16 = 0x618;
755 reg32 = 0xc30;
756 }
757 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~0xfffff00) |
758 (0x3f << 22) | (reg32 << 8);
759 MCHBAR8(0x26c) = 0x00;
760 MCHBAR16(0x2b8) = (MCHBAR16(0x2b8) & 0xc000) | reg16;
761 MCHBAR8(0x274) = MCHBAR8(0x274) | 1;
762
763 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0x7f000000) | (0xb << 25);
764 i = s->selected_timings.mem_clock;
765 j = s->selected_timings.fsb_clock;
766 if (i > j) {
767 MCHBAR32(0x248) = MCHBAR32(0x248) | (1 << 24);
768 }
769
770 MCHBAR8(0x24c) = MCHBAR8(0x24c) & ~0x3;
771 MCHBAR16(0x24d) = (MCHBAR16(0x24d) & ~0x7c00) | ((wl + 10) << 10);
772 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x70e0000) | (3 << 24) | (3 << 17);
773 reg16 = 0x15 << 6;
774 reg16 |= 0x1f;
775 reg16 |= (0x6 << 12);
776 MCHBAR16(0x26d) = (MCHBAR16(0x26d) & ~0x7fff) | reg16;
777
778 reg32 = (0x6 << 27) | (1 << 25);
779 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~0x30000000) | ((u32)(reg32 << 8));
780 MCHBAR8(0x26c) = (MCHBAR8(0x26c) & ~0xfa) | ((u8)(reg32 >> 24));
781 MCHBAR8(0x271) = MCHBAR8(0x271) & ~(1 << 7);
782 MCHBAR8(0x274) = MCHBAR8(0x274) & ~0x6;
Stefan Reinauer66fbeae2016-05-06 13:48:39 -0700783 reg32 = (u32) (((6 & 0x03) << 30) | (4 << 25) | (1 << 20) | (8 << 15) |
Damien Zammit003d15c2015-11-20 17:17:51 +1100784 (6 << 10) | (4 << 5) | 1);
785 MCHBAR32(0x278) = reg32;
786
787 MCHBAR16(0x27c) = (MCHBAR16(0x27c) & ~0x1ff) | (8 << 3) | (6 >> 2);
788 MCHBAR16(0x125) = MCHBAR16(0x125) | 0x1c00 | (0x1f << 5);
789 MCHBAR8(0x127) = (MCHBAR8(0x127) & ~0xff) | 0x40;
790 MCHBAR8(0x128) = (MCHBAR8(0x128) & ~0x7) | 0x5;
791 MCHBAR8(0x129) = MCHBAR8(0x129) | 0x1f;
792 reg8 = 3 << 6;
793 reg8 |= (s->dt0mode << 4);
794 reg8 |= 0x0c;
795 MCHBAR8(0x12f) = (MCHBAR8(0x12f) & ~0xdf) | reg8;
796 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0x2;
797 MCHBAR8(0x228) = (MCHBAR8(0x228) & ~0x7) | 0x2;
798 MCHBAR16(0x241) = (MCHBAR16(0x241) & ~0x3fc) | (4 << 2);
799 reg32 = (2 << 29) | (1 << 28) | (1 << 23);
800 MCHBAR32(0x120) = (MCHBAR32(0x120) & ~0xffb00000) | reg32;
801
802 reg8 = (u8) ((MCHBAR16(0x252) & 0xe000) >> 13);
803 reg8 |= (u8) ((MCHBAR16(0x254) & 1) << 3);
804 MCHBAR8(0x12d) = (MCHBAR8(0x12d) & ~0xf0) | (reg8 << 4);
805 reg8 = (u8) ((MCHBAR32(0x258) & 0xf0000) >> 17);
806 MCHBAR8(0x12d) = (MCHBAR8(0x12d) & ~0xf) | reg8;
807 MCHBAR8(0x12e) = MCHBAR8(0x12e) & ~0xfc;
808 MCHBAR8(0x12e) = MCHBAR8(0x12e) & ~0x3;
809 MCHBAR8(0x12f) = MCHBAR8(0x12f) & ~0x3;
810 MCHBAR8(0x241) = MCHBAR8(0x241) | 1;
811 MCHBAR16(0x1b6) = MCHBAR16(0x1b6) | (1 << 9);
812 for (i = 0; i < 8; i++) {
813 MCHBAR32(0x540 + i*4) = (MCHBAR32(0x540 + i*4) & ~0x3f3f3f3f) |
814 0x0c0c0c0c;
815 }
816 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) |
817 ((s->selected_timings.CAS + 1) << 16);
818 for (i = 0; i < 8; i++) {
819 MCHBAR8(0x560 + i*4) = MCHBAR8(0x560 + i*4) & ~0x3f;
820 MCHBAR16(0x58c) = MCHBAR16(0x58c) & ((u16) (~(3 << (i*2))));
821 MCHBAR16(0x588) = MCHBAR16(0x588) & ((u16) (~(3 << (i*2))));
822 MCHBAR16(0x5fa) = MCHBAR16(0x5fa) & ((u16) (~(3 << (i*2))));
823 }
824 MCHBAR8(0x5f0) = MCHBAR8(0x5f0) & ~0x1;
825 MCHBAR8(0x5f0) = MCHBAR8(0x5f0) | 0x2;
826 MCHBAR8(0x5f0) = MCHBAR8(0x5f0) | 0x4;
827 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) | 0xc0400;
828 MCHBAR32(0x594) = MCHBAR32(0x594) | (1 << 31);
829}
830
Arthur Heymans6bf13012017-06-10 12:03:27 +0200831static void sdram_p_clkset0(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100832{
833 MCHBAR16(0x5a0) = (MCHBAR16(0x5a0) & ~0xc440) |
834 (pll->clkdelay[f][i] << 14) |
835 (pll->dben[f][i] << 10) |
836 (pll->dbsel[f][i] << 6);
837 MCHBAR8(0x581) = (MCHBAR8(0x581) & ~0x3f) | pll->pi[f][i];
838}
839
Arthur Heymans6bf13012017-06-10 12:03:27 +0200840static void sdram_p_clkset1(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100841{
842 MCHBAR16(0x5a0) = (MCHBAR16(0x5a0) & ~0x30880) |
843 (pll->clkdelay[f][i] << 16) |
844 (pll->dben[f][i] << 11) |
845 (pll->dbsel[f][i] << 7);
846 MCHBAR8(0x582) = (MCHBAR8(0x582) & ~0x3f) | pll->pi[f][i];
847}
848
Arthur Heymans6bf13012017-06-10 12:03:27 +0200849static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100850{
851 u8 reg8;
852 reg8 = pll->dbsel[f][i] << 5;
853 reg8 |= pll->dben[f][i] << 6;
854 MCHBAR8(0x594) = (MCHBAR8(0x594) & ~0x60) | reg8;
855
856 reg8 = pll->clkdelay[f][i] << 4;
857 MCHBAR8(0x598) = (MCHBAR8(0x598) & ~0x30) | reg8;
858
859 reg8 = pll->pi[f][i];
860 MCHBAR8(0x580) = (MCHBAR8(0x580) & ~0x3f) | reg8;
861 MCHBAR8(0x583) = (MCHBAR8(0x583) & ~0x3f) | reg8;
862}
863
Arthur Heymans6bf13012017-06-10 12:03:27 +0200864static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100865{
866 u8 reg8;
867 u32 reg32;
868 reg32 = ((u32) pll->dbsel[f][i]) << 20;
869 reg32 |= ((u32) pll->dben[f][i]) << 21;
870 reg32 |= ((u32) pll->dbsel[f][i]) << 22;
871 reg32 |= ((u32) pll->dben[f][i]) << 23;
872 reg32 |= ((u32) pll->clkdelay[f][i]) << 24;
873 reg32 |= ((u32) pll->clkdelay[f][i]) << 27;
874 MCHBAR32(0x59c) = (MCHBAR32(0x59c) & ~0x1bf0000) | reg32;
875
876 reg8 = pll->pi[f][i];
877 MCHBAR8(0x584) = (MCHBAR8(0x584) & ~0x3f) | reg8;
878 MCHBAR8(0x585) = (MCHBAR8(0x585) & ~0x3f) | reg8;
879
880 reg32 = ((u32) pll->dbsel[f][i]) << 12;
881 reg32 |= ((u32) pll->dben[f][i]) << 13;
882 reg32 |= ((u32) pll->dbsel[f][i]) << 8;
883 reg32 |= ((u32) pll->dben[f][i]) << 9;
884 reg32 |= ((u32) pll->clkdelay[f][i]) << 14;
885 reg32 |= ((u32) pll->clkdelay[f][i]) << 10;
886 MCHBAR32(0x598) = (MCHBAR32(0x598) & ~0xff00) | reg32;
887
888 reg8 = pll->pi[f][i];
889 MCHBAR8(0x586) = (MCHBAR8(0x586) & ~0x3f) | reg8;
890 MCHBAR8(0x587) = (MCHBAR8(0x587) & ~0x3f) | reg8;
891}
892
893static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
894{
895 u8 rank, dqs, reg8, j;
896 u32 reg32;
897
898 j = clk - 40;
899 reg8 = 0;
900 reg32 = 0;
901 rank = j % 4;
902 dqs = j / 4;
903
904 reg32 |= ((u32) pll->dben[f][clk]) << (dqs + 9);
905 reg32 |= ((u32) pll->dbsel[f][clk]) << dqs;
906 MCHBAR32(0x5b4+rank*4) = (MCHBAR32(0x5b4+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200907 ~((1 << (dqs+9))|(1 << dqs))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100908
909 reg32 = ((u32) pll->clkdelay[f][clk]) << ((dqs*2) + 16);
910 MCHBAR32(0x5c8+rank*4) = (MCHBAR32(0x5c8+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200911 ~((1 << (dqs*2 + 17))|(1 << (dqs*2 + 16)))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100912
913 reg8 = pll->pi[f][clk];
914 MCHBAR8(0x520+j) = (MCHBAR8(0x520+j) & ~0x3f) | reg8;
915}
916
917
918static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
919{
920 u8 rank, dq, reg8, j;
921 u32 reg32;
922
923 j = clk - 8;
924 reg8 = 0;
925 reg32 = 0;
926 rank = j % 4;
927 dq = j / 4;
928
929 reg32 |= ((u32) pll->dben[f][clk]) << (dq + 9);
930 reg32 |= ((u32) pll->dbsel[f][clk]) << dq;
931 MCHBAR32(0x5a4+rank*4) = (MCHBAR32(0x5a4+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200932 ~((1 << (dq+9))|(1 << dq))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100933
934 reg32 = ((u32) pll->clkdelay[f][clk]) << (dq*2);
935 MCHBAR32(0x5c8+rank*4) = (MCHBAR32(0x5c8+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200936 ~((1 << (dq*2 + 1))|(1 << (dq*2)))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100937
938 reg8 = pll->pi[f][clk];
939 MCHBAR8(0x500+j) = (MCHBAR8(0x500+j) & ~0x3f) | reg8;
940}
941
942static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
943{
944 struct pllparam pll = {
945 .pi = {
946 { // 667
947 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
948 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
949 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
950 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
951 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
952 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3
953 },
954 { // 800
955 53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
956 34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
957 47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
958 47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
959 2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
960 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15
961 }},
962
963 .dben = {
964 { // 667
965 0,0,1,1,1,1,1,1,1,1,1,1,
966 1,1,1,1,0,0,0,0,0,0,0,0,
967 0,0,0,0,0,0,0,0,0,0,0,0,
968 1,1,1,1,0,0,0,0,0,0,0,0,
969 0,0,0,0,0,0,0,0,0,0,0,0,
970 0,0,0,0,0,0,0,0,0,0,0,0
971 },
972 { // 800
973 1,1,1,1,1,1,1,1,0,0,0,0,
974 0,0,0,0,0,0,0,0,0,0,0,0,
975 0,0,0,0,0,0,0,0,0,0,0,0,
976 0,0,0,0,1,1,1,1,1,1,1,1,
977 1,1,1,1,1,1,1,1,0,0,0,0,
978 1,1,1,1,0,0,0,0,0,0,0,0
979 }},
980
981 .dbsel = {
982 { // 667
983 0,0,1,1,1,1,1,1,1,1,1,1,
984 1,1,1,1,0,0,0,0,0,0,0,0,
985 0,0,0,0,0,0,0,0,0,0,0,0,
986 1,1,1,1,0,0,0,0,0,0,0,0,
987 0,0,0,0,0,0,0,0,0,0,0,0,
988 0,0,0,0,0,0,0,0,0,0,0,0
989 },
990 { // 800
991 0,0,1,1,1,1,1,1,0,0,0,0,
992 0,0,0,0,0,0,0,0,0,0,0,0,
993 0,0,0,0,0,0,0,0,0,0,0,0,
994 0,0,0,0,0,0,0,0,1,1,1,1,
995 1,1,1,1,1,1,1,1,0,0,0,0,
996 1,1,1,1,0,0,0,0,0,0,0,0
997 }},
998
999 .clkdelay = {
1000 { // 667
1001 0,0,1,1,0,0,0,0,1,1,1,1,
1002 1,1,1,1,1,1,1,1,1,1,1,1,
1003 1,1,1,1,1,1,1,1,1,1,1,1,
1004 1,1,1,1,0,0,0,0,0,0,0,0,
1005 0,0,0,0,0,0,0,0,0,0,0,0,
1006 0,0,0,0,0,0,0,0,0,0,0,0
1007 },
1008 { // 800
1009 0,0,0,0,0,0,0,0,1,1,1,1,
1010 1,1,1,1,1,1,1,1,1,1,1,1,
1011 1,1,1,1,1,1,1,1,1,1,1,1,
1012 1,1,1,1,0,0,0,0,1,1,1,1,
1013 1,1,1,1,1,1,1,1,1,1,1,1,
1014 1,1,1,1,1,1,1,1,1,1,1,1
1015 }}
1016 };
1017
1018 u8 i, f;
1019 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1020 f = 0;
1021 } else {
1022 f = 1;
1023 }
1024 for (i = 0; i < 72; i++) {
1025 pll.pi[f][i] += pidelay;
1026 }
1027
1028 MCHBAR8(0x1a4) = MCHBAR8(0x1a4) & ~(1 << 7);
1029 MCHBAR16(0x190) = (MCHBAR16(0x190) & (u16) ~(0x3fff)) | 0x1fff;
1030
1031 sdram_p_clkset0(&pll, f, 0);
1032 sdram_p_clkset1(&pll, f, 1);
1033 sdram_p_cmd(&pll, f, 2);
1034 sdram_p_ctrl(&pll, f, 4);
1035 for (i = 0; i < 32; i++) {
1036 sdram_p_dqs(&pll, f, i+40);
1037 }
1038 for (i = 0; i < 32; i++) {
1039 sdram_p_dq(&pll, f, i+8);
1040 }
1041}
1042
1043static void sdram_calibratehwpll(struct sysinfo *s)
1044{
1045 u8 reg8;
1046
1047 s->async = 0;
1048 reg8 = 0;
1049 MCHBAR16(0x180) = MCHBAR16(0x180) | (1 << 15);
1050 MCHBAR8(0x180) = MCHBAR8(0x180) & ~(1 << 7);
1051 MCHBAR8(0x180) = MCHBAR8(0x180) | (1 << 3);
1052 MCHBAR8(0x180) = MCHBAR8(0x180) | (1 << 2);
1053
1054 MCHBAR8(0x180) = MCHBAR8(0x180) | (1 << 7);
1055 while ((MCHBAR8(0x180) & (1 << 2)) == 0);
1056
1057 reg8 = (MCHBAR8(0x180) & (1 << 3)) >> 3;
1058 if (reg8 != 0) {
1059 s->async = 1;
1060 }
1061}
1062
1063static void sdram_dlltiming(struct sysinfo *s)
1064{
Elyes HAOUAS66b462d2019-01-02 21:11:32 +01001065 u8 reg8, i;
Damien Zammit003d15c2015-11-20 17:17:51 +11001066 u16 reg16;
1067 u32 reg32;
1068
1069 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1070 reg32 = 0x8014227;
1071 } else {
1072 reg32 = 0x14221;
1073 }
1074 MCHBAR32(0x19c) = (MCHBAR32(0x19c) & ~0xfffffff) | reg32;
1075 MCHBAR32(0x19c) = MCHBAR32(0x19c) | (1 << 23);
1076 MCHBAR32(0x19c) = MCHBAR32(0x19c) | (1 << 15);
1077 MCHBAR32(0x19c) = MCHBAR32(0x19c) & ~(1 << 15);
1078
1079 if (s->nodll) {
1080 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 0);
1081 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 2);
1082 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 4);
1083 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 8);
1084 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 10);
1085 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 12);
1086 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 14);
1087 } else {
1088 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 0);
1089 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 2);
1090 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 4);
1091 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 8);
1092 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 10);
1093 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 12);
1094 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 14);
1095 }
1096
1097 if (s->nodll) {
1098 MCHBAR8(0x1c8) = (MCHBAR8(0x1c8) & ~0x3f) | 0x7;
1099 } else {
1100 MCHBAR8(0x1c8) = (MCHBAR8(0x1c8) & ~0x3f);
1101 }
1102
1103 sdram_calibratepll(s, 0); // XXX check
1104
1105 MCHBAR16(0x5f0) = MCHBAR16(0x5f0) | (1 << 11);
1106 MCHBAR16(0x5f0) = MCHBAR16(0x5f0) | (1 << 12);
1107
1108 for (i = 0; i < 8; i++) {
1109 MCHBAR16(0x5f0) = MCHBAR16(0x5f0) | ((1 << 10) >> i);
1110 }
1111 MCHBAR8(0x2c14) = MCHBAR8(0x2c14) | 1;
1112 MCHBAR16(0x182) = 0x5005;
1113 MCHBAR16(0x18a) = (MCHBAR16(0x18a) & ~0x1f1f) | 0x51a;
1114 MCHBAR16(0x2c00) = (MCHBAR16(0x2c00) & ~0xbf3f) | 0x9010;
1115
1116 if (s->nodll) {
1117 MCHBAR8(0x18e) = (MCHBAR8(0x18e) & ~0x7f) | 0x6b;
1118 } else {
1119 MCHBAR8(0x18e) = (MCHBAR8(0x18e) & ~0x7f) | 0x55;
1120 sdram_calibratehwpll(s);
1121 }
Damien Zammit003d15c2015-11-20 17:17:51 +11001122
1123 MCHBAR32(0x248) = MCHBAR32(0x248) & ~(1 << 22);
1124 MCHBAR8(0x5d9) = MCHBAR8(0x5d9) & ~0x2;
1125 MCHBAR8(0x189) = MCHBAR8(0x189) | 0xc0;
1126 MCHBAR8(0x189) = MCHBAR8(0x189) & ~(1 << 5);
1127 MCHBAR8(0x189) = (MCHBAR8(0x189) & ~0xc0) | (1 << 6);
1128 MCHBAR8(0x188) = (MCHBAR8(0x188) & ~0x3f) | 0x1a;
1129 MCHBAR8(0x188) = MCHBAR8(0x188) | 1;
1130
1131 MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 1;
1132 MCHBAR32(0x1a0) = 0x551803;
1133 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0)) {
1134 reg8 = 0x3c;
1135 } else if (ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1136 reg8 = 0x27;
1137 } else if (BOTH_DIMMS_ARE_POPULATED(s->dimms, 0)) {
1138 reg8 = 0x24;
1139 } else {
1140 // None
1141 reg8 = 0x3f;
1142 }
1143 reg8 = 0x00; //switch all clocks on anyway
1144
1145 MCHBAR32(0x5a0) = (MCHBAR32(0x5a0) & ~0x3f000000) | (reg8 << 24);
1146 MCHBAR8(0x594) = MCHBAR8(0x594) & ~1;
1147 reg16 = 0;
1148 if (!rank_is_populated(s->dimms, 0, 0)) {
1149 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
1150 }
1151 if (!rank_is_populated(s->dimms, 0, 1)) {
1152 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
1153 }
1154 if (!rank_is_populated(s->dimms, 0, 2)) {
1155 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1156 }
1157 if (!rank_is_populated(s->dimms, 0, 3)) {
1158 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1159 }
1160 MCHBAR16(0x59c) = MCHBAR16(0x59c) | reg16;
1161}
1162
1163static void sdram_rcomp(struct sysinfo *s)
1164{
1165 u8 i, j, reg8, f, rcompp, rcompn, srup, srun;
1166 u16 reg16;
1167 u32 reg32, rcomp1, rcomp2;
1168
Arthur Heymans6bf13012017-06-10 12:03:27 +02001169 static const u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0 };
1170 static const u8 rcompslew = 0xa;
1171 static const u8 rcompstr[7] = { 0x66, 0, 0xaa, 0x55, 0x55, 0x77, 0x77 };
1172 static const u16 rcompscomp[7] = { 0xa22a, 0, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a };
1173 static const u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1 };
1174 static const u16 rcompctl[7] = { 0x31c, 0, 0x374, 0x3a2, 0x3d0, 0x3fe, 0x42c };
1175 static const u16 rcompf[7] = { 0x1114, 0, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a };
Damien Zammit003d15c2015-11-20 17:17:51 +11001176
1177 // NC-NC x16SS x16DS x16SS2 x16DS2 x8DS, x8DS2
Arthur Heymans6bf13012017-06-10 12:03:27 +02001178 static const u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa,
1179 0xaa , 0x55, 0xaa};
1180 static const u16 rcompscomp2[7] = { 0x0000, 0xe22e, 0xe22e, 0xe22e,
1181 0x8228 , 0xe22e, 0x8228 };
1182 static const u8 rcompdelay2[7] = { 0, 0, 0, 0, 2 , 0, 2};
Damien Zammit003d15c2015-11-20 17:17:51 +11001183
Arthur Heymans6bf13012017-06-10 12:03:27 +02001184 static const u8 rcomplut[64][12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001185 { 9, 9,11,11, 2, 2, 5,5, 6, 6,5, 5},
1186 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1187 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1188 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1189 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1190 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1191 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1192 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1193 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1194 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1195 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1196 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1197 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1198 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1199 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1200 { 10,9,12, 11, 2, 2, 5,5, 6, 6,5, 5},
1201 { 10,9,12, 11, 2, 2, 6,5, 7, 6,6, 5},
1202 { 10,10,12, 12, 2, 2, 6,5, 7, 6,6, 5},
1203 { 10,10,12, 12, 2, 2, 6,6, 7, 7,6, 6},
1204 { 10,10,12, 12, 3, 2, 6,6, 7, 7,6, 6},
1205 { 10,10,12, 12, 3, 2, 6,6, 7, 7,6, 6},
1206 { 10,10,12, 12, 3, 2, 6,6, 7, 7,6, 6},
1207 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1208 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1209 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1210 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1211 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1212 { 11,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1213 { 11,10,14, 13, 3, 3, 6,6, 7, 7,6, 6},
1214 { 12,10,14, 13, 3, 3, 6,6, 7, 7,6, 6},
1215 { 12,12,14, 13, 3, 3, 7,6, 7, 7,7, 6},
1216 { 13,12,16, 15, 3, 3, 7,6, 8, 7,7, 6},
1217 { 13,14,16, 15, 4, 3, 7,7, 8, 8,7, 7},
1218 { 14,14,16, 17, 4, 3, 7,7, 8, 8,7, 7},
1219 { 14,16,18, 17, 4, 4, 8,7, 8, 8,8, 7},
1220 { 15,16,18, 19, 4, 4, 8,7, 9, 8,8, 7},
1221 { 15,18,18, 19, 4, 4, 8,8, 9, 9,8, 8},
1222 { 16,18,20, 21, 4, 4, 8,8, 9, 9,8, 8},
1223 { 16,19,20, 21, 5, 4, 9,8, 10, 9,9, 8},
1224 { 16,19,20, 23, 5, 5, 9,9, 10, 10,9, 9},
1225 { 17,19,22, 23, 5, 5, 9,9, 10, 10,9, 9},
1226 { 17,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1227 { 17,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1228 { 18,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1229 { 18,21,24, 25, 5, 5, 9,9, 11, 10,9, 9},
1230 { 19,21,24, 27, 5, 5, 9, 9, 11, 11,9, 9},
1231 { 19,22,24, 27, 5, 5, 10,9, 11, 11,10, 9},
1232 { 20,22,24, 27, 6, 5, 10,10, 11, 11,10, 10},
1233 { 20,23,26, 27, 6, 6, 10,10, 12, 12,10, 10},
1234 { 20,23,26, 29, 6, 6, 10,10, 12, 12,10, 10},
1235 { 21,24,26, 29, 6, 6, 10,10, 12, 12,10, 10},
1236 { 21,24,26, 29, 6, 6, 11,10, 12, 13,11, 10},
1237 { 22,25,28, 29, 6, 6, 11,11, 13, 13,11, 11},
1238 { 22,25,28, 31, 6, 6, 11,11, 13, 13,11, 11},
1239 { 22,26,28, 31, 6, 6, 11,11, 13, 14,11, 11},
1240 { 23,26,30, 31, 7, 6, 12,11, 14, 14,12, 11},
1241 { 23,27,30, 33, 7, 7, 12,12, 14, 14,12, 12},
1242 { 23,27,30, 33, 7, 7, 12,12, 14, 15,12, 12},
1243 { 24,28,32, 33, 7, 7, 12,12, 15, 15,12, 12},
1244 { 24,28,32, 33, 7, 7, 12,12, 15, 16,12, 12},
1245 { 24,29,32, 35, 7, 7, 12,12, 15, 16,12, 12},
1246 { 25,29,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1247 { 25,30,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1248 { 25,30,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1249 };
1250
1251 srup = 0;
1252 srun = 0;
1253
1254 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1255 f = 0;
1256 rcomp1 = 0x00050431;
1257 } else {
1258 f = 1;
1259 rcomp1 = 0x00050542;
1260 }
1261 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
1262 rcomp2 = 0x14C42827;
1263 } else {
1264 rcomp2 = 0x19042827;
1265 }
1266
1267 for (i = 0; i < 7; i++) {
1268 if (i == 1)
1269 continue;
1270 reg8 = rcompupdate[i];
1271 MCHBAR8(rcompctl[i]) = (MCHBAR8(rcompctl[i]) & ~0x1) | reg8;
1272 MCHBAR8(rcompctl[i]) = MCHBAR8(rcompctl[i]) & ~0x2;
1273 reg16 = (u16) rcompslew;
1274 MCHBAR16(rcompctl[i]) = (MCHBAR16(rcompctl[i]) & ~0xf000) |
1275 (reg16 << 12);
1276 MCHBAR8(rcompctl[i]+4) = rcompstr[i];
1277 MCHBAR16(rcompctl[i]+0xe) = rcompscomp[i];
1278 MCHBAR8(rcompctl[i]+0x14) = (MCHBAR8(rcompctl[i]+0x14) & ~0x3) |
1279 rcompdelay[i];
1280 if (i == 2) {
1281 reg16 = (u16) rcompslew;
1282 MCHBAR16(rcompctl[i]) = (MCHBAR16(rcompctl[i]) &
1283 ~0xf000) | (reg16 << 12);
1284 MCHBAR8(rcompctl[i]+4) = rcompstr2[s->dimm_config[0]];
1285 MCHBAR16(rcompctl[i]+0xe) = rcompscomp2[s->dimm_config[0]];
1286 MCHBAR8(rcompctl[i]+0x14) = (MCHBAR8(rcompctl[i]+0x14) &
1287 ~0x3) | rcompdelay2[s->dimm_config[0]];
1288 }
1289
1290 MCHBAR16(rcompctl[i]+0x16) = MCHBAR16(rcompctl[i]+0x16) & ~0x7f7f;
1291 MCHBAR16(rcompctl[i]+0x18) = MCHBAR16(rcompctl[i]+0x18) & ~0x3f3f;
1292 MCHBAR16(rcompctl[i]+0x1a) = MCHBAR16(rcompctl[i]+0x1a) & ~0x3f3f;
1293 MCHBAR16(rcompctl[i]+0x1c) = MCHBAR16(rcompctl[i]+0x1c) & ~0x3f3f;
1294 MCHBAR16(rcompctl[i]+0x1e) = MCHBAR16(rcompctl[i]+0x1e) & ~0x3f3f;
1295 }
1296
1297 MCHBAR8(0x45a) = (MCHBAR8(0x45a) & ~0x3f) | 0x36;
1298 MCHBAR8(0x462) = (MCHBAR8(0x462) & ~0x3f) | 0x36;
1299
1300 for (i = 0; i < 7; i++) {
1301 if (i == 1)
1302 continue;
1303 MCHBAR8(rcompctl[i]) = MCHBAR8(rcompctl[i]) & ~0x60;
1304 MCHBAR16(rcompctl[i]+2) = MCHBAR16(rcompctl[i]+2) & ~0x706;
1305 MCHBAR16(rcompctl[i]+0xa) = MCHBAR16(rcompctl[i]+0xa) & ~0x7f7f;
1306 MCHBAR16(rcompctl[i]+0x12) = MCHBAR16(rcompctl[i]+0x12) & ~0x3f3f;
1307 MCHBAR16(rcompctl[i]+0x24) = MCHBAR16(rcompctl[i]+0x24) & ~0x1f1f;
1308 MCHBAR8(rcompctl[i]+0x26) = MCHBAR8(rcompctl[i]+0x26) & ~0x1f;
1309 }
1310
1311 MCHBAR16(0x45a) = MCHBAR16(0x45a) & ~0xffc0;
1312 MCHBAR16(0x45c) = MCHBAR16(0x45c) & ~0xf;
1313 MCHBAR16(0x462) = MCHBAR16(0x462) & ~0xffc0;
1314 MCHBAR16(0x464) = MCHBAR16(0x464) & ~0xf;
1315
1316 for (i = 0; i < 7; i++) {
1317 if (i == 1)
1318 continue;
1319 MCHBAR16(rcompctl[i]+0x10) = rcompf[i];
1320 MCHBAR16(rcompctl[i]+0x20) = 0x1219;
1321 MCHBAR16(rcompctl[i]+0x22) = 0x000C;
1322 }
1323
1324 MCHBAR32(0x164) = (MCHBAR32(0x164) & ~0x1f1f1f) | 0x0c1219;
1325 MCHBAR16(0x4b0) = (MCHBAR16(0x4b0) & ~0x1f00) | 0x1200;
1326 MCHBAR8(0x4b0) = (MCHBAR8(0x4b0) & ~0x1f) | 0x12;
1327 MCHBAR32(0x138) = 0x007C9007;
1328 MCHBAR32(0x16c) = rcomp1;
1329 MCHBAR16(0x17a) = 0x1f7f;
1330 MCHBAR32(0x134) = rcomp2;
1331 MCHBAR16(0x170) = (MCHBAR16(0x170) & ~0xf) | 1;
1332 MCHBAR16(0x178) = 0x134;
1333 MCHBAR32(0x130) = 0x4C293600;
1334 MCHBAR8(0x133) = (MCHBAR8(0x133) & ~0x44) | (1 << 6) | (1 << 2);
1335 MCHBAR16(0x4b0) = MCHBAR16(0x4b0) & ~(1 << 13);
1336 MCHBAR8(0x4b0) = MCHBAR8(0x4b0) & ~(1 << 5);
1337
1338 for (i = 0; i < 7; i++) {
1339 if (i == 1)
1340 continue;
1341 MCHBAR8(rcompctl[i]+2) = MCHBAR8(rcompctl[i]) & ~0x71;
1342 }
1343
1344 if ((MCHBAR32(0x130) & (1 << 30)) == 0) {
1345 MCHBAR8(0x130) = MCHBAR8(0x130) | 0x1;
1346 while ((MCHBAR8(0x130) & 0x1) != 0);
1347
1348 reg32 = MCHBAR32(0x13c);
1349 rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1350 rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1351
1352 for (i = 0; i < 7; i++) {
1353 if (i == 1)
1354 continue;
1355 srup = (MCHBAR8(rcompctl[i]+1) & 0xc0) >> 6;
1356 srun = (MCHBAR8(rcompctl[i]+1) & 0x30) >> 4;
1357 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
1358 MCHBAR16(rcompctl[i]+0x16) = (MCHBAR16(rcompctl[i]+0x16)
1359 & ~0x7f00) | reg16;
1360 reg16 = (u16)(rcompn - (1 << (srun + 1)));
1361 MCHBAR8(rcompctl[i]+0x16) = (MCHBAR8(rcompctl[i]+0x16) &
1362 ~0x7f) | (u8)reg16;
1363 }
1364
1365 reg8 = rcompp - (1 << (srup + 1));
1366 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1367 MCHBAR8(rcompctl[0]+0x18+i) =
1368 (MCHBAR8(rcompctl[0]+0x18+i) & ~0x3f) |
1369 rcomplut[j][0];
1370 }
1371
1372 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1373 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1374 MCHBAR8(rcompctl[2]+0x18+i) =
1375 (MCHBAR8(rcompctl[2]+0x18+i) & ~0x3f) |
1376 rcomplut[j][10];
1377 }
1378 }
1379
1380 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1381 MCHBAR8(rcompctl[3]+0x18+i) =
1382 (MCHBAR8(rcompctl[3]+0x18+i) & ~0x3f) |
1383 rcomplut[j][6];
1384 MCHBAR8(rcompctl[4]+0x18+i) =
1385 (MCHBAR8(rcompctl[4]+0x18+i) & ~0x3f) |
1386 rcomplut[j][6];
1387 }
1388
1389 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1390 MCHBAR8(rcompctl[5]+0x18+i) =
1391 (MCHBAR8(rcompctl[5]+0x18+i) & ~0x3f) |
1392 rcomplut[j][8];
1393 MCHBAR8(rcompctl[6]+0x18+i) =
1394 (MCHBAR8(rcompctl[6]+0x18+i) & ~0x3f) |
1395 rcomplut[j][8];
1396 }
1397
1398 reg8 = rcompn - (1 << (srun + 1));
1399 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1400 MCHBAR8(rcompctl[0]+0x1c+i) =
1401 (MCHBAR8(rcompctl[0]+0x1c+i) & ~0x3f) |
1402 rcomplut[j][1];
1403 }
1404
1405 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1406 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1407 MCHBAR8(rcompctl[2]+0x1c+i) =
1408 (MCHBAR8(rcompctl[2]+0x1c+i) & ~0x3f) |
1409 rcomplut[j][11];
1410 }
1411 }
1412
1413 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1414 MCHBAR8(rcompctl[3]+0x1c+i) =
1415 (MCHBAR8(rcompctl[3]+0x1c+i) & ~0x3f) |
1416 rcomplut[j][7];
1417 MCHBAR8(rcompctl[4]+0x1c+i) =
1418 (MCHBAR8(rcompctl[4]+0x1c+i) & ~0x3f) |
1419 rcomplut[j][7];
1420 }
1421
1422 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1423 MCHBAR8(rcompctl[5]+0x1c+i) =
1424 (MCHBAR8(rcompctl[5]+0x1c+i) & ~0x3f) |
1425 rcomplut[j][9];
1426 MCHBAR8(rcompctl[6]+0x1c+i) =
1427 (MCHBAR8(rcompctl[6]+0x1c+i) & ~0x3f) |
1428 rcomplut[j][9];
1429 }
1430 }
1431 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1432}
1433
1434static void sdram_odt(struct sysinfo *s)
1435{
1436 u8 rankindex = 0;
1437
Arthur Heymans6bf13012017-06-10 12:03:27 +02001438 static const u16 odt294[16] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001439 0x0000, 0x0000, 0x0000, 0x0000,
1440 0x0044, 0x1111, 0x0000, 0x1111,
1441 0x0000, 0x0000, 0x0000, 0x0000,
1442 0x0044, 0x1111, 0x0000, 0x1111
1443 };
Arthur Heymans6bf13012017-06-10 12:03:27 +02001444 static const u16 odt298[16] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001445 0x0000, 0x0011, 0x0000, 0x0011,
1446 0x0000, 0x4444, 0x0000, 0x4444,
1447 0x0000, 0x0000, 0x0000, 0x0000,
1448 0x0000, 0x4444, 0x0000, 0x4444
1449 };
1450
1451 switch (s->dimms[0].ranks) {
1452 case 0:
1453 if (s->dimms[1].ranks == 0) {
1454 rankindex = 0;
1455 } else if (s->dimms[1].ranks == 1) {
1456 rankindex = 4;
1457 } else if (s->dimms[1].ranks == 2) {
1458 rankindex = 12;
1459 }
1460 break;
1461 case 1:
1462 if (s->dimms[1].ranks == 0) {
1463 rankindex = 1;
1464 } else if (s->dimms[1].ranks == 1) {
1465 rankindex = 5;
1466 } else if (s->dimms[1].ranks == 2) {
1467 rankindex = 13;
1468 }
1469 break;
1470 case 2:
1471 if (s->dimms[1].ranks == 0) {
1472 rankindex = 3;
1473 } else if (s->dimms[1].ranks == 1) {
1474 rankindex = 7;
1475 } else if (s->dimms[1].ranks == 2) {
1476 rankindex = 15;
1477 }
1478 break;
1479 }
1480
1481 MCHBAR16(0x298) = odt298[rankindex];
1482 MCHBAR16(0x294) = odt294[rankindex];
1483}
1484
1485static void sdram_mmap(struct sysinfo *s)
1486{
Arthur Heymans6bf13012017-06-10 12:03:27 +02001487 static const u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000,
1488 0xc00001, 0xf00000};
1489 static const u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101,
1490 0x1010000, 0x1010101};
1491 static const u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1492 static const u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006,
1493 0x40002, 0x80006};
Damien Zammit003d15c2015-11-20 17:17:51 +11001494
Arthur Heymans6bf13012017-06-10 12:03:27 +02001495 static const u16 tolud[7] = {0x800, 0x800, 0x1000, 0x1000, 0x2000,
1496 0x1000, 0x2000};
1497 static const u16 tom[7] = {0x2, 0x2, 0x4, 0x4, 0x8, 0x4, 0x8};
1498 static const u16 touud[7] = {0x80, 0x80, 0x100, 0x100, 0x200, 0x100,
1499 0x200};
1500 static const u32 gbsm[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000,
1501 0x20000000, 0x10000000, 0x20000000};
1502 static const u32 bgsm[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000,
1503 0x20000000, 0x10000000, 0x20000000};
1504 static const u32 tsegmb[7] = {0x8000000, 0x8000000, 0x10000000,
1505 0x8000000, 0x20000000, 0x10000000,
1506 0x20000000};
Damien Zammit003d15c2015-11-20 17:17:51 +11001507
1508 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1509 if (s->dimms[0].sides > 1) {
1510 // 2R/NC
1511 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x300001;
1512 MCHBAR32(0x208) = 0x101;
1513 MCHBAR32(0x200) = 0x40002;
1514 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1515 } else {
1516 // 1R/NC
1517 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x100001;
1518 MCHBAR32(0x208) = 0x1;
1519 MCHBAR32(0x200) = 0x20002;
1520 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1521 }
1522 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
1523
1524 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x300001;
1525 MCHBAR32(0x208) = 0x101;
1526 MCHBAR32(0x200) = 0x40002;
1527 MCHBAR32(0x204) = 0x40004;
1528 } else {
1529 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | w260[s->dimm_config[0]];
1530 MCHBAR32(0x208) = w208[s->dimm_config[0]];
1531 MCHBAR32(0x200) = w200[s->dimm_config[0]];
1532 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1533 }
1534 pci_write_config16(PCI_DEV(0, 0, 0), 0xb0, tolud[s->dimm_config[0]]);
1535 pci_write_config16(PCI_DEV(0, 0, 0), 0xa0, tom[s->dimm_config[0]]);
1536 pci_write_config16(PCI_DEV(0, 0, 0), 0xa2, touud[s->dimm_config[0]]);
1537 pci_write_config32(PCI_DEV(0, 0, 0), 0xa4, gbsm[s->dimm_config[0]]);
1538 pci_write_config32(PCI_DEV(0, 0, 0), 0xa8, bgsm[s->dimm_config[0]]);
1539 pci_write_config32(PCI_DEV(0, 0, 0), 0xac, tsegmb[s->dimm_config[0]]);
1540}
1541
1542#if 1
1543static void hpet_udelay(u32 del)
1544{
1545 u32 start, finish, now;
1546
1547 del *= 15; /* now in usec */
1548
1549 start = HPET32(0xf0);
1550 finish = start + del;
1551 while (1) {
1552 now = HPET32(0xf0);
1553 if (finish > start) {
1554 if (now >= finish)
1555 break;
1556 } else {
1557 if ((now < start) && (now >= finish)) {
1558 break;
1559 }
1560 }
1561 }
1562}
1563#endif
1564
1565static u8 sdram_checkrcompoverride(void)
1566{
1567 u32 xcomp;
1568 u8 aa, bb, a, b, c, d;
1569
1570 xcomp = MCHBAR32(0x13c);
1571 a = (u8)((xcomp & 0x7f000000) >> 24);
1572 b = (u8)((xcomp & 0x7f0000) >> 16);
1573 c = (u8)((xcomp & 0x3f00) >> 8);
1574 d = (u8)(xcomp & 0x3f);
1575
1576 if (a > b) {
1577 aa = a - b;
1578 } else {
1579 aa = b - a;
1580 }
1581 if (c > d) {
1582 bb = c - d;
1583 } else {
1584 bb = d - c;
1585 }
1586 if ((aa > 18) || (bb > 7) ||
1587 (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
1588 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
1589 MCHBAR32(0x140) = 0x9718a729;
1590 return 1;
1591 }
1592 return 0;
1593}
1594
1595static void sdram_rcompupdate(struct sysinfo *s)
1596{
1597 u8 i, ok;
1598 u32 reg32a, reg32b;
1599
1600 ok = 0;
1601 MCHBAR8(0x170) = MCHBAR8(0x170) & ~(1 << 3);
1602 MCHBAR8(0x130) = MCHBAR8(0x130) & ~(1 << 7);
1603 for (i = 0; i < 3; i++) {
1604 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1605 hpet_udelay(1000);
1606 while ((MCHBAR8(0x130) & 0x1) != 0);
1607 ok |= sdram_checkrcompoverride();
1608 }
1609 if (!ok) {
1610 reg32a = MCHBAR32(0x13c);
1611 reg32b = (reg32a >> 16) & 0x0000ffff;
1612 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1613 reg32a |= (1 << 31) | (1 << 15);
1614 MCHBAR32(0x140) = reg32a;
1615 }
1616 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1617 hpet_udelay(1000);
1618 while ((MCHBAR8(0x130) & 0x1) != 0);
1619}
1620
1621static void __attribute__((noinline))
1622sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1623{
1624 u32 reg32;
1625
1626 reg32 = jval << 3;
1627 reg32 |= rank * 0x8000000;
1628 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | jmode;
1629 read32((void *)reg32);
1630 barrier();
1631 hpet_udelay(1); // 1us
1632}
1633
1634static void sdram_zqcl(struct sysinfo *s)
1635{
1636 if (s->boot_path == BOOT_PATH_RESUME) {
1637 MCHBAR32(0x260) = MCHBAR32(0x260) | (1 << 27);
1638 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0xe) | NORMAL_OP_CMD;
1639 MCHBAR8(0x271) = MCHBAR8(0x271) & ~0x30;
1640 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~((1 << 30) | (1 << 31))) |
1641 (1 << 30) | (1 << 31);
1642 }
1643}
1644
1645static void sdram_jedecinit(struct sysinfo *s)
1646{
1647 u8 r, i, ch;
1648 u16 reg16, mrs, rttnom;
1649 struct jedeclist {
1650 char debug[15];
1651 u8 cmd;
1652 u16 val;
1653 };
1654
Arthur Heymans6bf13012017-06-10 12:03:27 +02001655 static const struct jedeclist jedec[12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001656 { " NOP ", NOP_CMD, 0 },
1657 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1658 { " EMRS2 ", EMRS2_CMD, 0 },
1659 { " EMRS3 ", EMRS3_CMD, 0 },
1660 { " EMRS1 ", EMRS1_CMD, 0 },
1661 { " DLL RESET ", MRS_CMD, (1 << 8) },
1662 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1663 { " AUTOREFRESH", CBR_CMD, 0 },
1664 { " AUTOREFRESH", CBR_CMD, 0 },
1665 { " INITIALISE ", MRS_CMD, 0 },
1666 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1667 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1668 };
1669
1670 mrs = (s->selected_timings.CAS << 4) |
1671 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 1;
1672 rttnom = (1 << 2);
1673 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1674 rttnom |= (1 << 6);
1675 }
1676
1677 hpet_udelay(200); // 200us
1678 reg16 = 0;
1679 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1680 for (i = 0; i < 12; i++) {
1681 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1682 reg16 = jedec[i].val;
1683 switch (jedec[i].cmd) {
1684 case EMRS1_CMD:
1685 reg16 |= rttnom;
1686 break;
1687 case MRS_CMD:
1688 reg16 |= mrs;
1689 break;
1690 default:
1691 break;
1692 }
1693 sdram_jedec(s, r, jedec[i].cmd, reg16);
1694 PRINTK_DEBUG("done\n");
1695 }
1696 }
1697}
1698
1699static void sdram_misc(struct sysinfo *s)
1700{
1701 u32 reg32;
1702
1703 reg32 = 0;
1704 reg32 |= (0x4 << 13);
1705 reg32 |= (0x6 << 8);
1706 MCHBAR32(0x274) = (MCHBAR32(0x274) & ~0x3ff00) | reg32;
1707 MCHBAR8(0x274) = MCHBAR8(0x274) & ~(1 << 7);
1708 MCHBAR8(0x26c) = MCHBAR8(0x26c) | 1;
1709 if (s->boot_path != BOOT_PATH_RESUME) {
1710 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0xe) | NORMAL_OP_CMD;
1711 MCHBAR8(0x271) = MCHBAR8(0x271) & ~0x30;
1712 } else {
1713 sdram_zqcl(s);
1714 }
1715}
1716
1717static void sdram_checkreset(void)
1718{
1719 u8 pmcon2, pmcon3, reset;
1720
1721 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1722 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1723 pmcon3 &= ~0x2;
1724 if (pmcon2 & 0x80) {
1725 pmcon2 &= ~0x80;
1726 reset = 1;
1727 } else {
1728 pmcon2 |= 0x80;
1729 reset = 0;
1730 }
1731 if (pmcon2 & 0x4) {
1732 pmcon2 |= 0x4;
1733 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1734 pmcon3 |= (1 << 3);
1735 }
1736 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1737 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
1738 if (reset) {
1739 printk(BIOS_DEBUG, "Power cycle reset...\n");
1740 outb(0xe, 0xcf9);
1741 }
1742}
1743
1744static void sdram_dradrb(struct sysinfo *s)
1745{
1746 u8 i, reg8, ch, r;
1747 u32 reg32, ind, c0dra, c0drb, dra;
1748 u16 addr;
1749 i = 0;
Arthur Heymans6bf13012017-06-10 12:03:27 +02001750 static const u8 dratab[2][2][2][4] =
Damien Zammit003d15c2015-11-20 17:17:51 +11001751 {{
1752 {
1753 {0xff, 0xff, 0xff, 0xff},
1754 {0xff, 0x00, 0x02, 0xff}
1755 },
1756 {
1757 {0xff, 0x01, 0xff, 0xff},
1758 {0xff, 0x03, 0xff, 0x06}
1759 }
1760 },
1761 {
1762 {
1763 {0xff, 0xff, 0xff, 0xff},
1764 {0xff, 0x04, 0x06, 0x08}
1765 },
1766 {
1767 {0xff, 0xff, 0xff, 0xff},
1768 {0x05, 0x07, 0x09, 0xff}
1769 }
1770 }};
1771
Arthur Heymans6bf13012017-06-10 12:03:27 +02001772 static const u8 dradrb[10][6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001773 //Row Col Bank Width DRB
1774 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1775 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1776 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1777 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1778 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1779 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1780 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1781 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1782 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1783 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1784 };
1785
1786 reg32 = 0;
1787 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1788 i = r / 2;
1789 PRINTK_DEBUG("RANK %d PRESENT\n", r);
1790 dra = dratab[s->dimms[i].banks]
1791 [s->dimms[i].width]
1792 [s->dimms[i].cols - 9]
1793 [s->dimms[i].rows - 12];
1794
1795 if (s->dimms[i].banks == 1) {
1796 dra |= (1 << 7);
1797 }
1798 reg32 |= (dra << (r*8));
1799 }
1800 MCHBAR32(0x208) = reg32;
1801 c0dra = reg32;
1802 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1803
1804 reg32 = 0;
1805 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1806 reg32 |= (1 << r);
1807 }
1808 reg8 = (u8)(reg32 << 4) & 0xf0;
1809 MCHBAR8(0x262) = (MCHBAR8(0x262) & ~0xf0) | reg8;
1810 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) ||
1811 ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1812 MCHBAR8(0x260) = MCHBAR8(0x260) | 1;
1813 }
1814
1815 addr = 0x200;
1816 c0drb = 0;
1817 FOR_EACH_RANK(ch, r) {
1818 if (rank_is_populated(s->dimms, ch, r)) {
1819 ind = (c0dra >> (8*r)) & 0x7f;
1820 c0drb = (u16)(c0drb + dradrb[ind][5]);
1821 s->channel_capacity[0] += dradrb[ind][5] << 6;
1822 }
1823 MCHBAR16(addr) = c0drb;
1824 addr += 2;
1825 }
1826 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1827}
1828
1829static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1830{
1831 volatile u32 strobedata;
1832 u8 dqsmatches = 1;
1833 while (count--) {
1834 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0x2;
1835 hpet_udelay(1);
1836 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
1837 hpet_udelay(1);
1838 barrier();
Elyes HAOUASfd051dc2018-07-08 12:39:34 +02001839 strobedata = read32((void *)strobeaddr);
Damien Zammit003d15c2015-11-20 17:17:51 +11001840 barrier();
1841 hpet_udelay(1);
1842
1843 if (((MCHBAR8(dqshighaddr) & 0x40) >> 6) != highlow) {
1844 dqsmatches = 0;
1845 }
1846 }
1847
1848 return dqsmatches;
1849}
1850
1851static void rcvenclock(u8 *coarse, u8 *medium, u8 bytelane)
1852{
1853 if (*medium < 3) {
1854 (*medium)++;
1855 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << (bytelane*2))))
1856 | (*medium << (bytelane*2));
1857 } else {
1858 *medium = 0;
1859 (*coarse)++;
1860 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (*coarse << 16);
1861 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~0x3 << (bytelane*2)))
1862 | (*medium << (bytelane*2));
1863 }
1864}
1865
1866static void sdram_rcven(struct sysinfo *s)
1867{
1868 u8 curcoarse, savecoarse;
1869 u8 curmedium, savemedium;
1870 u8 pi, savepi;
1871 u8 bytelane;
1872 u8 bytelanecoarse[8] = { 0 };
1873 u8 minbytelanecoarse = 0xff;
1874 u8 bytelaneoffset;
1875 u8 maxbytelane = 8;
Arthur Heymans015339f2018-08-20 11:28:58 +02001876 /* Since dra/drb is already set up we know that at address 0x00000000
1877 we will always find the first available rank */
1878 u32 strobeaddr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001879 u32 dqshighaddr;
1880
1881 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xc;
1882 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
1883
1884 PRINTK_DEBUG("rcven 0\n");
1885 for (bytelane = 0; bytelane < maxbytelane; bytelane++) {
1886 PRINTK_DEBUG("rcven bytelane %d\n", bytelane);
1887//trylaneagain:
1888 dqshighaddr = 0x561 + (bytelane << 2);
1889
1890 curcoarse = s->selected_timings.CAS + 1;
1891 pi = 0;
1892 curmedium = 0;
1893
1894 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (curcoarse << 16);
1895 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << (bytelane*2))))
1896 | (curmedium << (bytelane*2));
1897 MCHBAR8(0x560+bytelane*4) = MCHBAR8(0x560+bytelane*4) & ~0x3f;
1898
1899 savecoarse = curcoarse;
1900 savemedium = curmedium;
1901 savepi = pi;
1902
1903 PRINTK_DEBUG("rcven 0.1\n");
1904
1905 //MCHBAR16(0x588) = (MCHBAR16(0x588) & (u16)~(0x3 << (bytelane*2))) | (1 << (bytelane*2)); // XXX comment out
1906
1907 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1908 //printk(BIOS_DEBUG, "coarse=%d medium=%d\n", curcoarse, curmedium);
1909 rcvenclock(&curcoarse, &curmedium, bytelane);
1910 if (curcoarse > 0xf) {
1911 PRINTK_DEBUG("Error: coarse > 0xf\n");
1912 //goto trylaneagain;
1913 break;
1914 }
1915 }
1916 PRINTK_DEBUG("rcven 0.2\n");
1917
1918 savecoarse = curcoarse;
1919 savemedium = curmedium;
1920 rcvenclock(&curcoarse, &curmedium, bytelane);
1921
1922 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1923 savecoarse = curcoarse;
1924 savemedium = curmedium;
1925 rcvenclock(&curcoarse, &curmedium, bytelane);
1926 if (curcoarse > 0xf) {
1927 PRINTK_DEBUG("Error: coarse > 0xf\n");
1928 //goto trylaneagain;
1929 break;
1930 }
1931 }
1932
1933 PRINTK_DEBUG("rcven 0.3\n");
1934 curcoarse = savecoarse;
1935 curmedium = savemedium;
1936 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (curcoarse << 16);
1937 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << bytelane*2)))
1938 | (curmedium << (bytelane*2));
1939
1940 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1941 savepi = pi;
1942 pi++;
1943 if (pi > s->maxpi) {
1944 //if (s->nodll) {
1945 pi = savepi = s->maxpi;
1946 break;
1947 //}
1948 }
1949 MCHBAR8(0x560 + bytelane*4) = (MCHBAR8(0x560 + bytelane*4)
1950 & ~0x3f) | (pi << s->pioffset);
1951 }
1952 PRINTK_DEBUG("rcven 0.4\n");
1953
1954 pi = savepi;
1955 MCHBAR8(0x560 + bytelane*4) = (MCHBAR8(0x560 + bytelane*4) & ~0x3f)
1956 | (pi << s->pioffset);
1957 rcvenclock(&curcoarse, &curmedium, bytelane);
1958 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1959 PRINTK_DEBUG("Error: DQS not high\n");
1960 //goto trylaneagain;
1961 }
1962 PRINTK_DEBUG("rcven 0.5\n");
1963 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1964 curcoarse--;
1965 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000)
1966 | (curcoarse << 16);
1967 if (curcoarse == 0) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +02001968 PRINTK_DEBUG("Error: DQS did not hit 0\n");
Damien Zammit003d15c2015-11-20 17:17:51 +11001969 break;
1970 }
1971 }
1972
1973 PRINTK_DEBUG("rcven 0.6\n");
1974 rcvenclock(&curcoarse, &curmedium, bytelane);
1975 s->pi[bytelane] = pi;
1976 bytelanecoarse[bytelane] = curcoarse;
1977 }
1978
1979 PRINTK_DEBUG("rcven 1\n");
1980
1981 bytelane = maxbytelane;
1982 do {
1983 bytelane--;
1984 if (minbytelanecoarse > bytelanecoarse[bytelane]) {
1985 minbytelanecoarse = bytelanecoarse[bytelane];
1986 }
1987 } while (bytelane != 0);
1988
1989 bytelane = maxbytelane;
1990 do {
1991 bytelane--;
1992 bytelaneoffset = bytelanecoarse[bytelane] - minbytelanecoarse;
1993 MCHBAR16(0x5fa) = (MCHBAR16(0x5fa) & (u16)(~(0x3 << (bytelane*2))))
1994 | (bytelaneoffset << (bytelane*2));
1995 } while (bytelane != 0);
1996
1997 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (minbytelanecoarse << 16);
1998
1999 s->coarsectrl = minbytelanecoarse;
2000 s->coarsedelay = MCHBAR16(0x5fa);
2001 s->mediumphase = MCHBAR16(0x58c);
2002 s->readptrdelay = MCHBAR16(0x588);
2003
2004 PRINTK_DEBUG("rcven 2\n");
2005 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xe;
2006 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
2007 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x4;
2008 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x8;
2009
2010 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2011 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
2012 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2013 PRINTK_DEBUG("rcven 3\n");
2014}
2015
2016static void sdram_mmap_regs(struct sysinfo *s)
2017{
2018 bool reclaim;
2019 u32 tsegsize;
2020 u32 mmiosize;
2021 u32 tom, tolud, touud, reclaimbase, reclaimlimit;
2022 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase;
2023 u16 ggc;
2024 u16 ggc_to_uma[10] = { 0, 1, 4, 8, 16, 32, 48, 64, 128, 256 };
2025 u8 ggc_to_gtt[4] = { 0, 1, 0, 0 };
2026
2027 reclaimbase = 0;
2028 reclaimlimit = 0;
2029 ggc = pci_read_config16(PCI_DEV(0,0,0), GGC);
Damien Zammit51fdb922016-01-18 18:34:52 +11002030 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
Damien Zammit003d15c2015-11-20 17:17:51 +11002031 gfxsize = ggc_to_uma[(ggc & 0xf0) >> 4];
Damien Zammit51fdb922016-01-18 18:34:52 +11002032 gttsize = ggc_to_gtt[(ggc & 0x300) >> 8];
Damien Zammit003d15c2015-11-20 17:17:51 +11002033 tom = s->channel_capacity[0];
2034
Arthur Heymansda44e342019-01-12 01:38:02 +01002035 /* with GTT always being 1M, TSEG 1M is the only setting that can
2036 be covered by SMRR which has alignment requirements. */
2037 tsegsize = 0x1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002038 mmiosize = 0x400; // 1GB
2039
2040 reclaim = false;
2041 tolud = MIN(0x1000 - mmiosize, tom);
2042 if ((tom - tolud) > 0x40) {
Arthur Heymansaaebb412017-08-27 18:46:12 +02002043 reclaim = true;
Damien Zammit003d15c2015-11-20 17:17:51 +11002044 }
2045 if (reclaim) {
2046 tolud = tolud & ~0x3f;
2047 tom = tom & ~0x3f;
2048 reclaimbase = MAX(0x1000, tom);
2049 reclaimlimit = reclaimbase + (MIN(0x1000, tom) - tolud) - 0x40;
2050 }
2051 touud = tom;
2052 if (reclaim) {
2053 touud = reclaimlimit + 0x40;
2054 }
2055
2056 gfxbase = tolud - gfxsize;
2057 gttbase = gfxbase - gttsize;
2058 tsegbase = gttbase - tsegsize;
2059
2060 /* Program the regs */
Damien Zammit51fdb922016-01-18 18:34:52 +11002061 pci_write_config16(PCI_DEV(0,0,0), TOLUD, (u16)(tolud << 4));
2062 pci_write_config16(PCI_DEV(0,0,0), TOM, (u16)(tom >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002063 if (reclaim) {
2064 pci_write_config16(PCI_DEV(0,0,0), 0x98, (u16)(reclaimbase >> 6));
2065 pci_write_config16(PCI_DEV(0,0,0), 0x9a, (u16)(reclaimlimit >> 6));
2066 }
Damien Zammit51fdb922016-01-18 18:34:52 +11002067 pci_write_config16(PCI_DEV(0,0,0), TOUUD, (u16)(touud));
2068 pci_write_config32(PCI_DEV(0,0,0), GBSM, gfxbase << 20);
2069 pci_write_config32(PCI_DEV(0,0,0), BGSM, gttbase << 20);
2070 pci_write_config32(PCI_DEV(0,0,0), TSEG, tsegbase << 20);
2071
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002072 u8 reg8 = pci_read_config8(PCI_DEV(0, 0, 0), ESMRAMC);
2073 reg8 &= ~0x7;
Arthur Heymansda44e342019-01-12 01:38:02 +01002074 reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002075 pci_write_config8(PCI_DEV(0, 0, 0), ESMRAMC, reg8);
2076
Damien Zammit51fdb922016-01-18 18:34:52 +11002077 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
2078 pci_read_config32(PCI_DEV(0,0,0), GBSM), gfxbase << 20);
2079 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
2080 pci_read_config32(PCI_DEV(0,0,0), BGSM), gttbase << 20);
2081 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
2082 pci_read_config32(PCI_DEV(0,0,0), TSEG), tsegbase << 20);
Damien Zammit003d15c2015-11-20 17:17:51 +11002083}
2084
2085static void sdram_enhancedmode(struct sysinfo *s)
2086{
2087 u8 reg8, ch, r, j, i;
2088 u32 mask32, reg32;
2089 MCHBAR8(0x246) = MCHBAR8(0x246) | 1;
2090 MCHBAR8(0x269 + 3) = MCHBAR8(0x269 + 3) | 1;
2091 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
2092 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2093 MCHBAR32(0x120) = (MCHBAR32(0x120) & ~mask32) | reg32;
2094 MCHBAR8(0x288 + 1) = 0x2;
2095 MCHBAR16(0x288 + 2) = 0x0804;
2096 MCHBAR16(0x288 + 4) = 0x2010;
2097 MCHBAR8(0x288 + 6) = 0x40;
2098 MCHBAR16(0x288 + 8) = 0x091c;
2099 MCHBAR8(0x288 + 10) = 0xf2;
2100 MCHBAR8(0x241) = MCHBAR8(0x241) | 1;
2101 MCHBAR8(0x243) = MCHBAR8(0x243) | 1;
2102 MCHBAR16(0x272) = MCHBAR16(0x272) | 0x100;
2103
2104 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf0);
2105 pci_write_config8(PCI_DEV(0,0,0), 0xf0, reg8 | 1);
2106 MCHBAR32(0xfa0) = 0x00000002;
2107 MCHBAR32(0xfa4) = 0x20310002;
2108 MCHBAR32(0x24) = 0x02020302;
2109 MCHBAR32(0x30) = 0x001f1806;
2110 MCHBAR32(0x34) = 0x01102800;
2111 MCHBAR32(0x38) = 0x07000000;
2112 MCHBAR32(0x3c) = 0x01014010;
2113 MCHBAR32(0x40) = 0x0f038000;
2114 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf0);
2115 pci_write_config8(PCI_DEV(0,0,0), 0xf0, reg8 & ~1);
2116
2117 u32 nranks, curranksize, maxranksize, maxdra, dra;
2118 u8 rankmismatch, dramismatch;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002119 static const u8 drbtab[10] = { 0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8,
2120 0x20, 0x10 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002121
2122 nranks = 0;
2123 curranksize = 0;
2124 maxranksize = 0;
2125 maxdra = 0;
2126 rankmismatch = 0;
2127 dramismatch = 0;
2128 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2129 nranks++;
2130 dra = (u8) ((MCHBAR32(0x208) >> (8*r)) & 0x7f);
2131 curranksize = drbtab[dra];
2132 if (maxranksize == 0) {
2133 maxranksize = curranksize;
2134 maxdra = dra;
2135 }
2136 if (curranksize != maxranksize) {
2137 rankmismatch = 1;
2138 }
2139 if (dra != maxdra) {
2140 dramismatch = 1;
2141 }
2142 }
2143
2144 reg8 = 0;
2145 switch (nranks) {
2146 case 4:
2147 if (rankmismatch) {
2148 reg8 = 0x64;
2149 } else {
2150 reg8 = 0xa4;
2151 }
2152 break;
2153 case 1:
2154 case 3:
2155 reg8 = 0x64;
2156 break;
2157 case 2:
2158 if (rankmismatch) {
2159 reg8 = 0x64;
2160 } else {
2161 reg8 = 0x24;
2162 }
2163 break;
2164 default:
2165 die("Invalid number of ranks found, halt\n");
2166 break;
2167 }
2168 MCHBAR8(0x111) = (MCHBAR8(0x111) & ~0xfc) | (reg8 & 0xfc);
2169 MCHBAR32(0xd0) = MCHBAR32(0xd0) & ~0x80000000;
2170
2171 MCHBAR32(0x28) = 0xf;
2172 MCHBAR8(0x2c4) = MCHBAR8(0x2c4) | 1;
2173
2174 MCHBAR32(0x3c) = MCHBAR32(0x3c) & ~0xe000000;
2175 MCHBAR32(0x40) = (MCHBAR32(0x40) & ~0xc0000) | 0x40000;
2176 u32 clkcx[2][2][3] = {
2177 {
2178 {0, 0x0c080302, 0x08010204}, // 667
2179 {0x02040000, 0x08100102, 0}
2180 },
2181 {
2182 {0x18000000, 0x3021060c, 0x20010208},
2183 {0, 0x0c090306, 0} // 800
2184 }
2185 };
2186 j = s->selected_timings.fsb_clock;
2187 i = s->selected_timings.mem_clock;
2188
2189 MCHBAR32(0x708) = clkcx[j][i][0];
2190 MCHBAR32(0x70c) = clkcx[j][i][1];
2191 MCHBAR32(0x6dc) = clkcx[j][i][2];
2192 MCHBAR8(0x40) = MCHBAR8(0x40) & ~0x2;
2193}
2194
2195static void sdram_periodic_rcomp(void)
2196{
2197 MCHBAR8(0x130) = MCHBAR8(0x130) & ~0x2;
2198 while ((MCHBAR32(0x130) & 0x80000000) > 0) {
2199 ;
2200 }
2201 MCHBAR16(0x1b4) = (MCHBAR16(0x1b4) & ~0x3000);
2202
2203 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2204 MCHBAR16(0x170) = (MCHBAR16(0x170) & ~0xf) | 0x9;
2205
2206 MCHBAR8(0x130) = MCHBAR8(0x130) | 0x82;
2207}
2208
2209static void sdram_new_trd(struct sysinfo *s)
2210{
2211 u8 pidelay, i, j, k, cc, trd_perphase[5];
2212 u8 bypass, freqgb, trd, reg8, txfifo, cas;
2213 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2214 u16 tmclk, thclk, buffertocore, postcalib;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002215 static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2216 static const u16 trd_adjust[2][2][5] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11002217 {
2218 {3000, 3000, 0,0,0},
2219 {1000,2000,3000,1500,2500}
2220 },
2221 {
2222 {2000,1000,3000,0,0},
2223 {2500, 2500, 0,0,0}
2224 }};
2225
2226 freqgb = 110;
2227 buffertocore = 5000;
2228 cas = s->selected_timings.CAS;
2229 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2230 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2231 tmclk = tmclk * 100 / freqgb;
2232 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2233 switch (s->selected_timings.mem_clock) {
2234 case MEM_CLOCK_667MHz:
2235 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2236 cc = 2;
2237 } else {
2238 cc = 3;
2239 }
2240 break;
2241 default:
2242 case MEM_CLOCK_800MHz:
2243 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2244 cc = 5;
2245 } else {
2246 cc = 2;
2247 }
2248 break;
2249 }
2250 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2251 maxrcvendelay = 0;
2252 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2253
2254 for (i = 0; i < 8; i++) {
2255 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 0x3) * (u32)(tmclk));
2256 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 0x3) * (u32)(tmclk) / 2);
2257 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 0x3) * (u32)(tmclk) / 4);
2258 rcvendelay += (u32)(pidelay * s->pi[i]);
2259 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2260 }
2261
2262 if ((MCHBAR8(0xc54+3) == 0xff) && (MCHBAR8(0xc08) & 0x80)) {
2263 bypass = 1;
2264 } else {
2265 bypass = 0;
2266 }
2267
2268 txfifo = 0;
2269 reg8 = (MCHBAR8(0x188) & 0xe) >> 1;
2270 txfifo = txfifo_lut[reg8] & 0x7;
2271
2272 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2273 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2274 if (s->async) {
2275 datadelay += tmclk / 2;
2276 }
2277
2278 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2279 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2280
2281 if (j == 0 && k == 0) {
2282 datadelay -= 3084;
2283 }
2284
2285 trd = 0;
2286 for (i = 0; i < cc; i++) {
2287 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2288 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2289 trd_perphase[i] += 1;
2290 if (trd_perphase[i] > trd) {
2291 trd = trd_perphase[i];
2292 }
2293 }
2294
2295 MCHBAR16(0x248) = (MCHBAR16(0x248) & ~0x1f00) | (trd << 8);
2296}
2297
2298static void sdram_powersettings(struct sysinfo *s)
2299{
2300 u8 j;
2301 u32 reg32;
2302
2303 /* Thermal sensor */
2304 MCHBAR8(0x3808) = 0x9b;
2305 MCHBAR32(0x380c) = (MCHBAR32(0x380c) & ~0x00ffffff) | 0x1d00;
2306 MCHBAR8(0x3814) = 0x08;
2307 MCHBAR8(0x3824) = 0x00;
2308 MCHBAR8(0x3809) = (MCHBAR8(0x3809) & ~0xf) | 0x4;
2309 MCHBAR8(0x3814) = (MCHBAR8(0x3814) & ~1) | 1;
2310 MCHBAR8(0x3812) = (MCHBAR8(0x3812) & ~0x80) | 0x80;
2311
2312 /* Clock gating */
2313 MCHBAR32(0xf18) = MCHBAR32(0xf18) & ~0x00040001;
2314 MCHBAR8(0xfac+3) = MCHBAR8(0xfac+3) & ~0x80;
2315 MCHBAR8(0xff8+3) = MCHBAR8(0xff8+3) & ~0x80;
2316 MCHBAR16(0xff0) = MCHBAR16(0xff0) & ~0x1fff;
2317 MCHBAR32(0xfb0) = MCHBAR32(0xfb0) & ~0x0001ffff;
2318 MCHBAR16(0x48) = (MCHBAR16(0x48) & ~0x03ff) & 0x6;
2319 MCHBAR32(0x20) = (MCHBAR32(0x20) & ~0xffffffff) | 0x20;
2320 MCHBAR8(0xd14) = MCHBAR8(0xd14) & ~1;
2321 MCHBAR8(0x239) = s->selected_timings.CAS - 1 + 0x15;
2322 MCHBAR16(0x2d1) = (MCHBAR16(0x2d1) & ~0x07fc) | 0x40;
2323 MCHBAR16(0x6d1) = (MCHBAR16(0x6d1) & ~0x0fff) | 0xd00;
2324 MCHBAR16(0x210) = MCHBAR16(0x210) & ~0x0d80;
2325 MCHBAR16(0xf6c+2) = 0xffff;
2326
2327 /* Sequencing */
2328 MCHBAR32(0x14) = (MCHBAR32(0x14) & ~0x1fffffff) | 0x1f643fff;
2329 MCHBAR32(0x18) = (MCHBAR32(0x18) & ~0xffffff7f) | 0x02010000;
2330 MCHBAR16(0x1c) = (MCHBAR16(0x1c) & ~0x7000) | (0x3 << 12);
2331
2332 /* Power */
2333 MCHBAR32(0x1104) = (MCHBAR32(0x1104) & ~0xffff0003) | 0x10100000;
2334 MCHBAR32(0x1108) = (MCHBAR32(0x1108) & ~0x0001bff7) | 0x00000078;
2335 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2336 MCHBAR16(0x110c) = (MCHBAR16(0x110c) & ~0x03ff) | 0xc8;
2337 } else {
2338 MCHBAR16(0x110c) = (MCHBAR16(0x110c) & ~0x03ff) | 0x100;
2339 }
2340 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2341
2342 MCHBAR32(0x1110) = (MCHBAR32(0x1110) & ~0x1fff37f) | 0x10810700;
2343 MCHBAR8(0x1114) = (MCHBAR8(0x1114) & ~0x07) | 1;
2344 MCHBAR8(0x1124) = MCHBAR8(0x1124) & ~0x02;
2345
Arthur Heymans6bf13012017-06-10 12:03:27 +02002346 static const u16 ddr2lut[2][4][2] = {{
Damien Zammit003d15c2015-11-20 17:17:51 +11002347 {0x0000, 0x0000},
2348 {0x019A, 0x0039},
2349 {0x0099, 0x1049},
2350 {0x0000, 0x0000}
2351 },
2352 {
2353 {0x0000, 0x0000},
2354 {0x019A, 0x0039},
2355 {0x0099, 0x1049},
2356 {0x0099, 0x2159}
2357 }};
2358
2359 MCHBAR16(0x23c) = 0x7a89;
2360 MCHBAR8(0x117) = 0xaa;
2361 MCHBAR16(0x118) = ddr2lut[j][s->selected_timings.CAS - 3][1];
2362 MCHBAR16(0x115) = (MCHBAR16(0x115) & ~0x7fff) | ddr2lut[j]
2363 [s->selected_timings.CAS - 3][0];
2364 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0xf000) | 0xf000;
2365 MCHBAR8(0x2c02) = (MCHBAR8(0x2c02) & ~0x77) | (4 << 4 | 4);
2366 if (s->nodll) {
2367 reg32 = 0x30000000;
2368 } else {
2369 reg32 = 0;
2370 }
2371 MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0x0f000000) | 0x20000000 | reg32;
2372 MCHBAR32(0x2d1) = (MCHBAR32(0x2d1) & ~0x00f00000) | 0x00f00000;
2373 MCHBAR32(0x6d0) = (MCHBAR32(0x6d0) & ~0x001ff000) | (0xbf << 20);
2374 MCHBAR16(0x610) = (MCHBAR16(0x610) & ~0x1f7f) | (0xb << 8) | (7 << 4) | 0xb;
2375 MCHBAR16(0x612) = 0x3264;
2376 MCHBAR16(0x614) = (MCHBAR16(0x614) & ~0x3f3f) | (0x14 << 8) | 0xa;
2377
2378 MCHBAR32(0x6c0) = MCHBAR32(0x6c0) | 0x80002000;
2379}
2380
2381static void sdram_programddr(void)
2382{
2383 MCHBAR16(0x6d1) = (MCHBAR16(0x6d1) & ~0x03ff) | 0x100;
2384 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0x003f) | 0x10;
2385 MCHBAR16(0x2d1) = (MCHBAR16(0x2d1) & ~0x7000) | 0x2000;
2386 MCHBAR8(0x180) = MCHBAR8(0x180) & ~0xe;
2387 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0xc;
2388 MCHBAR8(0x561) = MCHBAR8(0x561) & ~0xe;
2389 MCHBAR8(0x565) = MCHBAR8(0x565) & ~0xe;
2390 MCHBAR8(0x569) = MCHBAR8(0x569) & ~0xe;
2391 MCHBAR8(0x56d) = MCHBAR8(0x56d) & ~0xe;
2392 MCHBAR8(0x571) = MCHBAR8(0x571) & ~0xe;
2393 MCHBAR8(0x575) = MCHBAR8(0x575) & ~0xe;
2394 MCHBAR8(0x579) = MCHBAR8(0x579) & ~0xe;
2395 MCHBAR8(0x57d) = MCHBAR8(0x57d) & ~0xe;
2396 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0x2;
2397 MCHBAR16(0x1b4) = MCHBAR16(0x1b4) & ~0x400;
2398 MCHBAR16(0x210) = MCHBAR16(0x210) & ~0xdc0;
2399 MCHBAR8(0x239) = MCHBAR8(0x239) & ~0x80;
2400 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~(1 << 22);
2401 MCHBAR16(0x2d1) = MCHBAR16(0x2d1) & ~0x80fc;
2402 MCHBAR16(0x6d1) = MCHBAR16(0x6d1) & ~0xc00;
2403 MCHBAR8(0x180) = MCHBAR8(0x180) & ~0xd;
2404 MCHBAR8(0x561) = MCHBAR8(0x561) & ~1;
2405 MCHBAR8(0x565) = MCHBAR8(0x565) & ~1;
2406 MCHBAR8(0x569) = MCHBAR8(0x569) & ~1;
2407 MCHBAR8(0x56d) = MCHBAR8(0x56d) & ~1;
2408 MCHBAR8(0x571) = MCHBAR8(0x571) & ~1;
2409 MCHBAR8(0x575) = MCHBAR8(0x575) & ~1;
2410 MCHBAR8(0x579) = MCHBAR8(0x579) & ~1;
2411 MCHBAR8(0x57d) = MCHBAR8(0x57d) & ~1;
2412 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0x700000) | (0x3 << 20);
2413 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~0x100000;
2414 MCHBAR8(0x592) = MCHBAR8(0x592) | 0x1e;
2415 MCHBAR8(0x2c15) = MCHBAR8(0x2c15) | 0x3;
2416 MCHBAR32(0x62c) = (MCHBAR32(0x62c) & ~0xc000000) | 0x4000000;
2417 MCHBAR16(0x248) = MCHBAR16(0x248) | 0x6000;
2418 MCHBAR32(0x260) = MCHBAR32(0x260) | 0x10000;
2419 MCHBAR8(0x2c0) = MCHBAR8(0x2c0) | 0x10;
2420 MCHBAR32(0x2d0) = MCHBAR32(0x2d0) | (0xf << 24);
2421 MCHBAR8(0x189) = MCHBAR8(0x189) | 0x7;
2422 MCHBAR8(0x592) = MCHBAR8(0x592) | 0xc0;
2423 MCHBAR8(0x124) = MCHBAR8(0x124) | 0x7;
2424 MCHBAR16(0x12a) = (MCHBAR16(0x12a) & ~0xffff) | 0x0080;
2425 MCHBAR8(0x12c) = (MCHBAR8(0x12c) & ~0xff) | 0x10;
2426 MCHBAR16(0x2c0) = MCHBAR16(0x2c0) | 0x1e0;
2427 MCHBAR8(0x189) = MCHBAR8(0x189) | 0x18;
2428 MCHBAR8(0x193) = MCHBAR8(0x193) | 0xd;
2429 MCHBAR16(0x212) = MCHBAR16(0x212) | 0xa3f;
2430 MCHBAR8(0x248) = MCHBAR8(0x248) | 0x3;
2431 MCHBAR8(0x268) = (MCHBAR8(0x268) & ~0xff) | 0x4a;
2432 MCHBAR8(0x2c4) = MCHBAR8(0x2c4) & ~0x60;
2433 MCHBAR16(0x592) = MCHBAR16(0x592) | 0x321;
2434}
2435
2436static void sdram_programdqdqs(struct sysinfo *s)
2437{
2438 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2439 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2440 u8 repeat, halfclk, feature, reg8, push;
2441 u16 cwb, pimdclk;
2442 u32 reg32;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002443 static const u8 txfifotab[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002444
2445 tpi = 3000;
2446 dqdqs_out = 4382;
2447 dqdqs_outdelay = 5083;
2448 dqdqs_delay = 4692;
2449 coretomcp = 0;
2450 txdelay = 0;
2451 halfclk = 0;
2452 tmaxunmask = 0;
2453 tmaxpi = 0;
2454 repeat = 2;
2455 feature = 0;
2456 cwb = 0;
2457 pimdclk = 0;
2458 reg32 = 0;
2459 push = 0;
2460 reg8 = 0;
2461
2462 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2463 refclk = 3000 - mdclk;
2464
2465 coretomcp = ((MCHBAR8(0x246) >> 2) & 0x3) + 1;
2466 coretomcp *= mdclk;
2467
2468 reg8 = (MCHBAR8(0x188) & 0xe) >> 1;
2469
2470 while (repeat) {
2471 txdelay = mdclk * (
2472 ((MCHBAR16(0x220) >> 8) & 0x7) +
2473 (MCHBAR8(0x24d) & 0xf) +
2474 (MCHBAR8(0x24e) & 0x1)
2475 ) +
2476 txfifotab[reg8]*(mdclk/2) +
2477 coretomcp +
2478 refclk +
2479 cwb;
2480 halfclk = (MCHBAR8(0x5d9) >> 1) & 0x1;
2481 if (halfclk) {
2482 txdelay -= mdclk / 2;
2483 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2484 } else {
2485 reg32 = dqdqs_outdelay + coretomcp;
2486 }
2487
2488 tmaxunmask = txdelay - mdclk - dqdqs_out;
2489 tmaxpi = tmaxunmask - tpi;
2490
2491 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2492 if (repeat == 2) {
2493 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~(1 << 23);
2494 }
2495 feature = 1;
2496 repeat = 0;
2497 } else {
2498 repeat--;
2499 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) | (1 << 23);
2500 cwb = 2 * mdclk;
2501 }
2502 }
2503
2504 if (!feature) {
2505 MCHBAR8(0x2d1) = MCHBAR8(0x2d1) & ~0x3;
2506 return;
2507 }
2508 MCHBAR8(0x2d1) = MCHBAR8(0x2d1) | 0x3;
2509 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0xf000) | (pimdclk << 12);
2510 MCHBAR8(0x2c02) = (MCHBAR8(0x2c02) & ~0x77) | (push << 4) | push;
2511 MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0xf000000) | 0x3000000;
2512}
2513
2514/**
2515 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2516 */
2517void sdram_initialize(int boot_path, const u8 *spd_addresses)
2518{
2519 struct sysinfo si;
2520 u8 reg8;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002521 const char *boot_str[] = { "Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002522
2523 PRINTK_DEBUG("Setting up RAM controller.\n");
2524
2525 memset(&si, 0, sizeof(si));
2526
2527 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002528 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002529 si.spd_map[0] = spd_addresses[0];
2530 si.spd_map[1] = spd_addresses[1];
2531 si.spd_map[2] = spd_addresses[2];
2532 si.spd_map[3] = spd_addresses[3];
2533
2534 sdram_read_spds(&si);
2535
2536 /* Choose Common Frequency */
2537 sdram_detect_ram_speed(&si);
2538
2539 /* Determine smallest common tRAS, tRP, tRCD, etc */
2540 sdram_detect_smallest_params(&si);
2541
2542 /* Enable HPET */
2543 enable_hpet();
Damien Zammit003d15c2015-11-20 17:17:51 +11002544
2545 MCHBAR16(0xc1c) = MCHBAR16(0xc1c) | (1 << 15);
2546
Damien Zammit003d15c2015-11-20 17:17:51 +11002547 sdram_clk_crossing(&si);
2548
2549 sdram_checkreset();
2550 PRINTK_DEBUG("Done checkreset\n");
2551
2552 sdram_clkmode(&si);
2553 PRINTK_DEBUG("Done clkmode\n");
2554
2555 sdram_timings(&si);
2556 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2557
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002558 if (si.boot_path != BOOT_PATH_RESET) {
2559 sdram_dlltiming(&si);
2560 PRINTK_DEBUG("Done dlltiming\n");
2561 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002562
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002563 if (si.boot_path != BOOT_PATH_RESET) {
2564 sdram_rcomp(&si);
2565 PRINTK_DEBUG("Done RCOMP\n");
2566 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002567
2568 sdram_odt(&si);
2569 PRINTK_DEBUG("Done odt\n");
2570
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002571 if (si.boot_path != BOOT_PATH_RESET) {
2572 while ((MCHBAR8(0x130) & 0x1) != 0)
2573 ;
2574 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002575
2576 sdram_mmap(&si);
2577 PRINTK_DEBUG("Done mmap\n");
2578
2579 // Enable DDR IO buffer
2580 MCHBAR8(0x5dd) = (MCHBAR8(0x5dd) & ~0x3f) | 0x8;
2581 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x1;
2582
2583 sdram_rcompupdate(&si);
2584 PRINTK_DEBUG("Done RCOMP update\n");
2585
2586 MCHBAR8(0x40) = MCHBAR8(0x40) | 0x2;
2587
2588 if (si.boot_path != BOOT_PATH_RESUME) {
2589 MCHBAR32(0x260) = MCHBAR32(0x260) | (1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002590
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002591 sdram_jedecinit(&si);
2592 PRINTK_DEBUG("Done MRS\n");
2593 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002594
2595 sdram_misc(&si);
2596 PRINTK_DEBUG("Done misc\n");
2597
2598 sdram_zqcl(&si);
2599 PRINTK_DEBUG("Done zqcl\n");
2600
2601 if (si.boot_path != BOOT_PATH_RESUME) {
2602 MCHBAR32(0x268) = MCHBAR32(0x268) | 0xc0000000;
2603 }
2604
2605 sdram_dradrb(&si);
2606 PRINTK_DEBUG("Done dradrb\n");
2607
2608 sdram_rcven(&si);
2609 PRINTK_DEBUG("Done rcven\n");
2610
2611 sdram_new_trd(&si);
2612 PRINTK_DEBUG("Done tRD\n");
2613
2614 sdram_mmap_regs(&si);
2615 PRINTK_DEBUG("Done mmap regs\n");
2616
2617 sdram_enhancedmode(&si);
2618 PRINTK_DEBUG("Done enhanced mode\n");
2619
2620 sdram_powersettings(&si);
2621 PRINTK_DEBUG("Done power settings\n");
2622
2623 sdram_programddr();
2624 PRINTK_DEBUG("Done programming ddr\n");
2625
2626 sdram_programdqdqs(&si);
2627 PRINTK_DEBUG("Done programming dqdqs\n");
2628
2629 sdram_periodic_rcomp();
2630 PRINTK_DEBUG("Done periodic RCOMP\n");
2631
2632 /* Set init done */
2633 MCHBAR32(0x268) = MCHBAR32(0x268) | 0x40000000;
2634
2635 /* Tell ICH7 that we're done */
2636 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
2637 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8 & ~0x80);
2638
2639 /* Tell northbridge we're done */
2640 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf4);
2641 pci_write_config8(PCI_DEV(0,0,0), 0xf4, reg8 | 1);
2642
2643 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2644}