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