3rdparty/fsp: Update submodule to upstream master
[coreboot2.git] / src / northbridge / intel / pineview / raminit.c
blobdbc373d1fb87a88b66af9d2b23a392cc4a30373e
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <cf9_reset.h>
4 #include <device/mmio.h>
5 #include <device/pci_ops.h>
6 #include <device/smbus_host.h>
7 #include <commonlib/helpers.h>
8 #include <console/console.h>
9 #include <delay.h>
10 #include <lib.h>
11 #include <southbridge/intel/common/hpet.h>
12 #include "pineview.h"
13 #include "raminit.h"
14 #include <spd.h>
15 #include <string.h>
17 /* Debugging macros */
18 #if CONFIG(DEBUG_RAM_SETUP)
19 #define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
20 #else
21 #define PRINTK_DEBUG(x...)
22 #endif
24 #define MAX_TCLK_667 0x30
25 #define MAX_TCLK_800 0x25
26 #define MAX_TAC_667 0x45
27 #define MAX_TAC_800 0x40
29 #define NOP_CMD (1 << 1)
30 #define PRE_CHARGE_CMD (1 << 2)
31 #define MRS_CMD ((1 << 2) | (1 << 1))
32 #define EMRS_CMD (1 << 3)
33 #define EMRS1_CMD (EMRS_CMD | (1 << 4))
34 #define EMRS2_CMD (EMRS_CMD | (1 << 5))
35 #define EMRS3_CMD (EMRS_CMD | (1 << 5) | (1 << 4))
36 #define ZQCAL_CMD ((1 << 3) | (1 << 1))
37 #define CBR_CMD ((1 << 3) | (1 << 2))
38 #define NORMAL_OP_CMD ((1 << 3) | (1 << 2) | (1 << 1))
40 #define UBDIMM 1
41 #define SODIMM 2
43 #define TOTAL_CHANNELS 1
44 #define TOTAL_DIMMS 2
46 #define DIMM_IS_POPULATED(dimms, idx) (dimms[idx].card_type != 0)
47 #define IF_DIMM_POPULATED(dimms, idx) if (dimms[idx].card_type != 0)
48 #define ONLY_DIMMA_IS_POPULATED(dimms, ch) (\
49 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
50 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3)))
51 #define ONLY_DIMMB_IS_POPULATED(dimms, ch) (\
52 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3) && \
53 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2)))
54 #define BOTH_DIMMS_ARE_POPULATED(dimms, ch) (\
55 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
56 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3))))
57 #define FOR_EACH_DIMM(idx) \
58 for (idx = 0; idx < TOTAL_DIMMS; ++idx)
59 #define FOR_EACH_POPULATED_DIMM(dimms, idx) \
60 FOR_EACH_DIMM(idx) IF_DIMM_POPULATED(dimms, idx)
61 #define CHANNEL_IS_POPULATED(dimms, idx) ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0))
62 #define CHANNEL_IS_CARDF(dimms, idx) ((dimms[idx<<1].card_type == 0xf) || (dimms[(idx<<1) + 1].card_type == 0xf))
63 #define IF_CHANNEL_POPULATED(dimms, idx) if ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0))
64 #define FOR_EACH_CHANNEL(idx) \
65 for (idx = 0; idx < TOTAL_CHANNELS; ++idx)
66 #define FOR_EACH_POPULATED_CHANNEL(dimms, idx) \
67 FOR_EACH_CHANNEL(idx) IF_CHANNEL_POPULATED(dimms, idx)
69 #define RANKS_PER_CHANNEL 4
71 #define FOR_EACH_RANK_IN_CHANNEL(r) \
72 for (r = 0; r < RANKS_PER_CHANNEL; ++r)
73 #define FOR_EACH_POPULATED_RANK_IN_CHANNEL(dimms, ch, r) \
74 FOR_EACH_RANK_IN_CHANNEL(r) if (rank_is_populated(dimms, ch, r))
75 #define FOR_EACH_RANK(ch, r) \
76 FOR_EACH_CHANNEL(ch) FOR_EACH_RANK_IN_CHANNEL(r)
77 #define FOR_EACH_POPULATED_RANK(dimms, ch, r) \
78 FOR_EACH_RANK(ch, r) if (rank_is_populated(dimms, ch, r))
80 static bool rank_is_populated(struct dimminfo dimms[], u8 ch, u8 r)
82 return ((dimms[ch<<1].card_type && ((r) < dimms[ch<<1].ranks))
83 || (dimms[(ch<<1) + 1].card_type
84 && ((r) >= 2)
85 && ((r) < (dimms[(ch<<1) + 1].ranks + 2))));
88 static inline void barrier(void)
90 __asm__ __volatile__("": : :"memory");
93 static int decode_spd(struct dimminfo *d, int i)
95 d->type = 0;
96 if (d->spd_data[20] == 0x2) {
97 d->type = UBDIMM;
98 } else if (d->spd_data[20] == 0x4) {
99 d->type = SODIMM;
101 d->sides = (d->spd_data[5] & 0x7) + 1;
102 d->banks = (d->spd_data[17] >> 2) - 1;
103 d->chip_capacity = d->banks;
104 d->rows = d->spd_data[3];// - 12;
105 d->cols = d->spd_data[4];// - 9;
106 d->cas_latencies = 0x78;
107 d->cas_latencies &= d->spd_data[18];
108 if (d->cas_latencies == 0)
109 d->cas_latencies = 7;
110 d->tAAmin = d->spd_data[26];
111 d->tCKmin = d->spd_data[25];
112 d->width = (d->spd_data[13] >> 3) - 1;
113 d->page_size = (d->width+1) * (1 << d->cols); // Bytes
114 d->tRAS = d->spd_data[30];
115 d->tRP = d->spd_data[27];
116 d->tRCD = d->spd_data[29];
117 d->tWR = d->spd_data[36];
118 d->ranks = d->sides; // XXX
119 #if CONFIG(DEBUG_RAM_SETUP)
120 const char *ubso[2] = { "UB", "SO" };
121 #endif
122 PRINTK_DEBUG("%s-DIMM %d\n", &ubso[d->type][0], i);
123 PRINTK_DEBUG(" Sides : %d\n", d->sides);
124 PRINTK_DEBUG(" Banks : %d\n", d->banks);
125 PRINTK_DEBUG(" Ranks : %d\n", d->ranks);
126 PRINTK_DEBUG(" Rows : %d\n", d->rows);
127 PRINTK_DEBUG(" Cols : %d\n", d->cols);
128 PRINTK_DEBUG(" Page size : %d\n", d->page_size);
129 PRINTK_DEBUG(" Width : %d\n", (d->width + 1) * 8);
131 return 0;
135 * RAM Config: DIMMB-DIMMA
136 * 0 EMPTY-EMPTY
137 * 1 EMPTY-x16SS
138 * 2 EMPTY-x16DS
139 * 3 x16SS-x16SS
140 * 4 x16DS-x16DS
141 * 5 EMPTY- x8DS
142 * 6 x8DS - x8DS
144 static void find_ramconfig(struct sysinfo *s, u32 chan)
146 if (s->dimms[chan>>1].sides == 0) {
147 // NC
148 if (s->dimms[(chan>>1) + 1].sides == 0) {
149 // NC/NC
150 s->dimm_config[chan] = 0;
151 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
152 // NC/{8,16}SS
153 s->dimm_config[chan] = 1;
154 } else {
155 // NC/DS
156 if (s->dimms[(chan>>1) + 1].width == 0) {
157 // NC/8DS
158 s->dimm_config[chan] = 5;
159 } else {
160 // NC/16DS
161 s->dimm_config[chan] = 2;
164 } else if (s->dimms[chan>>1].sides == 1) {
165 // SS
166 if (s->dimms[(chan>>1) + 1].sides == 0) {
167 // {8,16}SS/NC
168 s->dimm_config[chan] = 1;
169 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
170 // SS/SS
171 if (s->dimms[chan>>1].width == 0) {
172 if (s->dimms[(chan>>1) + 1].width == 0) {
173 // 8SS/8SS
174 s->dimm_config[chan] = 3;
175 } else {
176 // 8SS/16SS
177 die("Mixed Not supported\n");
179 } else {
180 if (s->dimms[(chan>>1) + 1].width == 0) {
181 // 16SS/8SS
182 die("Mixed Not supported\n");
183 } else {
184 // 16SS/16SS
185 s->dimm_config[chan] = 3;
188 } else {
189 // {8,16}SS/8DS
190 die("Mixed Not supported\n");
192 } else {
193 // DS
194 if (s->dimms[(chan>>1) + 1].sides == 0) {
195 // DS/NC
196 if (s->dimms[chan>>1].width == 0) {
197 // 8DS/NC
198 s->dimm_config[chan] = 5;
199 } else {
200 s->dimm_config[chan] = 4;
202 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
203 // 8DS/{8,16}SS
204 if (s->dimms[chan>>1].width == 0) {
205 die("Mixed Not supported\n");
206 } else {
207 if (s->dimms[(chan>>1) + 1].width == 0) {
208 die("Mixed Not supported\n");
209 } else {
210 // 16DS/16DS
211 s->dimm_config[chan] = 4;
214 } else {
215 // DS/DS
216 if (s->dimms[chan>>1].width == 0 && s->dimms[(chan>>1)+1].width == 0) {
217 // 8DS/8DS
218 s->dimm_config[chan] = 6;
224 static void sdram_read_spds(struct sysinfo *s)
226 u8 i, chan;
227 s->dt0mode = 0;
228 FOR_EACH_DIMM(i) {
229 if (i2c_eeprom_read(s->spd_map[i], 0, 64, s->dimms[i].spd_data) != 64)
230 s->dimms[i].card_type = 0;
232 s->dimms[i].card_type = s->dimms[i].spd_data[62] & 0x1f;
233 hexdump(s->dimms[i].spd_data, 64);
236 s->spd_type = 0;
237 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
238 switch (s->dimms[i].spd_data[2]) {
239 case 0x8:
240 s->spd_type = DDR2;
241 break;
242 case 0xb:
243 default:
244 die("DIMM type mismatch\n");
245 break;
249 int err = 1;
250 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
251 err = decode_spd(&s->dimms[i], i);
252 s->dt0mode |= (s->dimms[i].spd_data[49] & 0x2) >> 1;
254 if (err) {
255 die("No memory dimms, halt\n");
258 FOR_EACH_POPULATED_CHANNEL(s->dimms, chan) {
259 find_ramconfig(s, chan);
260 PRINTK_DEBUG(" Config[CH%d] : %d\n", chan, s->dimm_config[chan]);
264 #if CONFIG(DEBUG_RAM_SETUP)
265 static u32 fsb_reg_to_mhz(u32 speed)
267 return (speed * 133) + 667;
270 static u32 ddr_reg_to_mhz(u32 speed)
272 return (speed == 0) ? 667 : (speed == 1) ? 800 : 0;
274 #endif
276 // Return the position of the least significant set bit, 0-indexed.
277 // 0 does not have a lsb, so return -1 for error.
278 static int lsbpos(u8 val)
280 for (int i = 0; i < 8; i++)
281 if (val & (1 << i))
282 return i;
283 return -1;
286 // Return the position of the most significant set bit, 0-indexed.
287 // 0 does not have a msb, so return -1 for error.
288 static int msbpos(u8 val)
290 for (int i = 7; i >= 0; i--)
291 if (val & (1 << i))
292 return i;
293 return -1;
296 static void sdram_detect_smallest_params(struct sysinfo *s)
298 static const u16 mult[6] = {
299 3000, // 667
300 2500, // 800
303 u8 i;
304 u32 maxtras = 0;
305 u32 maxtrp = 0;
306 u32 maxtrcd = 0;
307 u32 maxtwr = 0;
308 u32 maxtrfc = 0;
309 u32 maxtwtr = 0;
310 u32 maxtrrd = 0;
311 u32 maxtrtp = 0;
313 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
314 maxtras = MAX(maxtras, (s->dimms[i].spd_data[30] * 1000));
315 maxtrp = MAX(maxtrp, (s->dimms[i].spd_data[27] * 1000) >> 2);
316 maxtrcd = MAX(maxtrcd, (s->dimms[i].spd_data[29] * 1000) >> 2);
317 maxtwr = MAX(maxtwr, (s->dimms[i].spd_data[36] * 1000) >> 2);
318 maxtrfc = MAX(maxtrfc, (s->dimms[i].spd_data[42] * 1000) +
319 (s->dimms[i].spd_data[40] & 0xf));
320 maxtwtr = MAX(maxtwtr, (s->dimms[i].spd_data[37] * 1000) >> 2);
321 maxtrrd = MAX(maxtrrd, (s->dimms[i].spd_data[28] * 1000) >> 2);
322 maxtrtp = MAX(maxtrtp, (s->dimms[i].spd_data[38] * 1000) >> 2);
325 * TODO: on DDR3 there might be some minimal required values for some
326 * Timings: MIN_TRAS = 9, MIN_TRP = 3, MIN_TRCD = 3, MIN_TWR = 3,
327 * MIN_TWTR = 4, MIN_TRRD = 2, MIN_TRTP = 4
329 s->selected_timings.tRAS = MIN(24, DIV_ROUND_UP(maxtras,
330 mult[s->selected_timings.mem_clock]));
331 s->selected_timings.tRP = MIN(10, DIV_ROUND_UP(maxtrp,
332 mult[s->selected_timings.mem_clock]));
333 s->selected_timings.tRCD = MIN(10, DIV_ROUND_UP(maxtrcd,
334 mult[s->selected_timings.mem_clock]));
335 s->selected_timings.tWR = MIN(15, DIV_ROUND_UP(maxtwr,
336 mult[s->selected_timings.mem_clock]));
337 /* Needs to be even */
338 s->selected_timings.tRFC = 0xfe & (MIN(78, DIV_ROUND_UP(maxtrfc,
339 mult[s->selected_timings.mem_clock])) + 1);
340 s->selected_timings.tWTR = MIN(15, DIV_ROUND_UP(maxtwtr,
341 mult[s->selected_timings.mem_clock]));
342 s->selected_timings.tRRD = MIN(15, DIV_ROUND_UP(maxtrrd,
343 mult[s->selected_timings.mem_clock]));
344 s->selected_timings.tRTP = MIN(15, DIV_ROUND_UP(maxtrtp,
345 mult[s->selected_timings.mem_clock]));
347 PRINTK_DEBUG("Selected timings:\n");
348 PRINTK_DEBUG("\tFSB: %dMHz\n", fsb_reg_to_mhz(s->selected_timings.fsb_clock));
349 PRINTK_DEBUG("\tDDR: %dMHz\n", ddr_reg_to_mhz(s->selected_timings.mem_clock));
351 PRINTK_DEBUG("\tCAS: %d\n", s->selected_timings.CAS);
352 PRINTK_DEBUG("\ttRAS: %d\n", s->selected_timings.tRAS);
353 PRINTK_DEBUG("\ttRP: %d\n", s->selected_timings.tRP);
354 PRINTK_DEBUG("\ttRCD: %d\n", s->selected_timings.tRCD);
355 PRINTK_DEBUG("\ttWR: %d\n", s->selected_timings.tWR);
356 PRINTK_DEBUG("\ttRFC: %d\n", s->selected_timings.tRFC);
357 PRINTK_DEBUG("\ttWTR: %d\n", s->selected_timings.tWTR);
358 PRINTK_DEBUG("\ttRRD: %d\n", s->selected_timings.tRRD);
359 PRINTK_DEBUG("\ttRTP: %d\n", s->selected_timings.tRTP);
362 static void sdram_detect_ram_speed(struct sysinfo *s)
364 u8 cas, reg8;
365 u32 reg32;
366 u32 freq = 0;
367 u32 fsb = 0;
368 u8 i;
369 u8 commoncas = 0;
370 u8 highcas = 0;
371 u8 lowcas = 0;
373 // Core frequency
374 fsb = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0x70) >> 4;
375 if (fsb) {
376 fsb = 5 - fsb;
377 } else {
378 fsb = FSB_CLOCK_800MHz;
381 // DDR frequency
382 freq = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0x80) >> 7;
383 freq |= (pci_read_config8(HOST_BRIDGE, 0xe4) & 0x03) << 1;
384 if (freq) {
385 freq = 6 - freq;
386 } else {
387 freq = MEM_CLOCK_800MHz;
390 // Detect a common CAS latency
391 commoncas = 0xff;
392 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
393 commoncas &= s->dimms[i].spd_data[18];
395 if (commoncas == 0) {
396 die("No common CAS among dimms\n");
399 // commoncas is nonzero, so these calls will not error
400 u8 msbp = (u8)msbpos(commoncas);
401 u8 lsbp = (u8)lsbpos(commoncas);
403 // Start with fastest common CAS
404 cas = 0;
405 highcas = msbp;
406 lowcas = MAX(lsbp, 5);
408 while (cas == 0 && highcas >= lowcas) {
409 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
410 switch (freq) {
411 case MEM_CLOCK_800MHz:
412 if ((s->dimms[i].spd_data[9] > 0x25) ||
413 (s->dimms[i].spd_data[10] > 0x40)) {
414 // CAS too fast, lower it
415 highcas--;
416 break;
417 } else {
418 cas = highcas;
420 break;
421 case MEM_CLOCK_667MHz:
422 default:
423 if ((s->dimms[i].spd_data[9] > 0x30) ||
424 (s->dimms[i].spd_data[10] > 0x45)) {
425 // CAS too fast, lower it
426 highcas--;
427 break;
428 } else {
429 cas = highcas;
431 break;
435 if (highcas < lowcas) {
436 // Timings not supported by MCH, lower the frequency
437 if (freq == MEM_CLOCK_800MHz) {
438 freq--;
439 PRINTK_DEBUG("Run DDR clock speed reduced due to timings\n");
440 } else {
441 die("Timings not supported by MCH\n");
443 cas = 0;
444 highcas = msbp;
445 lowcas = lsbp;
446 while (cas == 0 && highcas >= lowcas) {
447 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
448 if ((s->dimms[i].spd_data[9] > 0x30) ||
449 (s->dimms[i].spd_data[10] > 0x45)) {
450 // CAS too fast, lower it
451 highcas--;
452 } else {
453 cas = highcas;
457 if (cas == 0) {
458 die("Unsupported dimms\n");
462 s->selected_timings.CAS = cas;
463 s->selected_timings.mem_clock = freq;
464 s->selected_timings.fsb_clock = fsb;
466 PRINTK_DEBUG("Drive Memory at %dMHz with CAS = %d clocks\n",
467 ddr_reg_to_mhz(s->selected_timings.mem_clock), s->selected_timings.CAS);
469 // Set memory frequency
470 if (s->boot_path == BOOT_PATH_RESET)
471 return;
473 mchbar_setbits32(PMSTS, 1 << 0);
475 reg32 = (mchbar_read32(CLKCFG) & ~0x70) | (1 << 10);
476 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
477 reg8 = 3;
478 } else {
479 reg8 = 2;
481 reg32 |= reg8 << 4;
482 mchbar_write32(CLKCFG, reg32);
484 s->selected_timings.mem_clock = ((mchbar_read32(CLKCFG) >> 4) & 0x7) - 2;
485 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
486 PRINTK_DEBUG("MCH validated at 800MHz\n");
487 s->nodll = 0;
488 s->maxpi = 63;
489 s->pioffset = 0;
490 } else if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
491 PRINTK_DEBUG("MCH validated at 667MHz\n");
492 s->nodll = 1;
493 s->maxpi = 15;
494 s->pioffset = 1;
495 } else {
496 PRINTK_DEBUG("MCH set to unknown (%02x)\n",
497 (uint8_t)s->selected_timings.mem_clock & 0xff);
501 static void sdram_clk_crossing(struct sysinfo *s)
503 u8 ddr_freq, fsb_freq;
504 static const u32 clkcross[2][2][4] = {
506 {0xffffffff, 0x05030305, 0x0000ffff, 0x00000000}, /* FSB = 667, DDR = 667 */
507 {0x1f1f1f1f, 0x2a1f1fa5, 0x00000000, 0x05000002}, /* FSB = 667, DDR = 800 */
510 {0x1f1f1f1f, 0x0d07070b, 0x00000000, 0x00000000}, /* FSB = 800, DDR = 667 */
511 {0xffffffff, 0x05030305, 0x0000ffff, 0x00000000}, /* FSB = 800, DDR = 800 */
515 ddr_freq = s->selected_timings.mem_clock;
516 fsb_freq = s->selected_timings.fsb_clock;
518 mchbar_write32(HMCCMP, clkcross[fsb_freq][ddr_freq][0]);
519 mchbar_write32(HMDCMP, clkcross[fsb_freq][ddr_freq][1]);
520 mchbar_write32(HMBYPCP, clkcross[fsb_freq][ddr_freq][2]);
521 mchbar_write32(HMCCPEXT, 0);
522 mchbar_write32(HMDCPEXT, clkcross[fsb_freq][ddr_freq][3]);
524 mchbar_setbits32(HMCCMC, 1 << 7);
526 if ((fsb_freq == 0) && (ddr_freq == 1)) {
527 mchbar_write8(CLKXSSH2MCBYPPHAS, 0);
528 mchbar_write32(CLKXSSH2MD, 0);
529 mchbar_write32(CLKXSSH2MD + 4, 0);
532 static const u32 clkcross2[2][2][8] = {
534 { // FSB = 667, DDR = 667
535 0x00000000, 0x08010204, 0x00000000, 0x08010204,
536 0x00000000, 0x00000000, 0x00000000, 0x04080102,
538 { // FSB = 667, DDR = 800
539 0x04080000, 0x10010002, 0x10000000, 0x20010208,
540 0x00000000, 0x00000004, 0x02040000, 0x08100102,
544 { // FSB = 800, DDR = 667
545 0x10000000, 0x20010208, 0x04080000, 0x10010002,
546 0x00000000, 0x00000000, 0x08000000, 0x10200204,
548 { // FSB = 800, DDR = 800
549 0x00000000, 0x08010204, 0x00000000, 0x08010204,
550 0x00000000, 0x00000000, 0x00000000, 0x04080102,
555 mchbar_write32(CLKXSSH2MCBYP, clkcross2[fsb_freq][ddr_freq][0]);
556 mchbar_write32(CLKXSSH2MCRDQ, clkcross2[fsb_freq][ddr_freq][0]);
557 mchbar_write32(CLKXSSH2MCRDCST, clkcross2[fsb_freq][ddr_freq][0]);
558 mchbar_write32(CLKXSSH2MCBYP + 4, clkcross2[fsb_freq][ddr_freq][1]);
559 mchbar_write32(CLKXSSH2MCRDQ + 4, clkcross2[fsb_freq][ddr_freq][1]);
560 mchbar_write32(CLKXSSH2MCRDCST + 4, clkcross2[fsb_freq][ddr_freq][1]);
561 mchbar_write32(CLKXSSMC2H, clkcross2[fsb_freq][ddr_freq][2]);
562 mchbar_write32(CLKXSSMC2H + 4, clkcross2[fsb_freq][ddr_freq][3]);
563 mchbar_write32(CLKXSSMC2HALT, clkcross2[fsb_freq][ddr_freq][4]);
564 mchbar_write32(CLKXSSMC2HALT + 4, clkcross2[fsb_freq][ddr_freq][5]);
565 mchbar_write32(CLKXSSH2X2MD, clkcross2[fsb_freq][ddr_freq][6]);
566 mchbar_write32(CLKXSSH2X2MD + 4, clkcross2[fsb_freq][ddr_freq][7]);
569 static void sdram_clkmode(struct sysinfo *s)
571 u8 ddr_freq;
572 u16 mpll_ctl;
574 mchbar_clrbits16(CSHRMISCCTL1, 1 << 8);
575 mchbar_clrbits8(CSHRMISCCTL1, 0x3f);
577 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
578 ddr_freq = 0;
579 mpll_ctl = 1;
580 } else {
581 ddr_freq = 1;
582 mpll_ctl = (1 << 8) | (1 << 5);
584 if (s->boot_path != BOOT_PATH_RESET)
585 mchbar_clrsetbits16(MPLLCTL, 0x033f, mpll_ctl);
587 mchbar_write32(C0GNT2LNCH1, 0x58001117);
588 mchbar_setbits32(C0STATRDCTRL, 1 << 23);
590 const u32 cas_to_reg[2][4] = {
591 {0x00000000, 0x00030100, 0x0c240201, 0x00000000}, /* DDR = 667 */
592 {0x00000000, 0x00030100, 0x0c240201, 0x10450302} /* DDR = 800 */
595 mchbar_write32(C0GNT2LNCH2, cas_to_reg[ddr_freq][s->selected_timings.CAS - 3]);
598 static void sdram_timings(struct sysinfo *s)
600 u8 i, j, ch, r, ta1, ta2, ta3, ta4, trp, bank, page, flag;
601 u8 reg8, wl;
602 u16 reg16;
603 u32 reg32, reg2;
605 static const u8 pagetab[2][2] = {
606 {0x0e, 0x12},
607 {0x10, 0x14},
610 /* Only consider DDR2 */
611 wl = s->selected_timings.CAS - 1;
612 ta1 = ta2 = 6;
613 ta3 = s->selected_timings.CAS;
614 ta4 = 8;
615 s->selected_timings.tRFC = (s->selected_timings.tRFC + 1) & 0xfe;
616 trp = 0;
617 bank = 1;
618 page = 0;
620 mchbar_write8(C0LATCTRL, (wl - 3) << 4 | (s->selected_timings.CAS - 3));
622 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
623 i = ch << 1;
624 if (s->dimms[i].banks == 1) {
625 trp = 1;
626 bank = 0;
628 if (s->dimms[i].page_size == 2048) {
629 page = 1;
632 PRINTK_DEBUG("trp=%d bank=%d page=%d\n",trp, bank, page);
634 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
635 flag = 0;
636 } else {
637 flag = 1;
640 mchbar_setbits8(C0PVCFG, 3);
641 mchbar_write16(C0CYCTRKPCHG, (wl + 4 + s->selected_timings.tWR) << 6 |
642 (2 + MAX(s->selected_timings.tRTP, 2)) << 2 | 1);
644 reg32 = (bank << 21) | (s->selected_timings.tRRD << 17) |
645 (s->selected_timings.tRP << 13) | ((s->selected_timings.tRP + trp) << 9) |
646 s->selected_timings.tRFC;
648 if (bank == 0) {
649 reg32 |= (pagetab[flag][page] << 22);
651 /* FIXME: Why not do a single dword write? */
652 mchbar_write16(C0CYCTRKACT + 0, (u16)(reg32));
653 mchbar_write16(C0CYCTRKACT + 2, (u16)(reg32 >> 16));
655 /* FIXME: Only applies to DDR2 */
656 reg16 = (mchbar_read16(C0CYCTRKACT + 2) & 0x0fc0) >> 6;
657 mchbar_clrsetbits16(SHCYCTRKCKEL, 0x3f << 7, reg16 << 7);
659 reg16 = (s->selected_timings.tRCD << 12) | (4 << 8) | (ta2 << 4) | ta4;
660 mchbar_write16(C0CYCTRKWR, reg16);
662 reg32 = (s->selected_timings.tRCD << 17) | ((wl + 4 + s->selected_timings.tWTR) << 12) |
663 (ta3 << 8) | (4 << 4) | ta1;
664 mchbar_write32(C0CYCTRKRD, reg32);
666 reg16 = ((s->selected_timings.tRP + trp) << 9) | s->selected_timings.tRFC;
668 /* FIXME: Why not do a single word write? */
669 mchbar_write8(C0CYCTRKREFR + 0, (u8)(reg16));
670 mchbar_write8(C0CYCTRKREFR + 1, (u8)(reg16 >> 8));
672 mchbar_clrsetbits16(C0CKECTRL, 0x1ff << 1, 100 << 1);
673 mchbar_clrsetbits8(C0CYCTRKPCHG2, 0x3f, s->selected_timings.tRAS);
674 mchbar_write16(C0ARBCTRL, 0x2310);
675 mchbar_clrsetbits8(C0ADDCSCTRL, 0x1f, 1);
677 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
678 reg32 = 3000;
679 } else {
680 reg32 = 2500;
682 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
683 reg2 = 6000;
684 } else {
685 reg2 = 5000;
687 reg16 = (u16)((((s->selected_timings.CAS + 7) * (reg32)) / reg2) << 8);
688 mchbar_clrsetbits16(C0STATRDCTRL, 0x1f << 8, reg16);
690 flag = 0;
691 if (wl > 2) {
692 flag = 1;
694 reg16 = (u8)(wl - 1 - flag);
695 reg16 |= reg16 << 4;
696 reg16 |= flag << 8;
697 mchbar_clrsetbits16(C0WRDATACTRL, 0x1ff, reg16);
699 mchbar_write16(C0RDQCTRL, 0x1585);
700 mchbar_clrbits8(C0PWLRCTRL, 0x1f);
702 /* rdmodwr_window[5..0] = CL+4+5 265[13..8] (264[21..16]) */
703 mchbar_clrsetbits16(C0PWLRCTRL, 0x3f << 8, (s->selected_timings.CAS + 9) << 8);
705 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
706 reg16 = 0x0514;
707 reg32 = 0x0a28;
708 } else {
709 reg16 = 0x0618;
710 reg32 = 0x0c30;
712 mchbar_clrsetbits32(C0REFRCTRL2, 0xfffff << 8, 0x3f << 22 | reg32 << 8);
714 /* FIXME: Is this weird access necessary? Reference code does it */
715 mchbar_write8(C0REFRCTRL + 3, 0);
716 mchbar_clrsetbits16(C0REFCTRL, 0x3fff, reg16);
718 /* NPUT Static Mode */
719 mchbar_setbits8(C0DYNRDCTRL, 1 << 0);
721 mchbar_clrsetbits32(C0STATRDCTRL, 0x7f << 24, 0xb << 25);
722 i = s->selected_timings.mem_clock;
723 j = s->selected_timings.fsb_clock;
724 if (i > j) {
725 mchbar_setbits32(C0STATRDCTRL, 1 << 24);
728 mchbar_clrbits8(C0RDFIFOCTRL, 3);
729 mchbar_clrsetbits16(C0WRDATACTRL, 0x1f << 10, (wl + 10) << 10);
730 mchbar_clrsetbits32(C0CKECTRL, 7 << 24 | 7 << 17, 3 << 24 | 3 << 17);
731 reg16 = 0x15 << 6;
732 reg16 |= 0x1f;
733 reg16 |= (0x6 << 12);
734 mchbar_clrsetbits16(C0REFRCTRL + 4, 0x7fff, reg16);
736 reg32 = (0x6 << 27) | (1 << 25); /* FIXME: For DDR3, set BIT26 as well */
737 mchbar_clrsetbits32(C0REFRCTRL2, 3 << 28, reg32 << 8);
738 mchbar_clrsetbits8(C0REFRCTRL + 3, 0xfa, reg32 >> 24);
739 mchbar_clrbits8(C0JEDEC, 1 << 7);
740 mchbar_clrbits8(C0DYNRDCTRL, 3 << 1);
742 /* Note: This is a 64-bit register, [34..30] = 0b00110 is split across two writes */
743 reg32 = ((6 & 3) << 30) | (4 << 25) | (1 << 20) | (8 << 15) | (6 << 10) | (4 << 5) | 1;
744 mchbar_write32(C0WRWMFLSH, reg32);
745 mchbar_clrsetbits16(C0WRWMFLSH + 4, 0x1ff, 8 << 3 | 6 >> 2);
746 mchbar_setbits16(SHPENDREG, 0x1c00 | 0x1f << 5);
748 /* FIXME: Why not do a single word write? */
749 mchbar_clrsetbits8(SHPAGECTRL, 0xff, 0x40);
750 mchbar_clrsetbits8(SHPAGECTRL + 1, 0x07, 0x05);
751 mchbar_setbits8(SHCMPLWRCMD, 0x1f);
753 reg8 = (3 << 6);
754 reg8 |= (s->dt0mode << 4);
755 reg8 |= 0x0c;
756 mchbar_clrsetbits8(SHBONUSREG, 0xdf, reg8);
757 mchbar_clrbits8(CSHRWRIOMLNS, 1 << 1);
758 mchbar_clrsetbits8(C0MISCTM, 0x07, 0x02);
759 mchbar_clrsetbits16(C0BYPCTRL, 0xff << 2, 4 << 2);
761 /* [31..29] = 0b010 for kN = 2 (2N) */
762 reg32 = (2 << 29) | (1 << 28) | (1 << 23);
763 mchbar_clrsetbits32(WRWMCONFIG, 0xffb << 20, reg32);
765 reg8 = (u8)((mchbar_read16(C0CYCTRKACT) & 0xe000) >> 13);
766 reg8 |= (u8)((mchbar_read16(C0CYCTRKACT + 2) & 1) << 3);
767 mchbar_clrsetbits8(BYPACTSF, 0xf << 4, reg8 << 4);
769 reg8 = (u8)((mchbar_read32(C0CYCTRKRD) & 0x000f0000) >> 17);
770 mchbar_clrsetbits8(BYPACTSF, 0xf, reg8);
772 /* FIXME: Why not clear everything at once? */
773 mchbar_clrbits8(BYPKNRULE, 0xfc);
774 mchbar_clrbits8(BYPKNRULE, 0x03);
775 mchbar_clrbits8(SHBONUSREG, 0x03);
776 mchbar_setbits8(C0BYPCTRL, 1 << 0);
777 mchbar_setbits16(CSHRMISCCTL1, 1 << 9);
779 for (i = 0; i < 8; i++) {
780 /* FIXME: Hardcoded for DDR2 SO-DIMMs */
781 mchbar_clrsetbits32(C0DLLRCVCTLy(i), 0x3f3f3f3f, 0x0c0c0c0c);
783 /* RDCS to RCVEN delay: Program coarse common to all bytelanes to default tCL + 1 */
784 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, (s->selected_timings.CAS + 1) << 16);
786 /* Program RCVEN delay with DLL-safe settings */
787 for (i = 0; i < 8; i++) {
788 mchbar_clrbits8(C0RXRCVyDLL(i), 0x3f);
789 mchbar_clrbits16(C0RCVMISCCTL2, 3 << (i * 2));
790 mchbar_clrbits16(C0RCVMISCCTL1, 3 << (i * 2));
791 mchbar_clrbits16(C0COARSEDLY0, 3 << (i * 2));
793 mchbar_clrbits8(C0DLLPIEN, 1 << 0); /* Power up receiver */
794 mchbar_setbits8(C0DLLPIEN, 1 << 1); /* Enable RCVEN DLL */
795 mchbar_setbits8(C0DLLPIEN, 1 << 2); /* Enable receiver DQS DLL */
796 mchbar_setbits32(C0COREBONUS, 0x000c0400);
797 mchbar_setbits32(C0CMDTX1, 1 << 31);
800 /* Program clkset0's register for Kcoarse, Tap, PI, DBEn and DBSel */
801 static void sdram_p_clkset0(const struct pllparam *pll, u8 f, u8 i)
803 mchbar_clrsetbits16(C0CKTX, 0xc440,
804 (pll->clkdelay[f][i] << 14) |
805 (pll->dben[f][i] << 10) |
806 (pll->dbsel[f][i] << 6));
808 mchbar_clrsetbits8(C0TXCK0DLL, 0x3f, pll->pi[f][i]);
811 /* Program clkset1's register for Kcoarse, Tap, PI, DBEn and DBSel */
812 static void sdram_p_clkset1(const struct pllparam *pll, u8 f, u8 i)
814 mchbar_clrsetbits32(C0CKTX, 0x00030880,
815 (pll->clkdelay[f][i] << 16) |
816 (pll->dben[f][i] << 11) |
817 (pll->dbsel[f][i] << 7));
819 mchbar_clrsetbits8(C0TXCK1DLL, 0x3f, pll->pi[f][i]);
822 /* Program CMD0 and CMD1 registers for Kcoarse, Tap, PI, DBEn and DBSel */
823 static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
825 u8 reg8;
826 /* Clock Group Index 3 */
827 reg8 = pll->dbsel[f][i] << 5;
828 reg8 |= pll->dben[f][i] << 6;
829 mchbar_clrsetbits8(C0CMDTX1, 3 << 5, reg8);
831 reg8 = pll->clkdelay[f][i] << 4;
832 mchbar_clrsetbits8(C0CMDTX2, 3 << 4, reg8);
834 reg8 = pll->pi[f][i];
835 mchbar_clrsetbits8(C0TXCMD0DLL, 0x3f, reg8);
836 mchbar_clrsetbits8(C0TXCMD1DLL, 0x3f, reg8);
839 /* Program CTRL registers for Kcoarse, Tap, PI, DBEn and DBSel */
840 static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
842 u8 reg8;
843 u32 reg32;
845 /* CTRL0 and CTRL1 */
846 reg32 = ((u32)pll->dbsel[f][i]) << 20;
847 reg32 |= ((u32)pll->dben[f][i]) << 21;
848 reg32 |= ((u32)pll->dbsel[f][i]) << 22;
849 reg32 |= ((u32)pll->dben[f][i]) << 23;
850 reg32 |= ((u32)pll->clkdelay[f][i]) << 24;
851 reg32 |= ((u32)pll->clkdelay[f][i]) << 27;
852 mchbar_clrsetbits32(C0CTLTX2, 0x01bf0000, reg32);
854 reg8 = pll->pi[f][i];
855 mchbar_clrsetbits8(C0TXCTL0DLL, 0x3f, reg8);
856 mchbar_clrsetbits8(C0TXCTL1DLL, 0x3f, reg8);
858 /* CTRL2 and CTRL3 */
859 reg32 = ((u32)pll->dbsel[f][i]) << 12;
860 reg32 |= ((u32)pll->dben[f][i]) << 13;
861 reg32 |= ((u32)pll->dbsel[f][i]) << 8;
862 reg32 |= ((u32)pll->dben[f][i]) << 9;
863 reg32 |= ((u32)pll->clkdelay[f][i]) << 14;
864 reg32 |= ((u32)pll->clkdelay[f][i]) << 10;
865 mchbar_clrsetbits32(C0CMDTX2, 0xff << 8, reg32);
867 reg8 = pll->pi[f][i];
868 mchbar_clrsetbits8(C0TXCTL2DLL, 0x3f, reg8);
869 mchbar_clrsetbits8(C0TXCTL3DLL, 0x3f, reg8);
872 static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
874 u8 rank, dqs, reg8, j;
875 u32 reg32;
877 j = clk - 40;
878 reg8 = 0;
879 reg32 = 0;
880 rank = j % 4;
881 dqs = j / 4;
883 reg32 |= ((u32)pll->dben[f][clk]) << (dqs + 9);
884 reg32 |= ((u32)pll->dbsel[f][clk]) << dqs;
886 mchbar_clrsetbits32(C0DQSRyTX1(rank), 1 << (dqs + 9) | 1 << dqs, reg32);
888 reg32 = ((u32)pll->clkdelay[f][clk]) << ((dqs * 2) + 16);
889 mchbar_clrsetbits32(C0DQSDQRyTX3(rank), 1 << (dqs * 2 + 17) | 1 << (dqs * 2 + 16),
890 reg32);
892 reg8 = pll->pi[f][clk];
893 mchbar_clrsetbits8(C0TXDQS0R0DLL + j, 0x3f, reg8);
896 static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
898 u8 rank, dq, reg8, j;
899 u32 reg32;
901 j = clk - 8;
902 reg8 = 0;
903 reg32 = 0;
904 rank = j % 4;
905 dq = j / 4;
907 reg32 |= ((u32)pll->dben[f][clk]) << (dq + 9);
908 reg32 |= ((u32)pll->dbsel[f][clk]) << dq;
910 mchbar_clrsetbits32(C0DQRyTX1(rank), 1 << (dq + 9) | 1 << dq, reg32);
912 reg32 = ((u32)pll->clkdelay[f][clk]) << (dq*2);
913 mchbar_clrsetbits32(C0DQSDQRyTX3(rank), 1 << (dq * 2 + 1) | 1 << (dq * 2), reg32);
915 reg8 = pll->pi[f][clk];
916 mchbar_clrsetbits8(C0TXDQ0R0DLL + j, 0x3f, reg8);
919 /* WDLL programming: Perform HPLL/MPLL calibration after write levelization */
920 static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
922 struct pllparam pll = {
923 .pi = {
924 { /* DDR = 667 */
925 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
926 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
927 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
928 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
929 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
930 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3,
932 { /* DDR = 800 */
933 53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
934 34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
935 47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
936 47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
937 2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
938 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15,
941 .dben = {
942 { /* DDR = 667 */
943 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
944 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
945 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
946 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
947 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
948 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
950 { /* DDR = 800 */
951 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
952 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
953 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
954 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
955 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
956 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
959 .dbsel = {
960 { /* DDR = 667 */
961 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
962 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
963 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
964 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
965 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
968 { /* DDR = 800 */
969 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
970 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
971 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
972 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
973 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
974 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
977 .clkdelay = {
978 { /* DDR = 667 */
979 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
980 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
981 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
982 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
983 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
984 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
986 { /* DDR = 800 */
987 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
988 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
989 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
990 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
991 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
992 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
996 u8 i, f;
997 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
998 f = 0;
999 } else {
1000 f = 1;
1002 for (i = 0; i < 72; i++) {
1003 pll.pi[f][i] += pidelay;
1006 /* Disable Dynamic DQS Slave Setting Per Rank */
1007 mchbar_clrbits8(CSHRDQSCMN, 1 << 7);
1008 mchbar_clrsetbits16(CSHRPDCTL4, 0x3fff, 0x1fff);
1010 sdram_p_clkset0(&pll, f, 0);
1011 sdram_p_clkset1(&pll, f, 1);
1012 sdram_p_cmd(&pll, f, 2);
1013 sdram_p_ctrl(&pll, f, 4);
1015 for (i = 0; i < 32; i++) {
1016 sdram_p_dqs(&pll, f, i + 40);
1018 for (i = 0; i < 32; i++) {
1019 sdram_p_dq(&pll, f, i + 8);
1023 /* Perform HMC hardware calibration */
1024 static void sdram_calibratehwpll(struct sysinfo *s)
1026 u8 reg8;
1028 s->async = 0;
1029 reg8 = 0;
1031 mchbar_setbits16(CSHRPDCTL, 1 << 15);
1032 mchbar_clrbits8(CSHRPDCTL, 1 << 7);
1033 mchbar_setbits8(CSHRPDCTL, 1 << 3);
1034 mchbar_setbits8(CSHRPDCTL, 1 << 2);
1036 /* Start hardware HMC calibration */
1037 mchbar_setbits8(CSHRPDCTL, 1 << 7);
1039 /* Busy-wait until calibration is done */
1040 while ((mchbar_read8(CSHRPDCTL) & (1 << 2)) == 0)
1043 /* If hardware HMC calibration failed */
1044 reg8 = (mchbar_read8(CSHRPDCTL) & (1 << 3)) >> 3;
1045 if (reg8 != 0) {
1046 s->async = 1;
1050 static void sdram_dlltiming(struct sysinfo *s)
1052 u8 reg8, i;
1053 u16 reg16;
1054 u32 reg32;
1056 /* Configure the Master DLL */
1057 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1058 reg32 = 0x08014227;
1059 } else {
1060 reg32 = 0x00014221;
1062 mchbar_clrsetbits32(CSHRMSTRCTL1, 0x0fffffff, reg32);
1063 mchbar_setbits32(CSHRMSTRCTL1, 1 << 23);
1064 mchbar_setbits32(CSHRMSTRCTL1, 1 << 15);
1065 mchbar_clrbits32(CSHRMSTRCTL1, 1 << 15);
1067 if (s->nodll) {
1068 /* Disable the Master DLLs by setting these bits, IN ORDER! */
1069 mchbar_setbits16(CSHRMSTRCTL0, 1 << 0);
1070 mchbar_setbits16(CSHRMSTRCTL0, 1 << 2);
1071 mchbar_setbits16(CSHRMSTRCTL0, 1 << 4);
1072 mchbar_setbits16(CSHRMSTRCTL0, 1 << 8);
1073 mchbar_setbits16(CSHRMSTRCTL0, 1 << 10);
1074 mchbar_setbits16(CSHRMSTRCTL0, 1 << 12);
1075 mchbar_setbits16(CSHRMSTRCTL0, 1 << 14);
1076 } else {
1077 /* Enable the Master DLLs by clearing these bits, IN ORDER! */
1078 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 0);
1079 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 2);
1080 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 4);
1081 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 8);
1082 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 10);
1083 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 12);
1084 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 14);
1087 /* Initialize the Transmit DLL PI values in the following sequence. */
1088 if (s->nodll) {
1089 mchbar_clrsetbits8(CREFPI, 0x3f, 0x07);
1090 } else {
1091 mchbar_clrbits8(CREFPI, 0x3f);
1094 sdram_calibratepll(s, 0); // XXX check
1096 /* Enable all modular Slave DLL */
1097 mchbar_setbits16(C0DLLPIEN, 1 << 11);
1098 mchbar_setbits16(C0DLLPIEN, 1 << 12);
1100 for (i = 0; i < 8; i++) {
1101 mchbar_setbits16(C0DLLPIEN, (1 << 10) >> i);
1103 /* Enable DQ/DQS output */
1104 mchbar_setbits8(C0SLVDLLOUTEN, 1 << 0);
1105 mchbar_write16(CSPDSLVWT, 0x5005);
1106 mchbar_clrsetbits16(CSHRPDCTL2, 0x1f1f, 0x051a);
1107 mchbar_clrsetbits16(CSHRPDCTL5, 0xbf3f, 0x9010);
1109 if (s->nodll) {
1110 mchbar_clrsetbits8(CSHRPDCTL3, 0x7f, 0x6b);
1111 } else {
1112 mchbar_clrsetbits8(CSHRPDCTL3, 0x7f, 0x55);
1113 sdram_calibratehwpll(s);
1115 /* Disable Dynamic Diff Amp */
1116 mchbar_clrbits32(C0STATRDCTRL, 1 << 22);
1118 /* Now, start initializing the transmit FIFO */
1119 mchbar_clrbits8(C0MISCCTL, 1 << 1);
1121 /* Disable (gate) mdclk and mdclkb */
1122 mchbar_setbits8(CSHWRIOBONUS, 3 << 6);
1124 /* Select mdmclk */
1125 mchbar_clrbits8(CSHWRIOBONUS, 1 << 5);
1127 /* Ungate mdclk */
1128 mchbar_clrsetbits8(CSHWRIOBONUS, 3 << 6, 1 << 6);
1129 mchbar_clrsetbits8(CSHRFIFOCTL, 0x3f, 0x1a);
1131 /* Enable the write pointer count */
1132 mchbar_setbits8(CSHRFIFOCTL, 1 << 0);
1134 /* Set the DDR3 Reset Enable bit */
1135 mchbar_setbits8(CSHRDDR3CTL, 1 << 0);
1137 /* Configure DQS-DQ Transmit */
1138 mchbar_write32(CSHRDQSTXPGM, 0x00551803);
1140 reg8 = 0; /* Switch all clocks on anyway */
1142 /* Enable clock groups depending on rank population */
1143 mchbar_clrsetbits32(C0CKTX, 0x3f << 24, reg8 << 24);
1145 /* Enable DDR command output buffers from core */
1146 mchbar_clrbits8(0x594, 1 << 0);
1148 reg16 = 0;
1149 if (!rank_is_populated(s->dimms, 0, 0)) {
1150 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
1152 if (!rank_is_populated(s->dimms, 0, 1)) {
1153 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
1155 if (!rank_is_populated(s->dimms, 0, 2)) {
1156 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1158 if (!rank_is_populated(s->dimms, 0, 3)) {
1159 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1161 mchbar_setbits16(C0CTLTX2, reg16);
1164 /* Define a shorter name for these to make the lines fit in 96 characters */
1165 #define TABLE static const
1167 /* Loop over each RCOMP group, but skip group 1 because it does not exist */
1168 #define FOR_EACH_RCOMP_GROUP(idx) for (idx = 0; idx < 7; idx++) if (idx != 1)
1170 /* Define accessors for the RCOMP register banks */
1171 #define C0RCOMPCTRLx(x) (rcompctl[(x)] + 0x00)
1172 #define C0RCOMPMULTx(x) (rcompctl[(x)] + 0x04)
1173 #define C0RCOMPOVRx(x) (rcompctl[(x)] + 0x06)
1174 #define C0RCOMPOSVx(x) (rcompctl[(x)] + 0x0a)
1175 #define C0SCOMPVREFx(x) (rcompctl[(x)] + 0x0e)
1176 #define C0SCOMPOVRx(x) (rcompctl[(x)] + 0x10)
1177 #define C0SCOMPOFFx(x) (rcompctl[(x)] + 0x12)
1178 #define C0DCOMPx(x) (rcompctl[(x)] + 0x14)
1179 #define C0SLEWBASEx(x) (rcompctl[(x)] + 0x16)
1180 #define C0SLEWPULUTx(x) (rcompctl[(x)] + 0x18)
1181 #define C0SLEWPDLUTx(x) (rcompctl[(x)] + 0x1c)
1182 #define C0DCOMPOVRx(x) (rcompctl[(x)] + 0x20)
1183 #define C0DCOMPOFFx(x) (rcompctl[(x)] + 0x24)
1185 /* FIXME: This only applies to DDR2 */
1186 static void sdram_rcomp(struct sysinfo *s)
1188 u8 i, j, reg8, rcompp, rcompn, srup, srun;
1189 u16 reg16;
1190 u32 reg32, rcomp1, rcomp2;
1192 static const u8 rcompslew = 0x0a;
1193 static const u16 rcompctl[7] = {
1194 C0RCOMPCTRL0,
1195 0, /* This register does not exist */
1196 C0RCOMPCTRL2,
1197 C0RCOMPCTRL3,
1198 C0RCOMPCTRL4,
1199 C0RCOMPCTRL5,
1200 C0RCOMPCTRL6,
1203 /* RCOMP settings tables = { NC-NC, x16SS, x16DS, x16SS2, x16DS2, x8DS, x8DS2}; */
1204 TABLE u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0};
1205 TABLE u8 rcompstr[7] = { 0x66, 0x00, 0xaa, 0x55, 0x55, 0x77, 0x77};
1206 TABLE u16 rcompscomp[7] = {0xa22a, 0x0000, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a};
1207 TABLE u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1};
1208 TABLE u16 rcompf[7] = {0x1114, 0x0000, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a};
1209 TABLE u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0xaa};
1210 TABLE u16 rcompscomp2[7] = {0x0000, 0xe22e, 0xe22e, 0xe22e, 0x8228, 0xe22e, 0x8228};
1211 TABLE u8 rcompdelay2[7] = { 0, 0, 0, 0, 2, 0, 2};
1213 TABLE u8 rcomplut[64][12] = {
1214 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1215 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1216 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1217 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1218 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1219 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1220 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1221 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1222 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1223 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1224 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1225 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
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 {10, 9, 12, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1230 {10, 9, 12, 11, 2, 2, 6, 5, 7, 6, 6, 5},
1231 {10, 10, 12, 12, 2, 2, 6, 5, 7, 6, 6, 5},
1232 {10, 10, 12, 12, 2, 2, 6, 6, 7, 7, 6, 6},
1233 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1234 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1235 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1236 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1237 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1238 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1239 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1240 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1241 {11, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1242 {11, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1243 {12, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1244 {12, 12, 14, 13, 3, 3, 7, 6, 7, 7, 7, 6},
1245 {13, 12, 16, 15, 3, 3, 7, 6, 8, 7, 7, 6},
1246 {13, 14, 16, 15, 4, 3, 7, 7, 8, 8, 7, 7},
1247 {14, 14, 16, 17, 4, 3, 7, 7, 8, 8, 7, 7},
1248 {14, 16, 18, 17, 4, 4, 8, 7, 8, 8, 8, 7},
1249 {15, 16, 18, 19, 4, 4, 8, 7, 9, 8, 8, 7},
1250 {15, 18, 18, 19, 4, 4, 8, 8, 9, 9, 8, 8},
1251 {16, 18, 20, 21, 4, 4, 8, 8, 9, 9, 8, 8},
1252 {16, 19, 20, 21, 5, 4, 9, 8, 10, 9, 9, 8},
1253 {16, 19, 20, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1254 {17, 19, 22, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1255 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1256 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1257 {18, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1258 {18, 21, 24, 25, 5, 5, 9, 9, 11, 10, 9, 9},
1259 {19, 21, 24, 27, 5, 5, 9, 9, 11, 11, 9, 9},
1260 {19, 22, 24, 27, 5, 5, 10, 9, 11, 11, 10, 9},
1261 {20, 22, 24, 27, 6, 5, 10, 10, 11, 11, 10, 10},
1262 {20, 23, 26, 27, 6, 6, 10, 10, 12, 12, 10, 10},
1263 {20, 23, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1264 {21, 24, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1265 {21, 24, 26, 29, 6, 6, 11, 10, 12, 13, 11, 10},
1266 {22, 25, 28, 29, 6, 6, 11, 11, 13, 13, 11, 11},
1267 {22, 25, 28, 31, 6, 6, 11, 11, 13, 13, 11, 11},
1268 {22, 26, 28, 31, 6, 6, 11, 11, 13, 14, 11, 11},
1269 {23, 26, 30, 31, 7, 6, 12, 11, 14, 14, 12, 11},
1270 {23, 27, 30, 33, 7, 7, 12, 12, 14, 14, 12, 12},
1271 {23, 27, 30, 33, 7, 7, 12, 12, 14, 15, 12, 12},
1272 {24, 28, 32, 33, 7, 7, 12, 12, 15, 15, 12, 12},
1273 {24, 28, 32, 33, 7, 7, 12, 12, 15, 16, 12, 12},
1274 {24, 29, 32, 35, 7, 7, 12, 12, 15, 16, 12, 12},
1275 {25, 29, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1276 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1277 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1280 srup = 0;
1281 srun = 0;
1283 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1284 rcomp1 = 0x00050431;
1285 } else {
1286 rcomp1 = 0x00050542;
1288 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
1289 rcomp2 = 0x14c42827;
1290 } else {
1291 rcomp2 = 0x19042827;
1294 FOR_EACH_RCOMP_GROUP(i) {
1295 reg8 = rcompupdate[i];
1296 mchbar_clrsetbits8(C0RCOMPCTRLx(i), 1 << 0, reg8);
1297 mchbar_clrbits8(C0RCOMPCTRLx(i), 1 << 1);
1299 reg16 = rcompslew;
1300 mchbar_clrsetbits16(C0RCOMPCTRLx(i), 0xf << 12, reg16 << 12);
1302 mchbar_write8(C0RCOMPMULTx(i), rcompstr[i]);
1303 mchbar_write16(C0SCOMPVREFx(i), rcompscomp[i]);
1304 mchbar_clrsetbits8(C0DCOMPx(i), 0x03, rcompdelay[i]);
1305 if (i == 2) {
1306 /* FIXME: Why are we rewriting this? */
1307 mchbar_clrsetbits16(C0RCOMPCTRLx(i), 0xf << 12, reg16 << 12);
1309 mchbar_write8(C0RCOMPMULTx(i), rcompstr2[s->dimm_config[0]]);
1310 mchbar_write16(C0SCOMPVREFx(i), rcompscomp2[s->dimm_config[0]]);
1311 mchbar_clrsetbits8(C0DCOMPx(i), 0x03, rcompdelay2[s->dimm_config[0]]);
1314 mchbar_clrbits16(C0SLEWBASEx(i), 0x7f7f);
1316 /* FIXME: Why not do a single dword write? */
1317 mchbar_clrbits16(C0SLEWPULUTx(i), 0x3f3f);
1318 mchbar_clrbits16(C0SLEWPULUTx(i) + 2, 0x3f3f);
1320 /* FIXME: Why not do a single dword write? */
1321 mchbar_clrbits16(C0SLEWPDLUTx(i), 0x3f3f);
1322 mchbar_clrbits16(C0SLEWPDLUTx(i) + 2, 0x3f3f);
1325 /* FIXME: Hardcoded */
1326 mchbar_clrsetbits8(C0ODTRECORDX, 0x3f, 0x36);
1327 mchbar_clrsetbits8(C0DQSODTRECORDX, 0x3f, 0x36);
1329 FOR_EACH_RCOMP_GROUP(i) {
1330 mchbar_clrbits8(C0RCOMPCTRLx(i), 3 << 5);
1331 mchbar_clrbits16(C0RCOMPCTRLx(i) + 2, 0x0706);
1332 mchbar_clrbits16(C0RCOMPOSVx(i), 0x7f7f);
1333 mchbar_clrbits16(C0SCOMPOFFx(i), 0x3f3f);
1334 mchbar_clrbits16(C0DCOMPOFFx(i), 0x1f1f);
1335 mchbar_clrbits8(C0DCOMPOFFx(i) + 2, 0x1f);
1338 mchbar_clrbits16(C0ODTRECORDX, 0xffc0);
1339 mchbar_clrbits16(C0ODTRECORDX + 2, 0x000f);
1341 /* FIXME: Why not do a single dword write? */
1342 mchbar_clrbits16(C0DQSODTRECORDX, 0xffc0);
1343 mchbar_clrbits16(C0DQSODTRECORDX + 2, 0x000f);
1345 FOR_EACH_RCOMP_GROUP(i) {
1346 mchbar_write16(C0SCOMPOVRx(i), rcompf[i]);
1348 /* FIXME: Why not do a single dword write? */
1349 mchbar_write16(C0DCOMPOVRx(i) + 0, 0x1219);
1350 mchbar_write16(C0DCOMPOVRx(i) + 2, 0x000c);
1353 mchbar_clrsetbits32(DCMEASBUFOVR, 0x001f1f1f, 0x000c1219);
1355 /* FIXME: Why not do a single word write? */
1356 mchbar_clrsetbits16(XCOMPSDR0BNS, 0x1f << 8, 0x12 << 8);
1357 mchbar_clrsetbits8(XCOMPSDR0BNS, 0x1f << 0, 0x12 << 0);
1359 mchbar_write32(COMPCTRL3, 0x007c9007);
1360 mchbar_write32(OFREQDELSEL, rcomp1);
1361 mchbar_write16(XCOMPCMNBNS, 0x1f7f);
1362 mchbar_write32(COMPCTRL2, rcomp2);
1363 mchbar_clrsetbits16(XCOMPDFCTRL, 0xf, 1);
1364 mchbar_write16(ZQCALCTRL, 0x0134);
1365 mchbar_write32(COMPCTRL1, 0x4c293600);
1367 mchbar_clrsetbits8(COMPCTRL1 + 3, 0x44, 1 << 6 | 1 << 2);
1368 mchbar_clrbits16(XCOMPSDR0BNS, 1 << 13);
1369 mchbar_clrbits8(XCOMPSDR0BNS, 1 << 5);
1371 FOR_EACH_RCOMP_GROUP(i) {
1372 /* POR values are zero */
1373 mchbar_clrbits8(C0RCOMPCTRLx(i) + 2, 0x71);
1376 if ((mchbar_read32(COMPCTRL1) & (1 << 30)) == 0) {
1377 /* Start COMP */
1378 mchbar_setbits8(COMPCTRL1, 1 << 0);
1380 /* Wait until COMP is done */
1381 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
1384 reg32 = mchbar_read32(XCOMP);
1385 rcompp = (u8)((reg32 & ~(1 << 31)) >> 24);
1386 rcompn = (u8)((reg32 & ~(0xff800000)) >> 16);
1388 FOR_EACH_RCOMP_GROUP(i) {
1389 srup = (mchbar_read8(C0RCOMPCTRLx(i) + 1) & 0xc0) >> 6;
1390 srun = (mchbar_read8(C0RCOMPCTRLx(i) + 1) & 0x30) >> 4;
1392 /* FIXME: Why not do a single word write? */
1393 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
1394 mchbar_clrsetbits16(C0SLEWBASEx(i), 0x7f << 8, reg16);
1396 reg16 = (u16)(rcompn - (1 << (srun + 1)));
1397 mchbar_clrsetbits8(C0SLEWBASEx(i), 0x7f, (u8)reg16);
1400 reg8 = rcompp - (1 << (srup + 1));
1401 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1402 mchbar_clrsetbits8(C0SLEWPULUTx(0) + i, 0x3f, rcomplut[j][0]);
1405 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1406 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1407 mchbar_clrsetbits8(C0SLEWPULUTx(2) + i, 0x3f, rcomplut[j][10]);
1411 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1412 mchbar_clrsetbits8(C0SLEWPULUTx(3) + i, 0x3f, rcomplut[j][6]);
1413 mchbar_clrsetbits8(C0SLEWPULUTx(4) + i, 0x3f, rcomplut[j][6]);
1416 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1417 mchbar_clrsetbits8(C0SLEWPULUTx(5) + i, 0x3f, rcomplut[j][8]);
1418 mchbar_clrsetbits8(C0SLEWPULUTx(6) + i, 0x3f, rcomplut[j][8]);
1421 reg8 = rcompn - (1 << (srun + 1));
1422 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1423 mchbar_clrsetbits8(C0SLEWPDLUTx(0) + i, 0x3f, rcomplut[j][1]);
1426 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1427 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1428 mchbar_clrsetbits8(C0SLEWPDLUTx(2) + i, 0x3f, rcomplut[j][11]);
1432 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1433 mchbar_clrsetbits8(C0SLEWPDLUTx(3) + i, 0x3f, rcomplut[j][7]);
1434 mchbar_clrsetbits8(C0SLEWPDLUTx(4) + i, 0x3f, rcomplut[j][7]);
1437 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1438 mchbar_clrsetbits8(C0SLEWPDLUTx(5) + i, 0x3f, rcomplut[j][9]);
1439 mchbar_clrsetbits8(C0SLEWPDLUTx(6) + i, 0x3f, rcomplut[j][9]);
1442 mchbar_setbits8(COMPCTRL1, 1 << 0);
1445 /* FIXME: The ODT tables are for DDR2 only! */
1446 static void sdram_odt(struct sysinfo *s)
1448 u8 rankindex = 0;
1450 static const u16 odt_rankctrl[16] = {
1451 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1452 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1453 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1454 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1456 static const u16 odt_matrix[16] = {
1457 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1458 0x0000, 0x0011, 0x0000, 0x0011, 0x0000, 0x4444, 0x0000, 0x4444,
1459 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1460 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4444, 0x0000, 0x4444,
1463 switch (s->dimms[0].ranks) {
1464 case 0:
1465 if (s->dimms[1].ranks == 0) {
1466 rankindex = 0;
1467 } else if (s->dimms[1].ranks == 1) {
1468 rankindex = 4;
1469 } else if (s->dimms[1].ranks == 2) {
1470 rankindex = 12;
1472 break;
1473 case 1:
1474 if (s->dimms[1].ranks == 0) {
1475 rankindex = 1;
1476 } else if (s->dimms[1].ranks == 1) {
1477 rankindex = 5;
1478 } else if (s->dimms[1].ranks == 2) {
1479 rankindex = 13;
1481 break;
1482 case 2:
1483 if (s->dimms[1].ranks == 0) {
1484 rankindex = 3;
1485 } else if (s->dimms[1].ranks == 1) {
1486 rankindex = 7;
1487 } else if (s->dimms[1].ranks == 2) {
1488 rankindex = 15;
1490 break;
1493 /* Program the ODT Matrix */
1494 mchbar_write16(C0ODT, odt_matrix[rankindex]);
1496 /* Program the ODT Rank Control */
1497 mchbar_write16(C0ODTRKCTRL, odt_rankctrl[rankindex]);
1500 static void sdram_mmap(struct sysinfo *s)
1502 TABLE u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000, 0xc00001, 0xf00000};
1503 TABLE u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101, 0x1010000, 0x1010101};
1504 TABLE u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1505 TABLE u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006, 0x40002, 0x80006};
1507 TABLE u16 tolud[7] = {2048, 2048, 4096, 4096, 8192, 4096, 8192};
1508 TABLE u16 tom[7] = { 2, 2, 4, 4, 8, 4, 8};
1509 TABLE u16 touud[7] = { 128, 128, 256, 256, 512, 256, 512};
1510 TABLE u32 gbsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1511 TABLE u32 bgsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1512 TABLE u32 tsegmb[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1514 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1515 if (s->dimms[0].sides > 1) {
1516 // 2R/NC
1517 mchbar_clrsetbits32(C0CKECTRL, 1, 0x300001);
1518 mchbar_write32(C0DRA01, 0x00000101);
1519 mchbar_write32(C0DRB0, 0x00040002);
1520 mchbar_write32(C0DRB2, w204[s->dimm_config[0]]);
1521 } else {
1522 // 1R/NC
1523 mchbar_clrsetbits32(C0CKECTRL, 1, 0x100001);
1524 mchbar_write32(C0DRA01, 0x00000001);
1525 mchbar_write32(C0DRB0, 0x00020002);
1526 mchbar_write32(C0DRB2, w204[s->dimm_config[0]]);
1528 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
1529 mchbar_clrsetbits32(C0CKECTRL, 1, 0x300001);
1530 mchbar_write32(C0DRA01, 0x00000101);
1531 mchbar_write32(C0DRB0, 0x00040002);
1532 mchbar_write32(C0DRB2, 0x00040004);
1533 } else {
1534 mchbar_clrsetbits32(C0CKECTRL, 1, w260[s->dimm_config[0]]);
1535 mchbar_write32(C0DRA01, w208[s->dimm_config[0]]);
1536 mchbar_write32(C0DRB0, w200[s->dimm_config[0]]);
1537 mchbar_write32(C0DRB2, w204[s->dimm_config[0]]);
1539 pci_write_config16(HOST_BRIDGE, 0xb0, tolud[s->dimm_config[0]]);
1540 pci_write_config16(HOST_BRIDGE, 0xa0, tom[s->dimm_config[0]]);
1541 pci_write_config16(HOST_BRIDGE, 0xa2, touud[s->dimm_config[0]]);
1542 pci_write_config32(HOST_BRIDGE, 0xa4, gbsm[s->dimm_config[0]]);
1543 pci_write_config32(HOST_BRIDGE, 0xa8, bgsm[s->dimm_config[0]]);
1544 pci_write_config32(HOST_BRIDGE, 0xac, tsegmb[s->dimm_config[0]]);
1547 static u8 sdram_checkrcompoverride(void)
1549 u32 xcomp;
1550 u8 aa, bb, a, b, c, d;
1552 xcomp = mchbar_read32(XCOMP);
1553 a = (u8)((xcomp & 0x7f000000) >> 24);
1554 b = (u8)((xcomp & 0x007f0000) >> 16);
1555 c = (u8)((xcomp & 0x00003f00) >> 8);
1556 d = (u8)((xcomp & 0x0000003f) >> 0);
1558 if (a > b) {
1559 aa = a - b;
1560 } else {
1561 aa = b - a;
1563 if (c > d) {
1564 bb = c - d;
1565 } else {
1566 bb = d - c;
1568 if ((aa > 18) || (bb > 7) || (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
1569 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
1570 mchbar_write32(RCMEASBUFXOVR, 0x9718a729);
1571 return 1;
1573 return 0;
1576 static void sdram_rcompupdate(struct sysinfo *s)
1578 u8 i, ok;
1579 u32 reg32a, reg32b;
1581 ok = 0;
1582 mchbar_clrbits8(XCOMPDFCTRL, 1 << 3);
1583 mchbar_clrbits8(COMPCTRL1, 1 << 7);
1584 for (i = 0; i < 3; i++) {
1585 mchbar_setbits8(COMPCTRL1, 1 << 0);
1586 hpet_udelay(1000);
1587 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
1589 ok |= sdram_checkrcompoverride();
1591 if (!ok) {
1592 reg32a = mchbar_read32(XCOMP);
1593 reg32b = ((reg32a >> 16) & 0x0000ffff);
1594 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1595 reg32a |= (1 << 31) | (1 << 15);
1596 mchbar_write32(RCMEASBUFXOVR, reg32a);
1598 mchbar_setbits8(COMPCTRL1, 1 << 0);
1599 hpet_udelay(1000);
1600 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
1604 static void __attribute__((noinline))
1605 sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1607 u32 reg32;
1609 reg32 = jval << 3;
1610 reg32 |= rank * (1 << 27);
1611 mchbar_clrsetbits8(C0JEDEC, 0x3e, jmode);
1612 read32p(reg32);
1613 barrier();
1614 hpet_udelay(1); // 1us
1617 static void sdram_zqcl(struct sysinfo *s)
1619 if (s->boot_path == BOOT_PATH_RESUME) {
1620 mchbar_setbits32(C0CKECTRL, 1 << 27);
1621 mchbar_clrsetbits8(C0JEDEC, 0x0e, NORMAL_OP_CMD);
1622 mchbar_clrbits8(C0JEDEC, 3 << 4);
1623 mchbar_clrsetbits32(C0REFRCTRL2, 3 << 30, 3 << 30);
1627 static void sdram_jedecinit(struct sysinfo *s)
1629 u8 r, i, ch;
1630 u16 reg16, mrs, rttnom;
1631 struct jedeclist {
1632 char debug[15];
1633 u8 cmd;
1634 u16 val;
1637 static const struct jedeclist jedec[12] = {
1638 { " NOP ", NOP_CMD, 0 },
1639 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1640 { " EMRS2 ", EMRS2_CMD, 0 },
1641 { " EMRS3 ", EMRS3_CMD, 0 },
1642 { " EMRS1 ", EMRS1_CMD, 0 },
1643 { " DLL RESET ", MRS_CMD, (1 << 8) },
1644 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1645 { " AUTOREFRESH", CBR_CMD, 0 },
1646 { " AUTOREFRESH", CBR_CMD, 0 },
1647 { " INITIALISE ", MRS_CMD, 0 },
1648 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1649 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1652 mrs = (s->selected_timings.CAS << 4) |
1653 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 3;
1655 rttnom = (1 << 2);
1656 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1657 rttnom |= (1 << 6);
1660 hpet_udelay(200); // 200us
1661 reg16 = 0;
1662 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1663 for (i = 0; i < 12; i++) {
1664 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1665 reg16 = jedec[i].val;
1666 switch (jedec[i].cmd) {
1667 case EMRS1_CMD:
1668 reg16 |= rttnom;
1669 break;
1670 case MRS_CMD:
1671 reg16 |= mrs;
1672 break;
1673 default:
1674 break;
1676 sdram_jedec(s, r, jedec[i].cmd, reg16);
1677 PRINTK_DEBUG("done\n");
1682 static void sdram_misc(struct sysinfo *s)
1684 u32 reg32;
1686 reg32 = 0;
1687 reg32 |= (4 << 13);
1688 reg32 |= (6 << 8);
1689 mchbar_clrsetbits32(C0DYNRDCTRL, 0x3ff << 8, reg32);
1690 mchbar_clrbits8(C0DYNRDCTRL, 1 << 7);
1691 mchbar_setbits8(C0REFRCTRL + 3, 1 << 0);
1692 if (s->boot_path != BOOT_PATH_RESUME) {
1693 mchbar_clrsetbits8(C0JEDEC, 0x0e, NORMAL_OP_CMD);
1694 mchbar_clrbits8(C0JEDEC, 3 << 4);
1695 } else {
1696 sdram_zqcl(s);
1700 static void sdram_checkreset(void)
1702 u8 pmcon2, pmcon3, reset;
1704 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1705 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1706 pmcon3 &= ~0x2;
1707 if (pmcon2 & 0x80) {
1708 pmcon2 &= ~0x80;
1709 reset = 1;
1710 } else {
1711 pmcon2 |= 0x80;
1712 reset = 0;
1714 if (pmcon2 & 0x4) {
1715 pmcon2 |= 0x4;
1716 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1717 pmcon3 |= (1 << 3);
1719 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1720 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
1721 if (reset)
1722 full_reset();
1725 static void sdram_dradrb(struct sysinfo *s)
1727 u8 i, reg8, ch, r;
1728 u32 reg32, ind, c0dra, c0drb, dra;
1729 u16 addr;
1730 i = 0;
1731 static const u8 dratab[2][2][2][4] =
1734 {0xff, 0xff, 0xff, 0xff},
1735 {0xff, 0x00, 0x02, 0xff}
1738 {0xff, 0x01, 0xff, 0xff},
1739 {0xff, 0x03, 0xff, 0x06}
1744 {0xff, 0xff, 0xff, 0xff},
1745 {0xff, 0x04, 0x06, 0x08}
1748 {0xff, 0xff, 0xff, 0xff},
1749 {0x05, 0x07, 0x09, 0xff}
1753 static const u8 dradrb[10][6] = {
1754 //Row Col Bank Width DRB
1755 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1756 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1757 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1758 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1759 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1760 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1761 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1762 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1763 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1764 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1767 reg32 = 0;
1768 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1769 i = r / 2;
1770 PRINTK_DEBUG("RANK %d PRESENT\n", r);
1771 dra = dratab
1772 [s->dimms[i].banks]
1773 [s->dimms[i].width]
1774 [s->dimms[i].cols - 9]
1775 [s->dimms[i].rows - 12];
1777 if (s->dimms[i].banks == 1) {
1778 dra |= (1 << 7);
1780 reg32 |= (dra << (r * 8));
1782 mchbar_write32(C0DRA01, reg32);
1783 c0dra = reg32;
1784 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1786 reg32 = 0;
1787 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1788 reg32 |= (1 << r);
1790 reg8 = (u8)(reg32 << 4) & 0xf0;
1791 mchbar_clrsetbits8(C0CKECTRL + 2, 0xf0, reg8);
1793 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) || ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1794 mchbar_setbits8(C0CKECTRL, 1 << 0);
1797 addr = C0DRB0;
1798 c0drb = 0;
1799 FOR_EACH_RANK(ch, r) {
1800 if (rank_is_populated(s->dimms, ch, r)) {
1801 ind = (c0dra >> (8 * r)) & 0x7f;
1802 c0drb = (u16)(c0drb + dradrb[ind][5]);
1803 s->channel_capacity[0] += dradrb[ind][5] << 6;
1805 mchbar_write16(addr, c0drb);
1806 addr += 2;
1808 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1811 static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1813 u8 dqsmatches = 1;
1814 while (count--) {
1815 mchbar_clrbits8(C0RSTCTL, 1 << 1);
1816 hpet_udelay(1);
1817 mchbar_setbits8(C0RSTCTL, 1 << 1);
1818 hpet_udelay(1);
1819 barrier();
1820 read32p(strobeaddr);
1821 barrier();
1822 hpet_udelay(1);
1824 if (((mchbar_read8(dqshighaddr) & (1 << 6)) >> 6) != highlow) {
1825 dqsmatches = 0;
1829 return dqsmatches;
1832 static void rcvenclock(u8 *coarse, u8 *medium, u8 lane)
1834 if (*medium < 3) {
1835 (*medium)++;
1836 mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), *medium << (lane * 2));
1837 } else {
1838 *medium = 0;
1839 (*coarse)++;
1840 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, *coarse << 16);
1841 mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), *medium << (lane * 2));
1845 static void sdram_rcven(struct sysinfo *s)
1847 u8 coarse, savecoarse;
1848 u8 medium, savemedium;
1849 u8 pi, savepi;
1850 u8 lane;
1851 u8 lanecoarse[8] = {0};
1852 u8 minlanecoarse = 0xff;
1853 u8 offset;
1854 u8 maxlane = 8;
1855 /* Since dra/drb is already set up we know that at address 0x00000000
1856 we will always find the first available rank */
1857 u32 strobeaddr = 0;
1858 u32 dqshighaddr;
1860 mchbar_clrbits8(C0RSTCTL, 3 << 2);
1861 mchbar_clrbits8(CMNDQFIFORST, 1 << 7);
1863 PRINTK_DEBUG("rcven 0\n");
1864 for (lane = 0; lane < maxlane; lane++) {
1865 PRINTK_DEBUG("rcven lane %d\n", lane);
1866 // trylaneagain:
1867 dqshighaddr = C0MISCCTLy(lane);
1869 coarse = s->selected_timings.CAS + 1;
1870 pi = 0;
1871 medium = 0;
1873 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
1874 mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), medium << (lane * 2));
1876 mchbar_clrbits8(C0RXRCVyDLL(lane), 0x3f);
1878 savecoarse = coarse;
1879 savemedium = medium;
1880 savepi = pi;
1882 PRINTK_DEBUG("rcven 0.1\n");
1884 // XXX comment out
1885 // mchbar_clrsetbits16(C0RCVMISCCTL1, 3 << (lane * 2), 1 << (lane * 2));
1887 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1888 // printk(BIOS_DEBUG, "coarse=%d medium=%d\n", coarse, medium);
1889 rcvenclock(&coarse, &medium, lane);
1890 if (coarse > 0xf) {
1891 PRINTK_DEBUG("Error: coarse > 0xf\n");
1892 // goto trylaneagain;
1893 break;
1896 PRINTK_DEBUG("rcven 0.2\n");
1898 savecoarse = coarse;
1899 savemedium = medium;
1900 rcvenclock(&coarse, &medium, lane);
1902 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1903 savecoarse = coarse;
1904 savemedium = medium;
1905 rcvenclock(&coarse, &medium, lane);
1906 if (coarse > 0xf) {
1907 PRINTK_DEBUG("Error: coarse > 0xf\n");
1908 //goto trylaneagain;
1909 break;
1913 PRINTK_DEBUG("rcven 0.3\n");
1914 coarse = savecoarse;
1915 medium = savemedium;
1916 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
1917 mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), medium << (lane * 2));
1919 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1920 savepi = pi;
1921 pi++;
1922 if (pi > s->maxpi) {
1923 // if (s->nodll) {
1924 pi = savepi = s->maxpi;
1925 break;
1926 // }
1928 mchbar_clrsetbits8(C0RXRCVyDLL(lane), 0x3f, pi << s->pioffset);
1930 PRINTK_DEBUG("rcven 0.4\n");
1932 pi = savepi;
1933 mchbar_clrsetbits8(C0RXRCVyDLL(lane), 0x3f, pi << s->pioffset);
1934 rcvenclock(&coarse, &medium, lane);
1936 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1937 PRINTK_DEBUG("Error: DQS not high\n");
1938 // goto trylaneagain;
1940 PRINTK_DEBUG("rcven 0.5\n");
1941 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1942 coarse--;
1943 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
1944 if (coarse == 0) {
1945 PRINTK_DEBUG("Error: DQS did not hit 0\n");
1946 break;
1950 PRINTK_DEBUG("rcven 0.6\n");
1951 rcvenclock(&coarse, &medium, lane);
1952 s->pi[lane] = pi;
1953 lanecoarse[lane] = coarse;
1956 PRINTK_DEBUG("rcven 1\n");
1958 lane = maxlane;
1959 do {
1960 lane--;
1961 if (minlanecoarse > lanecoarse[lane]) {
1962 minlanecoarse = lanecoarse[lane];
1964 } while (lane != 0);
1966 lane = maxlane;
1967 do {
1968 lane--;
1969 offset = lanecoarse[lane] - minlanecoarse;
1970 mchbar_clrsetbits16(C0COARSEDLY0, 3 << (lane * 2), offset << (lane * 2));
1971 } while (lane != 0);
1973 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, minlanecoarse << 16);
1975 s->coarsectrl = minlanecoarse;
1976 s->coarsedelay = mchbar_read16(C0COARSEDLY0);
1977 s->mediumphase = mchbar_read16(C0RCVMISCCTL2);
1978 s->readptrdelay = mchbar_read16(C0RCVMISCCTL1);
1980 PRINTK_DEBUG("rcven 2\n");
1981 mchbar_clrbits8(C0RSTCTL, 7 << 1);
1982 mchbar_setbits8(C0RSTCTL, 1 << 1);
1983 mchbar_setbits8(C0RSTCTL, 1 << 2);
1984 mchbar_setbits8(C0RSTCTL, 1 << 3);
1986 mchbar_setbits8(CMNDQFIFORST, 1 << 7);
1987 mchbar_clrbits8(CMNDQFIFORST, 1 << 7);
1988 mchbar_setbits8(CMNDQFIFORST, 1 << 7);
1989 PRINTK_DEBUG("rcven 3\n");
1992 /* NOTE: Unless otherwise specified, the values are expressed in MiB */
1993 static void sdram_mmap_regs(struct sysinfo *s)
1995 bool reclaim;
1996 u32 mmiosize, tom, tolud, touud, reclaimbase, reclaimlimit;
1997 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase, tsegsize;
1998 u16 ggc;
1999 u16 ggc_to_uma[10] = {0, 1, 4, 8, 16, 32, 48, 64, 128, 256};
2000 u8 ggc_to_gtt[4] = {0, 1, 0, 0};
2002 reclaimbase = 0;
2003 reclaimlimit = 0;
2005 ggc = pci_read_config16(HOST_BRIDGE, GGC);
2006 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
2008 gfxsize = ggc_to_uma[(ggc & 0x00f0) >> 4];
2010 gttsize = ggc_to_gtt[(ggc & 0x0300) >> 8];
2012 tom = s->channel_capacity[0];
2014 /* With GTT always being 1M, TSEG 1M is the only setting that can
2015 be covered by SMRR which has alignment requirements. */
2016 tsegsize = 1;
2017 mmiosize = 1024;
2019 reclaim = false;
2020 tolud = MIN(4096 - mmiosize, tom);
2021 if ((tom - tolud) > 64) {
2022 reclaim = true;
2024 if (reclaim) {
2025 tolud = tolud & ~0x3f;
2026 tom = tom & ~0x3f;
2027 reclaimbase = MAX(4096, tom);
2028 reclaimlimit = reclaimbase + (MIN(4096, tom) - tolud) - 0x40;
2030 touud = tom;
2031 if (reclaim) {
2032 touud = reclaimlimit + 64;
2035 gfxbase = tolud - gfxsize;
2036 gttbase = gfxbase - gttsize;
2037 tsegbase = gttbase - tsegsize;
2039 /* Program the regs */
2040 pci_write_config16(HOST_BRIDGE, TOLUD, (u16)(tolud << 4));
2041 pci_write_config16(HOST_BRIDGE, TOM, (u16)(tom >> 6));
2042 if (reclaim) {
2043 pci_write_config16(HOST_BRIDGE, 0x98, (u16)(reclaimbase >> 6));
2044 pci_write_config16(HOST_BRIDGE, 0x9a, (u16)(reclaimlimit >> 6));
2046 pci_write_config16(HOST_BRIDGE, TOUUD, (u16)(touud));
2047 pci_write_config32(HOST_BRIDGE, GBSM, gfxbase << 20);
2048 pci_write_config32(HOST_BRIDGE, BGSM, gttbase << 20);
2049 pci_write_config32(HOST_BRIDGE, TSEG, tsegbase << 20);
2051 u8 reg8 = pci_read_config8(HOST_BRIDGE, ESMRAMC);
2052 reg8 &= ~0x07;
2053 reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
2054 pci_write_config8(HOST_BRIDGE, ESMRAMC, reg8);
2056 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
2057 pci_read_config32(HOST_BRIDGE, GBSM), gfxbase << 20);
2058 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
2059 pci_read_config32(HOST_BRIDGE, BGSM), gttbase << 20);
2060 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
2061 pci_read_config32(HOST_BRIDGE, TSEG), tsegbase << 20);
2064 static void sdram_enhancedmode(struct sysinfo *s)
2066 u8 reg8, ch, r, fsb_freq, ddr_freq;
2067 u32 mask32, reg32;
2068 mchbar_setbits8(C0ADDCSCTRL, 1 << 0);
2069 mchbar_setbits8(C0REFRCTRL + 3, 1 << 0);
2070 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
2071 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2072 mchbar_clrsetbits32(WRWMCONFIG, mask32, reg32);
2073 mchbar_write8(C0DITCTRL + 1, 2);
2074 mchbar_write16(C0DITCTRL + 2, 0x0804);
2075 mchbar_write16(C0DITCTRL + 4, 0x2010);
2076 mchbar_write8(C0DITCTRL + 6, 0x40);
2077 mchbar_write16(C0DITCTRL + 8, 0x091c);
2078 mchbar_write8(C0DITCTRL + 10, 0xf2);
2079 mchbar_setbits8(C0BYPCTRL, 1 << 0);
2080 mchbar_setbits8(C0CWBCTRL, 1 << 0);
2081 mchbar_setbits16(C0ARBSPL, 1 << 8);
2083 pci_or_config8(HOST_BRIDGE, 0xf0, 1);
2084 mchbar_write32(SBCTL, 0x00000002);
2085 mchbar_write32(SBCTL2, 0x20310002);
2086 mchbar_write32(SLIMCFGTMG, 0x02020302);
2087 mchbar_write32(HIT0, 0x001f1806);
2088 mchbar_write32(HIT1, 0x01102800);
2089 mchbar_write32(HIT2, 0x07000000);
2090 mchbar_write32(HIT3, 0x01014010);
2091 mchbar_write32(HIT4, 0x0f038000);
2092 pci_and_config8(HOST_BRIDGE, 0xf0, ~1);
2094 u32 nranks, curranksize, maxranksize, dra;
2095 u8 rankmismatch;
2096 static const u8 drbtab[10] = {0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8, 0x20, 0x10};
2098 nranks = 0;
2099 curranksize = 0;
2100 maxranksize = 0;
2101 rankmismatch = 0;
2103 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2104 nranks++;
2105 dra = (u8)((mchbar_read32(C0DRA01) >> (8 * r)) & 0x7f);
2106 curranksize = drbtab[dra];
2107 if (maxranksize == 0) {
2108 maxranksize = curranksize;
2110 if (curranksize != maxranksize) {
2111 rankmismatch = 1;
2115 reg8 = 0;
2116 switch (nranks) {
2117 case 4:
2118 if (rankmismatch) {
2119 reg8 = 0x64;
2120 } else {
2121 reg8 = 0xa4;
2123 break;
2124 case 1:
2125 case 3:
2126 reg8 = 0x64;
2127 break;
2128 case 2:
2129 if (rankmismatch) {
2130 reg8 = 0x64;
2131 } else {
2132 reg8 = 0x24;
2134 break;
2135 default:
2136 die("Invalid number of ranks found, halt\n");
2137 break;
2139 mchbar_clrsetbits8(CHDECMISC, 0xfc, reg8 & 0xfc);
2140 mchbar_clrbits32(NOACFGBUSCTL, 1 << 31);
2142 mchbar_write32(HTBONUS0, 0xf);
2143 mchbar_setbits8(C0COREBONUS + 4, 1 << 0);
2145 mchbar_clrbits32(HIT3, 7 << 25);
2146 mchbar_clrsetbits32(HIT4, 3 << 18, 1 << 18);
2148 u32 clkcx[2][2][3] = {
2150 {0x00000000, 0x0c080302, 0x08010204}, /* FSB = 667, DDR = 667 */
2151 {0x02040000, 0x08100102, 0x00000000}, /* FSB = 667, DDR = 800 */
2154 {0x18000000, 0x3021060c, 0x20010208}, /* FSB = 800, DDR = 667 */
2155 {0x00000000, 0x0c090306, 0x00000000}, /* FSB = 800, DDR = 800 */
2159 fsb_freq = s->selected_timings.fsb_clock;
2160 ddr_freq = s->selected_timings.mem_clock;
2162 mchbar_write32(CLKXSSH2X2MD + 0, clkcx[fsb_freq][ddr_freq][0]);
2163 mchbar_write32(CLKXSSH2X2MD + 4, clkcx[fsb_freq][ddr_freq][1]);
2164 mchbar_write32(CLKXSSH2MCBYP + 4, clkcx[fsb_freq][ddr_freq][2]);
2166 mchbar_clrbits8(HIT4, 1 << 1);
2169 static void sdram_periodic_rcomp(void)
2171 mchbar_clrbits8(COMPCTRL1, 1 << 1);
2172 while ((mchbar_read32(COMPCTRL1) & (1 << 31)) > 0) {
2175 mchbar_clrbits16(CSHRMISCCTL, 3 << 12);
2176 mchbar_setbits8(CMNDQFIFORST, 1 << 7);
2177 mchbar_clrsetbits16(XCOMPDFCTRL, 0x0f, 0x09);
2179 mchbar_setbits8(COMPCTRL1, 1 << 7 | 1 << 1);
2182 static void sdram_new_trd(struct sysinfo *s)
2184 u8 pidelay, i, j, k, cc, trd_perphase[5];
2185 u8 bypass, freqgb, trd, reg8, txfifo;
2186 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2187 u16 tmclk, thclk, buffertocore, postcalib;
2188 static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2189 static const u16 trd_adjust[2][2][5] = {
2191 {3000, 3000, 0,0,0},
2192 {1000,2000,3000,1500,2500}
2195 {2000,1000,3000,0,0},
2196 {2500, 2500, 0,0,0}
2199 freqgb = 110;
2200 buffertocore = 5000;
2201 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2202 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2203 tmclk = tmclk * 100 / freqgb;
2204 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2205 switch (s->selected_timings.mem_clock) {
2206 case MEM_CLOCK_667MHz:
2207 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2208 cc = 2;
2209 } else {
2210 cc = 3;
2212 break;
2213 default:
2214 case MEM_CLOCK_800MHz:
2215 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2216 cc = 5;
2217 } else {
2218 cc = 2;
2220 break;
2222 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2223 maxrcvendelay = 0;
2224 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2226 for (i = 0; i < 8; i++) {
2227 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 3) * (u32)(tmclk));
2228 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 3) * (u32)(tmclk) / 2);
2229 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 3) * (u32)(tmclk) / 4);
2230 rcvendelay += (u32)(pidelay * s->pi[i]);
2231 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2234 if ((mchbar_read8(HMBYPCP + 3) == 0xff) && (mchbar_read8(HMCCMC) & (1 << 7))) {
2235 bypass = 1;
2236 } else {
2237 bypass = 0;
2240 txfifo = 0;
2241 reg8 = (mchbar_read8(CSHRFIFOCTL) & 0x0e) >> 1;
2242 txfifo = txfifo_lut[reg8] & 0x07;
2244 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2245 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2246 if (s->async) {
2247 datadelay += tmclk / 2;
2250 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2251 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2253 if (j == 0 && k == 0) {
2254 datadelay -= 3084;
2257 trd = 0;
2258 for (i = 0; i < cc; i++) {
2259 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2260 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2261 trd_perphase[i] += 1;
2262 if (trd_perphase[i] > trd) {
2263 trd = trd_perphase[i];
2267 mchbar_clrsetbits16(C0STATRDCTRL, 0x1f << 8, trd << 8);
2270 static void sdram_powersettings(struct sysinfo *s)
2272 u8 j;
2273 u32 reg32;
2275 /* Thermal sensor */
2276 mchbar_write8(TSC1, 0x9b);
2277 mchbar_clrsetbits32(TSTTP, 0x00ffffff, 0x1d00);
2278 mchbar_write8(THERM1, 0x08);
2279 mchbar_write8(TSC3, 0);
2280 mchbar_clrsetbits8(TSC2, 0x0f, 0x04);
2281 mchbar_clrsetbits8(THERM1, 1, 1);
2282 mchbar_clrsetbits8(TCO, 1 << 7, 1 << 7);
2284 /* Clock gating */
2285 mchbar_clrbits32(PMMISC, 1 << 18 | 1 << 0);
2286 mchbar_clrbits8(SBCTL3 + 3, 1 << 7);
2287 mchbar_clrbits8(CISDCTRL + 3, 1 << 7);
2288 mchbar_clrbits16(CICGDIS, 0x1fff);
2289 mchbar_clrbits32(SBCLKGATECTRL, 0x1ffff);
2290 mchbar_clrsetbits16(HICLKGTCTL, 0x03ff, 0x06);
2291 mchbar_clrsetbits32(HTCLKGTCTL, ~0, 0x20);
2292 mchbar_clrbits8(TSMISC, 1 << 0);
2293 mchbar_write8(C0WRDPYN, s->selected_timings.CAS - 1 + 0x15);
2294 mchbar_clrsetbits16(CLOCKGATINGI, 0x07fc, 0x0040);
2295 mchbar_clrsetbits16(CLOCKGATINGII, 0x0fff, 0x0d00);
2296 mchbar_clrbits16(CLOCKGATINGIII, 0x0d80);
2297 mchbar_write16(GTDPCGC + 2, 0xffff);
2299 /* Sequencing */
2300 mchbar_clrsetbits32(HPWRCTL1, 0x1fffffff, 0x1f643fff);
2301 mchbar_clrsetbits32(HPWRCTL2, 0xffffff7f, 0x02010000);
2302 mchbar_clrsetbits16(HPWRCTL3, 7 << 12, 3 << 12);
2304 /* Power */
2305 mchbar_clrsetbits32(GFXC3C4, 0xffff0003, 0x10100000);
2306 mchbar_clrsetbits32(PMDSLFRC, 0x0001bff7, 0x00000078);
2308 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz)
2309 mchbar_clrsetbits16(PMMSPMRES, 0x03ff, 0x00c8);
2310 else
2311 mchbar_clrsetbits16(PMMSPMRES, 0x03ff, 0x0100);
2313 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2315 mchbar_clrsetbits32(PMCLKRC, 0x01fff37f, 0x10810700);
2316 mchbar_clrsetbits8(PMPXPRC, 7, 1);
2317 mchbar_clrbits8(PMBAK, 1 << 1);
2319 static const u16 ddr2lut[2][4][2] = {
2321 {0x0000, 0x0000},
2322 {0x019A, 0x0039},
2323 {0x0099, 0x1049},
2324 {0x0000, 0x0000},
2327 {0x0000, 0x0000},
2328 {0x019A, 0x0039},
2329 {0x0099, 0x1049},
2330 {0x0099, 0x2159},
2334 mchbar_write16(C0C2REG, 0x7a89);
2335 mchbar_write8(SHC2REGII, 0xaa);
2336 mchbar_write16(SHC2REGII + 1, ddr2lut[j][s->selected_timings.CAS - 3][1]);
2337 mchbar_clrsetbits16(SHC2REGI, 0x7fff, ddr2lut[j][s->selected_timings.CAS - 3][0]);
2338 mchbar_clrsetbits16(CLOCKGATINGIII, 0xf000, 0xf000);
2339 mchbar_clrsetbits8(CSHWRIOBONUSX, 0x77, 4 << 4 | 4);
2341 reg32 = s->nodll ? 0x30000000 : 0;
2343 mchbar_clrsetbits32(C0COREBONUS, 0xf << 24, 1 << 29 | reg32);
2345 mchbar_clrsetbits32(CLOCKGATINGI, 0xf << 20, 0xf << 20);
2346 mchbar_clrsetbits32(CLOCKGATINGII - 1, 0x001ff000, 0xbf << 20);
2347 mchbar_clrsetbits16(SHC3C4REG2, 0x1f7f, 0x0b << 8 | 7 << 4 | 0x0b);
2348 mchbar_write16(SHC3C4REG3, 0x3264);
2349 mchbar_clrsetbits16(SHC3C4REG4, 0x3f3f, 0x14 << 8 | 0x0a);
2351 mchbar_setbits32(C1COREBONUS, 1 << 31 | 1 << 13);
2354 static void sdram_programddr(void)
2356 mchbar_clrsetbits16(CLOCKGATINGII, 0x03ff, 0x0100);
2357 mchbar_clrsetbits16(CLOCKGATINGIII, 0x003f, 0x0010);
2358 mchbar_clrsetbits16(CLOCKGATINGI, 0x7000, 0x2000);
2360 mchbar_clrbits8(CSHRPDCTL, 7 << 1);
2361 mchbar_clrbits8(CSHRWRIOMLNS, 3 << 2);
2362 mchbar_clrbits8(C0MISCCTLy(0), 7 << 1);
2363 mchbar_clrbits8(C0MISCCTLy(1), 7 << 1);
2364 mchbar_clrbits8(C0MISCCTLy(2), 7 << 1);
2365 mchbar_clrbits8(C0MISCCTLy(3), 7 << 1);
2366 mchbar_clrbits8(C0MISCCTLy(4), 7 << 1);
2367 mchbar_clrbits8(C0MISCCTLy(5), 7 << 1);
2368 mchbar_clrbits8(C0MISCCTLy(6), 7 << 1);
2369 mchbar_clrbits8(C0MISCCTLy(7), 7 << 1);
2370 mchbar_clrbits8(CSHRWRIOMLNS, 1 << 1);
2372 mchbar_clrbits16(CSHRMISCCTL, 1 << 10);
2373 mchbar_clrbits16(CLOCKGATINGIII, 0x0dc0);
2374 mchbar_clrbits8(C0WRDPYN, 1 << 7);
2375 mchbar_clrbits32(C0COREBONUS, 1 << 22);
2376 mchbar_clrbits16(CLOCKGATINGI, 0x80fc);
2377 mchbar_clrbits16(CLOCKGATINGII, 0x0c00);
2379 mchbar_clrbits8(CSHRPDCTL, 0x0d);
2380 mchbar_clrbits8(C0MISCCTLy(0), 1 << 0);
2381 mchbar_clrbits8(C0MISCCTLy(1), 1 << 0);
2382 mchbar_clrbits8(C0MISCCTLy(2), 1 << 0);
2383 mchbar_clrbits8(C0MISCCTLy(3), 1 << 0);
2384 mchbar_clrbits8(C0MISCCTLy(4), 1 << 0);
2385 mchbar_clrbits8(C0MISCCTLy(5), 1 << 0);
2386 mchbar_clrbits8(C0MISCCTLy(6), 1 << 0);
2387 mchbar_clrbits8(C0MISCCTLy(7), 1 << 0);
2389 mchbar_clrsetbits32(C0STATRDCTRL, 7 << 20, 3 << 20);
2390 mchbar_clrbits32(C0COREBONUS, 1 << 20);
2391 mchbar_setbits8(C0DYNSLVDLLEN, 0x1e);
2392 mchbar_setbits8(C0DYNSLVDLLEN2, 0x03);
2393 mchbar_clrsetbits32(SHCYCTRKCKEL, 3 << 26, 1 << 26);
2394 mchbar_setbits16(C0STATRDCTRL, 3 << 13);
2395 mchbar_setbits32(C0CKECTRL, 1 << 16);
2396 mchbar_setbits8(C0COREBONUS, 1 << 4);
2397 mchbar_setbits32(CLOCKGATINGI - 1, 0xf << 24);
2398 mchbar_setbits8(CSHWRIOBONUS, 7);
2399 mchbar_setbits8(C0DYNSLVDLLEN, 3 << 6);
2400 mchbar_setbits8(SHC2REGIII, 7);
2401 mchbar_clrsetbits16(SHC2MINTM, ~0, 1 << 7);
2402 mchbar_clrsetbits8(SHC2IDLETM, 0xff, 0x10);
2403 mchbar_setbits16(C0COREBONUS, 0xf << 5);
2404 mchbar_setbits8(CSHWRIOBONUS, 3 << 3);
2405 mchbar_setbits8(CSHRMSTDYNDLLENB, 0x0d);
2406 mchbar_setbits16(SHC3C4REG1, 0x0a3f);
2407 mchbar_setbits8(C0STATRDCTRL, 3);
2408 mchbar_clrsetbits8(C0REFRCTRL2, 0xff, 0x4a);
2409 mchbar_clrbits8(C0COREBONUS + 4, 3 << 5);
2410 mchbar_setbits16(C0DYNSLVDLLEN, 0x0321);
2413 static void sdram_programdqdqs(struct sysinfo *s)
2415 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2416 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2417 u8 repeat, halfclk, feature, reg8, push;
2418 u16 cwb, pimdclk;
2419 u32 reg32;
2420 static const u8 txfifotab[8] = {0, 7, 6, 5, 2, 1, 4, 3};
2422 tpi = 3000;
2423 dqdqs_out = 4382;
2424 dqdqs_outdelay = 5083;
2425 dqdqs_delay = 4692;
2426 coretomcp = 0;
2427 txdelay = 0;
2428 halfclk = 0;
2429 tmaxunmask = 0;
2430 tmaxpi = 0;
2431 repeat = 2;
2432 feature = 0;
2433 cwb = 0;
2434 pimdclk = 0;
2435 reg32 = 0;
2436 push = 0;
2437 reg8 = 0;
2439 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2440 refclk = 3000 - mdclk;
2442 coretomcp = ((mchbar_read8(C0ADDCSCTRL) >> 2) & 0x3) + 1;
2443 coretomcp *= mdclk;
2445 reg8 = (mchbar_read8(CSHRFIFOCTL) & 0x0e) >> 1;
2447 while (repeat) {
2448 txdelay = mdclk * (
2449 ((mchbar_read16(C0GNT2LNCH1) >> 8) & 0x7) +
2450 (mchbar_read8(C0WRDATACTRL) & 0xf) +
2451 (mchbar_read8(C0WRDATACTRL + 1) & 0x1)
2453 txfifotab[reg8]*(mdclk / 2) +
2454 coretomcp +
2455 refclk +
2456 cwb;
2457 halfclk = (mchbar_read8(C0MISCCTL) >> 1) & 0x1;
2458 if (halfclk) {
2459 txdelay -= mdclk / 2;
2460 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2461 } else {
2462 reg32 = dqdqs_outdelay + coretomcp;
2465 tmaxunmask = txdelay - mdclk - dqdqs_out;
2466 tmaxpi = tmaxunmask - tpi;
2468 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2469 if (repeat == 2) {
2470 mchbar_clrbits32(C0COREBONUS, 1 << 23);
2472 feature = 1;
2473 repeat = 0;
2474 } else {
2475 repeat--;
2476 mchbar_setbits32(C0COREBONUS, 1 << 23);
2477 cwb = 2 * mdclk;
2481 if (!feature) {
2482 mchbar_clrbits8(CLOCKGATINGI, 3);
2483 return;
2485 mchbar_setbits8(CLOCKGATINGI, 3);
2486 mchbar_clrsetbits16(CLOCKGATINGIII, 0xf << 12, pimdclk << 12);
2487 mchbar_clrsetbits8(CSHWRIOBONUSX, 0x77, push << 4 | push);
2488 mchbar_clrsetbits32(C0COREBONUS, 0xf << 24, 3 << 24);
2492 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2494 void sdram_initialize(int boot_path, const u8 *spd_addresses)
2496 struct sysinfo si;
2497 const char *boot_str[] = {"Normal", "Reset", "Resume"};
2499 PRINTK_DEBUG("Setting up RAM controller.\n");
2501 memset(&si, 0, sizeof(si));
2503 si.boot_path = boot_path;
2504 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
2505 si.spd_map[0] = spd_addresses[0];
2506 si.spd_map[1] = spd_addresses[1];
2507 si.spd_map[2] = spd_addresses[2];
2508 si.spd_map[3] = spd_addresses[3];
2510 sdram_read_spds(&si);
2512 /* Choose Common Frequency */
2513 sdram_detect_ram_speed(&si);
2515 /* Determine smallest common tRAS, tRP, tRCD, etc */
2516 sdram_detect_smallest_params(&si);
2518 /* Enable HPET */
2519 enable_hpet();
2521 mchbar_setbits16(CPCTL, 1 << 15);
2523 sdram_clk_crossing(&si);
2525 sdram_checkreset();
2526 PRINTK_DEBUG("Done checkreset\n");
2528 sdram_clkmode(&si);
2529 PRINTK_DEBUG("Done clkmode\n");
2531 sdram_timings(&si);
2532 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2534 if (si.boot_path != BOOT_PATH_RESET) {
2535 sdram_dlltiming(&si);
2536 PRINTK_DEBUG("Done dlltiming\n");
2539 if (si.boot_path != BOOT_PATH_RESET) {
2540 sdram_rcomp(&si);
2541 PRINTK_DEBUG("Done RCOMP\n");
2544 sdram_odt(&si);
2545 PRINTK_DEBUG("Done odt\n");
2547 if (si.boot_path != BOOT_PATH_RESET) {
2548 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
2552 sdram_mmap(&si);
2553 PRINTK_DEBUG("Done mmap\n");
2555 /* Enable DDR IO buffer */
2556 mchbar_clrsetbits8(C0IOBUFACTCTL, 0x3f, 0x08);
2557 mchbar_setbits8(C0RSTCTL, 1 << 0);
2559 sdram_rcompupdate(&si);
2560 PRINTK_DEBUG("Done RCOMP update\n");
2562 mchbar_setbits8(HIT4, 1 << 1);
2564 if (si.boot_path != BOOT_PATH_RESUME) {
2565 mchbar_setbits32(C0CKECTRL, 1 << 27);
2567 sdram_jedecinit(&si);
2568 PRINTK_DEBUG("Done MRS\n");
2571 sdram_misc(&si);
2572 PRINTK_DEBUG("Done misc\n");
2574 sdram_zqcl(&si);
2575 PRINTK_DEBUG("Done zqcl\n");
2577 if (si.boot_path != BOOT_PATH_RESUME) {
2578 mchbar_setbits32(C0REFRCTRL2, 3 << 30);
2581 sdram_dradrb(&si);
2582 PRINTK_DEBUG("Done dradrb\n");
2584 sdram_rcven(&si);
2585 PRINTK_DEBUG("Done rcven\n");
2587 sdram_new_trd(&si);
2588 PRINTK_DEBUG("Done tRD\n");
2590 sdram_mmap_regs(&si);
2591 PRINTK_DEBUG("Done mmap regs\n");
2593 sdram_enhancedmode(&si);
2594 PRINTK_DEBUG("Done enhanced mode\n");
2596 sdram_powersettings(&si);
2597 PRINTK_DEBUG("Done power settings\n");
2599 sdram_programddr();
2600 PRINTK_DEBUG("Done programming ddr\n");
2602 sdram_programdqdqs(&si);
2603 PRINTK_DEBUG("Done programming dqdqs\n");
2605 sdram_periodic_rcomp();
2606 PRINTK_DEBUG("Done periodic RCOMP\n");
2608 /* Set init done */
2609 mchbar_setbits32(C0REFRCTRL2, 1 << 30);
2611 /* Tell ICH7 that we're done */
2612 pci_and_config8(PCI_DEV(0, 0x1f, 0), 0xa2, (u8)~(1 << 7));
2614 /* Tell northbridge we're done */
2615 pci_or_config8(HOST_BRIDGE, 0xf4, 1);
2617 printk(BIOS_DEBUG, "RAM initialization finished.\n");