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