blob: 7f59d9197bdb303609e0818b81b38415e0d909d2 [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) {
Jacob Garber78107932019-06-11 12:45:51 -0600501 if ((s->dimms[i].spd_data[9] > 0x30) ||
502 (s->dimms[i].spd_data[10] > 0x45)) {
503 // CAS too fast, lower it
504 highcas--;
505 } else {
506 cas = highcas;
Damien Zammit003d15c2015-11-20 17:17:51 +1100507 }
508 }
509 }
510 if (cas == 0) {
511 die("Unsupported dimms\n");
512 }
513 }
514
515 s->selected_timings.CAS = cas;
516 s->selected_timings.mem_clock = freq;
517 s->selected_timings.fsb_clock = fsb;
518
519 PRINTK_DEBUG("Drive Memory at %dMHz with CAS = %d clocks\n", ddr_reg_to_mhz(s->selected_timings.mem_clock), s->selected_timings.CAS);
520
521 // Set memory frequency
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200522 if (s->boot_path == BOOT_PATH_RESET)
523 return;
Damien Zammit003d15c2015-11-20 17:17:51 +1100524 MCHBAR32(0xf14) = MCHBAR32(0xf14) | 0x1;
525 reg32 = (MCHBAR32(0xc00) & (~0x70)) | (1 << 10);
526 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
527 reg8 = 3;
528 } else {
529 reg8 = 2;
530 }
531 reg32 |= reg8 << 4;
532 MCHBAR32(0xc00) = reg32;
533 s->selected_timings.mem_clock = ((MCHBAR32(0xc00) >> 4) & 0x7) - 2;
534 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
535 PRINTK_DEBUG("MCH validated at 800MHz\n");
536 s->nodll = 0;
537 s->maxpi = 63;
538 s->pioffset = 0;
539 } else if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
540 PRINTK_DEBUG("MCH validated at 667MHz\n");
541 s->nodll = 1;
542 s->maxpi = 15;
543 s->pioffset = 1;
544 } else {
545 PRINTK_DEBUG("MCH set to unknown (%02x)\n",
546 (uint8_t) s->selected_timings.mem_clock & 0xff);
547 }
548}
549
550#define HPET_BASE 0xfed00000
551#define HPET32(x) *((volatile u32 *)(HPET_BASE + x))
552static void enable_hpet(void)
553{
554 u32 reg32;
Arthur Heymansc73c9232019-10-02 14:57:50 +0200555 reg32 = RCBA32(HPTC);
Damien Zammit003d15c2015-11-20 17:17:51 +1100556 reg32 &= ~0x3;
557 reg32 |= (1 << 7);
Arthur Heymansc73c9232019-10-02 14:57:50 +0200558 RCBA32(HPTC) = reg32;
559 /* On NM10 this only works if read back */
560 RCBA32(HPTC);
Damien Zammit003d15c2015-11-20 17:17:51 +1100561 HPET32(0x10) = HPET32(0x10) | 1;
562}
563
564static void sdram_clk_crossing(struct sysinfo *s)
565{
566 u8 clk_idx, fsb_idx;
Arthur Heymans6bf13012017-06-10 12:03:27 +0200567 static const u32 clkcross[2][2][4] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100568 {
569 {0xFFFFFFFF, 0x05030305, 0x0000FFFF, 0x00000000}, //667 667
570 {0x1F1F1F1F, 0x2A1F1FA5, 0x00000000, 0x05000002}, //667 800
571 },
572 {
573 {0x1F1F1F1F, 0x0D07070B, 0x00000000, 0x00000000}, //800 667
574 {0xFFFFFFFF, 0x05030305, 0x0000FFFF, 0x00000000}, //800 800
575 }
576 };
577 clk_idx = s->selected_timings.mem_clock;
578 fsb_idx = s->selected_timings.fsb_clock;
579
580 MCHBAR32(0xc04) = clkcross[fsb_idx][clk_idx][0];
581 MCHBAR32(0xc50) = clkcross[fsb_idx][clk_idx][1];
582 MCHBAR32(0xc54) = clkcross[fsb_idx][clk_idx][2];
583 MCHBAR32(0xc28) = 0;
584 MCHBAR32(0xc2c) = clkcross[fsb_idx][clk_idx][3];
585 MCHBAR32(0xc08) = MCHBAR32(0xc08) | (1 << 7);
586
587 if ((fsb_idx == 0) && (clk_idx == 1)) {
588 MCHBAR8(0x6d4) = 0;
589 MCHBAR32(0x700) = 0;
590 MCHBAR32(0x704) = 0;
591 }
592
Arthur Heymans6bf13012017-06-10 12:03:27 +0200593 static const u32 clkcross2[2][2][8] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100594 {
595 { 0, 0x08010204, 0, 0x08010204, 0, 0, 0, 0x04080102}, // 667 667
596 { 0x04080000, 0x10010002, 0x10000000, 0x20010208, 0, 0x00000004, 0x02040000, 0x08100102}, // 667 800
597 },
598 {
599 { 0x10000000, 0x20010208, 0x04080000, 0x10010002, 0, 0, 0x08000000, 0x10200204}, // 800 667
600 { 0x00000000, 0x08010204, 0, 0x08010204, 0, 0, 0, 0x04080102}, // 800 800
601 }
602 };
603
604 MCHBAR32(0x6d8) = clkcross2[fsb_idx][clk_idx][0];
605 MCHBAR32(0x6e0) = clkcross2[fsb_idx][clk_idx][0];
606 MCHBAR32(0x6e8) = clkcross2[fsb_idx][clk_idx][0];
607 MCHBAR32(0x6d8+4) = clkcross2[fsb_idx][clk_idx][1];
608 MCHBAR32(0x6e0+4) = clkcross2[fsb_idx][clk_idx][1];
609 MCHBAR32(0x6e8+4) = clkcross2[fsb_idx][clk_idx][1];
610 MCHBAR32(0x6f0) = clkcross2[fsb_idx][clk_idx][2];
611 MCHBAR32(0x6f4) = clkcross2[fsb_idx][clk_idx][3];
612 MCHBAR32(0x6f8) = clkcross2[fsb_idx][clk_idx][4];
613 MCHBAR32(0x6fc) = clkcross2[fsb_idx][clk_idx][5];
614 MCHBAR32(0x708) = clkcross2[fsb_idx][clk_idx][6];
615 MCHBAR32(0x70c) = clkcross2[fsb_idx][clk_idx][7];
616}
617
618static void sdram_clkmode(struct sysinfo *s)
619{
620 u8 reg8;
621 u16 reg16;
622
623 MCHBAR16(0x1b6) = MCHBAR16(0x1b6) & ~(1 << 8);
624 MCHBAR8(0x1b6) = MCHBAR8(0x1b6) & ~0x3f;
625
626 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
627 reg8 = 0;
628 reg16 = 1;
629 } else {
630 reg8 = 1;
631 reg16 = (1 << 8) | (1 << 5);
632 }
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200633 if (s->boot_path != BOOT_PATH_RESET)
634 MCHBAR16(0x1c0) = (MCHBAR16(0x1c0) & ~(0x033f)) | reg16;
Damien Zammit003d15c2015-11-20 17:17:51 +1100635
636 MCHBAR32(0x220) = 0x58001117;
637 MCHBAR32(0x248) = (MCHBAR32(0x248) | (1 << 23));
638
639 const u32 cas_to_reg[2][4] = {
640 {0x00000000, 0x00030100, 0x0C240201, 0x00000000}, // 667
641 {0x00000000, 0x00030100, 0x0C240201, 0x10450302} // 800
642 };
643
644 MCHBAR32(0x224) = cas_to_reg[reg8][s->selected_timings.CAS - 3];
645}
646
647static void sdram_timings(struct sysinfo *s)
648{
649 u8 i, j, ch, r, ta1, ta2, ta3, ta4, trp, bank, page, flag;
650 u8 reg8, wl;
651 u16 reg16;
652 u32 reg32, reg2;
Arthur Heymans6bf13012017-06-10 12:03:27 +0200653 static const u8 pagetab[2][2] = {{0xe, 0x12}, {0x10, 0x14}};
Damien Zammit003d15c2015-11-20 17:17:51 +1100654
655 // Only consider DDR2
656 wl = s->selected_timings.CAS - 1;
657 ta1 = ta2 = 6;
658 ta3 = s->selected_timings.CAS;
659 ta4 = 8;
660 s->selected_timings.tRFC = (s->selected_timings.tRFC + 1) & 0xfe;
661 trp = 0;
662 bank = 1;
663 page = 0;
664
665 MCHBAR8(0x240) = ((wl - 3) << 4) | (s->selected_timings.CAS - 3);
666
667 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
668 i = ch << 1;
669 if (s->dimms[i].banks == 1) {
670 trp = 1;
671 bank = 0;
672 }
673 if (s->dimms[i].page_size == 2048) {
674 page = 1;
675 }
676 }
677 PRINTK_DEBUG("trp=%d bank=%d page=%d\n",trp, bank, page);
678
679 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
680 flag = 0;
681 } else {
682 flag = 1;
683 }
684
685 MCHBAR8(0x26f) = MCHBAR8(0x26f) | 0x3;
686 MCHBAR16(0x250) = ((wl + 4 + s->selected_timings.tWR) << 6) |
687 ((2 + MAX(s->selected_timings.tRTP, 2)) << 2) | 1;
688 reg32 = (bank << 21) | (s->selected_timings.tRRD << 17) |
689 (s->selected_timings.tRP << 13) |
690 ((s->selected_timings.tRP + trp) << 9) |
691 s->selected_timings.tRFC;
692 if (bank == 0) {
693 reg32 |= (pagetab[flag][page] << 22);
694 }
695 MCHBAR16(0x252) = (u16) reg32;
696 MCHBAR16(0x254) = (u16) (reg32 >> 16);
697
698 reg16 = (MCHBAR16(0x254) & 0xfc0) >> 6;
699 MCHBAR16(0x62c) = (MCHBAR16(0x62c) & ~0x1f80) | (reg16 << 7);
700
701 reg16 = (s->selected_timings.tRCD << 12) | (4 << 8) | (ta2 << 4) | ta4;
702 MCHBAR16(0x256) = reg16;
703
704 reg32 = (s->selected_timings.tRCD << 17) |
705 ((wl + 4 + s->selected_timings.tWTR) << 12) |
706 (ta3 << 8) | (4 << 4) | ta1;
707 MCHBAR32(0x258) = reg32;
708
709 reg16 = ((s->selected_timings.tRP + trp) << 9) |
710 s->selected_timings.tRFC;
711 MCHBAR8(0x25b) = (u8) reg16;
712 MCHBAR8(0x25c) = (u8) (reg16 >> 8);
713
714 MCHBAR16(0x260) = (MCHBAR16(0x260) & ~0x3fe) | (100 << 1);
715 MCHBAR8(0x25d) = (MCHBAR8(0x25d) & ~0x3f) | s->selected_timings.tRAS;
716 MCHBAR16(0x244) = 0x2310;
717
718 MCHBAR8(0x246) = (MCHBAR8(0x246) & ~0x1f) | 1;
719
720 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
721 reg32 = 3000;
722 } else {
723 reg32 = 2500;
724 }
725 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
726 reg2 = 6000;
727 } else {
728 reg2 = 5000;
729 }
730 reg16 = (u16)((((s->selected_timings.CAS + 7)*(reg32)) / reg2) << 8);
731 MCHBAR16(0x248) = (MCHBAR16(0x248) & ~0x1f00) | reg16;
732
733 flag = 0;
734 if (wl > 2) {
735 flag = 1;
736 }
737 reg16 = (u8) (wl - 1 - flag);
738 reg16 |= reg16 << 4;
739 reg16 |= flag << 8;
740 MCHBAR16(0x24d) = (MCHBAR16(0x24d) & ~0x1ff) | reg16;
741
742 MCHBAR16(0x25e) = 0x1585;
743 MCHBAR8(0x265) = MCHBAR8(0x265) & ~0x1f;
744 MCHBAR16(0x265) = (MCHBAR16(0x265) & ~0x3f00) |
745 ((s->selected_timings.CAS + 9) << 8);
746
747 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
748 reg16 = 0x514;
749 reg32 = 0xa28;
750 } else {
751 reg16 = 0x618;
752 reg32 = 0xc30;
753 }
754 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~0xfffff00) |
755 (0x3f << 22) | (reg32 << 8);
756 MCHBAR8(0x26c) = 0x00;
757 MCHBAR16(0x2b8) = (MCHBAR16(0x2b8) & 0xc000) | reg16;
758 MCHBAR8(0x274) = MCHBAR8(0x274) | 1;
759
760 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0x7f000000) | (0xb << 25);
761 i = s->selected_timings.mem_clock;
762 j = s->selected_timings.fsb_clock;
763 if (i > j) {
764 MCHBAR32(0x248) = MCHBAR32(0x248) | (1 << 24);
765 }
766
767 MCHBAR8(0x24c) = MCHBAR8(0x24c) & ~0x3;
768 MCHBAR16(0x24d) = (MCHBAR16(0x24d) & ~0x7c00) | ((wl + 10) << 10);
769 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x70e0000) | (3 << 24) | (3 << 17);
770 reg16 = 0x15 << 6;
771 reg16 |= 0x1f;
772 reg16 |= (0x6 << 12);
773 MCHBAR16(0x26d) = (MCHBAR16(0x26d) & ~0x7fff) | reg16;
774
775 reg32 = (0x6 << 27) | (1 << 25);
776 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~0x30000000) | ((u32)(reg32 << 8));
777 MCHBAR8(0x26c) = (MCHBAR8(0x26c) & ~0xfa) | ((u8)(reg32 >> 24));
778 MCHBAR8(0x271) = MCHBAR8(0x271) & ~(1 << 7);
779 MCHBAR8(0x274) = MCHBAR8(0x274) & ~0x6;
Stefan Reinauer66fbeae2016-05-06 13:48:39 -0700780 reg32 = (u32) (((6 & 0x03) << 30) | (4 << 25) | (1 << 20) | (8 << 15) |
Damien Zammit003d15c2015-11-20 17:17:51 +1100781 (6 << 10) | (4 << 5) | 1);
782 MCHBAR32(0x278) = reg32;
783
784 MCHBAR16(0x27c) = (MCHBAR16(0x27c) & ~0x1ff) | (8 << 3) | (6 >> 2);
785 MCHBAR16(0x125) = MCHBAR16(0x125) | 0x1c00 | (0x1f << 5);
786 MCHBAR8(0x127) = (MCHBAR8(0x127) & ~0xff) | 0x40;
787 MCHBAR8(0x128) = (MCHBAR8(0x128) & ~0x7) | 0x5;
788 MCHBAR8(0x129) = MCHBAR8(0x129) | 0x1f;
789 reg8 = 3 << 6;
790 reg8 |= (s->dt0mode << 4);
791 reg8 |= 0x0c;
792 MCHBAR8(0x12f) = (MCHBAR8(0x12f) & ~0xdf) | reg8;
793 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0x2;
794 MCHBAR8(0x228) = (MCHBAR8(0x228) & ~0x7) | 0x2;
795 MCHBAR16(0x241) = (MCHBAR16(0x241) & ~0x3fc) | (4 << 2);
796 reg32 = (2 << 29) | (1 << 28) | (1 << 23);
797 MCHBAR32(0x120) = (MCHBAR32(0x120) & ~0xffb00000) | reg32;
798
799 reg8 = (u8) ((MCHBAR16(0x252) & 0xe000) >> 13);
800 reg8 |= (u8) ((MCHBAR16(0x254) & 1) << 3);
801 MCHBAR8(0x12d) = (MCHBAR8(0x12d) & ~0xf0) | (reg8 << 4);
802 reg8 = (u8) ((MCHBAR32(0x258) & 0xf0000) >> 17);
803 MCHBAR8(0x12d) = (MCHBAR8(0x12d) & ~0xf) | reg8;
804 MCHBAR8(0x12e) = MCHBAR8(0x12e) & ~0xfc;
805 MCHBAR8(0x12e) = MCHBAR8(0x12e) & ~0x3;
806 MCHBAR8(0x12f) = MCHBAR8(0x12f) & ~0x3;
807 MCHBAR8(0x241) = MCHBAR8(0x241) | 1;
808 MCHBAR16(0x1b6) = MCHBAR16(0x1b6) | (1 << 9);
809 for (i = 0; i < 8; i++) {
810 MCHBAR32(0x540 + i*4) = (MCHBAR32(0x540 + i*4) & ~0x3f3f3f3f) |
811 0x0c0c0c0c;
812 }
813 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) |
814 ((s->selected_timings.CAS + 1) << 16);
815 for (i = 0; i < 8; i++) {
816 MCHBAR8(0x560 + i*4) = MCHBAR8(0x560 + i*4) & ~0x3f;
817 MCHBAR16(0x58c) = MCHBAR16(0x58c) & ((u16) (~(3 << (i*2))));
818 MCHBAR16(0x588) = MCHBAR16(0x588) & ((u16) (~(3 << (i*2))));
819 MCHBAR16(0x5fa) = MCHBAR16(0x5fa) & ((u16) (~(3 << (i*2))));
820 }
821 MCHBAR8(0x5f0) = MCHBAR8(0x5f0) & ~0x1;
822 MCHBAR8(0x5f0) = MCHBAR8(0x5f0) | 0x2;
823 MCHBAR8(0x5f0) = MCHBAR8(0x5f0) | 0x4;
824 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) | 0xc0400;
825 MCHBAR32(0x594) = MCHBAR32(0x594) | (1 << 31);
826}
827
Arthur Heymans6bf13012017-06-10 12:03:27 +0200828static void sdram_p_clkset0(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100829{
830 MCHBAR16(0x5a0) = (MCHBAR16(0x5a0) & ~0xc440) |
831 (pll->clkdelay[f][i] << 14) |
832 (pll->dben[f][i] << 10) |
833 (pll->dbsel[f][i] << 6);
834 MCHBAR8(0x581) = (MCHBAR8(0x581) & ~0x3f) | pll->pi[f][i];
835}
836
Arthur Heymans6bf13012017-06-10 12:03:27 +0200837static void sdram_p_clkset1(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100838{
839 MCHBAR16(0x5a0) = (MCHBAR16(0x5a0) & ~0x30880) |
840 (pll->clkdelay[f][i] << 16) |
841 (pll->dben[f][i] << 11) |
842 (pll->dbsel[f][i] << 7);
843 MCHBAR8(0x582) = (MCHBAR8(0x582) & ~0x3f) | pll->pi[f][i];
844}
845
Arthur Heymans6bf13012017-06-10 12:03:27 +0200846static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100847{
848 u8 reg8;
849 reg8 = pll->dbsel[f][i] << 5;
850 reg8 |= pll->dben[f][i] << 6;
851 MCHBAR8(0x594) = (MCHBAR8(0x594) & ~0x60) | reg8;
852
853 reg8 = pll->clkdelay[f][i] << 4;
854 MCHBAR8(0x598) = (MCHBAR8(0x598) & ~0x30) | reg8;
855
856 reg8 = pll->pi[f][i];
857 MCHBAR8(0x580) = (MCHBAR8(0x580) & ~0x3f) | reg8;
858 MCHBAR8(0x583) = (MCHBAR8(0x583) & ~0x3f) | reg8;
859}
860
Arthur Heymans6bf13012017-06-10 12:03:27 +0200861static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100862{
863 u8 reg8;
864 u32 reg32;
865 reg32 = ((u32) pll->dbsel[f][i]) << 20;
866 reg32 |= ((u32) pll->dben[f][i]) << 21;
867 reg32 |= ((u32) pll->dbsel[f][i]) << 22;
868 reg32 |= ((u32) pll->dben[f][i]) << 23;
869 reg32 |= ((u32) pll->clkdelay[f][i]) << 24;
870 reg32 |= ((u32) pll->clkdelay[f][i]) << 27;
871 MCHBAR32(0x59c) = (MCHBAR32(0x59c) & ~0x1bf0000) | reg32;
872
873 reg8 = pll->pi[f][i];
874 MCHBAR8(0x584) = (MCHBAR8(0x584) & ~0x3f) | reg8;
875 MCHBAR8(0x585) = (MCHBAR8(0x585) & ~0x3f) | reg8;
876
877 reg32 = ((u32) pll->dbsel[f][i]) << 12;
878 reg32 |= ((u32) pll->dben[f][i]) << 13;
879 reg32 |= ((u32) pll->dbsel[f][i]) << 8;
880 reg32 |= ((u32) pll->dben[f][i]) << 9;
881 reg32 |= ((u32) pll->clkdelay[f][i]) << 14;
882 reg32 |= ((u32) pll->clkdelay[f][i]) << 10;
883 MCHBAR32(0x598) = (MCHBAR32(0x598) & ~0xff00) | reg32;
884
885 reg8 = pll->pi[f][i];
886 MCHBAR8(0x586) = (MCHBAR8(0x586) & ~0x3f) | reg8;
887 MCHBAR8(0x587) = (MCHBAR8(0x587) & ~0x3f) | reg8;
888}
889
890static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
891{
892 u8 rank, dqs, reg8, j;
893 u32 reg32;
894
895 j = clk - 40;
896 reg8 = 0;
897 reg32 = 0;
898 rank = j % 4;
899 dqs = j / 4;
900
901 reg32 |= ((u32) pll->dben[f][clk]) << (dqs + 9);
902 reg32 |= ((u32) pll->dbsel[f][clk]) << dqs;
903 MCHBAR32(0x5b4+rank*4) = (MCHBAR32(0x5b4+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200904 ~((1 << (dqs+9))|(1 << dqs))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100905
906 reg32 = ((u32) pll->clkdelay[f][clk]) << ((dqs*2) + 16);
907 MCHBAR32(0x5c8+rank*4) = (MCHBAR32(0x5c8+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200908 ~((1 << (dqs*2 + 17))|(1 << (dqs*2 + 16)))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100909
910 reg8 = pll->pi[f][clk];
911 MCHBAR8(0x520+j) = (MCHBAR8(0x520+j) & ~0x3f) | reg8;
912}
913
914
915static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
916{
917 u8 rank, dq, reg8, j;
918 u32 reg32;
919
920 j = clk - 8;
921 reg8 = 0;
922 reg32 = 0;
923 rank = j % 4;
924 dq = j / 4;
925
926 reg32 |= ((u32) pll->dben[f][clk]) << (dq + 9);
927 reg32 |= ((u32) pll->dbsel[f][clk]) << dq;
928 MCHBAR32(0x5a4+rank*4) = (MCHBAR32(0x5a4+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200929 ~((1 << (dq+9))|(1 << dq))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100930
931 reg32 = ((u32) pll->clkdelay[f][clk]) << (dq*2);
932 MCHBAR32(0x5c8+rank*4) = (MCHBAR32(0x5c8+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200933 ~((1 << (dq*2 + 1))|(1 << (dq*2)))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100934
935 reg8 = pll->pi[f][clk];
936 MCHBAR8(0x500+j) = (MCHBAR8(0x500+j) & ~0x3f) | reg8;
937}
938
939static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
940{
941 struct pllparam pll = {
942 .pi = {
943 { // 667
944 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
945 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
946 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
947 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
948 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
949 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3
950 },
951 { // 800
952 53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
953 34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
954 47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
955 47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
956 2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
957 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15
958 }},
959
960 .dben = {
961 { // 667
962 0,0,1,1,1,1,1,1,1,1,1,1,
963 1,1,1,1,0,0,0,0,0,0,0,0,
964 0,0,0,0,0,0,0,0,0,0,0,0,
965 1,1,1,1,0,0,0,0,0,0,0,0,
966 0,0,0,0,0,0,0,0,0,0,0,0,
967 0,0,0,0,0,0,0,0,0,0,0,0
968 },
969 { // 800
970 1,1,1,1,1,1,1,1,0,0,0,0,
971 0,0,0,0,0,0,0,0,0,0,0,0,
972 0,0,0,0,0,0,0,0,0,0,0,0,
973 0,0,0,0,1,1,1,1,1,1,1,1,
974 1,1,1,1,1,1,1,1,0,0,0,0,
975 1,1,1,1,0,0,0,0,0,0,0,0
976 }},
977
978 .dbsel = {
979 { // 667
980 0,0,1,1,1,1,1,1,1,1,1,1,
981 1,1,1,1,0,0,0,0,0,0,0,0,
982 0,0,0,0,0,0,0,0,0,0,0,0,
983 1,1,1,1,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,0,0,0,0,0,0,0,0
986 },
987 { // 800
988 0,0,1,1,1,1,1,1,0,0,0,0,
989 0,0,0,0,0,0,0,0,0,0,0,0,
990 0,0,0,0,0,0,0,0,0,0,0,0,
991 0,0,0,0,0,0,0,0,1,1,1,1,
992 1,1,1,1,1,1,1,1,0,0,0,0,
993 1,1,1,1,0,0,0,0,0,0,0,0
994 }},
995
996 .clkdelay = {
997 { // 667
998 0,0,1,1,0,0,0,0,1,1,1,1,
999 1,1,1,1,1,1,1,1,1,1,1,1,
1000 1,1,1,1,1,1,1,1,1,1,1,1,
1001 1,1,1,1,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,0,0,0,0
1004 },
1005 { // 800
1006 0,0,0,0,0,0,0,0,1,1,1,1,
1007 1,1,1,1,1,1,1,1,1,1,1,1,
1008 1,1,1,1,1,1,1,1,1,1,1,1,
1009 1,1,1,1,0,0,0,0,1,1,1,1,
1010 1,1,1,1,1,1,1,1,1,1,1,1,
1011 1,1,1,1,1,1,1,1,1,1,1,1
1012 }}
1013 };
1014
1015 u8 i, f;
1016 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1017 f = 0;
1018 } else {
1019 f = 1;
1020 }
1021 for (i = 0; i < 72; i++) {
1022 pll.pi[f][i] += pidelay;
1023 }
1024
1025 MCHBAR8(0x1a4) = MCHBAR8(0x1a4) & ~(1 << 7);
1026 MCHBAR16(0x190) = (MCHBAR16(0x190) & (u16) ~(0x3fff)) | 0x1fff;
1027
1028 sdram_p_clkset0(&pll, f, 0);
1029 sdram_p_clkset1(&pll, f, 1);
1030 sdram_p_cmd(&pll, f, 2);
1031 sdram_p_ctrl(&pll, f, 4);
1032 for (i = 0; i < 32; i++) {
1033 sdram_p_dqs(&pll, f, i+40);
1034 }
1035 for (i = 0; i < 32; i++) {
1036 sdram_p_dq(&pll, f, i+8);
1037 }
1038}
1039
1040static void sdram_calibratehwpll(struct sysinfo *s)
1041{
1042 u8 reg8;
1043
1044 s->async = 0;
1045 reg8 = 0;
1046 MCHBAR16(0x180) = MCHBAR16(0x180) | (1 << 15);
1047 MCHBAR8(0x180) = MCHBAR8(0x180) & ~(1 << 7);
1048 MCHBAR8(0x180) = MCHBAR8(0x180) | (1 << 3);
1049 MCHBAR8(0x180) = MCHBAR8(0x180) | (1 << 2);
1050
1051 MCHBAR8(0x180) = MCHBAR8(0x180) | (1 << 7);
1052 while ((MCHBAR8(0x180) & (1 << 2)) == 0);
1053
1054 reg8 = (MCHBAR8(0x180) & (1 << 3)) >> 3;
1055 if (reg8 != 0) {
1056 s->async = 1;
1057 }
1058}
1059
1060static void sdram_dlltiming(struct sysinfo *s)
1061{
Elyes HAOUAS66b462d2019-01-02 21:11:32 +01001062 u8 reg8, i;
Damien Zammit003d15c2015-11-20 17:17:51 +11001063 u16 reg16;
1064 u32 reg32;
1065
1066 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1067 reg32 = 0x8014227;
1068 } else {
1069 reg32 = 0x14221;
1070 }
1071 MCHBAR32(0x19c) = (MCHBAR32(0x19c) & ~0xfffffff) | reg32;
1072 MCHBAR32(0x19c) = MCHBAR32(0x19c) | (1 << 23);
1073 MCHBAR32(0x19c) = MCHBAR32(0x19c) | (1 << 15);
1074 MCHBAR32(0x19c) = MCHBAR32(0x19c) & ~(1 << 15);
1075
1076 if (s->nodll) {
1077 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 0);
1078 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 2);
1079 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 4);
1080 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 8);
1081 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 10);
1082 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 12);
1083 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 14);
1084 } else {
1085 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 0);
1086 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 2);
1087 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 4);
1088 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 8);
1089 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 10);
1090 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 12);
1091 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 14);
1092 }
1093
1094 if (s->nodll) {
1095 MCHBAR8(0x1c8) = (MCHBAR8(0x1c8) & ~0x3f) | 0x7;
1096 } else {
1097 MCHBAR8(0x1c8) = (MCHBAR8(0x1c8) & ~0x3f);
1098 }
1099
1100 sdram_calibratepll(s, 0); // XXX check
1101
1102 MCHBAR16(0x5f0) = MCHBAR16(0x5f0) | (1 << 11);
1103 MCHBAR16(0x5f0) = MCHBAR16(0x5f0) | (1 << 12);
1104
1105 for (i = 0; i < 8; i++) {
1106 MCHBAR16(0x5f0) = MCHBAR16(0x5f0) | ((1 << 10) >> i);
1107 }
1108 MCHBAR8(0x2c14) = MCHBAR8(0x2c14) | 1;
1109 MCHBAR16(0x182) = 0x5005;
1110 MCHBAR16(0x18a) = (MCHBAR16(0x18a) & ~0x1f1f) | 0x51a;
1111 MCHBAR16(0x2c00) = (MCHBAR16(0x2c00) & ~0xbf3f) | 0x9010;
1112
1113 if (s->nodll) {
1114 MCHBAR8(0x18e) = (MCHBAR8(0x18e) & ~0x7f) | 0x6b;
1115 } else {
1116 MCHBAR8(0x18e) = (MCHBAR8(0x18e) & ~0x7f) | 0x55;
1117 sdram_calibratehwpll(s);
1118 }
Damien Zammit003d15c2015-11-20 17:17:51 +11001119
1120 MCHBAR32(0x248) = MCHBAR32(0x248) & ~(1 << 22);
1121 MCHBAR8(0x5d9) = MCHBAR8(0x5d9) & ~0x2;
1122 MCHBAR8(0x189) = MCHBAR8(0x189) | 0xc0;
1123 MCHBAR8(0x189) = MCHBAR8(0x189) & ~(1 << 5);
1124 MCHBAR8(0x189) = (MCHBAR8(0x189) & ~0xc0) | (1 << 6);
1125 MCHBAR8(0x188) = (MCHBAR8(0x188) & ~0x3f) | 0x1a;
1126 MCHBAR8(0x188) = MCHBAR8(0x188) | 1;
1127
1128 MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 1;
1129 MCHBAR32(0x1a0) = 0x551803;
Jacob Garberd10680b2019-06-11 14:13:04 -06001130
Damien Zammit003d15c2015-11-20 17:17:51 +11001131 reg8 = 0x00; //switch all clocks on anyway
1132
1133 MCHBAR32(0x5a0) = (MCHBAR32(0x5a0) & ~0x3f000000) | (reg8 << 24);
1134 MCHBAR8(0x594) = MCHBAR8(0x594) & ~1;
1135 reg16 = 0;
1136 if (!rank_is_populated(s->dimms, 0, 0)) {
1137 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
1138 }
1139 if (!rank_is_populated(s->dimms, 0, 1)) {
1140 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
1141 }
1142 if (!rank_is_populated(s->dimms, 0, 2)) {
1143 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1144 }
1145 if (!rank_is_populated(s->dimms, 0, 3)) {
1146 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1147 }
1148 MCHBAR16(0x59c) = MCHBAR16(0x59c) | reg16;
1149}
1150
1151static void sdram_rcomp(struct sysinfo *s)
1152{
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02001153 u8 i, j, reg8, rcompp, rcompn, srup, srun;
Damien Zammit003d15c2015-11-20 17:17:51 +11001154 u16 reg16;
1155 u32 reg32, rcomp1, rcomp2;
1156
Arthur Heymans6bf13012017-06-10 12:03:27 +02001157 static const u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0 };
1158 static const u8 rcompslew = 0xa;
1159 static const u8 rcompstr[7] = { 0x66, 0, 0xaa, 0x55, 0x55, 0x77, 0x77 };
1160 static const u16 rcompscomp[7] = { 0xa22a, 0, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a };
1161 static const u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1 };
1162 static const u16 rcompctl[7] = { 0x31c, 0, 0x374, 0x3a2, 0x3d0, 0x3fe, 0x42c };
1163 static const u16 rcompf[7] = { 0x1114, 0, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a };
Damien Zammit003d15c2015-11-20 17:17:51 +11001164
1165 // NC-NC x16SS x16DS x16SS2 x16DS2 x8DS, x8DS2
Arthur Heymans6bf13012017-06-10 12:03:27 +02001166 static const u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa,
1167 0xaa , 0x55, 0xaa};
1168 static const u16 rcompscomp2[7] = { 0x0000, 0xe22e, 0xe22e, 0xe22e,
1169 0x8228 , 0xe22e, 0x8228 };
1170 static const u8 rcompdelay2[7] = { 0, 0, 0, 0, 2 , 0, 2};
Damien Zammit003d15c2015-11-20 17:17:51 +11001171
Arthur Heymans6bf13012017-06-10 12:03:27 +02001172 static const u8 rcomplut[64][12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001173 { 9, 9,11,11, 2, 2, 5,5, 6, 6,5, 5},
1174 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1175 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1176 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1177 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1178 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1179 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1180 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1181 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1182 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1183 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1184 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1185 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1186 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1187 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1188 { 10,9,12, 11, 2, 2, 5,5, 6, 6,5, 5},
1189 { 10,9,12, 11, 2, 2, 6,5, 7, 6,6, 5},
1190 { 10,10,12, 12, 2, 2, 6,5, 7, 6,6, 5},
1191 { 10,10,12, 12, 2, 2, 6,6, 7, 7,6, 6},
1192 { 10,10,12, 12, 3, 2, 6,6, 7, 7,6, 6},
1193 { 10,10,12, 12, 3, 2, 6,6, 7, 7,6, 6},
1194 { 10,10,12, 12, 3, 2, 6,6, 7, 7,6, 6},
1195 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1196 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1197 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1198 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1199 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1200 { 11,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1201 { 11,10,14, 13, 3, 3, 6,6, 7, 7,6, 6},
1202 { 12,10,14, 13, 3, 3, 6,6, 7, 7,6, 6},
1203 { 12,12,14, 13, 3, 3, 7,6, 7, 7,7, 6},
1204 { 13,12,16, 15, 3, 3, 7,6, 8, 7,7, 6},
1205 { 13,14,16, 15, 4, 3, 7,7, 8, 8,7, 7},
1206 { 14,14,16, 17, 4, 3, 7,7, 8, 8,7, 7},
1207 { 14,16,18, 17, 4, 4, 8,7, 8, 8,8, 7},
1208 { 15,16,18, 19, 4, 4, 8,7, 9, 8,8, 7},
1209 { 15,18,18, 19, 4, 4, 8,8, 9, 9,8, 8},
1210 { 16,18,20, 21, 4, 4, 8,8, 9, 9,8, 8},
1211 { 16,19,20, 21, 5, 4, 9,8, 10, 9,9, 8},
1212 { 16,19,20, 23, 5, 5, 9,9, 10, 10,9, 9},
1213 { 17,19,22, 23, 5, 5, 9,9, 10, 10,9, 9},
1214 { 17,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1215 { 17,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1216 { 18,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1217 { 18,21,24, 25, 5, 5, 9,9, 11, 10,9, 9},
1218 { 19,21,24, 27, 5, 5, 9, 9, 11, 11,9, 9},
1219 { 19,22,24, 27, 5, 5, 10,9, 11, 11,10, 9},
1220 { 20,22,24, 27, 6, 5, 10,10, 11, 11,10, 10},
1221 { 20,23,26, 27, 6, 6, 10,10, 12, 12,10, 10},
1222 { 20,23,26, 29, 6, 6, 10,10, 12, 12,10, 10},
1223 { 21,24,26, 29, 6, 6, 10,10, 12, 12,10, 10},
1224 { 21,24,26, 29, 6, 6, 11,10, 12, 13,11, 10},
1225 { 22,25,28, 29, 6, 6, 11,11, 13, 13,11, 11},
1226 { 22,25,28, 31, 6, 6, 11,11, 13, 13,11, 11},
1227 { 22,26,28, 31, 6, 6, 11,11, 13, 14,11, 11},
1228 { 23,26,30, 31, 7, 6, 12,11, 14, 14,12, 11},
1229 { 23,27,30, 33, 7, 7, 12,12, 14, 14,12, 12},
1230 { 23,27,30, 33, 7, 7, 12,12, 14, 15,12, 12},
1231 { 24,28,32, 33, 7, 7, 12,12, 15, 15,12, 12},
1232 { 24,28,32, 33, 7, 7, 12,12, 15, 16,12, 12},
1233 { 24,29,32, 35, 7, 7, 12,12, 15, 16,12, 12},
1234 { 25,29,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1235 { 25,30,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1236 { 25,30,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1237 };
1238
1239 srup = 0;
1240 srun = 0;
1241
1242 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001243 rcomp1 = 0x00050431;
1244 } else {
Damien Zammit003d15c2015-11-20 17:17:51 +11001245 rcomp1 = 0x00050542;
1246 }
1247 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
1248 rcomp2 = 0x14C42827;
1249 } else {
1250 rcomp2 = 0x19042827;
1251 }
1252
1253 for (i = 0; i < 7; i++) {
1254 if (i == 1)
1255 continue;
1256 reg8 = rcompupdate[i];
1257 MCHBAR8(rcompctl[i]) = (MCHBAR8(rcompctl[i]) & ~0x1) | reg8;
1258 MCHBAR8(rcompctl[i]) = MCHBAR8(rcompctl[i]) & ~0x2;
1259 reg16 = (u16) rcompslew;
1260 MCHBAR16(rcompctl[i]) = (MCHBAR16(rcompctl[i]) & ~0xf000) |
1261 (reg16 << 12);
1262 MCHBAR8(rcompctl[i]+4) = rcompstr[i];
1263 MCHBAR16(rcompctl[i]+0xe) = rcompscomp[i];
1264 MCHBAR8(rcompctl[i]+0x14) = (MCHBAR8(rcompctl[i]+0x14) & ~0x3) |
1265 rcompdelay[i];
1266 if (i == 2) {
1267 reg16 = (u16) rcompslew;
1268 MCHBAR16(rcompctl[i]) = (MCHBAR16(rcompctl[i]) &
1269 ~0xf000) | (reg16 << 12);
1270 MCHBAR8(rcompctl[i]+4) = rcompstr2[s->dimm_config[0]];
1271 MCHBAR16(rcompctl[i]+0xe) = rcompscomp2[s->dimm_config[0]];
1272 MCHBAR8(rcompctl[i]+0x14) = (MCHBAR8(rcompctl[i]+0x14) &
1273 ~0x3) | rcompdelay2[s->dimm_config[0]];
1274 }
1275
1276 MCHBAR16(rcompctl[i]+0x16) = MCHBAR16(rcompctl[i]+0x16) & ~0x7f7f;
1277 MCHBAR16(rcompctl[i]+0x18) = MCHBAR16(rcompctl[i]+0x18) & ~0x3f3f;
1278 MCHBAR16(rcompctl[i]+0x1a) = MCHBAR16(rcompctl[i]+0x1a) & ~0x3f3f;
1279 MCHBAR16(rcompctl[i]+0x1c) = MCHBAR16(rcompctl[i]+0x1c) & ~0x3f3f;
1280 MCHBAR16(rcompctl[i]+0x1e) = MCHBAR16(rcompctl[i]+0x1e) & ~0x3f3f;
1281 }
1282
1283 MCHBAR8(0x45a) = (MCHBAR8(0x45a) & ~0x3f) | 0x36;
1284 MCHBAR8(0x462) = (MCHBAR8(0x462) & ~0x3f) | 0x36;
1285
1286 for (i = 0; i < 7; i++) {
1287 if (i == 1)
1288 continue;
1289 MCHBAR8(rcompctl[i]) = MCHBAR8(rcompctl[i]) & ~0x60;
1290 MCHBAR16(rcompctl[i]+2) = MCHBAR16(rcompctl[i]+2) & ~0x706;
1291 MCHBAR16(rcompctl[i]+0xa) = MCHBAR16(rcompctl[i]+0xa) & ~0x7f7f;
1292 MCHBAR16(rcompctl[i]+0x12) = MCHBAR16(rcompctl[i]+0x12) & ~0x3f3f;
1293 MCHBAR16(rcompctl[i]+0x24) = MCHBAR16(rcompctl[i]+0x24) & ~0x1f1f;
1294 MCHBAR8(rcompctl[i]+0x26) = MCHBAR8(rcompctl[i]+0x26) & ~0x1f;
1295 }
1296
1297 MCHBAR16(0x45a) = MCHBAR16(0x45a) & ~0xffc0;
1298 MCHBAR16(0x45c) = MCHBAR16(0x45c) & ~0xf;
1299 MCHBAR16(0x462) = MCHBAR16(0x462) & ~0xffc0;
1300 MCHBAR16(0x464) = MCHBAR16(0x464) & ~0xf;
1301
1302 for (i = 0; i < 7; i++) {
1303 if (i == 1)
1304 continue;
1305 MCHBAR16(rcompctl[i]+0x10) = rcompf[i];
1306 MCHBAR16(rcompctl[i]+0x20) = 0x1219;
1307 MCHBAR16(rcompctl[i]+0x22) = 0x000C;
1308 }
1309
1310 MCHBAR32(0x164) = (MCHBAR32(0x164) & ~0x1f1f1f) | 0x0c1219;
1311 MCHBAR16(0x4b0) = (MCHBAR16(0x4b0) & ~0x1f00) | 0x1200;
1312 MCHBAR8(0x4b0) = (MCHBAR8(0x4b0) & ~0x1f) | 0x12;
1313 MCHBAR32(0x138) = 0x007C9007;
1314 MCHBAR32(0x16c) = rcomp1;
1315 MCHBAR16(0x17a) = 0x1f7f;
1316 MCHBAR32(0x134) = rcomp2;
1317 MCHBAR16(0x170) = (MCHBAR16(0x170) & ~0xf) | 1;
1318 MCHBAR16(0x178) = 0x134;
1319 MCHBAR32(0x130) = 0x4C293600;
1320 MCHBAR8(0x133) = (MCHBAR8(0x133) & ~0x44) | (1 << 6) | (1 << 2);
1321 MCHBAR16(0x4b0) = MCHBAR16(0x4b0) & ~(1 << 13);
1322 MCHBAR8(0x4b0) = MCHBAR8(0x4b0) & ~(1 << 5);
1323
1324 for (i = 0; i < 7; i++) {
1325 if (i == 1)
1326 continue;
1327 MCHBAR8(rcompctl[i]+2) = MCHBAR8(rcompctl[i]) & ~0x71;
1328 }
1329
1330 if ((MCHBAR32(0x130) & (1 << 30)) == 0) {
1331 MCHBAR8(0x130) = MCHBAR8(0x130) | 0x1;
1332 while ((MCHBAR8(0x130) & 0x1) != 0);
1333
1334 reg32 = MCHBAR32(0x13c);
1335 rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1336 rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1337
1338 for (i = 0; i < 7; i++) {
1339 if (i == 1)
1340 continue;
1341 srup = (MCHBAR8(rcompctl[i]+1) & 0xc0) >> 6;
1342 srun = (MCHBAR8(rcompctl[i]+1) & 0x30) >> 4;
1343 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
1344 MCHBAR16(rcompctl[i]+0x16) = (MCHBAR16(rcompctl[i]+0x16)
1345 & ~0x7f00) | reg16;
1346 reg16 = (u16)(rcompn - (1 << (srun + 1)));
1347 MCHBAR8(rcompctl[i]+0x16) = (MCHBAR8(rcompctl[i]+0x16) &
1348 ~0x7f) | (u8)reg16;
1349 }
1350
1351 reg8 = rcompp - (1 << (srup + 1));
1352 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1353 MCHBAR8(rcompctl[0]+0x18+i) =
1354 (MCHBAR8(rcompctl[0]+0x18+i) & ~0x3f) |
1355 rcomplut[j][0];
1356 }
1357
1358 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1359 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1360 MCHBAR8(rcompctl[2]+0x18+i) =
1361 (MCHBAR8(rcompctl[2]+0x18+i) & ~0x3f) |
1362 rcomplut[j][10];
1363 }
1364 }
1365
1366 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1367 MCHBAR8(rcompctl[3]+0x18+i) =
1368 (MCHBAR8(rcompctl[3]+0x18+i) & ~0x3f) |
1369 rcomplut[j][6];
1370 MCHBAR8(rcompctl[4]+0x18+i) =
1371 (MCHBAR8(rcompctl[4]+0x18+i) & ~0x3f) |
1372 rcomplut[j][6];
1373 }
1374
1375 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1376 MCHBAR8(rcompctl[5]+0x18+i) =
1377 (MCHBAR8(rcompctl[5]+0x18+i) & ~0x3f) |
1378 rcomplut[j][8];
1379 MCHBAR8(rcompctl[6]+0x18+i) =
1380 (MCHBAR8(rcompctl[6]+0x18+i) & ~0x3f) |
1381 rcomplut[j][8];
1382 }
1383
1384 reg8 = rcompn - (1 << (srun + 1));
1385 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1386 MCHBAR8(rcompctl[0]+0x1c+i) =
1387 (MCHBAR8(rcompctl[0]+0x1c+i) & ~0x3f) |
1388 rcomplut[j][1];
1389 }
1390
1391 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1392 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1393 MCHBAR8(rcompctl[2]+0x1c+i) =
1394 (MCHBAR8(rcompctl[2]+0x1c+i) & ~0x3f) |
1395 rcomplut[j][11];
1396 }
1397 }
1398
1399 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1400 MCHBAR8(rcompctl[3]+0x1c+i) =
1401 (MCHBAR8(rcompctl[3]+0x1c+i) & ~0x3f) |
1402 rcomplut[j][7];
1403 MCHBAR8(rcompctl[4]+0x1c+i) =
1404 (MCHBAR8(rcompctl[4]+0x1c+i) & ~0x3f) |
1405 rcomplut[j][7];
1406 }
1407
1408 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1409 MCHBAR8(rcompctl[5]+0x1c+i) =
1410 (MCHBAR8(rcompctl[5]+0x1c+i) & ~0x3f) |
1411 rcomplut[j][9];
1412 MCHBAR8(rcompctl[6]+0x1c+i) =
1413 (MCHBAR8(rcompctl[6]+0x1c+i) & ~0x3f) |
1414 rcomplut[j][9];
1415 }
1416 }
1417 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1418}
1419
1420static void sdram_odt(struct sysinfo *s)
1421{
1422 u8 rankindex = 0;
1423
Arthur Heymans6bf13012017-06-10 12:03:27 +02001424 static const u16 odt294[16] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001425 0x0000, 0x0000, 0x0000, 0x0000,
1426 0x0044, 0x1111, 0x0000, 0x1111,
1427 0x0000, 0x0000, 0x0000, 0x0000,
1428 0x0044, 0x1111, 0x0000, 0x1111
1429 };
Arthur Heymans6bf13012017-06-10 12:03:27 +02001430 static const u16 odt298[16] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001431 0x0000, 0x0011, 0x0000, 0x0011,
1432 0x0000, 0x4444, 0x0000, 0x4444,
1433 0x0000, 0x0000, 0x0000, 0x0000,
1434 0x0000, 0x4444, 0x0000, 0x4444
1435 };
1436
1437 switch (s->dimms[0].ranks) {
1438 case 0:
1439 if (s->dimms[1].ranks == 0) {
1440 rankindex = 0;
1441 } else if (s->dimms[1].ranks == 1) {
1442 rankindex = 4;
1443 } else if (s->dimms[1].ranks == 2) {
1444 rankindex = 12;
1445 }
1446 break;
1447 case 1:
1448 if (s->dimms[1].ranks == 0) {
1449 rankindex = 1;
1450 } else if (s->dimms[1].ranks == 1) {
1451 rankindex = 5;
1452 } else if (s->dimms[1].ranks == 2) {
1453 rankindex = 13;
1454 }
1455 break;
1456 case 2:
1457 if (s->dimms[1].ranks == 0) {
1458 rankindex = 3;
1459 } else if (s->dimms[1].ranks == 1) {
1460 rankindex = 7;
1461 } else if (s->dimms[1].ranks == 2) {
1462 rankindex = 15;
1463 }
1464 break;
1465 }
1466
1467 MCHBAR16(0x298) = odt298[rankindex];
1468 MCHBAR16(0x294) = odt294[rankindex];
1469}
1470
1471static void sdram_mmap(struct sysinfo *s)
1472{
Arthur Heymans6bf13012017-06-10 12:03:27 +02001473 static const u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000,
1474 0xc00001, 0xf00000};
1475 static const u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101,
1476 0x1010000, 0x1010101};
1477 static const u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1478 static const u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006,
1479 0x40002, 0x80006};
Damien Zammit003d15c2015-11-20 17:17:51 +11001480
Arthur Heymans6bf13012017-06-10 12:03:27 +02001481 static const u16 tolud[7] = {0x800, 0x800, 0x1000, 0x1000, 0x2000,
1482 0x1000, 0x2000};
1483 static const u16 tom[7] = {0x2, 0x2, 0x4, 0x4, 0x8, 0x4, 0x8};
1484 static const u16 touud[7] = {0x80, 0x80, 0x100, 0x100, 0x200, 0x100,
1485 0x200};
1486 static const u32 gbsm[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000,
1487 0x20000000, 0x10000000, 0x20000000};
1488 static const u32 bgsm[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000,
1489 0x20000000, 0x10000000, 0x20000000};
1490 static const u32 tsegmb[7] = {0x8000000, 0x8000000, 0x10000000,
1491 0x8000000, 0x20000000, 0x10000000,
1492 0x20000000};
Damien Zammit003d15c2015-11-20 17:17:51 +11001493
1494 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1495 if (s->dimms[0].sides > 1) {
1496 // 2R/NC
1497 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x300001;
1498 MCHBAR32(0x208) = 0x101;
1499 MCHBAR32(0x200) = 0x40002;
1500 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1501 } else {
1502 // 1R/NC
1503 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x100001;
1504 MCHBAR32(0x208) = 0x1;
1505 MCHBAR32(0x200) = 0x20002;
1506 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1507 }
1508 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
1509
1510 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x300001;
1511 MCHBAR32(0x208) = 0x101;
1512 MCHBAR32(0x200) = 0x40002;
1513 MCHBAR32(0x204) = 0x40004;
1514 } else {
1515 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | w260[s->dimm_config[0]];
1516 MCHBAR32(0x208) = w208[s->dimm_config[0]];
1517 MCHBAR32(0x200) = w200[s->dimm_config[0]];
1518 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1519 }
1520 pci_write_config16(PCI_DEV(0, 0, 0), 0xb0, tolud[s->dimm_config[0]]);
1521 pci_write_config16(PCI_DEV(0, 0, 0), 0xa0, tom[s->dimm_config[0]]);
1522 pci_write_config16(PCI_DEV(0, 0, 0), 0xa2, touud[s->dimm_config[0]]);
1523 pci_write_config32(PCI_DEV(0, 0, 0), 0xa4, gbsm[s->dimm_config[0]]);
1524 pci_write_config32(PCI_DEV(0, 0, 0), 0xa8, bgsm[s->dimm_config[0]]);
1525 pci_write_config32(PCI_DEV(0, 0, 0), 0xac, tsegmb[s->dimm_config[0]]);
1526}
1527
1528#if 1
1529static void hpet_udelay(u32 del)
1530{
1531 u32 start, finish, now;
1532
1533 del *= 15; /* now in usec */
1534
1535 start = HPET32(0xf0);
1536 finish = start + del;
1537 while (1) {
1538 now = HPET32(0xf0);
1539 if (finish > start) {
1540 if (now >= finish)
1541 break;
1542 } else {
1543 if ((now < start) && (now >= finish)) {
1544 break;
1545 }
1546 }
1547 }
1548}
1549#endif
1550
1551static u8 sdram_checkrcompoverride(void)
1552{
1553 u32 xcomp;
1554 u8 aa, bb, a, b, c, d;
1555
1556 xcomp = MCHBAR32(0x13c);
1557 a = (u8)((xcomp & 0x7f000000) >> 24);
1558 b = (u8)((xcomp & 0x7f0000) >> 16);
1559 c = (u8)((xcomp & 0x3f00) >> 8);
1560 d = (u8)(xcomp & 0x3f);
1561
1562 if (a > b) {
1563 aa = a - b;
1564 } else {
1565 aa = b - a;
1566 }
1567 if (c > d) {
1568 bb = c - d;
1569 } else {
1570 bb = d - c;
1571 }
1572 if ((aa > 18) || (bb > 7) ||
1573 (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
1574 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
1575 MCHBAR32(0x140) = 0x9718a729;
1576 return 1;
1577 }
1578 return 0;
1579}
1580
1581static void sdram_rcompupdate(struct sysinfo *s)
1582{
1583 u8 i, ok;
1584 u32 reg32a, reg32b;
1585
1586 ok = 0;
1587 MCHBAR8(0x170) = MCHBAR8(0x170) & ~(1 << 3);
1588 MCHBAR8(0x130) = MCHBAR8(0x130) & ~(1 << 7);
1589 for (i = 0; i < 3; i++) {
1590 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1591 hpet_udelay(1000);
1592 while ((MCHBAR8(0x130) & 0x1) != 0);
1593 ok |= sdram_checkrcompoverride();
1594 }
1595 if (!ok) {
1596 reg32a = MCHBAR32(0x13c);
1597 reg32b = (reg32a >> 16) & 0x0000ffff;
1598 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1599 reg32a |= (1 << 31) | (1 << 15);
1600 MCHBAR32(0x140) = reg32a;
1601 }
1602 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1603 hpet_udelay(1000);
1604 while ((MCHBAR8(0x130) & 0x1) != 0);
1605}
1606
1607static void __attribute__((noinline))
1608sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1609{
1610 u32 reg32;
1611
1612 reg32 = jval << 3;
1613 reg32 |= rank * 0x8000000;
1614 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | jmode;
1615 read32((void *)reg32);
1616 barrier();
1617 hpet_udelay(1); // 1us
1618}
1619
1620static void sdram_zqcl(struct sysinfo *s)
1621{
1622 if (s->boot_path == BOOT_PATH_RESUME) {
1623 MCHBAR32(0x260) = MCHBAR32(0x260) | (1 << 27);
1624 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0xe) | NORMAL_OP_CMD;
1625 MCHBAR8(0x271) = MCHBAR8(0x271) & ~0x30;
1626 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~((1 << 30) | (1 << 31))) |
1627 (1 << 30) | (1 << 31);
1628 }
1629}
1630
1631static void sdram_jedecinit(struct sysinfo *s)
1632{
1633 u8 r, i, ch;
1634 u16 reg16, mrs, rttnom;
1635 struct jedeclist {
1636 char debug[15];
1637 u8 cmd;
1638 u16 val;
1639 };
1640
Arthur Heymans6bf13012017-06-10 12:03:27 +02001641 static const struct jedeclist jedec[12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001642 { " NOP ", NOP_CMD, 0 },
1643 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1644 { " EMRS2 ", EMRS2_CMD, 0 },
1645 { " EMRS3 ", EMRS3_CMD, 0 },
1646 { " EMRS1 ", EMRS1_CMD, 0 },
1647 { " DLL RESET ", MRS_CMD, (1 << 8) },
1648 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1649 { " AUTOREFRESH", CBR_CMD, 0 },
1650 { " AUTOREFRESH", CBR_CMD, 0 },
1651 { " INITIALISE ", MRS_CMD, 0 },
1652 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1653 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1654 };
1655
1656 mrs = (s->selected_timings.CAS << 4) |
1657 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 1;
1658 rttnom = (1 << 2);
1659 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1660 rttnom |= (1 << 6);
1661 }
1662
1663 hpet_udelay(200); // 200us
1664 reg16 = 0;
1665 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1666 for (i = 0; i < 12; i++) {
1667 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1668 reg16 = jedec[i].val;
1669 switch (jedec[i].cmd) {
1670 case EMRS1_CMD:
1671 reg16 |= rttnom;
1672 break;
1673 case MRS_CMD:
1674 reg16 |= mrs;
1675 break;
1676 default:
1677 break;
1678 }
1679 sdram_jedec(s, r, jedec[i].cmd, reg16);
1680 PRINTK_DEBUG("done\n");
1681 }
1682 }
1683}
1684
1685static void sdram_misc(struct sysinfo *s)
1686{
1687 u32 reg32;
1688
1689 reg32 = 0;
1690 reg32 |= (0x4 << 13);
1691 reg32 |= (0x6 << 8);
1692 MCHBAR32(0x274) = (MCHBAR32(0x274) & ~0x3ff00) | reg32;
1693 MCHBAR8(0x274) = MCHBAR8(0x274) & ~(1 << 7);
1694 MCHBAR8(0x26c) = MCHBAR8(0x26c) | 1;
1695 if (s->boot_path != BOOT_PATH_RESUME) {
1696 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0xe) | NORMAL_OP_CMD;
1697 MCHBAR8(0x271) = MCHBAR8(0x271) & ~0x30;
1698 } else {
1699 sdram_zqcl(s);
1700 }
1701}
1702
1703static void sdram_checkreset(void)
1704{
1705 u8 pmcon2, pmcon3, reset;
1706
1707 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1708 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1709 pmcon3 &= ~0x2;
1710 if (pmcon2 & 0x80) {
1711 pmcon2 &= ~0x80;
1712 reset = 1;
1713 } else {
1714 pmcon2 |= 0x80;
1715 reset = 0;
1716 }
1717 if (pmcon2 & 0x4) {
1718 pmcon2 |= 0x4;
1719 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1720 pmcon3 |= (1 << 3);
1721 }
1722 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1723 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +02001724 if (reset)
1725 full_reset();
Damien Zammit003d15c2015-11-20 17:17:51 +11001726}
1727
1728static void sdram_dradrb(struct sysinfo *s)
1729{
1730 u8 i, reg8, ch, r;
1731 u32 reg32, ind, c0dra, c0drb, dra;
1732 u16 addr;
1733 i = 0;
Arthur Heymans6bf13012017-06-10 12:03:27 +02001734 static const u8 dratab[2][2][2][4] =
Damien Zammit003d15c2015-11-20 17:17:51 +11001735 {{
1736 {
1737 {0xff, 0xff, 0xff, 0xff},
1738 {0xff, 0x00, 0x02, 0xff}
1739 },
1740 {
1741 {0xff, 0x01, 0xff, 0xff},
1742 {0xff, 0x03, 0xff, 0x06}
1743 }
1744 },
1745 {
1746 {
1747 {0xff, 0xff, 0xff, 0xff},
1748 {0xff, 0x04, 0x06, 0x08}
1749 },
1750 {
1751 {0xff, 0xff, 0xff, 0xff},
1752 {0x05, 0x07, 0x09, 0xff}
1753 }
1754 }};
1755
Arthur Heymans6bf13012017-06-10 12:03:27 +02001756 static const u8 dradrb[10][6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001757 //Row Col Bank Width DRB
1758 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1759 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1760 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1761 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1762 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1763 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1764 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1765 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1766 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1767 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1768 };
1769
1770 reg32 = 0;
1771 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1772 i = r / 2;
1773 PRINTK_DEBUG("RANK %d PRESENT\n", r);
1774 dra = dratab[s->dimms[i].banks]
1775 [s->dimms[i].width]
1776 [s->dimms[i].cols - 9]
1777 [s->dimms[i].rows - 12];
1778
1779 if (s->dimms[i].banks == 1) {
1780 dra |= (1 << 7);
1781 }
1782 reg32 |= (dra << (r*8));
1783 }
1784 MCHBAR32(0x208) = reg32;
1785 c0dra = reg32;
1786 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1787
1788 reg32 = 0;
1789 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1790 reg32 |= (1 << r);
1791 }
1792 reg8 = (u8)(reg32 << 4) & 0xf0;
1793 MCHBAR8(0x262) = (MCHBAR8(0x262) & ~0xf0) | reg8;
1794 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) ||
1795 ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1796 MCHBAR8(0x260) = MCHBAR8(0x260) | 1;
1797 }
1798
1799 addr = 0x200;
1800 c0drb = 0;
1801 FOR_EACH_RANK(ch, r) {
1802 if (rank_is_populated(s->dimms, ch, r)) {
1803 ind = (c0dra >> (8*r)) & 0x7f;
1804 c0drb = (u16)(c0drb + dradrb[ind][5]);
1805 s->channel_capacity[0] += dradrb[ind][5] << 6;
1806 }
1807 MCHBAR16(addr) = c0drb;
1808 addr += 2;
1809 }
1810 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1811}
1812
1813static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1814{
Damien Zammit003d15c2015-11-20 17:17:51 +11001815 u8 dqsmatches = 1;
1816 while (count--) {
1817 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0x2;
1818 hpet_udelay(1);
1819 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
1820 hpet_udelay(1);
1821 barrier();
Elyes HAOUASaf159d42019-05-22 20:19:22 +02001822 read32((void *)strobeaddr);
Damien Zammit003d15c2015-11-20 17:17:51 +11001823 barrier();
1824 hpet_udelay(1);
1825
1826 if (((MCHBAR8(dqshighaddr) & 0x40) >> 6) != highlow) {
1827 dqsmatches = 0;
1828 }
1829 }
1830
1831 return dqsmatches;
1832}
1833
1834static void rcvenclock(u8 *coarse, u8 *medium, u8 bytelane)
1835{
1836 if (*medium < 3) {
1837 (*medium)++;
1838 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << (bytelane*2))))
1839 | (*medium << (bytelane*2));
1840 } else {
1841 *medium = 0;
1842 (*coarse)++;
1843 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (*coarse << 16);
1844 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~0x3 << (bytelane*2)))
1845 | (*medium << (bytelane*2));
1846 }
1847}
1848
1849static void sdram_rcven(struct sysinfo *s)
1850{
1851 u8 curcoarse, savecoarse;
1852 u8 curmedium, savemedium;
1853 u8 pi, savepi;
1854 u8 bytelane;
1855 u8 bytelanecoarse[8] = { 0 };
1856 u8 minbytelanecoarse = 0xff;
1857 u8 bytelaneoffset;
1858 u8 maxbytelane = 8;
Arthur Heymans015339f2018-08-20 11:28:58 +02001859 /* Since dra/drb is already set up we know that at address 0x00000000
1860 we will always find the first available rank */
1861 u32 strobeaddr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001862 u32 dqshighaddr;
1863
1864 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xc;
1865 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
1866
1867 PRINTK_DEBUG("rcven 0\n");
1868 for (bytelane = 0; bytelane < maxbytelane; bytelane++) {
1869 PRINTK_DEBUG("rcven bytelane %d\n", bytelane);
1870//trylaneagain:
1871 dqshighaddr = 0x561 + (bytelane << 2);
1872
1873 curcoarse = s->selected_timings.CAS + 1;
1874 pi = 0;
1875 curmedium = 0;
1876
1877 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (curcoarse << 16);
1878 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << (bytelane*2))))
1879 | (curmedium << (bytelane*2));
1880 MCHBAR8(0x560+bytelane*4) = MCHBAR8(0x560+bytelane*4) & ~0x3f;
1881
1882 savecoarse = curcoarse;
1883 savemedium = curmedium;
1884 savepi = pi;
1885
1886 PRINTK_DEBUG("rcven 0.1\n");
1887
1888 //MCHBAR16(0x588) = (MCHBAR16(0x588) & (u16)~(0x3 << (bytelane*2))) | (1 << (bytelane*2)); // XXX comment out
1889
1890 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1891 //printk(BIOS_DEBUG, "coarse=%d medium=%d\n", curcoarse, curmedium);
1892 rcvenclock(&curcoarse, &curmedium, bytelane);
1893 if (curcoarse > 0xf) {
1894 PRINTK_DEBUG("Error: coarse > 0xf\n");
1895 //goto trylaneagain;
1896 break;
1897 }
1898 }
1899 PRINTK_DEBUG("rcven 0.2\n");
1900
1901 savecoarse = curcoarse;
1902 savemedium = curmedium;
1903 rcvenclock(&curcoarse, &curmedium, bytelane);
1904
1905 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1906 savecoarse = curcoarse;
1907 savemedium = curmedium;
1908 rcvenclock(&curcoarse, &curmedium, bytelane);
1909 if (curcoarse > 0xf) {
1910 PRINTK_DEBUG("Error: coarse > 0xf\n");
1911 //goto trylaneagain;
1912 break;
1913 }
1914 }
1915
1916 PRINTK_DEBUG("rcven 0.3\n");
1917 curcoarse = savecoarse;
1918 curmedium = savemedium;
1919 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (curcoarse << 16);
1920 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << bytelane*2)))
1921 | (curmedium << (bytelane*2));
1922
1923 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1924 savepi = pi;
1925 pi++;
1926 if (pi > s->maxpi) {
1927 //if (s->nodll) {
1928 pi = savepi = s->maxpi;
1929 break;
1930 //}
1931 }
1932 MCHBAR8(0x560 + bytelane*4) = (MCHBAR8(0x560 + bytelane*4)
1933 & ~0x3f) | (pi << s->pioffset);
1934 }
1935 PRINTK_DEBUG("rcven 0.4\n");
1936
1937 pi = savepi;
1938 MCHBAR8(0x560 + bytelane*4) = (MCHBAR8(0x560 + bytelane*4) & ~0x3f)
1939 | (pi << s->pioffset);
1940 rcvenclock(&curcoarse, &curmedium, bytelane);
1941 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1942 PRINTK_DEBUG("Error: DQS not high\n");
1943 //goto trylaneagain;
1944 }
1945 PRINTK_DEBUG("rcven 0.5\n");
1946 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1947 curcoarse--;
1948 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000)
1949 | (curcoarse << 16);
1950 if (curcoarse == 0) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +02001951 PRINTK_DEBUG("Error: DQS did not hit 0\n");
Damien Zammit003d15c2015-11-20 17:17:51 +11001952 break;
1953 }
1954 }
1955
1956 PRINTK_DEBUG("rcven 0.6\n");
1957 rcvenclock(&curcoarse, &curmedium, bytelane);
1958 s->pi[bytelane] = pi;
1959 bytelanecoarse[bytelane] = curcoarse;
1960 }
1961
1962 PRINTK_DEBUG("rcven 1\n");
1963
1964 bytelane = maxbytelane;
1965 do {
1966 bytelane--;
1967 if (minbytelanecoarse > bytelanecoarse[bytelane]) {
1968 minbytelanecoarse = bytelanecoarse[bytelane];
1969 }
1970 } while (bytelane != 0);
1971
1972 bytelane = maxbytelane;
1973 do {
1974 bytelane--;
1975 bytelaneoffset = bytelanecoarse[bytelane] - minbytelanecoarse;
1976 MCHBAR16(0x5fa) = (MCHBAR16(0x5fa) & (u16)(~(0x3 << (bytelane*2))))
1977 | (bytelaneoffset << (bytelane*2));
1978 } while (bytelane != 0);
1979
1980 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (minbytelanecoarse << 16);
1981
1982 s->coarsectrl = minbytelanecoarse;
1983 s->coarsedelay = MCHBAR16(0x5fa);
1984 s->mediumphase = MCHBAR16(0x58c);
1985 s->readptrdelay = MCHBAR16(0x588);
1986
1987 PRINTK_DEBUG("rcven 2\n");
1988 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xe;
1989 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
1990 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x4;
1991 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x8;
1992
1993 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
1994 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
1995 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
1996 PRINTK_DEBUG("rcven 3\n");
1997}
1998
1999static void sdram_mmap_regs(struct sysinfo *s)
2000{
2001 bool reclaim;
2002 u32 tsegsize;
2003 u32 mmiosize;
2004 u32 tom, tolud, touud, reclaimbase, reclaimlimit;
2005 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase;
2006 u16 ggc;
2007 u16 ggc_to_uma[10] = { 0, 1, 4, 8, 16, 32, 48, 64, 128, 256 };
2008 u8 ggc_to_gtt[4] = { 0, 1, 0, 0 };
2009
2010 reclaimbase = 0;
2011 reclaimlimit = 0;
2012 ggc = pci_read_config16(PCI_DEV(0,0,0), GGC);
Damien Zammit51fdb922016-01-18 18:34:52 +11002013 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
Damien Zammit003d15c2015-11-20 17:17:51 +11002014 gfxsize = ggc_to_uma[(ggc & 0xf0) >> 4];
Damien Zammit51fdb922016-01-18 18:34:52 +11002015 gttsize = ggc_to_gtt[(ggc & 0x300) >> 8];
Damien Zammit003d15c2015-11-20 17:17:51 +11002016 tom = s->channel_capacity[0];
2017
Arthur Heymansda44e342019-01-12 01:38:02 +01002018 /* with GTT always being 1M, TSEG 1M is the only setting that can
2019 be covered by SMRR which has alignment requirements. */
2020 tsegsize = 0x1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002021 mmiosize = 0x400; // 1GB
2022
2023 reclaim = false;
2024 tolud = MIN(0x1000 - mmiosize, tom);
2025 if ((tom - tolud) > 0x40) {
Arthur Heymansaaebb412017-08-27 18:46:12 +02002026 reclaim = true;
Damien Zammit003d15c2015-11-20 17:17:51 +11002027 }
2028 if (reclaim) {
2029 tolud = tolud & ~0x3f;
2030 tom = tom & ~0x3f;
2031 reclaimbase = MAX(0x1000, tom);
2032 reclaimlimit = reclaimbase + (MIN(0x1000, tom) - tolud) - 0x40;
2033 }
2034 touud = tom;
2035 if (reclaim) {
2036 touud = reclaimlimit + 0x40;
2037 }
2038
2039 gfxbase = tolud - gfxsize;
2040 gttbase = gfxbase - gttsize;
2041 tsegbase = gttbase - tsegsize;
2042
2043 /* Program the regs */
Damien Zammit51fdb922016-01-18 18:34:52 +11002044 pci_write_config16(PCI_DEV(0,0,0), TOLUD, (u16)(tolud << 4));
2045 pci_write_config16(PCI_DEV(0,0,0), TOM, (u16)(tom >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002046 if (reclaim) {
2047 pci_write_config16(PCI_DEV(0,0,0), 0x98, (u16)(reclaimbase >> 6));
2048 pci_write_config16(PCI_DEV(0,0,0), 0x9a, (u16)(reclaimlimit >> 6));
2049 }
Damien Zammit51fdb922016-01-18 18:34:52 +11002050 pci_write_config16(PCI_DEV(0,0,0), TOUUD, (u16)(touud));
2051 pci_write_config32(PCI_DEV(0,0,0), GBSM, gfxbase << 20);
2052 pci_write_config32(PCI_DEV(0,0,0), BGSM, gttbase << 20);
2053 pci_write_config32(PCI_DEV(0,0,0), TSEG, tsegbase << 20);
2054
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002055 u8 reg8 = pci_read_config8(PCI_DEV(0, 0, 0), ESMRAMC);
2056 reg8 &= ~0x7;
Arthur Heymansda44e342019-01-12 01:38:02 +01002057 reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002058 pci_write_config8(PCI_DEV(0, 0, 0), ESMRAMC, reg8);
2059
Damien Zammit51fdb922016-01-18 18:34:52 +11002060 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
2061 pci_read_config32(PCI_DEV(0,0,0), GBSM), gfxbase << 20);
2062 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
2063 pci_read_config32(PCI_DEV(0,0,0), BGSM), gttbase << 20);
2064 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
2065 pci_read_config32(PCI_DEV(0,0,0), TSEG), tsegbase << 20);
Damien Zammit003d15c2015-11-20 17:17:51 +11002066}
2067
2068static void sdram_enhancedmode(struct sysinfo *s)
2069{
2070 u8 reg8, ch, r, j, i;
2071 u32 mask32, reg32;
2072 MCHBAR8(0x246) = MCHBAR8(0x246) | 1;
2073 MCHBAR8(0x269 + 3) = MCHBAR8(0x269 + 3) | 1;
2074 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
2075 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2076 MCHBAR32(0x120) = (MCHBAR32(0x120) & ~mask32) | reg32;
2077 MCHBAR8(0x288 + 1) = 0x2;
2078 MCHBAR16(0x288 + 2) = 0x0804;
2079 MCHBAR16(0x288 + 4) = 0x2010;
2080 MCHBAR8(0x288 + 6) = 0x40;
2081 MCHBAR16(0x288 + 8) = 0x091c;
2082 MCHBAR8(0x288 + 10) = 0xf2;
2083 MCHBAR8(0x241) = MCHBAR8(0x241) | 1;
2084 MCHBAR8(0x243) = MCHBAR8(0x243) | 1;
2085 MCHBAR16(0x272) = MCHBAR16(0x272) | 0x100;
2086
2087 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf0);
2088 pci_write_config8(PCI_DEV(0,0,0), 0xf0, reg8 | 1);
2089 MCHBAR32(0xfa0) = 0x00000002;
2090 MCHBAR32(0xfa4) = 0x20310002;
2091 MCHBAR32(0x24) = 0x02020302;
2092 MCHBAR32(0x30) = 0x001f1806;
2093 MCHBAR32(0x34) = 0x01102800;
2094 MCHBAR32(0x38) = 0x07000000;
2095 MCHBAR32(0x3c) = 0x01014010;
2096 MCHBAR32(0x40) = 0x0f038000;
2097 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf0);
2098 pci_write_config8(PCI_DEV(0,0,0), 0xf0, reg8 & ~1);
2099
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002100 u32 nranks, curranksize, maxranksize, dra;
2101 u8 rankmismatch;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002102 static const u8 drbtab[10] = { 0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8,
2103 0x20, 0x10 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002104
2105 nranks = 0;
2106 curranksize = 0;
2107 maxranksize = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002108 rankmismatch = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002109 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2110 nranks++;
2111 dra = (u8) ((MCHBAR32(0x208) >> (8*r)) & 0x7f);
2112 curranksize = drbtab[dra];
2113 if (maxranksize == 0) {
2114 maxranksize = curranksize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002115 }
2116 if (curranksize != maxranksize) {
2117 rankmismatch = 1;
2118 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002119 }
2120
2121 reg8 = 0;
2122 switch (nranks) {
2123 case 4:
2124 if (rankmismatch) {
2125 reg8 = 0x64;
2126 } else {
2127 reg8 = 0xa4;
2128 }
2129 break;
2130 case 1:
2131 case 3:
2132 reg8 = 0x64;
2133 break;
2134 case 2:
2135 if (rankmismatch) {
2136 reg8 = 0x64;
2137 } else {
2138 reg8 = 0x24;
2139 }
2140 break;
2141 default:
2142 die("Invalid number of ranks found, halt\n");
2143 break;
2144 }
2145 MCHBAR8(0x111) = (MCHBAR8(0x111) & ~0xfc) | (reg8 & 0xfc);
2146 MCHBAR32(0xd0) = MCHBAR32(0xd0) & ~0x80000000;
2147
2148 MCHBAR32(0x28) = 0xf;
2149 MCHBAR8(0x2c4) = MCHBAR8(0x2c4) | 1;
2150
2151 MCHBAR32(0x3c) = MCHBAR32(0x3c) & ~0xe000000;
2152 MCHBAR32(0x40) = (MCHBAR32(0x40) & ~0xc0000) | 0x40000;
2153 u32 clkcx[2][2][3] = {
2154 {
2155 {0, 0x0c080302, 0x08010204}, // 667
2156 {0x02040000, 0x08100102, 0}
2157 },
2158 {
2159 {0x18000000, 0x3021060c, 0x20010208},
2160 {0, 0x0c090306, 0} // 800
2161 }
2162 };
2163 j = s->selected_timings.fsb_clock;
2164 i = s->selected_timings.mem_clock;
2165
2166 MCHBAR32(0x708) = clkcx[j][i][0];
2167 MCHBAR32(0x70c) = clkcx[j][i][1];
2168 MCHBAR32(0x6dc) = clkcx[j][i][2];
2169 MCHBAR8(0x40) = MCHBAR8(0x40) & ~0x2;
2170}
2171
2172static void sdram_periodic_rcomp(void)
2173{
2174 MCHBAR8(0x130) = MCHBAR8(0x130) & ~0x2;
2175 while ((MCHBAR32(0x130) & 0x80000000) > 0) {
2176 ;
2177 }
2178 MCHBAR16(0x1b4) = (MCHBAR16(0x1b4) & ~0x3000);
2179
2180 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2181 MCHBAR16(0x170) = (MCHBAR16(0x170) & ~0xf) | 0x9;
2182
2183 MCHBAR8(0x130) = MCHBAR8(0x130) | 0x82;
2184}
2185
2186static void sdram_new_trd(struct sysinfo *s)
2187{
2188 u8 pidelay, i, j, k, cc, trd_perphase[5];
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002189 u8 bypass, freqgb, trd, reg8, txfifo;
Damien Zammit003d15c2015-11-20 17:17:51 +11002190 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2191 u16 tmclk, thclk, buffertocore, postcalib;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002192 static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2193 static const u16 trd_adjust[2][2][5] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11002194 {
2195 {3000, 3000, 0,0,0},
2196 {1000,2000,3000,1500,2500}
2197 },
2198 {
2199 {2000,1000,3000,0,0},
2200 {2500, 2500, 0,0,0}
2201 }};
2202
2203 freqgb = 110;
2204 buffertocore = 5000;
Damien Zammit003d15c2015-11-20 17:17:51 +11002205 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2206 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2207 tmclk = tmclk * 100 / freqgb;
2208 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2209 switch (s->selected_timings.mem_clock) {
2210 case MEM_CLOCK_667MHz:
2211 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2212 cc = 2;
2213 } else {
2214 cc = 3;
2215 }
2216 break;
2217 default:
2218 case MEM_CLOCK_800MHz:
2219 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2220 cc = 5;
2221 } else {
2222 cc = 2;
2223 }
2224 break;
2225 }
2226 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2227 maxrcvendelay = 0;
2228 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2229
2230 for (i = 0; i < 8; i++) {
2231 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 0x3) * (u32)(tmclk));
2232 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 0x3) * (u32)(tmclk) / 2);
2233 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 0x3) * (u32)(tmclk) / 4);
2234 rcvendelay += (u32)(pidelay * s->pi[i]);
2235 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2236 }
2237
2238 if ((MCHBAR8(0xc54+3) == 0xff) && (MCHBAR8(0xc08) & 0x80)) {
2239 bypass = 1;
2240 } else {
2241 bypass = 0;
2242 }
2243
2244 txfifo = 0;
2245 reg8 = (MCHBAR8(0x188) & 0xe) >> 1;
2246 txfifo = txfifo_lut[reg8] & 0x7;
2247
2248 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2249 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2250 if (s->async) {
2251 datadelay += tmclk / 2;
2252 }
2253
2254 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2255 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2256
2257 if (j == 0 && k == 0) {
2258 datadelay -= 3084;
2259 }
2260
2261 trd = 0;
2262 for (i = 0; i < cc; i++) {
2263 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2264 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2265 trd_perphase[i] += 1;
2266 if (trd_perphase[i] > trd) {
2267 trd = trd_perphase[i];
2268 }
2269 }
2270
2271 MCHBAR16(0x248) = (MCHBAR16(0x248) & ~0x1f00) | (trd << 8);
2272}
2273
2274static void sdram_powersettings(struct sysinfo *s)
2275{
2276 u8 j;
2277 u32 reg32;
2278
2279 /* Thermal sensor */
2280 MCHBAR8(0x3808) = 0x9b;
2281 MCHBAR32(0x380c) = (MCHBAR32(0x380c) & ~0x00ffffff) | 0x1d00;
2282 MCHBAR8(0x3814) = 0x08;
2283 MCHBAR8(0x3824) = 0x00;
2284 MCHBAR8(0x3809) = (MCHBAR8(0x3809) & ~0xf) | 0x4;
2285 MCHBAR8(0x3814) = (MCHBAR8(0x3814) & ~1) | 1;
2286 MCHBAR8(0x3812) = (MCHBAR8(0x3812) & ~0x80) | 0x80;
2287
2288 /* Clock gating */
2289 MCHBAR32(0xf18) = MCHBAR32(0xf18) & ~0x00040001;
2290 MCHBAR8(0xfac+3) = MCHBAR8(0xfac+3) & ~0x80;
2291 MCHBAR8(0xff8+3) = MCHBAR8(0xff8+3) & ~0x80;
2292 MCHBAR16(0xff0) = MCHBAR16(0xff0) & ~0x1fff;
2293 MCHBAR32(0xfb0) = MCHBAR32(0xfb0) & ~0x0001ffff;
2294 MCHBAR16(0x48) = (MCHBAR16(0x48) & ~0x03ff) & 0x6;
2295 MCHBAR32(0x20) = (MCHBAR32(0x20) & ~0xffffffff) | 0x20;
2296 MCHBAR8(0xd14) = MCHBAR8(0xd14) & ~1;
2297 MCHBAR8(0x239) = s->selected_timings.CAS - 1 + 0x15;
2298 MCHBAR16(0x2d1) = (MCHBAR16(0x2d1) & ~0x07fc) | 0x40;
2299 MCHBAR16(0x6d1) = (MCHBAR16(0x6d1) & ~0x0fff) | 0xd00;
2300 MCHBAR16(0x210) = MCHBAR16(0x210) & ~0x0d80;
2301 MCHBAR16(0xf6c+2) = 0xffff;
2302
2303 /* Sequencing */
2304 MCHBAR32(0x14) = (MCHBAR32(0x14) & ~0x1fffffff) | 0x1f643fff;
2305 MCHBAR32(0x18) = (MCHBAR32(0x18) & ~0xffffff7f) | 0x02010000;
2306 MCHBAR16(0x1c) = (MCHBAR16(0x1c) & ~0x7000) | (0x3 << 12);
2307
2308 /* Power */
2309 MCHBAR32(0x1104) = (MCHBAR32(0x1104) & ~0xffff0003) | 0x10100000;
2310 MCHBAR32(0x1108) = (MCHBAR32(0x1108) & ~0x0001bff7) | 0x00000078;
2311 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2312 MCHBAR16(0x110c) = (MCHBAR16(0x110c) & ~0x03ff) | 0xc8;
2313 } else {
2314 MCHBAR16(0x110c) = (MCHBAR16(0x110c) & ~0x03ff) | 0x100;
2315 }
2316 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2317
2318 MCHBAR32(0x1110) = (MCHBAR32(0x1110) & ~0x1fff37f) | 0x10810700;
2319 MCHBAR8(0x1114) = (MCHBAR8(0x1114) & ~0x07) | 1;
2320 MCHBAR8(0x1124) = MCHBAR8(0x1124) & ~0x02;
2321
Arthur Heymans6bf13012017-06-10 12:03:27 +02002322 static const u16 ddr2lut[2][4][2] = {{
Damien Zammit003d15c2015-11-20 17:17:51 +11002323 {0x0000, 0x0000},
2324 {0x019A, 0x0039},
2325 {0x0099, 0x1049},
2326 {0x0000, 0x0000}
2327 },
2328 {
2329 {0x0000, 0x0000},
2330 {0x019A, 0x0039},
2331 {0x0099, 0x1049},
2332 {0x0099, 0x2159}
2333 }};
2334
2335 MCHBAR16(0x23c) = 0x7a89;
2336 MCHBAR8(0x117) = 0xaa;
2337 MCHBAR16(0x118) = ddr2lut[j][s->selected_timings.CAS - 3][1];
2338 MCHBAR16(0x115) = (MCHBAR16(0x115) & ~0x7fff) | ddr2lut[j]
2339 [s->selected_timings.CAS - 3][0];
2340 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0xf000) | 0xf000;
2341 MCHBAR8(0x2c02) = (MCHBAR8(0x2c02) & ~0x77) | (4 << 4 | 4);
2342 if (s->nodll) {
2343 reg32 = 0x30000000;
2344 } else {
2345 reg32 = 0;
2346 }
2347 MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0x0f000000) | 0x20000000 | reg32;
2348 MCHBAR32(0x2d1) = (MCHBAR32(0x2d1) & ~0x00f00000) | 0x00f00000;
2349 MCHBAR32(0x6d0) = (MCHBAR32(0x6d0) & ~0x001ff000) | (0xbf << 20);
2350 MCHBAR16(0x610) = (MCHBAR16(0x610) & ~0x1f7f) | (0xb << 8) | (7 << 4) | 0xb;
2351 MCHBAR16(0x612) = 0x3264;
2352 MCHBAR16(0x614) = (MCHBAR16(0x614) & ~0x3f3f) | (0x14 << 8) | 0xa;
2353
2354 MCHBAR32(0x6c0) = MCHBAR32(0x6c0) | 0x80002000;
2355}
2356
2357static void sdram_programddr(void)
2358{
2359 MCHBAR16(0x6d1) = (MCHBAR16(0x6d1) & ~0x03ff) | 0x100;
2360 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0x003f) | 0x10;
2361 MCHBAR16(0x2d1) = (MCHBAR16(0x2d1) & ~0x7000) | 0x2000;
2362 MCHBAR8(0x180) = MCHBAR8(0x180) & ~0xe;
2363 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0xc;
2364 MCHBAR8(0x561) = MCHBAR8(0x561) & ~0xe;
2365 MCHBAR8(0x565) = MCHBAR8(0x565) & ~0xe;
2366 MCHBAR8(0x569) = MCHBAR8(0x569) & ~0xe;
2367 MCHBAR8(0x56d) = MCHBAR8(0x56d) & ~0xe;
2368 MCHBAR8(0x571) = MCHBAR8(0x571) & ~0xe;
2369 MCHBAR8(0x575) = MCHBAR8(0x575) & ~0xe;
2370 MCHBAR8(0x579) = MCHBAR8(0x579) & ~0xe;
2371 MCHBAR8(0x57d) = MCHBAR8(0x57d) & ~0xe;
2372 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0x2;
2373 MCHBAR16(0x1b4) = MCHBAR16(0x1b4) & ~0x400;
2374 MCHBAR16(0x210) = MCHBAR16(0x210) & ~0xdc0;
2375 MCHBAR8(0x239) = MCHBAR8(0x239) & ~0x80;
2376 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~(1 << 22);
2377 MCHBAR16(0x2d1) = MCHBAR16(0x2d1) & ~0x80fc;
2378 MCHBAR16(0x6d1) = MCHBAR16(0x6d1) & ~0xc00;
2379 MCHBAR8(0x180) = MCHBAR8(0x180) & ~0xd;
2380 MCHBAR8(0x561) = MCHBAR8(0x561) & ~1;
2381 MCHBAR8(0x565) = MCHBAR8(0x565) & ~1;
2382 MCHBAR8(0x569) = MCHBAR8(0x569) & ~1;
2383 MCHBAR8(0x56d) = MCHBAR8(0x56d) & ~1;
2384 MCHBAR8(0x571) = MCHBAR8(0x571) & ~1;
2385 MCHBAR8(0x575) = MCHBAR8(0x575) & ~1;
2386 MCHBAR8(0x579) = MCHBAR8(0x579) & ~1;
2387 MCHBAR8(0x57d) = MCHBAR8(0x57d) & ~1;
2388 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0x700000) | (0x3 << 20);
2389 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~0x100000;
2390 MCHBAR8(0x592) = MCHBAR8(0x592) | 0x1e;
2391 MCHBAR8(0x2c15) = MCHBAR8(0x2c15) | 0x3;
2392 MCHBAR32(0x62c) = (MCHBAR32(0x62c) & ~0xc000000) | 0x4000000;
2393 MCHBAR16(0x248) = MCHBAR16(0x248) | 0x6000;
2394 MCHBAR32(0x260) = MCHBAR32(0x260) | 0x10000;
2395 MCHBAR8(0x2c0) = MCHBAR8(0x2c0) | 0x10;
2396 MCHBAR32(0x2d0) = MCHBAR32(0x2d0) | (0xf << 24);
2397 MCHBAR8(0x189) = MCHBAR8(0x189) | 0x7;
2398 MCHBAR8(0x592) = MCHBAR8(0x592) | 0xc0;
2399 MCHBAR8(0x124) = MCHBAR8(0x124) | 0x7;
2400 MCHBAR16(0x12a) = (MCHBAR16(0x12a) & ~0xffff) | 0x0080;
2401 MCHBAR8(0x12c) = (MCHBAR8(0x12c) & ~0xff) | 0x10;
2402 MCHBAR16(0x2c0) = MCHBAR16(0x2c0) | 0x1e0;
2403 MCHBAR8(0x189) = MCHBAR8(0x189) | 0x18;
2404 MCHBAR8(0x193) = MCHBAR8(0x193) | 0xd;
2405 MCHBAR16(0x212) = MCHBAR16(0x212) | 0xa3f;
2406 MCHBAR8(0x248) = MCHBAR8(0x248) | 0x3;
2407 MCHBAR8(0x268) = (MCHBAR8(0x268) & ~0xff) | 0x4a;
2408 MCHBAR8(0x2c4) = MCHBAR8(0x2c4) & ~0x60;
2409 MCHBAR16(0x592) = MCHBAR16(0x592) | 0x321;
2410}
2411
2412static void sdram_programdqdqs(struct sysinfo *s)
2413{
2414 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2415 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2416 u8 repeat, halfclk, feature, reg8, push;
2417 u16 cwb, pimdclk;
2418 u32 reg32;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002419 static const u8 txfifotab[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002420
2421 tpi = 3000;
2422 dqdqs_out = 4382;
2423 dqdqs_outdelay = 5083;
2424 dqdqs_delay = 4692;
2425 coretomcp = 0;
2426 txdelay = 0;
2427 halfclk = 0;
2428 tmaxunmask = 0;
2429 tmaxpi = 0;
2430 repeat = 2;
2431 feature = 0;
2432 cwb = 0;
2433 pimdclk = 0;
2434 reg32 = 0;
2435 push = 0;
2436 reg8 = 0;
2437
2438 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2439 refclk = 3000 - mdclk;
2440
2441 coretomcp = ((MCHBAR8(0x246) >> 2) & 0x3) + 1;
2442 coretomcp *= mdclk;
2443
2444 reg8 = (MCHBAR8(0x188) & 0xe) >> 1;
2445
2446 while (repeat) {
2447 txdelay = mdclk * (
2448 ((MCHBAR16(0x220) >> 8) & 0x7) +
2449 (MCHBAR8(0x24d) & 0xf) +
2450 (MCHBAR8(0x24e) & 0x1)
2451 ) +
2452 txfifotab[reg8]*(mdclk/2) +
2453 coretomcp +
2454 refclk +
2455 cwb;
2456 halfclk = (MCHBAR8(0x5d9) >> 1) & 0x1;
2457 if (halfclk) {
2458 txdelay -= mdclk / 2;
2459 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2460 } else {
2461 reg32 = dqdqs_outdelay + coretomcp;
2462 }
2463
2464 tmaxunmask = txdelay - mdclk - dqdqs_out;
2465 tmaxpi = tmaxunmask - tpi;
2466
2467 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2468 if (repeat == 2) {
2469 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~(1 << 23);
2470 }
2471 feature = 1;
2472 repeat = 0;
2473 } else {
2474 repeat--;
2475 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) | (1 << 23);
2476 cwb = 2 * mdclk;
2477 }
2478 }
2479
2480 if (!feature) {
2481 MCHBAR8(0x2d1) = MCHBAR8(0x2d1) & ~0x3;
2482 return;
2483 }
2484 MCHBAR8(0x2d1) = MCHBAR8(0x2d1) | 0x3;
2485 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0xf000) | (pimdclk << 12);
2486 MCHBAR8(0x2c02) = (MCHBAR8(0x2c02) & ~0x77) | (push << 4) | push;
2487 MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0xf000000) | 0x3000000;
2488}
2489
2490/**
2491 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2492 */
2493void sdram_initialize(int boot_path, const u8 *spd_addresses)
2494{
2495 struct sysinfo si;
2496 u8 reg8;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002497 const char *boot_str[] = { "Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002498
2499 PRINTK_DEBUG("Setting up RAM controller.\n");
2500
2501 memset(&si, 0, sizeof(si));
2502
2503 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002504 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002505 si.spd_map[0] = spd_addresses[0];
2506 si.spd_map[1] = spd_addresses[1];
2507 si.spd_map[2] = spd_addresses[2];
2508 si.spd_map[3] = spd_addresses[3];
2509
2510 sdram_read_spds(&si);
2511
2512 /* Choose Common Frequency */
2513 sdram_detect_ram_speed(&si);
2514
2515 /* Determine smallest common tRAS, tRP, tRCD, etc */
2516 sdram_detect_smallest_params(&si);
2517
2518 /* Enable HPET */
2519 enable_hpet();
Damien Zammit003d15c2015-11-20 17:17:51 +11002520
2521 MCHBAR16(0xc1c) = MCHBAR16(0xc1c) | (1 << 15);
2522
Damien Zammit003d15c2015-11-20 17:17:51 +11002523 sdram_clk_crossing(&si);
2524
2525 sdram_checkreset();
2526 PRINTK_DEBUG("Done checkreset\n");
2527
2528 sdram_clkmode(&si);
2529 PRINTK_DEBUG("Done clkmode\n");
2530
2531 sdram_timings(&si);
2532 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2533
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002534 if (si.boot_path != BOOT_PATH_RESET) {
2535 sdram_dlltiming(&si);
2536 PRINTK_DEBUG("Done dlltiming\n");
2537 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002538
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002539 if (si.boot_path != BOOT_PATH_RESET) {
2540 sdram_rcomp(&si);
2541 PRINTK_DEBUG("Done RCOMP\n");
2542 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002543
2544 sdram_odt(&si);
2545 PRINTK_DEBUG("Done odt\n");
2546
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002547 if (si.boot_path != BOOT_PATH_RESET) {
2548 while ((MCHBAR8(0x130) & 0x1) != 0)
2549 ;
2550 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002551
2552 sdram_mmap(&si);
2553 PRINTK_DEBUG("Done mmap\n");
2554
2555 // Enable DDR IO buffer
2556 MCHBAR8(0x5dd) = (MCHBAR8(0x5dd) & ~0x3f) | 0x8;
2557 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x1;
2558
2559 sdram_rcompupdate(&si);
2560 PRINTK_DEBUG("Done RCOMP update\n");
2561
2562 MCHBAR8(0x40) = MCHBAR8(0x40) | 0x2;
2563
2564 if (si.boot_path != BOOT_PATH_RESUME) {
2565 MCHBAR32(0x260) = MCHBAR32(0x260) | (1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002566
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002567 sdram_jedecinit(&si);
2568 PRINTK_DEBUG("Done MRS\n");
2569 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002570
2571 sdram_misc(&si);
2572 PRINTK_DEBUG("Done misc\n");
2573
2574 sdram_zqcl(&si);
2575 PRINTK_DEBUG("Done zqcl\n");
2576
2577 if (si.boot_path != BOOT_PATH_RESUME) {
2578 MCHBAR32(0x268) = MCHBAR32(0x268) | 0xc0000000;
2579 }
2580
2581 sdram_dradrb(&si);
2582 PRINTK_DEBUG("Done dradrb\n");
2583
2584 sdram_rcven(&si);
2585 PRINTK_DEBUG("Done rcven\n");
2586
2587 sdram_new_trd(&si);
2588 PRINTK_DEBUG("Done tRD\n");
2589
2590 sdram_mmap_regs(&si);
2591 PRINTK_DEBUG("Done mmap regs\n");
2592
2593 sdram_enhancedmode(&si);
2594 PRINTK_DEBUG("Done enhanced mode\n");
2595
2596 sdram_powersettings(&si);
2597 PRINTK_DEBUG("Done power settings\n");
2598
2599 sdram_programddr();
2600 PRINTK_DEBUG("Done programming ddr\n");
2601
2602 sdram_programdqdqs(&si);
2603 PRINTK_DEBUG("Done programming dqdqs\n");
2604
2605 sdram_periodic_rcomp();
2606 PRINTK_DEBUG("Done periodic RCOMP\n");
2607
2608 /* Set init done */
2609 MCHBAR32(0x268) = MCHBAR32(0x268) | 0x40000000;
2610
2611 /* Tell ICH7 that we're done */
2612 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
2613 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8 & ~0x80);
2614
2615 /* Tell northbridge we're done */
2616 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf4);
2617 pci_write_config8(PCI_DEV(0,0,0), 0xf4, reg8 | 1);
2618
2619 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2620}