blob: cf6cbb9e0bd84e43ed7a9807433f8c4216461ead [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{
353 u16 mult[6] = {
354 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;
614 const u32 clkcross[2][2][4] = {
615 {
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
640 const u32 clkcross2[2][2][8] = {
641 {
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;
700 u8 pagetab[2][2] = {{0xe, 0x12}, {0x10, 0x14}};
701
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
875static void sdram_p_clkset0(struct pllparam *pll, u8 f, u8 i)
876{
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
884static void sdram_p_clkset1(struct pllparam *pll, u8 f, u8 i)
885{
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
893static void sdram_p_cmd(struct pllparam *pll, u8 f, u8 i)
894{
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
908static void sdram_p_ctrl(struct pllparam *pll, u8 f, u8 i)
909{
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
1214 u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0 };
1215 u8 rcompslew = 0xa;
1216 u8 rcompstr[7] = { 0x66, 0, 0xaa, 0x55, 0x55, 0x77, 0x77 };
1217 u16 rcompscomp[7] = { 0xa22a, 0, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a };
1218 u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1 };
1219 u16 rcompctl[7] = { 0x31c, 0, 0x374, 0x3a2, 0x3d0, 0x3fe, 0x42c };
1220 u16 rcompf[7] = { 0x1114, 0, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a };
1221
1222 // NC-NC x16SS x16DS x16SS2 x16DS2 x8DS, x8DS2
1223 u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa, 0xaa , 0x55, 0xaa};
1224 u16 rcompscomp2[7] = { 0x0000, 0xe22e, 0xe22e, 0xe22e, 0x8228 , 0xe22e, 0x8228 };
1225 u8 rcompdelay2[7] = { 0, 0, 0, 0, 2 , 0, 2};
1226
1227 u8 rcomplut[64][12] = {
1228 { 9, 9,11,11, 2, 2, 5,5, 6, 6,5, 5},
1229 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1230 { 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 { 10,9,12, 11, 2, 2, 5,5, 6, 6,5, 5},
1244 { 10,9,12, 11, 2, 2, 6,5, 7, 6,6, 5},
1245 { 10,10,12, 12, 2, 2, 6,5, 7, 6,6, 5},
1246 { 10,10,12, 12, 2, 2, 6,6, 7, 7,6, 6},
1247 { 10,10,12, 12, 3, 2, 6,6, 7, 7,6, 6},
1248 { 10,10,12, 12, 3, 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, 3, 6,6, 7, 7,6, 6},
1251 { 10,10,12, 12, 3, 3, 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 { 11,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1256 { 11,10,14, 13, 3, 3, 6,6, 7, 7,6, 6},
1257 { 12,10,14, 13, 3, 3, 6,6, 7, 7,6, 6},
1258 { 12,12,14, 13, 3, 3, 7,6, 7, 7,7, 6},
1259 { 13,12,16, 15, 3, 3, 7,6, 8, 7,7, 6},
1260 { 13,14,16, 15, 4, 3, 7,7, 8, 8,7, 7},
1261 { 14,14,16, 17, 4, 3, 7,7, 8, 8,7, 7},
1262 { 14,16,18, 17, 4, 4, 8,7, 8, 8,8, 7},
1263 { 15,16,18, 19, 4, 4, 8,7, 9, 8,8, 7},
1264 { 15,18,18, 19, 4, 4, 8,8, 9, 9,8, 8},
1265 { 16,18,20, 21, 4, 4, 8,8, 9, 9,8, 8},
1266 { 16,19,20, 21, 5, 4, 9,8, 10, 9,9, 8},
1267 { 16,19,20, 23, 5, 5, 9,9, 10, 10,9, 9},
1268 { 17,19,22, 23, 5, 5, 9,9, 10, 10,9, 9},
1269 { 17,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1270 { 17,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1271 { 18,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1272 { 18,21,24, 25, 5, 5, 9,9, 11, 10,9, 9},
1273 { 19,21,24, 27, 5, 5, 9, 9, 11, 11,9, 9},
1274 { 19,22,24, 27, 5, 5, 10,9, 11, 11,10, 9},
1275 { 20,22,24, 27, 6, 5, 10,10, 11, 11,10, 10},
1276 { 20,23,26, 27, 6, 6, 10,10, 12, 12,10, 10},
1277 { 20,23,26, 29, 6, 6, 10,10, 12, 12,10, 10},
1278 { 21,24,26, 29, 6, 6, 10,10, 12, 12,10, 10},
1279 { 21,24,26, 29, 6, 6, 11,10, 12, 13,11, 10},
1280 { 22,25,28, 29, 6, 6, 11,11, 13, 13,11, 11},
1281 { 22,25,28, 31, 6, 6, 11,11, 13, 13,11, 11},
1282 { 22,26,28, 31, 6, 6, 11,11, 13, 14,11, 11},
1283 { 23,26,30, 31, 7, 6, 12,11, 14, 14,12, 11},
1284 { 23,27,30, 33, 7, 7, 12,12, 14, 14,12, 12},
1285 { 23,27,30, 33, 7, 7, 12,12, 14, 15,12, 12},
1286 { 24,28,32, 33, 7, 7, 12,12, 15, 15,12, 12},
1287 { 24,28,32, 33, 7, 7, 12,12, 15, 16,12, 12},
1288 { 24,29,32, 35, 7, 7, 12,12, 15, 16,12, 12},
1289 { 25,29,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1290 { 25,30,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1291 { 25,30,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1292 };
1293
1294 srup = 0;
1295 srun = 0;
1296
1297 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1298 f = 0;
1299 rcomp1 = 0x00050431;
1300 } else {
1301 f = 1;
1302 rcomp1 = 0x00050542;
1303 }
1304 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
1305 rcomp2 = 0x14C42827;
1306 } else {
1307 rcomp2 = 0x19042827;
1308 }
1309
1310 for (i = 0; i < 7; i++) {
1311 if (i == 1)
1312 continue;
1313 reg8 = rcompupdate[i];
1314 MCHBAR8(rcompctl[i]) = (MCHBAR8(rcompctl[i]) & ~0x1) | reg8;
1315 MCHBAR8(rcompctl[i]) = MCHBAR8(rcompctl[i]) & ~0x2;
1316 reg16 = (u16) rcompslew;
1317 MCHBAR16(rcompctl[i]) = (MCHBAR16(rcompctl[i]) & ~0xf000) |
1318 (reg16 << 12);
1319 MCHBAR8(rcompctl[i]+4) = rcompstr[i];
1320 MCHBAR16(rcompctl[i]+0xe) = rcompscomp[i];
1321 MCHBAR8(rcompctl[i]+0x14) = (MCHBAR8(rcompctl[i]+0x14) & ~0x3) |
1322 rcompdelay[i];
1323 if (i == 2) {
1324 reg16 = (u16) rcompslew;
1325 MCHBAR16(rcompctl[i]) = (MCHBAR16(rcompctl[i]) &
1326 ~0xf000) | (reg16 << 12);
1327 MCHBAR8(rcompctl[i]+4) = rcompstr2[s->dimm_config[0]];
1328 MCHBAR16(rcompctl[i]+0xe) = rcompscomp2[s->dimm_config[0]];
1329 MCHBAR8(rcompctl[i]+0x14) = (MCHBAR8(rcompctl[i]+0x14) &
1330 ~0x3) | rcompdelay2[s->dimm_config[0]];
1331 }
1332
1333 MCHBAR16(rcompctl[i]+0x16) = MCHBAR16(rcompctl[i]+0x16) & ~0x7f7f;
1334 MCHBAR16(rcompctl[i]+0x18) = MCHBAR16(rcompctl[i]+0x18) & ~0x3f3f;
1335 MCHBAR16(rcompctl[i]+0x1a) = MCHBAR16(rcompctl[i]+0x1a) & ~0x3f3f;
1336 MCHBAR16(rcompctl[i]+0x1c) = MCHBAR16(rcompctl[i]+0x1c) & ~0x3f3f;
1337 MCHBAR16(rcompctl[i]+0x1e) = MCHBAR16(rcompctl[i]+0x1e) & ~0x3f3f;
1338 }
1339
1340 MCHBAR8(0x45a) = (MCHBAR8(0x45a) & ~0x3f) | 0x36;
1341 MCHBAR8(0x462) = (MCHBAR8(0x462) & ~0x3f) | 0x36;
1342
1343 for (i = 0; i < 7; i++) {
1344 if (i == 1)
1345 continue;
1346 MCHBAR8(rcompctl[i]) = MCHBAR8(rcompctl[i]) & ~0x60;
1347 MCHBAR16(rcompctl[i]+2) = MCHBAR16(rcompctl[i]+2) & ~0x706;
1348 MCHBAR16(rcompctl[i]+0xa) = MCHBAR16(rcompctl[i]+0xa) & ~0x7f7f;
1349 MCHBAR16(rcompctl[i]+0x12) = MCHBAR16(rcompctl[i]+0x12) & ~0x3f3f;
1350 MCHBAR16(rcompctl[i]+0x24) = MCHBAR16(rcompctl[i]+0x24) & ~0x1f1f;
1351 MCHBAR8(rcompctl[i]+0x26) = MCHBAR8(rcompctl[i]+0x26) & ~0x1f;
1352 }
1353
1354 MCHBAR16(0x45a) = MCHBAR16(0x45a) & ~0xffc0;
1355 MCHBAR16(0x45c) = MCHBAR16(0x45c) & ~0xf;
1356 MCHBAR16(0x462) = MCHBAR16(0x462) & ~0xffc0;
1357 MCHBAR16(0x464) = MCHBAR16(0x464) & ~0xf;
1358
1359 for (i = 0; i < 7; i++) {
1360 if (i == 1)
1361 continue;
1362 MCHBAR16(rcompctl[i]+0x10) = rcompf[i];
1363 MCHBAR16(rcompctl[i]+0x20) = 0x1219;
1364 MCHBAR16(rcompctl[i]+0x22) = 0x000C;
1365 }
1366
1367 MCHBAR32(0x164) = (MCHBAR32(0x164) & ~0x1f1f1f) | 0x0c1219;
1368 MCHBAR16(0x4b0) = (MCHBAR16(0x4b0) & ~0x1f00) | 0x1200;
1369 MCHBAR8(0x4b0) = (MCHBAR8(0x4b0) & ~0x1f) | 0x12;
1370 MCHBAR32(0x138) = 0x007C9007;
1371 MCHBAR32(0x16c) = rcomp1;
1372 MCHBAR16(0x17a) = 0x1f7f;
1373 MCHBAR32(0x134) = rcomp2;
1374 MCHBAR16(0x170) = (MCHBAR16(0x170) & ~0xf) | 1;
1375 MCHBAR16(0x178) = 0x134;
1376 MCHBAR32(0x130) = 0x4C293600;
1377 MCHBAR8(0x133) = (MCHBAR8(0x133) & ~0x44) | (1 << 6) | (1 << 2);
1378 MCHBAR16(0x4b0) = MCHBAR16(0x4b0) & ~(1 << 13);
1379 MCHBAR8(0x4b0) = MCHBAR8(0x4b0) & ~(1 << 5);
1380
1381 for (i = 0; i < 7; i++) {
1382 if (i == 1)
1383 continue;
1384 MCHBAR8(rcompctl[i]+2) = MCHBAR8(rcompctl[i]) & ~0x71;
1385 }
1386
1387 if ((MCHBAR32(0x130) & (1 << 30)) == 0) {
1388 MCHBAR8(0x130) = MCHBAR8(0x130) | 0x1;
1389 while ((MCHBAR8(0x130) & 0x1) != 0);
1390
1391 reg32 = MCHBAR32(0x13c);
1392 rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1393 rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1394
1395 for (i = 0; i < 7; i++) {
1396 if (i == 1)
1397 continue;
1398 srup = (MCHBAR8(rcompctl[i]+1) & 0xc0) >> 6;
1399 srun = (MCHBAR8(rcompctl[i]+1) & 0x30) >> 4;
1400 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
1401 MCHBAR16(rcompctl[i]+0x16) = (MCHBAR16(rcompctl[i]+0x16)
1402 & ~0x7f00) | reg16;
1403 reg16 = (u16)(rcompn - (1 << (srun + 1)));
1404 MCHBAR8(rcompctl[i]+0x16) = (MCHBAR8(rcompctl[i]+0x16) &
1405 ~0x7f) | (u8)reg16;
1406 }
1407
1408 reg8 = rcompp - (1 << (srup + 1));
1409 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1410 MCHBAR8(rcompctl[0]+0x18+i) =
1411 (MCHBAR8(rcompctl[0]+0x18+i) & ~0x3f) |
1412 rcomplut[j][0];
1413 }
1414
1415 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1416 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1417 MCHBAR8(rcompctl[2]+0x18+i) =
1418 (MCHBAR8(rcompctl[2]+0x18+i) & ~0x3f) |
1419 rcomplut[j][10];
1420 }
1421 }
1422
1423 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1424 MCHBAR8(rcompctl[3]+0x18+i) =
1425 (MCHBAR8(rcompctl[3]+0x18+i) & ~0x3f) |
1426 rcomplut[j][6];
1427 MCHBAR8(rcompctl[4]+0x18+i) =
1428 (MCHBAR8(rcompctl[4]+0x18+i) & ~0x3f) |
1429 rcomplut[j][6];
1430 }
1431
1432 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1433 MCHBAR8(rcompctl[5]+0x18+i) =
1434 (MCHBAR8(rcompctl[5]+0x18+i) & ~0x3f) |
1435 rcomplut[j][8];
1436 MCHBAR8(rcompctl[6]+0x18+i) =
1437 (MCHBAR8(rcompctl[6]+0x18+i) & ~0x3f) |
1438 rcomplut[j][8];
1439 }
1440
1441 reg8 = rcompn - (1 << (srun + 1));
1442 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1443 MCHBAR8(rcompctl[0]+0x1c+i) =
1444 (MCHBAR8(rcompctl[0]+0x1c+i) & ~0x3f) |
1445 rcomplut[j][1];
1446 }
1447
1448 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1449 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1450 MCHBAR8(rcompctl[2]+0x1c+i) =
1451 (MCHBAR8(rcompctl[2]+0x1c+i) & ~0x3f) |
1452 rcomplut[j][11];
1453 }
1454 }
1455
1456 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1457 MCHBAR8(rcompctl[3]+0x1c+i) =
1458 (MCHBAR8(rcompctl[3]+0x1c+i) & ~0x3f) |
1459 rcomplut[j][7];
1460 MCHBAR8(rcompctl[4]+0x1c+i) =
1461 (MCHBAR8(rcompctl[4]+0x1c+i) & ~0x3f) |
1462 rcomplut[j][7];
1463 }
1464
1465 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1466 MCHBAR8(rcompctl[5]+0x1c+i) =
1467 (MCHBAR8(rcompctl[5]+0x1c+i) & ~0x3f) |
1468 rcomplut[j][9];
1469 MCHBAR8(rcompctl[6]+0x1c+i) =
1470 (MCHBAR8(rcompctl[6]+0x1c+i) & ~0x3f) |
1471 rcomplut[j][9];
1472 }
1473 }
1474 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1475}
1476
1477static void sdram_odt(struct sysinfo *s)
1478{
1479 u8 rankindex = 0;
1480
1481 u16 odt294[16] = {
1482 0x0000, 0x0000, 0x0000, 0x0000,
1483 0x0044, 0x1111, 0x0000, 0x1111,
1484 0x0000, 0x0000, 0x0000, 0x0000,
1485 0x0044, 0x1111, 0x0000, 0x1111
1486 };
1487 u16 odt298[16] = {
1488 0x0000, 0x0011, 0x0000, 0x0011,
1489 0x0000, 0x4444, 0x0000, 0x4444,
1490 0x0000, 0x0000, 0x0000, 0x0000,
1491 0x0000, 0x4444, 0x0000, 0x4444
1492 };
1493
1494 switch (s->dimms[0].ranks) {
1495 case 0:
1496 if (s->dimms[1].ranks == 0) {
1497 rankindex = 0;
1498 } else if (s->dimms[1].ranks == 1) {
1499 rankindex = 4;
1500 } else if (s->dimms[1].ranks == 2) {
1501 rankindex = 12;
1502 }
1503 break;
1504 case 1:
1505 if (s->dimms[1].ranks == 0) {
1506 rankindex = 1;
1507 } else if (s->dimms[1].ranks == 1) {
1508 rankindex = 5;
1509 } else if (s->dimms[1].ranks == 2) {
1510 rankindex = 13;
1511 }
1512 break;
1513 case 2:
1514 if (s->dimms[1].ranks == 0) {
1515 rankindex = 3;
1516 } else if (s->dimms[1].ranks == 1) {
1517 rankindex = 7;
1518 } else if (s->dimms[1].ranks == 2) {
1519 rankindex = 15;
1520 }
1521 break;
1522 }
1523
1524 MCHBAR16(0x298) = odt298[rankindex];
1525 MCHBAR16(0x294) = odt294[rankindex];
1526}
1527
1528static void sdram_mmap(struct sysinfo *s)
1529{
1530 u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000, 0xc00001, 0xf00000};
1531 u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101, 0x1010000, 0x1010101};
1532 u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1533 u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006, 0x40002, 0x80006};
1534
1535 u16 tolud[7] = {0x800, 0x800, 0x1000, 0x1000, 0x2000, 0x1000, 0x2000};
1536 u16 tom[7] = {0x2, 0x2, 0x4, 0x4, 0x8, 0x4, 0x8};
1537 u16 touud[7] = {0x80, 0x80, 0x100, 0x100, 0x200, 0x100, 0x200};
1538 u32 gbsm[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000, 0x20000000, 0x10000000, 0x20000000};
1539 u32 bgsm[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000, 0x20000000, 0x10000000, 0x20000000};
1540 u32 tsegmb[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000, 0x20000000, 0x10000000, 0x20000000};
1541
1542 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1543 if (s->dimms[0].sides > 1) {
1544 // 2R/NC
1545 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x300001;
1546 MCHBAR32(0x208) = 0x101;
1547 MCHBAR32(0x200) = 0x40002;
1548 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1549 } else {
1550 // 1R/NC
1551 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x100001;
1552 MCHBAR32(0x208) = 0x1;
1553 MCHBAR32(0x200) = 0x20002;
1554 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1555 }
1556 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
1557
1558 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x300001;
1559 MCHBAR32(0x208) = 0x101;
1560 MCHBAR32(0x200) = 0x40002;
1561 MCHBAR32(0x204) = 0x40004;
1562 } else {
1563 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | w260[s->dimm_config[0]];
1564 MCHBAR32(0x208) = w208[s->dimm_config[0]];
1565 MCHBAR32(0x200) = w200[s->dimm_config[0]];
1566 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1567 }
1568 pci_write_config16(PCI_DEV(0, 0, 0), 0xb0, tolud[s->dimm_config[0]]);
1569 pci_write_config16(PCI_DEV(0, 0, 0), 0xa0, tom[s->dimm_config[0]]);
1570 pci_write_config16(PCI_DEV(0, 0, 0), 0xa2, touud[s->dimm_config[0]]);
1571 pci_write_config32(PCI_DEV(0, 0, 0), 0xa4, gbsm[s->dimm_config[0]]);
1572 pci_write_config32(PCI_DEV(0, 0, 0), 0xa8, bgsm[s->dimm_config[0]]);
1573 pci_write_config32(PCI_DEV(0, 0, 0), 0xac, tsegmb[s->dimm_config[0]]);
1574}
1575
1576#if 1
1577static void hpet_udelay(u32 del)
1578{
1579 u32 start, finish, now;
1580
1581 del *= 15; /* now in usec */
1582
1583 start = HPET32(0xf0);
1584 finish = start + del;
1585 while (1) {
1586 now = HPET32(0xf0);
1587 if (finish > start) {
1588 if (now >= finish)
1589 break;
1590 } else {
1591 if ((now < start) && (now >= finish)) {
1592 break;
1593 }
1594 }
1595 }
1596}
1597#endif
1598
1599static u8 sdram_checkrcompoverride(void)
1600{
1601 u32 xcomp;
1602 u8 aa, bb, a, b, c, d;
1603
1604 xcomp = MCHBAR32(0x13c);
1605 a = (u8)((xcomp & 0x7f000000) >> 24);
1606 b = (u8)((xcomp & 0x7f0000) >> 16);
1607 c = (u8)((xcomp & 0x3f00) >> 8);
1608 d = (u8)(xcomp & 0x3f);
1609
1610 if (a > b) {
1611 aa = a - b;
1612 } else {
1613 aa = b - a;
1614 }
1615 if (c > d) {
1616 bb = c - d;
1617 } else {
1618 bb = d - c;
1619 }
1620 if ((aa > 18) || (bb > 7) ||
1621 (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
1622 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
1623 MCHBAR32(0x140) = 0x9718a729;
1624 return 1;
1625 }
1626 return 0;
1627}
1628
1629static void sdram_rcompupdate(struct sysinfo *s)
1630{
1631 u8 i, ok;
1632 u32 reg32a, reg32b;
1633
1634 ok = 0;
1635 MCHBAR8(0x170) = MCHBAR8(0x170) & ~(1 << 3);
1636 MCHBAR8(0x130) = MCHBAR8(0x130) & ~(1 << 7);
1637 for (i = 0; i < 3; i++) {
1638 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1639 hpet_udelay(1000);
1640 while ((MCHBAR8(0x130) & 0x1) != 0);
1641 ok |= sdram_checkrcompoverride();
1642 }
1643 if (!ok) {
1644 reg32a = MCHBAR32(0x13c);
1645 reg32b = (reg32a >> 16) & 0x0000ffff;
1646 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1647 reg32a |= (1 << 31) | (1 << 15);
1648 MCHBAR32(0x140) = reg32a;
1649 }
1650 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1651 hpet_udelay(1000);
1652 while ((MCHBAR8(0x130) & 0x1) != 0);
1653}
1654
1655static void __attribute__((noinline))
1656sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1657{
1658 u32 reg32;
1659
1660 reg32 = jval << 3;
1661 reg32 |= rank * 0x8000000;
1662 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | jmode;
1663 read32((void *)reg32);
1664 barrier();
1665 hpet_udelay(1); // 1us
1666}
1667
1668static void sdram_zqcl(struct sysinfo *s)
1669{
1670 if (s->boot_path == BOOT_PATH_RESUME) {
1671 MCHBAR32(0x260) = MCHBAR32(0x260) | (1 << 27);
1672 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0xe) | NORMAL_OP_CMD;
1673 MCHBAR8(0x271) = MCHBAR8(0x271) & ~0x30;
1674 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~((1 << 30) | (1 << 31))) |
1675 (1 << 30) | (1 << 31);
1676 }
1677}
1678
1679static void sdram_jedecinit(struct sysinfo *s)
1680{
1681 u8 r, i, ch;
1682 u16 reg16, mrs, rttnom;
1683 struct jedeclist {
1684 char debug[15];
1685 u8 cmd;
1686 u16 val;
1687 };
1688
1689 struct jedeclist jedec[12] = {
1690 { " NOP ", NOP_CMD, 0 },
1691 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1692 { " EMRS2 ", EMRS2_CMD, 0 },
1693 { " EMRS3 ", EMRS3_CMD, 0 },
1694 { " EMRS1 ", EMRS1_CMD, 0 },
1695 { " DLL RESET ", MRS_CMD, (1 << 8) },
1696 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1697 { " AUTOREFRESH", CBR_CMD, 0 },
1698 { " AUTOREFRESH", CBR_CMD, 0 },
1699 { " INITIALISE ", MRS_CMD, 0 },
1700 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1701 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1702 };
1703
1704 mrs = (s->selected_timings.CAS << 4) |
1705 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 1;
1706 rttnom = (1 << 2);
1707 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1708 rttnom |= (1 << 6);
1709 }
1710
1711 hpet_udelay(200); // 200us
1712 reg16 = 0;
1713 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1714 for (i = 0; i < 12; i++) {
1715 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1716 reg16 = jedec[i].val;
1717 switch (jedec[i].cmd) {
1718 case EMRS1_CMD:
1719 reg16 |= rttnom;
1720 break;
1721 case MRS_CMD:
1722 reg16 |= mrs;
1723 break;
1724 default:
1725 break;
1726 }
1727 sdram_jedec(s, r, jedec[i].cmd, reg16);
1728 PRINTK_DEBUG("done\n");
1729 }
1730 }
1731}
1732
1733static void sdram_misc(struct sysinfo *s)
1734{
1735 u32 reg32;
1736
1737 reg32 = 0;
1738 reg32 |= (0x4 << 13);
1739 reg32 |= (0x6 << 8);
1740 MCHBAR32(0x274) = (MCHBAR32(0x274) & ~0x3ff00) | reg32;
1741 MCHBAR8(0x274) = MCHBAR8(0x274) & ~(1 << 7);
1742 MCHBAR8(0x26c) = MCHBAR8(0x26c) | 1;
1743 if (s->boot_path != BOOT_PATH_RESUME) {
1744 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0xe) | NORMAL_OP_CMD;
1745 MCHBAR8(0x271) = MCHBAR8(0x271) & ~0x30;
1746 } else {
1747 sdram_zqcl(s);
1748 }
1749}
1750
1751static void sdram_checkreset(void)
1752{
1753 u8 pmcon2, pmcon3, reset;
1754
1755 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1756 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1757 pmcon3 &= ~0x2;
1758 if (pmcon2 & 0x80) {
1759 pmcon2 &= ~0x80;
1760 reset = 1;
1761 } else {
1762 pmcon2 |= 0x80;
1763 reset = 0;
1764 }
1765 if (pmcon2 & 0x4) {
1766 pmcon2 |= 0x4;
1767 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1768 pmcon3 |= (1 << 3);
1769 }
1770 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1771 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
1772 if (reset) {
1773 printk(BIOS_DEBUG, "Power cycle reset...\n");
1774 outb(0xe, 0xcf9);
1775 }
1776}
1777
1778static void sdram_dradrb(struct sysinfo *s)
1779{
1780 u8 i, reg8, ch, r;
1781 u32 reg32, ind, c0dra, c0drb, dra;
1782 u16 addr;
1783 i = 0;
1784 u8 dratab[2][2][2][4] =
1785 {{
1786 {
1787 {0xff, 0xff, 0xff, 0xff},
1788 {0xff, 0x00, 0x02, 0xff}
1789 },
1790 {
1791 {0xff, 0x01, 0xff, 0xff},
1792 {0xff, 0x03, 0xff, 0x06}
1793 }
1794 },
1795 {
1796 {
1797 {0xff, 0xff, 0xff, 0xff},
1798 {0xff, 0x04, 0x06, 0x08}
1799 },
1800 {
1801 {0xff, 0xff, 0xff, 0xff},
1802 {0x05, 0x07, 0x09, 0xff}
1803 }
1804 }};
1805
1806 u8 dradrb[10][6] = {
1807 //Row Col Bank Width DRB
1808 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1809 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1810 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1811 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1812 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1813 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1814 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1815 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1816 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1817 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1818 };
1819
1820 reg32 = 0;
1821 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1822 i = r / 2;
1823 PRINTK_DEBUG("RANK %d PRESENT\n", r);
1824 dra = dratab[s->dimms[i].banks]
1825 [s->dimms[i].width]
1826 [s->dimms[i].cols - 9]
1827 [s->dimms[i].rows - 12];
1828
1829 if (s->dimms[i].banks == 1) {
1830 dra |= (1 << 7);
1831 }
1832 reg32 |= (dra << (r*8));
1833 }
1834 MCHBAR32(0x208) = reg32;
1835 c0dra = reg32;
1836 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1837
1838 reg32 = 0;
1839 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1840 reg32 |= (1 << r);
1841 }
1842 reg8 = (u8)(reg32 << 4) & 0xf0;
1843 MCHBAR8(0x262) = (MCHBAR8(0x262) & ~0xf0) | reg8;
1844 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) ||
1845 ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1846 MCHBAR8(0x260) = MCHBAR8(0x260) | 1;
1847 }
1848
1849 addr = 0x200;
1850 c0drb = 0;
1851 FOR_EACH_RANK(ch, r) {
1852 if (rank_is_populated(s->dimms, ch, r)) {
1853 ind = (c0dra >> (8*r)) & 0x7f;
1854 c0drb = (u16)(c0drb + dradrb[ind][5]);
1855 s->channel_capacity[0] += dradrb[ind][5] << 6;
1856 }
1857 MCHBAR16(addr) = c0drb;
1858 addr += 2;
1859 }
1860 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1861}
1862
1863static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1864{
1865 volatile u32 strobedata;
1866 u8 dqsmatches = 1;
1867 while (count--) {
1868 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0x2;
1869 hpet_udelay(1);
1870 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
1871 hpet_udelay(1);
1872 barrier();
1873 strobedata = read32((void*)strobeaddr);
1874 barrier();
1875 hpet_udelay(1);
1876
1877 if (((MCHBAR8(dqshighaddr) & 0x40) >> 6) != highlow) {
1878 dqsmatches = 0;
1879 }
1880 }
1881
1882 return dqsmatches;
1883}
1884
1885static void rcvenclock(u8 *coarse, u8 *medium, u8 bytelane)
1886{
1887 if (*medium < 3) {
1888 (*medium)++;
1889 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << (bytelane*2))))
1890 | (*medium << (bytelane*2));
1891 } else {
1892 *medium = 0;
1893 (*coarse)++;
1894 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (*coarse << 16);
1895 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~0x3 << (bytelane*2)))
1896 | (*medium << (bytelane*2));
1897 }
1898}
1899
1900static void sdram_rcven(struct sysinfo *s)
1901{
1902 u8 curcoarse, savecoarse;
1903 u8 curmedium, savemedium;
1904 u8 pi, savepi;
1905 u8 bytelane;
1906 u8 bytelanecoarse[8] = { 0 };
1907 u8 minbytelanecoarse = 0xff;
1908 u8 bytelaneoffset;
1909 u8 maxbytelane = 8;
1910 u32 strobeaddr = (rank_is_populated(s->dimms, 0, 0)) ? 0 : 2*128*1024*1024;
1911 u32 dqshighaddr;
1912
1913 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xc;
1914 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
1915
1916 PRINTK_DEBUG("rcven 0\n");
1917 for (bytelane = 0; bytelane < maxbytelane; bytelane++) {
1918 PRINTK_DEBUG("rcven bytelane %d\n", bytelane);
1919//trylaneagain:
1920 dqshighaddr = 0x561 + (bytelane << 2);
1921
1922 curcoarse = s->selected_timings.CAS + 1;
1923 pi = 0;
1924 curmedium = 0;
1925
1926 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (curcoarse << 16);
1927 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << (bytelane*2))))
1928 | (curmedium << (bytelane*2));
1929 MCHBAR8(0x560+bytelane*4) = MCHBAR8(0x560+bytelane*4) & ~0x3f;
1930
1931 savecoarse = curcoarse;
1932 savemedium = curmedium;
1933 savepi = pi;
1934
1935 PRINTK_DEBUG("rcven 0.1\n");
1936
1937 //MCHBAR16(0x588) = (MCHBAR16(0x588) & (u16)~(0x3 << (bytelane*2))) | (1 << (bytelane*2)); // XXX comment out
1938
1939 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1940 //printk(BIOS_DEBUG, "coarse=%d medium=%d\n", curcoarse, curmedium);
1941 rcvenclock(&curcoarse, &curmedium, bytelane);
1942 if (curcoarse > 0xf) {
1943 PRINTK_DEBUG("Error: coarse > 0xf\n");
1944 //goto trylaneagain;
1945 break;
1946 }
1947 }
1948 PRINTK_DEBUG("rcven 0.2\n");
1949
1950 savecoarse = curcoarse;
1951 savemedium = curmedium;
1952 rcvenclock(&curcoarse, &curmedium, bytelane);
1953
1954 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1955 savecoarse = curcoarse;
1956 savemedium = curmedium;
1957 rcvenclock(&curcoarse, &curmedium, bytelane);
1958 if (curcoarse > 0xf) {
1959 PRINTK_DEBUG("Error: coarse > 0xf\n");
1960 //goto trylaneagain;
1961 break;
1962 }
1963 }
1964
1965 PRINTK_DEBUG("rcven 0.3\n");
1966 curcoarse = savecoarse;
1967 curmedium = savemedium;
1968 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (curcoarse << 16);
1969 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << bytelane*2)))
1970 | (curmedium << (bytelane*2));
1971
1972 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1973 savepi = pi;
1974 pi++;
1975 if (pi > s->maxpi) {
1976 //if (s->nodll) {
1977 pi = savepi = s->maxpi;
1978 break;
1979 //}
1980 }
1981 MCHBAR8(0x560 + bytelane*4) = (MCHBAR8(0x560 + bytelane*4)
1982 & ~0x3f) | (pi << s->pioffset);
1983 }
1984 PRINTK_DEBUG("rcven 0.4\n");
1985
1986 pi = savepi;
1987 MCHBAR8(0x560 + bytelane*4) = (MCHBAR8(0x560 + bytelane*4) & ~0x3f)
1988 | (pi << s->pioffset);
1989 rcvenclock(&curcoarse, &curmedium, bytelane);
1990 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1991 PRINTK_DEBUG("Error: DQS not high\n");
1992 //goto trylaneagain;
1993 }
1994 PRINTK_DEBUG("rcven 0.5\n");
1995 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1996 curcoarse--;
1997 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000)
1998 | (curcoarse << 16);
1999 if (curcoarse == 0) {
2000 PRINTK_DEBUG("Error: DQS didnt hit 0\n");
2001 break;
2002 }
2003 }
2004
2005 PRINTK_DEBUG("rcven 0.6\n");
2006 rcvenclock(&curcoarse, &curmedium, bytelane);
2007 s->pi[bytelane] = pi;
2008 bytelanecoarse[bytelane] = curcoarse;
2009 }
2010
2011 PRINTK_DEBUG("rcven 1\n");
2012
2013 bytelane = maxbytelane;
2014 do {
2015 bytelane--;
2016 if (minbytelanecoarse > bytelanecoarse[bytelane]) {
2017 minbytelanecoarse = bytelanecoarse[bytelane];
2018 }
2019 } while (bytelane != 0);
2020
2021 bytelane = maxbytelane;
2022 do {
2023 bytelane--;
2024 bytelaneoffset = bytelanecoarse[bytelane] - minbytelanecoarse;
2025 MCHBAR16(0x5fa) = (MCHBAR16(0x5fa) & (u16)(~(0x3 << (bytelane*2))))
2026 | (bytelaneoffset << (bytelane*2));
2027 } while (bytelane != 0);
2028
2029 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (minbytelanecoarse << 16);
2030
2031 s->coarsectrl = minbytelanecoarse;
2032 s->coarsedelay = MCHBAR16(0x5fa);
2033 s->mediumphase = MCHBAR16(0x58c);
2034 s->readptrdelay = MCHBAR16(0x588);
2035
2036 PRINTK_DEBUG("rcven 2\n");
2037 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xe;
2038 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
2039 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x4;
2040 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x8;
2041
2042 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2043 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
2044 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2045 PRINTK_DEBUG("rcven 3\n");
2046}
2047
2048static void sdram_mmap_regs(struct sysinfo *s)
2049{
2050 bool reclaim;
2051 u32 tsegsize;
2052 u32 mmiosize;
2053 u32 tom, tolud, touud, reclaimbase, reclaimlimit;
2054 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase;
2055 u16 ggc;
2056 u16 ggc_to_uma[10] = { 0, 1, 4, 8, 16, 32, 48, 64, 128, 256 };
2057 u8 ggc_to_gtt[4] = { 0, 1, 0, 0 };
2058
2059 reclaimbase = 0;
2060 reclaimlimit = 0;
2061 ggc = pci_read_config16(PCI_DEV(0,0,0), GGC);
Damien Zammit51fdb922016-01-18 18:34:52 +11002062 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
Damien Zammit003d15c2015-11-20 17:17:51 +11002063 gfxsize = ggc_to_uma[(ggc & 0xf0) >> 4];
Damien Zammit51fdb922016-01-18 18:34:52 +11002064 gttsize = ggc_to_gtt[(ggc & 0x300) >> 8];
Damien Zammit003d15c2015-11-20 17:17:51 +11002065 tom = s->channel_capacity[0];
2066
2067 tsegsize = 0x1; // 1MB
2068 mmiosize = 0x400; // 1GB
2069
2070 reclaim = false;
2071 tolud = MIN(0x1000 - mmiosize, tom);
2072 if ((tom - tolud) > 0x40) {
2073 // reclaim = true;
2074 }
2075 if (reclaim) {
2076 tolud = tolud & ~0x3f;
2077 tom = tom & ~0x3f;
2078 reclaimbase = MAX(0x1000, tom);
2079 reclaimlimit = reclaimbase + (MIN(0x1000, tom) - tolud) - 0x40;
2080 }
2081 touud = tom;
2082 if (reclaim) {
2083 touud = reclaimlimit + 0x40;
2084 }
2085
2086 gfxbase = tolud - gfxsize;
2087 gttbase = gfxbase - gttsize;
2088 tsegbase = gttbase - tsegsize;
2089
2090 /* Program the regs */
Damien Zammit51fdb922016-01-18 18:34:52 +11002091 pci_write_config16(PCI_DEV(0,0,0), TOLUD, (u16)(tolud << 4));
2092 pci_write_config16(PCI_DEV(0,0,0), TOM, (u16)(tom >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002093 if (reclaim) {
2094 pci_write_config16(PCI_DEV(0,0,0), 0x98, (u16)(reclaimbase >> 6));
2095 pci_write_config16(PCI_DEV(0,0,0), 0x9a, (u16)(reclaimlimit >> 6));
2096 }
Damien Zammit51fdb922016-01-18 18:34:52 +11002097 pci_write_config16(PCI_DEV(0,0,0), TOUUD, (u16)(touud));
2098 pci_write_config32(PCI_DEV(0,0,0), GBSM, gfxbase << 20);
2099 pci_write_config32(PCI_DEV(0,0,0), BGSM, gttbase << 20);
2100 pci_write_config32(PCI_DEV(0,0,0), TSEG, tsegbase << 20);
2101
2102 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
2103 pci_read_config32(PCI_DEV(0,0,0), GBSM), gfxbase << 20);
2104 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
2105 pci_read_config32(PCI_DEV(0,0,0), BGSM), gttbase << 20);
2106 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
2107 pci_read_config32(PCI_DEV(0,0,0), TSEG), tsegbase << 20);
Damien Zammit003d15c2015-11-20 17:17:51 +11002108}
2109
2110static void sdram_enhancedmode(struct sysinfo *s)
2111{
2112 u8 reg8, ch, r, j, i;
2113 u32 mask32, reg32;
2114 MCHBAR8(0x246) = MCHBAR8(0x246) | 1;
2115 MCHBAR8(0x269 + 3) = MCHBAR8(0x269 + 3) | 1;
2116 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
2117 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2118 MCHBAR32(0x120) = (MCHBAR32(0x120) & ~mask32) | reg32;
2119 MCHBAR8(0x288 + 1) = 0x2;
2120 MCHBAR16(0x288 + 2) = 0x0804;
2121 MCHBAR16(0x288 + 4) = 0x2010;
2122 MCHBAR8(0x288 + 6) = 0x40;
2123 MCHBAR16(0x288 + 8) = 0x091c;
2124 MCHBAR8(0x288 + 10) = 0xf2;
2125 MCHBAR8(0x241) = MCHBAR8(0x241) | 1;
2126 MCHBAR8(0x243) = MCHBAR8(0x243) | 1;
2127 MCHBAR16(0x272) = MCHBAR16(0x272) | 0x100;
2128
2129 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf0);
2130 pci_write_config8(PCI_DEV(0,0,0), 0xf0, reg8 | 1);
2131 MCHBAR32(0xfa0) = 0x00000002;
2132 MCHBAR32(0xfa4) = 0x20310002;
2133 MCHBAR32(0x24) = 0x02020302;
2134 MCHBAR32(0x30) = 0x001f1806;
2135 MCHBAR32(0x34) = 0x01102800;
2136 MCHBAR32(0x38) = 0x07000000;
2137 MCHBAR32(0x3c) = 0x01014010;
2138 MCHBAR32(0x40) = 0x0f038000;
2139 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf0);
2140 pci_write_config8(PCI_DEV(0,0,0), 0xf0, reg8 & ~1);
2141
2142 u32 nranks, curranksize, maxranksize, maxdra, dra;
2143 u8 rankmismatch, dramismatch;
2144 u8 drbtab[10] = { 0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8, 0x20, 0x10 };
2145
2146 nranks = 0;
2147 curranksize = 0;
2148 maxranksize = 0;
2149 maxdra = 0;
2150 rankmismatch = 0;
2151 dramismatch = 0;
2152 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2153 nranks++;
2154 dra = (u8) ((MCHBAR32(0x208) >> (8*r)) & 0x7f);
2155 curranksize = drbtab[dra];
2156 if (maxranksize == 0) {
2157 maxranksize = curranksize;
2158 maxdra = dra;
2159 }
2160 if (curranksize != maxranksize) {
2161 rankmismatch = 1;
2162 }
2163 if (dra != maxdra) {
2164 dramismatch = 1;
2165 }
2166 }
2167
2168 reg8 = 0;
2169 switch (nranks) {
2170 case 4:
2171 if (rankmismatch) {
2172 reg8 = 0x64;
2173 } else {
2174 reg8 = 0xa4;
2175 }
2176 break;
2177 case 1:
2178 case 3:
2179 reg8 = 0x64;
2180 break;
2181 case 2:
2182 if (rankmismatch) {
2183 reg8 = 0x64;
2184 } else {
2185 reg8 = 0x24;
2186 }
2187 break;
2188 default:
2189 die("Invalid number of ranks found, halt\n");
2190 break;
2191 }
2192 MCHBAR8(0x111) = (MCHBAR8(0x111) & ~0xfc) | (reg8 & 0xfc);
2193 MCHBAR32(0xd0) = MCHBAR32(0xd0) & ~0x80000000;
2194
2195 MCHBAR32(0x28) = 0xf;
2196 MCHBAR8(0x2c4) = MCHBAR8(0x2c4) | 1;
2197
2198 MCHBAR32(0x3c) = MCHBAR32(0x3c) & ~0xe000000;
2199 MCHBAR32(0x40) = (MCHBAR32(0x40) & ~0xc0000) | 0x40000;
2200 u32 clkcx[2][2][3] = {
2201 {
2202 {0, 0x0c080302, 0x08010204}, // 667
2203 {0x02040000, 0x08100102, 0}
2204 },
2205 {
2206 {0x18000000, 0x3021060c, 0x20010208},
2207 {0, 0x0c090306, 0} // 800
2208 }
2209 };
2210 j = s->selected_timings.fsb_clock;
2211 i = s->selected_timings.mem_clock;
2212
2213 MCHBAR32(0x708) = clkcx[j][i][0];
2214 MCHBAR32(0x70c) = clkcx[j][i][1];
2215 MCHBAR32(0x6dc) = clkcx[j][i][2];
2216 MCHBAR8(0x40) = MCHBAR8(0x40) & ~0x2;
2217}
2218
2219static void sdram_periodic_rcomp(void)
2220{
2221 MCHBAR8(0x130) = MCHBAR8(0x130) & ~0x2;
2222 while ((MCHBAR32(0x130) & 0x80000000) > 0) {
2223 ;
2224 }
2225 MCHBAR16(0x1b4) = (MCHBAR16(0x1b4) & ~0x3000);
2226
2227 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2228 MCHBAR16(0x170) = (MCHBAR16(0x170) & ~0xf) | 0x9;
2229
2230 MCHBAR8(0x130) = MCHBAR8(0x130) | 0x82;
2231}
2232
2233static void sdram_new_trd(struct sysinfo *s)
2234{
2235 u8 pidelay, i, j, k, cc, trd_perphase[5];
2236 u8 bypass, freqgb, trd, reg8, txfifo, cas;
2237 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2238 u16 tmclk, thclk, buffertocore, postcalib;
2239 u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2240 u16 trd_adjust[2][2][5] = {
2241 {
2242 {3000, 3000, 0,0,0},
2243 {1000,2000,3000,1500,2500}
2244 },
2245 {
2246 {2000,1000,3000,0,0},
2247 {2500, 2500, 0,0,0}
2248 }};
2249
2250 freqgb = 110;
2251 buffertocore = 5000;
2252 cas = s->selected_timings.CAS;
2253 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2254 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2255 tmclk = tmclk * 100 / freqgb;
2256 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2257 switch (s->selected_timings.mem_clock) {
2258 case MEM_CLOCK_667MHz:
2259 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2260 cc = 2;
2261 } else {
2262 cc = 3;
2263 }
2264 break;
2265 default:
2266 case MEM_CLOCK_800MHz:
2267 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2268 cc = 5;
2269 } else {
2270 cc = 2;
2271 }
2272 break;
2273 }
2274 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2275 maxrcvendelay = 0;
2276 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2277
2278 for (i = 0; i < 8; i++) {
2279 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 0x3) * (u32)(tmclk));
2280 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 0x3) * (u32)(tmclk) / 2);
2281 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 0x3) * (u32)(tmclk) / 4);
2282 rcvendelay += (u32)(pidelay * s->pi[i]);
2283 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2284 }
2285
2286 if ((MCHBAR8(0xc54+3) == 0xff) && (MCHBAR8(0xc08) & 0x80)) {
2287 bypass = 1;
2288 } else {
2289 bypass = 0;
2290 }
2291
2292 txfifo = 0;
2293 reg8 = (MCHBAR8(0x188) & 0xe) >> 1;
2294 txfifo = txfifo_lut[reg8] & 0x7;
2295
2296 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2297 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2298 if (s->async) {
2299 datadelay += tmclk / 2;
2300 }
2301
2302 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2303 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2304
2305 if (j == 0 && k == 0) {
2306 datadelay -= 3084;
2307 }
2308
2309 trd = 0;
2310 for (i = 0; i < cc; i++) {
2311 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2312 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2313 trd_perphase[i] += 1;
2314 if (trd_perphase[i] > trd) {
2315 trd = trd_perphase[i];
2316 }
2317 }
2318
2319 MCHBAR16(0x248) = (MCHBAR16(0x248) & ~0x1f00) | (trd << 8);
2320}
2321
2322static void sdram_powersettings(struct sysinfo *s)
2323{
2324 u8 j;
2325 u32 reg32;
2326
2327 /* Thermal sensor */
2328 MCHBAR8(0x3808) = 0x9b;
2329 MCHBAR32(0x380c) = (MCHBAR32(0x380c) & ~0x00ffffff) | 0x1d00;
2330 MCHBAR8(0x3814) = 0x08;
2331 MCHBAR8(0x3824) = 0x00;
2332 MCHBAR8(0x3809) = (MCHBAR8(0x3809) & ~0xf) | 0x4;
2333 MCHBAR8(0x3814) = (MCHBAR8(0x3814) & ~1) | 1;
2334 MCHBAR8(0x3812) = (MCHBAR8(0x3812) & ~0x80) | 0x80;
2335
2336 /* Clock gating */
2337 MCHBAR32(0xf18) = MCHBAR32(0xf18) & ~0x00040001;
2338 MCHBAR8(0xfac+3) = MCHBAR8(0xfac+3) & ~0x80;
2339 MCHBAR8(0xff8+3) = MCHBAR8(0xff8+3) & ~0x80;
2340 MCHBAR16(0xff0) = MCHBAR16(0xff0) & ~0x1fff;
2341 MCHBAR32(0xfb0) = MCHBAR32(0xfb0) & ~0x0001ffff;
2342 MCHBAR16(0x48) = (MCHBAR16(0x48) & ~0x03ff) & 0x6;
2343 MCHBAR32(0x20) = (MCHBAR32(0x20) & ~0xffffffff) | 0x20;
2344 MCHBAR8(0xd14) = MCHBAR8(0xd14) & ~1;
2345 MCHBAR8(0x239) = s->selected_timings.CAS - 1 + 0x15;
2346 MCHBAR16(0x2d1) = (MCHBAR16(0x2d1) & ~0x07fc) | 0x40;
2347 MCHBAR16(0x6d1) = (MCHBAR16(0x6d1) & ~0x0fff) | 0xd00;
2348 MCHBAR16(0x210) = MCHBAR16(0x210) & ~0x0d80;
2349 MCHBAR16(0xf6c+2) = 0xffff;
2350
2351 /* Sequencing */
2352 MCHBAR32(0x14) = (MCHBAR32(0x14) & ~0x1fffffff) | 0x1f643fff;
2353 MCHBAR32(0x18) = (MCHBAR32(0x18) & ~0xffffff7f) | 0x02010000;
2354 MCHBAR16(0x1c) = (MCHBAR16(0x1c) & ~0x7000) | (0x3 << 12);
2355
2356 /* Power */
2357 MCHBAR32(0x1104) = (MCHBAR32(0x1104) & ~0xffff0003) | 0x10100000;
2358 MCHBAR32(0x1108) = (MCHBAR32(0x1108) & ~0x0001bff7) | 0x00000078;
2359 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2360 MCHBAR16(0x110c) = (MCHBAR16(0x110c) & ~0x03ff) | 0xc8;
2361 } else {
2362 MCHBAR16(0x110c) = (MCHBAR16(0x110c) & ~0x03ff) | 0x100;
2363 }
2364 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2365
2366 MCHBAR32(0x1110) = (MCHBAR32(0x1110) & ~0x1fff37f) | 0x10810700;
2367 MCHBAR8(0x1114) = (MCHBAR8(0x1114) & ~0x07) | 1;
2368 MCHBAR8(0x1124) = MCHBAR8(0x1124) & ~0x02;
2369
2370 u16 ddr2lut[2][4][2] = {{
2371 {0x0000, 0x0000},
2372 {0x019A, 0x0039},
2373 {0x0099, 0x1049},
2374 {0x0000, 0x0000}
2375 },
2376 {
2377 {0x0000, 0x0000},
2378 {0x019A, 0x0039},
2379 {0x0099, 0x1049},
2380 {0x0099, 0x2159}
2381 }};
2382
2383 MCHBAR16(0x23c) = 0x7a89;
2384 MCHBAR8(0x117) = 0xaa;
2385 MCHBAR16(0x118) = ddr2lut[j][s->selected_timings.CAS - 3][1];
2386 MCHBAR16(0x115) = (MCHBAR16(0x115) & ~0x7fff) | ddr2lut[j]
2387 [s->selected_timings.CAS - 3][0];
2388 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0xf000) | 0xf000;
2389 MCHBAR8(0x2c02) = (MCHBAR8(0x2c02) & ~0x77) | (4 << 4 | 4);
2390 if (s->nodll) {
2391 reg32 = 0x30000000;
2392 } else {
2393 reg32 = 0;
2394 }
2395 MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0x0f000000) | 0x20000000 | reg32;
2396 MCHBAR32(0x2d1) = (MCHBAR32(0x2d1) & ~0x00f00000) | 0x00f00000;
2397 MCHBAR32(0x6d0) = (MCHBAR32(0x6d0) & ~0x001ff000) | (0xbf << 20);
2398 MCHBAR16(0x610) = (MCHBAR16(0x610) & ~0x1f7f) | (0xb << 8) | (7 << 4) | 0xb;
2399 MCHBAR16(0x612) = 0x3264;
2400 MCHBAR16(0x614) = (MCHBAR16(0x614) & ~0x3f3f) | (0x14 << 8) | 0xa;
2401
2402 MCHBAR32(0x6c0) = MCHBAR32(0x6c0) | 0x80002000;
2403}
2404
2405static void sdram_programddr(void)
2406{
2407 MCHBAR16(0x6d1) = (MCHBAR16(0x6d1) & ~0x03ff) | 0x100;
2408 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0x003f) | 0x10;
2409 MCHBAR16(0x2d1) = (MCHBAR16(0x2d1) & ~0x7000) | 0x2000;
2410 MCHBAR8(0x180) = MCHBAR8(0x180) & ~0xe;
2411 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0xc;
2412 MCHBAR8(0x561) = MCHBAR8(0x561) & ~0xe;
2413 MCHBAR8(0x565) = MCHBAR8(0x565) & ~0xe;
2414 MCHBAR8(0x569) = MCHBAR8(0x569) & ~0xe;
2415 MCHBAR8(0x56d) = MCHBAR8(0x56d) & ~0xe;
2416 MCHBAR8(0x571) = MCHBAR8(0x571) & ~0xe;
2417 MCHBAR8(0x575) = MCHBAR8(0x575) & ~0xe;
2418 MCHBAR8(0x579) = MCHBAR8(0x579) & ~0xe;
2419 MCHBAR8(0x57d) = MCHBAR8(0x57d) & ~0xe;
2420 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0x2;
2421 MCHBAR16(0x1b4) = MCHBAR16(0x1b4) & ~0x400;
2422 MCHBAR16(0x210) = MCHBAR16(0x210) & ~0xdc0;
2423 MCHBAR8(0x239) = MCHBAR8(0x239) & ~0x80;
2424 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~(1 << 22);
2425 MCHBAR16(0x2d1) = MCHBAR16(0x2d1) & ~0x80fc;
2426 MCHBAR16(0x6d1) = MCHBAR16(0x6d1) & ~0xc00;
2427 MCHBAR8(0x180) = MCHBAR8(0x180) & ~0xd;
2428 MCHBAR8(0x561) = MCHBAR8(0x561) & ~1;
2429 MCHBAR8(0x565) = MCHBAR8(0x565) & ~1;
2430 MCHBAR8(0x569) = MCHBAR8(0x569) & ~1;
2431 MCHBAR8(0x56d) = MCHBAR8(0x56d) & ~1;
2432 MCHBAR8(0x571) = MCHBAR8(0x571) & ~1;
2433 MCHBAR8(0x575) = MCHBAR8(0x575) & ~1;
2434 MCHBAR8(0x579) = MCHBAR8(0x579) & ~1;
2435 MCHBAR8(0x57d) = MCHBAR8(0x57d) & ~1;
2436 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0x700000) | (0x3 << 20);
2437 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~0x100000;
2438 MCHBAR8(0x592) = MCHBAR8(0x592) | 0x1e;
2439 MCHBAR8(0x2c15) = MCHBAR8(0x2c15) | 0x3;
2440 MCHBAR32(0x62c) = (MCHBAR32(0x62c) & ~0xc000000) | 0x4000000;
2441 MCHBAR16(0x248) = MCHBAR16(0x248) | 0x6000;
2442 MCHBAR32(0x260) = MCHBAR32(0x260) | 0x10000;
2443 MCHBAR8(0x2c0) = MCHBAR8(0x2c0) | 0x10;
2444 MCHBAR32(0x2d0) = MCHBAR32(0x2d0) | (0xf << 24);
2445 MCHBAR8(0x189) = MCHBAR8(0x189) | 0x7;
2446 MCHBAR8(0x592) = MCHBAR8(0x592) | 0xc0;
2447 MCHBAR8(0x124) = MCHBAR8(0x124) | 0x7;
2448 MCHBAR16(0x12a) = (MCHBAR16(0x12a) & ~0xffff) | 0x0080;
2449 MCHBAR8(0x12c) = (MCHBAR8(0x12c) & ~0xff) | 0x10;
2450 MCHBAR16(0x2c0) = MCHBAR16(0x2c0) | 0x1e0;
2451 MCHBAR8(0x189) = MCHBAR8(0x189) | 0x18;
2452 MCHBAR8(0x193) = MCHBAR8(0x193) | 0xd;
2453 MCHBAR16(0x212) = MCHBAR16(0x212) | 0xa3f;
2454 MCHBAR8(0x248) = MCHBAR8(0x248) | 0x3;
2455 MCHBAR8(0x268) = (MCHBAR8(0x268) & ~0xff) | 0x4a;
2456 MCHBAR8(0x2c4) = MCHBAR8(0x2c4) & ~0x60;
2457 MCHBAR16(0x592) = MCHBAR16(0x592) | 0x321;
2458}
2459
2460static void sdram_programdqdqs(struct sysinfo *s)
2461{
2462 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2463 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2464 u8 repeat, halfclk, feature, reg8, push;
2465 u16 cwb, pimdclk;
2466 u32 reg32;
2467 u8 txfifotab[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2468
2469 tpi = 3000;
2470 dqdqs_out = 4382;
2471 dqdqs_outdelay = 5083;
2472 dqdqs_delay = 4692;
2473 coretomcp = 0;
2474 txdelay = 0;
2475 halfclk = 0;
2476 tmaxunmask = 0;
2477 tmaxpi = 0;
2478 repeat = 2;
2479 feature = 0;
2480 cwb = 0;
2481 pimdclk = 0;
2482 reg32 = 0;
2483 push = 0;
2484 reg8 = 0;
2485
2486 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2487 refclk = 3000 - mdclk;
2488
2489 coretomcp = ((MCHBAR8(0x246) >> 2) & 0x3) + 1;
2490 coretomcp *= mdclk;
2491
2492 reg8 = (MCHBAR8(0x188) & 0xe) >> 1;
2493
2494 while (repeat) {
2495 txdelay = mdclk * (
2496 ((MCHBAR16(0x220) >> 8) & 0x7) +
2497 (MCHBAR8(0x24d) & 0xf) +
2498 (MCHBAR8(0x24e) & 0x1)
2499 ) +
2500 txfifotab[reg8]*(mdclk/2) +
2501 coretomcp +
2502 refclk +
2503 cwb;
2504 halfclk = (MCHBAR8(0x5d9) >> 1) & 0x1;
2505 if (halfclk) {
2506 txdelay -= mdclk / 2;
2507 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2508 } else {
2509 reg32 = dqdqs_outdelay + coretomcp;
2510 }
2511
2512 tmaxunmask = txdelay - mdclk - dqdqs_out;
2513 tmaxpi = tmaxunmask - tpi;
2514
2515 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2516 if (repeat == 2) {
2517 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~(1 << 23);
2518 }
2519 feature = 1;
2520 repeat = 0;
2521 } else {
2522 repeat--;
2523 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) | (1 << 23);
2524 cwb = 2 * mdclk;
2525 }
2526 }
2527
2528 if (!feature) {
2529 MCHBAR8(0x2d1) = MCHBAR8(0x2d1) & ~0x3;
2530 return;
2531 }
2532 MCHBAR8(0x2d1) = MCHBAR8(0x2d1) | 0x3;
2533 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0xf000) | (pimdclk << 12);
2534 MCHBAR8(0x2c02) = (MCHBAR8(0x2c02) & ~0x77) | (push << 4) | push;
2535 MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0xf000000) | 0x3000000;
2536}
2537
2538/**
2539 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2540 */
2541void sdram_initialize(int boot_path, const u8 *spd_addresses)
2542{
2543 struct sysinfo si;
2544 u8 reg8;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002545 const char *boot_str[] = { "Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002546
2547 PRINTK_DEBUG("Setting up RAM controller.\n");
2548
2549 memset(&si, 0, sizeof(si));
2550
2551 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002552 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002553 si.spd_map[0] = spd_addresses[0];
2554 si.spd_map[1] = spd_addresses[1];
2555 si.spd_map[2] = spd_addresses[2];
2556 si.spd_map[3] = spd_addresses[3];
2557
2558 sdram_read_spds(&si);
2559
2560 /* Choose Common Frequency */
2561 sdram_detect_ram_speed(&si);
2562
2563 /* Determine smallest common tRAS, tRP, tRCD, etc */
2564 sdram_detect_smallest_params(&si);
2565
2566 /* Enable HPET */
2567 enable_hpet();
2568 hpet_udelay(300000);
2569
2570 MCHBAR16(0xc1c) = MCHBAR16(0xc1c) | (1 << 15);
2571
2572 hpet_udelay(100000);
2573
2574 sdram_clk_crossing(&si);
2575
2576 sdram_checkreset();
2577 PRINTK_DEBUG("Done checkreset\n");
2578
2579 sdram_clkmode(&si);
2580 PRINTK_DEBUG("Done clkmode\n");
2581
2582 sdram_timings(&si);
2583 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2584
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002585 if (si.boot_path != BOOT_PATH_RESET) {
2586 sdram_dlltiming(&si);
2587 PRINTK_DEBUG("Done dlltiming\n");
2588 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002589
2590 hpet_udelay(200000);
2591
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002592 if (si.boot_path != BOOT_PATH_RESET) {
2593 sdram_rcomp(&si);
2594 PRINTK_DEBUG("Done RCOMP\n");
2595 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002596
2597 sdram_odt(&si);
2598 PRINTK_DEBUG("Done odt\n");
2599
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002600 if (si.boot_path != BOOT_PATH_RESET) {
2601 while ((MCHBAR8(0x130) & 0x1) != 0)
2602 ;
2603 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002604
2605 sdram_mmap(&si);
2606 PRINTK_DEBUG("Done mmap\n");
2607
2608 // Enable DDR IO buffer
2609 MCHBAR8(0x5dd) = (MCHBAR8(0x5dd) & ~0x3f) | 0x8;
2610 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x1;
2611
2612 sdram_rcompupdate(&si);
2613 PRINTK_DEBUG("Done RCOMP update\n");
2614
2615 MCHBAR8(0x40) = MCHBAR8(0x40) | 0x2;
2616
2617 if (si.boot_path != BOOT_PATH_RESUME) {
2618 MCHBAR32(0x260) = MCHBAR32(0x260) | (1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002619
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002620 sdram_jedecinit(&si);
2621 PRINTK_DEBUG("Done MRS\n");
2622 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002623
2624 sdram_misc(&si);
2625 PRINTK_DEBUG("Done misc\n");
2626
2627 sdram_zqcl(&si);
2628 PRINTK_DEBUG("Done zqcl\n");
2629
2630 if (si.boot_path != BOOT_PATH_RESUME) {
2631 MCHBAR32(0x268) = MCHBAR32(0x268) | 0xc0000000;
2632 }
2633
2634 sdram_dradrb(&si);
2635 PRINTK_DEBUG("Done dradrb\n");
2636
2637 sdram_rcven(&si);
2638 PRINTK_DEBUG("Done rcven\n");
2639
2640 sdram_new_trd(&si);
2641 PRINTK_DEBUG("Done tRD\n");
2642
2643 sdram_mmap_regs(&si);
2644 PRINTK_DEBUG("Done mmap regs\n");
2645
2646 sdram_enhancedmode(&si);
2647 PRINTK_DEBUG("Done enhanced mode\n");
2648
2649 sdram_powersettings(&si);
2650 PRINTK_DEBUG("Done power settings\n");
2651
2652 sdram_programddr();
2653 PRINTK_DEBUG("Done programming ddr\n");
2654
2655 sdram_programdqdqs(&si);
2656 PRINTK_DEBUG("Done programming dqdqs\n");
2657
2658 sdram_periodic_rcomp();
2659 PRINTK_DEBUG("Done periodic RCOMP\n");
2660
2661 /* Set init done */
2662 MCHBAR32(0x268) = MCHBAR32(0x268) | 0x40000000;
2663
2664 /* Tell ICH7 that we're done */
2665 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
2666 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8 & ~0x80);
2667
2668 /* Tell northbridge we're done */
2669 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf4);
2670 pci_write_config8(PCI_DEV(0,0,0), 0xf4, reg8 | 1);
2671
2672 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2673}