blob: a80aeacf8e0f5072c2605eba92e264165b0ab7f7 [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
112static int decode_spd(struct dimminfo *d)
113{
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
139 const char *ubso[] = { {"UB"}, {"SO"} };
140#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) {
308 err = decode_spd(&s->dimms[i]);
309 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
524 if(freq == MEM_CLOCK_800MHz) {
525 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;
825 reg32 = (u32) ((6 << 30) | (4 << 25) | (1 << 20) | (8 << 15) |
826 (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);
2060 gfxsize = ggc_to_uma[(ggc & 0xf0) >> 4];
2061 gttsize = ggc_to_gtt[(ggc & 0xc00) >> 8];
2062 tom = s->channel_capacity[0];
2063
2064 tsegsize = 0x1; // 1MB
2065 mmiosize = 0x400; // 1GB
2066
2067 reclaim = false;
2068 tolud = MIN(0x1000 - mmiosize, tom);
2069 if ((tom - tolud) > 0x40) {
2070 // reclaim = true;
2071 }
2072 if (reclaim) {
2073 tolud = tolud & ~0x3f;
2074 tom = tom & ~0x3f;
2075 reclaimbase = MAX(0x1000, tom);
2076 reclaimlimit = reclaimbase + (MIN(0x1000, tom) - tolud) - 0x40;
2077 }
2078 touud = tom;
2079 if (reclaim) {
2080 touud = reclaimlimit + 0x40;
2081 }
2082
2083 gfxbase = tolud - gfxsize;
2084 gttbase = gfxbase - gttsize;
2085 tsegbase = gttbase - tsegsize;
2086
2087 /* Program the regs */
2088 pci_write_config16(PCI_DEV(0,0,0), 0xb0, (u16)(tolud << 4));
2089 pci_write_config16(PCI_DEV(0,0,0), 0xa0, (u16)(tom >> 6));
2090 if (reclaim) {
2091 pci_write_config16(PCI_DEV(0,0,0), 0x98, (u16)(reclaimbase >> 6));
2092 pci_write_config16(PCI_DEV(0,0,0), 0x9a, (u16)(reclaimlimit >> 6));
2093 }
2094 pci_write_config16(PCI_DEV(0,0,0), 0xa2, (u16)(touud));
2095 pci_write_config32(PCI_DEV(0,0,0), 0xa4, gfxbase << 20);
2096 pci_write_config32(PCI_DEV(0,0,0), 0xa8, gttbase << 20);
2097 pci_write_config32(PCI_DEV(0,0,0), 0xac, tsegbase << 20);
2098}
2099
2100static void sdram_enhancedmode(struct sysinfo *s)
2101{
2102 u8 reg8, ch, r, j, i;
2103 u32 mask32, reg32;
2104 MCHBAR8(0x246) = MCHBAR8(0x246) | 1;
2105 MCHBAR8(0x269 + 3) = MCHBAR8(0x269 + 3) | 1;
2106 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
2107 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2108 MCHBAR32(0x120) = (MCHBAR32(0x120) & ~mask32) | reg32;
2109 MCHBAR8(0x288 + 1) = 0x2;
2110 MCHBAR16(0x288 + 2) = 0x0804;
2111 MCHBAR16(0x288 + 4) = 0x2010;
2112 MCHBAR8(0x288 + 6) = 0x40;
2113 MCHBAR16(0x288 + 8) = 0x091c;
2114 MCHBAR8(0x288 + 10) = 0xf2;
2115 MCHBAR8(0x241) = MCHBAR8(0x241) | 1;
2116 MCHBAR8(0x243) = MCHBAR8(0x243) | 1;
2117 MCHBAR16(0x272) = MCHBAR16(0x272) | 0x100;
2118
2119 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf0);
2120 pci_write_config8(PCI_DEV(0,0,0), 0xf0, reg8 | 1);
2121 MCHBAR32(0xfa0) = 0x00000002;
2122 MCHBAR32(0xfa4) = 0x20310002;
2123 MCHBAR32(0x24) = 0x02020302;
2124 MCHBAR32(0x30) = 0x001f1806;
2125 MCHBAR32(0x34) = 0x01102800;
2126 MCHBAR32(0x38) = 0x07000000;
2127 MCHBAR32(0x3c) = 0x01014010;
2128 MCHBAR32(0x40) = 0x0f038000;
2129 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf0);
2130 pci_write_config8(PCI_DEV(0,0,0), 0xf0, reg8 & ~1);
2131
2132 u32 nranks, curranksize, maxranksize, maxdra, dra;
2133 u8 rankmismatch, dramismatch;
2134 u8 drbtab[10] = { 0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8, 0x20, 0x10 };
2135
2136 nranks = 0;
2137 curranksize = 0;
2138 maxranksize = 0;
2139 maxdra = 0;
2140 rankmismatch = 0;
2141 dramismatch = 0;
2142 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2143 nranks++;
2144 dra = (u8) ((MCHBAR32(0x208) >> (8*r)) & 0x7f);
2145 curranksize = drbtab[dra];
2146 if (maxranksize == 0) {
2147 maxranksize = curranksize;
2148 maxdra = dra;
2149 }
2150 if (curranksize != maxranksize) {
2151 rankmismatch = 1;
2152 }
2153 if (dra != maxdra) {
2154 dramismatch = 1;
2155 }
2156 }
2157
2158 reg8 = 0;
2159 switch (nranks) {
2160 case 4:
2161 if (rankmismatch) {
2162 reg8 = 0x64;
2163 } else {
2164 reg8 = 0xa4;
2165 }
2166 break;
2167 case 1:
2168 case 3:
2169 reg8 = 0x64;
2170 break;
2171 case 2:
2172 if (rankmismatch) {
2173 reg8 = 0x64;
2174 } else {
2175 reg8 = 0x24;
2176 }
2177 break;
2178 default:
2179 die("Invalid number of ranks found, halt\n");
2180 break;
2181 }
2182 MCHBAR8(0x111) = (MCHBAR8(0x111) & ~0xfc) | (reg8 & 0xfc);
2183 MCHBAR32(0xd0) = MCHBAR32(0xd0) & ~0x80000000;
2184
2185 MCHBAR32(0x28) = 0xf;
2186 MCHBAR8(0x2c4) = MCHBAR8(0x2c4) | 1;
2187
2188 MCHBAR32(0x3c) = MCHBAR32(0x3c) & ~0xe000000;
2189 MCHBAR32(0x40) = (MCHBAR32(0x40) & ~0xc0000) | 0x40000;
2190 u32 clkcx[2][2][3] = {
2191 {
2192 {0, 0x0c080302, 0x08010204}, // 667
2193 {0x02040000, 0x08100102, 0}
2194 },
2195 {
2196 {0x18000000, 0x3021060c, 0x20010208},
2197 {0, 0x0c090306, 0} // 800
2198 }
2199 };
2200 j = s->selected_timings.fsb_clock;
2201 i = s->selected_timings.mem_clock;
2202
2203 MCHBAR32(0x708) = clkcx[j][i][0];
2204 MCHBAR32(0x70c) = clkcx[j][i][1];
2205 MCHBAR32(0x6dc) = clkcx[j][i][2];
2206 MCHBAR8(0x40) = MCHBAR8(0x40) & ~0x2;
2207}
2208
2209static void sdram_periodic_rcomp(void)
2210{
2211 MCHBAR8(0x130) = MCHBAR8(0x130) & ~0x2;
2212 while ((MCHBAR32(0x130) & 0x80000000) > 0) {
2213 ;
2214 }
2215 MCHBAR16(0x1b4) = (MCHBAR16(0x1b4) & ~0x3000);
2216
2217 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2218 MCHBAR16(0x170) = (MCHBAR16(0x170) & ~0xf) | 0x9;
2219
2220 MCHBAR8(0x130) = MCHBAR8(0x130) | 0x82;
2221}
2222
2223static void sdram_new_trd(struct sysinfo *s)
2224{
2225 u8 pidelay, i, j, k, cc, trd_perphase[5];
2226 u8 bypass, freqgb, trd, reg8, txfifo, cas;
2227 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2228 u16 tmclk, thclk, buffertocore, postcalib;
2229 u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2230 u16 trd_adjust[2][2][5] = {
2231 {
2232 {3000, 3000, 0,0,0},
2233 {1000,2000,3000,1500,2500}
2234 },
2235 {
2236 {2000,1000,3000,0,0},
2237 {2500, 2500, 0,0,0}
2238 }};
2239
2240 freqgb = 110;
2241 buffertocore = 5000;
2242 cas = s->selected_timings.CAS;
2243 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2244 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2245 tmclk = tmclk * 100 / freqgb;
2246 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2247 switch (s->selected_timings.mem_clock) {
2248 case MEM_CLOCK_667MHz:
2249 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2250 cc = 2;
2251 } else {
2252 cc = 3;
2253 }
2254 break;
2255 default:
2256 case MEM_CLOCK_800MHz:
2257 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2258 cc = 5;
2259 } else {
2260 cc = 2;
2261 }
2262 break;
2263 }
2264 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2265 maxrcvendelay = 0;
2266 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2267
2268 for (i = 0; i < 8; i++) {
2269 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 0x3) * (u32)(tmclk));
2270 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 0x3) * (u32)(tmclk) / 2);
2271 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 0x3) * (u32)(tmclk) / 4);
2272 rcvendelay += (u32)(pidelay * s->pi[i]);
2273 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2274 }
2275
2276 if ((MCHBAR8(0xc54+3) == 0xff) && (MCHBAR8(0xc08) & 0x80)) {
2277 bypass = 1;
2278 } else {
2279 bypass = 0;
2280 }
2281
2282 txfifo = 0;
2283 reg8 = (MCHBAR8(0x188) & 0xe) >> 1;
2284 txfifo = txfifo_lut[reg8] & 0x7;
2285
2286 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2287 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2288 if (s->async) {
2289 datadelay += tmclk / 2;
2290 }
2291
2292 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2293 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2294
2295 if (j == 0 && k == 0) {
2296 datadelay -= 3084;
2297 }
2298
2299 trd = 0;
2300 for (i = 0; i < cc; i++) {
2301 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2302 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2303 trd_perphase[i] += 1;
2304 if (trd_perphase[i] > trd) {
2305 trd = trd_perphase[i];
2306 }
2307 }
2308
2309 MCHBAR16(0x248) = (MCHBAR16(0x248) & ~0x1f00) | (trd << 8);
2310}
2311
2312static void sdram_powersettings(struct sysinfo *s)
2313{
2314 u8 j;
2315 u32 reg32;
2316
2317 /* Thermal sensor */
2318 MCHBAR8(0x3808) = 0x9b;
2319 MCHBAR32(0x380c) = (MCHBAR32(0x380c) & ~0x00ffffff) | 0x1d00;
2320 MCHBAR8(0x3814) = 0x08;
2321 MCHBAR8(0x3824) = 0x00;
2322 MCHBAR8(0x3809) = (MCHBAR8(0x3809) & ~0xf) | 0x4;
2323 MCHBAR8(0x3814) = (MCHBAR8(0x3814) & ~1) | 1;
2324 MCHBAR8(0x3812) = (MCHBAR8(0x3812) & ~0x80) | 0x80;
2325
2326 /* Clock gating */
2327 MCHBAR32(0xf18) = MCHBAR32(0xf18) & ~0x00040001;
2328 MCHBAR8(0xfac+3) = MCHBAR8(0xfac+3) & ~0x80;
2329 MCHBAR8(0xff8+3) = MCHBAR8(0xff8+3) & ~0x80;
2330 MCHBAR16(0xff0) = MCHBAR16(0xff0) & ~0x1fff;
2331 MCHBAR32(0xfb0) = MCHBAR32(0xfb0) & ~0x0001ffff;
2332 MCHBAR16(0x48) = (MCHBAR16(0x48) & ~0x03ff) & 0x6;
2333 MCHBAR32(0x20) = (MCHBAR32(0x20) & ~0xffffffff) | 0x20;
2334 MCHBAR8(0xd14) = MCHBAR8(0xd14) & ~1;
2335 MCHBAR8(0x239) = s->selected_timings.CAS - 1 + 0x15;
2336 MCHBAR16(0x2d1) = (MCHBAR16(0x2d1) & ~0x07fc) | 0x40;
2337 MCHBAR16(0x6d1) = (MCHBAR16(0x6d1) & ~0x0fff) | 0xd00;
2338 MCHBAR16(0x210) = MCHBAR16(0x210) & ~0x0d80;
2339 MCHBAR16(0xf6c+2) = 0xffff;
2340
2341 /* Sequencing */
2342 MCHBAR32(0x14) = (MCHBAR32(0x14) & ~0x1fffffff) | 0x1f643fff;
2343 MCHBAR32(0x18) = (MCHBAR32(0x18) & ~0xffffff7f) | 0x02010000;
2344 MCHBAR16(0x1c) = (MCHBAR16(0x1c) & ~0x7000) | (0x3 << 12);
2345
2346 /* Power */
2347 MCHBAR32(0x1104) = (MCHBAR32(0x1104) & ~0xffff0003) | 0x10100000;
2348 MCHBAR32(0x1108) = (MCHBAR32(0x1108) & ~0x0001bff7) | 0x00000078;
2349 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2350 MCHBAR16(0x110c) = (MCHBAR16(0x110c) & ~0x03ff) | 0xc8;
2351 } else {
2352 MCHBAR16(0x110c) = (MCHBAR16(0x110c) & ~0x03ff) | 0x100;
2353 }
2354 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2355
2356 MCHBAR32(0x1110) = (MCHBAR32(0x1110) & ~0x1fff37f) | 0x10810700;
2357 MCHBAR8(0x1114) = (MCHBAR8(0x1114) & ~0x07) | 1;
2358 MCHBAR8(0x1124) = MCHBAR8(0x1124) & ~0x02;
2359
2360 u16 ddr2lut[2][4][2] = {{
2361 {0x0000, 0x0000},
2362 {0x019A, 0x0039},
2363 {0x0099, 0x1049},
2364 {0x0000, 0x0000}
2365 },
2366 {
2367 {0x0000, 0x0000},
2368 {0x019A, 0x0039},
2369 {0x0099, 0x1049},
2370 {0x0099, 0x2159}
2371 }};
2372
2373 MCHBAR16(0x23c) = 0x7a89;
2374 MCHBAR8(0x117) = 0xaa;
2375 MCHBAR16(0x118) = ddr2lut[j][s->selected_timings.CAS - 3][1];
2376 MCHBAR16(0x115) = (MCHBAR16(0x115) & ~0x7fff) | ddr2lut[j]
2377 [s->selected_timings.CAS - 3][0];
2378 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0xf000) | 0xf000;
2379 MCHBAR8(0x2c02) = (MCHBAR8(0x2c02) & ~0x77) | (4 << 4 | 4);
2380 if (s->nodll) {
2381 reg32 = 0x30000000;
2382 } else {
2383 reg32 = 0;
2384 }
2385 MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0x0f000000) | 0x20000000 | reg32;
2386 MCHBAR32(0x2d1) = (MCHBAR32(0x2d1) & ~0x00f00000) | 0x00f00000;
2387 MCHBAR32(0x6d0) = (MCHBAR32(0x6d0) & ~0x001ff000) | (0xbf << 20);
2388 MCHBAR16(0x610) = (MCHBAR16(0x610) & ~0x1f7f) | (0xb << 8) | (7 << 4) | 0xb;
2389 MCHBAR16(0x612) = 0x3264;
2390 MCHBAR16(0x614) = (MCHBAR16(0x614) & ~0x3f3f) | (0x14 << 8) | 0xa;
2391
2392 MCHBAR32(0x6c0) = MCHBAR32(0x6c0) | 0x80002000;
2393}
2394
2395static void sdram_programddr(void)
2396{
2397 MCHBAR16(0x6d1) = (MCHBAR16(0x6d1) & ~0x03ff) | 0x100;
2398 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0x003f) | 0x10;
2399 MCHBAR16(0x2d1) = (MCHBAR16(0x2d1) & ~0x7000) | 0x2000;
2400 MCHBAR8(0x180) = MCHBAR8(0x180) & ~0xe;
2401 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0xc;
2402 MCHBAR8(0x561) = MCHBAR8(0x561) & ~0xe;
2403 MCHBAR8(0x565) = MCHBAR8(0x565) & ~0xe;
2404 MCHBAR8(0x569) = MCHBAR8(0x569) & ~0xe;
2405 MCHBAR8(0x56d) = MCHBAR8(0x56d) & ~0xe;
2406 MCHBAR8(0x571) = MCHBAR8(0x571) & ~0xe;
2407 MCHBAR8(0x575) = MCHBAR8(0x575) & ~0xe;
2408 MCHBAR8(0x579) = MCHBAR8(0x579) & ~0xe;
2409 MCHBAR8(0x57d) = MCHBAR8(0x57d) & ~0xe;
2410 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0x2;
2411 MCHBAR16(0x1b4) = MCHBAR16(0x1b4) & ~0x400;
2412 MCHBAR16(0x210) = MCHBAR16(0x210) & ~0xdc0;
2413 MCHBAR8(0x239) = MCHBAR8(0x239) & ~0x80;
2414 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~(1 << 22);
2415 MCHBAR16(0x2d1) = MCHBAR16(0x2d1) & ~0x80fc;
2416 MCHBAR16(0x6d1) = MCHBAR16(0x6d1) & ~0xc00;
2417 MCHBAR8(0x180) = MCHBAR8(0x180) & ~0xd;
2418 MCHBAR8(0x561) = MCHBAR8(0x561) & ~1;
2419 MCHBAR8(0x565) = MCHBAR8(0x565) & ~1;
2420 MCHBAR8(0x569) = MCHBAR8(0x569) & ~1;
2421 MCHBAR8(0x56d) = MCHBAR8(0x56d) & ~1;
2422 MCHBAR8(0x571) = MCHBAR8(0x571) & ~1;
2423 MCHBAR8(0x575) = MCHBAR8(0x575) & ~1;
2424 MCHBAR8(0x579) = MCHBAR8(0x579) & ~1;
2425 MCHBAR8(0x57d) = MCHBAR8(0x57d) & ~1;
2426 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0x700000) | (0x3 << 20);
2427 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~0x100000;
2428 MCHBAR8(0x592) = MCHBAR8(0x592) | 0x1e;
2429 MCHBAR8(0x2c15) = MCHBAR8(0x2c15) | 0x3;
2430 MCHBAR32(0x62c) = (MCHBAR32(0x62c) & ~0xc000000) | 0x4000000;
2431 MCHBAR16(0x248) = MCHBAR16(0x248) | 0x6000;
2432 MCHBAR32(0x260) = MCHBAR32(0x260) | 0x10000;
2433 MCHBAR8(0x2c0) = MCHBAR8(0x2c0) | 0x10;
2434 MCHBAR32(0x2d0) = MCHBAR32(0x2d0) | (0xf << 24);
2435 MCHBAR8(0x189) = MCHBAR8(0x189) | 0x7;
2436 MCHBAR8(0x592) = MCHBAR8(0x592) | 0xc0;
2437 MCHBAR8(0x124) = MCHBAR8(0x124) | 0x7;
2438 MCHBAR16(0x12a) = (MCHBAR16(0x12a) & ~0xffff) | 0x0080;
2439 MCHBAR8(0x12c) = (MCHBAR8(0x12c) & ~0xff) | 0x10;
2440 MCHBAR16(0x2c0) = MCHBAR16(0x2c0) | 0x1e0;
2441 MCHBAR8(0x189) = MCHBAR8(0x189) | 0x18;
2442 MCHBAR8(0x193) = MCHBAR8(0x193) | 0xd;
2443 MCHBAR16(0x212) = MCHBAR16(0x212) | 0xa3f;
2444 MCHBAR8(0x248) = MCHBAR8(0x248) | 0x3;
2445 MCHBAR8(0x268) = (MCHBAR8(0x268) & ~0xff) | 0x4a;
2446 MCHBAR8(0x2c4) = MCHBAR8(0x2c4) & ~0x60;
2447 MCHBAR16(0x592) = MCHBAR16(0x592) | 0x321;
2448}
2449
2450static void sdram_programdqdqs(struct sysinfo *s)
2451{
2452 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2453 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2454 u8 repeat, halfclk, feature, reg8, push;
2455 u16 cwb, pimdclk;
2456 u32 reg32;
2457 u8 txfifotab[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2458
2459 tpi = 3000;
2460 dqdqs_out = 4382;
2461 dqdqs_outdelay = 5083;
2462 dqdqs_delay = 4692;
2463 coretomcp = 0;
2464 txdelay = 0;
2465 halfclk = 0;
2466 tmaxunmask = 0;
2467 tmaxpi = 0;
2468 repeat = 2;
2469 feature = 0;
2470 cwb = 0;
2471 pimdclk = 0;
2472 reg32 = 0;
2473 push = 0;
2474 reg8 = 0;
2475
2476 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2477 refclk = 3000 - mdclk;
2478
2479 coretomcp = ((MCHBAR8(0x246) >> 2) & 0x3) + 1;
2480 coretomcp *= mdclk;
2481
2482 reg8 = (MCHBAR8(0x188) & 0xe) >> 1;
2483
2484 while (repeat) {
2485 txdelay = mdclk * (
2486 ((MCHBAR16(0x220) >> 8) & 0x7) +
2487 (MCHBAR8(0x24d) & 0xf) +
2488 (MCHBAR8(0x24e) & 0x1)
2489 ) +
2490 txfifotab[reg8]*(mdclk/2) +
2491 coretomcp +
2492 refclk +
2493 cwb;
2494 halfclk = (MCHBAR8(0x5d9) >> 1) & 0x1;
2495 if (halfclk) {
2496 txdelay -= mdclk / 2;
2497 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2498 } else {
2499 reg32 = dqdqs_outdelay + coretomcp;
2500 }
2501
2502 tmaxunmask = txdelay - mdclk - dqdqs_out;
2503 tmaxpi = tmaxunmask - tpi;
2504
2505 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2506 if (repeat == 2) {
2507 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~(1 << 23);
2508 }
2509 feature = 1;
2510 repeat = 0;
2511 } else {
2512 repeat--;
2513 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) | (1 << 23);
2514 cwb = 2 * mdclk;
2515 }
2516 }
2517
2518 if (!feature) {
2519 MCHBAR8(0x2d1) = MCHBAR8(0x2d1) & ~0x3;
2520 return;
2521 }
2522 MCHBAR8(0x2d1) = MCHBAR8(0x2d1) | 0x3;
2523 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0xf000) | (pimdclk << 12);
2524 MCHBAR8(0x2c02) = (MCHBAR8(0x2c02) & ~0x77) | (push << 4) | push;
2525 MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0xf000000) | 0x3000000;
2526}
2527
2528/**
2529 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2530 */
2531void sdram_initialize(int boot_path, const u8 *spd_addresses)
2532{
2533 struct sysinfo si;
2534 u8 reg8;
2535
2536 PRINTK_DEBUG("Setting up RAM controller.\n");
2537
2538 memset(&si, 0, sizeof(si));
2539
2540 si.boot_path = boot_path;
2541 si.spd_map[0] = spd_addresses[0];
2542 si.spd_map[1] = spd_addresses[1];
2543 si.spd_map[2] = spd_addresses[2];
2544 si.spd_map[3] = spd_addresses[3];
2545
2546 sdram_read_spds(&si);
2547
2548 /* Choose Common Frequency */
2549 sdram_detect_ram_speed(&si);
2550
2551 /* Determine smallest common tRAS, tRP, tRCD, etc */
2552 sdram_detect_smallest_params(&si);
2553
2554 /* Enable HPET */
2555 enable_hpet();
2556 hpet_udelay(300000);
2557
2558 MCHBAR16(0xc1c) = MCHBAR16(0xc1c) | (1 << 15);
2559
2560 hpet_udelay(100000);
2561
2562 sdram_clk_crossing(&si);
2563
2564 sdram_checkreset();
2565 PRINTK_DEBUG("Done checkreset\n");
2566
2567 sdram_clkmode(&si);
2568 PRINTK_DEBUG("Done clkmode\n");
2569
2570 sdram_timings(&si);
2571 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2572
2573 sdram_dlltiming(&si);
2574 PRINTK_DEBUG("Done dlltiming\n");
2575
2576 hpet_udelay(200000);
2577
2578 sdram_rcomp(&si);
2579 PRINTK_DEBUG("Done RCOMP\n");
2580
2581 sdram_odt(&si);
2582 PRINTK_DEBUG("Done odt\n");
2583
2584 while ((MCHBAR8(0x130) & 0x1) != 0);
2585
2586 sdram_mmap(&si);
2587 PRINTK_DEBUG("Done mmap\n");
2588
2589 // Enable DDR IO buffer
2590 MCHBAR8(0x5dd) = (MCHBAR8(0x5dd) & ~0x3f) | 0x8;
2591 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x1;
2592
2593 sdram_rcompupdate(&si);
2594 PRINTK_DEBUG("Done RCOMP update\n");
2595
2596 MCHBAR8(0x40) = MCHBAR8(0x40) | 0x2;
2597
2598 if (si.boot_path != BOOT_PATH_RESUME) {
2599 MCHBAR32(0x260) = MCHBAR32(0x260) | (1 << 27);
2600 }
2601
2602 sdram_jedecinit(&si);
2603 PRINTK_DEBUG("Done MRS\n");
2604
2605 sdram_misc(&si);
2606 PRINTK_DEBUG("Done misc\n");
2607
2608 sdram_zqcl(&si);
2609 PRINTK_DEBUG("Done zqcl\n");
2610
2611 if (si.boot_path != BOOT_PATH_RESUME) {
2612 MCHBAR32(0x268) = MCHBAR32(0x268) | 0xc0000000;
2613 }
2614
2615 sdram_dradrb(&si);
2616 PRINTK_DEBUG("Done dradrb\n");
2617
2618 sdram_rcven(&si);
2619 PRINTK_DEBUG("Done rcven\n");
2620
2621 sdram_new_trd(&si);
2622 PRINTK_DEBUG("Done tRD\n");
2623
2624 sdram_mmap_regs(&si);
2625 PRINTK_DEBUG("Done mmap regs\n");
2626
2627 sdram_enhancedmode(&si);
2628 PRINTK_DEBUG("Done enhanced mode\n");
2629
2630 sdram_powersettings(&si);
2631 PRINTK_DEBUG("Done power settings\n");
2632
2633 sdram_programddr();
2634 PRINTK_DEBUG("Done programming ddr\n");
2635
2636 sdram_programdqdqs(&si);
2637 PRINTK_DEBUG("Done programming dqdqs\n");
2638
2639 sdram_periodic_rcomp();
2640 PRINTK_DEBUG("Done periodic RCOMP\n");
2641
2642 /* Set init done */
2643 MCHBAR32(0x268) = MCHBAR32(0x268) | 0x40000000;
2644
2645 /* Tell ICH7 that we're done */
2646 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
2647 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8 & ~0x80);
2648
2649 /* Tell northbridge we're done */
2650 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf4);
2651 pci_write_config8(PCI_DEV(0,0,0), 0xf4, reg8 | 1);
2652
2653 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2654}