blob: 144905fb92ec05ba28afa95506691c638d10d5cd [file] [log] [blame]
Damien Zammit003d15c2015-11-20 17:17:51 +11001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2015 Damien Zammit <damien@zamaudio.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <arch/io.h>
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +020018#include <cf9_reset.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020019#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020020#include <device/pci_ops.h>
Damien Zammit003d15c2015-11-20 17:17:51 +110021#include <console/console.h>
22#include <cpu/x86/cache.h>
Damien Zammit003d15c2015-11-20 17:17:51 +110023#include <delay.h>
Damien Zammit003d15c2015-11-20 17:17:51 +110024#include <lib.h>
25#include "pineview.h"
26#include "raminit.h"
Damien Zammit003d15c2015-11-20 17:17:51 +110027#include <spd.h>
28#include <string.h>
29
30/* Debugging macros. */
Julius Wernercd49cce2019-03-05 16:53:33 -080031#if CONFIG(DEBUG_RAM_SETUP)
Damien Zammit003d15c2015-11-20 17:17:51 +110032#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
33#else
34#define PRINTK_DEBUG(x...)
35#endif
36
37#define MAX_TCLK_667 0x30
38#define MAX_TCLK_800 0x25
39#define MAX_TAC_667 0x45
40#define MAX_TAC_800 0x40
41
42#define NOP_CMD (1 << 1)
43#define PRE_CHARGE_CMD (1 << 2)
44#define MRS_CMD ((1 << 2) | (1 << 1))
45#define EMRS_CMD (1 << 3)
46#define EMRS1_CMD (EMRS_CMD | (1 << 4))
47#define EMRS2_CMD (EMRS_CMD | (1 << 5))
48#define EMRS3_CMD (EMRS_CMD | (1 << 5) | (1 << 4))
49#define ZQCAL_CMD ((1 << 3) | (1 << 1))
50#define CBR_CMD ((1 << 3) | (1 << 2))
51#define NORMAL_OP_CMD ((1 << 3) | (1 << 2) | (1 << 1))
52
53#define UBDIMM 1
54#define SODIMM 2
55
56#define TOTAL_CHANNELS 1
57#define TOTAL_DIMMS 2
58
59#define DIMM_IS_POPULATED(dimms, idx) (dimms[idx].card_type != 0)
60#define IF_DIMM_POPULATED(dimms, idx) if (dimms[idx].card_type != 0)
Elyes HAOUASa342f392018-10-17 10:56:26 +020061#define ONLY_DIMMA_IS_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110062 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
63 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3)))
Elyes HAOUASa342f392018-10-17 10:56:26 +020064#define ONLY_DIMMB_IS_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110065 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3) && \
66 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2)))
Elyes HAOUASa342f392018-10-17 10:56:26 +020067#define BOTH_DIMMS_ARE_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110068 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
69 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3))))
70#define FOR_EACH_DIMM(idx) \
71 for (idx = 0; idx < TOTAL_DIMMS; ++idx)
72#define FOR_EACH_POPULATED_DIMM(dimms, idx) \
73 FOR_EACH_DIMM(idx) IF_DIMM_POPULATED(dimms, idx)
74#define CHANNEL_IS_POPULATED(dimms, idx) ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0))
75#define CHANNEL_IS_CARDF(dimms, idx) ((dimms[idx<<1].card_type == 0xf) || (dimms[(idx<<1) + 1].card_type == 0xf))
76#define IF_CHANNEL_POPULATED(dimms, idx) if ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0))
77#define FOR_EACH_CHANNEL(idx) \
78 for (idx = 0; idx < TOTAL_CHANNELS; ++idx)
79#define FOR_EACH_POPULATED_CHANNEL(dimms, idx) \
80 FOR_EACH_CHANNEL(idx) IF_CHANNEL_POPULATED(dimms, idx)
81
82#define RANKS_PER_CHANNEL 4
83
84#define FOR_EACH_RANK_IN_CHANNEL(r) \
85 for (r = 0; r < RANKS_PER_CHANNEL; ++r)
86#define FOR_EACH_POPULATED_RANK_IN_CHANNEL(dimms, ch, r) \
87 FOR_EACH_RANK_IN_CHANNEL(r) if (rank_is_populated(dimms, ch, r))
88#define FOR_EACH_RANK(ch, r) \
89 FOR_EACH_CHANNEL(ch) FOR_EACH_RANK_IN_CHANNEL(r)
90#define FOR_EACH_POPULATED_RANK(dimms, ch, r) \
91 FOR_EACH_RANK(ch, r) if (rank_is_populated(dimms, ch, r))
92
93static bool rank_is_populated(struct dimminfo dimms[], u8 ch, u8 r)
94{
95 return ((dimms[ch<<1].card_type && ((r) < dimms[ch<<1].ranks))
96 || (dimms[(ch<<1) + 1].card_type
97 && ((r) >= 2)
98 && ((r) < (dimms[(ch<<1) + 1].ranks + 2))));
99}
100
101static inline void barrier(void)
102{
103 __asm__ __volatile__("": : :"memory");
104}
105
Elyes HAOUASb60920d2018-09-20 17:38:38 +0200106static inline int spd_read_byte(unsigned int device, unsigned int address)
Damien Zammit003d15c2015-11-20 17:17:51 +1100107{
108 return smbus_read_byte(device, address);
109}
110
Arthur Heymans097d7532017-04-17 10:14:32 +0200111static int decode_spd(struct dimminfo *d, int i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100112{
113 d->type = 0;
114 if (d->spd_data[20] == 0x2) {
115 d->type = UBDIMM;
116 } else if (d->spd_data[20] == 0x4) {
117 d->type = SODIMM;
118 }
119 d->sides = (d->spd_data[5] & 0x7) + 1;
120 d->banks = (d->spd_data[17] >> 2) - 1;
121 d->chip_capacity = d->banks;
122 d->rows = d->spd_data[3];// - 12;
123 d->cols = d->spd_data[4];// - 9;
124 d->cas_latencies = 0x78;
125 d->cas_latencies &= d->spd_data[18];
126 if (d->cas_latencies == 0)
127 d->cas_latencies = 7;
128 d->tAAmin = d->spd_data[26];
129 d->tCKmin = d->spd_data[25];
130 d->width = (d->spd_data[13] >> 3) - 1;
131 d->page_size = (d->width+1) * (1 << d->cols); // Bytes
132 d->tRAS = d->spd_data[30];
133 d->tRP = d->spd_data[27];
134 d->tRCD = d->spd_data[29];
135 d->tWR = d->spd_data[36];
136 d->ranks = d->sides; // XXX
Julius Wernercd49cce2019-03-05 16:53:33 -0800137#if CONFIG(DEBUG_RAM_SETUP)
Arthur Heymans097d7532017-04-17 10:14:32 +0200138 const char *ubso[2] = { "UB", "SO" };
Damien Zammit003d15c2015-11-20 17:17:51 +1100139#endif
140 PRINTK_DEBUG("%s-DIMM %d\n", &ubso[d->type][0], i);
141 PRINTK_DEBUG(" Sides : %d\n", d->sides);
142 PRINTK_DEBUG(" Banks : %d\n", d->banks);
143 PRINTK_DEBUG(" Ranks : %d\n", d->ranks);
144 PRINTK_DEBUG(" Rows : %d\n", d->rows);
145 PRINTK_DEBUG(" Cols : %d\n", d->cols);
146 PRINTK_DEBUG(" Page size : %d\n", d->page_size);
147 PRINTK_DEBUG(" Width : %d\n", (d->width + 1) * 8);
148
149 return 0;
150}
151
152/* Ram Config: DIMMB-DIMMA
153 * 0 EMPTY-EMPTY
154 * 1 EMPTY-x16SS
155 * 2 EMPTY-x16DS
156 * 3 x16SS-x16SS
157 * 4 x16DS-x16DS
158 * 5 EMPTY- x8DS
159 * 6 x8DS - x8DS
160 */
161static void find_ramconfig(struct sysinfo *s, u32 chan)
162{
163 if (s->dimms[chan>>1].sides == 0) {
164 // NC
165 if (s->dimms[(chan>>1) + 1].sides == 0) {
166 // NC/NC
167 s->dimm_config[chan] = 0;
168 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
169 // NC/SS
170 if (s->dimms[(chan>>1) + 1].width == 0) {
171 // NC/8SS
172 s->dimm_config[chan] = 1;
173 } else {
174 // NC/16SS
175 s->dimm_config[chan] = 1;
176 }
177 } else {
178 // NC/DS
179 if (s->dimms[(chan>>1) + 1].width == 0) {
180 // NC/8DS
181 s->dimm_config[chan] = 5;
182 } else {
183 // NC/16DS
184 s->dimm_config[chan] = 2;
185 }
186 }
187 } else if (s->dimms[chan>>1].sides == 1) {
188 // SS
189 if (s->dimms[(chan>>1) + 1].sides == 0) {
190 // SS/NC
191 if (s->dimms[chan>>1].width == 0) {
192 // 8SS/NC
193 s->dimm_config[chan] = 1;
194 } else {
195 // 16SS/NC
196 s->dimm_config[chan] = 1;
197 }
198 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
199 // SS/SS
200 if (s->dimms[chan>>1].width == 0) {
201 if (s->dimms[(chan>>1) + 1].width == 0) {
202 // 8SS/8SS
203 s->dimm_config[chan] = 3;
204 } else {
205 // 8SS/16SS
206 die("Mixed Not supported\n");
207 }
208 } else {
209 if (s->dimms[(chan>>1) + 1].width == 0) {
210 // 16SS/8SS
211 die("Mixed Not supported\n");
212 } else {
213 // 16SS/16SS
214 s->dimm_config[chan] = 3;
215 }
216 }
217 } else {
218 // SS/DS
219 if (s->dimms[chan>>1].width == 0) {
220 if (s->dimms[(chan>>1) + 1].width == 0) {
221 // 8SS/8DS
222 die("Mixed Not supported\n");
223 } else {
224 die("Mixed Not supported\n");
225 }
226 } else {
227 if (s->dimms[(chan>>1) + 1].width == 0) {
228 // 16SS/8DS
229 die("Mixed Not supported\n");
230 } else {
231 die("Mixed Not supported\n");
232 }
233 }
234 }
235 } else {
236 // DS
237 if (s->dimms[(chan>>1) + 1].sides == 0) {
238 // DS/NC
239 if (s->dimms[chan>>1].width == 0) {
240 // 8DS/NC
241 s->dimm_config[chan] = 5;
242 } else {
243 s->dimm_config[chan] = 4;
244 }
245 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
246 // DS/SS
247 if (s->dimms[chan>>1].width == 0) {
248 if (s->dimms[(chan>>1) + 1].width == 0) {
249 // 8DS/8SS
250 die("Mixed Not supported\n");
251 } else {
252 // 8DS/16SS
253 die("Mixed Not supported\n");
254 }
255 } else {
256 if (s->dimms[(chan>>1) + 1].width == 0) {
257 die("Mixed Not supported\n");
258 } else {
259 // 16DS/16DS
260 s->dimm_config[chan] = 4;
261 }
262 }
263 } else {
264 // DS/DS
265 if (s->dimms[chan>>1].width == 0 && s->dimms[(chan>>1)+1].width == 0) {
266 // 8DS/8DS
267 s->dimm_config[chan] = 6;
268 }
269 }
270 }
271}
272
273static void sdram_read_spds(struct sysinfo *s)
274{
Arthur Heymans1f6369e2018-08-20 11:27:41 +0200275 u8 i, chan;
Damien Zammit003d15c2015-11-20 17:17:51 +1100276 s->dt0mode = 0;
277 FOR_EACH_DIMM(i) {
Kyösti Mälkkic01a5052019-01-30 09:39:23 +0200278 if (i2c_eeprom_read(s->spd_map[i], 0, 64, s->dimms[i].spd_data) != 64)
Arthur Heymans1f6369e2018-08-20 11:27:41 +0200279 s->dimms[i].card_type = 0;
280
281 s->dimms[i].card_type = s->dimms[i].spd_data[62] & 0x1f;
Damien Zammit003d15c2015-11-20 17:17:51 +1100282 hexdump(s->dimms[i].spd_data, 64);
283 }
284
285 s->spd_type = 0;
286 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
287 switch (s->dimms[i].spd_data[2]) {
288 case 0x8:
289 s->spd_type = DDR2;
290 break;
291 case 0xb:
292 default:
293 die("DIMM type mismatch\n");
294 break;
295 }
296 }
297
298 int err = 1;
299 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Arthur Heymans097d7532017-04-17 10:14:32 +0200300 err = decode_spd(&s->dimms[i], i);
Damien Zammit003d15c2015-11-20 17:17:51 +1100301 s->dt0mode |= (s->dimms[i].spd_data[49] & 0x2) >> 1;
302 }
303 if (err) {
304 die("No memory dimms, halt\n");
305 }
306
307 FOR_EACH_POPULATED_CHANNEL(s->dimms, chan) {
308 find_ramconfig(s, chan);
309 PRINTK_DEBUG(" Config[CH%d] : %d\n",
310 chan, s->dimm_config[chan]);
311 }
312}
313
Julius Wernercd49cce2019-03-05 16:53:33 -0800314#if CONFIG(DEBUG_RAM_SETUP)
Damien Zammit003d15c2015-11-20 17:17:51 +1100315static u32 fsb_reg_to_mhz(u32 speed)
316{
317 return (speed * 133) + 667;
318}
319
320static u32 ddr_reg_to_mhz(u32 speed)
321{
322 u32 mhz;
323 mhz = (speed == 0) ? 667 :
324 (speed == 1) ? 800 :
325 0;
326 return mhz;
327}
328#endif
329
Jacob Garberb70c7762019-03-25 18:20:06 -0600330// Return the position of the least significant set bit, 0-indexed.
331// 0 does not have a lsb, so return -1 for error.
332static int lsbpos(u8 val)
Damien Zammit003d15c2015-11-20 17:17:51 +1100333{
Jacob Garberb70c7762019-03-25 18:20:06 -0600334 for (int i = 0; i < 8; i++)
335 if (val & (1 << i))
336 return i;
337 return -1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100338}
339
Jacob Garberb70c7762019-03-25 18:20:06 -0600340// Return the position of the most significant set bit, 0-indexed.
341// 0 does not have a msb, so return -1 for error.
342static int msbpos(u8 val)
Damien Zammit003d15c2015-11-20 17:17:51 +1100343{
Jacob Garberb70c7762019-03-25 18:20:06 -0600344 for (int i = 7; i >= 0; i--)
345 if (val & (1 << i))
346 return i;
347 return -1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100348}
349
350static void sdram_detect_smallest_params(struct sysinfo *s)
351{
Arthur Heymans6bf13012017-06-10 12:03:27 +0200352 static const u16 mult[6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100353 3000, // 667
354 2500, // 800
355 };
356
357 u8 i;
Damien Zammit003d15c2015-11-20 17:17:51 +1100358 u32 maxtras = 0;
359 u32 maxtrp = 0;
360 u32 maxtrcd = 0;
361 u32 maxtwr = 0;
362 u32 maxtrfc = 0;
363 u32 maxtwtr = 0;
364 u32 maxtrrd = 0;
365 u32 maxtrtp = 0;
366
367 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
368 maxtras = max(maxtras, s->dimms[i].spd_data[30] * 1000);
369 maxtrp = max(maxtrp, (s->dimms[i].spd_data[27] * 1000) >> 2);
370 maxtrcd = max(maxtrcd, (s->dimms[i].spd_data[29] * 1000) >> 2);
371 maxtwr = max(maxtwr, (s->dimms[i].spd_data[36] * 1000) >> 2);
372 maxtrfc = max(maxtrfc, s->dimms[i].spd_data[42] * 1000 +
373 (s->dimms[i].spd_data[40] & 0xf));
374 maxtwtr = max(maxtwtr, (s->dimms[i].spd_data[37] * 1000) >> 2);
375 maxtrrd = max(maxtrrd, (s->dimms[i].spd_data[28] * 1000) >> 2);
376 maxtrtp = max(maxtrtp, (s->dimms[i].spd_data[38] * 1000) >> 2);
377 }
Arthur Heymans12a4e982017-04-28 20:53:05 +0200378 /*
379 * TODO: on ddr3 there might be some minimal required values for some
380 * Timings: MIN_TRAS = 9, MIN_TRP = 3, MIN_TRCD = 3, MIN_TWR = 3,
381 * MIN_TWTR = 4, MIN_TRRD = 2, MIN_TRTP = 4
382 */
383 s->selected_timings.tRAS = MIN(24, DIV_ROUND_UP(maxtras,
384 mult[s->selected_timings.mem_clock]));
385 s->selected_timings.tRP = MIN(10, DIV_ROUND_UP(maxtrp,
386 mult[s->selected_timings.mem_clock]));
387 s->selected_timings.tRCD = MIN(10, DIV_ROUND_UP(maxtrcd,
388 mult[s->selected_timings.mem_clock]));
389 s->selected_timings.tWR = MIN(15, DIV_ROUND_UP(maxtwr,
390 mult[s->selected_timings.mem_clock]));
391 /* Needs to be even */
392 s->selected_timings.tRFC = 0xfe & (MIN(78, DIV_ROUND_UP(maxtrfc,
393 mult[s->selected_timings.mem_clock])) + 1);
394 s->selected_timings.tWTR = MIN(15, DIV_ROUND_UP(maxtwtr,
395 mult[s->selected_timings.mem_clock]));
396 s->selected_timings.tRRD = MIN(15, DIV_ROUND_UP(maxtrrd,
397 mult[s->selected_timings.mem_clock]));
Arthur Heymans5bb27b72017-08-26 21:24:21 +0200398 s->selected_timings.tRTP = MIN(15, DIV_ROUND_UP(maxtrtp,
Arthur Heymans12a4e982017-04-28 20:53:05 +0200399 mult[s->selected_timings.mem_clock]));
Damien Zammit003d15c2015-11-20 17:17:51 +1100400
401 PRINTK_DEBUG("Selected timings:\n");
402 PRINTK_DEBUG("\tFSB: %dMHz\n", fsb_reg_to_mhz(s->selected_timings.fsb_clock));
403 PRINTK_DEBUG("\tDDR: %dMHz\n", ddr_reg_to_mhz(s->selected_timings.mem_clock));
404
405 PRINTK_DEBUG("\tCAS: %d\n", s->selected_timings.CAS);
406 PRINTK_DEBUG("\ttRAS: %d\n", s->selected_timings.tRAS);
407 PRINTK_DEBUG("\ttRP: %d\n", s->selected_timings.tRP);
408 PRINTK_DEBUG("\ttRCD: %d\n", s->selected_timings.tRCD);
409 PRINTK_DEBUG("\ttWR: %d\n", s->selected_timings.tWR);
410 PRINTK_DEBUG("\ttRFC: %d\n", s->selected_timings.tRFC);
411 PRINTK_DEBUG("\ttWTR: %d\n", s->selected_timings.tWTR);
412 PRINTK_DEBUG("\ttRRD: %d\n", s->selected_timings.tRRD);
413 PRINTK_DEBUG("\ttRTP: %d\n", s->selected_timings.tRTP);
414}
415
416static void sdram_detect_ram_speed(struct sysinfo *s)
417{
418 u8 cas, reg8;
419 u32 reg32;
420 u32 freq = 0;
421 u32 fsb = 0;
422 u8 i;
423 u8 commoncas = 0;
424 u8 highcas = 0;
425 u8 lowcas = 0;
426
427 // Core frequency
428 fsb = (pci_read_config8(PCI_DEV(0,0,0), 0xe3) & 0x70) >> 4;
429 if (fsb) {
430 fsb = 5 - fsb;
431 } else {
432 fsb = FSB_CLOCK_800MHz;
433 }
434
435 // DDR frequency
436 freq = (pci_read_config8(PCI_DEV(0,0,0), 0xe3) & 0x80) >> 7;
437 freq |= (pci_read_config8(PCI_DEV(0,0,0), 0xe4) & 0x3) << 1;
438 if (freq) {
439 freq = 6 - freq;
440 } else {
441 freq = MEM_CLOCK_800MHz;
442 }
443
444 // Detect a common CAS latency
445 commoncas = 0xff;
446 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
447 commoncas &= s->dimms[i].spd_data[18];
448 }
449 if (commoncas == 0) {
450 die("No common CAS among dimms\n");
451 }
452
Jacob Garberb70c7762019-03-25 18:20:06 -0600453 // commoncas is nonzero, so these calls will not error
454 u8 msbp = (u8)msbpos(commoncas);
455 u8 lsbp = (u8)lsbpos(commoncas);
456
Damien Zammit003d15c2015-11-20 17:17:51 +1100457 // Start with fastest common CAS
458 cas = 0;
Jacob Garberb70c7762019-03-25 18:20:06 -0600459 highcas = msbp;
460 lowcas = max(lsbp, 5);
Damien Zammit003d15c2015-11-20 17:17:51 +1100461
462 while (cas == 0 && highcas >= lowcas) {
463 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
464 switch (freq) {
465 case MEM_CLOCK_800MHz:
466 if ((s->dimms[i].spd_data[9] > 0x25) ||
467 (s->dimms[i].spd_data[10] > 0x40)) {
468 // CAS too fast, lower it
469 highcas--;
470 break;
471 } else {
472 cas = highcas;
473 }
474 break;
475 case MEM_CLOCK_667MHz:
476 default:
477 if ((s->dimms[i].spd_data[9] > 0x30) ||
478 (s->dimms[i].spd_data[10] > 0x45)) {
479 // CAS too fast, lower it
480 highcas--;
481 break;
482 } else {
483 cas = highcas;
484 }
485 break;
486 }
487 }
488 }
489 if (highcas < lowcas) {
490 // Timings not supported by MCH, lower the frequency
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200491 if (freq == MEM_CLOCK_800MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +1100492 freq--;
493 PRINTK_DEBUG("Run DDR clock speed reduced due to timings\n");
494 } else {
495 die("Timings not supported by MCH\n");
496 }
497 cas = 0;
Jacob Garberb70c7762019-03-25 18:20:06 -0600498 highcas = msbp;
499 lowcas = lsbp;
Damien Zammit003d15c2015-11-20 17:17:51 +1100500 while (cas == 0 && highcas >= lowcas) {
501 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
502 switch (freq) {
503 case MEM_CLOCK_800MHz:
504 if ((s->dimms[i].spd_data[9] > 0x25) ||
505 (s->dimms[i].spd_data[10] > 0x40)) {
506 // CAS too fast, lower it
507 highcas--;
508 break;
509 } else {
510 cas = highcas;
511 }
512 break;
513 case MEM_CLOCK_667MHz:
514 default:
515 if ((s->dimms[i].spd_data[9] > 0x30) ||
516 (s->dimms[i].spd_data[10] > 0x45)) {
517 // CAS too fast, lower it
518 highcas--;
519 break;
520 } else {
521 cas = highcas;
522 }
523 break;
524 }
525 }
526 }
527 if (cas == 0) {
528 die("Unsupported dimms\n");
529 }
530 }
531
532 s->selected_timings.CAS = cas;
533 s->selected_timings.mem_clock = freq;
534 s->selected_timings.fsb_clock = fsb;
535
536 PRINTK_DEBUG("Drive Memory at %dMHz with CAS = %d clocks\n", ddr_reg_to_mhz(s->selected_timings.mem_clock), s->selected_timings.CAS);
537
538 // Set memory frequency
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200539 if (s->boot_path == BOOT_PATH_RESET)
540 return;
Damien Zammit003d15c2015-11-20 17:17:51 +1100541 MCHBAR32(0xf14) = MCHBAR32(0xf14) | 0x1;
542 reg32 = (MCHBAR32(0xc00) & (~0x70)) | (1 << 10);
543 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
544 reg8 = 3;
545 } else {
546 reg8 = 2;
547 }
548 reg32 |= reg8 << 4;
549 MCHBAR32(0xc00) = reg32;
550 s->selected_timings.mem_clock = ((MCHBAR32(0xc00) >> 4) & 0x7) - 2;
551 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
552 PRINTK_DEBUG("MCH validated at 800MHz\n");
553 s->nodll = 0;
554 s->maxpi = 63;
555 s->pioffset = 0;
556 } else if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
557 PRINTK_DEBUG("MCH validated at 667MHz\n");
558 s->nodll = 1;
559 s->maxpi = 15;
560 s->pioffset = 1;
561 } else {
562 PRINTK_DEBUG("MCH set to unknown (%02x)\n",
563 (uint8_t) s->selected_timings.mem_clock & 0xff);
564 }
565}
566
567#define HPET_BASE 0xfed00000
568#define HPET32(x) *((volatile u32 *)(HPET_BASE + x))
569static void enable_hpet(void)
570{
571 u32 reg32;
572 reg32 = RCBA32(0x3404);
573 reg32 &= ~0x3;
574 reg32 |= (1 << 7);
575 RCBA32(0x3404) = reg32;
576 HPET32(0x10) = HPET32(0x10) | 1;
577}
578
579static void sdram_clk_crossing(struct sysinfo *s)
580{
581 u8 clk_idx, fsb_idx;
Arthur Heymans6bf13012017-06-10 12:03:27 +0200582 static const u32 clkcross[2][2][4] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100583 {
584 {0xFFFFFFFF, 0x05030305, 0x0000FFFF, 0x00000000}, //667 667
585 {0x1F1F1F1F, 0x2A1F1FA5, 0x00000000, 0x05000002}, //667 800
586 },
587 {
588 {0x1F1F1F1F, 0x0D07070B, 0x00000000, 0x00000000}, //800 667
589 {0xFFFFFFFF, 0x05030305, 0x0000FFFF, 0x00000000}, //800 800
590 }
591 };
592 clk_idx = s->selected_timings.mem_clock;
593 fsb_idx = s->selected_timings.fsb_clock;
594
595 MCHBAR32(0xc04) = clkcross[fsb_idx][clk_idx][0];
596 MCHBAR32(0xc50) = clkcross[fsb_idx][clk_idx][1];
597 MCHBAR32(0xc54) = clkcross[fsb_idx][clk_idx][2];
598 MCHBAR32(0xc28) = 0;
599 MCHBAR32(0xc2c) = clkcross[fsb_idx][clk_idx][3];
600 MCHBAR32(0xc08) = MCHBAR32(0xc08) | (1 << 7);
601
602 if ((fsb_idx == 0) && (clk_idx == 1)) {
603 MCHBAR8(0x6d4) = 0;
604 MCHBAR32(0x700) = 0;
605 MCHBAR32(0x704) = 0;
606 }
607
Arthur Heymans6bf13012017-06-10 12:03:27 +0200608 static const u32 clkcross2[2][2][8] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100609 {
610 { 0, 0x08010204, 0, 0x08010204, 0, 0, 0, 0x04080102}, // 667 667
611 { 0x04080000, 0x10010002, 0x10000000, 0x20010208, 0, 0x00000004, 0x02040000, 0x08100102}, // 667 800
612 },
613 {
614 { 0x10000000, 0x20010208, 0x04080000, 0x10010002, 0, 0, 0x08000000, 0x10200204}, // 800 667
615 { 0x00000000, 0x08010204, 0, 0x08010204, 0, 0, 0, 0x04080102}, // 800 800
616 }
617 };
618
619 MCHBAR32(0x6d8) = clkcross2[fsb_idx][clk_idx][0];
620 MCHBAR32(0x6e0) = clkcross2[fsb_idx][clk_idx][0];
621 MCHBAR32(0x6e8) = clkcross2[fsb_idx][clk_idx][0];
622 MCHBAR32(0x6d8+4) = clkcross2[fsb_idx][clk_idx][1];
623 MCHBAR32(0x6e0+4) = clkcross2[fsb_idx][clk_idx][1];
624 MCHBAR32(0x6e8+4) = clkcross2[fsb_idx][clk_idx][1];
625 MCHBAR32(0x6f0) = clkcross2[fsb_idx][clk_idx][2];
626 MCHBAR32(0x6f4) = clkcross2[fsb_idx][clk_idx][3];
627 MCHBAR32(0x6f8) = clkcross2[fsb_idx][clk_idx][4];
628 MCHBAR32(0x6fc) = clkcross2[fsb_idx][clk_idx][5];
629 MCHBAR32(0x708) = clkcross2[fsb_idx][clk_idx][6];
630 MCHBAR32(0x70c) = clkcross2[fsb_idx][clk_idx][7];
631}
632
633static void sdram_clkmode(struct sysinfo *s)
634{
635 u8 reg8;
636 u16 reg16;
637
638 MCHBAR16(0x1b6) = MCHBAR16(0x1b6) & ~(1 << 8);
639 MCHBAR8(0x1b6) = MCHBAR8(0x1b6) & ~0x3f;
640
641 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
642 reg8 = 0;
643 reg16 = 1;
644 } else {
645 reg8 = 1;
646 reg16 = (1 << 8) | (1 << 5);
647 }
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200648 if (s->boot_path != BOOT_PATH_RESET)
649 MCHBAR16(0x1c0) = (MCHBAR16(0x1c0) & ~(0x033f)) | reg16;
Damien Zammit003d15c2015-11-20 17:17:51 +1100650
651 MCHBAR32(0x220) = 0x58001117;
652 MCHBAR32(0x248) = (MCHBAR32(0x248) | (1 << 23));
653
654 const u32 cas_to_reg[2][4] = {
655 {0x00000000, 0x00030100, 0x0C240201, 0x00000000}, // 667
656 {0x00000000, 0x00030100, 0x0C240201, 0x10450302} // 800
657 };
658
659 MCHBAR32(0x224) = cas_to_reg[reg8][s->selected_timings.CAS - 3];
660}
661
662static void sdram_timings(struct sysinfo *s)
663{
664 u8 i, j, ch, r, ta1, ta2, ta3, ta4, trp, bank, page, flag;
665 u8 reg8, wl;
666 u16 reg16;
667 u32 reg32, reg2;
Arthur Heymans6bf13012017-06-10 12:03:27 +0200668 static const u8 pagetab[2][2] = {{0xe, 0x12}, {0x10, 0x14}};
Damien Zammit003d15c2015-11-20 17:17:51 +1100669
670 // Only consider DDR2
671 wl = s->selected_timings.CAS - 1;
672 ta1 = ta2 = 6;
673 ta3 = s->selected_timings.CAS;
674 ta4 = 8;
675 s->selected_timings.tRFC = (s->selected_timings.tRFC + 1) & 0xfe;
676 trp = 0;
677 bank = 1;
678 page = 0;
679
680 MCHBAR8(0x240) = ((wl - 3) << 4) | (s->selected_timings.CAS - 3);
681
682 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
683 i = ch << 1;
684 if (s->dimms[i].banks == 1) {
685 trp = 1;
686 bank = 0;
687 }
688 if (s->dimms[i].page_size == 2048) {
689 page = 1;
690 }
691 }
692 PRINTK_DEBUG("trp=%d bank=%d page=%d\n",trp, bank, page);
693
694 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
695 flag = 0;
696 } else {
697 flag = 1;
698 }
699
700 MCHBAR8(0x26f) = MCHBAR8(0x26f) | 0x3;
701 MCHBAR16(0x250) = ((wl + 4 + s->selected_timings.tWR) << 6) |
702 ((2 + MAX(s->selected_timings.tRTP, 2)) << 2) | 1;
703 reg32 = (bank << 21) | (s->selected_timings.tRRD << 17) |
704 (s->selected_timings.tRP << 13) |
705 ((s->selected_timings.tRP + trp) << 9) |
706 s->selected_timings.tRFC;
707 if (bank == 0) {
708 reg32 |= (pagetab[flag][page] << 22);
709 }
710 MCHBAR16(0x252) = (u16) reg32;
711 MCHBAR16(0x254) = (u16) (reg32 >> 16);
712
713 reg16 = (MCHBAR16(0x254) & 0xfc0) >> 6;
714 MCHBAR16(0x62c) = (MCHBAR16(0x62c) & ~0x1f80) | (reg16 << 7);
715
716 reg16 = (s->selected_timings.tRCD << 12) | (4 << 8) | (ta2 << 4) | ta4;
717 MCHBAR16(0x256) = reg16;
718
719 reg32 = (s->selected_timings.tRCD << 17) |
720 ((wl + 4 + s->selected_timings.tWTR) << 12) |
721 (ta3 << 8) | (4 << 4) | ta1;
722 MCHBAR32(0x258) = reg32;
723
724 reg16 = ((s->selected_timings.tRP + trp) << 9) |
725 s->selected_timings.tRFC;
726 MCHBAR8(0x25b) = (u8) reg16;
727 MCHBAR8(0x25c) = (u8) (reg16 >> 8);
728
729 MCHBAR16(0x260) = (MCHBAR16(0x260) & ~0x3fe) | (100 << 1);
730 MCHBAR8(0x25d) = (MCHBAR8(0x25d) & ~0x3f) | s->selected_timings.tRAS;
731 MCHBAR16(0x244) = 0x2310;
732
733 MCHBAR8(0x246) = (MCHBAR8(0x246) & ~0x1f) | 1;
734
735 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
736 reg32 = 3000;
737 } else {
738 reg32 = 2500;
739 }
740 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
741 reg2 = 6000;
742 } else {
743 reg2 = 5000;
744 }
745 reg16 = (u16)((((s->selected_timings.CAS + 7)*(reg32)) / reg2) << 8);
746 MCHBAR16(0x248) = (MCHBAR16(0x248) & ~0x1f00) | reg16;
747
748 flag = 0;
749 if (wl > 2) {
750 flag = 1;
751 }
752 reg16 = (u8) (wl - 1 - flag);
753 reg16 |= reg16 << 4;
754 reg16 |= flag << 8;
755 MCHBAR16(0x24d) = (MCHBAR16(0x24d) & ~0x1ff) | reg16;
756
757 MCHBAR16(0x25e) = 0x1585;
758 MCHBAR8(0x265) = MCHBAR8(0x265) & ~0x1f;
759 MCHBAR16(0x265) = (MCHBAR16(0x265) & ~0x3f00) |
760 ((s->selected_timings.CAS + 9) << 8);
761
762 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
763 reg16 = 0x514;
764 reg32 = 0xa28;
765 } else {
766 reg16 = 0x618;
767 reg32 = 0xc30;
768 }
769 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~0xfffff00) |
770 (0x3f << 22) | (reg32 << 8);
771 MCHBAR8(0x26c) = 0x00;
772 MCHBAR16(0x2b8) = (MCHBAR16(0x2b8) & 0xc000) | reg16;
773 MCHBAR8(0x274) = MCHBAR8(0x274) | 1;
774
775 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0x7f000000) | (0xb << 25);
776 i = s->selected_timings.mem_clock;
777 j = s->selected_timings.fsb_clock;
778 if (i > j) {
779 MCHBAR32(0x248) = MCHBAR32(0x248) | (1 << 24);
780 }
781
782 MCHBAR8(0x24c) = MCHBAR8(0x24c) & ~0x3;
783 MCHBAR16(0x24d) = (MCHBAR16(0x24d) & ~0x7c00) | ((wl + 10) << 10);
784 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x70e0000) | (3 << 24) | (3 << 17);
785 reg16 = 0x15 << 6;
786 reg16 |= 0x1f;
787 reg16 |= (0x6 << 12);
788 MCHBAR16(0x26d) = (MCHBAR16(0x26d) & ~0x7fff) | reg16;
789
790 reg32 = (0x6 << 27) | (1 << 25);
791 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~0x30000000) | ((u32)(reg32 << 8));
792 MCHBAR8(0x26c) = (MCHBAR8(0x26c) & ~0xfa) | ((u8)(reg32 >> 24));
793 MCHBAR8(0x271) = MCHBAR8(0x271) & ~(1 << 7);
794 MCHBAR8(0x274) = MCHBAR8(0x274) & ~0x6;
Stefan Reinauer66fbeae2016-05-06 13:48:39 -0700795 reg32 = (u32) (((6 & 0x03) << 30) | (4 << 25) | (1 << 20) | (8 << 15) |
Damien Zammit003d15c2015-11-20 17:17:51 +1100796 (6 << 10) | (4 << 5) | 1);
797 MCHBAR32(0x278) = reg32;
798
799 MCHBAR16(0x27c) = (MCHBAR16(0x27c) & ~0x1ff) | (8 << 3) | (6 >> 2);
800 MCHBAR16(0x125) = MCHBAR16(0x125) | 0x1c00 | (0x1f << 5);
801 MCHBAR8(0x127) = (MCHBAR8(0x127) & ~0xff) | 0x40;
802 MCHBAR8(0x128) = (MCHBAR8(0x128) & ~0x7) | 0x5;
803 MCHBAR8(0x129) = MCHBAR8(0x129) | 0x1f;
804 reg8 = 3 << 6;
805 reg8 |= (s->dt0mode << 4);
806 reg8 |= 0x0c;
807 MCHBAR8(0x12f) = (MCHBAR8(0x12f) & ~0xdf) | reg8;
808 MCHBAR8(0x18c) = MCHBAR8(0x18c) & ~0x2;
809 MCHBAR8(0x228) = (MCHBAR8(0x228) & ~0x7) | 0x2;
810 MCHBAR16(0x241) = (MCHBAR16(0x241) & ~0x3fc) | (4 << 2);
811 reg32 = (2 << 29) | (1 << 28) | (1 << 23);
812 MCHBAR32(0x120) = (MCHBAR32(0x120) & ~0xffb00000) | reg32;
813
814 reg8 = (u8) ((MCHBAR16(0x252) & 0xe000) >> 13);
815 reg8 |= (u8) ((MCHBAR16(0x254) & 1) << 3);
816 MCHBAR8(0x12d) = (MCHBAR8(0x12d) & ~0xf0) | (reg8 << 4);
817 reg8 = (u8) ((MCHBAR32(0x258) & 0xf0000) >> 17);
818 MCHBAR8(0x12d) = (MCHBAR8(0x12d) & ~0xf) | reg8;
819 MCHBAR8(0x12e) = MCHBAR8(0x12e) & ~0xfc;
820 MCHBAR8(0x12e) = MCHBAR8(0x12e) & ~0x3;
821 MCHBAR8(0x12f) = MCHBAR8(0x12f) & ~0x3;
822 MCHBAR8(0x241) = MCHBAR8(0x241) | 1;
823 MCHBAR16(0x1b6) = MCHBAR16(0x1b6) | (1 << 9);
824 for (i = 0; i < 8; i++) {
825 MCHBAR32(0x540 + i*4) = (MCHBAR32(0x540 + i*4) & ~0x3f3f3f3f) |
826 0x0c0c0c0c;
827 }
828 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) |
829 ((s->selected_timings.CAS + 1) << 16);
830 for (i = 0; i < 8; i++) {
831 MCHBAR8(0x560 + i*4) = MCHBAR8(0x560 + i*4) & ~0x3f;
832 MCHBAR16(0x58c) = MCHBAR16(0x58c) & ((u16) (~(3 << (i*2))));
833 MCHBAR16(0x588) = MCHBAR16(0x588) & ((u16) (~(3 << (i*2))));
834 MCHBAR16(0x5fa) = MCHBAR16(0x5fa) & ((u16) (~(3 << (i*2))));
835 }
836 MCHBAR8(0x5f0) = MCHBAR8(0x5f0) & ~0x1;
837 MCHBAR8(0x5f0) = MCHBAR8(0x5f0) | 0x2;
838 MCHBAR8(0x5f0) = MCHBAR8(0x5f0) | 0x4;
839 MCHBAR32(0x2c0) = MCHBAR32(0x2c0) | 0xc0400;
840 MCHBAR32(0x594) = MCHBAR32(0x594) | (1 << 31);
841}
842
Arthur Heymans6bf13012017-06-10 12:03:27 +0200843static void sdram_p_clkset0(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100844{
845 MCHBAR16(0x5a0) = (MCHBAR16(0x5a0) & ~0xc440) |
846 (pll->clkdelay[f][i] << 14) |
847 (pll->dben[f][i] << 10) |
848 (pll->dbsel[f][i] << 6);
849 MCHBAR8(0x581) = (MCHBAR8(0x581) & ~0x3f) | pll->pi[f][i];
850}
851
Arthur Heymans6bf13012017-06-10 12:03:27 +0200852static void sdram_p_clkset1(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100853{
854 MCHBAR16(0x5a0) = (MCHBAR16(0x5a0) & ~0x30880) |
855 (pll->clkdelay[f][i] << 16) |
856 (pll->dben[f][i] << 11) |
857 (pll->dbsel[f][i] << 7);
858 MCHBAR8(0x582) = (MCHBAR8(0x582) & ~0x3f) | pll->pi[f][i];
859}
860
Arthur Heymans6bf13012017-06-10 12:03:27 +0200861static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100862{
863 u8 reg8;
864 reg8 = pll->dbsel[f][i] << 5;
865 reg8 |= pll->dben[f][i] << 6;
866 MCHBAR8(0x594) = (MCHBAR8(0x594) & ~0x60) | reg8;
867
868 reg8 = pll->clkdelay[f][i] << 4;
869 MCHBAR8(0x598) = (MCHBAR8(0x598) & ~0x30) | reg8;
870
871 reg8 = pll->pi[f][i];
872 MCHBAR8(0x580) = (MCHBAR8(0x580) & ~0x3f) | reg8;
873 MCHBAR8(0x583) = (MCHBAR8(0x583) & ~0x3f) | reg8;
874}
875
Arthur Heymans6bf13012017-06-10 12:03:27 +0200876static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100877{
878 u8 reg8;
879 u32 reg32;
880 reg32 = ((u32) pll->dbsel[f][i]) << 20;
881 reg32 |= ((u32) pll->dben[f][i]) << 21;
882 reg32 |= ((u32) pll->dbsel[f][i]) << 22;
883 reg32 |= ((u32) pll->dben[f][i]) << 23;
884 reg32 |= ((u32) pll->clkdelay[f][i]) << 24;
885 reg32 |= ((u32) pll->clkdelay[f][i]) << 27;
886 MCHBAR32(0x59c) = (MCHBAR32(0x59c) & ~0x1bf0000) | reg32;
887
888 reg8 = pll->pi[f][i];
889 MCHBAR8(0x584) = (MCHBAR8(0x584) & ~0x3f) | reg8;
890 MCHBAR8(0x585) = (MCHBAR8(0x585) & ~0x3f) | reg8;
891
892 reg32 = ((u32) pll->dbsel[f][i]) << 12;
893 reg32 |= ((u32) pll->dben[f][i]) << 13;
894 reg32 |= ((u32) pll->dbsel[f][i]) << 8;
895 reg32 |= ((u32) pll->dben[f][i]) << 9;
896 reg32 |= ((u32) pll->clkdelay[f][i]) << 14;
897 reg32 |= ((u32) pll->clkdelay[f][i]) << 10;
898 MCHBAR32(0x598) = (MCHBAR32(0x598) & ~0xff00) | reg32;
899
900 reg8 = pll->pi[f][i];
901 MCHBAR8(0x586) = (MCHBAR8(0x586) & ~0x3f) | reg8;
902 MCHBAR8(0x587) = (MCHBAR8(0x587) & ~0x3f) | reg8;
903}
904
905static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
906{
907 u8 rank, dqs, reg8, j;
908 u32 reg32;
909
910 j = clk - 40;
911 reg8 = 0;
912 reg32 = 0;
913 rank = j % 4;
914 dqs = j / 4;
915
916 reg32 |= ((u32) pll->dben[f][clk]) << (dqs + 9);
917 reg32 |= ((u32) pll->dbsel[f][clk]) << dqs;
918 MCHBAR32(0x5b4+rank*4) = (MCHBAR32(0x5b4+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200919 ~((1 << (dqs+9))|(1 << dqs))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100920
921 reg32 = ((u32) pll->clkdelay[f][clk]) << ((dqs*2) + 16);
922 MCHBAR32(0x5c8+rank*4) = (MCHBAR32(0x5c8+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200923 ~((1 << (dqs*2 + 17))|(1 << (dqs*2 + 16)))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100924
925 reg8 = pll->pi[f][clk];
926 MCHBAR8(0x520+j) = (MCHBAR8(0x520+j) & ~0x3f) | reg8;
927}
928
929
930static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
931{
932 u8 rank, dq, reg8, j;
933 u32 reg32;
934
935 j = clk - 8;
936 reg8 = 0;
937 reg32 = 0;
938 rank = j % 4;
939 dq = j / 4;
940
941 reg32 |= ((u32) pll->dben[f][clk]) << (dq + 9);
942 reg32 |= ((u32) pll->dbsel[f][clk]) << dq;
943 MCHBAR32(0x5a4+rank*4) = (MCHBAR32(0x5a4+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200944 ~((1 << (dq+9))|(1 << dq))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100945
946 reg32 = ((u32) pll->clkdelay[f][clk]) << (dq*2);
947 MCHBAR32(0x5c8+rank*4) = (MCHBAR32(0x5c8+rank*4) &
Elyes HAOUASa342f392018-10-17 10:56:26 +0200948 ~((1 << (dq*2 + 1))|(1 << (dq*2)))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100949
950 reg8 = pll->pi[f][clk];
951 MCHBAR8(0x500+j) = (MCHBAR8(0x500+j) & ~0x3f) | reg8;
952}
953
954static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
955{
956 struct pllparam pll = {
957 .pi = {
958 { // 667
959 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
960 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
961 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
962 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
963 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
964 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3
965 },
966 { // 800
967 53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
968 34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
969 47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
970 47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
971 2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
972 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15
973 }},
974
975 .dben = {
976 { // 667
977 0,0,1,1,1,1,1,1,1,1,1,1,
978 1,1,1,1,0,0,0,0,0,0,0,0,
979 0,0,0,0,0,0,0,0,0,0,0,0,
980 1,1,1,1,0,0,0,0,0,0,0,0,
981 0,0,0,0,0,0,0,0,0,0,0,0,
982 0,0,0,0,0,0,0,0,0,0,0,0
983 },
984 { // 800
985 1,1,1,1,1,1,1,1,0,0,0,0,
986 0,0,0,0,0,0,0,0,0,0,0,0,
987 0,0,0,0,0,0,0,0,0,0,0,0,
988 0,0,0,0,1,1,1,1,1,1,1,1,
989 1,1,1,1,1,1,1,1,0,0,0,0,
990 1,1,1,1,0,0,0,0,0,0,0,0
991 }},
992
993 .dbsel = {
994 { // 667
995 0,0,1,1,1,1,1,1,1,1,1,1,
996 1,1,1,1,0,0,0,0,0,0,0,0,
997 0,0,0,0,0,0,0,0,0,0,0,0,
998 1,1,1,1,0,0,0,0,0,0,0,0,
999 0,0,0,0,0,0,0,0,0,0,0,0,
1000 0,0,0,0,0,0,0,0,0,0,0,0
1001 },
1002 { // 800
1003 0,0,1,1,1,1,1,1,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,0,0,0,0,
1006 0,0,0,0,0,0,0,0,1,1,1,1,
1007 1,1,1,1,1,1,1,1,0,0,0,0,
1008 1,1,1,1,0,0,0,0,0,0,0,0
1009 }},
1010
1011 .clkdelay = {
1012 { // 667
1013 0,0,1,1,0,0,0,0,1,1,1,1,
1014 1,1,1,1,1,1,1,1,1,1,1,1,
1015 1,1,1,1,1,1,1,1,1,1,1,1,
1016 1,1,1,1,0,0,0,0,0,0,0,0,
1017 0,0,0,0,0,0,0,0,0,0,0,0,
1018 0,0,0,0,0,0,0,0,0,0,0,0
1019 },
1020 { // 800
1021 0,0,0,0,0,0,0,0,1,1,1,1,
1022 1,1,1,1,1,1,1,1,1,1,1,1,
1023 1,1,1,1,1,1,1,1,1,1,1,1,
1024 1,1,1,1,0,0,0,0,1,1,1,1,
1025 1,1,1,1,1,1,1,1,1,1,1,1,
1026 1,1,1,1,1,1,1,1,1,1,1,1
1027 }}
1028 };
1029
1030 u8 i, f;
1031 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1032 f = 0;
1033 } else {
1034 f = 1;
1035 }
1036 for (i = 0; i < 72; i++) {
1037 pll.pi[f][i] += pidelay;
1038 }
1039
1040 MCHBAR8(0x1a4) = MCHBAR8(0x1a4) & ~(1 << 7);
1041 MCHBAR16(0x190) = (MCHBAR16(0x190) & (u16) ~(0x3fff)) | 0x1fff;
1042
1043 sdram_p_clkset0(&pll, f, 0);
1044 sdram_p_clkset1(&pll, f, 1);
1045 sdram_p_cmd(&pll, f, 2);
1046 sdram_p_ctrl(&pll, f, 4);
1047 for (i = 0; i < 32; i++) {
1048 sdram_p_dqs(&pll, f, i+40);
1049 }
1050 for (i = 0; i < 32; i++) {
1051 sdram_p_dq(&pll, f, i+8);
1052 }
1053}
1054
1055static void sdram_calibratehwpll(struct sysinfo *s)
1056{
1057 u8 reg8;
1058
1059 s->async = 0;
1060 reg8 = 0;
1061 MCHBAR16(0x180) = MCHBAR16(0x180) | (1 << 15);
1062 MCHBAR8(0x180) = MCHBAR8(0x180) & ~(1 << 7);
1063 MCHBAR8(0x180) = MCHBAR8(0x180) | (1 << 3);
1064 MCHBAR8(0x180) = MCHBAR8(0x180) | (1 << 2);
1065
1066 MCHBAR8(0x180) = MCHBAR8(0x180) | (1 << 7);
1067 while ((MCHBAR8(0x180) & (1 << 2)) == 0);
1068
1069 reg8 = (MCHBAR8(0x180) & (1 << 3)) >> 3;
1070 if (reg8 != 0) {
1071 s->async = 1;
1072 }
1073}
1074
1075static void sdram_dlltiming(struct sysinfo *s)
1076{
Elyes HAOUAS66b462d2019-01-02 21:11:32 +01001077 u8 reg8, i;
Damien Zammit003d15c2015-11-20 17:17:51 +11001078 u16 reg16;
1079 u32 reg32;
1080
1081 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1082 reg32 = 0x8014227;
1083 } else {
1084 reg32 = 0x14221;
1085 }
1086 MCHBAR32(0x19c) = (MCHBAR32(0x19c) & ~0xfffffff) | reg32;
1087 MCHBAR32(0x19c) = MCHBAR32(0x19c) | (1 << 23);
1088 MCHBAR32(0x19c) = MCHBAR32(0x19c) | (1 << 15);
1089 MCHBAR32(0x19c) = MCHBAR32(0x19c) & ~(1 << 15);
1090
1091 if (s->nodll) {
1092 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 0);
1093 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 2);
1094 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 4);
1095 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 8);
1096 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 10);
1097 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 12);
1098 MCHBAR16(0x198) = MCHBAR16(0x198) | (1 << 14);
1099 } else {
1100 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 0);
1101 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 2);
1102 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 4);
1103 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 8);
1104 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 10);
1105 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 12);
1106 MCHBAR16(0x198) = MCHBAR16(0x198) & ~(1 << 14);
1107 }
1108
1109 if (s->nodll) {
1110 MCHBAR8(0x1c8) = (MCHBAR8(0x1c8) & ~0x3f) | 0x7;
1111 } else {
1112 MCHBAR8(0x1c8) = (MCHBAR8(0x1c8) & ~0x3f);
1113 }
1114
1115 sdram_calibratepll(s, 0); // XXX check
1116
1117 MCHBAR16(0x5f0) = MCHBAR16(0x5f0) | (1 << 11);
1118 MCHBAR16(0x5f0) = MCHBAR16(0x5f0) | (1 << 12);
1119
1120 for (i = 0; i < 8; i++) {
1121 MCHBAR16(0x5f0) = MCHBAR16(0x5f0) | ((1 << 10) >> i);
1122 }
1123 MCHBAR8(0x2c14) = MCHBAR8(0x2c14) | 1;
1124 MCHBAR16(0x182) = 0x5005;
1125 MCHBAR16(0x18a) = (MCHBAR16(0x18a) & ~0x1f1f) | 0x51a;
1126 MCHBAR16(0x2c00) = (MCHBAR16(0x2c00) & ~0xbf3f) | 0x9010;
1127
1128 if (s->nodll) {
1129 MCHBAR8(0x18e) = (MCHBAR8(0x18e) & ~0x7f) | 0x6b;
1130 } else {
1131 MCHBAR8(0x18e) = (MCHBAR8(0x18e) & ~0x7f) | 0x55;
1132 sdram_calibratehwpll(s);
1133 }
Damien Zammit003d15c2015-11-20 17:17:51 +11001134
1135 MCHBAR32(0x248) = MCHBAR32(0x248) & ~(1 << 22);
1136 MCHBAR8(0x5d9) = MCHBAR8(0x5d9) & ~0x2;
1137 MCHBAR8(0x189) = MCHBAR8(0x189) | 0xc0;
1138 MCHBAR8(0x189) = MCHBAR8(0x189) & ~(1 << 5);
1139 MCHBAR8(0x189) = (MCHBAR8(0x189) & ~0xc0) | (1 << 6);
1140 MCHBAR8(0x188) = (MCHBAR8(0x188) & ~0x3f) | 0x1a;
1141 MCHBAR8(0x188) = MCHBAR8(0x188) | 1;
1142
1143 MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 1;
1144 MCHBAR32(0x1a0) = 0x551803;
1145 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0)) {
1146 reg8 = 0x3c;
1147 } else if (ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1148 reg8 = 0x27;
1149 } else if (BOTH_DIMMS_ARE_POPULATED(s->dimms, 0)) {
1150 reg8 = 0x24;
1151 } else {
1152 // None
1153 reg8 = 0x3f;
1154 }
1155 reg8 = 0x00; //switch all clocks on anyway
1156
1157 MCHBAR32(0x5a0) = (MCHBAR32(0x5a0) & ~0x3f000000) | (reg8 << 24);
1158 MCHBAR8(0x594) = MCHBAR8(0x594) & ~1;
1159 reg16 = 0;
1160 if (!rank_is_populated(s->dimms, 0, 0)) {
1161 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
1162 }
1163 if (!rank_is_populated(s->dimms, 0, 1)) {
1164 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
1165 }
1166 if (!rank_is_populated(s->dimms, 0, 2)) {
1167 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1168 }
1169 if (!rank_is_populated(s->dimms, 0, 3)) {
1170 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1171 }
1172 MCHBAR16(0x59c) = MCHBAR16(0x59c) | reg16;
1173}
1174
1175static void sdram_rcomp(struct sysinfo *s)
1176{
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02001177 u8 i, j, reg8, rcompp, rcompn, srup, srun;
Damien Zammit003d15c2015-11-20 17:17:51 +11001178 u16 reg16;
1179 u32 reg32, rcomp1, rcomp2;
1180
Arthur Heymans6bf13012017-06-10 12:03:27 +02001181 static const u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0 };
1182 static const u8 rcompslew = 0xa;
1183 static const u8 rcompstr[7] = { 0x66, 0, 0xaa, 0x55, 0x55, 0x77, 0x77 };
1184 static const u16 rcompscomp[7] = { 0xa22a, 0, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a };
1185 static const u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1 };
1186 static const u16 rcompctl[7] = { 0x31c, 0, 0x374, 0x3a2, 0x3d0, 0x3fe, 0x42c };
1187 static const u16 rcompf[7] = { 0x1114, 0, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a };
Damien Zammit003d15c2015-11-20 17:17:51 +11001188
1189 // NC-NC x16SS x16DS x16SS2 x16DS2 x8DS, x8DS2
Arthur Heymans6bf13012017-06-10 12:03:27 +02001190 static const u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa,
1191 0xaa , 0x55, 0xaa};
1192 static const u16 rcompscomp2[7] = { 0x0000, 0xe22e, 0xe22e, 0xe22e,
1193 0x8228 , 0xe22e, 0x8228 };
1194 static const u8 rcompdelay2[7] = { 0, 0, 0, 0, 2 , 0, 2};
Damien Zammit003d15c2015-11-20 17:17:51 +11001195
Arthur Heymans6bf13012017-06-10 12:03:27 +02001196 static const u8 rcomplut[64][12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001197 { 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 { 9, 9,11, 11, 2, 2, 5,5, 6, 6,5, 5},
1212 { 10,9,12, 11, 2, 2, 5,5, 6, 6,5, 5},
1213 { 10,9,12, 11, 2, 2, 6,5, 7, 6,6, 5},
1214 { 10,10,12, 12, 2, 2, 6,5, 7, 6,6, 5},
1215 { 10,10,12, 12, 2, 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, 2, 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 { 10,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1224 { 11,10,12, 12, 3, 3, 6,6, 7, 7,6, 6},
1225 { 11,10,14, 13, 3, 3, 6,6, 7, 7,6, 6},
1226 { 12,10,14, 13, 3, 3, 6,6, 7, 7,6, 6},
1227 { 12,12,14, 13, 3, 3, 7,6, 7, 7,7, 6},
1228 { 13,12,16, 15, 3, 3, 7,6, 8, 7,7, 6},
1229 { 13,14,16, 15, 4, 3, 7,7, 8, 8,7, 7},
1230 { 14,14,16, 17, 4, 3, 7,7, 8, 8,7, 7},
1231 { 14,16,18, 17, 4, 4, 8,7, 8, 8,8, 7},
1232 { 15,16,18, 19, 4, 4, 8,7, 9, 8,8, 7},
1233 { 15,18,18, 19, 4, 4, 8,8, 9, 9,8, 8},
1234 { 16,18,20, 21, 4, 4, 8,8, 9, 9,8, 8},
1235 { 16,19,20, 21, 5, 4, 9,8, 10, 9,9, 8},
1236 { 16,19,20, 23, 5, 5, 9,9, 10, 10,9, 9},
1237 { 17,19,22, 23, 5, 5, 9,9, 10, 10,9, 9},
1238 { 17,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1239 { 17,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1240 { 18,20,22, 25, 5, 5, 9,9, 10, 10,9, 9},
1241 { 18,21,24, 25, 5, 5, 9,9, 11, 10,9, 9},
1242 { 19,21,24, 27, 5, 5, 9, 9, 11, 11,9, 9},
1243 { 19,22,24, 27, 5, 5, 10,9, 11, 11,10, 9},
1244 { 20,22,24, 27, 6, 5, 10,10, 11, 11,10, 10},
1245 { 20,23,26, 27, 6, 6, 10,10, 12, 12,10, 10},
1246 { 20,23,26, 29, 6, 6, 10,10, 12, 12,10, 10},
1247 { 21,24,26, 29, 6, 6, 10,10, 12, 12,10, 10},
1248 { 21,24,26, 29, 6, 6, 11,10, 12, 13,11, 10},
1249 { 22,25,28, 29, 6, 6, 11,11, 13, 13,11, 11},
1250 { 22,25,28, 31, 6, 6, 11,11, 13, 13,11, 11},
1251 { 22,26,28, 31, 6, 6, 11,11, 13, 14,11, 11},
1252 { 23,26,30, 31, 7, 6, 12,11, 14, 14,12, 11},
1253 { 23,27,30, 33, 7, 7, 12,12, 14, 14,12, 12},
1254 { 23,27,30, 33, 7, 7, 12,12, 14, 15,12, 12},
1255 { 24,28,32, 33, 7, 7, 12,12, 15, 15,12, 12},
1256 { 24,28,32, 33, 7, 7, 12,12, 15, 16,12, 12},
1257 { 24,29,32, 35, 7, 7, 12,12, 15, 16,12, 12},
1258 { 25,29,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1259 { 25,30,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1260 { 25,30,32, 35, 7, 7, 12,12, 15, 17,12, 12},
1261 };
1262
1263 srup = 0;
1264 srun = 0;
1265
1266 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001267 rcomp1 = 0x00050431;
1268 } else {
Damien Zammit003d15c2015-11-20 17:17:51 +11001269 rcomp1 = 0x00050542;
1270 }
1271 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
1272 rcomp2 = 0x14C42827;
1273 } else {
1274 rcomp2 = 0x19042827;
1275 }
1276
1277 for (i = 0; i < 7; i++) {
1278 if (i == 1)
1279 continue;
1280 reg8 = rcompupdate[i];
1281 MCHBAR8(rcompctl[i]) = (MCHBAR8(rcompctl[i]) & ~0x1) | reg8;
1282 MCHBAR8(rcompctl[i]) = MCHBAR8(rcompctl[i]) & ~0x2;
1283 reg16 = (u16) rcompslew;
1284 MCHBAR16(rcompctl[i]) = (MCHBAR16(rcompctl[i]) & ~0xf000) |
1285 (reg16 << 12);
1286 MCHBAR8(rcompctl[i]+4) = rcompstr[i];
1287 MCHBAR16(rcompctl[i]+0xe) = rcompscomp[i];
1288 MCHBAR8(rcompctl[i]+0x14) = (MCHBAR8(rcompctl[i]+0x14) & ~0x3) |
1289 rcompdelay[i];
1290 if (i == 2) {
1291 reg16 = (u16) rcompslew;
1292 MCHBAR16(rcompctl[i]) = (MCHBAR16(rcompctl[i]) &
1293 ~0xf000) | (reg16 << 12);
1294 MCHBAR8(rcompctl[i]+4) = rcompstr2[s->dimm_config[0]];
1295 MCHBAR16(rcompctl[i]+0xe) = rcompscomp2[s->dimm_config[0]];
1296 MCHBAR8(rcompctl[i]+0x14) = (MCHBAR8(rcompctl[i]+0x14) &
1297 ~0x3) | rcompdelay2[s->dimm_config[0]];
1298 }
1299
1300 MCHBAR16(rcompctl[i]+0x16) = MCHBAR16(rcompctl[i]+0x16) & ~0x7f7f;
1301 MCHBAR16(rcompctl[i]+0x18) = MCHBAR16(rcompctl[i]+0x18) & ~0x3f3f;
1302 MCHBAR16(rcompctl[i]+0x1a) = MCHBAR16(rcompctl[i]+0x1a) & ~0x3f3f;
1303 MCHBAR16(rcompctl[i]+0x1c) = MCHBAR16(rcompctl[i]+0x1c) & ~0x3f3f;
1304 MCHBAR16(rcompctl[i]+0x1e) = MCHBAR16(rcompctl[i]+0x1e) & ~0x3f3f;
1305 }
1306
1307 MCHBAR8(0x45a) = (MCHBAR8(0x45a) & ~0x3f) | 0x36;
1308 MCHBAR8(0x462) = (MCHBAR8(0x462) & ~0x3f) | 0x36;
1309
1310 for (i = 0; i < 7; i++) {
1311 if (i == 1)
1312 continue;
1313 MCHBAR8(rcompctl[i]) = MCHBAR8(rcompctl[i]) & ~0x60;
1314 MCHBAR16(rcompctl[i]+2) = MCHBAR16(rcompctl[i]+2) & ~0x706;
1315 MCHBAR16(rcompctl[i]+0xa) = MCHBAR16(rcompctl[i]+0xa) & ~0x7f7f;
1316 MCHBAR16(rcompctl[i]+0x12) = MCHBAR16(rcompctl[i]+0x12) & ~0x3f3f;
1317 MCHBAR16(rcompctl[i]+0x24) = MCHBAR16(rcompctl[i]+0x24) & ~0x1f1f;
1318 MCHBAR8(rcompctl[i]+0x26) = MCHBAR8(rcompctl[i]+0x26) & ~0x1f;
1319 }
1320
1321 MCHBAR16(0x45a) = MCHBAR16(0x45a) & ~0xffc0;
1322 MCHBAR16(0x45c) = MCHBAR16(0x45c) & ~0xf;
1323 MCHBAR16(0x462) = MCHBAR16(0x462) & ~0xffc0;
1324 MCHBAR16(0x464) = MCHBAR16(0x464) & ~0xf;
1325
1326 for (i = 0; i < 7; i++) {
1327 if (i == 1)
1328 continue;
1329 MCHBAR16(rcompctl[i]+0x10) = rcompf[i];
1330 MCHBAR16(rcompctl[i]+0x20) = 0x1219;
1331 MCHBAR16(rcompctl[i]+0x22) = 0x000C;
1332 }
1333
1334 MCHBAR32(0x164) = (MCHBAR32(0x164) & ~0x1f1f1f) | 0x0c1219;
1335 MCHBAR16(0x4b0) = (MCHBAR16(0x4b0) & ~0x1f00) | 0x1200;
1336 MCHBAR8(0x4b0) = (MCHBAR8(0x4b0) & ~0x1f) | 0x12;
1337 MCHBAR32(0x138) = 0x007C9007;
1338 MCHBAR32(0x16c) = rcomp1;
1339 MCHBAR16(0x17a) = 0x1f7f;
1340 MCHBAR32(0x134) = rcomp2;
1341 MCHBAR16(0x170) = (MCHBAR16(0x170) & ~0xf) | 1;
1342 MCHBAR16(0x178) = 0x134;
1343 MCHBAR32(0x130) = 0x4C293600;
1344 MCHBAR8(0x133) = (MCHBAR8(0x133) & ~0x44) | (1 << 6) | (1 << 2);
1345 MCHBAR16(0x4b0) = MCHBAR16(0x4b0) & ~(1 << 13);
1346 MCHBAR8(0x4b0) = MCHBAR8(0x4b0) & ~(1 << 5);
1347
1348 for (i = 0; i < 7; i++) {
1349 if (i == 1)
1350 continue;
1351 MCHBAR8(rcompctl[i]+2) = MCHBAR8(rcompctl[i]) & ~0x71;
1352 }
1353
1354 if ((MCHBAR32(0x130) & (1 << 30)) == 0) {
1355 MCHBAR8(0x130) = MCHBAR8(0x130) | 0x1;
1356 while ((MCHBAR8(0x130) & 0x1) != 0);
1357
1358 reg32 = MCHBAR32(0x13c);
1359 rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1360 rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1361
1362 for (i = 0; i < 7; i++) {
1363 if (i == 1)
1364 continue;
1365 srup = (MCHBAR8(rcompctl[i]+1) & 0xc0) >> 6;
1366 srun = (MCHBAR8(rcompctl[i]+1) & 0x30) >> 4;
1367 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
1368 MCHBAR16(rcompctl[i]+0x16) = (MCHBAR16(rcompctl[i]+0x16)
1369 & ~0x7f00) | reg16;
1370 reg16 = (u16)(rcompn - (1 << (srun + 1)));
1371 MCHBAR8(rcompctl[i]+0x16) = (MCHBAR8(rcompctl[i]+0x16) &
1372 ~0x7f) | (u8)reg16;
1373 }
1374
1375 reg8 = rcompp - (1 << (srup + 1));
1376 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1377 MCHBAR8(rcompctl[0]+0x18+i) =
1378 (MCHBAR8(rcompctl[0]+0x18+i) & ~0x3f) |
1379 rcomplut[j][0];
1380 }
1381
1382 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1383 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1384 MCHBAR8(rcompctl[2]+0x18+i) =
1385 (MCHBAR8(rcompctl[2]+0x18+i) & ~0x3f) |
1386 rcomplut[j][10];
1387 }
1388 }
1389
1390 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1391 MCHBAR8(rcompctl[3]+0x18+i) =
1392 (MCHBAR8(rcompctl[3]+0x18+i) & ~0x3f) |
1393 rcomplut[j][6];
1394 MCHBAR8(rcompctl[4]+0x18+i) =
1395 (MCHBAR8(rcompctl[4]+0x18+i) & ~0x3f) |
1396 rcomplut[j][6];
1397 }
1398
1399 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1400 MCHBAR8(rcompctl[5]+0x18+i) =
1401 (MCHBAR8(rcompctl[5]+0x18+i) & ~0x3f) |
1402 rcomplut[j][8];
1403 MCHBAR8(rcompctl[6]+0x18+i) =
1404 (MCHBAR8(rcompctl[6]+0x18+i) & ~0x3f) |
1405 rcomplut[j][8];
1406 }
1407
1408 reg8 = rcompn - (1 << (srun + 1));
1409 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1410 MCHBAR8(rcompctl[0]+0x1c+i) =
1411 (MCHBAR8(rcompctl[0]+0x1c+i) & ~0x3f) |
1412 rcomplut[j][1];
1413 }
1414
1415 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1416 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
1417 MCHBAR8(rcompctl[2]+0x1c+i) =
1418 (MCHBAR8(rcompctl[2]+0x1c+i) & ~0x3f) |
1419 rcomplut[j][11];
1420 }
1421 }
1422
1423 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1424 MCHBAR8(rcompctl[3]+0x1c+i) =
1425 (MCHBAR8(rcompctl[3]+0x1c+i) & ~0x3f) |
1426 rcomplut[j][7];
1427 MCHBAR8(rcompctl[4]+0x1c+i) =
1428 (MCHBAR8(rcompctl[4]+0x1c+i) & ~0x3f) |
1429 rcomplut[j][7];
1430 }
1431
1432 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1433 MCHBAR8(rcompctl[5]+0x1c+i) =
1434 (MCHBAR8(rcompctl[5]+0x1c+i) & ~0x3f) |
1435 rcomplut[j][9];
1436 MCHBAR8(rcompctl[6]+0x1c+i) =
1437 (MCHBAR8(rcompctl[6]+0x1c+i) & ~0x3f) |
1438 rcomplut[j][9];
1439 }
1440 }
1441 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1442}
1443
1444static void sdram_odt(struct sysinfo *s)
1445{
1446 u8 rankindex = 0;
1447
Arthur Heymans6bf13012017-06-10 12:03:27 +02001448 static const u16 odt294[16] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001449 0x0000, 0x0000, 0x0000, 0x0000,
1450 0x0044, 0x1111, 0x0000, 0x1111,
1451 0x0000, 0x0000, 0x0000, 0x0000,
1452 0x0044, 0x1111, 0x0000, 0x1111
1453 };
Arthur Heymans6bf13012017-06-10 12:03:27 +02001454 static const u16 odt298[16] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001455 0x0000, 0x0011, 0x0000, 0x0011,
1456 0x0000, 0x4444, 0x0000, 0x4444,
1457 0x0000, 0x0000, 0x0000, 0x0000,
1458 0x0000, 0x4444, 0x0000, 0x4444
1459 };
1460
1461 switch (s->dimms[0].ranks) {
1462 case 0:
1463 if (s->dimms[1].ranks == 0) {
1464 rankindex = 0;
1465 } else if (s->dimms[1].ranks == 1) {
1466 rankindex = 4;
1467 } else if (s->dimms[1].ranks == 2) {
1468 rankindex = 12;
1469 }
1470 break;
1471 case 1:
1472 if (s->dimms[1].ranks == 0) {
1473 rankindex = 1;
1474 } else if (s->dimms[1].ranks == 1) {
1475 rankindex = 5;
1476 } else if (s->dimms[1].ranks == 2) {
1477 rankindex = 13;
1478 }
1479 break;
1480 case 2:
1481 if (s->dimms[1].ranks == 0) {
1482 rankindex = 3;
1483 } else if (s->dimms[1].ranks == 1) {
1484 rankindex = 7;
1485 } else if (s->dimms[1].ranks == 2) {
1486 rankindex = 15;
1487 }
1488 break;
1489 }
1490
1491 MCHBAR16(0x298) = odt298[rankindex];
1492 MCHBAR16(0x294) = odt294[rankindex];
1493}
1494
1495static void sdram_mmap(struct sysinfo *s)
1496{
Arthur Heymans6bf13012017-06-10 12:03:27 +02001497 static const u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000,
1498 0xc00001, 0xf00000};
1499 static const u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101,
1500 0x1010000, 0x1010101};
1501 static const u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1502 static const u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006,
1503 0x40002, 0x80006};
Damien Zammit003d15c2015-11-20 17:17:51 +11001504
Arthur Heymans6bf13012017-06-10 12:03:27 +02001505 static const u16 tolud[7] = {0x800, 0x800, 0x1000, 0x1000, 0x2000,
1506 0x1000, 0x2000};
1507 static const u16 tom[7] = {0x2, 0x2, 0x4, 0x4, 0x8, 0x4, 0x8};
1508 static const u16 touud[7] = {0x80, 0x80, 0x100, 0x100, 0x200, 0x100,
1509 0x200};
1510 static const u32 gbsm[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000,
1511 0x20000000, 0x10000000, 0x20000000};
1512 static const u32 bgsm[7] = {0x8000000, 0x8000000, 0x10000000, 0x8000000,
1513 0x20000000, 0x10000000, 0x20000000};
1514 static const u32 tsegmb[7] = {0x8000000, 0x8000000, 0x10000000,
1515 0x8000000, 0x20000000, 0x10000000,
1516 0x20000000};
Damien Zammit003d15c2015-11-20 17:17:51 +11001517
1518 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1519 if (s->dimms[0].sides > 1) {
1520 // 2R/NC
1521 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x300001;
1522 MCHBAR32(0x208) = 0x101;
1523 MCHBAR32(0x200) = 0x40002;
1524 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1525 } else {
1526 // 1R/NC
1527 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x100001;
1528 MCHBAR32(0x208) = 0x1;
1529 MCHBAR32(0x200) = 0x20002;
1530 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1531 }
1532 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
1533
1534 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | 0x300001;
1535 MCHBAR32(0x208) = 0x101;
1536 MCHBAR32(0x200) = 0x40002;
1537 MCHBAR32(0x204) = 0x40004;
1538 } else {
1539 MCHBAR32(0x260) = (MCHBAR32(0x260) & ~0x1) | w260[s->dimm_config[0]];
1540 MCHBAR32(0x208) = w208[s->dimm_config[0]];
1541 MCHBAR32(0x200) = w200[s->dimm_config[0]];
1542 MCHBAR32(0x204) = w204[s->dimm_config[0]];
1543 }
1544 pci_write_config16(PCI_DEV(0, 0, 0), 0xb0, tolud[s->dimm_config[0]]);
1545 pci_write_config16(PCI_DEV(0, 0, 0), 0xa0, tom[s->dimm_config[0]]);
1546 pci_write_config16(PCI_DEV(0, 0, 0), 0xa2, touud[s->dimm_config[0]]);
1547 pci_write_config32(PCI_DEV(0, 0, 0), 0xa4, gbsm[s->dimm_config[0]]);
1548 pci_write_config32(PCI_DEV(0, 0, 0), 0xa8, bgsm[s->dimm_config[0]]);
1549 pci_write_config32(PCI_DEV(0, 0, 0), 0xac, tsegmb[s->dimm_config[0]]);
1550}
1551
1552#if 1
1553static void hpet_udelay(u32 del)
1554{
1555 u32 start, finish, now;
1556
1557 del *= 15; /* now in usec */
1558
1559 start = HPET32(0xf0);
1560 finish = start + del;
1561 while (1) {
1562 now = HPET32(0xf0);
1563 if (finish > start) {
1564 if (now >= finish)
1565 break;
1566 } else {
1567 if ((now < start) && (now >= finish)) {
1568 break;
1569 }
1570 }
1571 }
1572}
1573#endif
1574
1575static u8 sdram_checkrcompoverride(void)
1576{
1577 u32 xcomp;
1578 u8 aa, bb, a, b, c, d;
1579
1580 xcomp = MCHBAR32(0x13c);
1581 a = (u8)((xcomp & 0x7f000000) >> 24);
1582 b = (u8)((xcomp & 0x7f0000) >> 16);
1583 c = (u8)((xcomp & 0x3f00) >> 8);
1584 d = (u8)(xcomp & 0x3f);
1585
1586 if (a > b) {
1587 aa = a - b;
1588 } else {
1589 aa = b - a;
1590 }
1591 if (c > d) {
1592 bb = c - d;
1593 } else {
1594 bb = d - c;
1595 }
1596 if ((aa > 18) || (bb > 7) ||
1597 (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
1598 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
1599 MCHBAR32(0x140) = 0x9718a729;
1600 return 1;
1601 }
1602 return 0;
1603}
1604
1605static void sdram_rcompupdate(struct sysinfo *s)
1606{
1607 u8 i, ok;
1608 u32 reg32a, reg32b;
1609
1610 ok = 0;
1611 MCHBAR8(0x170) = MCHBAR8(0x170) & ~(1 << 3);
1612 MCHBAR8(0x130) = MCHBAR8(0x130) & ~(1 << 7);
1613 for (i = 0; i < 3; i++) {
1614 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1615 hpet_udelay(1000);
1616 while ((MCHBAR8(0x130) & 0x1) != 0);
1617 ok |= sdram_checkrcompoverride();
1618 }
1619 if (!ok) {
1620 reg32a = MCHBAR32(0x13c);
1621 reg32b = (reg32a >> 16) & 0x0000ffff;
1622 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1623 reg32a |= (1 << 31) | (1 << 15);
1624 MCHBAR32(0x140) = reg32a;
1625 }
1626 MCHBAR8(0x130) = MCHBAR8(0x130) | 1;
1627 hpet_udelay(1000);
1628 while ((MCHBAR8(0x130) & 0x1) != 0);
1629}
1630
1631static void __attribute__((noinline))
1632sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1633{
1634 u32 reg32;
1635
1636 reg32 = jval << 3;
1637 reg32 |= rank * 0x8000000;
1638 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | jmode;
1639 read32((void *)reg32);
1640 barrier();
1641 hpet_udelay(1); // 1us
1642}
1643
1644static void sdram_zqcl(struct sysinfo *s)
1645{
1646 if (s->boot_path == BOOT_PATH_RESUME) {
1647 MCHBAR32(0x260) = MCHBAR32(0x260) | (1 << 27);
1648 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0xe) | NORMAL_OP_CMD;
1649 MCHBAR8(0x271) = MCHBAR8(0x271) & ~0x30;
1650 MCHBAR32(0x268) = (MCHBAR32(0x268) & ~((1 << 30) | (1 << 31))) |
1651 (1 << 30) | (1 << 31);
1652 }
1653}
1654
1655static void sdram_jedecinit(struct sysinfo *s)
1656{
1657 u8 r, i, ch;
1658 u16 reg16, mrs, rttnom;
1659 struct jedeclist {
1660 char debug[15];
1661 u8 cmd;
1662 u16 val;
1663 };
1664
Arthur Heymans6bf13012017-06-10 12:03:27 +02001665 static const struct jedeclist jedec[12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001666 { " NOP ", NOP_CMD, 0 },
1667 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1668 { " EMRS2 ", EMRS2_CMD, 0 },
1669 { " EMRS3 ", EMRS3_CMD, 0 },
1670 { " EMRS1 ", EMRS1_CMD, 0 },
1671 { " DLL RESET ", MRS_CMD, (1 << 8) },
1672 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1673 { " AUTOREFRESH", CBR_CMD, 0 },
1674 { " AUTOREFRESH", CBR_CMD, 0 },
1675 { " INITIALISE ", MRS_CMD, 0 },
1676 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1677 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1678 };
1679
1680 mrs = (s->selected_timings.CAS << 4) |
1681 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 1;
1682 rttnom = (1 << 2);
1683 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1684 rttnom |= (1 << 6);
1685 }
1686
1687 hpet_udelay(200); // 200us
1688 reg16 = 0;
1689 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1690 for (i = 0; i < 12; i++) {
1691 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1692 reg16 = jedec[i].val;
1693 switch (jedec[i].cmd) {
1694 case EMRS1_CMD:
1695 reg16 |= rttnom;
1696 break;
1697 case MRS_CMD:
1698 reg16 |= mrs;
1699 break;
1700 default:
1701 break;
1702 }
1703 sdram_jedec(s, r, jedec[i].cmd, reg16);
1704 PRINTK_DEBUG("done\n");
1705 }
1706 }
1707}
1708
1709static void sdram_misc(struct sysinfo *s)
1710{
1711 u32 reg32;
1712
1713 reg32 = 0;
1714 reg32 |= (0x4 << 13);
1715 reg32 |= (0x6 << 8);
1716 MCHBAR32(0x274) = (MCHBAR32(0x274) & ~0x3ff00) | reg32;
1717 MCHBAR8(0x274) = MCHBAR8(0x274) & ~(1 << 7);
1718 MCHBAR8(0x26c) = MCHBAR8(0x26c) | 1;
1719 if (s->boot_path != BOOT_PATH_RESUME) {
1720 MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0xe) | NORMAL_OP_CMD;
1721 MCHBAR8(0x271) = MCHBAR8(0x271) & ~0x30;
1722 } else {
1723 sdram_zqcl(s);
1724 }
1725}
1726
1727static void sdram_checkreset(void)
1728{
1729 u8 pmcon2, pmcon3, reset;
1730
1731 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1732 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1733 pmcon3 &= ~0x2;
1734 if (pmcon2 & 0x80) {
1735 pmcon2 &= ~0x80;
1736 reset = 1;
1737 } else {
1738 pmcon2 |= 0x80;
1739 reset = 0;
1740 }
1741 if (pmcon2 & 0x4) {
1742 pmcon2 |= 0x4;
1743 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1744 pmcon3 |= (1 << 3);
1745 }
1746 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1747 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +02001748 if (reset)
1749 full_reset();
Damien Zammit003d15c2015-11-20 17:17:51 +11001750}
1751
1752static void sdram_dradrb(struct sysinfo *s)
1753{
1754 u8 i, reg8, ch, r;
1755 u32 reg32, ind, c0dra, c0drb, dra;
1756 u16 addr;
1757 i = 0;
Arthur Heymans6bf13012017-06-10 12:03:27 +02001758 static const u8 dratab[2][2][2][4] =
Damien Zammit003d15c2015-11-20 17:17:51 +11001759 {{
1760 {
1761 {0xff, 0xff, 0xff, 0xff},
1762 {0xff, 0x00, 0x02, 0xff}
1763 },
1764 {
1765 {0xff, 0x01, 0xff, 0xff},
1766 {0xff, 0x03, 0xff, 0x06}
1767 }
1768 },
1769 {
1770 {
1771 {0xff, 0xff, 0xff, 0xff},
1772 {0xff, 0x04, 0x06, 0x08}
1773 },
1774 {
1775 {0xff, 0xff, 0xff, 0xff},
1776 {0x05, 0x07, 0x09, 0xff}
1777 }
1778 }};
1779
Arthur Heymans6bf13012017-06-10 12:03:27 +02001780 static const u8 dradrb[10][6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001781 //Row Col Bank Width DRB
1782 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1783 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1784 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1785 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1786 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1787 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1788 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1789 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1790 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1791 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1792 };
1793
1794 reg32 = 0;
1795 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1796 i = r / 2;
1797 PRINTK_DEBUG("RANK %d PRESENT\n", r);
1798 dra = dratab[s->dimms[i].banks]
1799 [s->dimms[i].width]
1800 [s->dimms[i].cols - 9]
1801 [s->dimms[i].rows - 12];
1802
1803 if (s->dimms[i].banks == 1) {
1804 dra |= (1 << 7);
1805 }
1806 reg32 |= (dra << (r*8));
1807 }
1808 MCHBAR32(0x208) = reg32;
1809 c0dra = reg32;
1810 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1811
1812 reg32 = 0;
1813 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1814 reg32 |= (1 << r);
1815 }
1816 reg8 = (u8)(reg32 << 4) & 0xf0;
1817 MCHBAR8(0x262) = (MCHBAR8(0x262) & ~0xf0) | reg8;
1818 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) ||
1819 ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1820 MCHBAR8(0x260) = MCHBAR8(0x260) | 1;
1821 }
1822
1823 addr = 0x200;
1824 c0drb = 0;
1825 FOR_EACH_RANK(ch, r) {
1826 if (rank_is_populated(s->dimms, ch, r)) {
1827 ind = (c0dra >> (8*r)) & 0x7f;
1828 c0drb = (u16)(c0drb + dradrb[ind][5]);
1829 s->channel_capacity[0] += dradrb[ind][5] << 6;
1830 }
1831 MCHBAR16(addr) = c0drb;
1832 addr += 2;
1833 }
1834 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1835}
1836
1837static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1838{
1839 volatile u32 strobedata;
1840 u8 dqsmatches = 1;
1841 while (count--) {
1842 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0x2;
1843 hpet_udelay(1);
1844 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) | 0x2;
1845 hpet_udelay(1);
1846 barrier();
Elyes HAOUASfd051dc2018-07-08 12:39:34 +02001847 strobedata = read32((void *)strobeaddr);
Damien Zammit003d15c2015-11-20 17:17:51 +11001848 barrier();
1849 hpet_udelay(1);
1850
1851 if (((MCHBAR8(dqshighaddr) & 0x40) >> 6) != highlow) {
1852 dqsmatches = 0;
1853 }
1854 }
1855
1856 return dqsmatches;
1857}
1858
1859static void rcvenclock(u8 *coarse, u8 *medium, u8 bytelane)
1860{
1861 if (*medium < 3) {
1862 (*medium)++;
1863 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~(0x3 << (bytelane*2))))
1864 | (*medium << (bytelane*2));
1865 } else {
1866 *medium = 0;
1867 (*coarse)++;
1868 MCHBAR32(0x248) = (MCHBAR32(0x248) & ~0xf0000) | (*coarse << 16);
1869 MCHBAR16(0x58c) = (MCHBAR16(0x58c) & (u16)(~0x3 << (bytelane*2)))
1870 | (*medium << (bytelane*2));
1871 }
1872}
1873
1874static void sdram_rcven(struct sysinfo *s)
1875{
1876 u8 curcoarse, savecoarse;
1877 u8 curmedium, savemedium;
1878 u8 pi, savepi;
1879 u8 bytelane;
1880 u8 bytelanecoarse[8] = { 0 };
1881 u8 minbytelanecoarse = 0xff;
1882 u8 bytelaneoffset;
1883 u8 maxbytelane = 8;
Arthur Heymans015339f2018-08-20 11:28:58 +02001884 /* Since dra/drb is already set up we know that at address 0x00000000
1885 we will always find the first available rank */
1886 u32 strobeaddr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001887 u32 dqshighaddr;
1888
1889 MCHBAR8(0x5d8) = MCHBAR8(0x5d8) & ~0xc;
1890 MCHBAR8(0x5dc) = MCHBAR8(0x5dc) & ~0x80;
1891
1892 PRINTK_DEBUG("rcven 0\n");
1893 for (bytelane = 0; bytelane < maxbytelane; bytelane++) {
1894 PRINTK_DEBUG("rcven bytelane %d\n", bytelane);