blob: 1d24ea221739557d29071314b2cbc90a0564f56d [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;
Jacob Garberd10680b2019-06-11 14:13:04 -06001144
Damien Zammit003d15c2015-11-20 17:17:51 +11001145 reg8 = 0x00; //switch all clocks on anyway
1146
1147 MCHBAR32(0x5a0) = (MCHBAR32(0x5a0) & ~0x3f000000) | (reg8 << 24);
1148 MCHBAR8(0x594) = MCHBAR8(0x594) & ~1;
1149 reg16 = 0;
1150 if (!rank_is_populated(s->dimms, 0, 0)) {
1151 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
1152 }
1153 if (!rank_is_populated(s->dimms, 0, 1)) {
1154 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
1155 }
1156 if (!rank_is_populated(s->dimms, 0, 2)) {
1157 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1158 }
1159 if (!rank_is_populated(s->dimms, 0, 3)) {
1160 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1161 }
1162 MCHBAR16(0x59c) = MCHBAR16(0x59c) | reg16;
1163}
1164
1165static void sdram_rcomp(struct sysinfo *s)
1166{
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02001167 u8 i, j, reg8, rcompp, rcompn, srup, srun;
Damien Zammit003d15c2015-11-20 17:17:51 +11001168 u16 reg16;
1169 u32 reg32, rcomp1, rcomp2;
1170
Arthur Heymans6bf13012017-06-10 12:03:27 +02001171 static const u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0 };
1172 static const u8 rcompslew = 0xa;
1173 static const u8 rcompstr[7] = { 0x66, 0, 0xaa, 0x55, 0x55, 0x77, 0x77 };
1174 static const u16 rcompscomp[7] = { 0xa22a, 0, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a };
1175 static const u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1 };
1176 static const u16 rcompctl[7] = { 0x31c, 0, 0x374, 0x3a2, 0x3d0, 0x3fe, 0x42c };
1177 static const u16 rcompf[7] = { 0x1114, 0, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a };
Damien Zammit003d15c2015-11-20 17:17:51 +11001178
1179 // NC-NC x16SS x16DS x16SS2 x16DS2 x8DS, x8DS2
Arthur Heymans6bf13012017-06-10 12:03:27 +02001180 static const u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa,
1181 0xaa , 0x55, 0xaa};
1182 static const u16 rcompscomp2[7] = { 0x0000, 0xe22e, 0xe22e, 0xe22e,
1183 0x8228 , 0xe22e, 0x8228 };
1184 static const u8 rcompdelay2[7] = { 0, 0, 0, 0, 2 , 0, 2};
Damien Zammit003d15c2015-11-20 17:17:51 +11001185
Arthur Heymans6bf13012017-06-10 12:03:27 +02001186 static const u8 rcomplut[64][12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001187 { 9, 9,11,11, 2, 2, 5,5, 6, 6,5, 5},
1188 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1189 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1190 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1191 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1192 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1193 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1194 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1195 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1196 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1197 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1198 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1199 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1200 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1201 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1202 { 10,9,12, 11, 2, 2, 5,5, 6, 6,5, 5},
1203 { 10,9,12, 11, 2, 2, 6,5, 7, 6,6, 5},
1204 { 10,10,12, 12, 2, 2, 6,5, 7, 6,6, 5},
1205 { 10,10,12, 12, 2, 2, 6,6, 7, 7,6, 6},
1206 { 10,10,12, 12, 3, 2, 6,6, 7, 7,6, 6},
1207 { 10,10,12, 12, 3, 2, 6,6, 7, 7,6, 6},
1208 { 10,10,12, 12, 3, 2, 6,6, 7, 7,6, 6},
1209 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1210 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1211 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1212 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1213 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1214 { 11,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1215 { 11,10,14, 13, 3, 3, 6,6, 7, 7,6, 6},
1216 { 12,10,14, 13, 3, 3, 6,6, 7, 7,6, 6},
1217 { 12,12,14, 13, 3, 3, 7,6, 7, 7,7, 6},
1218 { 13,12,16, 15, 3, 3, 7,6, 8, 7,7, 6},
1219 { 13,14,16, 15, 4, 3, 7,7, 8, 8,7, 7},
1220 { 14,14,16, 17, 4, 3, 7,7, 8, 8,7, 7},
1221 { 14,16,18, 17, 4, 4, 8,7, 8, 8,8, 7},
1222 { 15,16,18, 19, 4, 4, 8,7, 9, 8,8, 7},
1223 { 15,18,18, 19, 4, 4, 8,8, 9, 9,8, 8},
1224 { 16,18,20, 21, 4, 4, 8,8, 9, 9,8, 8},
1225 { 16,19,20, 21, 5, 4, 9,8, 10, 9,9, 8},
1226 { 16,19,20, 23, 5, 5, 9,9, 10, 10,9, 9},
1227 { 17,19,22, 23, 5, 5, 9,9, 10, 10,9, 9},
1228 { 17,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1229 { 17,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1230 { 18,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1231 { 18,21,24, 25, 5, 5, 9,9, 11, 10,9, 9},
1232 { 19,21,24, 27, 5, 5, 9, 9, 11, 11,9, 9},
1233 { 19,22,24, 27, 5, 5, 10,9, 11, 11,10, 9},
1234 { 20,22,24, 27, 6, 5, 10,10, 11, 11,10, 10},
1235 { 20,23,26, 27, 6, 6, 10,10, 12, 12,10, 10},
1236 { 20,23,26, 29, 6, 6, 10,10, 12, 12,10, 10},
1237 { 21,24,26, 29, 6, 6, 10,10, 12, 12,10, 10},
1238 { 21,24,26, 29, 6, 6, 11,10, 12, 13,11, 10},
1239 { 22,25,28, 29, 6, 6, 11,11, 13, 13,11, 11},
1240 { 22,25,28, 31, 6, 6, 11,11, 13, 13,11, 11},
1241 { 22,26,28, 31, 6, 6, 11,11, 13, 14,11, 11},
1242 { 23,26,30, 31, 7, 6, 12,11, 14, 14,12, 11},
1243 { 23,27,30, 33, 7, 7, 12,12, 14, 14,12, 12},
1244 { 23,27,30, 33, 7, 7, 12,12, 14, 15,12, 12},
1245 { 24,28,32, 33, 7, 7, 12,12, 15, 15,12, 12},
1246 { 24,28,32, 33, 7, 7, 12,12, 15, 16,12, 12},
1247 { 24,29,32, 35, 7, 7, 12,12, 15, 16,12, 12},
1248 { 25,29,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1249 { 25,30,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1250 { 25,30,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1251 };
1252
1253 srup = 0;
1254 srun = 0;
1255
1256 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001257 rcomp1 = 0x00050431;
1258 } else {
Damien Zammit003d15c2015-11-20 17:17:51 +11001259 rcomp1 = 0x00050542;
1260 }
1261 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
1262 rcomp2 = 0x14C42827;
1263 } else {
1264 rcomp2 = 0x19042827;
1265 }
1266
1267 for (i = 0; i < 7; i++) {
1268 if (i == 1)
1269 continue;
1270 reg8 = rcompupdate[i];
1271 MCHBAR8(rcompctl[i]) = (MCHBAR8(rcompctl[i]) & ~0x1) | reg8;
1272 MCHBAR8(rcompctl[i]) = MCHBAR8(rcompctl[i]) & ~0x2;
1273 reg16 = (u16) rcompslew;
1274 MCHBAR16(rcompctl[i]) = (MCHBAR16(rcompctl[i]) & ~0xf000) |
1275 (reg16 << 12);
1276 MCHBAR8(rcompctl[i]+4) = rcompstr[i];
1277 MCHBAR16(rcompctl[i]+0xe) = rcompscomp[i];
1278 MCHBAR8(rcompctl[i]+0x14) = (MCHBAR8(rcompctl[i]+0x14) & ~0x3) |
1279 rcompdelay[i];
1280 if (i == 2) {
1281 reg16 = (u16) rcompslew;
1282 MCHBAR16(rcompctl[i]) = (MCHBAR16(rcompctl[i]) &
1283 ~0xf000) | (reg16 << 12);
1284 MCHBAR8(rcompctl[i]+4) = rcompstr2[s->dimm_config[0]];
1285 MCHBAR16(rcompctl[i]+0xe) = rcompscomp2[s->dimm_config[0]];
1286 MCHBAR8(rcompctl[i]+0x14) = (MCHBAR8(rcompctl[i]+0x14) &
1287 ~0x3) | rcompdelay2[s->dimm_config[0]];
1288 }
1289
1290 MCHBAR16(rcompctl[i]+0x16) = MCHBAR16(rcompctl[i]+0x16) & ~0x7f7f;
1291 MCHBAR16(rcompctl[i]+0x18) = MCHBAR16(rcompctl[i]+0x18) & ~0x3f3f;
1292 MCHBAR16(rcompctl[i]+0x1a) = MCHBAR16(rcompctl[i]+0x1a) & ~0x3f3f;
1293 MCHBAR16(rcompctl[i]+0x1c) = MCHBAR16(rcompctl[i]+0x1c) & ~0x3f3f;
1294 MCHBAR16(rcompctl[i]+0x1e) = MCHBAR16(rcompctl[i]+0x1e) & ~0x3f3f;
1295 }
1296
1297 MCHBAR8(0x45a) = (MCHBAR8(0x45a) & ~0x3f) | 0x36;
1298 MCHBAR8(0x462) = (MCHBAR8(0x462) & ~0x3f) | 0x36;
1299
1300 for (i = 0; i < 7; i++) {
1301 if (i == 1)
1302 continue;
1303 MCHBAR8(rcompctl[i]) = MCHBAR8(rcompctl[i]) & ~0x60;
1304 MCHBAR16(rcompctl[i]+2) = MCHBAR16(rcompctl[i]+2) & ~0x706;
1305 MCHBAR16(rcompctl[i]+0xa) = MCHBAR16(rcompctl[i]+0xa) & ~0x7f7f;
1306 MCHBAR16(rcompctl[i]+0x12) = MCHBAR16(rcompctl[i]+0x12) & ~0x3f3f;
1307 MCHBAR16(rcompctl[i]+0x24) = MCHBAR16(rcompctl[i]+0x24) & ~0x1f1f;
1308 MCHBAR8(rcompctl[i]+0x26) = MCHBAR8(rcompctl[i]+0x26) & ~0x1f;
1309 }
1310
1311 MCHBAR16(0x45a) = MCHBAR16(0x45a) & ~0xffc0;
1312 MCHBAR16(0x45c) = MCHBAR16(0x45c) & ~0xf;
1313 MCHBAR16(0x462) = MCHBAR16(0x462) & ~0xffc0;
1314 MCHBAR16(0x464) = MCHBAR16(0x464) & ~0xf;
1315
1316 for (i = 0; i < 7; i++) {
1317 if (i == 1)
1318 continue;
1319 MCHBAR16(rcompctl[i]+0x10) = rcompf[i];
1320 MCHBAR16(rcompctl[i]+0x20) = 0x1219;
1321 MCHBAR16(rcompctl[i]+0x22) = 0x000C;
1322 }
1323
1324 MCHBAR32(0x164) = (MCHBAR32(0x164) & ~0x1f1f1f) | 0x0c1219;
1325 MCHBAR16(0x4b0) = (MCHBAR16(0x4b0) & ~0x1f00) | 0x1200;
1326 MCHBAR8(0x4b0) = (MCHBAR8(0x4b0) & ~0x1f) | 0x12;
1327 MCHBAR32(0x138) = 0x007C9007;
1328 MCHBAR32(0x16c) = rcomp1;
1329 MCHBAR16(0x17a) = 0x1f7f;
1330 MCHBAR32(0x134) = rcomp2;
1331 MCHBAR16(0x170) = (MCHBAR16(0x170) & ~0xf) | 1;
1332 MCHBAR16(0x178) = 0x134;
1333 MCHBAR32(0x130) = 0x4C293600;
1334 MCHBAR8(0x133) = (MCHBAR8(0x133) & ~0x44) | (1 << 6) | (1 << 2);
1335 MCHBAR16(0x4b0) = MCHBAR16(0x4b0) & ~(1 << 13);
1336 MCHBAR8(0x4b0) = MCHBAR8(0x4b0) & ~(1 << 5);
1337
1338 for (i = 0; i < 7; i++) {
1339 if (i == 1)
1340 continue;
1341 MCHBAR8(rcompctl[i]+2) = MCHBAR8(rcompctl[i]) & ~0x71;
1342 }
1343
1344 if ((MCHBAR32(0x130) & (1 << 30)) == 0) {
1345 MCHBAR8(0x130) = MCHBAR8(0x130) | 0x1;
1346 while ((MCHBAR8(0x130) & 0x1) != 0);
1347
1348 reg32 = MCHBAR32(0x13c);
1349 rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1350 rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1351
1352 for (i = 0; i < 7; i++) {
1353 if (i == 1)
1354 continue;
1355 srup = (MCHBAR8(rcompctl[i]+1) & 0xc0) >> 6;
1356 srun = (MCHBAR8(rcompctl[i]+1) & 0x30) >> 4;
1357 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
1358 MCHBAR16(rcompctl[i]+0x16) = (MCHBAR16(rcompctl[i]+0x16)
1359 & ~0x7f00) | reg16;
1360 reg16 = (u16)(rcompn - (1 << (srun + 1)));
1361 MCHBAR8(rcompctl[i]+0x16) = (MCHBAR8(rcompctl[i]+0x16) &
1362 ~0x7f) | (u8)reg16;
1363 }
1364
1365 reg8 = rcompp - (1 << (srup + 1));
1366 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1367 MCHBAR8(rcompctl[0]+0x18+i) =
1368 (MCHBAR8(rcompctl[0]+0x18+i) & ~0x3f) |
1369 rcomplut[j][0];
1370 }
1371
1372 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1373 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1374 MCHBAR8(rcompctl[2]+0x18+i) =
1375 (MCHBAR8(rcompctl[2]+0x18+i) & ~0x3f) |
1376 rcomplut[j][10];
1377 }
1378 }
1379
1380 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1381 MCHBAR8(rcompctl[3]+0x18+i) =
1382 (MCHBAR8(rcompctl[3]+0x18+i) & ~0x3f) |
1383 rcomplut[j][6];
1384 MCHBAR8(rcompctl[4]+0x18+i) =
1385 (MCHBAR8(rcompctl[4]+0x18+i) & ~0x3f) |
1386 rcomplut[j][6];
1387 }
1388
1389 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1390 MCHBAR8(rcompctl[5]+0x18+i) =
1391 (MCHBAR8(rcompctl[5]+0x18+i) & ~0x3f) |
1392 rcomplut[j][8];
1393 MCHBAR8(rcompctl[6]+0x18+i) =
1394 (MCHBAR8(rcompctl[6]+0x18+i) & ~0x3f) |
1395 rcomplut[j][8];
1396 }
1397
1398 reg8 = rcompn - (1 << (srun + 1));
1399 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1400 MCHBAR8(rcompctl[0]+0x1c+i) =
1401 (MCHBAR8(rcompctl[0]+0x1c+i) & ~0x3f) |
1402 rcomplut[j][1];
1403 }
1404
1405 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1406 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1407 MCHBAR8(rcompctl[2]+0x1c+i) =
1408 (MCHBAR8(rcompctl[2]+0x1c+i) & ~0x3f) |
1409 rcomplut[j][11];
1410 }
1411 }
1412
1413 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1414 MCHBAR8(rcompctl[3]+0x1c+i) =
1415 (MCHBAR8(rcompctl[3]+0x1c+i) & ~0x3f) |
1416 rcomplut[j][7];
1417 MCHBAR8(rcompctl[4]+0x1c+i) =
1418 (MCHBAR8(rcompctl[4]+0x1c+i) & ~0x3f) |
1419 rcomplut[j][7];
1420 }
1421
1422 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1423 MCHBAR8(rcompctl[5]+0x1c+i) =
1424 (MCHBAR8(rcompctl[5]+0x1c+i) & ~0x3f) |
1425 rcomplut[j][9];
1426 MCHBAR8(rcompctl[6]+0x1c+i) =
1427 (MCHBAR8(rcompctl[6]+0x1c+i) & ~0x3f) |
1428 rcomplut[j][9];
1429 }
1430 }
1431 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1432}
1433
1434static void sdram_odt(struct sysinfo *s)
1435{
1436 u8 rankindex = 0;
1437
Arthur Heymans6bf13012017-06-10 12:03:27 +02001438 static const u16 odt294[16] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001439 0x0000, 0x0000, 0x0000, 0x0000,
1440 0x0044, 0x1111, 0x0000, 0x1111,
1441 0x0000, 0x0000, 0x0000, 0x0000,
1442 0x0044, 0x1111, 0x0000, 0x1111
1443 };
Arthur Heymans6bf13012017-06-10 12:03:27 +02001444 static const u16 odt298[16] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001445 0x0000, 0x0011, 0x0000, 0x0011,
1446 0x0000, 0x4444, 0x0000, 0x4444,
1447 0x0000, 0x0000, 0x0000, 0x0000,
1448 0x0000, 0x4444, 0x0000, 0x4444
1449 };
1450
1451 switch (s->dimms[0].ranks) {
1452 case 0:
1453 if (s->dimms[1].ranks == 0) {
1454 rankindex = 0;
1455 } else if (s->dimms[1].ranks == 1) {
1456 rankindex = 4;
1457 } else if (s->dimms[1].ranks == 2) {
1458 rankindex = 12;
1459 }
1460 break;
1461 case 1:
1462 if (s->dimms[1].ranks == 0) {
1463 rankindex = 1;
1464 } else if (s->dimms[1].ranks == 1) {
1465 rankindex = 5;
1466 } else if (s->dimms[1].ranks == 2) {
1467 rankindex = 13;
1468 }
1469 break;
1470 case 2:
1471 if (s->dimms[1].ranks == 0) {
1472 rankindex = 3;
1473 } else if (s->dimms[1].ranks == 1) {
1474 rankindex = 7;
1475 } else if (s->dimms[1].ranks == 2) {
1476 rankindex = 15;
1477 }
1478 break;
1479 }
1480
1481 MCHBAR16(0x298) = odt298[rankindex];
1482 MCHBAR16(0x294) = odt294[rankindex];
1483}
1484
1485static void sdram_mmap(struct sysinfo *s)
1486{
Arthur Heymans6bf13012017-06-10 12:03:27 +02001487 static const u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000,
1488 0xc00001, 0xf00000};
1489 static const u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101,
1490 0x1010000, 0x1010101};
1491 static const u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1492 static const u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006,
1493 0x40002, 0x80006};
Damien Zammit003d15c2015-11-20 17:17:51 +11001494
Arthur Heymans6bf13012017-06-10 12:03:27 +02001495 static const u16 tolud[7] = {0x800, 0x800, 0x1000, 0x1000, 0x2000,
1496 0x1000, 0x2000};
1497 static const u16 tom[7] = {0x2, 0x2, 0x4, 0x4, 0x8, 0x4, 0x8};
1498 static const u16 touud[7] = {0x80, 0x80, 0x100, 0x100, 0x200, 0x100,
1499 0x200};
1500 static const u32 gbsm[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000,
1501 0x20000000, 0x10000000, 0x20000000};
1502 static const u32 bgsm[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000,
1503 0x20000000, 0x10000000, 0x20000000};
1504 static const u32 tsegmb[7] = {0x8000000, 0x8000000, 0x10000000,
1505 0x8000000, 0x20000000, 0x10000000,
1506 0x20000000};
Damien Zammit003d15c2015-11-20 17:17:51 +11001507
1508 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1509 if (s->dimms[0].sides > 1) {
1510 // 2R/NC
1511 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x300001;
1512 MCHBAR32(0x208) = 0x101;
1513 MCHBAR32(0x200) = 0x40002;
1514 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1515 } else {
1516 // 1R/NC
1517 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x100001;
1518 MCHBAR32(0x208) = 0x1;
1519 MCHBAR32(0x200) = 0x20002;
1520 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1521 }
1522 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
1523
1524 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x300001;
1525 MCHBAR32(0x208) = 0x101;
1526 MCHBAR32(0x200) = 0x40002;
1527 MCHBAR32(0x204) = 0x40004;
1528 } else {
1529 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | w260[s->dimm_config[0]];
1530 MCHBAR32(0x208) = w208[s->dimm_config[0]];
1531 MCHBAR32(0x200) = w200[s->dimm_config[0]];
1532 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1533 }
1534 pci_write_config16(PCI_DEV(0, 0, 0), 0xb0, tolud[s->dimm_config[0]]);
1535 pci_write_config16(PCI_DEV(0, 0, 0), 0xa0, tom[s->dimm_config[0]]);
1536 pci_write_config16(PCI_DEV(0, 0, 0), 0xa2, touud[s->dimm_config[0]]);
1537 pci_write_config32(PCI_DEV(0, 0, 0), 0xa4, gbsm[s->dimm_config[0]]);
1538 pci_write_config32(PCI_DEV(0, 0, 0), 0xa8, bgsm[s->dimm_config[0]]);
1539 pci_write_config32(PCI_DEV(0, 0, 0), 0xac, tsegmb[s->dimm_config[0]]);
1540}
1541
1542#if 1
1543static void hpet_udelay(u32 del)
1544{
1545 u32 start, finish, now;
1546
1547 del *= 15; /* now in usec */
1548
1549 start = HPET32(0xf0);
1550 finish = start + del;
1551 while (1) {
1552 now = HPET32(0xf0);
1553 if (finish > start) {
1554 if (now >= finish)
1555 break;
1556 } else {
1557 if ((now < start) && (now >= finish)) {
1558 break;
1559 }
1560 }
1561 }
1562}
1563#endif
1564
1565static u8 sdram_checkrcompoverride(void)
1566{
1567 u32 xcomp;
1568 u8 aa, bb, a, b, c, d;
1569
1570 xcomp = MCHBAR32(0x13c);
1571 a = (u8)((xcomp & 0x7f000000) >> 24);
1572 b = (u8)((xcomp & 0x7f0000) >> 16);
1573 c = (u8)((xcomp & 0x3f00) >> 8);
1574 d = (u8)(xcomp & 0x3f);
1575
1576 if (a > b) {
1577 aa = a - b;
1578 } else {
1579 aa = b - a;
1580 }
1581 if (c > d) {
1582 bb = c - d;
1583 } else {
1584 bb = d - c;
1585 }
1586 if ((aa > 18) || (bb > 7) ||
1587 (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
1588 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
1589 MCHBAR32(0x140) = 0x9718a729;
1590 return 1;
1591 }
1592 return 0;
1593}
1594
1595static void sdram_rcompupdate(struct sysinfo *s)
1596{
1597 u8 i, ok;
1598 u32 reg32a, reg32b;
1599
1600 ok = 0;
1601 MCHBAR8(0x170) = MCHBAR8(0x170) & ~(1 << 3);
1602 MCHBAR8(0x130) = MCHBAR8(0x130) & ~(1 << 7);
1603 for (i = 0; i < 3; i++) {
1604 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1605 hpet_udelay(1000);
1606 while ((MCHBAR8(0x130) & 0x1) != 0);
1607 ok |= sdram_checkrcompoverride();
1608 }
1609 if (!ok) {
1610 reg32a = MCHBAR32(0x13c);
1611 reg32b = (reg32a >> 16) & 0x0000ffff;
1612 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1613 reg32a |= (1 << 31) | (1 << 15);
1614 MCHBAR32(0x140) = reg32a;
1615 }
1616 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1617 hpet_udelay(1000);
1618 while ((MCHBAR8(0x130) & 0x1) != 0);
1619}
1620
1621static void __attribute__((noinline))
1622sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1623{
1624 u32 reg32;
1625
1626 reg32 = jval << 3;
1627 reg32 |= rank * 0x8000000;
1628 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | jmode;
1629 read32((void *)reg32);
1630 barrier();
1631 hpet_udelay(1); // 1us
1632}
1633
1634static void sdram_zqcl(struct sysinfo *s)
1635{
1636 if (s->boot_path == BOOT_PATH_RESUME) {
1637 MCHBAR32(0x260) = MCHBAR32(0x260) | (1 << 27);
1638 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0xe) | NORMAL_OP_CMD;
1639 MCHBAR8(0x271) = MCHBAR8(0x271) & ~0x30;
1640 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~((1 << 30) | (1 << 31))) |
1641 (1 << 30) | (1 << 31);
1642 }
1643}
1644
1645static void sdram_jedecinit(struct sysinfo *s)
1646{
1647 u8 r, i, ch;
1648 u16 reg16, mrs, rttnom;
1649 struct jedeclist {
1650 char debug[15];
1651 u8 cmd;
1652 u16 val;
1653 };
1654
Arthur Heymans6bf13012017-06-10 12:03:27 +02001655 static const struct jedeclist jedec[12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001656 { " NOP ", NOP_CMD, 0 },
1657 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1658 { " EMRS2 ", EMRS2_CMD, 0 },
1659 { " EMRS3 ", EMRS3_CMD, 0 },
1660 { " EMRS1 ", EMRS1_CMD, 0 },
1661 { " DLL RESET ", MRS_CMD, (1 << 8) },
1662 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1663 { " AUTOREFRESH", CBR_CMD, 0 },
1664 { " AUTOREFRESH", CBR_CMD, 0 },
1665 { " INITIALISE ", MRS_CMD, 0 },
1666 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1667 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1668 };
1669
1670 mrs = (s->selected_timings.CAS << 4) |
1671 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 1;
1672 rttnom = (1 << 2);
1673 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1674 rttnom |= (1 << 6);
1675 }
1676
1677 hpet_udelay(200); // 200us
1678 reg16 = 0;
1679 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1680 for (i = 0; i < 12; i++) {
1681 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1682 reg16 = jedec[i].val;
1683 switch (jedec[i].cmd) {
1684 case EMRS1_CMD:
1685 reg16 |= rttnom;
1686 break;
1687 case MRS_CMD:
1688 reg16 |= mrs;
1689 break;
1690 default:
1691 break;
1692 }
1693 sdram_jedec(s, r, jedec[i].cmd, reg16);
1694 PRINTK_DEBUG("done\n");
1695 }
1696 }
1697}
1698
1699static void sdram_misc(struct sysinfo *s)
1700{
1701 u32 reg32;
1702
1703 reg32 = 0;
1704 reg32 |= (0x4 << 13);
1705 reg32 |= (0x6 << 8);
1706 MCHBAR32(0x274) = (MCHBAR32(0x274) & ~0x3ff00) | reg32;
1707 MCHBAR8(0x274) = MCHBAR8(0x274) & ~(1 << 7);
1708 MCHBAR8(0x26c) = MCHBAR8(0x26c) | 1;
1709 if (s->boot_path != BOOT_PATH_RESUME) {
1710 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0xe) | NORMAL_OP_CMD;
1711 MCHBAR8(0x271) = MCHBAR8(0x271) & ~0x30;
1712 } else {
1713 sdram_zqcl(s);
1714 }
1715}
1716
1717static void sdram_checkreset(void)
1718{
1719 u8 pmcon2, pmcon3, reset;
1720
1721 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1722 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1723 pmcon3 &= ~0x2;
1724 if (pmcon2 & 0x80) {
1725 pmcon2 &= ~0x80;
1726 reset = 1;
1727 } else {
1728 pmcon2 |= 0x80;
1729 reset = 0;
1730 }
1731 if (pmcon2 & 0x4) {
1732 pmcon2 |= 0x4;
1733 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1734 pmcon3 |= (1 << 3);
1735 }
1736 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1737 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +02001738 if (reset)
1739 full_reset();
Damien Zammit003d15c2015-11-20 17:17:51 +11001740}
1741
1742static void sdram_dradrb(struct sysinfo *s)
1743{
1744 u8 i, reg8, ch, r;
1745 u32 reg32, ind, c0dra, c0drb, dra;
1746 u16 addr;
1747 i = 0;
Arthur Heymans6bf13012017-06-10 12:03:27 +02001748 static const u8 dratab[2][2][2][4] =
Damien Zammit003d15c2015-11-20 17:17:51 +11001749 {{
1750 {
1751 {0xff, 0xff, 0xff, 0xff},
1752 {0xff, 0x00, 0x02, 0xff}
1753 },
1754 {
1755 {0xff, 0x01, 0xff, 0xff},
1756 {0xff, 0x03, 0xff, 0x06}
1757 }
1758 },
1759 {
1760 {
1761 {0xff, 0xff, 0xff, 0xff},
1762 {0xff, 0x04, 0x06, 0x08}
1763 },
1764 {
1765 {0xff, 0xff, 0xff, 0xff},
1766 {0x05, 0x07, 0x09, 0xff}
1767 }
1768 }};
1769
Arthur Heymans6bf13012017-06-10 12:03:27 +02001770 static const u8 dradrb[10][6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001771 //Row Col Bank Width DRB
1772 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1773 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1774 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1775 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1776 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1777 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1778 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1779 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1780 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1781 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1782 };
1783
1784 reg32 = 0;
1785 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1786 i = r / 2;
1787 PRINTK_DEBUG("RANK %d PRESENT\n", r);
1788 dra = dratab[s->dimms[i].banks]
1789 [s->dimms[i].width]
1790 [s->dimms[i].cols - 9]
1791 [s->dimms[i].rows - 12];
1792
1793 if (s->dimms[i].banks == 1) {
1794 dra |= (1 << 7);
1795 }
1796 reg32 |= (dra << (r*8));
1797 }
1798 MCHBAR32(0x208) = reg32;
1799 c0dra = reg32;
1800 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1801
1802 reg32 = 0;
1803 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1804 reg32 |= (1 << r);
1805 }
1806 reg8 = (u8)(reg32 << 4) & 0xf0;
1807 MCHBAR8(0x262) = (MCHBAR8(0x262) & ~0xf0) | reg8;
1808 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) ||
1809 ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1810 MCHBAR8(0x260) = MCHBAR8(0x260) | 1;
1811 }
1812
1813 addr = 0x200;
1814 c0drb = 0;
1815 FOR_EACH_RANK(ch, r) {
1816 if (rank_is_populated(s->dimms, ch, r)) {
1817 ind = (c0dra >> (8*r)) & 0x7f;
1818 c0drb = (u16)(c0drb + dradrb[ind][5]);
1819 s->channel_capacity[0] += dradrb[ind][5] << 6;
1820 }
1821 MCHBAR16(addr) = c0drb;
1822 addr += 2;
1823 }
1824 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1825}
1826
1827static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1828{
Damien Zammit003d15c2015-11-20 17:17:51 +11001829 u8 dqsmatches = 1;
1830 while (count--) {
1831 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0x2;
1832 hpet_udelay(1);
1833 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
1834 hpet_udelay(1);
1835 barrier();
Elyes HAOUASaf159d42019-05-22 20:19:22 +02001836 read32((void *)strobeaddr);
Damien Zammit003d15c2015-11-20 17:17:51 +11001837 barrier();
1838 hpet_udelay(1);
1839
1840 if (((MCHBAR8(dqshighaddr) & 0x40) >> 6) != highlow) {
1841 dqsmatches = 0;
1842 }
1843 }
1844
1845 return dqsmatches;
1846}
1847
1848static void rcvenclock(u8 *coarse, u8 *medium, u8 bytelane)
1849{
1850 if (*medium < 3) {
1851 (*medium)++;
1852 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << (bytelane*2))))
1853 | (*medium << (bytelane*2));
1854 } else {
1855 *medium = 0;
1856 (*coarse)++;
1857 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (*coarse << 16);
1858 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~0x3 << (bytelane*2)))
1859 | (*medium << (bytelane*2));
1860 }
1861}
1862
1863static void sdram_rcven(struct sysinfo *s)
1864{
1865 u8 curcoarse, savecoarse;
1866 u8 curmedium, savemedium;
1867 u8 pi, savepi;
1868 u8 bytelane;
1869 u8 bytelanecoarse[8] = { 0 };
1870 u8 minbytelanecoarse = 0xff;
1871 u8 bytelaneoffset;
1872 u8 maxbytelane = 8;
Arthur Heymans015339f2018-08-20 11:28:58 +02001873 /* Since dra/drb is already set up we know that at address 0x00000000
1874 we will always find the first available rank */
1875 u32 strobeaddr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001876 u32 dqshighaddr;
1877
1878 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xc;
1879 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
1880
1881 PRINTK_DEBUG("rcven 0\n");
1882 for (bytelane = 0; bytelane < maxbytelane; bytelane++) {
1883 PRINTK_DEBUG("rcven bytelane %d\n", bytelane);
1884//trylaneagain:
1885 dqshighaddr = 0x561 + (bytelane << 2);
1886
1887 curcoarse = s->selected_timings.CAS + 1;
1888 pi = 0;
1889 curmedium = 0;
1890
1891 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (curcoarse << 16);
1892 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << (bytelane*2))))
1893 | (curmedium << (bytelane*2));
1894 MCHBAR8(0x560+bytelane*4) = MCHBAR8(0x560+bytelane*4) & ~0x3f;
1895
1896 savecoarse = curcoarse;
1897 savemedium = curmedium;
1898 savepi = pi;
1899
1900 PRINTK_DEBUG("rcven 0.1\n");
1901
1902 //MCHBAR16(0x588) = (MCHBAR16(0x588) & (u16)~(0x3 << (bytelane*2))) | (1 << (bytelane*2)); // XXX comment out
1903
1904 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1905 //printk(BIOS_DEBUG, "coarse=%d medium=%d\n", curcoarse, curmedium);
1906 rcvenclock(&curcoarse, &curmedium, bytelane);
1907 if (curcoarse > 0xf) {
1908 PRINTK_DEBUG("Error: coarse > 0xf\n");
1909 //goto trylaneagain;
1910 break;
1911 }
1912 }
1913 PRINTK_DEBUG("rcven 0.2\n");
1914
1915 savecoarse = curcoarse;
1916 savemedium = curmedium;
1917 rcvenclock(&curcoarse, &curmedium, bytelane);
1918
1919 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1920 savecoarse = curcoarse;
1921 savemedium = curmedium;
1922 rcvenclock(&curcoarse, &curmedium, bytelane);
1923 if (curcoarse > 0xf) {
1924 PRINTK_DEBUG("Error: coarse > 0xf\n");
1925 //goto trylaneagain;
1926 break;
1927 }
1928 }
1929
1930 PRINTK_DEBUG("rcven 0.3\n");
1931 curcoarse = savecoarse;
1932 curmedium = savemedium;
1933 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (curcoarse << 16);
1934 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << bytelane*2)))
1935 | (curmedium << (bytelane*2));
1936
1937 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1938 savepi = pi;
1939 pi++;
1940 if (pi > s->maxpi) {
1941 //if (s->nodll) {
1942 pi = savepi = s->maxpi;
1943 break;
1944 //}
1945 }
1946 MCHBAR8(0x560 + bytelane*4) = (MCHBAR8(0x560 + bytelane*4)
1947 & ~0x3f) | (pi << s->pioffset);
1948 }
1949 PRINTK_DEBUG("rcven 0.4\n");
1950
1951 pi = savepi;
1952 MCHBAR8(0x560 + bytelane*4) = (MCHBAR8(0x560 + bytelane*4) & ~0x3f)
1953 | (pi << s->pioffset);
1954 rcvenclock(&curcoarse, &curmedium, bytelane);
1955 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1956 PRINTK_DEBUG("Error: DQS not high\n");
1957 //goto trylaneagain;
1958 }
1959 PRINTK_DEBUG("rcven 0.5\n");
1960 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
1961 curcoarse--;
1962 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000)
1963 | (curcoarse << 16);
1964 if (curcoarse == 0) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +02001965 PRINTK_DEBUG("Error: DQS did not hit 0\n");
Damien Zammit003d15c2015-11-20 17:17:51 +11001966 break;
1967 }
1968 }
1969
1970 PRINTK_DEBUG("rcven 0.6\n");
1971 rcvenclock(&curcoarse, &curmedium, bytelane);
1972 s->pi[bytelane] = pi;
1973 bytelanecoarse[bytelane] = curcoarse;
1974 }
1975
1976 PRINTK_DEBUG("rcven 1\n");
1977
1978 bytelane = maxbytelane;
1979 do {
1980 bytelane--;
1981 if (minbytelanecoarse > bytelanecoarse[bytelane]) {
1982 minbytelanecoarse = bytelanecoarse[bytelane];
1983 }
1984 } while (bytelane != 0);
1985
1986 bytelane = maxbytelane;
1987 do {
1988 bytelane--;
1989 bytelaneoffset = bytelanecoarse[bytelane] - minbytelanecoarse;
1990 MCHBAR16(0x5fa) = (MCHBAR16(0x5fa) & (u16)(~(0x3 << (bytelane*2))))
1991 | (bytelaneoffset << (bytelane*2));
1992 } while (bytelane != 0);
1993
1994 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (minbytelanecoarse << 16);
1995
1996 s->coarsectrl = minbytelanecoarse;
1997 s->coarsedelay = MCHBAR16(0x5fa);
1998 s->mediumphase = MCHBAR16(0x58c);
1999 s->readptrdelay = MCHBAR16(0x588);
2000
2001 PRINTK_DEBUG("rcven 2\n");
2002 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xe;
2003 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
2004 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x4;
2005 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x8;
2006
2007 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2008 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
2009 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2010 PRINTK_DEBUG("rcven 3\n");
2011}
2012
2013static void sdram_mmap_regs(struct sysinfo *s)
2014{
2015 bool reclaim;
2016 u32 tsegsize;
2017 u32 mmiosize;
2018 u32 tom, tolud, touud, reclaimbase, reclaimlimit;
2019 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase;
2020 u16 ggc;
2021 u16 ggc_to_uma[10] = { 0, 1, 4, 8, 16, 32, 48, 64, 128, 256 };
2022 u8 ggc_to_gtt[4] = { 0, 1, 0, 0 };
2023
2024 reclaimbase = 0;
2025 reclaimlimit = 0;
2026 ggc = pci_read_config16(PCI_DEV(0,0,0), GGC);
Damien Zammit51fdb922016-01-18 18:34:52 +11002027 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
Damien Zammit003d15c2015-11-20 17:17:51 +11002028 gfxsize = ggc_to_uma[(ggc & 0xf0) >> 4];
Damien Zammit51fdb922016-01-18 18:34:52 +11002029 gttsize = ggc_to_gtt[(ggc & 0x300) >> 8];
Damien Zammit003d15c2015-11-20 17:17:51 +11002030 tom = s->channel_capacity[0];
2031
Arthur Heymansda44e342019-01-12 01:38:02 +01002032 /* with GTT always being 1M, TSEG 1M is the only setting that can
2033 be covered by SMRR which has alignment requirements. */
2034 tsegsize = 0x1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002035 mmiosize = 0x400; // 1GB
2036
2037 reclaim = false;
2038 tolud = MIN(0x1000 - mmiosize, tom);
2039 if ((tom - tolud) > 0x40) {
Arthur Heymansaaebb412017-08-27 18:46:12 +02002040 reclaim = true;
Damien Zammit003d15c2015-11-20 17:17:51 +11002041 }
2042 if (reclaim) {
2043 tolud = tolud & ~0x3f;
2044 tom = tom & ~0x3f;
2045 reclaimbase = MAX(0x1000, tom);
2046 reclaimlimit = reclaimbase + (MIN(0x1000, tom) - tolud) - 0x40;
2047 }
2048 touud = tom;
2049 if (reclaim) {
2050 touud = reclaimlimit + 0x40;
2051 }
2052
2053 gfxbase = tolud - gfxsize;
2054 gttbase = gfxbase - gttsize;
2055 tsegbase = gttbase - tsegsize;
2056
2057 /* Program the regs */
Damien Zammit51fdb922016-01-18 18:34:52 +11002058 pci_write_config16(PCI_DEV(0,0,0), TOLUD, (u16)(tolud << 4));
2059 pci_write_config16(PCI_DEV(0,0,0), TOM, (u16)(tom >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002060 if (reclaim) {
2061 pci_write_config16(PCI_DEV(0,0,0), 0x98, (u16)(reclaimbase >> 6));
2062 pci_write_config16(PCI_DEV(0,0,0), 0x9a, (u16)(reclaimlimit >> 6));
2063 }
Damien Zammit51fdb922016-01-18 18:34:52 +11002064 pci_write_config16(PCI_DEV(0,0,0), TOUUD, (u16)(touud));
2065 pci_write_config32(PCI_DEV(0,0,0), GBSM, gfxbase << 20);
2066 pci_write_config32(PCI_DEV(0,0,0), BGSM, gttbase << 20);
2067 pci_write_config32(PCI_DEV(0,0,0), TSEG, tsegbase << 20);
2068
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002069 u8 reg8 = pci_read_config8(PCI_DEV(0, 0, 0), ESMRAMC);
2070 reg8 &= ~0x7;
Arthur Heymansda44e342019-01-12 01:38:02 +01002071 reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002072 pci_write_config8(PCI_DEV(0, 0, 0), ESMRAMC, reg8);
2073
Damien Zammit51fdb922016-01-18 18:34:52 +11002074 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
2075 pci_read_config32(PCI_DEV(0,0,0), GBSM), gfxbase << 20);
2076 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
2077 pci_read_config32(PCI_DEV(0,0,0), BGSM), gttbase << 20);
2078 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
2079 pci_read_config32(PCI_DEV(0,0,0), TSEG), tsegbase << 20);
Damien Zammit003d15c2015-11-20 17:17:51 +11002080}
2081
2082static void sdram_enhancedmode(struct sysinfo *s)
2083{
2084 u8 reg8, ch, r, j, i;
2085 u32 mask32, reg32;
2086 MCHBAR8(0x246) = MCHBAR8(0x246) | 1;
2087 MCHBAR8(0x269 + 3) = MCHBAR8(0x269 + 3) | 1;
2088 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
2089 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2090 MCHBAR32(0x120) = (MCHBAR32(0x120) & ~mask32) | reg32;
2091 MCHBAR8(0x288 + 1) = 0x2;
2092 MCHBAR16(0x288 + 2) = 0x0804;
2093 MCHBAR16(0x288 + 4) = 0x2010;
2094 MCHBAR8(0x288 + 6) = 0x40;
2095 MCHBAR16(0x288 + 8) = 0x091c;
2096 MCHBAR8(0x288 + 10) = 0xf2;
2097 MCHBAR8(0x241) = MCHBAR8(0x241) | 1;
2098 MCHBAR8(0x243) = MCHBAR8(0x243) | 1;
2099 MCHBAR16(0x272) = MCHBAR16(0x272) | 0x100;
2100
2101 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf0);
2102 pci_write_config8(PCI_DEV(0,0,0), 0xf0, reg8 | 1);
2103 MCHBAR32(0xfa0) = 0x00000002;
2104 MCHBAR32(0xfa4) = 0x20310002;
2105 MCHBAR32(0x24) = 0x02020302;
2106 MCHBAR32(0x30) = 0x001f1806;
2107 MCHBAR32(0x34) = 0x01102800;
2108 MCHBAR32(0x38) = 0x07000000;
2109 MCHBAR32(0x3c) = 0x01014010;
2110 MCHBAR32(0x40) = 0x0f038000;
2111 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf0);
2112 pci_write_config8(PCI_DEV(0,0,0), 0xf0, reg8 & ~1);
2113
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002114 u32 nranks, curranksize, maxranksize, dra;
2115 u8 rankmismatch;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002116 static const u8 drbtab[10] = { 0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8,
2117 0x20, 0x10 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002118
2119 nranks = 0;
2120 curranksize = 0;
2121 maxranksize = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002122 rankmismatch = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002123 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2124 nranks++;
2125 dra = (u8) ((MCHBAR32(0x208) >> (8*r)) & 0x7f);
2126 curranksize = drbtab[dra];
2127 if (maxranksize == 0) {
2128 maxranksize = curranksize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002129 }
2130 if (curranksize != maxranksize) {
2131 rankmismatch = 1;
2132 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002133 }
2134
2135 reg8 = 0;
2136 switch (nranks) {
2137 case 4:
2138 if (rankmismatch) {
2139 reg8 = 0x64;
2140 } else {
2141 reg8 = 0xa4;
2142 }
2143 break;
2144 case 1:
2145 case 3:
2146 reg8 = 0x64;
2147 break;
2148 case 2:
2149 if (rankmismatch) {
2150 reg8 = 0x64;
2151 } else {
2152 reg8 = 0x24;
2153 }
2154 break;
2155 default:
2156 die("Invalid number of ranks found, halt\n");
2157 break;
2158 }
2159 MCHBAR8(0x111) = (MCHBAR8(0x111) & ~0xfc) | (reg8 & 0xfc);
2160 MCHBAR32(0xd0) = MCHBAR32(0xd0) & ~0x80000000;
2161
2162 MCHBAR32(0x28) = 0xf;
2163 MCHBAR8(0x2c4) = MCHBAR8(0x2c4) | 1;
2164
2165 MCHBAR32(0x3c) = MCHBAR32(0x3c) & ~0xe000000;
2166 MCHBAR32(0x40) = (MCHBAR32(0x40) & ~0xc0000) | 0x40000;
2167 u32 clkcx[2][2][3] = {
2168 {
2169 {0, 0x0c080302, 0x08010204}, // 667
2170 {0x02040000, 0x08100102, 0}
2171 },
2172 {
2173 {0x18000000, 0x3021060c, 0x20010208},
2174 {0, 0x0c090306, 0} // 800
2175 }
2176 };
2177 j = s->selected_timings.fsb_clock;
2178 i = s->selected_timings.mem_clock;
2179
2180 MCHBAR32(0x708) = clkcx[j][i][0];
2181 MCHBAR32(0x70c) = clkcx[j][i][1];
2182 MCHBAR32(0x6dc) = clkcx[j][i][2];
2183 MCHBAR8(0x40) = MCHBAR8(0x40) & ~0x2;
2184}
2185
2186static void sdram_periodic_rcomp(void)
2187{
2188 MCHBAR8(0x130) = MCHBAR8(0x130) & ~0x2;
2189 while ((MCHBAR32(0x130) & 0x80000000) > 0) {
2190 ;
2191 }
2192 MCHBAR16(0x1b4) = (MCHBAR16(0x1b4) & ~0x3000);
2193
2194 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) | 0x80;
2195 MCHBAR16(0x170) = (MCHBAR16(0x170) & ~0xf) | 0x9;
2196
2197 MCHBAR8(0x130) = MCHBAR8(0x130) | 0x82;
2198}
2199
2200static void sdram_new_trd(struct sysinfo *s)
2201{
2202 u8 pidelay, i, j, k, cc, trd_perphase[5];
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002203 u8 bypass, freqgb, trd, reg8, txfifo;
Damien Zammit003d15c2015-11-20 17:17:51 +11002204 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2205 u16 tmclk, thclk, buffertocore, postcalib;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002206 static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2207 static const u16 trd_adjust[2][2][5] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11002208 {
2209 {3000, 3000, 0,0,0},
2210 {1000,2000,3000,1500,2500}
2211 },
2212 {
2213 {2000,1000,3000,0,0},
2214 {2500, 2500, 0,0,0}
2215 }};
2216
2217 freqgb = 110;
2218 buffertocore = 5000;
Damien Zammit003d15c2015-11-20 17:17:51 +11002219 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2220 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2221 tmclk = tmclk * 100 / freqgb;
2222 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2223 switch (s->selected_timings.mem_clock) {
2224 case MEM_CLOCK_667MHz:
2225 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2226 cc = 2;
2227 } else {
2228 cc = 3;
2229 }
2230 break;
2231 default:
2232 case MEM_CLOCK_800MHz:
2233 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2234 cc = 5;
2235 } else {
2236 cc = 2;
2237 }
2238 break;
2239 }
2240 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2241 maxrcvendelay = 0;
2242 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2243
2244 for (i = 0; i < 8; i++) {
2245 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 0x3) * (u32)(tmclk));
2246 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 0x3) * (u32)(tmclk) / 2);
2247 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 0x3) * (u32)(tmclk) / 4);
2248 rcvendelay += (u32)(pidelay * s->pi[i]);
2249 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2250 }
2251
2252 if ((MCHBAR8(0xc54+3) == 0xff) && (MCHBAR8(0xc08) & 0x80)) {
2253 bypass = 1;
2254 } else {
2255 bypass = 0;
2256 }
2257
2258 txfifo = 0;
2259 reg8 = (MCHBAR8(0x188) & 0xe) >> 1;
2260 txfifo = txfifo_lut[reg8] & 0x7;
2261
2262 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2263 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2264 if (s->async) {
2265 datadelay += tmclk / 2;
2266 }
2267
2268 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2269 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2270
2271 if (j == 0 && k == 0) {
2272 datadelay -= 3084;
2273 }
2274
2275 trd = 0;
2276 for (i = 0; i < cc; i++) {
2277 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2278 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2279 trd_perphase[i] += 1;
2280 if (trd_perphase[i] > trd) {
2281 trd = trd_perphase[i];
2282 }
2283 }
2284
2285 MCHBAR16(0x248) = (MCHBAR16(0x248) & ~0x1f00) | (trd << 8);
2286}
2287
2288static void sdram_powersettings(struct sysinfo *s)
2289{
2290 u8 j;
2291 u32 reg32;
2292
2293 /* Thermal sensor */
2294 MCHBAR8(0x3808) = 0x9b;
2295 MCHBAR32(0x380c) = (MCHBAR32(0x380c) & ~0x00ffffff) | 0x1d00;
2296 MCHBAR8(0x3814) = 0x08;
2297 MCHBAR8(0x3824) = 0x00;
2298 MCHBAR8(0x3809) = (MCHBAR8(0x3809) & ~0xf) | 0x4;
2299 MCHBAR8(0x3814) = (MCHBAR8(0x3814) & ~1) | 1;
2300 MCHBAR8(0x3812) = (MCHBAR8(0x3812) & ~0x80) | 0x80;
2301
2302 /* Clock gating */
2303 MCHBAR32(0xf18) = MCHBAR32(0xf18) & ~0x00040001;
2304 MCHBAR8(0xfac+3) = MCHBAR8(0xfac+3) & ~0x80;
2305 MCHBAR8(0xff8+3) = MCHBAR8(0xff8+3) & ~0x80;
2306 MCHBAR16(0xff0) = MCHBAR16(0xff0) & ~0x1fff;
2307 MCHBAR32(0xfb0) = MCHBAR32(0xfb0) & ~0x0001ffff;
2308 MCHBAR16(0x48) = (MCHBAR16(0x48) & ~0x03ff) & 0x6;
2309 MCHBAR32(0x20) = (MCHBAR32(0x20) & ~0xffffffff) | 0x20;
2310 MCHBAR8(0xd14) = MCHBAR8(0xd14) & ~1;
2311 MCHBAR8(0x239) = s->selected_timings.CAS - 1 + 0x15;
2312 MCHBAR16(0x2d1) = (MCHBAR16(0x2d1) & ~0x07fc) | 0x40;
2313 MCHBAR16(0x6d1) = (MCHBAR16(0x6d1) & ~0x0fff) | 0xd00;
2314 MCHBAR16(0x210) = MCHBAR16(0x210) & ~0x0d80;
2315 MCHBAR16(0xf6c+2) = 0xffff;
2316
2317 /* Sequencing */
2318 MCHBAR32(0x14) = (MCHBAR32(0x14) & ~0x1fffffff) | 0x1f643fff;
2319 MCHBAR32(0x18) = (MCHBAR32(0x18) & ~0xffffff7f) | 0x02010000;
2320 MCHBAR16(0x1c) = (MCHBAR16(0x1c) & ~0x7000) | (0x3 << 12);
2321
2322 /* Power */
2323 MCHBAR32(0x1104) = (MCHBAR32(0x1104) & ~0xffff0003) | 0x10100000;
2324 MCHBAR32(0x1108) = (MCHBAR32(0x1108) & ~0x0001bff7) | 0x00000078;
2325 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2326 MCHBAR16(0x110c) = (MCHBAR16(0x110c) & ~0x03ff) | 0xc8;
2327 } else {
2328 MCHBAR16(0x110c) = (MCHBAR16(0x110c) & ~0x03ff) | 0x100;
2329 }
2330 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2331
2332 MCHBAR32(0x1110) = (MCHBAR32(0x1110) & ~0x1fff37f) | 0x10810700;
2333 MCHBAR8(0x1114) = (MCHBAR8(0x1114) & ~0x07) | 1;
2334 MCHBAR8(0x1124) = MCHBAR8(0x1124) & ~0x02;
2335
Arthur Heymans6bf13012017-06-10 12:03:27 +02002336 static const u16 ddr2lut[2][4][2] = {{
Damien Zammit003d15c2015-11-20 17:17:51 +11002337 {0x0000, 0x0000},
2338 {0x019A, 0x0039},
2339 {0x0099, 0x1049},
2340 {0x0000, 0x0000}
2341 },
2342 {
2343 {0x0000, 0x0000},
2344 {0x019A, 0x0039},
2345 {0x0099, 0x1049},
2346 {0x0099, 0x2159}
2347 }};
2348
2349 MCHBAR16(0x23c) = 0x7a89;
2350 MCHBAR8(0x117) = 0xaa;
2351 MCHBAR16(0x118) = ddr2lut[j][s->selected_timings.CAS - 3][1];
2352 MCHBAR16(0x115) = (MCHBAR16(0x115) & ~0x7fff) | ddr2lut[j]
2353 [s->selected_timings.CAS - 3][0];
2354 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0xf000) | 0xf000;
2355 MCHBAR8(0x2c02) = (MCHBAR8(0x2c02) & ~0x77) | (4 << 4 | 4);
2356 if (s->nodll) {
2357 reg32 = 0x30000000;
2358 } else {
2359 reg32 = 0;
2360 }
2361 MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0x0f000000) | 0x20000000 | reg32;
2362 MCHBAR32(0x2d1) = (MCHBAR32(0x2d1) & ~0x00f00000) | 0x00f00000;
2363 MCHBAR32(0x6d0) = (MCHBAR32(0x6d0) & ~0x001ff000) | (0xbf << 20);
2364 MCHBAR16(0x610) = (MCHBAR16(0x610) & ~0x1f7f) | (0xb << 8) | (7 << 4) | 0xb;
2365 MCHBAR16(0x612) = 0x3264;
2366 MCHBAR16(0x614) = (MCHBAR16(0x614) & ~0x3f3f) | (0x14 << 8) | 0xa;
2367
2368 MCHBAR32(0x6c0) = MCHBAR32(0x6c0) | 0x80002000;
2369}
2370
2371static void sdram_programddr(void)
2372{
2373 MCHBAR16(0x6d1) = (MCHBAR16(0x6d1) & ~0x03ff) | 0x100;
2374 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0x003f) | 0x10;
2375 MCHBAR16(0x2d1) = (MCHBAR16(0x2d1) & ~0x7000) | 0x2000;
2376 MCHBAR8(0x180) = MCHBAR8(0x180) & ~0xe;
2377 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0xc;
2378 MCHBAR8(0x561) = MCHBAR8(0x561) & ~0xe;
2379 MCHBAR8(0x565) = MCHBAR8(0x565) & ~0xe;
2380 MCHBAR8(0x569) = MCHBAR8(0x569) & ~0xe;
2381 MCHBAR8(0x56d) = MCHBAR8(0x56d) & ~0xe;
2382 MCHBAR8(0x571) = MCHBAR8(0x571) & ~0xe;
2383 MCHBAR8(0x575) = MCHBAR8(0x575) & ~0xe;
2384 MCHBAR8(0x579) = MCHBAR8(0x579) & ~0xe;
2385 MCHBAR8(0x57d) = MCHBAR8(0x57d) & ~0xe;
2386 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0x2;
2387 MCHBAR16(0x1b4) = MCHBAR16(0x1b4) & ~0x400;
2388 MCHBAR16(0x210) = MCHBAR16(0x210) & ~0xdc0;
2389 MCHBAR8(0x239) = MCHBAR8(0x239) & ~0x80;
2390 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~(1 << 22);
2391 MCHBAR16(0x2d1) = MCHBAR16(0x2d1) & ~0x80fc;
2392 MCHBAR16(0x6d1) = MCHBAR16(0x6d1) & ~0xc00;
2393 MCHBAR8(0x180) = MCHBAR8(0x180) & ~0xd;
2394 MCHBAR8(0x561) = MCHBAR8(0x561) & ~1;
2395 MCHBAR8(0x565) = MCHBAR8(0x565) & ~1;
2396 MCHBAR8(0x569) = MCHBAR8(0x569) & ~1;
2397 MCHBAR8(0x56d) = MCHBAR8(0x56d) & ~1;
2398 MCHBAR8(0x571) = MCHBAR8(0x571) & ~1;
2399 MCHBAR8(0x575) = MCHBAR8(0x575) & ~1;
2400 MCHBAR8(0x579) = MCHBAR8(0x579) & ~1;
2401 MCHBAR8(0x57d) = MCHBAR8(0x57d) & ~1;
2402 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0x700000) | (0x3 << 20);
2403 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~0x100000;
2404 MCHBAR8(0x592) = MCHBAR8(0x592) | 0x1e;
2405 MCHBAR8(0x2c15) = MCHBAR8(0x2c15) | 0x3;
2406 MCHBAR32(0x62c) = (MCHBAR32(0x62c) & ~0xc000000) | 0x4000000;
2407 MCHBAR16(0x248) = MCHBAR16(0x248) | 0x6000;
2408 MCHBAR32(0x260) = MCHBAR32(0x260) | 0x10000;
2409 MCHBAR8(0x2c0) = MCHBAR8(0x2c0) | 0x10;
2410 MCHBAR32(0x2d0) = MCHBAR32(0x2d0) | (0xf << 24);
2411 MCHBAR8(0x189) = MCHBAR8(0x189) | 0x7;
2412 MCHBAR8(0x592) = MCHBAR8(0x592) | 0xc0;
2413 MCHBAR8(0x124) = MCHBAR8(0x124) | 0x7;
2414 MCHBAR16(0x12a) = (MCHBAR16(0x12a) & ~0xffff) | 0x0080;
2415 MCHBAR8(0x12c) = (MCHBAR8(0x12c) & ~0xff) | 0x10;
2416 MCHBAR16(0x2c0) = MCHBAR16(0x2c0) | 0x1e0;
2417 MCHBAR8(0x189) = MCHBAR8(0x189) | 0x18;
2418 MCHBAR8(0x193) = MCHBAR8(0x193) | 0xd;
2419 MCHBAR16(0x212) = MCHBAR16(0x212) | 0xa3f;
2420 MCHBAR8(0x248) = MCHBAR8(0x248) | 0x3;
2421 MCHBAR8(0x268) = (MCHBAR8(0x268) & ~0xff) | 0x4a;
2422 MCHBAR8(0x2c4) = MCHBAR8(0x2c4) & ~0x60;
2423 MCHBAR16(0x592) = MCHBAR16(0x592) | 0x321;
2424}
2425
2426static void sdram_programdqdqs(struct sysinfo *s)
2427{
2428 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2429 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2430 u8 repeat, halfclk, feature, reg8, push;
2431 u16 cwb, pimdclk;
2432 u32 reg32;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002433 static const u8 txfifotab[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002434
2435 tpi = 3000;
2436 dqdqs_out = 4382;
2437 dqdqs_outdelay = 5083;
2438 dqdqs_delay = 4692;
2439 coretomcp = 0;
2440 txdelay = 0;
2441 halfclk = 0;
2442 tmaxunmask = 0;
2443 tmaxpi = 0;
2444 repeat = 2;
2445 feature = 0;
2446 cwb = 0;
2447 pimdclk = 0;
2448 reg32 = 0;
2449 push = 0;
2450 reg8 = 0;
2451
2452 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2453 refclk = 3000 - mdclk;
2454
2455 coretomcp = ((MCHBAR8(0x246) >> 2) & 0x3) + 1;
2456 coretomcp *= mdclk;
2457
2458 reg8 = (MCHBAR8(0x188) & 0xe) >> 1;
2459
2460 while (repeat) {
2461 txdelay = mdclk * (
2462 ((MCHBAR16(0x220) >> 8) & 0x7) +
2463 (MCHBAR8(0x24d) & 0xf) +
2464 (MCHBAR8(0x24e) & 0x1)
2465 ) +
2466 txfifotab[reg8]*(mdclk/2) +
2467 coretomcp +
2468 refclk +
2469 cwb;
2470 halfclk = (MCHBAR8(0x5d9) >> 1) & 0x1;
2471 if (halfclk) {
2472 txdelay -= mdclk / 2;
2473 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2474 } else {
2475 reg32 = dqdqs_outdelay + coretomcp;
2476 }
2477
2478 tmaxunmask = txdelay - mdclk - dqdqs_out;
2479 tmaxpi = tmaxunmask - tpi;
2480
2481 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2482 if (repeat == 2) {
2483 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) & ~(1 << 23);
2484 }
2485 feature = 1;
2486 repeat = 0;
2487 } else {
2488 repeat--;
2489 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) | (1 << 23);
2490 cwb = 2 * mdclk;
2491 }
2492 }
2493
2494 if (!feature) {
2495 MCHBAR8(0x2d1) = MCHBAR8(0x2d1) & ~0x3;
2496 return;
2497 }
2498 MCHBAR8(0x2d1) = MCHBAR8(0x2d1) | 0x3;
2499 MCHBAR16(0x210) = (MCHBAR16(0x210) & ~0xf000) | (pimdclk << 12);
2500 MCHBAR8(0x2c02) = (MCHBAR8(0x2c02) & ~0x77) | (push << 4) | push;
2501 MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0xf000000) | 0x3000000;
2502}
2503
2504/**
2505 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2506 */
2507void sdram_initialize(int boot_path, const u8 *spd_addresses)
2508{
2509 struct sysinfo si;
2510 u8 reg8;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002511 const char *boot_str[] = { "Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002512
2513 PRINTK_DEBUG("Setting up RAM controller.\n");
2514
2515 memset(&si, 0, sizeof(si));
2516
2517 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002518 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002519 si.spd_map[0] = spd_addresses[0];
2520 si.spd_map[1] = spd_addresses[1];
2521 si.spd_map[2] = spd_addresses[2];
2522 si.spd_map[3] = spd_addresses[3];
2523
2524 sdram_read_spds(&si);
2525
2526 /* Choose Common Frequency */
2527 sdram_detect_ram_speed(&si);
2528
2529 /* Determine smallest common tRAS, tRP, tRCD, etc */
2530 sdram_detect_smallest_params(&si);
2531
2532 /* Enable HPET */
2533 enable_hpet();
Damien Zammit003d15c2015-11-20 17:17:51 +11002534
2535 MCHBAR16(0xc1c) = MCHBAR16(0xc1c) | (1 << 15);
2536
Damien Zammit003d15c2015-11-20 17:17:51 +11002537 sdram_clk_crossing(&si);
2538
2539 sdram_checkreset();
2540 PRINTK_DEBUG("Done checkreset\n");
2541
2542 sdram_clkmode(&si);
2543 PRINTK_DEBUG("Done clkmode\n");
2544
2545 sdram_timings(&si);
2546 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2547
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002548 if (si.boot_path != BOOT_PATH_RESET) {
2549 sdram_dlltiming(&si);
2550 PRINTK_DEBUG("Done dlltiming\n");
2551 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002552
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002553 if (si.boot_path != BOOT_PATH_RESET) {
2554 sdram_rcomp(&si);
2555 PRINTK_DEBUG("Done RCOMP\n");
2556 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002557
2558 sdram_odt(&si);
2559 PRINTK_DEBUG("Done odt\n");
2560
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002561 if (si.boot_path != BOOT_PATH_RESET) {
2562 while ((MCHBAR8(0x130) & 0x1) != 0)
2563 ;
2564 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002565
2566 sdram_mmap(&si);
2567 PRINTK_DEBUG("Done mmap\n");
2568
2569 // Enable DDR IO buffer
2570 MCHBAR8(0x5dd) = (MCHBAR8(0x5dd) & ~0x3f) | 0x8;
2571 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x1;
2572
2573 sdram_rcompupdate(&si);
2574 PRINTK_DEBUG("Done RCOMP update\n");
2575
2576 MCHBAR8(0x40) = MCHBAR8(0x40) | 0x2;
2577
2578 if (si.boot_path != BOOT_PATH_RESUME) {
2579 MCHBAR32(0x260) = MCHBAR32(0x260) | (1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002580
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002581 sdram_jedecinit(&si);
2582 PRINTK_DEBUG("Done MRS\n");
2583 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002584
2585 sdram_misc(&si);
2586 PRINTK_DEBUG("Done misc\n");
2587
2588 sdram_zqcl(&si);
2589 PRINTK_DEBUG("Done zqcl\n");
2590
2591 if (si.boot_path != BOOT_PATH_RESUME) {
2592 MCHBAR32(0x268) = MCHBAR32(0x268) | 0xc0000000;
2593 }
2594
2595 sdram_dradrb(&si);
2596 PRINTK_DEBUG("Done dradrb\n");
2597
2598 sdram_rcven(&si);
2599 PRINTK_DEBUG("Done rcven\n");
2600
2601 sdram_new_trd(&si);
2602 PRINTK_DEBUG("Done tRD\n");
2603
2604 sdram_mmap_regs(&si);
2605 PRINTK_DEBUG("Done mmap regs\n");
2606
2607 sdram_enhancedmode(&si);
2608 PRINTK_DEBUG("Done enhanced mode\n");
2609
2610 sdram_powersettings(&si);
2611 PRINTK_DEBUG("Done power settings\n");
2612
2613 sdram_programddr();
2614 PRINTK_DEBUG("Done programming ddr\n");
2615
2616 sdram_programdqdqs(&si);
2617 PRINTK_DEBUG("Done programming dqdqs\n");
2618
2619 sdram_periodic_rcomp();
2620 PRINTK_DEBUG("Done periodic RCOMP\n");
2621
2622 /* Set init done */
2623 MCHBAR32(0x268) = MCHBAR32(0x268) | 0x40000000;
2624
2625 /* Tell ICH7 that we're done */
2626 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
2627 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8 & ~0x80);
2628
2629 /* Tell northbridge we're done */
2630 reg8 = pci_read_config8(PCI_DEV(0,0,0), 0xf4);
2631 pci_write_config8(PCI_DEV(0,0,0), 0xf4, reg8 | 1);
2632
2633 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2634}