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