coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
raminit.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
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>
12 #include "pineview.h"
13 #include "raminit.h"
14 #include <spd.h>
15 #include <string.h>
16 
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
23 
24 #define MAX_TCLK_667 0x30
25 #define MAX_TCLK_800 0x25
26 #define MAX_TAC_667 0x45
27 #define MAX_TAC_800 0x40
28 
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))
39 
40 #define UBDIMM 1
41 #define SODIMM 2
42 
43 #define TOTAL_CHANNELS 1
44 #define TOTAL_DIMMS 2
45 
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)
68 
69 #define RANKS_PER_CHANNEL 4
70 
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))
79 
80 static bool rank_is_populated(struct dimminfo dimms[], u8 ch, u8 r)
81 {
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))));
86 }
87 
88 static inline void barrier(void)
89 {
90  __asm__ __volatile__("": : :"memory");
91 }
92 
93 static int decode_spd(struct dimminfo *d, int i)
94 {
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;
100  }
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);
130 
131  return 0;
132 }
133 
134 /*
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
143  */
144 static void find_ramconfig(struct sysinfo *s, u32 chan)
145 {
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/SS
153  if (s->dimms[(chan>>1) + 1].width == 0) {
154  // NC/8SS
155  s->dimm_config[chan] = 1;
156  } else {
157  // NC/16SS
158  s->dimm_config[chan] = 1;
159  }
160  } else {
161  // NC/DS
162  if (s->dimms[(chan>>1) + 1].width == 0) {
163  // NC/8DS
164  s->dimm_config[chan] = 5;
165  } else {
166  // NC/16DS
167  s->dimm_config[chan] = 2;
168  }
169  }
170  } else if (s->dimms[chan>>1].sides == 1) {
171  // SS
172  if (s->dimms[(chan>>1) + 1].sides == 0) {
173  // SS/NC
174  if (s->dimms[chan>>1].width == 0) {
175  // 8SS/NC
176  s->dimm_config[chan] = 1;
177  } else {
178  // 16SS/NC
179  s->dimm_config[chan] = 1;
180  }
181  } else if (s->dimms[(chan>>1) + 1].sides == 1) {
182  // SS/SS
183  if (s->dimms[chan>>1].width == 0) {
184  if (s->dimms[(chan>>1) + 1].width == 0) {
185  // 8SS/8SS
186  s->dimm_config[chan] = 3;
187  } else {
188  // 8SS/16SS
189  die("Mixed Not supported\n");
190  }
191  } else {
192  if (s->dimms[(chan>>1) + 1].width == 0) {
193  // 16SS/8SS
194  die("Mixed Not supported\n");
195  } else {
196  // 16SS/16SS
197  s->dimm_config[chan] = 3;
198  }
199  }
200  } else {
201  // SS/DS
202  if (s->dimms[chan>>1].width == 0) {
203  if (s->dimms[(chan>>1) + 1].width == 0) {
204  // 8SS/8DS
205  die("Mixed Not supported\n");
206  } else {
207  die("Mixed Not supported\n");
208  }
209  } else {
210  if (s->dimms[(chan>>1) + 1].width == 0) {
211  // 16SS/8DS
212  die("Mixed Not supported\n");
213  } else {
214  die("Mixed Not supported\n");
215  }
216  }
217  }
218  } else {
219  // DS
220  if (s->dimms[(chan>>1) + 1].sides == 0) {
221  // DS/NC
222  if (s->dimms[chan>>1].width == 0) {
223  // 8DS/NC
224  s->dimm_config[chan] = 5;
225  } else {
226  s->dimm_config[chan] = 4;
227  }
228  } else if (s->dimms[(chan>>1) + 1].sides == 1) {
229  // DS/SS
230  if (s->dimms[chan>>1].width == 0) {
231  if (s->dimms[(chan>>1) + 1].width == 0) {
232  // 8DS/8SS
233  die("Mixed Not supported\n");
234  } else {
235  // 8DS/16SS
236  die("Mixed Not supported\n");
237  }
238  } else {
239  if (s->dimms[(chan>>1) + 1].width == 0) {
240  die("Mixed Not supported\n");
241  } else {
242  // 16DS/16DS
243  s->dimm_config[chan] = 4;
244  }
245  }
246  } else {
247  // DS/DS
248  if (s->dimms[chan>>1].width == 0 && s->dimms[(chan>>1)+1].width == 0) {
249  // 8DS/8DS
250  s->dimm_config[chan] = 6;
251  }
252  }
253  }
254 }
255 
256 static void sdram_read_spds(struct sysinfo *s)
257 {
258  u8 i, chan;
259  s->dt0mode = 0;
260  FOR_EACH_DIMM(i) {
261  if (i2c_eeprom_read(s->spd_map[i], 0, 64, s->dimms[i].spd_data) != 64)
262  s->dimms[i].card_type = 0;
263 
264  s->dimms[i].card_type = s->dimms[i].spd_data[62] & 0x1f;
265  hexdump(s->dimms[i].spd_data, 64);
266  }
267 
268  s->spd_type = 0;
269  FOR_EACH_POPULATED_DIMM(s->dimms, i) {
270  switch (s->dimms[i].spd_data[2]) {
271  case 0x8:
272  s->spd_type = DDR2;
273  break;
274  case 0xb:
275  default:
276  die("DIMM type mismatch\n");
277  break;
278  }
279  }
280 
281  int err = 1;
282  FOR_EACH_POPULATED_DIMM(s->dimms, i) {
283  err = decode_spd(&s->dimms[i], i);
284  s->dt0mode |= (s->dimms[i].spd_data[49] & 0x2) >> 1;
285  }
286  if (err) {
287  die("No memory dimms, halt\n");
288  }
289 
290  FOR_EACH_POPULATED_CHANNEL(s->dimms, chan) {
291  find_ramconfig(s, chan);
292  PRINTK_DEBUG(" Config[CH%d] : %d\n", chan, s->dimm_config[chan]);
293  }
294 }
295 
296 #if CONFIG(DEBUG_RAM_SETUP)
297 static u32 fsb_reg_to_mhz(u32 speed)
298 {
299  return (speed * 133) + 667;
300 }
301 
302 static u32 ddr_reg_to_mhz(u32 speed)
303 {
304  return (speed == 0) ? 667 : (speed == 1) ? 800 : 0;
305 }
306 #endif
307 
308 // Return the position of the least significant set bit, 0-indexed.
309 // 0 does not have a lsb, so return -1 for error.
310 static int lsbpos(u8 val)
311 {
312  for (int i = 0; i < 8; i++)
313  if (val & (1 << i))
314  return i;
315  return -1;
316 }
317 
318 // Return the position of the most significant set bit, 0-indexed.
319 // 0 does not have a msb, so return -1 for error.
320 static int msbpos(u8 val)
321 {
322  for (int i = 7; i >= 0; i--)
323  if (val & (1 << i))
324  return i;
325  return -1;
326 }
327 
329 {
330  static const u16 mult[6] = {
331  3000, // 667
332  2500, // 800
333  };
334 
335  u8 i;
336  u32 maxtras = 0;
337  u32 maxtrp = 0;
338  u32 maxtrcd = 0;
339  u32 maxtwr = 0;
340  u32 maxtrfc = 0;
341  u32 maxtwtr = 0;
342  u32 maxtrrd = 0;
343  u32 maxtrtp = 0;
344 
345  FOR_EACH_POPULATED_DIMM(s->dimms, i) {
346  maxtras = MAX(maxtras, (s->dimms[i].spd_data[30] * 1000));
347  maxtrp = MAX(maxtrp, (s->dimms[i].spd_data[27] * 1000) >> 2);
348  maxtrcd = MAX(maxtrcd, (s->dimms[i].spd_data[29] * 1000) >> 2);
349  maxtwr = MAX(maxtwr, (s->dimms[i].spd_data[36] * 1000) >> 2);
350  maxtrfc = MAX(maxtrfc, (s->dimms[i].spd_data[42] * 1000) +
351  (s->dimms[i].spd_data[40] & 0xf));
352  maxtwtr = MAX(maxtwtr, (s->dimms[i].spd_data[37] * 1000) >> 2);
353  maxtrrd = MAX(maxtrrd, (s->dimms[i].spd_data[28] * 1000) >> 2);
354  maxtrtp = MAX(maxtrtp, (s->dimms[i].spd_data[38] * 1000) >> 2);
355  }
356  /*
357  * TODO: on DDR3 there might be some minimal required values for some
358  * Timings: MIN_TRAS = 9, MIN_TRP = 3, MIN_TRCD = 3, MIN_TWR = 3,
359  * MIN_TWTR = 4, MIN_TRRD = 2, MIN_TRTP = 4
360  */
361  s->selected_timings.tRAS = MIN(24, DIV_ROUND_UP(maxtras,
362  mult[s->selected_timings.mem_clock]));
363  s->selected_timings.tRP = MIN(10, DIV_ROUND_UP(maxtrp,
364  mult[s->selected_timings.mem_clock]));
365  s->selected_timings.tRCD = MIN(10, DIV_ROUND_UP(maxtrcd,
366  mult[s->selected_timings.mem_clock]));
367  s->selected_timings.tWR = MIN(15, DIV_ROUND_UP(maxtwr,
368  mult[s->selected_timings.mem_clock]));
369  /* Needs to be even */
370  s->selected_timings.tRFC = 0xfe & (MIN(78, DIV_ROUND_UP(maxtrfc,
371  mult[s->selected_timings.mem_clock])) + 1);
372  s->selected_timings.tWTR = MIN(15, DIV_ROUND_UP(maxtwtr,
373  mult[s->selected_timings.mem_clock]));
374  s->selected_timings.tRRD = MIN(15, DIV_ROUND_UP(maxtrrd,
375  mult[s->selected_timings.mem_clock]));
376  s->selected_timings.tRTP = MIN(15, DIV_ROUND_UP(maxtrtp,
377  mult[s->selected_timings.mem_clock]));
378 
379  PRINTK_DEBUG("Selected timings:\n");
380  PRINTK_DEBUG("\tFSB: %dMHz\n", fsb_reg_to_mhz(s->selected_timings.fsb_clock));
381  PRINTK_DEBUG("\tDDR: %dMHz\n", ddr_reg_to_mhz(s->selected_timings.mem_clock));
382 
383  PRINTK_DEBUG("\tCAS: %d\n", s->selected_timings.CAS);
384  PRINTK_DEBUG("\ttRAS: %d\n", s->selected_timings.tRAS);
385  PRINTK_DEBUG("\ttRP: %d\n", s->selected_timings.tRP);
386  PRINTK_DEBUG("\ttRCD: %d\n", s->selected_timings.tRCD);
387  PRINTK_DEBUG("\ttWR: %d\n", s->selected_timings.tWR);
388  PRINTK_DEBUG("\ttRFC: %d\n", s->selected_timings.tRFC);
389  PRINTK_DEBUG("\ttWTR: %d\n", s->selected_timings.tWTR);
390  PRINTK_DEBUG("\ttRRD: %d\n", s->selected_timings.tRRD);
391  PRINTK_DEBUG("\ttRTP: %d\n", s->selected_timings.tRTP);
392 }
393 
394 static void sdram_detect_ram_speed(struct sysinfo *s)
395 {
396  u8 cas, reg8;
397  u32 reg32;
398  u32 freq = 0;
399  u32 fsb = 0;
400  u8 i;
401  u8 commoncas = 0;
402  u8 highcas = 0;
403  u8 lowcas = 0;
404 
405  // Core frequency
406  fsb = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0x70) >> 4;
407  if (fsb) {
408  fsb = 5 - fsb;
409  } else {
410  fsb = FSB_CLOCK_800MHz;
411  }
412 
413  // DDR frequency
414  freq = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0x80) >> 7;
415  freq |= (pci_read_config8(HOST_BRIDGE, 0xe4) & 0x03) << 1;
416  if (freq) {
417  freq = 6 - freq;
418  } else {
420  }
421 
422  // Detect a common CAS latency
423  commoncas = 0xff;
424  FOR_EACH_POPULATED_DIMM(s->dimms, i) {
425  commoncas &= s->dimms[i].spd_data[18];
426  }
427  if (commoncas == 0) {
428  die("No common CAS among dimms\n");
429  }
430 
431  // commoncas is nonzero, so these calls will not error
432  u8 msbp = (u8)msbpos(commoncas);
433  u8 lsbp = (u8)lsbpos(commoncas);
434 
435  // Start with fastest common CAS
436  cas = 0;
437  highcas = msbp;
438  lowcas = MAX(lsbp, 5);
439 
440  while (cas == 0 && highcas >= lowcas) {
441  FOR_EACH_POPULATED_DIMM(s->dimms, i) {
442  switch (freq) {
443  case MEM_CLOCK_800MHz:
444  if ((s->dimms[i].spd_data[9] > 0x25) ||
445  (s->dimms[i].spd_data[10] > 0x40)) {
446  // CAS too fast, lower it
447  highcas--;
448  break;
449  } else {
450  cas = highcas;
451  }
452  break;
453  case MEM_CLOCK_667MHz:
454  default:
455  if ((s->dimms[i].spd_data[9] > 0x30) ||
456  (s->dimms[i].spd_data[10] > 0x45)) {
457  // CAS too fast, lower it
458  highcas--;
459  break;
460  } else {
461  cas = highcas;
462  }
463  break;
464  }
465  }
466  }
467  if (highcas < lowcas) {
468  // Timings not supported by MCH, lower the frequency
469  if (freq == MEM_CLOCK_800MHz) {
470  freq--;
471  PRINTK_DEBUG("Run DDR clock speed reduced due to timings\n");
472  } else {
473  die("Timings not supported by MCH\n");
474  }
475  cas = 0;
476  highcas = msbp;
477  lowcas = lsbp;
478  while (cas == 0 && highcas >= lowcas) {
479  FOR_EACH_POPULATED_DIMM(s->dimms, i) {
480  if ((s->dimms[i].spd_data[9] > 0x30) ||
481  (s->dimms[i].spd_data[10] > 0x45)) {
482  // CAS too fast, lower it
483  highcas--;
484  } else {
485  cas = highcas;
486  }
487  }
488  }
489  if (cas == 0) {
490  die("Unsupported dimms\n");
491  }
492  }
493 
494  s->selected_timings.CAS = cas;
495  s->selected_timings.mem_clock = freq;
496  s->selected_timings.fsb_clock = fsb;
497 
498  PRINTK_DEBUG("Drive Memory at %dMHz with CAS = %d clocks\n",
499  ddr_reg_to_mhz(s->selected_timings.mem_clock), s->selected_timings.CAS);
500 
501  // Set memory frequency
502  if (s->boot_path == BOOT_PATH_RESET)
503  return;
504 
505  mchbar_setbits32(PMSTS, 1 << 0);
506 
507  reg32 = (mchbar_read32(CLKCFG) & ~0x70) | (1 << 10);
508  if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
509  reg8 = 3;
510  } else {
511  reg8 = 2;
512  }
513  reg32 |= reg8 << 4;
514  mchbar_write32(CLKCFG, reg32);
515 
516  s->selected_timings.mem_clock = ((mchbar_read32(CLKCFG) >> 4) & 0x7) - 2;
517  if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
518  PRINTK_DEBUG("MCH validated at 800MHz\n");
519  s->nodll = 0;
520  s->maxpi = 63;
521  s->pioffset = 0;
522  } else if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
523  PRINTK_DEBUG("MCH validated at 667MHz\n");
524  s->nodll = 1;
525  s->maxpi = 15;
526  s->pioffset = 1;
527  } else {
528  PRINTK_DEBUG("MCH set to unknown (%02x)\n",
529  (uint8_t) s->selected_timings.mem_clock & 0xff);
530  }
531 }
532 
533 static void sdram_clk_crossing(struct sysinfo *s)
534 {
535  u8 ddr_freq, fsb_freq;
536  static const u32 clkcross[2][2][4] = {
537  {
538  {0xffffffff, 0x05030305, 0x0000ffff, 0x00000000}, /* FSB = 667, DDR = 667 */
539  {0x1f1f1f1f, 0x2a1f1fa5, 0x00000000, 0x05000002}, /* FSB = 667, DDR = 800 */
540  },
541  {
542  {0x1f1f1f1f, 0x0d07070b, 0x00000000, 0x00000000}, /* FSB = 800, DDR = 667 */
543  {0xffffffff, 0x05030305, 0x0000ffff, 0x00000000}, /* FSB = 800, DDR = 800 */
544  },
545  };
546 
547  ddr_freq = s->selected_timings.mem_clock;
548  fsb_freq = s->selected_timings.fsb_clock;
549 
550  mchbar_write32(HMCCMP, clkcross[fsb_freq][ddr_freq][0]);
551  mchbar_write32(HMDCMP, clkcross[fsb_freq][ddr_freq][1]);
552  mchbar_write32(HMBYPCP, clkcross[fsb_freq][ddr_freq][2]);
554  mchbar_write32(HMDCPEXT, clkcross[fsb_freq][ddr_freq][3]);
555 
556  mchbar_setbits32(HMCCMC, 1 << 7);
557 
558  if ((fsb_freq == 0) && (ddr_freq == 1)) {
561  mchbar_write32(CLKXSSH2MD + 4, 0);
562  }
563 
564  static const u32 clkcross2[2][2][8] = {
565  {
566  { // FSB = 667, DDR = 667
567  0x00000000, 0x08010204, 0x00000000, 0x08010204,
568  0x00000000, 0x00000000, 0x00000000, 0x04080102,
569  },
570  { // FSB = 667, DDR = 800
571  0x04080000, 0x10010002, 0x10000000, 0x20010208,
572  0x00000000, 0x00000004, 0x02040000, 0x08100102,
573  },
574  },
575  {
576  { // FSB = 800, DDR = 667
577  0x10000000, 0x20010208, 0x04080000, 0x10010002,
578  0x00000000, 0x00000000, 0x08000000, 0x10200204,
579  },
580  { // FSB = 800, DDR = 800
581  0x00000000, 0x08010204, 0x00000000, 0x08010204,
582  0x00000000, 0x00000000, 0x00000000, 0x04080102,
583  },
584  },
585  };
586 
587  mchbar_write32(CLKXSSH2MCBYP, clkcross2[fsb_freq][ddr_freq][0]);
588  mchbar_write32(CLKXSSH2MCRDQ, clkcross2[fsb_freq][ddr_freq][0]);
589  mchbar_write32(CLKXSSH2MCRDCST, clkcross2[fsb_freq][ddr_freq][0]);
590  mchbar_write32(CLKXSSH2MCBYP + 4, clkcross2[fsb_freq][ddr_freq][1]);
591  mchbar_write32(CLKXSSH2MCRDQ + 4, clkcross2[fsb_freq][ddr_freq][1]);
592  mchbar_write32(CLKXSSH2MCRDCST + 4, clkcross2[fsb_freq][ddr_freq][1]);
593  mchbar_write32(CLKXSSMC2H, clkcross2[fsb_freq][ddr_freq][2]);
594  mchbar_write32(CLKXSSMC2H + 4, clkcross2[fsb_freq][ddr_freq][3]);
595  mchbar_write32(CLKXSSMC2HALT, clkcross2[fsb_freq][ddr_freq][4]);
596  mchbar_write32(CLKXSSMC2HALT + 4, clkcross2[fsb_freq][ddr_freq][5]);
597  mchbar_write32(CLKXSSH2X2MD, clkcross2[fsb_freq][ddr_freq][6]);
598  mchbar_write32(CLKXSSH2X2MD + 4, clkcross2[fsb_freq][ddr_freq][7]);
599 }
600 
601 static void sdram_clkmode(struct sysinfo *s)
602 {
603  u8 ddr_freq;
604  u16 mpll_ctl;
605 
608 
609  if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
610  ddr_freq = 0;
611  mpll_ctl = 1;
612  } else {
613  ddr_freq = 1;
614  mpll_ctl = (1 << 8) | (1 << 5);
615  }
616  if (s->boot_path != BOOT_PATH_RESET)
617  mchbar_clrsetbits16(MPLLCTL, 0x033f, mpll_ctl);
618 
619  mchbar_write32(C0GNT2LNCH1, 0x58001117);
620  mchbar_setbits32(C0STATRDCTRL, 1 << 23);
621 
622  const u32 cas_to_reg[2][4] = {
623  {0x00000000, 0x00030100, 0x0c240201, 0x00000000}, /* DDR = 667 */
624  {0x00000000, 0x00030100, 0x0c240201, 0x10450302} /* DDR = 800 */
625  };
626 
627  mchbar_write32(C0GNT2LNCH2, cas_to_reg[ddr_freq][s->selected_timings.CAS - 3]);
628 }
629 
630 static void sdram_timings(struct sysinfo *s)
631 {
632  u8 i, j, ch, r, ta1, ta2, ta3, ta4, trp, bank, page, flag;
633  u8 reg8, wl;
634  u16 reg16;
635  u32 reg32, reg2;
636 
637  static const u8 pagetab[2][2] = {
638  {0x0e, 0x12},
639  {0x10, 0x14},
640  };
641 
642  /* Only consider DDR2 */
643  wl = s->selected_timings.CAS - 1;
644  ta1 = ta2 = 6;
645  ta3 = s->selected_timings.CAS;
646  ta4 = 8;
647  s->selected_timings.tRFC = (s->selected_timings.tRFC + 1) & 0xfe;
648  trp = 0;
649  bank = 1;
650  page = 0;
651 
652  mchbar_write8(C0LATCTRL, (wl - 3) << 4 | (s->selected_timings.CAS - 3));
653 
654  FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
655  i = ch << 1;
656  if (s->dimms[i].banks == 1) {
657  trp = 1;
658  bank = 0;
659  }
660  if (s->dimms[i].page_size == 2048) {
661  page = 1;
662  }
663  }
664  PRINTK_DEBUG("trp=%d bank=%d page=%d\n",trp, bank, page);
665 
666  if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
667  flag = 0;
668  } else {
669  flag = 1;
670  }
671 
673  mchbar_write16(C0CYCTRKPCHG, (wl + 4 + s->selected_timings.tWR) << 6 |
674  (2 + MAX(s->selected_timings.tRTP, 2)) << 2 | 1);
675 
676  reg32 = (bank << 21) | (s->selected_timings.tRRD << 17) |
677  (s->selected_timings.tRP << 13) | ((s->selected_timings.tRP + trp) << 9) |
678  s->selected_timings.tRFC;
679 
680  if (bank == 0) {
681  reg32 |= (pagetab[flag][page] << 22);
682  }
683  /* FIXME: Why not do a single dword write? */
684  mchbar_write16(C0CYCTRKACT + 0, (u16)(reg32));
685  mchbar_write16(C0CYCTRKACT + 2, (u16)(reg32 >> 16));
686 
687  /* FIXME: Only applies to DDR2 */
688  reg16 = (mchbar_read16(C0CYCTRKACT + 2) & 0x0fc0) >> 6;
689  mchbar_clrsetbits16(SHCYCTRKCKEL, 0x3f << 7, reg16 << 7);
690 
691  reg16 = (s->selected_timings.tRCD << 12) | (4 << 8) | (ta2 << 4) | ta4;
692  mchbar_write16(C0CYCTRKWR, reg16);
693 
694  reg32 = (s->selected_timings.tRCD << 17) | ((wl + 4 + s->selected_timings.tWTR) << 12) |
695  (ta3 << 8) | (4 << 4) | ta1;
696  mchbar_write32(C0CYCTRKRD, reg32);
697 
698  reg16 = ((s->selected_timings.tRP + trp) << 9) | s->selected_timings.tRFC;
699 
700  /* FIXME: Why not do a single word write? */
701  mchbar_write8(C0CYCTRKREFR + 0, (u8)(reg16));
702  mchbar_write8(C0CYCTRKREFR + 1, (u8)(reg16 >> 8));
703 
704  mchbar_clrsetbits16(C0CKECTRL, 0x1ff << 1, 100 << 1);
705  mchbar_clrsetbits8(C0CYCTRKPCHG2, 0x3f, s->selected_timings.tRAS);
706  mchbar_write16(C0ARBCTRL, 0x2310);
708 
709  if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
710  reg32 = 3000;
711  } else {
712  reg32 = 2500;
713  }
714  if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
715  reg2 = 6000;
716  } else {
717  reg2 = 5000;
718  }
719  reg16 = (u16)((((s->selected_timings.CAS + 7) * (reg32)) / reg2) << 8);
720  mchbar_clrsetbits16(C0STATRDCTRL, 0x1f << 8, reg16);
721 
722  flag = 0;
723  if (wl > 2) {
724  flag = 1;
725  }
726  reg16 = (u8) (wl - 1 - flag);
727  reg16 |= reg16 << 4;
728  reg16 |= flag << 8;
729  mchbar_clrsetbits16(C0WRDATACTRL, 0x1ff, reg16);
730 
731  mchbar_write16(C0RDQCTRL, 0x1585);
733 
734  /* rdmodwr_window[5..0] = CL+4+5 265[13..8] (264[21..16]) */
735  mchbar_clrsetbits16(C0PWLRCTRL, 0x3f << 8, (s->selected_timings.CAS + 9) << 8);
736 
737  if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
738  reg16 = 0x0514;
739  reg32 = 0x0a28;
740  } else {
741  reg16 = 0x0618;
742  reg32 = 0x0c30;
743  }
744  mchbar_clrsetbits32(C0REFRCTRL2, 0xfffff << 8, 0x3f << 22 | reg32 << 8);
745 
746  /* FIXME: Is this weird access necessary? Reference code does it */
747  mchbar_write8(C0REFRCTRL + 3, 0);
748  mchbar_clrsetbits16(C0REFCTRL, 0x3fff, reg16);
749 
750  /* NPUT Static Mode */
751  mchbar_setbits8(C0DYNRDCTRL, 1 << 0);
752 
753  mchbar_clrsetbits32(C0STATRDCTRL, 0x7f << 24, 0xb << 25);
754  i = s->selected_timings.mem_clock;
755  j = s->selected_timings.fsb_clock;
756  if (i > j) {
757  mchbar_setbits32(C0STATRDCTRL, 1 << 24);
758  }
759 
761  mchbar_clrsetbits16(C0WRDATACTRL, 0x1f << 10, (wl + 10) << 10);
762  mchbar_clrsetbits32(C0CKECTRL, 7 << 24 | 7 << 17, 3 << 24 | 3 << 17);
763  reg16 = 0x15 << 6;
764  reg16 |= 0x1f;
765  reg16 |= (0x6 << 12);
766  mchbar_clrsetbits16(C0REFRCTRL + 4, 0x7fff, reg16);
767 
768  reg32 = (0x6 << 27) | (1 << 25); /* FIXME: For DDR3, set BIT26 as well */
769  mchbar_clrsetbits32(C0REFRCTRL2, 3 << 28, reg32 << 8);
770  mchbar_clrsetbits8(C0REFRCTRL + 3, 0xfa, reg32 >> 24);
771  mchbar_clrbits8(C0JEDEC, 1 << 7);
772  mchbar_clrbits8(C0DYNRDCTRL, 3 << 1);
773 
774  /* Note: This is a 64-bit register, [34..30] = 0b00110 is split across two writes */
775  reg32 = ((6 & 3) << 30) | (4 << 25) | (1 << 20) | (8 << 15) | (6 << 10) | (4 << 5) | 1;
776  mchbar_write32(C0WRWMFLSH, reg32);
777  mchbar_clrsetbits16(C0WRWMFLSH + 4, 0x1ff, 8 << 3 | 6 >> 2);
778  mchbar_setbits16(SHPENDREG, 0x1c00 | 0x1f << 5);
779 
780  /* FIXME: Why not do a single word write? */
781  mchbar_clrsetbits8(SHPAGECTRL, 0xff, 0x40);
782  mchbar_clrsetbits8(SHPAGECTRL + 1, 0x07, 0x05);
784 
785  reg8 = (3 << 6);
786  reg8 |= (s->dt0mode << 4);
787  reg8 |= 0x0c;
788  mchbar_clrsetbits8(SHBONUSREG, 0xdf, reg8);
789  mchbar_clrbits8(CSHRWRIOMLNS, 1 << 1);
790  mchbar_clrsetbits8(C0MISCTM, 0x07, 0x02);
791  mchbar_clrsetbits16(C0BYPCTRL, 0xff << 2, 4 << 2);
792 
793  /* [31..29] = 0b010 for kN = 2 (2N) */
794  reg32 = (2 << 29) | (1 << 28) | (1 << 23);
795  mchbar_clrsetbits32(WRWMCONFIG, 0xffb << 20, reg32);
796 
797  reg8 = (u8) ((mchbar_read16(C0CYCTRKACT) & 0xe000) >> 13);
798  reg8 |= (u8) ((mchbar_read16(C0CYCTRKACT + 2) & 1) << 3);
799  mchbar_clrsetbits8(BYPACTSF, 0xf << 4, reg8 << 4);
800 
801  reg8 = (u8) ((mchbar_read32(C0CYCTRKRD) & 0x000f0000) >> 17);
802  mchbar_clrsetbits8(BYPACTSF, 0xf, reg8);
803 
804  /* FIXME: Why not clear everything at once? */
805  mchbar_clrbits8(BYPKNRULE, 0xfc);
806  mchbar_clrbits8(BYPKNRULE, 0x03);
808  mchbar_setbits8(C0BYPCTRL, 1 << 0);
810 
811  for (i = 0; i < 8; i++) {
812  /* FIXME: Hardcoded for DDR2 SO-DIMMs */
813  mchbar_clrsetbits32(C0DLLRCVCTLy(i), 0x3f3f3f3f, 0x0c0c0c0c);
814  }
815  /* RDCS to RCVEN delay: Program coarse common to all bytelanes to default tCL + 1 */
816  mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, (s->selected_timings.CAS + 1) << 16);
817 
818  /* Program RCVEN delay with DLL-safe settings */
819  for (i = 0; i < 8; i++) {
820  mchbar_clrbits8(C0RXRCVyDLL(i), 0x3f);
821  mchbar_clrbits16(C0RCVMISCCTL2, 3 << (i * 2));
822  mchbar_clrbits16(C0RCVMISCCTL1, 3 << (i * 2));
823  mchbar_clrbits16(C0COARSEDLY0, 3 << (i * 2));
824  }
825  mchbar_clrbits8(C0DLLPIEN, 1 << 0); /* Power up receiver */
826  mchbar_setbits8(C0DLLPIEN, 1 << 1); /* Enable RCVEN DLL */
827  mchbar_setbits8(C0DLLPIEN, 1 << 2); /* Enable receiver DQS DLL */
828  mchbar_setbits32(C0COREBONUS, 0x000c0400);
829  mchbar_setbits32(C0CMDTX1, 1 << 31);
830 }
831 
832 /* Program clkset0's register for Kcoarse, Tap, PI, DBEn and DBSel */
833 static void sdram_p_clkset0(const struct pllparam *pll, u8 f, u8 i)
834 {
835  mchbar_clrsetbits16(C0CKTX, 0xc440,
836  (pll->clkdelay[f][i] << 14) |
837  (pll->dben[f][i] << 10) |
838  (pll->dbsel[f][i] << 6));
839 
840  mchbar_clrsetbits8(C0TXCK0DLL, 0x3f, pll->pi[f][i]);
841 }
842 
843 /* Program clkset1's register for Kcoarse, Tap, PI, DBEn and DBSel */
844 static void sdram_p_clkset1(const struct pllparam *pll, u8 f, u8 i)
845 {
846  mchbar_clrsetbits32(C0CKTX, 0x00030880,
847  (pll->clkdelay[f][i] << 16) |
848  (pll->dben[f][i] << 11) |
849  (pll->dbsel[f][i] << 7));
850 
851  mchbar_clrsetbits8(C0TXCK1DLL, 0x3f, pll->pi[f][i]);
852 }
853 
854 /* Program CMD0 and CMD1 registers for Kcoarse, Tap, PI, DBEn and DBSel */
855 static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
856 {
857  u8 reg8;
858  /* Clock Group Index 3 */
859  reg8 = pll->dbsel[f][i] << 5;
860  reg8 |= pll->dben[f][i] << 6;
861  mchbar_clrsetbits8(C0CMDTX1, 3 << 5, reg8);
862 
863  reg8 = pll->clkdelay[f][i] << 4;
864  mchbar_clrsetbits8(C0CMDTX2, 3 << 4, reg8);
865 
866  reg8 = pll->pi[f][i];
867  mchbar_clrsetbits8(C0TXCMD0DLL, 0x3f, reg8);
868  mchbar_clrsetbits8(C0TXCMD1DLL, 0x3f, reg8);
869 }
870 
871 /* Program CTRL registers for Kcoarse, Tap, PI, DBEn and DBSel */
872 static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
873 {
874  u8 reg8;
875  u32 reg32;
876 
877  /* CTRL0 and CTRL1 */
878  reg32 = ((u32) pll->dbsel[f][i]) << 20;
879  reg32 |= ((u32) pll->dben[f][i]) << 21;
880  reg32 |= ((u32) pll->dbsel[f][i]) << 22;
881  reg32 |= ((u32) pll->dben[f][i]) << 23;
882  reg32 |= ((u32) pll->clkdelay[f][i]) << 24;
883  reg32 |= ((u32) pll->clkdelay[f][i]) << 27;
884  mchbar_clrsetbits32(C0CTLTX2, 0x01bf0000, reg32);
885 
886  reg8 = pll->pi[f][i];
887  mchbar_clrsetbits8(C0TXCTL0DLL, 0x3f, reg8);
888  mchbar_clrsetbits8(C0TXCTL1DLL, 0x3f, reg8);
889 
890  /* CTRL2 and CTRL3 */
891  reg32 = ((u32) pll->dbsel[f][i]) << 12;
892  reg32 |= ((u32) pll->dben[f][i]) << 13;
893  reg32 |= ((u32) pll->dbsel[f][i]) << 8;
894  reg32 |= ((u32) pll->dben[f][i]) << 9;
895  reg32 |= ((u32) pll->clkdelay[f][i]) << 14;
896  reg32 |= ((u32) pll->clkdelay[f][i]) << 10;
897  mchbar_clrsetbits32(C0CMDTX2, 0xff << 8, reg32);
898 
899  reg8 = pll->pi[f][i];
900  mchbar_clrsetbits8(C0TXCTL2DLL, 0x3f, reg8);
901  mchbar_clrsetbits8(C0TXCTL3DLL, 0x3f, reg8);
902 }
903 
904 static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
905 {
906  u8 rank, dqs, reg8, j;
907  u32 reg32;
908 
909  j = clk - 40;
910  reg8 = 0;
911  reg32 = 0;
912  rank = j % 4;
913  dqs = j / 4;
914 
915  reg32 |= ((u32) pll->dben[f][clk]) << (dqs + 9);
916  reg32 |= ((u32) pll->dbsel[f][clk]) << dqs;
917 
918  mchbar_clrsetbits32(C0DQSRyTX1(rank), 1 << (dqs + 9) | 1 << dqs, reg32);
919 
920  reg32 = ((u32) pll->clkdelay[f][clk]) << ((dqs * 2) + 16);
921  mchbar_clrsetbits32(C0DQSDQRyTX3(rank), 1 << (dqs * 2 + 17) | 1 << (dqs * 2 + 16),
922  reg32);
923 
924  reg8 = pll->pi[f][clk];
925  mchbar_clrsetbits8(C0TXDQS0R0DLL + j, 0x3f, reg8);
926 }
927 
928 static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
929 {
930  u8 rank, dq, reg8, j;
931  u32 reg32;
932 
933  j = clk - 8;
934  reg8 = 0;
935  reg32 = 0;
936  rank = j % 4;
937  dq = j / 4;
938 
939  reg32 |= ((u32) pll->dben[f][clk]) << (dq + 9);
940  reg32 |= ((u32) pll->dbsel[f][clk]) << dq;
941 
942  mchbar_clrsetbits32(C0DQRyTX1(rank), 1 << (dq + 9) | 1 << dq, reg32);
943 
944  reg32 = ((u32) pll->clkdelay[f][clk]) << (dq*2);
945  mchbar_clrsetbits32(C0DQSDQRyTX3(rank), 1 << (dq * 2 + 1) | 1 << (dq * 2), reg32);
946 
947  reg8 = pll->pi[f][clk];
948  mchbar_clrsetbits8(C0TXDQ0R0DLL + j, 0x3f, reg8);
949 }
950 
951 /* WDLL programming: Perform HPLL/MPLL calibration after write levelization */
952 static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
953 {
954  struct pllparam pll = {
955  .pi = {
956  { /* DDR = 667 */
957  3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
958  7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
959  4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
960  7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
961  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
962  0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3,
963  },
964  { /* DDR = 800 */
965  53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
966  34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
967  47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
968  47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
969  2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
970  12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15,
971  }},
972 
973  .dben = {
974  { /* DDR = 667 */
975  0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
976  1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
977  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
978  1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
979  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
980  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
981  },
982  { /* DDR = 800 */
983  1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
984  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
985  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
986  0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
987  1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
988  1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
989  }},
990 
991  .dbsel = {
992  { /* DDR = 667 */
993  0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
994  1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
995  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
996  1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
997  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
998  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
999  },
1000  { /* DDR = 800 */
1001  0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1002  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1003  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1004  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1005  1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1006  1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1007  }},
1008 
1009  .clkdelay = {
1010  { /* DDR = 667 */
1011  0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1012  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1013  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1014  1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1015  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1016  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1017  },
1018  { /* DDR = 800 */
1019  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1020  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1021  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1022  1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1023  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1024  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1025  }}
1026  };
1027 
1028  u8 i, f;
1029  if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1030  f = 0;
1031  } else {
1032  f = 1;
1033  }
1034  for (i = 0; i < 72; i++) {
1035  pll.pi[f][i] += pidelay;
1036  }
1037 
1038  /* Disable Dynamic DQS Slave Setting Per Rank */
1039  mchbar_clrbits8(CSHRDQSCMN, 1 << 7);
1040  mchbar_clrsetbits16(CSHRPDCTL4, 0x3fff, 0x1fff);
1041 
1042  sdram_p_clkset0(&pll, f, 0);
1043  sdram_p_clkset1(&pll, f, 1);
1044  sdram_p_cmd(&pll, f, 2);
1045  sdram_p_ctrl(&pll, f, 4);
1046 
1047  for (i = 0; i < 32; i++) {
1048  sdram_p_dqs(&pll, f, i + 40);
1049  }
1050  for (i = 0; i < 32; i++) {
1051  sdram_p_dq(&pll, f, i + 8);
1052  }
1053 }
1054 
1055 /* Perform HMC hardware calibration */
1056 static void sdram_calibratehwpll(struct sysinfo *s)
1057 {
1058  u8 reg8;
1059 
1060  s->async = 0;
1061  reg8 = 0;
1062 
1063  mchbar_setbits16(CSHRPDCTL, 1 << 15);
1064  mchbar_clrbits8(CSHRPDCTL, 1 << 7);
1065  mchbar_setbits8(CSHRPDCTL, 1 << 3);
1066  mchbar_setbits8(CSHRPDCTL, 1 << 2);
1067 
1068  /* Start hardware HMC calibration */
1069  mchbar_setbits8(CSHRPDCTL, 1 << 7);
1070 
1071  /* Busy-wait until calibration is done */
1072  while ((mchbar_read8(CSHRPDCTL) & (1 << 2)) == 0)
1073  ;
1074 
1075  /* If hardware HMC calibration failed */
1076  reg8 = (mchbar_read8(CSHRPDCTL) & (1 << 3)) >> 3;
1077  if (reg8 != 0) {
1078  s->async = 1;
1079  }
1080 }
1081 
1082 static void sdram_dlltiming(struct sysinfo *s)
1083 {
1084  u8 reg8, i;
1085  u16 reg16;
1086  u32 reg32;
1087 
1088  /* Configure the Master DLL */
1089  if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1090  reg32 = 0x08014227;
1091  } else {
1092  reg32 = 0x00014221;
1093  }
1094  mchbar_clrsetbits32(CSHRMSTRCTL1, 0x0fffffff, reg32);
1095  mchbar_setbits32(CSHRMSTRCTL1, 1 << 23);
1096  mchbar_setbits32(CSHRMSTRCTL1, 1 << 15);
1097  mchbar_clrbits32(CSHRMSTRCTL1, 1 << 15);
1098 
1099  if (s->nodll) {
1100  /* Disable the Master DLLs by setting these bits, IN ORDER! */
1101  mchbar_setbits16(CSHRMSTRCTL0, 1 << 0);
1102  mchbar_setbits16(CSHRMSTRCTL0, 1 << 2);
1103  mchbar_setbits16(CSHRMSTRCTL0, 1 << 4);
1104  mchbar_setbits16(CSHRMSTRCTL0, 1 << 8);
1105  mchbar_setbits16(CSHRMSTRCTL0, 1 << 10);
1106  mchbar_setbits16(CSHRMSTRCTL0, 1 << 12);
1107  mchbar_setbits16(CSHRMSTRCTL0, 1 << 14);
1108  } else {
1109  /* Enable the Master DLLs by clearing these bits, IN ORDER! */
1110  mchbar_clrbits16(CSHRMSTRCTL0, 1 << 0);
1111  mchbar_clrbits16(CSHRMSTRCTL0, 1 << 2);
1112  mchbar_clrbits16(CSHRMSTRCTL0, 1 << 4);
1113  mchbar_clrbits16(CSHRMSTRCTL0, 1 << 8);
1114  mchbar_clrbits16(CSHRMSTRCTL0, 1 << 10);
1115  mchbar_clrbits16(CSHRMSTRCTL0, 1 << 12);
1116  mchbar_clrbits16(CSHRMSTRCTL0, 1 << 14);
1117  }
1118 
1119  /* Initialize the Transmit DLL PI values in the following sequence. */
1120  if (s->nodll) {
1121  mchbar_clrsetbits8(CREFPI, 0x3f, 0x07);
1122  } else {
1123  mchbar_clrbits8(CREFPI, 0x3f);
1124  }
1125 
1126  sdram_calibratepll(s, 0); // XXX check
1127 
1128  /* Enable all modular Slave DLL */
1129  mchbar_setbits16(C0DLLPIEN, 1 << 11);
1130  mchbar_setbits16(C0DLLPIEN, 1 << 12);
1131 
1132  for (i = 0; i < 8; i++) {
1133  mchbar_setbits16(C0DLLPIEN, (1 << 10) >> i);
1134  }
1135  /* Enable DQ/DQS output */
1136  mchbar_setbits8(C0SLVDLLOUTEN, 1 << 0);
1137  mchbar_write16(CSPDSLVWT, 0x5005);
1138  mchbar_clrsetbits16(CSHRPDCTL2, 0x1f1f, 0x051a);
1139  mchbar_clrsetbits16(CSHRPDCTL5, 0xbf3f, 0x9010);
1140 
1141  if (s->nodll) {
1142  mchbar_clrsetbits8(CSHRPDCTL3, 0x7f, 0x6b);
1143  } else {
1144  mchbar_clrsetbits8(CSHRPDCTL3, 0x7f, 0x55);
1146  }
1147  /* Disable Dynamic Diff Amp */
1148  mchbar_clrbits32(C0STATRDCTRL, 1 << 22);
1149 
1150  /* Now, start initializing the transmit FIFO */
1151  mchbar_clrbits8(C0MISCCTL, 1 << 1);
1152 
1153  /* Disable (gate) mdclk and mdclkb */
1154  mchbar_setbits8(CSHWRIOBONUS, 3 << 6);
1155 
1156  /* Select mdmclk */
1157  mchbar_clrbits8(CSHWRIOBONUS, 1 << 5);
1158 
1159  /* Ungate mdclk */
1160  mchbar_clrsetbits8(CSHWRIOBONUS, 3 << 6, 1 << 6);
1161  mchbar_clrsetbits8(CSHRFIFOCTL, 0x3f, 0x1a);
1162 
1163  /* Enable the write pointer count */
1164  mchbar_setbits8(CSHRFIFOCTL, 1 << 0);
1165 
1166  /* Set the DDR3 Reset Enable bit */
1167  mchbar_setbits8(CSHRDDR3CTL, 1 << 0);
1168 
1169  /* Configure DQS-DQ Transmit */
1170  mchbar_write32(CSHRDQSTXPGM, 0x00551803);
1171 
1172  reg8 = 0; /* Switch all clocks on anyway */
1173 
1174  /* Enable clock groups depending on rank population */
1175  mchbar_clrsetbits32(C0CKTX, 0x3f << 24, reg8 << 24);
1176 
1177  /* Enable DDR command output buffers from core */
1178  mchbar_clrbits8(0x594, 1 << 0);
1179 
1180  reg16 = 0;
1181  if (!rank_is_populated(s->dimms, 0, 0)) {
1182  reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
1183  }
1184  if (!rank_is_populated(s->dimms, 0, 1)) {
1185  reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
1186  }
1187  if (!rank_is_populated(s->dimms, 0, 2)) {
1188  reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1189  }
1190  if (!rank_is_populated(s->dimms, 0, 3)) {
1191  reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1192  }
1193  mchbar_setbits16(C0CTLTX2, reg16);
1194 }
1195 
1196 /* Define a shorter name for these to make the lines fit in 96 characters */
1197 #define TABLE static const
1198 
1199 /* Loop over each RCOMP group, but skip group 1 because it does not exist */
1200 #define FOR_EACH_RCOMP_GROUP(idx) for (idx = 0; idx < 7; idx++) if (idx != 1)
1201 
1202 /* Define accessors for the RCOMP register banks */
1203 #define C0RCOMPCTRLx(x) (rcompctl[(x)] + 0x00)
1204 #define C0RCOMPMULTx(x) (rcompctl[(x)] + 0x04)
1205 #define C0RCOMPOVRx(x) (rcompctl[(x)] + 0x06)
1206 #define C0RCOMPOSVx(x) (rcompctl[(x)] + 0x0a)
1207 #define C0SCOMPVREFx(x) (rcompctl[(x)] + 0x0e)
1208 #define C0SCOMPOVRx(x) (rcompctl[(x)] + 0x10)
1209 #define C0SCOMPOFFx(x) (rcompctl[(x)] + 0x12)
1210 #define C0DCOMPx(x) (rcompctl[(x)] + 0x14)
1211 #define C0SLEWBASEx(x) (rcompctl[(x)] + 0x16)
1212 #define C0SLEWPULUTx(x) (rcompctl[(x)] + 0x18)
1213 #define C0SLEWPDLUTx(x) (rcompctl[(x)] + 0x1c)
1214 #define C0DCOMPOVRx(x) (rcompctl[(x)] + 0x20)
1215 #define C0DCOMPOFFx(x) (rcompctl[(x)] + 0x24)
1216 
1217 /* FIXME: This only applies to DDR2 */
1218 static void sdram_rcomp(struct sysinfo *s)
1219 {
1220  u8 i, j, reg8, rcompp, rcompn, srup, srun;
1221  u16 reg16;
1222  u32 reg32, rcomp1, rcomp2;
1223 
1224  static const u8 rcompslew = 0x0a;
1225  static const u16 rcompctl[7] = {
1226  C0RCOMPCTRL0,
1227  0, /* This register does not exist */
1228  C0RCOMPCTRL2,
1229  C0RCOMPCTRL3,
1230  C0RCOMPCTRL4,
1231  C0RCOMPCTRL5,
1232  C0RCOMPCTRL6,
1233  };
1234 
1235  /* RCOMP settings tables = { NC-NC, x16SS, x16DS, x16SS2, x16DS2, x8DS, x8DS2}; */
1236  TABLE u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0};
1237  TABLE u8 rcompstr[7] = { 0x66, 0x00, 0xaa, 0x55, 0x55, 0x77, 0x77};
1238  TABLE u16 rcompscomp[7] = {0xa22a, 0x0000, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a};
1239  TABLE u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1};
1240  TABLE u16 rcompf[7] = {0x1114, 0x0000, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a};
1241  TABLE u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0xaa};
1242  TABLE u16 rcompscomp2[7] = {0x0000, 0xe22e, 0xe22e, 0xe22e, 0x8228, 0xe22e, 0x8228};
1243  TABLE u8 rcompdelay2[7] = { 0, 0, 0, 0, 2, 0, 2};
1244 
1245  TABLE u8 rcomplut[64][12] = {
1246  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1247  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1248  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1249  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1250  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1251  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1252  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1253  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1254  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1255  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1256  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1257  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1258  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1259  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1260  { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1261  {10, 9, 12, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1262  {10, 9, 12, 11, 2, 2, 6, 5, 7, 6, 6, 5},
1263  {10, 10, 12, 12, 2, 2, 6, 5, 7, 6, 6, 5},
1264  {10, 10, 12, 12, 2, 2, 6, 6, 7, 7, 6, 6},
1265  {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1266  {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1267  {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1268  {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1269  {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1270  {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1271  {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1272  {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1273  {11, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1274  {11, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1275  {12, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1276  {12, 12, 14, 13, 3, 3, 7, 6, 7, 7, 7, 6},
1277  {13, 12, 16, 15, 3, 3, 7, 6, 8, 7, 7, 6},
1278  {13, 14, 16, 15, 4, 3, 7, 7, 8, 8, 7, 7},
1279  {14, 14, 16, 17, 4, 3, 7, 7, 8, 8, 7, 7},
1280  {14, 16, 18, 17, 4, 4, 8, 7, 8, 8, 8, 7},
1281  {15, 16, 18, 19, 4, 4, 8, 7, 9, 8, 8, 7},
1282  {15, 18, 18, 19, 4, 4, 8, 8, 9, 9, 8, 8},
1283  {16, 18, 20, 21, 4, 4, 8, 8, 9, 9, 8, 8},
1284  {16, 19, 20, 21, 5, 4, 9, 8, 10, 9, 9, 8},
1285  {16, 19, 20, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1286  {17, 19, 22, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1287  {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1288  {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1289  {18, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1290  {18, 21, 24, 25, 5, 5, 9, 9, 11, 10, 9, 9},
1291  {19, 21, 24, 27, 5, 5, 9, 9, 11, 11, 9, 9},
1292  {19, 22, 24, 27, 5, 5, 10, 9, 11, 11, 10, 9},
1293  {20, 22, 24, 27, 6, 5, 10, 10, 11, 11, 10, 10},
1294  {20, 23, 26, 27, 6, 6, 10, 10, 12, 12, 10, 10},
1295  {20, 23, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1296  {21, 24, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1297  {21, 24, 26, 29, 6, 6, 11, 10, 12, 13, 11, 10},
1298  {22, 25, 28, 29, 6, 6, 11, 11, 13, 13, 11, 11},
1299  {22, 25, 28, 31, 6, 6, 11, 11, 13, 13, 11, 11},
1300  {22, 26, 28, 31, 6, 6, 11, 11, 13, 14, 11, 11},
1301  {23, 26, 30, 31, 7, 6, 12, 11, 14, 14, 12, 11},
1302  {23, 27, 30, 33, 7, 7, 12, 12, 14, 14, 12, 12},
1303  {23, 27, 30, 33, 7, 7, 12, 12, 14, 15, 12, 12},
1304  {24, 28, 32, 33, 7, 7, 12, 12, 15, 15, 12, 12},
1305  {24, 28, 32, 33, 7, 7, 12, 12, 15, 16, 12, 12},
1306  {24, 29, 32, 35, 7, 7, 12, 12, 15, 16, 12, 12},
1307  {25, 29, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1308  {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1309  {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1310  };
1311 
1312  srup = 0;
1313  srun = 0;
1314 
1315  if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1316  rcomp1 = 0x00050431;
1317  } else {
1318  rcomp1 = 0x00050542;
1319  }
1320  if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
1321  rcomp2 = 0x14c42827;
1322  } else {
1323  rcomp2 = 0x19042827;
1324  }
1325 
1327  reg8 = rcompupdate[i];
1328  mchbar_clrsetbits8(C0RCOMPCTRLx(i), 1 << 0, reg8);
1329  mchbar_clrbits8(C0RCOMPCTRLx(i), 1 << 1);
1330 
1331  reg16 = rcompslew;
1332  mchbar_clrsetbits16(C0RCOMPCTRLx(i), 0xf << 12, reg16 << 12);
1333 
1334  mchbar_write8(C0RCOMPMULTx(i), rcompstr[i]);
1335  mchbar_write16(C0SCOMPVREFx(i), rcompscomp[i]);
1336  mchbar_clrsetbits8(C0DCOMPx(i), 0x03, rcompdelay[i]);
1337  if (i == 2) {
1338  /* FIXME: Why are we rewriting this? */
1339  mchbar_clrsetbits16(C0RCOMPCTRLx(i), 0xf << 12, reg16 << 12);
1340 
1341  mchbar_write8(C0RCOMPMULTx(i), rcompstr2[s->dimm_config[0]]);
1342  mchbar_write16(C0SCOMPVREFx(i), rcompscomp2[s->dimm_config[0]]);
1343  mchbar_clrsetbits8(C0DCOMPx(i), 0x03, rcompdelay2[s->dimm_config[0]]);
1344  }
1345 
1346  mchbar_clrbits16(C0SLEWBASEx(i), 0x7f7f);
1347 
1348  /* FIXME: Why not do a single dword write? */
1349  mchbar_clrbits16(C0SLEWPULUTx(i), 0x3f3f);
1350  mchbar_clrbits16(C0SLEWPULUTx(i) + 2, 0x3f3f);
1351 
1352  /* FIXME: Why not do a single dword write? */
1353  mchbar_clrbits16(C0SLEWPDLUTx(i), 0x3f3f);
1354  mchbar_clrbits16(C0SLEWPDLUTx(i) + 2, 0x3f3f);
1355  }
1356 
1357  /* FIXME: Hardcoded */
1358  mchbar_clrsetbits8(C0ODTRECORDX, 0x3f, 0x36);
1359  mchbar_clrsetbits8(C0DQSODTRECORDX, 0x3f, 0x36);
1360 
1362  mchbar_clrbits8(C0RCOMPCTRLx(i), 3 << 5);
1363  mchbar_clrbits16(C0RCOMPCTRLx(i) + 2, 0x0706);
1364  mchbar_clrbits16(C0RCOMPOSVx(i), 0x7f7f);
1365  mchbar_clrbits16(C0SCOMPOFFx(i), 0x3f3f);
1366  mchbar_clrbits16(C0DCOMPOFFx(i), 0x1f1f);
1367  mchbar_clrbits8(C0DCOMPOFFx(i) + 2, 0x1f);
1368  }
1369 
1370  mchbar_clrbits16(C0ODTRECORDX, 0xffc0);
1371  mchbar_clrbits16(C0ODTRECORDX + 2, 0x000f);
1372 
1373  /* FIXME: Why not do a single dword write? */
1375  mchbar_clrbits16(C0DQSODTRECORDX + 2, 0x000f);
1376 
1378  mchbar_write16(C0SCOMPOVRx(i), rcompf[i]);
1379 
1380  /* FIXME: Why not do a single dword write? */
1381  mchbar_write16(C0DCOMPOVRx(i) + 0, 0x1219);
1382  mchbar_write16(C0DCOMPOVRx(i) + 2, 0x000c);
1383  }
1384 
1385  mchbar_clrsetbits32(DCMEASBUFOVR, 0x001f1f1f, 0x000c1219);
1386 
1387  /* FIXME: Why not do a single word write? */
1388  mchbar_clrsetbits16(XCOMPSDR0BNS, 0x1f << 8, 0x12 << 8);
1389  mchbar_clrsetbits8(XCOMPSDR0BNS, 0x1f << 0, 0x12 << 0);
1390 
1391  mchbar_write32(COMPCTRL3, 0x007c9007);
1392  mchbar_write32(OFREQDELSEL, rcomp1);
1393  mchbar_write16(XCOMPCMNBNS, 0x1f7f);
1394  mchbar_write32(COMPCTRL2, rcomp2);
1396  mchbar_write16(ZQCALCTRL, 0x0134);
1397  mchbar_write32(COMPCTRL1, 0x4c293600);
1398 
1399  mchbar_clrsetbits8(COMPCTRL1 + 3, 0x44, 1 << 6 | 1 << 2);
1400  mchbar_clrbits16(XCOMPSDR0BNS, 1 << 13);
1401  mchbar_clrbits8(XCOMPSDR0BNS, 1 << 5);
1402 
1404  /* POR values are zero */
1405  mchbar_clrbits8(C0RCOMPCTRLx(i) + 2, 0x71);
1406  }
1407 
1408  if ((mchbar_read32(COMPCTRL1) & (1 << 30)) == 0) {
1409  /* Start COMP */
1410  mchbar_setbits8(COMPCTRL1, 1 << 0);
1411 
1412  /* Wait until COMP is done */
1413  while ((mchbar_read8(COMPCTRL1) & 1) != 0)
1414  ;
1415 
1416  reg32 = mchbar_read32(XCOMP);
1417  rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1418  rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1419 
1421  srup = (mchbar_read8(C0RCOMPCTRLx(i) + 1) & 0xc0) >> 6;
1422  srun = (mchbar_read8(C0RCOMPCTRLx(i) + 1) & 0x30) >> 4;
1423 
1424  /* FIXME: Why not do a single word write? */
1425  reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
1426  mchbar_clrsetbits16(C0SLEWBASEx(i), 0x7f << 8, reg16);
1427 
1428  reg16 = (u16)(rcompn - (1 << (srun + 1)));
1429  mchbar_clrsetbits8(C0SLEWBASEx(i), 0x7f, (u8)reg16);
1430  }
1431 
1432  reg8 = rcompp - (1 << (srup + 1));
1433  for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1434  mchbar_clrsetbits8(C0SLEWPULUTx(0) + i, 0x3f, rcomplut[j][0]);
1435  }
1436 
1437  for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1438  if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1439  mchbar_clrsetbits8(C0SLEWPULUTx(2) + i, 0x3f, rcomplut[j][10]);
1440  }
1441  }
1442 
1443  for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1444  mchbar_clrsetbits8(C0SLEWPULUTx(3) + i, 0x3f, rcomplut[j][6]);
1445  mchbar_clrsetbits8(C0SLEWPULUTx(4) + i, 0x3f, rcomplut[j][6]);
1446  }
1447 
1448  for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1449  mchbar_clrsetbits8(C0SLEWPULUTx(5) + i, 0x3f, rcomplut[j][8]);
1450  mchbar_clrsetbits8(C0SLEWPULUTx(6) + i, 0x3f, rcomplut[j][8]);
1451  }
1452 
1453  reg8 = rcompn - (1 << (srun + 1));
1454  for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1455  mchbar_clrsetbits8(C0SLEWPDLUTx(0) + i, 0x3f, rcomplut[j][1]);
1456  }
1457 
1458  for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1459  if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1460  mchbar_clrsetbits8(C0SLEWPDLUTx(2) + i, 0x3f, rcomplut[j][11]);
1461  }
1462  }
1463 
1464  for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1465  mchbar_clrsetbits8(C0SLEWPDLUTx(3) + i, 0x3f, rcomplut[j][7]);
1466  mchbar_clrsetbits8(C0SLEWPDLUTx(4) + i, 0x3f, rcomplut[j][7]);
1467  }
1468 
1469  for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1470  mchbar_clrsetbits8(C0SLEWPDLUTx(5) + i, 0x3f, rcomplut[j][9]);
1471  mchbar_clrsetbits8(C0SLEWPDLUTx(6) + i, 0x3f, rcomplut[j][9]);
1472  }
1473  }
1474  mchbar_setbits8(COMPCTRL1, 1 << 0);
1475 }
1476 
1477 /* FIXME: The ODT tables are for DDR2 only! */
1478 static void sdram_odt(struct sysinfo *s)
1479 {
1480  u8 rankindex = 0;
1481 
1482  static const u16 odt_rankctrl[16] = {
1483  /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1484  0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1485  /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1486  0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1487  };
1488  static const u16 odt_matrix[16] = {
1489  /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1490  0x0000, 0x0011, 0x0000, 0x0011, 0x0000, 0x4444, 0x0000, 0x4444,
1491  /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1492  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4444, 0x0000, 0x4444,
1493  };
1494 
1495  switch (s->dimms[0].ranks) {
1496  case 0:
1497  if (s->dimms[1].ranks == 0) {
1498  rankindex = 0;
1499  } else if (s->dimms[1].ranks == 1) {
1500  rankindex = 4;
1501  } else if (s->dimms[1].ranks == 2) {
1502  rankindex = 12;
1503  }
1504  break;
1505  case 1:
1506  if (s->dimms[1].ranks == 0) {
1507  rankindex = 1;
1508  } else if (s->dimms[1].ranks == 1) {
1509  rankindex = 5;
1510  } else if (s->dimms[1].ranks == 2) {
1511  rankindex = 13;
1512  }
1513  break;
1514  case 2:
1515  if (s->dimms[1].ranks == 0) {
1516  rankindex = 3;
1517  } else if (s->dimms[1].ranks == 1) {
1518  rankindex = 7;
1519  } else if (s->dimms[1].ranks == 2) {
1520  rankindex = 15;
1521  }
1522  break;
1523  }
1524 
1525  /* Program the ODT Matrix */
1526  mchbar_write16(C0ODT, odt_matrix[rankindex]);
1527 
1528  /* Program the ODT Rank Control */
1529  mchbar_write16(C0ODTRKCTRL, odt_rankctrl[rankindex]);
1530 }
1531 
1532 static void sdram_mmap(struct sysinfo *s)
1533 {
1534  TABLE u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000, 0xc00001, 0xf00000};
1535  TABLE u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101, 0x1010000, 0x1010101};
1536  TABLE u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1537  TABLE u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006, 0x40002, 0x80006};
1538 
1539  TABLE u16 tolud[7] = {2048, 2048, 4096, 4096, 8192, 4096, 8192};
1540  TABLE u16 tom[7] = { 2, 2, 4, 4, 8, 4, 8};
1541  TABLE u16 touud[7] = { 128, 128, 256, 256, 512, 256, 512};
1542  TABLE u32 gbsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1543  TABLE u32 bgsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1544  TABLE u32 tsegmb[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1545 
1546  if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1547  if (s->dimms[0].sides > 1) {
1548  // 2R/NC
1549  mchbar_clrsetbits32(C0CKECTRL, 1, 0x300001);
1550  mchbar_write32(C0DRA01, 0x00000101);
1551  mchbar_write32(C0DRB0, 0x00040002);
1552  mchbar_write32(C0DRB2, w204[s->dimm_config[0]]);
1553  } else {
1554  // 1R/NC
1555  mchbar_clrsetbits32(C0CKECTRL, 1, 0x100001);
1556  mchbar_write32(C0DRA01, 0x00000001);
1557  mchbar_write32(C0DRB0, 0x00020002);
1558  mchbar_write32(C0DRB2, w204[s->dimm_config[0]]);
1559  }
1560  } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
1561  mchbar_clrsetbits32(C0CKECTRL, 1, 0x300001);
1562  mchbar_write32(C0DRA01, 0x00000101);
1563  mchbar_write32(C0DRB0, 0x00040002);
1564  mchbar_write32(C0DRB2, 0x00040004);
1565  } else {
1566  mchbar_clrsetbits32(C0CKECTRL, 1, w260[s->dimm_config[0]]);
1567  mchbar_write32(C0DRA01, w208[s->dimm_config[0]]);
1568  mchbar_write32(C0DRB0, w200[s->dimm_config[0]]);
1569  mchbar_write32(C0DRB2, w204[s->dimm_config[0]]);
1570  }
1571  pci_write_config16(HOST_BRIDGE, 0xb0, tolud[s->dimm_config[0]]);
1572  pci_write_config16(HOST_BRIDGE, 0xa0, tom[s->dimm_config[0]]);
1573  pci_write_config16(HOST_BRIDGE, 0xa2, touud[s->dimm_config[0]]);
1574  pci_write_config32(HOST_BRIDGE, 0xa4, gbsm[s->dimm_config[0]]);
1575  pci_write_config32(HOST_BRIDGE, 0xa8, bgsm[s->dimm_config[0]]);
1576  pci_write_config32(HOST_BRIDGE, 0xac, tsegmb[s->dimm_config[0]]);
1577 }
1578 
1580 {
1581  u32 xcomp;
1582  u8 aa, bb, a, b, c, d;
1583 
1584  xcomp = mchbar_read32(XCOMP);
1585  a = (u8)((xcomp & 0x7f000000) >> 24);
1586  b = (u8)((xcomp & 0x007f0000) >> 16);
1587  c = (u8)((xcomp & 0x00003f00) >> 8);
1588  d = (u8)((xcomp & 0x0000003f) >> 0);
1589 
1590  if (a > b) {
1591  aa = a - b;
1592  } else {
1593  aa = b - a;
1594  }
1595  if (c > d) {
1596  bb = c - d;
1597  } else {
1598  bb = d - c;
1599  }
1600  if ((aa > 18) || (bb > 7) || (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
1601  (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
1602  mchbar_write32(RCMEASBUFXOVR, 0x9718a729);
1603  return 1;
1604  }
1605  return 0;
1606 }
1607 
1608 static void sdram_rcompupdate(struct sysinfo *s)
1609 {
1610  u8 i, ok;
1611  u32 reg32a, reg32b;
1612 
1613  ok = 0;
1614  mchbar_clrbits8(XCOMPDFCTRL, 1 << 3);
1615  mchbar_clrbits8(COMPCTRL1, 1 << 7);
1616  for (i = 0; i < 3; i++) {
1617  mchbar_setbits8(COMPCTRL1, 1 << 0);
1618  hpet_udelay(1000);
1619  while ((mchbar_read8(COMPCTRL1) & 1) != 0)
1620  ;
1621  ok |= sdram_checkrcompoverride();
1622  }
1623  if (!ok) {
1624  reg32a = mchbar_read32(XCOMP);
1625  reg32b = ((reg32a >> 16) & 0x0000ffff);
1626  reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1627  reg32a |= (1 << 31) | (1 << 15);
1628  mchbar_write32(RCMEASBUFXOVR, reg32a);
1629  }
1630  mchbar_setbits8(COMPCTRL1, 1 << 0);
1631  hpet_udelay(1000);
1632  while ((mchbar_read8(COMPCTRL1) & 1) != 0)
1633  ;
1634 }
1635 
1636 static void __attribute__((noinline))
1637 sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1638 {
1639  u32 reg32;
1640 
1641  reg32 = jval << 3;
1642  reg32 |= rank * (1 << 27);
1643  mchbar_clrsetbits8(C0JEDEC, 0x3e, jmode);
1644  read32((void *)reg32);
1645  barrier();
1646  hpet_udelay(1); // 1us
1647 }
1648 
1649 static void sdram_zqcl(struct sysinfo *s)
1650 {
1651  if (s->boot_path == BOOT_PATH_RESUME) {
1652  mchbar_setbits32(C0CKECTRL, 1 << 27);
1654  mchbar_clrbits8(C0JEDEC, 3 << 4);
1655  mchbar_clrsetbits32(C0REFRCTRL2, 3 << 30, 3 << 30);
1656  }
1657 }
1658 
1659 static void sdram_jedecinit(struct sysinfo *s)
1660 {
1661  u8 r, i, ch;
1662  u16 reg16, mrs, rttnom;
1663  struct jedeclist {
1664  char debug[15];
1665  u8 cmd;
1666  u16 val;
1667  };
1668 
1669  static const struct jedeclist jedec[12] = {
1670  { " NOP ", NOP_CMD, 0 },
1671  { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1672  { " EMRS2 ", EMRS2_CMD, 0 },
1673  { " EMRS3 ", EMRS3_CMD, 0 },
1674  { " EMRS1 ", EMRS1_CMD, 0 },
1675  { " DLL RESET ", MRS_CMD, (1 << 8) },
1676  { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1677  { " AUTOREFRESH", CBR_CMD, 0 },
1678  { " AUTOREFRESH", CBR_CMD, 0 },
1679  { " INITIALISE ", MRS_CMD, 0 },
1680  { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1681  { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1682  };
1683 
1684  mrs = (s->selected_timings.CAS << 4) |
1685  ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 3;
1686 
1687  rttnom = (1 << 2);
1688  if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1689  rttnom |= (1 << 6);
1690  }
1691 
1692  hpet_udelay(200); // 200us
1693  reg16 = 0;
1694  FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1695  for (i = 0; i < 12; i++) {
1696  PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1697  reg16 = jedec[i].val;
1698  switch (jedec[i].cmd) {
1699  case EMRS1_CMD:
1700  reg16 |= rttnom;
1701  break;
1702  case MRS_CMD:
1703  reg16 |= mrs;
1704  break;
1705  default:
1706  break;
1707  }
1708  sdram_jedec(s, r, jedec[i].cmd, reg16);
1709  PRINTK_DEBUG("done\n");
1710  }
1711  }
1712 }
1713 
1714 static void sdram_misc(struct sysinfo *s)
1715 {
1716  u32 reg32;
1717 
1718  reg32 = 0;
1719  reg32 |= (4 << 13);
1720  reg32 |= (6 << 8);
1721  mchbar_clrsetbits32(C0DYNRDCTRL, 0x3ff << 8, reg32);
1722  mchbar_clrbits8(C0DYNRDCTRL, 1 << 7);
1723  mchbar_setbits8(C0REFRCTRL + 3, 1 << 0);
1724  if (s->boot_path != BOOT_PATH_RESUME) {
1726  mchbar_clrbits8(C0JEDEC, 3 << 4);
1727  } else {
1728  sdram_zqcl(s);
1729  }
1730 }
1731 
1732 static void sdram_checkreset(void)
1733 {
1734  u8 pmcon2, pmcon3, reset;
1735 
1736  pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1737  pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1738  pmcon3 &= ~0x2;
1739  if (pmcon2 & 0x80) {
1740  pmcon2 &= ~0x80;
1741  reset = 1;
1742  } else {
1743  pmcon2 |= 0x80;
1744  reset = 0;
1745  }
1746  if (pmcon2 & 0x4) {
1747  pmcon2 |= 0x4;
1748  pmcon3 = (pmcon3 & ~0x30) | 0x30;
1749  pmcon3 |= (1 << 3);
1750  }
1751  pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1752  pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
1753  if (reset)
1754  full_reset();
1755 }
1756 
1757 static void sdram_dradrb(struct sysinfo *s)
1758 {
1759  u8 i, reg8, ch, r;
1760  u32 reg32, ind, c0dra, c0drb, dra;
1761  u16 addr;
1762  i = 0;
1763  static const u8 dratab[2][2][2][4] =
1764  {{
1765  {
1766  {0xff, 0xff, 0xff, 0xff},
1767  {0xff, 0x00, 0x02, 0xff}
1768  },
1769  {
1770  {0xff, 0x01, 0xff, 0xff},
1771  {0xff, 0x03, 0xff, 0x06}
1772  }
1773  },
1774  {
1775  {
1776  {0xff, 0xff, 0xff, 0xff},
1777  {0xff, 0x04, 0x06, 0x08}
1778  },
1779  {
1780  {0xff, 0xff, 0xff, 0xff},
1781  {0x05, 0x07, 0x09, 0xff}
1782  }
1783  }};
1784 
1785  static const u8 dradrb[10][6] = {
1786  //Row Col Bank Width DRB
1787  {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1788  {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1789  {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1790  {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1791  {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1792  {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1793  {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1794  {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1795  {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1796  {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1797  };
1798 
1799  reg32 = 0;
1800  FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1801  i = r / 2;
1802  PRINTK_DEBUG("RANK %d PRESENT\n", r);
1803  dra = dratab
1804  [s->dimms[i].banks]
1805  [s->dimms[i].width]
1806  [s->dimms[i].cols - 9]
1807  [s->dimms[i].rows - 12];
1808 
1809  if (s->dimms[i].banks == 1) {
1810  dra |= (1 << 7);
1811  }
1812  reg32 |= (dra << (r * 8));
1813  }
1814  mchbar_write32(C0DRA01, reg32);
1815  c0dra = reg32;
1816  PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1817 
1818  reg32 = 0;
1819  FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1820  reg32 |= (1 << r);
1821  }
1822  reg8 = (u8)(reg32 << 4) & 0xf0;
1823  mchbar_clrsetbits8(C0CKECTRL + 2, 0xf0, reg8);
1824 
1825  if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) || ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1826  mchbar_setbits8(C0CKECTRL, 1 << 0);
1827  }
1828 
1829  addr = C0DRB0;
1830  c0drb = 0;
1831  FOR_EACH_RANK(ch, r) {
1832  if (rank_is_populated(s->dimms, ch, r)) {
1833  ind = (c0dra >> (8 * r)) & 0x7f;
1834  c0drb = (u16)(c0drb + dradrb[ind][5]);
1835  s->channel_capacity[0] += dradrb[ind][5] << 6;
1836  }
1837  mchbar_write16(addr, c0drb);
1838  addr += 2;
1839  }
1840  printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1841 }
1842 
1843 static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1844 {
1845  u8 dqsmatches = 1;
1846  while (count--) {
1847  mchbar_clrbits8(C0RSTCTL, 1 << 1);
1848  hpet_udelay(1);
1849  mchbar_setbits8(C0RSTCTL, 1 << 1);
1850  hpet_udelay(1);
1851  barrier();
1852  read32((void *)strobeaddr);
1853  barrier();
1854  hpet_udelay(1);
1855 
1856  if (((mchbar_read8(dqshighaddr) & (1 << 6)) >> 6) != highlow) {
1857  dqsmatches = 0;
1858  }
1859  }
1860 
1861  return dqsmatches;
1862 }
1863 
1864 static void rcvenclock(u8 *coarse, u8 *medium, u8 lane)
1865 {
1866  if (*medium < 3) {
1867  (*medium)++;
1868  mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), *medium << (lane * 2));
1869  } else {
1870  *medium = 0;
1871  (*coarse)++;
1872  mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, *coarse << 16);
1873  mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), *medium << (lane * 2));
1874  }
1875 }
1876 
1877 static void sdram_rcven(struct sysinfo *s)
1878 {
1879  u8 coarse, savecoarse;
1880  u8 medium, savemedium;
1881  u8 pi, savepi;
1882  u8 lane;
1883  u8 lanecoarse[8] = {0};
1884  u8 minlanecoarse = 0xff;
1885  u8 offset;
1886  u8 maxlane = 8;
1887  /* Since dra/drb is already set up we know that at address 0x00000000
1888  we will always find the first available rank */
1889  u32 strobeaddr = 0;
1890  u32 dqshighaddr;
1891 
1892  mchbar_clrbits8(C0RSTCTL, 3 << 2);
1893  mchbar_clrbits8(CMNDQFIFORST, 1 << 7);
1894 
1895  PRINTK_DEBUG("rcven 0\n");
1896  for (lane = 0; lane < maxlane; lane++) {
1897  PRINTK_DEBUG("rcven lane %d\n", lane);
1898 // trylaneagain:
1899  dqshighaddr = C0MISCCTLy(lane);
1900 
1901  coarse = s->selected_timings.CAS + 1;
1902  pi = 0;
1903  medium = 0;
1904 
1905  mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
1906  mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), medium << (lane * 2));
1907 
1908  mchbar_clrbits8(C0RXRCVyDLL(lane), 0x3f);
1909 
1910  savecoarse = coarse;
1911  savemedium = medium;
1912  savepi = pi;
1913 
1914  PRINTK_DEBUG("rcven 0.1\n");
1915 
1916  // XXX comment out
1917  // mchbar_clrsetbits16(C0RCVMISCCTL1, 3 << (lane * 2), 1 << (lane * 2));
1918 
1919  while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1920  // printk(BIOS_DEBUG, "coarse=%d medium=%d\n", coarse, medium);
1921  rcvenclock(&coarse, &medium, lane);
1922  if (coarse > 0xf) {
1923  PRINTK_DEBUG("Error: coarse > 0xf\n");
1924  // goto trylaneagain;
1925  break;
1926  }
1927  }
1928  PRINTK_DEBUG("rcven 0.2\n");
1929 
1930  savecoarse = coarse;
1931  savemedium = medium;
1932  rcvenclock(&coarse, &medium, lane);
1933 
1934  while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1935  savecoarse = coarse;
1936  savemedium = medium;
1937  rcvenclock(&coarse, &medium, lane);
1938  if (coarse > 0xf) {
1939  PRINTK_DEBUG("Error: coarse > 0xf\n");
1940  //goto trylaneagain;
1941  break;
1942  }
1943  }
1944 
1945  PRINTK_DEBUG("rcven 0.3\n");
1946  coarse = savecoarse;
1947  medium = savemedium;
1948  mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
1949  mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), medium << (lane * 2));
1950 
1951  while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1952  savepi = pi;
1953  pi++;
1954  if (pi > s->maxpi) {
1955  // if (s->nodll) {
1956  pi = savepi = s->maxpi;
1957  break;
1958  // }
1959  }
1960  mchbar_clrsetbits8(C0RXRCVyDLL(lane), 0x3f, pi << s->pioffset);
1961  }
1962  PRINTK_DEBUG("rcven 0.4\n");
1963 
1964  pi = savepi;
1965  mchbar_clrsetbits8(C0RXRCVyDLL(lane), 0x3f, pi << s->pioffset);
1966  rcvenclock(&coarse, &medium, lane);
1967 
1968  if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1969  PRINTK_DEBUG("Error: DQS not high\n");
1970  // goto trylaneagain;
1971  }
1972  PRINTK_DEBUG("rcven 0.5\n");
1973  while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1974  coarse--;
1975  mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
1976  if (coarse == 0) {
1977  PRINTK_DEBUG("Error: DQS did not hit 0\n");
1978  break;
1979  }
1980  }
1981 
1982  PRINTK_DEBUG("rcven 0.6\n");
1983  rcvenclock(&coarse, &medium, lane);
1984  s->pi[lane] = pi;
1985  lanecoarse[lane] = coarse;
1986  }
1987 
1988  PRINTK_DEBUG("rcven 1\n");
1989 
1990  lane = maxlane;
1991  do {
1992  lane--;
1993  if (minlanecoarse > lanecoarse[lane]) {
1994  minlanecoarse = lanecoarse[lane];
1995  }
1996  } while (lane != 0);
1997 
1998  lane = maxlane;
1999  do {
2000  lane--;
2001  offset = lanecoarse[lane] - minlanecoarse;
2002  mchbar_clrsetbits16(C0COARSEDLY0, 3 << (lane * 2), offset << (lane * 2));
2003  } while (lane != 0);
2004 
2005  mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, minlanecoarse << 16);
2006 
2007  s->coarsectrl = minlanecoarse;
2008  s->coarsedelay = mchbar_read16(C0COARSEDLY0);
2009  s->mediumphase = mchbar_read16(C0RCVMISCCTL2);
2010  s->readptrdelay = mchbar_read16(C0RCVMISCCTL1);
2011 
2012  PRINTK_DEBUG("rcven 2\n");
2013  mchbar_clrbits8(C0RSTCTL, 7 << 1);
2014  mchbar_setbits8(C0RSTCTL, 1 << 1);
2015  mchbar_setbits8(C0RSTCTL, 1 << 2);
2016  mchbar_setbits8(C0RSTCTL, 1 << 3);
2017 
2018  mchbar_setbits8(CMNDQFIFORST, 1 << 7);
2019  mchbar_clrbits8(CMNDQFIFORST, 1 << 7);
2020  mchbar_setbits8(CMNDQFIFORST, 1 << 7);
2021  PRINTK_DEBUG("rcven 3\n");
2022 }
2023 
2024 /* NOTE: Unless otherwise specified, the values are expressed in MiB */
2025 static void sdram_mmap_regs(struct sysinfo *s)
2026 {
2027  bool reclaim;
2028  u32 mmiosize, tom, tolud, touud, reclaimbase, reclaimlimit;
2029  u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase, tsegsize;
2030  u16 ggc;
2031  u16 ggc_to_uma[10] = {0, 1, 4, 8, 16, 32, 48, 64, 128, 256};
2032  u8 ggc_to_gtt[4] = {0, 1, 0, 0};
2033 
2034  reclaimbase = 0;
2035  reclaimlimit = 0;
2036 
2038  printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
2039 
2040  gfxsize = ggc_to_uma[(ggc & 0x00f0) >> 4];
2041 
2042  gttsize = ggc_to_gtt[(ggc & 0x0300) >> 8];
2043 
2044  tom = s->channel_capacity[0];
2045 
2046  /* With GTT always being 1M, TSEG 1M is the only setting that can
2047  be covered by SMRR which has alignment requirements. */
2048  tsegsize = 1;
2049  mmiosize = 1024;
2050 
2051  reclaim = false;
2052  tolud = MIN(4096 - mmiosize, tom);
2053  if ((tom - tolud) > 64) {
2054  reclaim = true;
2055  }
2056  if (reclaim) {
2057  tolud = tolud & ~0x3f;
2058  tom = tom & ~0x3f;
2059  reclaimbase = MAX(4096, tom);
2060  reclaimlimit = reclaimbase + (MIN(4096, tom) - tolud) - 0x40;
2061  }
2062  touud = tom;
2063  if (reclaim) {
2064  touud = reclaimlimit + 64;
2065  }
2066 
2067  gfxbase = tolud - gfxsize;
2068  gttbase = gfxbase - gttsize;
2069  tsegbase = gttbase - tsegsize;
2070 
2071  /* Program the regs */
2072  pci_write_config16(HOST_BRIDGE, TOLUD, (u16)(tolud << 4));
2073  pci_write_config16(HOST_BRIDGE, TOM, (u16)(tom >> 6));
2074  if (reclaim) {
2075  pci_write_config16(HOST_BRIDGE, 0x98, (u16)(reclaimbase >> 6));
2076  pci_write_config16(HOST_BRIDGE, 0x9a, (u16)(reclaimlimit >> 6));
2077  }
2079  pci_write_config32(HOST_BRIDGE, GBSM, gfxbase << 20);
2080  pci_write_config32(HOST_BRIDGE, BGSM, gttbase << 20);
2081  pci_write_config32(HOST_BRIDGE, TSEG, tsegbase << 20);
2082 
2084  reg8 &= ~0x07;
2085  reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
2087 
2088  printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
2089  pci_read_config32(HOST_BRIDGE, GBSM), gfxbase << 20);
2090  printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
2091  pci_read_config32(HOST_BRIDGE, BGSM), gttbase << 20);
2092  printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
2093  pci_read_config32(HOST_BRIDGE, TSEG), tsegbase << 20);
2094 }
2095 
2096 static void sdram_enhancedmode(struct sysinfo *s)
2097 {
2098  u8 reg8, ch, r, fsb_freq, ddr_freq;
2099  u32 mask32, reg32;
2100  mchbar_setbits8(C0ADDCSCTRL, 1 << 0);
2101  mchbar_setbits8(C0REFRCTRL + 3, 1 << 0);
2102  mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
2103  reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2104  mchbar_clrsetbits32(WRWMCONFIG, mask32, reg32);
2105  mchbar_write8(C0DITCTRL + 1, 2);
2106  mchbar_write16(C0DITCTRL + 2, 0x0804);
2107  mchbar_write16(C0DITCTRL + 4, 0x2010);
2108  mchbar_write8(C0DITCTRL + 6, 0x40);
2109  mchbar_write16(C0DITCTRL + 8, 0x091c);
2110  mchbar_write8(C0DITCTRL + 10, 0xf2);
2111  mchbar_setbits8(C0BYPCTRL, 1 << 0);
2112  mchbar_setbits8(C0CWBCTRL, 1 << 0);
2113  mchbar_setbits16(C0ARBSPL, 1 << 8);
2114 
2115  pci_or_config8(HOST_BRIDGE, 0xf0, 1);
2116  mchbar_write32(SBCTL, 0x00000002);
2117  mchbar_write32(SBCTL2, 0x20310002);
2118  mchbar_write32(SLIMCFGTMG, 0x02020302);
2119  mchbar_write32(HIT0, 0x001f1806);
2120  mchbar_write32(HIT1, 0x01102800);
2121  mchbar_write32(HIT2, 0x07000000);
2122  mchbar_write32(HIT3, 0x01014010);
2123  mchbar_write32(HIT4, 0x0f038000);
2124  pci_and_config8(HOST_BRIDGE, 0xf0, ~1);
2125 
2126  u32 nranks, curranksize, maxranksize, dra;
2127  u8 rankmismatch;
2128  static const u8 drbtab[10] = {0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8, 0x20, 0x10};
2129 
2130  nranks = 0;
2131  curranksize = 0;
2132  maxranksize = 0;
2133  rankmismatch = 0;
2134 
2135  FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2136  nranks++;
2137  dra = (u8) ((mchbar_read32(C0DRA01) >> (8 * r)) & 0x7f);
2138  curranksize = drbtab[dra];
2139  if (maxranksize == 0) {
2140  maxranksize = curranksize;
2141  }
2142  if (curranksize != maxranksize) {
2143  rankmismatch = 1;
2144  }
2145  }
2146 
2147  reg8 = 0;
2148  switch (nranks) {
2149  case 4:
2150  if (rankmismatch) {
2151  reg8 = 0x64;
2152  } else {
2153  reg8 = 0xa4;
2154  }
2155  break;
2156  case 1:
2157  case 3:
2158  reg8 = 0x64;
2159  break;
2160  case 2:
2161  if (rankmismatch) {
2162  reg8 = 0x64;
2163  } else {
2164  reg8 = 0x24;
2165  }
2166  break;
2167  default:
2168  die("Invalid number of ranks found, halt\n");
2169  break;
2170  }
2171  mchbar_clrsetbits8(CHDECMISC, 0xfc, reg8 & 0xfc);
2172  mchbar_clrbits32(NOACFGBUSCTL, 1 << 31);
2173 
2174  mchbar_write32(HTBONUS0, 0xf);
2175  mchbar_setbits8(C0COREBONUS + 4, 1 << 0);
2176 
2177  mchbar_clrbits32(HIT3, 7 << 25);
2178  mchbar_clrsetbits32(HIT4, 3 << 18, 1 << 18);
2179 
2180  u32 clkcx[2][2][3] = {
2181  {
2182  {0x00000000, 0x0c080302, 0x08010204}, /* FSB = 667, DDR = 667 */
2183  {0x02040000, 0x08100102, 0x00000000}, /* FSB = 667, DDR = 800 */
2184  },
2185  {
2186  {0x18000000, 0x3021060c, 0x20010208}, /* FSB = 800, DDR = 667 */
2187  {0x00000000, 0x0c090306, 0x00000000}, /* FSB = 800, DDR = 800 */
2188  }
2189  };
2190 
2191  fsb_freq = s->selected_timings.fsb_clock;
2192  ddr_freq = s->selected_timings.mem_clock;
2193 
2194  mchbar_write32(CLKXSSH2X2MD + 0, clkcx[fsb_freq][ddr_freq][0]);
2195  mchbar_write32(CLKXSSH2X2MD + 4, clkcx[fsb_freq][ddr_freq][1]);
2196  mchbar_write32(CLKXSSH2MCBYP + 4, clkcx[fsb_freq][ddr_freq][2]);
2197 
2198  mchbar_clrbits8(HIT4, 1 << 1);
2199 }
2200 
2201 static void sdram_periodic_rcomp(void)
2202 {
2203  mchbar_clrbits8(COMPCTRL1, 1 << 1);
2204  while ((mchbar_read32(COMPCTRL1) & (1 << 31)) > 0) {
2205  ;
2206  }
2207  mchbar_clrbits16(CSHRMISCCTL, 3 << 12);
2208  mchbar_setbits8(CMNDQFIFORST, 1 << 7);
2209  mchbar_clrsetbits16(XCOMPDFCTRL, 0x0f, 0x09);
2210 
2211  mchbar_setbits8(COMPCTRL1, 1 << 7 | 1 << 1);
2212 }
2213 
2214 static void sdram_new_trd(struct sysinfo *s)
2215 {
2216  u8 pidelay, i, j, k, cc, trd_perphase[5];
2217  u8 bypass, freqgb, trd, reg8, txfifo;
2218  u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2219  u16 tmclk, thclk, buffertocore, postcalib;
2220  static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2221  static const u16 trd_adjust[2][2][5] = {
2222  {
2223  {3000, 3000, 0,0,0},
2224  {1000,2000,3000,1500,2500}
2225  },
2226  {
2227  {2000,1000,3000,0,0},
2228  {2500, 2500, 0,0,0}
2229  }};
2230 
2231  freqgb = 110;
2232  buffertocore = 5000;
2233  postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2234  tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2235  tmclk = tmclk * 100 / freqgb;
2236  thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2237  switch (s->selected_timings.mem_clock) {
2238  case MEM_CLOCK_667MHz:
2239  if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2240  cc = 2;
2241  } else {
2242  cc = 3;
2243  }
2244  break;
2245  default:
2246  case MEM_CLOCK_800MHz:
2247  if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2248  cc = 5;
2249  } else {
2250  cc = 2;
2251  }
2252  break;
2253  }
2254  tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2255  maxrcvendelay = 0;
2256  pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2257 
2258  for (i = 0; i < 8; i++) {
2259  rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 3) * (u32)(tmclk));
2260  rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 3) * (u32)(tmclk) / 2);
2261  rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 3) * (u32)(tmclk) / 4);
2262  rcvendelay += (u32)(pidelay * s->pi[i]);
2263  maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2264  }
2265 
2266  if ((mchbar_read8(HMBYPCP + 3) == 0xff) && (mchbar_read8(HMCCMC) & (1 << 7))) {
2267  bypass = 1;
2268  } else {
2269  bypass = 0;
2270  }
2271 
2272  txfifo = 0;
2273  reg8 = (mchbar_read8(CSHRFIFOCTL) & 0x0e) >> 1;
2274  txfifo = txfifo_lut[reg8] & 0x07;
2275 
2276  datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2277  + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2278  if (s->async) {
2279  datadelay += tmclk / 2;
2280  }
2281 
2282  j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2283  k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2284 
2285  if (j == 0 && k == 0) {
2286  datadelay -= 3084;
2287  }
2288 
2289  trd = 0;
2290  for (i = 0; i < cc; i++) {
2291  reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2292  trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2293  trd_perphase[i] += 1;
2294  if (trd_perphase[i] > trd) {
2295  trd = trd_perphase[i];
2296  }
2297  }
2298 
2299  mchbar_clrsetbits16(C0STATRDCTRL, 0x1f << 8, trd << 8);
2300 }
2301 
2302 static void sdram_powersettings(struct sysinfo *s)
2303 {
2304  u8 j;
2305  u32 reg32;
2306 
2307  /* Thermal sensor */
2308  mchbar_write8(TSC1, 0x9b);
2309  mchbar_clrsetbits32(TSTTP, 0x00ffffff, 0x1d00);
2310  mchbar_write8(THERM1, 0x08);
2311  mchbar_write8(TSC3, 0);
2312  mchbar_clrsetbits8(TSC2, 0x0f, 0x04);
2313  mchbar_clrsetbits8(THERM1, 1, 1);
2314  mchbar_clrsetbits8(TCO, 1 << 7, 1 << 7);
2315 
2316  /* Clock gating */
2317  mchbar_clrbits32(PMMISC, 1 << 18 | 1 << 0);
2318  mchbar_clrbits8(SBCTL3 + 3, 1 << 7);
2319  mchbar_clrbits8(CISDCTRL + 3, 1 << 7);
2320  mchbar_clrbits16(CICGDIS, 0x1fff);
2321  mchbar_clrbits32(SBCLKGATECTRL, 0x1ffff);
2322  mchbar_clrsetbits16(HICLKGTCTL, 0x03ff, 0x06);
2323  mchbar_clrsetbits32(HTCLKGTCTL, ~0, 0x20);
2324  mchbar_clrbits8(TSMISC, 1 << 0);
2325  mchbar_write8(C0WRDPYN, s->selected_timings.CAS - 1 + 0x15);
2326  mchbar_clrsetbits16(CLOCKGATINGI, 0x07fc, 0x0040);
2327  mchbar_clrsetbits16(CLOCKGATINGII, 0x0fff, 0x0d00);
2329  mchbar_write16(GTDPCGC + 2, 0xffff);
2330 
2331  /* Sequencing */
2332  mchbar_clrsetbits32(HPWRCTL1, 0x1fffffff, 0x1f643fff);
2333  mchbar_clrsetbits32(HPWRCTL2, 0xffffff7f, 0x02010000);
2334  mchbar_clrsetbits16(HPWRCTL3, 7 << 12, 3 << 12);
2335 
2336  /* Power */
2337  mchbar_clrsetbits32(GFXC3C4, 0xffff0003, 0x10100000);
2338  mchbar_clrsetbits32(PMDSLFRC, 0x0001bff7, 0x00000078);
2339 
2340  if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz)
2341  mchbar_clrsetbits16(PMMSPMRES, 0x03ff, 0x00c8);
2342  else
2343  mchbar_clrsetbits16(PMMSPMRES, 0x03ff, 0x0100);
2344 
2345  j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2346 
2347  mchbar_clrsetbits32(PMCLKRC, 0x01fff37f, 0x10810700);
2348  mchbar_clrsetbits8(PMPXPRC, 7, 1);
2349  mchbar_clrbits8(PMBAK, 1 << 1);
2350 
2351  static const u16 ddr2lut[2][4][2] = {
2352  {
2353  {0x0000, 0x0000},
2354  {0x019A, 0x0039},
2355  {0x0099, 0x1049},
2356  {0x0000, 0x0000},
2357  },
2358  {
2359  {0x0000, 0x0000},
2360  {0x019A, 0x0039},
2361  {0x0099, 0x1049},
2362  {0x0099, 0x2159},
2363  },
2364  };
2365 
2366  mchbar_write16(C0C2REG, 0x7a89);
2367  mchbar_write8(SHC2REGII, 0xaa);
2368  mchbar_write16(SHC2REGII + 1, ddr2lut[j][s->selected_timings.CAS - 3][1]);
2369  mchbar_clrsetbits16(SHC2REGI, 0x7fff, ddr2lut[j][s->selected_timings.CAS - 3][0]);
2370  mchbar_clrsetbits16(CLOCKGATINGIII, 0xf000, 0xf000);
2371  mchbar_clrsetbits8(CSHWRIOBONUSX, 0x77, 4 << 4 | 4);
2372 
2373  reg32 = s->nodll ? 0x30000000 : 0;
2374 
2375  mchbar_clrsetbits32(C0COREBONUS, 0xf << 24, 1 << 29 | reg32);
2376 
2377  mchbar_clrsetbits32(CLOCKGATINGI, 0xf << 20, 0xf << 20);
2378  mchbar_clrsetbits32(CLOCKGATINGII - 1, 0x001ff000, 0xbf << 20);
2379  mchbar_clrsetbits16(SHC3C4REG2, 0x1f7f, 0x0b << 8 | 7 << 4 | 0x0b);
2380  mchbar_write16(SHC3C4REG3, 0x3264);
2381  mchbar_clrsetbits16(SHC3C4REG4, 0x3f3f, 0x14 << 8 | 0x0a);
2382 
2383  mchbar_setbits32(C1COREBONUS, 1 << 31 | 1 << 13);
2384 }
2385 
2386 static void sdram_programddr(void)
2387 {
2388  mchbar_clrsetbits16(CLOCKGATINGII, 0x03ff, 0x0100);
2389  mchbar_clrsetbits16(CLOCKGATINGIII, 0x003f, 0x0010);
2390  mchbar_clrsetbits16(CLOCKGATINGI, 0x7000, 0x2000);
2391 
2392  mchbar_clrbits8(CSHRPDCTL, 7 << 1);
2393  mchbar_clrbits8(CSHRWRIOMLNS, 3 << 2);
2394  mchbar_clrbits8(C0MISCCTLy(0), 7 << 1);
2395  mchbar_clrbits8(C0MISCCTLy(1), 7 << 1);
2396  mchbar_clrbits8(C0MISCCTLy(2), 7 << 1);
2397  mchbar_clrbits8(C0MISCCTLy(3), 7 << 1);
2398  mchbar_clrbits8(C0MISCCTLy(4), 7 << 1);
2399  mchbar_clrbits8(C0MISCCTLy(5), 7 << 1);
2400  mchbar_clrbits8(C0MISCCTLy(6), 7 << 1);
2401  mchbar_clrbits8(C0MISCCTLy(7), 7 << 1);
2402  mchbar_clrbits8(CSHRWRIOMLNS, 1 << 1);
2403 
2404  mchbar_clrbits16(CSHRMISCCTL, 1 << 10);
2406  mchbar_clrbits8(C0WRDPYN, 1 << 7);
2407  mchbar_clrbits32(C0COREBONUS, 1 << 22);
2408  mchbar_clrbits16(CLOCKGATINGI, 0x80fc);
2410 
2411  mchbar_clrbits8(CSHRPDCTL, 0x0d);
2412  mchbar_clrbits8(C0MISCCTLy(0), 1 << 0);
2413  mchbar_clrbits8(C0MISCCTLy(1), 1 << 0);
2414  mchbar_clrbits8(C0MISCCTLy(2), 1 << 0);
2415  mchbar_clrbits8(C0MISCCTLy(3), 1 << 0);
2416  mchbar_clrbits8(C0MISCCTLy(4), 1 << 0);
2417  mchbar_clrbits8(C0MISCCTLy(5), 1 << 0);
2418  mchbar_clrbits8(C0MISCCTLy(6), 1 << 0);
2419  mchbar_clrbits8(C0MISCCTLy(7), 1 << 0);
2420 
2421  mchbar_clrsetbits32(C0STATRDCTRL, 7 << 20, 3 << 20);
2422  mchbar_clrbits32(C0COREBONUS, 1 << 20);
2425  mchbar_clrsetbits32(SHCYCTRKCKEL, 3 << 26, 1 << 26);
2426  mchbar_setbits16(C0STATRDCTRL, 3 << 13);
2427  mchbar_setbits32(C0CKECTRL, 1 << 16);
2428  mchbar_setbits8(C0COREBONUS, 1 << 4);
2429  mchbar_setbits32(CLOCKGATINGI - 1, 0xf << 24);
2431  mchbar_setbits8(C0DYNSLVDLLEN, 3 << 6);
2433  mchbar_clrsetbits16(SHC2MINTM, ~0, 1 << 7);
2434  mchbar_clrsetbits8(SHC2IDLETM, 0xff, 0x10);
2435  mchbar_setbits16(C0COREBONUS, 0xf << 5);
2436  mchbar_setbits8(CSHWRIOBONUS, 3 << 3);
2438  mchbar_setbits16(SHC3C4REG1, 0x0a3f);
2440  mchbar_clrsetbits8(C0REFRCTRL2, 0xff, 0x4a);
2441  mchbar_clrbits8(C0COREBONUS + 4, 3 << 5);
2443 }
2444 
2445 static void sdram_programdqdqs(struct sysinfo *s)
2446 {
2447  u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2448  u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2449  u8 repeat, halfclk, feature, reg8, push;
2450  u16 cwb, pimdclk;
2451  u32 reg32;
2452  static const u8 txfifotab[8] = {0, 7, 6, 5, 2, 1, 4, 3};
2453 
2454  tpi = 3000;
2455  dqdqs_out = 4382;
2456  dqdqs_outdelay = 5083;
2457  dqdqs_delay = 4692;
2458  coretomcp = 0;
2459  txdelay = 0;
2460  halfclk = 0;
2461  tmaxunmask = 0;
2462  tmaxpi = 0;
2463  repeat = 2;
2464  feature = 0;
2465  cwb = 0;
2466  pimdclk = 0;
2467  reg32 = 0;
2468  push = 0;
2469  reg8 = 0;
2470 
2471  mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2472  refclk = 3000 - mdclk;
2473 
2474  coretomcp = ((mchbar_read8(C0ADDCSCTRL) >> 2) & 0x3) + 1;
2475  coretomcp *= mdclk;
2476 
2477  reg8 = (mchbar_read8(CSHRFIFOCTL) & 0x0e) >> 1;
2478 
2479  while (repeat) {
2480  txdelay = mdclk * (
2481  ((mchbar_read16(C0GNT2LNCH1) >> 8) & 0x7) +
2482  (mchbar_read8(C0WRDATACTRL) & 0xf) +
2483  (mchbar_read8(C0WRDATACTRL + 1) & 0x1)
2484  ) +
2485  txfifotab[reg8]*(mdclk / 2) +
2486  coretomcp +
2487  refclk +
2488  cwb;
2489  halfclk = (mchbar_read8(C0MISCCTL) >> 1) & 0x1;
2490  if (halfclk) {
2491  txdelay -= mdclk / 2;
2492  reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2493  } else {
2494  reg32 = dqdqs_outdelay + coretomcp;
2495  }
2496 
2497  tmaxunmask = txdelay - mdclk - dqdqs_out;
2498  tmaxpi = tmaxunmask - tpi;
2499 
2500  if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2501  if (repeat == 2) {
2502  mchbar_clrbits32(C0COREBONUS, 1 << 23);
2503  }
2504  feature = 1;
2505  repeat = 0;
2506  } else {
2507  repeat--;
2508  mchbar_setbits32(C0COREBONUS, 1 << 23);
2509  cwb = 2 * mdclk;
2510  }
2511  }
2512 
2513  if (!feature) {
2515  return;
2516  }
2518  mchbar_clrsetbits16(CLOCKGATINGIII, 0xf << 12, pimdclk << 12);
2519  mchbar_clrsetbits8(CSHWRIOBONUSX, 0x77, push << 4 | push);
2520  mchbar_clrsetbits32(C0COREBONUS, 0xf << 24, 3 << 24);
2521 }
2522 
2523 /**
2524  * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2525  */
2526 void sdram_initialize(int boot_path, const u8 *spd_addresses)
2527 {
2528  struct sysinfo si;
2529  const char *boot_str[] = {"Normal", "Reset", "Resume"};
2530 
2531  PRINTK_DEBUG("Setting up RAM controller.\n");
2532 
2533  memset(&si, 0, sizeof(si));
2534 
2535  si.boot_path = boot_path;
2536  printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
2537  si.spd_map[0] = spd_addresses[0];
2538  si.spd_map[1] = spd_addresses[1];
2539  si.spd_map[2] = spd_addresses[2];
2540  si.spd_map[3] = spd_addresses[3];
2541 
2542  sdram_read_spds(&si);
2543 
2544  /* Choose Common Frequency */
2546 
2547  /* Determine smallest common tRAS, tRP, tRCD, etc */
2549 
2550  /* Enable HPET */
2551  enable_hpet();
2552 
2553  mchbar_setbits16(CPCTL, 1 << 15);
2554 
2555  sdram_clk_crossing(&si);
2556 
2557  sdram_checkreset();
2558  PRINTK_DEBUG("Done checkreset\n");
2559 
2560  sdram_clkmode(&si);
2561  PRINTK_DEBUG("Done clkmode\n");
2562 
2563  sdram_timings(&si);
2564  PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2565 
2566  if (si.boot_path != BOOT_PATH_RESET) {
2567  sdram_dlltiming(&si);
2568  PRINTK_DEBUG("Done dlltiming\n");
2569  }
2570 
2571  if (si.boot_path != BOOT_PATH_RESET) {
2572  sdram_rcomp(&si);
2573  PRINTK_DEBUG("Done RCOMP\n");
2574  }
2575 
2576  sdram_odt(&si);
2577  PRINTK_DEBUG("Done odt\n");
2578 
2579  if (si.boot_path != BOOT_PATH_RESET) {
2580  while ((mchbar_read8(COMPCTRL1) & 1) != 0)
2581  ;
2582  }
2583 
2584  sdram_mmap(&si);
2585  PRINTK_DEBUG("Done mmap\n");
2586 
2587  /* Enable DDR IO buffer */
2588  mchbar_clrsetbits8(C0IOBUFACTCTL, 0x3f, 0x08);
2589  mchbar_setbits8(C0RSTCTL, 1 << 0);
2590 
2591  sdram_rcompupdate(&si);
2592  PRINTK_DEBUG("Done RCOMP update\n");
2593 
2594  mchbar_setbits8(HIT4, 1 << 1);
2595 
2596  if (si.boot_path != BOOT_PATH_RESUME) {
2597  mchbar_setbits32(C0CKECTRL, 1 << 27);
2598 
2599  sdram_jedecinit(&si);
2600  PRINTK_DEBUG("Done MRS\n");
2601  }
2602 
2603  sdram_misc(&si);
2604  PRINTK_DEBUG("Done misc\n");
2605 
2606  sdram_zqcl(&si);
2607  PRINTK_DEBUG("Done zqcl\n");
2608 
2609  if (si.boot_path != BOOT_PATH_RESUME) {
2610  mchbar_setbits32(C0REFRCTRL2, 3 << 30);
2611  }
2612 
2613  sdram_dradrb(&si);
2614  PRINTK_DEBUG("Done dradrb\n");
2615 
2616  sdram_rcven(&si);
2617  PRINTK_DEBUG("Done rcven\n");
2618 
2619  sdram_new_trd(&si);
2620  PRINTK_DEBUG("Done tRD\n");
2621 
2622  sdram_mmap_regs(&si);
2623  PRINTK_DEBUG("Done mmap regs\n");
2624 
2625  sdram_enhancedmode(&si);
2626  PRINTK_DEBUG("Done enhanced mode\n");
2627 
2628  sdram_powersettings(&si);
2629  PRINTK_DEBUG("Done power settings\n");
2630 
2631  sdram_programddr();
2632  PRINTK_DEBUG("Done programming ddr\n");
2633 
2634  sdram_programdqdqs(&si);
2635  PRINTK_DEBUG("Done programming dqdqs\n");
2636 
2638  PRINTK_DEBUG("Done periodic RCOMP\n");
2639 
2640  /* Set init done */
2641  mchbar_setbits32(C0REFRCTRL2, 1 << 30);
2642 
2643  /* Tell ICH7 that we're done */
2644  pci_and_config8(PCI_DEV(0, 0x1f, 0), 0xa2, (u8)~(1 << 7));
2645 
2646  /* Tell northbridge we're done */
2647  pci_or_config8(HOST_BRIDGE, 0xf4, 1);
2648 
2649  printk(BIOS_DEBUG, "RAM initialization finished.\n");
2650 }
static uint32_t read32(const void *addr)
Definition: mmio.h:22
void * memset(void *dstpp, int c, size_t len)
Definition: memset.c:12
#define push
Definition: asmlib.h:27
#define MIN(a, b)
Definition: helpers.h:37
#define MAX(a, b)
Definition: helpers.h:40
#define DIV_ROUND_UP(x, y)
Definition: helpers.h:60
void full_reset(void)
Definition: cf9_reset.c:45
static u32 addr
Definition: cirrus.c:14
#define printk(level,...)
Definition: stdlib.h:16
void __noreturn die(const char *fmt,...)
Definition: die.c:17
static __always_inline uint8_t mchbar_read8(const uintptr_t offset)
Definition: fixed_bars.h:11
#define mchbar_setbits32(addr, set)
Definition: fixed_bars.h:58
static __always_inline void mchbar_write16(const uintptr_t offset, const uint16_t value)
Definition: fixed_bars.h:31
static __always_inline void mchbar_write8(const uintptr_t offset, const uint8_t value)
Definition: fixed_bars.h:26
static __always_inline void mchbar_clrsetbits8(uintptr_t offset, uint8_t clear, uint8_t set)
Definition: fixed_bars.h:41
static __always_inline void mchbar_write32(const uintptr_t offset, const uint32_t value)
Definition: fixed_bars.h:36
#define mchbar_clrbits8(addr, clear)
Definition: fixed_bars.h:60
#define mchbar_clrbits16(addr, clear)
Definition: fixed_bars.h:61
#define mchbar_setbits8(addr, set)
Definition: fixed_bars.h:56
static __always_inline void mchbar_clrsetbits32(uintptr_t offset, uint32_t clear, uint32_t set)
Definition: fixed_bars.h:51
static __always_inline uint32_t mchbar_read32(const uintptr_t offset)
Definition: fixed_bars.h:21
#define mchbar_clrbits32(addr, clear)
Definition: fixed_bars.h:62
static __always_inline void mchbar_clrsetbits16(uintptr_t offset, uint16_t clear, uint16_t set)
Definition: fixed_bars.h:46
static __always_inline uint16_t mchbar_read16(const uintptr_t offset)
Definition: fixed_bars.h:16
#define mchbar_setbits16(addr, set)
Definition: fixed_bars.h:57
static size_t offset
Definition: flashconsole.c:16
@ DDR2
Definition: gm45.h:52
@ FSB_CLOCK_800MHz
Definition: gm45.h:10
@ FSB_CLOCK_667MHz
Definition: gm45.h:11
#define GGC
Definition: host_bridge.h:9
#define TOLUD
Definition: host_bridge.h:61
#define TOUUD
Definition: host_bridge.h:57
#define TSEG
Definition: host_bridge.h:60
#define TOM
Definition: host_bridge.h:56
#define BGSM
Definition: host_bridge.h:59
#define GBSM
void hpet_udelay(u32 delay)
Definition: hpet.c:25
#define BOOT_PATH_RESET
Definition: raminit.h:34
#define BOOT_PATH_RESUME
Definition: raminit.h:35
#define CLKCFG
Definition: i945.h:217
#define C0DRB0
Definition: i945.h:101
#define C0ODT
Definition: i945.h:124
#define TSC1
Definition: i945.h:227
#define C0DRB2
Definition: i945.h:103
#define CPCTL
Definition: i945.h:219
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline void pci_and_config8(const struct device *dev, u16 reg, u8 andmask)
Definition: pci_ops.h:136
static __always_inline u16 pci_read_config16(const struct device *dev, u16 reg)
Definition: pci_ops.h:52
static __always_inline void pci_or_config8(const struct device *dev, u16 reg, u8 ormask)
Definition: pci_ops.h:169
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
static __always_inline u8 pci_read_config8(const struct device *dev, u16 reg)
Definition: pci_ops.h:46
static __always_inline void pci_write_config16(const struct device *dev, u16 reg, u16 val)
Definition: pci_ops.h:70
static __always_inline void pci_write_config8(const struct device *dev, u16 reg, u8 val)
Definition: pci_ops.h:64
void hexdump(const void *memory, size_t length)
Definition: hexdump.c:7
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define ESMRAMC
Definition: memmap.c:45
#define CSHRPDCTL3
Definition: mchbar_regs.h:98
#define HPWRCTL1
Definition: mchbar_regs.h:13
#define C0CYCTRKWR
Definition: mchbar_regs.h:146
#define HMDCMP
Definition: mchbar_regs.h:424
#define C0REFRCTRL2
Definition: mchbar_regs.h:155
#define C0ADDCSCTRL
Definition: mchbar_regs.h:140
#define SBCTL
Definition: mchbar_regs.h:499
#define C0ODTRKCTRL
Definition: mchbar_regs.h:164
#define XCOMPCMNBNS
Definition: mchbar_regs.h:89
#define C0DLLRCVCTLy(y)
Definition: mchbar_regs.h:351
#define CLKXSSH2MCBYPPHAS
Definition: mchbar_regs.h:397
#define C0TXCK0DLL
Definition: mchbar_regs.h:356
#define C0GNT2LNCH2
Definition: mchbar_regs.h:128
#define C0CMDTX1
Definition: mchbar_regs.h:367
#define C0CYCTRKREFR
Definition: mchbar_regs.h:148
#define SHC2REGIII
Definition: mchbar_regs.h:61
#define TSTTP
Definition: mchbar_regs.h:552
#define SHC3C4REG2
Definition: mchbar_regs.h:389
#define HICLKGTCTL
Definition: mchbar_regs.h:26
#define CLOCKGATINGII
Definition: mchbar_regs.h:396
#define C0RCVMISCCTL2
Definition: mchbar_regs.h:364
#define COMPCTRL2
Definition: mchbar_regs.h:71
#define CSHRPDCTL4
Definition: mchbar_regs.h:99
#define CSHRMSTRCTL1
Definition: mchbar_regs.h:104
#define CSHRPDCTL2
Definition: mchbar_regs.h:96
#define PMSTS
Definition: mchbar_regs.h:475
#define HPWRCTL2
Definition: mchbar_regs.h:14
#define C0JEDEC
Definition: mchbar_regs.h:158
#define C0TXDQ0R0DLL
Definition: mchbar_regs.h:286
#define C0RCOMPCTRL2
Definition: mchbar_regs.h:209
#define SHC3C4REG4
Definition: mchbar_regs.h:391
#define CSHWRIOBONUSX
Definition: mchbar_regs.h:533
#define HIT0
Definition: mchbar_regs.h:20
#define C0TXDQS0R0DLL
Definition: mchbar_regs.h:318
#define C0RCOMPCTRL3
Definition: mchbar_regs.h:224
#define CLOCKGATINGIII
Definition: mchbar_regs.h:122
#define HTCLKGTCTL
Definition: mchbar_regs.h:16
#define SHC2IDLETM
Definition: mchbar_regs.h:66
#define SBCTL3
Definition: mchbar_regs.h:502
#define SHC2REGII
Definition: mchbar_regs.h:59
#define SLIMCFGTMG
Definition: mchbar_regs.h:17
#define C0TXCTL1DLL
Definition: mchbar_regs.h:360
#define TCO
Definition: mchbar_regs.h:553
#define HIT4
Definition: mchbar_regs.h:24
#define SHC3C4REG3
Definition: mchbar_regs.h:390
#define C0DYNSLVDLLEN
Definition: mchbar_regs.h:366
#define C0TXCTL2DLL
Definition: mchbar_regs.h:361
#define HMCCPEXT
Definition: mchbar_regs.h:414
#define XCOMPSDR0BNS
Definition: mchbar_regs.h:285
#define ZQCALCTRL
Definition: mchbar_regs.h:88
#define C0CTLTX2
Definition: mchbar_regs.h:369
#define C0CWBCTRL
Definition: mchbar_regs.h:138
#define C0GNT2LNCH1
Definition: mchbar_regs.h:127
#define OFREQDELSEL
Definition: mchbar_regs.h:86
#define CLKXSSH2MCRDCST
Definition: mchbar_regs.h:400
#define PMPXPRC
Definition: mchbar_regs.h:520
#define CSHRWRIOMLNS
Definition: mchbar_regs.h:97
#define C0CMDTX2
Definition: mchbar_regs.h:368
#define SHC2REGI
Definition: mchbar_regs.h:58
#define C0MISCCTLy(y)
Definition: mchbar_regs.h:353
#define C0DITCTRL
Definition: mchbar_regs.h:163
#define CLOCKGATINGI
Definition: mchbar_regs.h:176
#define CLKXSSH2MD
Definition: mchbar_regs.h:403
#define SHC3C4REG1
Definition: mchbar_regs.h:123
#define C0SLVDLLOUTEN
Definition: mchbar_regs.h:538
#define C0CYCTRKRD
Definition: mchbar_regs.h:147
#define HMDCPEXT
Definition: mchbar_regs.h:415
#define C0TXCK1DLL
Definition: mchbar_regs.h:357
#define HMBYPCP
Definition: mchbar_regs.h:425
#define C0TXCMD1DLL
Definition: mchbar_regs.h:358
#define HTBONUS0
Definition: mchbar_regs.h:18
#define C0RCOMPCTRL6
Definition: mchbar_regs.h:269
#define CSHRMISCCTL1
Definition: mchbar_regs.h:110
#define PMBAK
Definition: mchbar_regs.h:523
#define C0COARSEDLY0
Definition: mchbar_regs.h:387
#define CREFPI
Definition: mchbar_regs.h:114
#define GTDPCGC
Definition: mchbar_regs.h:496
#define XCOMPDFCTRL
Definition: mchbar_regs.h:87
#define C0DYNRDCTRL
Definition: mchbar_regs.h:160
#define C0TXCTL0DLL
Definition: mchbar_regs.h:359
#define C0DLLPIEN
Definition: mchbar_regs.h:386
#define XCOMP
Definition: mchbar_regs.h:73
#define PMCLKRC
Definition: mchbar_regs.h:519
#define C0RCOMPCTRL5
Definition: mchbar_regs.h:254
#define PMDSLFRC
Definition: mchbar_regs.h:517
#define COMPCTRL3
Definition: mchbar_regs.h:72
#define C0DQSODTRECORDX
Definition: mchbar_regs.h:284
#define HIT1
Definition: mchbar_regs.h:21
#define C0DYNSLVDLLEN2
Definition: mchbar_regs.h:539
#define C0IOBUFACTCTL
Definition: mchbar_regs.h:384
#define CMNDQFIFORST
Definition: mchbar_regs.h:383
#define C0BYPCTRL
Definition: mchbar_regs.h:137
#define C0RXRCVyDLL(y)
Definition: mchbar_regs.h:352
#define CSHRDQSTXPGM
Definition: mchbar_regs.h:105
#define HIT3
Definition: mchbar_regs.h:23
#define SBCLKGATECTRL
Definition: mchbar_regs.h:503
#define CSHRPDCTL5
Definition: mchbar_regs.h:532
#define C0COREBONUS
Definition: mchbar_regs.h:174
#define SHCYCTRKCKEL
Definition: mchbar_regs.h:392
#define GFXC3C4
Definition: mchbar_regs.h:516
#define BYPKNRULE
Definition: mchbar_regs.h:68
#define C1COREBONUS
Definition: mchbar_regs.h:395
#define C0ARBCTRL
Definition: mchbar_regs.h:139
#define C0ODTRECORDX
Definition: mchbar_regs.h:283
#define C0RSTCTL
Definition: mchbar_regs.h:379
#define CSHRDQSCMN
Definition: mchbar_regs.h:106
#define THERM1
Definition: mchbar_regs.h:555
#define C0RCVMISCCTL1
Definition: mchbar_regs.h:363
#define COMPCTRL1
Definition: mchbar_regs.h:70
#define C0MISCCTL
Definition: mchbar_regs.h:380
#define CLKXSSMC2HALT
Definition: mchbar_regs.h:402
#define CSHRFIFOCTL
Definition: mchbar_regs.h:94
#define CLKXSSH2MCRDQ
Definition: mchbar_regs.h:399
#define C0CKTX
Definition: mchbar_regs.h:370
#define C0REFCTRL
Definition: mchbar_regs.h:172
#define C0RCOMPCTRL0
Definition: mchbar_regs.h:194
#define CSHRMSTDYNDLLENB
Definition: mchbar_regs.h:101
#define CISDCTRL
Definition: mchbar_regs.h:514
#define HMCCMC
Definition: mchbar_regs.h:410
#define SHPENDREG
Definition: mchbar_regs.h:62
#define CSHRPDCTL
Definition: mchbar_regs.h:91
#define C0CYCTRKACT
Definition: mchbar_regs.h:145
#define CSHWRIOBONUS
Definition: mchbar_regs.h:95
#define HPWRCTL3
Definition: mchbar_regs.h:15
#define C0CYCTRKPCHG
Definition: mchbar_regs.h:144
#define CHDECMISC
Definition: mchbar_regs.h:56
#define DCMEASBUFOVR
Definition: mchbar_regs.h:84
#define C0REFRCTRL
Definition: mchbar_regs.h:156
#define C0WRDPYN
Definition: mchbar_regs.h:133
#define HIT2
Definition: mchbar_regs.h:22
#define WRWMCONFIG
Definition: mchbar_regs.h:60
#define RCMEASBUFXOVR
Definition: mchbar_regs.h:74
#define SHPAGECTRL
Definition: mchbar_regs.h:63
#define SHCMPLWRCMD
Definition: mchbar_regs.h:64
#define C0CYCTRKPCHG2
Definition: mchbar_regs.h:149
#define TSMISC
Definition: mchbar_regs.h:443
#define C0C2REG
Definition: mchbar_regs.h:134
#define C0RDFIFOCTRL
Definition: mchbar_regs.h:142
#define PMMSPMRES
Definition: mchbar_regs.h:518
#define C0DQSRyTX1(y)
Definition: mchbar_regs.h:373
#define C0WRDATACTRL
Definition: mchbar_regs.h:143
#define SHBONUSREG
Definition: mchbar_regs.h:69
#define SHC2MINTM
Definition: mchbar_regs.h:65
#define CSHRMSTRCTL0
Definition: mchbar_regs.h:103
#define CLKXSSMC2H
Definition: mchbar_regs.h:401
#define TSC3
Definition: mchbar_regs.h:561
#define C0RCOMPCTRL4
Definition: mchbar_regs.h:239
#define C0CKECTRL
Definition: mchbar_regs.h:151
#define C0ARBSPL
Definition: mchbar_regs.h:159
#define C0RDQCTRL
Definition: mchbar_regs.h:150
#define HMCCMP
Definition: mchbar_regs.h:409
#define C0DRA01
Definition: mchbar_regs.h:120
#define MPLLCTL
Definition: mchbar_regs.h:112
#define BYPACTSF
Definition: mchbar_regs.h:67
#define NOACFGBUSCTL
Definition: mchbar_regs.h:53
#define C0PWLRCTRL
Definition: mchbar_regs.h:153
#define CSHRMISCCTL
Definition: mchbar_regs.h:109
#define CICGDIS
Definition: mchbar_regs.h:512
#define CLKXSSH2X2MD
Definition: mchbar_regs.h:404
#define C0WRWMFLSH
Definition: mchbar_regs.h:161
#define CLKXSSH2MCBYP
Definition: mchbar_regs.h:398
#define C0DQRyTX1(y)
Definition: mchbar_regs.h:372
#define TSC2
Definition: mchbar_regs.h:549
#define CSPDSLVWT
Definition: mchbar_regs.h:92
#define C0DQSDQRyTX3(y)
Definition: mchbar_regs.h:377
#define SBCTL2
Definition: mchbar_regs.h:500
#define C0TXCMD0DLL
Definition: mchbar_regs.h:355
#define C0MISCTM
Definition: mchbar_regs.h:129
#define C0PVCFG
Definition: mchbar_regs.h:157
#define C0TXCTL3DLL
Definition: mchbar_regs.h:362
#define CSHRDDR3CTL
Definition: mchbar_regs.h:107
#define PMMISC
Definition: mchbar_regs.h:476
#define C0STATRDCTRL
Definition: mchbar_regs.h:141
#define C0LATCTRL
Definition: mchbar_regs.h:136
static struct dramc_channel const ch[2]
void sdram_initialize(void)
Definition: raminit.c:1692
static void sdram_read_spds(struct sysinfo *s)
Definition: raminit.c:256
static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
Definition: raminit.c:952
static void sdram_jedecinit(struct sysinfo *s)
Definition: raminit.c:1659
static void sdram_calibratehwpll(struct sysinfo *s)
Definition: raminit.c:1056
static void sdram_powersettings(struct sysinfo *s)
Definition: raminit.c:2302
static void sdram_checkreset(void)
Definition: raminit.c:1732
static int decode_spd(struct dimminfo *d, int i)
Definition: raminit.c:93
static void sdram_dradrb(struct sysinfo *s)
Definition: raminit.c:1757
#define FOR_EACH_POPULATED_CHANNEL(dimms, idx)
Definition: raminit.c:66
static void sdram_p_clkset0(const struct pllparam *pll, u8 f, u8 i)
Definition: raminit.c:833
static void sdram_odt(struct sysinfo *s)
Definition: raminit.c:1478
#define C0RCOMPCTRLx(x)
Definition: raminit.c:1203
static void sdram_detect_ram_speed(struct sysinfo *s)
Definition: raminit.c:394
#define CBR_CMD
Definition: raminit.c:37
static void sdram_clkmode(struct sysinfo *s)
Definition: raminit.c:601
static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
Definition: raminit.c:904
static void sdram_detect_smallest_params(struct sysinfo *s)
Definition: raminit.c:328
#define EMRS2_CMD
Definition: raminit.c:34
#define C0RCOMPOSVx(x)
Definition: raminit.c:1206
static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
Definition: raminit.c:855
static void sdram_mmap_regs(struct sysinfo *s)
Definition: raminit.c:2025
#define C0RCOMPMULTx(x)
Definition: raminit.c:1204
static void sdram_programdqdqs(struct sysinfo *s)
Definition: raminit.c:2445
#define ONLY_DIMMA_IS_POPULATED(dimms, ch)
Definition: raminit.c:48
static u8 sdram_checkrcompoverride(void)
Definition: raminit.c:1579
static void sdram_dlltiming(struct sysinfo *s)
Definition: raminit.c:1082
#define FOR_EACH_POPULATED_RANK(dimms, ch, r)
Definition: raminit.c:77
#define UBDIMM
Definition: raminit.c:40
static void sdram_rcven(struct sysinfo *s)
Definition: raminit.c:1877
static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
Definition: raminit.c:1843
static void sdram_misc(struct sysinfo *s)
Definition: raminit.c:1714
static int lsbpos(u8 val)
Definition: raminit.c:310
static void sdram_p_clkset1(const struct pllparam *pll, u8 f, u8 i)
Definition: raminit.c:844
#define C0SLEWBASEx(x)
Definition: raminit.c:1211
#define PRINTK_DEBUG(x...)
Definition: raminit.c:21
#define C0SLEWPULUTx(x)
Definition: raminit.c:1212
#define NORMAL_OP_CMD
Definition: raminit.c:38
#define C0DCOMPx(x)
Definition: raminit.c:1210
static bool rank_is_populated(struct dimminfo dimms[], u8 ch, u8 r)
Definition: raminit.c:80
#define PRE_CHARGE_CMD
Definition: raminit.c:30
#define FOR_EACH_DIMM(idx)
Definition: raminit.c:57
static void sdram_programddr(void)
Definition: raminit.c:2386
static void barrier(void)
Definition: raminit.c:88
#define C0SLEWPDLUTx(x)
Definition: raminit.c:1213
#define C0DCOMPOFFx(x)
Definition: raminit.c:1215
#define EMRS3_CMD
Definition: raminit.c:35
#define C0SCOMPOVRx(x)
Definition: raminit.c:1208
#define MRS_CMD
Definition: raminit.c:31
static void sdram_clk_crossing(struct sysinfo *s)
Definition: raminit.c:533
static void sdram_periodic_rcomp(void)
Definition: raminit.c:2201
#define EMRS1_CMD
Definition: raminit.c:33
static void find_ramconfig(struct sysinfo *s, u32 chan)
Definition: raminit.c:144
#define FOR_EACH_POPULATED_DIMM(dimms, idx)
Definition: raminit.c:59
static void sdram_mmap(struct sysinfo *s)
Definition: raminit.c:1532
static void sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
Definition: raminit.c:1637
static int msbpos(u8 val)
Definition: raminit.c:320
static void sdram_rcomp(struct sysinfo *s)
Definition: raminit.c:1218
#define C0SCOMPOFFx(x)
Definition: raminit.c:1209
static void sdram_enhancedmode(struct sysinfo *s)
Definition: raminit.c:2096
static void sdram_new_trd(struct sysinfo *s)
Definition: raminit.c:2214
#define SODIMM
Definition: raminit.c:41
#define TABLE
Definition: raminit.c:1197
#define ONLY_DIMMB_IS_POPULATED(dimms, ch)
Definition: raminit.c:51
static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
Definition: raminit.c:872
static void sdram_timings(struct sysinfo *s)
Definition: raminit.c:630
#define FOR_EACH_RANK(ch, r)
Definition: raminit.c:75
static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
Definition: raminit.c:928
#define FOR_EACH_RCOMP_GROUP(idx)
Definition: raminit.c:1200
#define NOP_CMD
Definition: raminit.c:29
#define C0DCOMPOVRx(x)
Definition: raminit.c:1214
static void sdram_rcompupdate(struct sysinfo *s)
Definition: raminit.c:1608
#define C0SCOMPVREFx(x)
Definition: raminit.c:1207
static void sdram_zqcl(struct sysinfo *s)
Definition: raminit.c:1649
static void rcvenclock(u8 *coarse, u8 *medium, u8 lane)
Definition: raminit.c:1864
#define PCI_DEV(SEGBUS, DEV, FN)
Definition: pci_type.h:14
@ MEM_CLOCK_667MHz
Definition: raminit.h:18
@ MEM_CLOCK_800MHz
Definition: raminit.h:19
static void enable_hpet(struct device *dev)
Definition: lpc.c:39
@ HOST_BRIDGE
Definition: reg_access.h:23
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
unsigned char uint8_t
Definition: stdint.h:8
unsigned int cols
Definition: raminit.h:69
unsigned int tWR
Definition: raminit.h:73
unsigned int rows
Definition: raminit.h:68
unsigned int tAAmin
Definition: raminit.h:71
u8 type
Definition: raminit.h:61
unsigned int ranks
Definition: raminit.h:67
u8 spd_data[256]
Definition: raminit.h:78
unsigned int tRAS
Definition: raminit.h:76
unsigned int page_size
Definition: raminit.h:64
unsigned int tRP
Definition: raminit.h:74
enum chip_width width
Definition: raminit.h:62
enum chip_cap chip_capacity
Definition: raminit.h:63
unsigned int tCKmin
Definition: raminit.h:72
unsigned int sides
Definition: raminit.h:65
unsigned int tRCD
Definition: raminit.h:75
unsigned int banks
Definition: raminit.h:66
unsigned int cas_latencies
Definition: raminit.h:70
Definition: dw_i2c.c:39
Definition: pll_common.h:32
u8 spd_map[4]
Definition: raminit.h:115
int boot_path
Definition: raminit.h:100
u8 val
Definition: sys.c:300
static void __noreturn reset(void)
#define s(param, src_bits, pmcreg, dst_bits)
#define c(value, pmcreg, dst_bits)
#define count