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