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