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