blob: af846e3588d48168764d48f781f005df96eaddcb [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Damien Zammit003d15c2015-11-20 17:17:51 +11002
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +02003#include <cf9_reset.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02005#include <device/pci_ops.h>
Elyes HAOUASf97c1c92019-12-03 18:22:06 +01006#include <commonlib/helpers.h>
Damien Zammit003d15c2015-11-20 17:17:51 +11007#include <console/console.h>
Damien Zammit003d15c2015-11-20 17:17:51 +11008#include <delay.h>
Damien Zammit003d15c2015-11-20 17:17:51 +11009#include <lib.h>
10#include "pineview.h"
11#include "raminit.h"
Damien Zammit003d15c2015-11-20 17:17:51 +110012#include <spd.h>
13#include <string.h>
14
Angel Pons39ff7032020-03-09 21:39:44 +010015/* Debugging macros */
Julius Wernercd49cce2019-03-05 16:53:33 -080016#if CONFIG(DEBUG_RAM_SETUP)
Damien Zammit003d15c2015-11-20 17:17:51 +110017#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
18#else
19#define PRINTK_DEBUG(x...)
20#endif
21
22#define MAX_TCLK_667 0x30
23#define MAX_TCLK_800 0x25
24#define MAX_TAC_667 0x45
25#define MAX_TAC_800 0x40
26
27#define NOP_CMD (1 << 1)
28#define PRE_CHARGE_CMD (1 << 2)
29#define MRS_CMD ((1 << 2) | (1 << 1))
30#define EMRS_CMD (1 << 3)
31#define EMRS1_CMD (EMRS_CMD | (1 << 4))
32#define EMRS2_CMD (EMRS_CMD | (1 << 5))
33#define EMRS3_CMD (EMRS_CMD | (1 << 5) | (1 << 4))
34#define ZQCAL_CMD ((1 << 3) | (1 << 1))
35#define CBR_CMD ((1 << 3) | (1 << 2))
36#define NORMAL_OP_CMD ((1 << 3) | (1 << 2) | (1 << 1))
37
38#define UBDIMM 1
39#define SODIMM 2
40
41#define TOTAL_CHANNELS 1
42#define TOTAL_DIMMS 2
43
44#define DIMM_IS_POPULATED(dimms, idx) (dimms[idx].card_type != 0)
45#define IF_DIMM_POPULATED(dimms, idx) if (dimms[idx].card_type != 0)
Elyes HAOUASa342f392018-10-17 10:56:26 +020046#define ONLY_DIMMA_IS_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110047 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
48 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3)))
Elyes HAOUASa342f392018-10-17 10:56:26 +020049#define ONLY_DIMMB_IS_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110050 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3) && \
51 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2)))
Elyes HAOUASa342f392018-10-17 10:56:26 +020052#define BOTH_DIMMS_ARE_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110053 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
54 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3))))
55#define FOR_EACH_DIMM(idx) \
56 for (idx = 0; idx < TOTAL_DIMMS; ++idx)
57#define FOR_EACH_POPULATED_DIMM(dimms, idx) \
58 FOR_EACH_DIMM(idx) IF_DIMM_POPULATED(dimms, idx)
59#define CHANNEL_IS_POPULATED(dimms, idx) ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0))
60#define CHANNEL_IS_CARDF(dimms, idx) ((dimms[idx<<1].card_type == 0xf) || (dimms[(idx<<1) + 1].card_type == 0xf))
61#define IF_CHANNEL_POPULATED(dimms, idx) if ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0))
62#define FOR_EACH_CHANNEL(idx) \
63 for (idx = 0; idx < TOTAL_CHANNELS; ++idx)
64#define FOR_EACH_POPULATED_CHANNEL(dimms, idx) \
65 FOR_EACH_CHANNEL(idx) IF_CHANNEL_POPULATED(dimms, idx)
66
67#define RANKS_PER_CHANNEL 4
68
69#define FOR_EACH_RANK_IN_CHANNEL(r) \
70 for (r = 0; r < RANKS_PER_CHANNEL; ++r)
71#define FOR_EACH_POPULATED_RANK_IN_CHANNEL(dimms, ch, r) \
72 FOR_EACH_RANK_IN_CHANNEL(r) if (rank_is_populated(dimms, ch, r))
73#define FOR_EACH_RANK(ch, r) \
74 FOR_EACH_CHANNEL(ch) FOR_EACH_RANK_IN_CHANNEL(r)
75#define FOR_EACH_POPULATED_RANK(dimms, ch, r) \
76 FOR_EACH_RANK(ch, r) if (rank_is_populated(dimms, ch, r))
77
78static bool rank_is_populated(struct dimminfo dimms[], u8 ch, u8 r)
79{
80 return ((dimms[ch<<1].card_type && ((r) < dimms[ch<<1].ranks))
81 || (dimms[(ch<<1) + 1].card_type
82 && ((r) >= 2)
83 && ((r) < (dimms[(ch<<1) + 1].ranks + 2))));
84}
85
86static inline void barrier(void)
87{
88 __asm__ __volatile__("": : :"memory");
89}
90
Arthur Heymans097d7532017-04-17 10:14:32 +020091static int decode_spd(struct dimminfo *d, int i)
Damien Zammit003d15c2015-11-20 17:17:51 +110092{
93 d->type = 0;
94 if (d->spd_data[20] == 0x2) {
95 d->type = UBDIMM;
96 } else if (d->spd_data[20] == 0x4) {
97 d->type = SODIMM;
98 }
99 d->sides = (d->spd_data[5] & 0x7) + 1;
100 d->banks = (d->spd_data[17] >> 2) - 1;
101 d->chip_capacity = d->banks;
102 d->rows = d->spd_data[3];// - 12;
103 d->cols = d->spd_data[4];// - 9;
104 d->cas_latencies = 0x78;
105 d->cas_latencies &= d->spd_data[18];
106 if (d->cas_latencies == 0)
107 d->cas_latencies = 7;
108 d->tAAmin = d->spd_data[26];
109 d->tCKmin = d->spd_data[25];
110 d->width = (d->spd_data[13] >> 3) - 1;
111 d->page_size = (d->width+1) * (1 << d->cols); // Bytes
112 d->tRAS = d->spd_data[30];
113 d->tRP = d->spd_data[27];
114 d->tRCD = d->spd_data[29];
115 d->tWR = d->spd_data[36];
116 d->ranks = d->sides; // XXX
Julius Wernercd49cce2019-03-05 16:53:33 -0800117#if CONFIG(DEBUG_RAM_SETUP)
Arthur Heymans097d7532017-04-17 10:14:32 +0200118 const char *ubso[2] = { "UB", "SO" };
Damien Zammit003d15c2015-11-20 17:17:51 +1100119#endif
120 PRINTK_DEBUG("%s-DIMM %d\n", &ubso[d->type][0], i);
121 PRINTK_DEBUG(" Sides : %d\n", d->sides);
122 PRINTK_DEBUG(" Banks : %d\n", d->banks);
123 PRINTK_DEBUG(" Ranks : %d\n", d->ranks);
124 PRINTK_DEBUG(" Rows : %d\n", d->rows);
125 PRINTK_DEBUG(" Cols : %d\n", d->cols);
126 PRINTK_DEBUG(" Page size : %d\n", d->page_size);
127 PRINTK_DEBUG(" Width : %d\n", (d->width + 1) * 8);
128
129 return 0;
130}
131
Angel Pons39ff7032020-03-09 21:39:44 +0100132/*
133 * RAM Config: DIMMB-DIMMA
Damien Zammit003d15c2015-11-20 17:17:51 +1100134 * 0 EMPTY-EMPTY
135 * 1 EMPTY-x16SS
136 * 2 EMPTY-x16DS
137 * 3 x16SS-x16SS
138 * 4 x16DS-x16DS
139 * 5 EMPTY- x8DS
140 * 6 x8DS - x8DS
141 */
142static void find_ramconfig(struct sysinfo *s, u32 chan)
143{
144 if (s->dimms[chan>>1].sides == 0) {
145 // NC
146 if (s->dimms[(chan>>1) + 1].sides == 0) {
147 // NC/NC
148 s->dimm_config[chan] = 0;
149 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
150 // NC/SS
151 if (s->dimms[(chan>>1) + 1].width == 0) {
152 // NC/8SS
153 s->dimm_config[chan] = 1;
154 } else {
155 // NC/16SS
156 s->dimm_config[chan] = 1;
157 }
158 } else {
159 // NC/DS
160 if (s->dimms[(chan>>1) + 1].width == 0) {
161 // NC/8DS
162 s->dimm_config[chan] = 5;
163 } else {
164 // NC/16DS
165 s->dimm_config[chan] = 2;
166 }
167 }
168 } else if (s->dimms[chan>>1].sides == 1) {
169 // SS
170 if (s->dimms[(chan>>1) + 1].sides == 0) {
171 // SS/NC
172 if (s->dimms[chan>>1].width == 0) {
173 // 8SS/NC
174 s->dimm_config[chan] = 1;
175 } else {
176 // 16SS/NC
177 s->dimm_config[chan] = 1;
178 }
179 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
180 // SS/SS
181 if (s->dimms[chan>>1].width == 0) {
182 if (s->dimms[(chan>>1) + 1].width == 0) {
183 // 8SS/8SS
184 s->dimm_config[chan] = 3;
185 } else {
186 // 8SS/16SS
187 die("Mixed Not supported\n");
188 }
189 } else {
190 if (s->dimms[(chan>>1) + 1].width == 0) {
191 // 16SS/8SS
192 die("Mixed Not supported\n");
193 } else {
194 // 16SS/16SS
195 s->dimm_config[chan] = 3;
196 }
197 }
198 } else {
199 // SS/DS
200 if (s->dimms[chan>>1].width == 0) {
201 if (s->dimms[(chan>>1) + 1].width == 0) {
202 // 8SS/8DS
203 die("Mixed Not supported\n");
204 } else {
205 die("Mixed Not supported\n");
206 }
207 } else {
208 if (s->dimms[(chan>>1) + 1].width == 0) {
209 // 16SS/8DS
210 die("Mixed Not supported\n");
211 } else {
212 die("Mixed Not supported\n");
213 }
214 }
215 }
216 } else {
217 // DS
218 if (s->dimms[(chan>>1) + 1].sides == 0) {
219 // DS/NC
220 if (s->dimms[chan>>1].width == 0) {
221 // 8DS/NC
222 s->dimm_config[chan] = 5;
223 } else {
224 s->dimm_config[chan] = 4;
225 }
226 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
227 // DS/SS
228 if (s->dimms[chan>>1].width == 0) {
229 if (s->dimms[(chan>>1) + 1].width == 0) {
230 // 8DS/8SS
231 die("Mixed Not supported\n");
232 } else {
233 // 8DS/16SS
234 die("Mixed Not supported\n");
235 }
236 } else {
237 if (s->dimms[(chan>>1) + 1].width == 0) {
238 die("Mixed Not supported\n");
239 } else {
240 // 16DS/16DS
241 s->dimm_config[chan] = 4;
242 }
243 }
244 } else {
245 // DS/DS
246 if (s->dimms[chan>>1].width == 0 && s->dimms[(chan>>1)+1].width == 0) {
247 // 8DS/8DS
248 s->dimm_config[chan] = 6;
249 }
250 }
251 }
252}
253
254static void sdram_read_spds(struct sysinfo *s)
255{
Arthur Heymans1f6369e2018-08-20 11:27:41 +0200256 u8 i, chan;
Damien Zammit003d15c2015-11-20 17:17:51 +1100257 s->dt0mode = 0;
258 FOR_EACH_DIMM(i) {
Kyösti Mälkkic01a5052019-01-30 09:39:23 +0200259 if (i2c_eeprom_read(s->spd_map[i], 0, 64, s->dimms[i].spd_data) != 64)
Arthur Heymans1f6369e2018-08-20 11:27:41 +0200260 s->dimms[i].card_type = 0;
261
262 s->dimms[i].card_type = s->dimms[i].spd_data[62] & 0x1f;
Damien Zammit003d15c2015-11-20 17:17:51 +1100263 hexdump(s->dimms[i].spd_data, 64);
264 }
265
266 s->spd_type = 0;
267 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
268 switch (s->dimms[i].spd_data[2]) {
269 case 0x8:
270 s->spd_type = DDR2;
271 break;
272 case 0xb:
273 default:
274 die("DIMM type mismatch\n");
275 break;
276 }
277 }
278
279 int err = 1;
280 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Arthur Heymans097d7532017-04-17 10:14:32 +0200281 err = decode_spd(&s->dimms[i], i);
Damien Zammit003d15c2015-11-20 17:17:51 +1100282 s->dt0mode |= (s->dimms[i].spd_data[49] & 0x2) >> 1;
283 }
284 if (err) {
285 die("No memory dimms, halt\n");
286 }
287
288 FOR_EACH_POPULATED_CHANNEL(s->dimms, chan) {
289 find_ramconfig(s, chan);
Angel Pons39ff7032020-03-09 21:39:44 +0100290 PRINTK_DEBUG(" Config[CH%d] : %d\n", chan, s->dimm_config[chan]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100291 }
292}
293
Julius Wernercd49cce2019-03-05 16:53:33 -0800294#if CONFIG(DEBUG_RAM_SETUP)
Damien Zammit003d15c2015-11-20 17:17:51 +1100295static u32 fsb_reg_to_mhz(u32 speed)
296{
297 return (speed * 133) + 667;
298}
299
300static u32 ddr_reg_to_mhz(u32 speed)
301{
Angel Pons39ff7032020-03-09 21:39:44 +0100302 return (speed == 0) ? 667 : (speed == 1) ? 800 : 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100303}
304#endif
305
Jacob Garberb70c7762019-03-25 18:20:06 -0600306// Return the position of the least significant set bit, 0-indexed.
307// 0 does not have a lsb, so return -1 for error.
308static int lsbpos(u8 val)
Damien Zammit003d15c2015-11-20 17:17:51 +1100309{
Jacob Garberb70c7762019-03-25 18:20:06 -0600310 for (int i = 0; i < 8; i++)
311 if (val & (1 << i))
312 return i;
313 return -1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100314}
315
Jacob Garberb70c7762019-03-25 18:20:06 -0600316// Return the position of the most significant set bit, 0-indexed.
317// 0 does not have a msb, so return -1 for error.
318static int msbpos(u8 val)
Damien Zammit003d15c2015-11-20 17:17:51 +1100319{
Jacob Garberb70c7762019-03-25 18:20:06 -0600320 for (int i = 7; i >= 0; i--)
321 if (val & (1 << i))
322 return i;
323 return -1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100324}
325
326static void sdram_detect_smallest_params(struct sysinfo *s)
327{
Arthur Heymans6bf13012017-06-10 12:03:27 +0200328 static const u16 mult[6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100329 3000, // 667
330 2500, // 800
331 };
332
333 u8 i;
Damien Zammit003d15c2015-11-20 17:17:51 +1100334 u32 maxtras = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100335 u32 maxtrp = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100336 u32 maxtrcd = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100337 u32 maxtwr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100338 u32 maxtrfc = 0;
339 u32 maxtwtr = 0;
340 u32 maxtrrd = 0;
341 u32 maxtrtp = 0;
342
343 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Angel Pons39ff7032020-03-09 21:39:44 +0100344 maxtras = MAX(maxtras, (s->dimms[i].spd_data[30] * 1000));
345 maxtrp = MAX(maxtrp, (s->dimms[i].spd_data[27] * 1000) >> 2);
Elyes HAOUASf97c1c92019-12-03 18:22:06 +0100346 maxtrcd = MAX(maxtrcd, (s->dimms[i].spd_data[29] * 1000) >> 2);
Angel Pons39ff7032020-03-09 21:39:44 +0100347 maxtwr = MAX(maxtwr, (s->dimms[i].spd_data[36] * 1000) >> 2);
348 maxtrfc = MAX(maxtrfc, (s->dimms[i].spd_data[42] * 1000) +
349 (s->dimms[i].spd_data[40] & 0xf));
Elyes HAOUASf97c1c92019-12-03 18:22:06 +0100350 maxtwtr = MAX(maxtwtr, (s->dimms[i].spd_data[37] * 1000) >> 2);
351 maxtrrd = MAX(maxtrrd, (s->dimms[i].spd_data[28] * 1000) >> 2);
352 maxtrtp = MAX(maxtrtp, (s->dimms[i].spd_data[38] * 1000) >> 2);
Damien Zammit003d15c2015-11-20 17:17:51 +1100353 }
Arthur Heymans12a4e982017-04-28 20:53:05 +0200354 /*
Angel Pons39ff7032020-03-09 21:39:44 +0100355 * TODO: on DDR3 there might be some minimal required values for some
Arthur Heymans12a4e982017-04-28 20:53:05 +0200356 * Timings: MIN_TRAS = 9, MIN_TRP = 3, MIN_TRCD = 3, MIN_TWR = 3,
357 * MIN_TWTR = 4, MIN_TRRD = 2, MIN_TRTP = 4
358 */
359 s->selected_timings.tRAS = MIN(24, DIV_ROUND_UP(maxtras,
360 mult[s->selected_timings.mem_clock]));
361 s->selected_timings.tRP = MIN(10, DIV_ROUND_UP(maxtrp,
362 mult[s->selected_timings.mem_clock]));
363 s->selected_timings.tRCD = MIN(10, DIV_ROUND_UP(maxtrcd,
364 mult[s->selected_timings.mem_clock]));
365 s->selected_timings.tWR = MIN(15, DIV_ROUND_UP(maxtwr,
366 mult[s->selected_timings.mem_clock]));
367 /* Needs to be even */
368 s->selected_timings.tRFC = 0xfe & (MIN(78, DIV_ROUND_UP(maxtrfc,
369 mult[s->selected_timings.mem_clock])) + 1);
370 s->selected_timings.tWTR = MIN(15, DIV_ROUND_UP(maxtwtr,
371 mult[s->selected_timings.mem_clock]));
372 s->selected_timings.tRRD = MIN(15, DIV_ROUND_UP(maxtrrd,
373 mult[s->selected_timings.mem_clock]));
Arthur Heymans5bb27b72017-08-26 21:24:21 +0200374 s->selected_timings.tRTP = MIN(15, DIV_ROUND_UP(maxtrtp,
Arthur Heymans12a4e982017-04-28 20:53:05 +0200375 mult[s->selected_timings.mem_clock]));
Damien Zammit003d15c2015-11-20 17:17:51 +1100376
377 PRINTK_DEBUG("Selected timings:\n");
378 PRINTK_DEBUG("\tFSB: %dMHz\n", fsb_reg_to_mhz(s->selected_timings.fsb_clock));
379 PRINTK_DEBUG("\tDDR: %dMHz\n", ddr_reg_to_mhz(s->selected_timings.mem_clock));
380
381 PRINTK_DEBUG("\tCAS: %d\n", s->selected_timings.CAS);
382 PRINTK_DEBUG("\ttRAS: %d\n", s->selected_timings.tRAS);
383 PRINTK_DEBUG("\ttRP: %d\n", s->selected_timings.tRP);
384 PRINTK_DEBUG("\ttRCD: %d\n", s->selected_timings.tRCD);
385 PRINTK_DEBUG("\ttWR: %d\n", s->selected_timings.tWR);
386 PRINTK_DEBUG("\ttRFC: %d\n", s->selected_timings.tRFC);
387 PRINTK_DEBUG("\ttWTR: %d\n", s->selected_timings.tWTR);
388 PRINTK_DEBUG("\ttRRD: %d\n", s->selected_timings.tRRD);
389 PRINTK_DEBUG("\ttRTP: %d\n", s->selected_timings.tRTP);
390}
391
392static void sdram_detect_ram_speed(struct sysinfo *s)
393{
394 u8 cas, reg8;
395 u32 reg32;
396 u32 freq = 0;
397 u32 fsb = 0;
398 u8 i;
399 u8 commoncas = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100400 u8 highcas = 0;
401 u8 lowcas = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100402
403 // Core frequency
Angel Pons39ff7032020-03-09 21:39:44 +0100404 fsb = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0x70) >> 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100405 if (fsb) {
406 fsb = 5 - fsb;
407 } else {
408 fsb = FSB_CLOCK_800MHz;
409 }
410
411 // DDR frequency
Angel Pons39ff7032020-03-09 21:39:44 +0100412 freq = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0x80) >> 7;
413 freq |= (pci_read_config8(HOST_BRIDGE, 0xe4) & 0x03) << 1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100414 if (freq) {
415 freq = 6 - freq;
416 } else {
417 freq = MEM_CLOCK_800MHz;
418 }
419
420 // Detect a common CAS latency
421 commoncas = 0xff;
422 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
423 commoncas &= s->dimms[i].spd_data[18];
424 }
425 if (commoncas == 0) {
426 die("No common CAS among dimms\n");
427 }
428
Jacob Garberb70c7762019-03-25 18:20:06 -0600429 // commoncas is nonzero, so these calls will not error
430 u8 msbp = (u8)msbpos(commoncas);
431 u8 lsbp = (u8)lsbpos(commoncas);
432
Damien Zammit003d15c2015-11-20 17:17:51 +1100433 // Start with fastest common CAS
434 cas = 0;
Jacob Garberb70c7762019-03-25 18:20:06 -0600435 highcas = msbp;
Elyes HAOUASf97c1c92019-12-03 18:22:06 +0100436 lowcas = MAX(lsbp, 5);
Damien Zammit003d15c2015-11-20 17:17:51 +1100437
438 while (cas == 0 && highcas >= lowcas) {
439 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
440 switch (freq) {
441 case MEM_CLOCK_800MHz:
Angel Pons39ff7032020-03-09 21:39:44 +0100442 if ((s->dimms[i].spd_data[9] > 0x25) ||
Damien Zammit003d15c2015-11-20 17:17:51 +1100443 (s->dimms[i].spd_data[10] > 0x40)) {
444 // CAS too fast, lower it
445 highcas--;
446 break;
447 } else {
448 cas = highcas;
449 }
450 break;
451 case MEM_CLOCK_667MHz:
452 default:
Angel Pons39ff7032020-03-09 21:39:44 +0100453 if ((s->dimms[i].spd_data[9] > 0x30) ||
Damien Zammit003d15c2015-11-20 17:17:51 +1100454 (s->dimms[i].spd_data[10] > 0x45)) {
455 // CAS too fast, lower it
456 highcas--;
457 break;
458 } else {
459 cas = highcas;
460 }
461 break;
462 }
463 }
464 }
465 if (highcas < lowcas) {
466 // Timings not supported by MCH, lower the frequency
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200467 if (freq == MEM_CLOCK_800MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +1100468 freq--;
469 PRINTK_DEBUG("Run DDR clock speed reduced due to timings\n");
470 } else {
471 die("Timings not supported by MCH\n");
472 }
473 cas = 0;
Jacob Garberb70c7762019-03-25 18:20:06 -0600474 highcas = msbp;
475 lowcas = lsbp;
Damien Zammit003d15c2015-11-20 17:17:51 +1100476 while (cas == 0 && highcas >= lowcas) {
477 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Angel Pons39ff7032020-03-09 21:39:44 +0100478 if ((s->dimms[i].spd_data[9] > 0x30) ||
Jacob Garber78107932019-06-11 12:45:51 -0600479 (s->dimms[i].spd_data[10] > 0x45)) {
480 // CAS too fast, lower it
481 highcas--;
482 } else {
483 cas = highcas;
Damien Zammit003d15c2015-11-20 17:17:51 +1100484 }
485 }
486 }
487 if (cas == 0) {
488 die("Unsupported dimms\n");
489 }
490 }
491
492 s->selected_timings.CAS = cas;
493 s->selected_timings.mem_clock = freq;
494 s->selected_timings.fsb_clock = fsb;
495
Angel Pons39ff7032020-03-09 21:39:44 +0100496 PRINTK_DEBUG("Drive Memory at %dMHz with CAS = %d clocks\n",
497 ddr_reg_to_mhz(s->selected_timings.mem_clock), s->selected_timings.CAS);
Damien Zammit003d15c2015-11-20 17:17:51 +1100498
499 // Set memory frequency
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200500 if (s->boot_path == BOOT_PATH_RESET)
501 return;
Angel Pons39ff7032020-03-09 21:39:44 +0100502
503 MCHBAR32_OR(PMSTS, 1);
504
505 reg32 = (MCHBAR32(CLKCFG) & ~0x70) | (1 << 10);
Damien Zammit003d15c2015-11-20 17:17:51 +1100506 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
507 reg8 = 3;
508 } else {
509 reg8 = 2;
510 }
511 reg32 |= reg8 << 4;
Angel Pons39ff7032020-03-09 21:39:44 +0100512 MCHBAR32(CLKCFG) = reg32;
513
514 s->selected_timings.mem_clock = ((MCHBAR32(CLKCFG) >> 4) & 0x7) - 2;
Damien Zammit003d15c2015-11-20 17:17:51 +1100515 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
516 PRINTK_DEBUG("MCH validated at 800MHz\n");
517 s->nodll = 0;
518 s->maxpi = 63;
519 s->pioffset = 0;
520 } else if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
521 PRINTK_DEBUG("MCH validated at 667MHz\n");
522 s->nodll = 1;
523 s->maxpi = 15;
524 s->pioffset = 1;
525 } else {
526 PRINTK_DEBUG("MCH set to unknown (%02x)\n",
527 (uint8_t) s->selected_timings.mem_clock & 0xff);
528 }
529}
530
531#define HPET_BASE 0xfed00000
532#define HPET32(x) *((volatile u32 *)(HPET_BASE + x))
533static void enable_hpet(void)
534{
535 u32 reg32;
Arthur Heymansc73c9232019-10-02 14:57:50 +0200536 reg32 = RCBA32(HPTC);
Angel Pons39ff7032020-03-09 21:39:44 +0100537 reg32 &= ~0x03;
Damien Zammit003d15c2015-11-20 17:17:51 +1100538 reg32 |= (1 << 7);
Arthur Heymansc73c9232019-10-02 14:57:50 +0200539 RCBA32(HPTC) = reg32;
540 /* On NM10 this only works if read back */
541 RCBA32(HPTC);
Damien Zammit003d15c2015-11-20 17:17:51 +1100542 HPET32(0x10) = HPET32(0x10) | 1;
543}
544
545static void sdram_clk_crossing(struct sysinfo *s)
546{
Angel Pons39ff7032020-03-09 21:39:44 +0100547 u8 ddr_freq, fsb_freq;
Arthur Heymans6bf13012017-06-10 12:03:27 +0200548 static const u32 clkcross[2][2][4] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100549 {
Angel Pons39ff7032020-03-09 21:39:44 +0100550 {0xFFFFFFFF, 0x05030305, 0x0000FFFF, 0x00000000}, /* FSB = 667, DDR = 667 */
551 {0x1F1F1F1F, 0x2A1F1FA5, 0x00000000, 0x05000002}, /* FSB = 667, DDR = 800 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100552 },
553 {
Angel Pons39ff7032020-03-09 21:39:44 +0100554 {0x1F1F1F1F, 0x0D07070B, 0x00000000, 0x00000000}, /* FSB = 800, DDR = 667 */
555 {0xFFFFFFFF, 0x05030305, 0x0000FFFF, 0x00000000}, /* FSB = 800, DDR = 800 */
556 },
Damien Zammit003d15c2015-11-20 17:17:51 +1100557 };
Damien Zammit003d15c2015-11-20 17:17:51 +1100558
Angel Pons39ff7032020-03-09 21:39:44 +0100559 ddr_freq = s->selected_timings.mem_clock;
560 fsb_freq = s->selected_timings.fsb_clock;
Damien Zammit003d15c2015-11-20 17:17:51 +1100561
Angel Pons39ff7032020-03-09 21:39:44 +0100562 MCHBAR32(HMCCMP) = clkcross[fsb_freq][ddr_freq][0];
563 MCHBAR32(HMDCMP) = clkcross[fsb_freq][ddr_freq][1];
564 MCHBAR32(HMBYPCP) = clkcross[fsb_freq][ddr_freq][2];
565 MCHBAR32(HMCCPEXT) = 0;
566 MCHBAR32(HMDCPEXT) = clkcross[fsb_freq][ddr_freq][3];
567
568 MCHBAR32_OR(HMCCMC, 1 << 7);
569
570 if ((fsb_freq == 0) && (ddr_freq == 1)) {
571 MCHBAR8(CLKXSSH2MCBYPPHAS) = 0;
572 MCHBAR32(CLKXSSH2MD) = 0;
573 MCHBAR32(CLKXSSH2MD + 4) = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100574 }
575
Arthur Heymans6bf13012017-06-10 12:03:27 +0200576 static const u32 clkcross2[2][2][8] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100577 {
Angel Pons39ff7032020-03-09 21:39:44 +0100578 { // FSB = 667, DDR = 667
579 0x00000000, 0x08010204, 0x00000000, 0x08010204,
580 0x00000000, 0x00000000, 0x00000000, 0x04080102,
581 },
582 { // FSB = 667, DDR = 800
583 0x04080000, 0x10010002, 0x10000000, 0x20010208,
584 0x00000000, 0x00000004, 0x02040000, 0x08100102,
585 },
Damien Zammit003d15c2015-11-20 17:17:51 +1100586 },
587 {
Angel Pons39ff7032020-03-09 21:39:44 +0100588 { // FSB = 800, DDR = 667
589 0x10000000, 0x20010208, 0x04080000, 0x10010002,
590 0x00000000, 0x00000000, 0x08000000, 0x10200204,
591 },
592 { // FSB = 800, DDR = 800
593 0x00000000, 0x08010204, 0x00000000, 0x08010204,
594 0x00000000, 0x00000000, 0x00000000, 0x04080102,
595 },
596 },
Damien Zammit003d15c2015-11-20 17:17:51 +1100597 };
598
Angel Pons39ff7032020-03-09 21:39:44 +0100599 MCHBAR32(CLKXSSH2MCBYP) = clkcross2[fsb_freq][ddr_freq][0];
600 MCHBAR32(CLKXSSH2MCRDQ) = clkcross2[fsb_freq][ddr_freq][0];
601 MCHBAR32(CLKXSSH2MCRDCST) = clkcross2[fsb_freq][ddr_freq][0];
602 MCHBAR32(CLKXSSH2MCBYP + 4) = clkcross2[fsb_freq][ddr_freq][1];
603 MCHBAR32(CLKXSSH2MCRDQ + 4) = clkcross2[fsb_freq][ddr_freq][1];
604 MCHBAR32(CLKXSSH2MCRDCST + 4) = clkcross2[fsb_freq][ddr_freq][1];
605 MCHBAR32(CLKXSSMC2H) = clkcross2[fsb_freq][ddr_freq][2];
606 MCHBAR32(CLKXSSMC2H + 4) = clkcross2[fsb_freq][ddr_freq][3];
607 MCHBAR32(CLKXSSMC2HALT) = clkcross2[fsb_freq][ddr_freq][4];
608 MCHBAR32(CLKXSSMC2HALT + 4) = clkcross2[fsb_freq][ddr_freq][5];
609 MCHBAR32(CLKXSSH2X2MD) = clkcross2[fsb_freq][ddr_freq][6];
610 MCHBAR32(CLKXSSH2X2MD + 4) = clkcross2[fsb_freq][ddr_freq][7];
Damien Zammit003d15c2015-11-20 17:17:51 +1100611}
612
613static void sdram_clkmode(struct sysinfo *s)
614{
Angel Pons39ff7032020-03-09 21:39:44 +0100615 u8 ddr_freq;
616 u16 mpll_ctl;
Damien Zammit003d15c2015-11-20 17:17:51 +1100617
Angel Pons39ff7032020-03-09 21:39:44 +0100618 MCHBAR16_AND(CSHRMISCCTL1, ~(1 << 8));
619 MCHBAR8_AND(CSHRMISCCTL1, ~0x3f);
Damien Zammit003d15c2015-11-20 17:17:51 +1100620
621 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +0100622 ddr_freq = 0;
623 mpll_ctl = 1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100624 } else {
Angel Pons39ff7032020-03-09 21:39:44 +0100625 ddr_freq = 1;
626 mpll_ctl = (1 << 8) | (1 << 5);
Damien Zammit003d15c2015-11-20 17:17:51 +1100627 }
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200628 if (s->boot_path != BOOT_PATH_RESET)
Angel Pons39ff7032020-03-09 21:39:44 +0100629 MCHBAR16_AND_OR(MPLLCTL, ~(0x033f), mpll_ctl);
Damien Zammit003d15c2015-11-20 17:17:51 +1100630
Angel Pons39ff7032020-03-09 21:39:44 +0100631 MCHBAR32(C0GNT2LNCH1) = 0x58001117;
632 MCHBAR32_OR(C0STATRDCTRL, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +1100633
634 const u32 cas_to_reg[2][4] = {
Angel Pons39ff7032020-03-09 21:39:44 +0100635 {0x00000000, 0x00030100, 0x0C240201, 0x00000000}, /* DDR = 667 */
636 {0x00000000, 0x00030100, 0x0C240201, 0x10450302} /* DDR = 800 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100637 };
638
Angel Pons39ff7032020-03-09 21:39:44 +0100639 MCHBAR32(C0GNT2LNCH2) = cas_to_reg[ddr_freq][s->selected_timings.CAS - 3];
Damien Zammit003d15c2015-11-20 17:17:51 +1100640}
641
642static void sdram_timings(struct sysinfo *s)
643{
644 u8 i, j, ch, r, ta1, ta2, ta3, ta4, trp, bank, page, flag;
645 u8 reg8, wl;
646 u16 reg16;
647 u32 reg32, reg2;
Damien Zammit003d15c2015-11-20 17:17:51 +1100648
Angel Pons39ff7032020-03-09 21:39:44 +0100649 static const u8 pagetab[2][2] = {
650 {0x0e, 0x12},
651 {0x10, 0x14},
652 };
653
654 /* Only consider DDR2 */
655 wl = s->selected_timings.CAS - 1;
656 ta1 = ta2 = 6;
657 ta3 = s->selected_timings.CAS;
658 ta4 = 8;
Damien Zammit003d15c2015-11-20 17:17:51 +1100659 s->selected_timings.tRFC = (s->selected_timings.tRFC + 1) & 0xfe;
Angel Pons39ff7032020-03-09 21:39:44 +0100660 trp = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100661 bank = 1;
662 page = 0;
663
Angel Pons39ff7032020-03-09 21:39:44 +0100664 MCHBAR8(C0LATCTRL) = ((wl - 3) << 4) | (s->selected_timings.CAS - 3);
Damien Zammit003d15c2015-11-20 17:17:51 +1100665
666 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
667 i = ch << 1;
668 if (s->dimms[i].banks == 1) {
669 trp = 1;
670 bank = 0;
671 }
672 if (s->dimms[i].page_size == 2048) {
673 page = 1;
674 }
675 }
676 PRINTK_DEBUG("trp=%d bank=%d page=%d\n",trp, bank, page);
677
678 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
679 flag = 0;
680 } else {
681 flag = 1;
682 }
683
Angel Pons39ff7032020-03-09 21:39:44 +0100684 MCHBAR8_OR(C0PVCFG, 0x03);
685 MCHBAR16(C0CYCTRKPCHG) = ((wl + 4 + s->selected_timings.tWR) << 6) |
686 ((2 + MAX(s->selected_timings.tRTP, 2)) << 2) | 1;
687
Damien Zammit003d15c2015-11-20 17:17:51 +1100688 reg32 = (bank << 21) | (s->selected_timings.tRRD << 17) |
Angel Pons39ff7032020-03-09 21:39:44 +0100689 (s->selected_timings.tRP << 13) | ((s->selected_timings.tRP + trp) << 9) |
690 s->selected_timings.tRFC;
691
Damien Zammit003d15c2015-11-20 17:17:51 +1100692 if (bank == 0) {
693 reg32 |= (pagetab[flag][page] << 22);
694 }
Angel Pons39ff7032020-03-09 21:39:44 +0100695 /* FIXME: Why not do a single dword write? */
696 MCHBAR16(C0CYCTRKACT) = (u16) (reg32);
697 MCHBAR16(C0CYCTRKACT + 2) = (u16) (reg32 >> 16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100698
Angel Pons39ff7032020-03-09 21:39:44 +0100699 /* FIXME: Only applies to DDR2 */
700 reg16 = (MCHBAR16(C0CYCTRKACT + 2) & 0x0fc0) >> 6;
701 MCHBAR16_AND_OR(SHCYCTRKCKEL, ~0x1f80, (reg16 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +1100702
703 reg16 = (s->selected_timings.tRCD << 12) | (4 << 8) | (ta2 << 4) | ta4;
Angel Pons39ff7032020-03-09 21:39:44 +0100704 MCHBAR16(C0CYCTRKWR) = reg16;
Damien Zammit003d15c2015-11-20 17:17:51 +1100705
Angel Pons39ff7032020-03-09 21:39:44 +0100706 reg32 = (s->selected_timings.tRCD << 17) | ((wl + 4 + s->selected_timings.tWTR) << 12) |
Damien Zammit003d15c2015-11-20 17:17:51 +1100707 (ta3 << 8) | (4 << 4) | ta1;
Angel Pons39ff7032020-03-09 21:39:44 +0100708 MCHBAR32(C0CYCTRKRD) = reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100709
Angel Pons39ff7032020-03-09 21:39:44 +0100710 reg16 = ((s->selected_timings.tRP + trp) << 9) | s->selected_timings.tRFC;
Damien Zammit003d15c2015-11-20 17:17:51 +1100711
Angel Pons39ff7032020-03-09 21:39:44 +0100712 /* FIXME: Why not do a single word write? */
713 MCHBAR8(C0CYCTRKREFR) = (u8) (reg16);
714 MCHBAR8(C0CYCTRKREFR + 1) = (u8) (reg16 >> 8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100715
Angel Pons39ff7032020-03-09 21:39:44 +0100716 MCHBAR16_AND_OR(C0CKECTRL, ~0x03fe, 100 << 1);
717 MCHBAR8_AND_OR(C0CYCTRKPCHG2, ~0x3f, s->selected_timings.tRAS);
718 MCHBAR16(C0ARBCTRL) = 0x2310;
719 MCHBAR8_AND_OR(C0ADDCSCTRL, ~0x1f, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +1100720
721 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
722 reg32 = 3000;
723 } else {
724 reg32 = 2500;
725 }
726 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
727 reg2 = 6000;
728 } else {
729 reg2 = 5000;
730 }
Angel Pons39ff7032020-03-09 21:39:44 +0100731 reg16 = (u16)((((s->selected_timings.CAS + 7) * (reg32)) / reg2) << 8);
732 MCHBAR16_AND_OR(C0STATRDCTRL, ~0x1f00, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100733
734 flag = 0;
735 if (wl > 2) {
736 flag = 1;
737 }
738 reg16 = (u8) (wl - 1 - flag);
739 reg16 |= reg16 << 4;
740 reg16 |= flag << 8;
Angel Pons39ff7032020-03-09 21:39:44 +0100741 MCHBAR16_AND_OR(C0WRDATACTRL, ~0x01ff, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100742
Angel Pons39ff7032020-03-09 21:39:44 +0100743 MCHBAR16(C0RDQCTRL) = 0x1585;
744 MCHBAR8_AND(C0PWLRCTRL, ~0x1f);
745
746 /* rdmodwr_window[5..0] = CL+4+5 265[13..8] (264[21..16]) */
747 MCHBAR16_AND_OR(C0PWLRCTRL, ~0x3f00, (s->selected_timings.CAS + 9) << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100748
749 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +0100750 reg16 = 0x0514;
751 reg32 = 0x0a28;
Damien Zammit003d15c2015-11-20 17:17:51 +1100752 } else {
Angel Pons39ff7032020-03-09 21:39:44 +0100753 reg16 = 0x0618;
754 reg32 = 0x0c30;
Damien Zammit003d15c2015-11-20 17:17:51 +1100755 }
Angel Pons39ff7032020-03-09 21:39:44 +0100756 MCHBAR32_AND_OR(C0REFRCTRL2, ~0x0fffff00, (0x3f << 22) | (reg32 << 8));
Damien Zammit003d15c2015-11-20 17:17:51 +1100757
Angel Pons39ff7032020-03-09 21:39:44 +0100758 /* FIXME: Is this weird access necessary? Reference code does it */
759 MCHBAR8(C0REFRCTRL + 3) = 0;
760 MCHBAR16_AND_OR(C0REFCTRL, 0xc000, reg16);
761
762 /* NPUT Static Mode */
763 MCHBAR8_OR(C0DYNRDCTRL, 1);
764
765 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x7f000000, 0xb << 25);
Damien Zammit003d15c2015-11-20 17:17:51 +1100766 i = s->selected_timings.mem_clock;
767 j = s->selected_timings.fsb_clock;
768 if (i > j) {
Angel Pons39ff7032020-03-09 21:39:44 +0100769 MCHBAR32_OR(C0STATRDCTRL, 1 << 24);
Damien Zammit003d15c2015-11-20 17:17:51 +1100770 }
771
Angel Pons39ff7032020-03-09 21:39:44 +0100772 MCHBAR8_AND(C0RDFIFOCTRL, ~0x3);
773 MCHBAR16_AND_OR(C0WRDATACTRL, ~0x7c00, (wl + 10) << 10);
774 MCHBAR32_AND_OR(C0CKECTRL, ~0x070e0000, (3 << 24) | (3 << 17));
Damien Zammit003d15c2015-11-20 17:17:51 +1100775 reg16 = 0x15 << 6;
776 reg16 |= 0x1f;
777 reg16 |= (0x6 << 12);
Angel Pons39ff7032020-03-09 21:39:44 +0100778 MCHBAR16_AND_OR(C0REFRCTRL + 4, ~0x7fff, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100779
Angel Pons39ff7032020-03-09 21:39:44 +0100780 reg32 = (0x6 << 27) | (1 << 25); /* FIXME: For DDR3, set BIT26 as well */
781 MCHBAR32_AND_OR(C0REFRCTRL2, ~0x30000000, reg32 << 8);
782 MCHBAR8_AND_OR(C0REFRCTRL + 3, ~0xfa, reg32 >> 24);
783 MCHBAR8_AND(C0JEDEC, ~(1 << 7));
784 MCHBAR8_AND(C0DYNRDCTRL, ~0x6);
Damien Zammit003d15c2015-11-20 17:17:51 +1100785
Angel Pons39ff7032020-03-09 21:39:44 +0100786 /* Note: This is a 64-bit register, [34..30] = 0b00110 is split across two writes */
787 reg32 = ((6 & 3) << 30) | (4 << 25) | (1 << 20) | (8 << 15) | (6 << 10) | (4 << 5) | 1;
788 MCHBAR32(C0WRWMFLSH) = reg32;
789 MCHBAR16_AND_OR(C0WRWMFLSH + 4, ~0x1ff, (8 << 3) | (6 >> 2));
790 MCHBAR16_OR(SHPENDREG, 0x1c00 | (0x1f << 5));
791
792 /* FIXME: Why not do a single word write? */
793 MCHBAR8_AND_OR(SHPAGECTRL, ~0xff, 0x40);
794 MCHBAR8_AND_OR(SHPAGECTRL + 1, ~0x07, 0x05);
795 MCHBAR8_OR(SHCMPLWRCMD, 0x1f);
796
797 reg8 = (3 << 6);
Damien Zammit003d15c2015-11-20 17:17:51 +1100798 reg8 |= (s->dt0mode << 4);
799 reg8 |= 0x0c;
Angel Pons39ff7032020-03-09 21:39:44 +0100800 MCHBAR8_AND_OR(SHBONUSREG, ~0xdf, reg8);
801 MCHBAR8_AND(CSHRWRIOMLNS, ~0x02);
802 MCHBAR8_AND_OR(C0MISCTM, ~0x07, 0x02);
803 MCHBAR16_AND_OR(C0BYPCTRL, ~0x3fc, 4 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +1100804
Angel Pons39ff7032020-03-09 21:39:44 +0100805 /* [31..29] = 0b010 for kN = 2 (2N) */
806 reg32 = (2 << 29) | (1 << 28) | (1 << 23);
807 MCHBAR32_AND_OR(WRWMCONFIG, ~0xffb00000, reg32);
808
809 reg8 = (u8) ((MCHBAR16(C0CYCTRKACT) & 0xe000) >> 13);
810 reg8 |= (u8) ((MCHBAR16(C0CYCTRKACT + 2) & 1) << 3);
811 MCHBAR8_AND_OR(BYPACTSF, ~0xf0, reg8 << 4);
812
813 reg8 = (u8) ((MCHBAR32(C0CYCTRKRD) & 0x000f0000) >> 17);
814 MCHBAR8_AND_OR(BYPACTSF, ~0x0f, reg8);
815
816 /* FIXME: Why not clear everything at once? */
817 MCHBAR8_AND(BYPKNRULE, ~0xfc);
818 MCHBAR8_AND(BYPKNRULE, ~0x03);
819 MCHBAR8_AND(SHBONUSREG, ~0x03);
820 MCHBAR8_OR(C0BYPCTRL, 1);
821 MCHBAR16_OR(CSHRMISCCTL1, 1 << 9);
822
Damien Zammit003d15c2015-11-20 17:17:51 +1100823 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +0100824 /* FIXME: Hardcoded for DDR2 SO-DIMMs */
825 MCHBAR32_AND_OR(C0DLLRCVCTLy(i), ~0x3f3f3f3f, 0x0c0c0c0c);
Damien Zammit003d15c2015-11-20 17:17:51 +1100826 }
Angel Pons39ff7032020-03-09 21:39:44 +0100827 /* RDCS to RCVEN delay: Program coarse common to all bytelanes to default tCL + 1 */
828 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, (s->selected_timings.CAS + 1) << 16);
829
830 /* Program RCVEN delay with DLL-safe settings */
Damien Zammit003d15c2015-11-20 17:17:51 +1100831 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +0100832 MCHBAR8_AND(C0RXRCVyDLL(i), ~0x3f);
833 MCHBAR16_AND(C0RCVMISCCTL2, (u16) ~(3 << (i * 2)));
834 MCHBAR16_AND(C0RCVMISCCTL1, (u16) ~(3 << (i * 2)));
835 MCHBAR16_AND(C0COARSEDLY0, (u16) ~(3 << (i * 2)));
Damien Zammit003d15c2015-11-20 17:17:51 +1100836 }
Angel Pons39ff7032020-03-09 21:39:44 +0100837 MCHBAR8_AND(C0DLLPIEN, ~1); /* Power up receiver */
838 MCHBAR8_OR(C0DLLPIEN, 2); /* Enable RCVEN DLL */
839 MCHBAR8_OR(C0DLLPIEN, 4); /* Enable receiver DQS DLL */
840 MCHBAR32_OR(C0COREBONUS, 0x000c0400);
841 MCHBAR32_OR(C0CMDTX1, 1 << 31);
Damien Zammit003d15c2015-11-20 17:17:51 +1100842}
843
Angel Pons39ff7032020-03-09 21:39:44 +0100844/* Program clkset0's register for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200845static void sdram_p_clkset0(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100846{
Angel Pons39ff7032020-03-09 21:39:44 +0100847 MCHBAR16_AND_OR(C0CKTX, ~0xc440,
Damien Zammit003d15c2015-11-20 17:17:51 +1100848 (pll->clkdelay[f][i] << 14) |
849 (pll->dben[f][i] << 10) |
Angel Pons39ff7032020-03-09 21:39:44 +0100850 (pll->dbsel[f][i] << 6));
851
852 MCHBAR8_AND_OR(C0TXCK0DLL, ~0x3f, pll->pi[f][i]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100853}
854
Angel Pons39ff7032020-03-09 21:39:44 +0100855/* Program clkset1's register for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200856static void sdram_p_clkset1(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100857{
Angel Pons39ff7032020-03-09 21:39:44 +0100858 /* FIXME: This is actually a dword write! */
859 MCHBAR16_AND_OR(C0CKTX, ~0x00030880,
Damien Zammit003d15c2015-11-20 17:17:51 +1100860 (pll->clkdelay[f][i] << 16) |
861 (pll->dben[f][i] << 11) |
Angel Pons39ff7032020-03-09 21:39:44 +0100862 (pll->dbsel[f][i] << 7));
863
864 MCHBAR8_AND_OR(C0TXCK1DLL, ~0x3f, pll->pi[f][i]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100865}
866
Angel Pons39ff7032020-03-09 21:39:44 +0100867/* Program CMD0 and CMD1 registers for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200868static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100869{
870 u8 reg8;
Angel Pons39ff7032020-03-09 21:39:44 +0100871 /* Clock Group Index 3 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100872 reg8 = pll->dbsel[f][i] << 5;
873 reg8 |= pll->dben[f][i] << 6;
Angel Pons39ff7032020-03-09 21:39:44 +0100874 MCHBAR8_AND_OR(C0CMDTX1, ~0x60, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100875
876 reg8 = pll->clkdelay[f][i] << 4;
Angel Pons39ff7032020-03-09 21:39:44 +0100877 MCHBAR8_AND_OR(C0CMDTX2, ~0x30, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100878
879 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100880 MCHBAR8_AND_OR(C0TXCMD0DLL, ~0x3f, reg8);
881 MCHBAR8_AND_OR(C0TXCMD1DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100882}
883
Angel Pons39ff7032020-03-09 21:39:44 +0100884/* Program CTRL registers for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200885static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100886{
887 u8 reg8;
888 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +0100889
890 /* CTRL0 and CTRL1 */
891 reg32 = ((u32) pll->dbsel[f][i]) << 20;
892 reg32 |= ((u32) pll->dben[f][i]) << 21;
Damien Zammit003d15c2015-11-20 17:17:51 +1100893 reg32 |= ((u32) pll->dbsel[f][i]) << 22;
Angel Pons39ff7032020-03-09 21:39:44 +0100894 reg32 |= ((u32) pll->dben[f][i]) << 23;
Damien Zammit003d15c2015-11-20 17:17:51 +1100895 reg32 |= ((u32) pll->clkdelay[f][i]) << 24;
896 reg32 |= ((u32) pll->clkdelay[f][i]) << 27;
Angel Pons39ff7032020-03-09 21:39:44 +0100897 MCHBAR32_AND_OR(C0CTLTX2, ~0x01bf0000, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100898
899 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100900 MCHBAR8_AND_OR(C0TXCTL0DLL, ~0x3f, reg8);
901 MCHBAR8_AND_OR(C0TXCTL1DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100902
Angel Pons39ff7032020-03-09 21:39:44 +0100903 /* CTRL2 and CTRL3 */
904 reg32 = ((u32) pll->dbsel[f][i]) << 12;
905 reg32 |= ((u32) pll->dben[f][i]) << 13;
Damien Zammit003d15c2015-11-20 17:17:51 +1100906 reg32 |= ((u32) pll->dbsel[f][i]) << 8;
Angel Pons39ff7032020-03-09 21:39:44 +0100907 reg32 |= ((u32) pll->dben[f][i]) << 9;
Damien Zammit003d15c2015-11-20 17:17:51 +1100908 reg32 |= ((u32) pll->clkdelay[f][i]) << 14;
909 reg32 |= ((u32) pll->clkdelay[f][i]) << 10;
Angel Pons39ff7032020-03-09 21:39:44 +0100910 MCHBAR32_AND_OR(C0CMDTX2, ~0xff00, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100911
912 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100913 MCHBAR8_AND_OR(C0TXCTL2DLL, ~0x3f, reg8);
914 MCHBAR8_AND_OR(C0TXCTL3DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100915}
916
917static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
918{
919 u8 rank, dqs, reg8, j;
920 u32 reg32;
921
Angel Pons39ff7032020-03-09 21:39:44 +0100922 j = clk - 40;
923 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100924 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100925 rank = j % 4;
926 dqs = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100927
Angel Pons39ff7032020-03-09 21:39:44 +0100928 reg32 |= ((u32) pll->dben[f][clk]) << (dqs + 9);
Damien Zammit003d15c2015-11-20 17:17:51 +1100929 reg32 |= ((u32) pll->dbsel[f][clk]) << dqs;
Damien Zammit003d15c2015-11-20 17:17:51 +1100930
Angel Pons39ff7032020-03-09 21:39:44 +0100931 /* FIXME: Somehow, touching this changes the binary... */
932 MCHBAR32(C0DQSRyTX1(rank)) = (MCHBAR32(0x5b4 + (rank * 4))
933 & ~((1 << (dqs + 9)) | (1 << dqs))) | reg32;
934
935 reg32 = ((u32) pll->clkdelay[f][clk]) << ((dqs * 2) + 16);
936 MCHBAR32_AND_OR(C0DQSDQRyTX3(rank), ~((1 << (dqs * 2 + 17)) | (1 << (dqs * 2 + 16))),
937 reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100938
939 reg8 = pll->pi[f][clk];
Angel Pons39ff7032020-03-09 21:39:44 +0100940 MCHBAR8_AND_OR(C0TXDQS0R0DLL + j, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100941}
942
943
944static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
945{
946 u8 rank, dq, reg8, j;
947 u32 reg32;
948
Angel Pons39ff7032020-03-09 21:39:44 +0100949 j = clk - 8;
950 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100951 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100952 rank = j % 4;
953 dq = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100954
Angel Pons39ff7032020-03-09 21:39:44 +0100955 reg32 |= ((u32) pll->dben[f][clk]) << (dq + 9);
Damien Zammit003d15c2015-11-20 17:17:51 +1100956 reg32 |= ((u32) pll->dbsel[f][clk]) << dq;
Angel Pons39ff7032020-03-09 21:39:44 +0100957
958 /* FIXME: Somehow, touching this changes the binary... */
959 MCHBAR32(C0DQRyTX1(rank)) = (MCHBAR32(0x5a4 + rank * 4)
960 & ~((1 << (dq + 9)) | (1 << dq))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100961
962 reg32 = ((u32) pll->clkdelay[f][clk]) << (dq*2);
Angel Pons39ff7032020-03-09 21:39:44 +0100963 MCHBAR32_AND_OR(C0DQSDQRyTX3(rank), ~((1 << (dq * 2 + 1)) | (1 << (dq * 2))), reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100964
965 reg8 = pll->pi[f][clk];
Angel Pons39ff7032020-03-09 21:39:44 +0100966 MCHBAR8_AND_OR(C0TXDQ0R0DLL + j, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100967}
968
Angel Pons39ff7032020-03-09 21:39:44 +0100969/* WDLL programming: Perform HPLL/MPLL calibration after write levelization */
Damien Zammit003d15c2015-11-20 17:17:51 +1100970static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
971{
972 struct pllparam pll = {
973 .pi = {
Angel Pons39ff7032020-03-09 21:39:44 +0100974 { /* DDR = 667 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100975 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
976 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
977 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
978 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
979 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Angel Pons39ff7032020-03-09 21:39:44 +0100980 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3,
Damien Zammit003d15c2015-11-20 17:17:51 +1100981 },
Angel Pons39ff7032020-03-09 21:39:44 +0100982 { /* DDR = 800 */
983 53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
Damien Zammit003d15c2015-11-20 17:17:51 +1100984 34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
985 47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
Angel Pons39ff7032020-03-09 21:39:44 +0100986 47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
987 2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
988 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15,
Damien Zammit003d15c2015-11-20 17:17:51 +1100989 }},
990
991 .dben = {
Angel Pons39ff7032020-03-09 21:39:44 +0100992 { /* DDR = 667 */
993 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
994 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
995 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100999 },
Angel Pons39ff7032020-03-09 21:39:44 +01001000 { /* DDR = 800 */
1001 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1002 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1003 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1004 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1005 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1006 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001007 }},
1008
1009 .dbsel = {
Angel Pons39ff7032020-03-09 21:39:44 +01001010 { /* DDR = 667 */
1011 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1012 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1013 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1014 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1015 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1016 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001017 },
Angel Pons39ff7032020-03-09 21:39:44 +01001018 { /* DDR = 800 */
1019 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1020 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1021 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1022 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1023 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1024 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001025 }},
1026
1027 .clkdelay = {
Angel Pons39ff7032020-03-09 21:39:44 +01001028 { /* DDR = 667 */
1029 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1030 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1031 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1032 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1033 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1034 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001035 },
Angel Pons39ff7032020-03-09 21:39:44 +01001036 { /* DDR = 800 */
1037 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1038 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1039 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1040 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1041 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1042 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Damien Zammit003d15c2015-11-20 17:17:51 +11001043 }}
1044 };
1045
1046 u8 i, f;
1047 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1048 f = 0;
1049 } else {
1050 f = 1;
1051 }
1052 for (i = 0; i < 72; i++) {
1053 pll.pi[f][i] += pidelay;
1054 }
1055
Angel Pons39ff7032020-03-09 21:39:44 +01001056 /* Disable Dynamic DQS Slave Setting Per Rank */
1057 MCHBAR8_AND(CSHRDQSCMN, ~(1 << 7));
1058 MCHBAR16_AND_OR(CSHRPDCTL4, ~0x3fff, 0x1fff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001059
1060 sdram_p_clkset0(&pll, f, 0);
1061 sdram_p_clkset1(&pll, f, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01001062 sdram_p_cmd(&pll, f, 2);
1063 sdram_p_ctrl(&pll, f, 4);
1064
Damien Zammit003d15c2015-11-20 17:17:51 +11001065 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001066 sdram_p_dqs(&pll, f, i + 40);
Damien Zammit003d15c2015-11-20 17:17:51 +11001067 }
1068 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001069 sdram_p_dq(&pll, f, i + 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11001070 }
1071}
1072
Angel Pons39ff7032020-03-09 21:39:44 +01001073/* Perform HMC hardware calibration */
Damien Zammit003d15c2015-11-20 17:17:51 +11001074static void sdram_calibratehwpll(struct sysinfo *s)
1075{
1076 u8 reg8;
1077
1078 s->async = 0;
1079 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001080
Angel Pons39ff7032020-03-09 21:39:44 +01001081 MCHBAR16_OR(CSHRPDCTL, 1 << 15);
1082 MCHBAR8_AND(CSHRPDCTL, ~(1 << 7));
1083 MCHBAR8_OR(CSHRPDCTL, 1 << 3);
1084 MCHBAR8_OR(CSHRPDCTL, 1 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001085
Angel Pons39ff7032020-03-09 21:39:44 +01001086 /* Start hardware HMC calibration */
1087 MCHBAR8_OR(CSHRPDCTL, 1 << 7);
1088
1089 /* Busy-wait until calibration is done */
1090 while ((MCHBAR8(CSHRPDCTL) & (1 << 2)) == 0)
1091 ;
1092
1093 /* If hardware HMC calibration failed */
1094 reg8 = (MCHBAR8(CSHRPDCTL) & (1 << 3)) >> 3;
Damien Zammit003d15c2015-11-20 17:17:51 +11001095 if (reg8 != 0) {
1096 s->async = 1;
1097 }
1098}
1099
1100static void sdram_dlltiming(struct sysinfo *s)
1101{
Elyes HAOUAS66b462d2019-01-02 21:11:32 +01001102 u8 reg8, i;
Damien Zammit003d15c2015-11-20 17:17:51 +11001103 u16 reg16;
1104 u32 reg32;
1105
Angel Pons39ff7032020-03-09 21:39:44 +01001106 /* Configure the Master DLL */
Damien Zammit003d15c2015-11-20 17:17:51 +11001107 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +01001108 reg32 = 0x08014227;
Damien Zammit003d15c2015-11-20 17:17:51 +11001109 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001110 reg32 = 0x00014221;
Damien Zammit003d15c2015-11-20 17:17:51 +11001111 }
Angel Pons39ff7032020-03-09 21:39:44 +01001112 MCHBAR32_AND_OR(CSHRMSTRCTL1, ~0x0fffffff, reg32);
1113 MCHBAR32_OR(CSHRMSTRCTL1, 1 << 23);
1114 MCHBAR32_OR(CSHRMSTRCTL1, 1 << 15);
1115 MCHBAR32_AND(CSHRMSTRCTL1, ~(1 << 15));
Damien Zammit003d15c2015-11-20 17:17:51 +11001116
1117 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001118 /* Disable the Master DLLs by setting these bits, IN ORDER! */
1119 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 0);
1120 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 2);
1121 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 4);
1122 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 8);
1123 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 10);
1124 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 12);
1125 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 14);
Damien Zammit003d15c2015-11-20 17:17:51 +11001126 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001127 /* Enable the Master DLLs by clearing these bits, IN ORDER! */
1128 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 0));
1129 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 2));
1130 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 4));
1131 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 8));
1132 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 10));
1133 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 12));
1134 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 14));
Damien Zammit003d15c2015-11-20 17:17:51 +11001135 }
1136
Angel Pons39ff7032020-03-09 21:39:44 +01001137 /* Initialize the Transmit DLL PI values in the following sequence. */
Damien Zammit003d15c2015-11-20 17:17:51 +11001138 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001139 MCHBAR8_AND_OR(CREFPI, ~0x3f, 0x07);
Damien Zammit003d15c2015-11-20 17:17:51 +11001140 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001141 MCHBAR8_AND(CREFPI, ~0x3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001142 }
1143
1144 sdram_calibratepll(s, 0); // XXX check
1145
Angel Pons39ff7032020-03-09 21:39:44 +01001146 /* Enable all modular Slave DLL */
1147 MCHBAR16_OR(C0DLLPIEN, 1 << 11);
1148 MCHBAR16_OR(C0DLLPIEN, 1 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11001149
1150 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001151 MCHBAR16_OR(C0DLLPIEN, (1 << 10) >> i);
Damien Zammit003d15c2015-11-20 17:17:51 +11001152 }
Angel Pons39ff7032020-03-09 21:39:44 +01001153 /* Enable DQ/DQS output */
1154 MCHBAR8_OR(C0SLVDLLOUTEN, 1);
1155 MCHBAR16(CSPDSLVWT) = 0x5005;
1156 MCHBAR16_AND_OR(CSHRPDCTL2, ~0x1f1f, 0x051a);
1157 MCHBAR16_AND_OR(CSHRPDCTL5, ~0xbf3f, 0x9010);
Damien Zammit003d15c2015-11-20 17:17:51 +11001158
1159 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001160 MCHBAR8_AND_OR(CSHRPDCTL3, ~0x7f, 0x6b);
Damien Zammit003d15c2015-11-20 17:17:51 +11001161 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001162 MCHBAR8_AND_OR(CSHRPDCTL3, ~0x7f, 0x55);
Damien Zammit003d15c2015-11-20 17:17:51 +11001163 sdram_calibratehwpll(s);
1164 }
Angel Pons39ff7032020-03-09 21:39:44 +01001165 /* Disable Dynamic Diff Amp */
1166 MCHBAR32_AND(C0STATRDCTRL, ~(1 << 22));
Damien Zammit003d15c2015-11-20 17:17:51 +11001167
Angel Pons39ff7032020-03-09 21:39:44 +01001168 /* Now, start initializing the transmit FIFO */
1169 MCHBAR8_AND(C0MISCCTL, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11001170
Angel Pons39ff7032020-03-09 21:39:44 +01001171 /* Disable (gate) mdclk and mdclkb */
1172 MCHBAR8_OR(CSHWRIOBONUS, 0xc0);
Jacob Garberd10680b2019-06-11 14:13:04 -06001173
Angel Pons39ff7032020-03-09 21:39:44 +01001174 /* Select mdmclk */
1175 MCHBAR8_AND(CSHWRIOBONUS, ~(1 << 5));
Damien Zammit003d15c2015-11-20 17:17:51 +11001176
Angel Pons39ff7032020-03-09 21:39:44 +01001177 /* Ungate mdclk */
1178 MCHBAR8_AND_OR(CSHWRIOBONUS, ~0xc0, 1 << 6);
1179 MCHBAR8_AND_OR(CSHRFIFOCTL, ~0x3f, 0x1a);
1180
1181 /* Enable the write pointer count */
1182 MCHBAR8_OR(CSHRFIFOCTL, 1);
1183
1184 /* Set the DDR3 Reset Enable bit */
1185 MCHBAR8_OR(CSHRDDR3CTL, 1);
1186
1187 /* Configure DQS-DQ Transmit */
1188 MCHBAR32(CSHRDQSTXPGM) = 0x00551803;
1189
1190 reg8 = 0; /* Switch all clocks on anyway */
1191
1192 /* Enable clock groups depending on rank population */
1193 MCHBAR32_AND_OR(C0CKTX, ~0x3f000000, reg8 << 24);
1194
1195 /* Enable DDR command output buffers from core */
1196 MCHBAR8_AND(0x594, ~1);
1197
Damien Zammit003d15c2015-11-20 17:17:51 +11001198 reg16 = 0;
1199 if (!rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001200 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001201 }
1202 if (!rank_is_populated(s->dimms, 0, 1)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001203 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001204 }
1205 if (!rank_is_populated(s->dimms, 0, 2)) {
1206 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1207 }
1208 if (!rank_is_populated(s->dimms, 0, 3)) {
1209 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1210 }
Angel Pons39ff7032020-03-09 21:39:44 +01001211 MCHBAR16_OR(C0CTLTX2, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001212}
1213
Angel Pons39ff7032020-03-09 21:39:44 +01001214/* Define a shorter name for these to make the lines fit in 96 characters */
1215#define TABLE static const
1216
1217/* Loop over each RCOMP group, but skip group 1 because it does not exist */
1218#define FOR_EACH_RCOMP_GROUP(idx) for (idx = 0; idx < 7; idx++) if (idx != 1)
1219
1220/* Define accessors for the RCOMP register banks */
1221#define C0RCOMPCTRLx(x) (rcompctl[(x)] + 0x00)
1222#define C0RCOMPMULTx(x) (rcompctl[(x)] + 0x04)
1223#define C0RCOMPOVRx(x) (rcompctl[(x)] + 0x06)
1224#define C0RCOMPOSVx(x) (rcompctl[(x)] + 0x0A)
1225#define C0SCOMPVREFx(x) (rcompctl[(x)] + 0x0E)
1226#define C0SCOMPOVRx(x) (rcompctl[(x)] + 0x10)
1227#define C0SCOMPOFFx(x) (rcompctl[(x)] + 0x12)
1228#define C0DCOMPx(x) (rcompctl[(x)] + 0x14)
1229#define C0SLEWBASEx(x) (rcompctl[(x)] + 0x16)
1230#define C0SLEWPULUTx(x) (rcompctl[(x)] + 0x18)
1231#define C0SLEWPDLUTx(x) (rcompctl[(x)] + 0x1C)
1232#define C0DCOMPOVRx(x) (rcompctl[(x)] + 0x20)
1233#define C0DCOMPOFFx(x) (rcompctl[(x)] + 0x24)
1234
1235/* FIXME: This only applies to DDR2 */
Damien Zammit003d15c2015-11-20 17:17:51 +11001236static void sdram_rcomp(struct sysinfo *s)
1237{
Angel Pons39ff7032020-03-09 21:39:44 +01001238 u8 i, j, reg8, rcompp, rcompn, srup, srun;
Damien Zammit003d15c2015-11-20 17:17:51 +11001239 u16 reg16;
1240 u32 reg32, rcomp1, rcomp2;
1241
Angel Pons39ff7032020-03-09 21:39:44 +01001242 static const u8 rcompslew = 0x0a;
1243 static const u16 rcompctl[7] = {
1244 C0RCOMPCTRL0,
1245 0, /* This register does not exist */
1246 C0RCOMPCTRL2,
1247 C0RCOMPCTRL3,
1248 C0RCOMPCTRL4,
1249 C0RCOMPCTRL5,
1250 C0RCOMPCTRL6,
1251 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001252
Angel Pons39ff7032020-03-09 21:39:44 +01001253 /* RCOMP settings tables = { NC-NC, x16SS, x16DS, x16SS2, x16DS2, x8DS, x8DS2}; */
1254 TABLE u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0};
1255 TABLE u8 rcompstr[7] = { 0x66, 0x00, 0xaa, 0x55, 0x55, 0x77, 0x77};
1256 TABLE u16 rcompscomp[7] = {0xa22a, 0x0000, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a};
1257 TABLE u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1};
1258 TABLE u16 rcompf[7] = {0x1114, 0x0000, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a};
1259 TABLE u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0xaa};
1260 TABLE u16 rcompscomp2[7] = {0x0000, 0xe22e, 0xe22e, 0xe22e, 0x8228, 0xe22e, 0x8228};
1261 TABLE u8 rcompdelay2[7] = { 0, 0, 0, 0, 2, 0, 2};
Damien Zammit003d15c2015-11-20 17:17:51 +11001262
Angel Pons39ff7032020-03-09 21:39:44 +01001263 TABLE u8 rcomplut[64][12] = {
1264 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1265 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1266 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1267 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1268 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1269 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1270 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1271 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1272 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1273 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1274 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1275 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1276 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1277 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1278 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1279 {10, 9, 12, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1280 {10, 9, 12, 11, 2, 2, 6, 5, 7, 6, 6, 5},
1281 {10, 10, 12, 12, 2, 2, 6, 5, 7, 6, 6, 5},
1282 {10, 10, 12, 12, 2, 2, 6, 6, 7, 7, 6, 6},
1283 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1284 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1285 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1286 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1287 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1288 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1289 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1290 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1291 {11, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1292 {11, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1293 {12, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1294 {12, 12, 14, 13, 3, 3, 7, 6, 7, 7, 7, 6},
1295 {13, 12, 16, 15, 3, 3, 7, 6, 8, 7, 7, 6},
1296 {13, 14, 16, 15, 4, 3, 7, 7, 8, 8, 7, 7},
1297 {14, 14, 16, 17, 4, 3, 7, 7, 8, 8, 7, 7},
1298 {14, 16, 18, 17, 4, 4, 8, 7, 8, 8, 8, 7},
1299 {15, 16, 18, 19, 4, 4, 8, 7, 9, 8, 8, 7},
1300 {15, 18, 18, 19, 4, 4, 8, 8, 9, 9, 8, 8},
1301 {16, 18, 20, 21, 4, 4, 8, 8, 9, 9, 8, 8},
1302 {16, 19, 20, 21, 5, 4, 9, 8, 10, 9, 9, 8},
1303 {16, 19, 20, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1304 {17, 19, 22, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1305 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1306 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1307 {18, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1308 {18, 21, 24, 25, 5, 5, 9, 9, 11, 10, 9, 9},
1309 {19, 21, 24, 27, 5, 5, 9, 9, 11, 11, 9, 9},
1310 {19, 22, 24, 27, 5, 5, 10, 9, 11, 11, 10, 9},
1311 {20, 22, 24, 27, 6, 5, 10, 10, 11, 11, 10, 10},
1312 {20, 23, 26, 27, 6, 6, 10, 10, 12, 12, 10, 10},
1313 {20, 23, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1314 {21, 24, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1315 {21, 24, 26, 29, 6, 6, 11, 10, 12, 13, 11, 10},
1316 {22, 25, 28, 29, 6, 6, 11, 11, 13, 13, 11, 11},
1317 {22, 25, 28, 31, 6, 6, 11, 11, 13, 13, 11, 11},
1318 {22, 26, 28, 31, 6, 6, 11, 11, 13, 14, 11, 11},
1319 {23, 26, 30, 31, 7, 6, 12, 11, 14, 14, 12, 11},
1320 {23, 27, 30, 33, 7, 7, 12, 12, 14, 14, 12, 12},
1321 {23, 27, 30, 33, 7, 7, 12, 12, 14, 15, 12, 12},
1322 {24, 28, 32, 33, 7, 7, 12, 12, 15, 15, 12, 12},
1323 {24, 28, 32, 33, 7, 7, 12, 12, 15, 16, 12, 12},
1324 {24, 29, 32, 35, 7, 7, 12, 12, 15, 16, 12, 12},
1325 {25, 29, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1326 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1327 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
Damien Zammit003d15c2015-11-20 17:17:51 +11001328 };
1329
1330 srup = 0;
1331 srun = 0;
1332
1333 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001334 rcomp1 = 0x00050431;
1335 } else {
Damien Zammit003d15c2015-11-20 17:17:51 +11001336 rcomp1 = 0x00050542;
1337 }
1338 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
1339 rcomp2 = 0x14C42827;
1340 } else {
1341 rcomp2 = 0x19042827;
1342 }
1343
Angel Pons39ff7032020-03-09 21:39:44 +01001344 FOR_EACH_RCOMP_GROUP(i) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001345 reg8 = rcompupdate[i];
Angel Pons39ff7032020-03-09 21:39:44 +01001346 MCHBAR8_AND_OR(C0RCOMPCTRLx(i), ~1, reg8);
1347 MCHBAR8_AND(C0RCOMPCTRLx(i), ~2);
1348
1349 reg16 = rcompslew;
1350 MCHBAR16_AND_OR(C0RCOMPCTRLx(i), ~0xf000, reg16 << 12);
1351
1352 MCHBAR8(C0RCOMPMULTx(i)) = rcompstr[i];
1353 MCHBAR16(C0SCOMPVREFx(i)) = rcompscomp[i];
1354 MCHBAR8_AND_OR(C0DCOMPx(i), ~0x03, rcompdelay[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001355 if (i == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01001356 /* FIXME: Why are we rewriting this? */
1357 MCHBAR16_AND_OR(C0RCOMPCTRLx(i), ~0xf000, reg16 << 12);
1358
1359 MCHBAR8(C0RCOMPMULTx(i)) = rcompstr2[s->dimm_config[0]];
1360 MCHBAR16(C0SCOMPVREFx(i)) = rcompscomp2[s->dimm_config[0]];
1361 MCHBAR8_AND_OR(C0DCOMPx(i), ~0x03, rcompdelay2[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001362 }
1363
Angel Pons39ff7032020-03-09 21:39:44 +01001364 MCHBAR16_AND(C0SLEWBASEx(i), ~0x7f7f);
1365
1366 /* FIXME: Why not do a single dword write? */
1367 MCHBAR16_AND(C0SLEWPULUTx(i), ~0x3f3f);
1368 MCHBAR16_AND(C0SLEWPULUTx(i) + 2, ~0x3f3f);
1369
1370 /* FIXME: Why not do a single dword write? */
1371 MCHBAR16_AND(C0SLEWPDLUTx(i), ~0x3f3f);
1372 MCHBAR16_AND(C0SLEWPDLUTx(i) + 2, ~0x3f3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001373 }
1374
Angel Pons39ff7032020-03-09 21:39:44 +01001375 /* FIXME: Hardcoded */
1376 MCHBAR8_AND_OR(C0ODTRECORDX, ~0x3f, 0x36);
1377 MCHBAR8_AND_OR(C0DQSODTRECORDX, ~0x3f, 0x36);
Damien Zammit003d15c2015-11-20 17:17:51 +11001378
Angel Pons39ff7032020-03-09 21:39:44 +01001379 FOR_EACH_RCOMP_GROUP(i) {
1380 MCHBAR8_AND(C0RCOMPCTRLx(i), ~0x60);
1381 MCHBAR16_AND(C0RCOMPCTRLx(i) + 2, ~0x0706);
1382 MCHBAR16_AND(C0RCOMPOSVx(i), ~0x7f7f);
1383 MCHBAR16_AND(C0SCOMPOFFx(i), ~0x3f3f);
1384 MCHBAR16_AND(C0DCOMPOFFx(i), ~0x1f1f);
1385 MCHBAR8_AND(C0DCOMPOFFx(i) + 2, ~0x1f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001386 }
1387
Angel Pons39ff7032020-03-09 21:39:44 +01001388 MCHBAR16_AND(C0ODTRECORDX, ~0xffc0);
1389 MCHBAR16_AND(C0ODTRECORDX + 2, ~0x000f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001390
Angel Pons39ff7032020-03-09 21:39:44 +01001391 /* FIXME: Why not do a single dword write? */
1392 MCHBAR16_AND(C0DQSODTRECORDX, ~0xffc0);
1393 MCHBAR16_AND(C0DQSODTRECORDX + 2, ~0x000f);
1394
1395 FOR_EACH_RCOMP_GROUP(i) {
1396 MCHBAR16(C0SCOMPOVRx(i)) = rcompf[i];
1397
1398 /* FIXME: Why not do a single dword write? */
1399 MCHBAR16(C0DCOMPOVRx(i)) = 0x1219;
1400 MCHBAR16(C0DCOMPOVRx(i) + 2) = 0x000C;
Damien Zammit003d15c2015-11-20 17:17:51 +11001401 }
1402
Angel Pons39ff7032020-03-09 21:39:44 +01001403 MCHBAR32_AND_OR(DCMEASBUFOVR, ~0x001f1f1f, 0x000c1219);
Damien Zammit003d15c2015-11-20 17:17:51 +11001404
Angel Pons39ff7032020-03-09 21:39:44 +01001405 /* FIXME: Why not do a single word write? */
1406 MCHBAR16_AND_OR(XCOMPSDR0BNS, ~0x1f00, 0x1200);
1407 MCHBAR8_AND_OR(XCOMPSDR0BNS, ~0x1f, 0x12);
1408
1409 MCHBAR32(COMPCTRL3) = 0x007C9007;
1410 MCHBAR32(OFREQDELSEL) = rcomp1;
1411 MCHBAR16(XCOMPCMNBNS) = 0x1f7f;
1412 MCHBAR32(COMPCTRL2) = rcomp2;
1413 MCHBAR16_AND_OR(XCOMPDFCTRL, ~0x0f, 1);
1414 MCHBAR16(ZQCALCTRL) = 0x0134;
1415 MCHBAR32(COMPCTRL1) = 0x4C293600;
1416
1417 /* FIXME: wtf did these MRC guys smoke */
1418 MCHBAR8_AND_OR(COMPCTRL1 + 3, ~0x44, (1 << 6) | (1 << 2));
1419 MCHBAR16_AND(XCOMPSDR0BNS, ~(1 << 13));
1420 MCHBAR8_AND(XCOMPSDR0BNS, ~(1 << 5));
1421
1422 FOR_EACH_RCOMP_GROUP(i) {
1423 /* FIXME: This should be an _AND_OR */
1424 MCHBAR8(C0RCOMPCTRLx(i) + 2) = MCHBAR8(C0RCOMPCTRLx(i)) & ~0x71;
Damien Zammit003d15c2015-11-20 17:17:51 +11001425 }
1426
Angel Pons39ff7032020-03-09 21:39:44 +01001427 if ((MCHBAR32(COMPCTRL1) & (1 << 30)) == 0) {
1428 /* Start COMP */
1429 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001430
Angel Pons39ff7032020-03-09 21:39:44 +01001431 /* Wait until COMP is done */
1432 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1433 ;
1434
1435 reg32 = MCHBAR32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001436 rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1437 rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1438
Angel Pons39ff7032020-03-09 21:39:44 +01001439 FOR_EACH_RCOMP_GROUP(i) {
1440 srup = (MCHBAR8(C0RCOMPCTRLx(i) + 1) & 0xc0) >> 6;
1441 srun = (MCHBAR8(C0RCOMPCTRLx(i) + 1) & 0x30) >> 4;
1442
1443 /* FIXME: Why not do a single word write? */
Damien Zammit003d15c2015-11-20 17:17:51 +11001444 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
Angel Pons39ff7032020-03-09 21:39:44 +01001445 MCHBAR16_AND_OR(C0SLEWBASEx(i), ~0x7f00, reg16);
1446
Damien Zammit003d15c2015-11-20 17:17:51 +11001447 reg16 = (u16)(rcompn - (1 << (srun + 1)));
Angel Pons39ff7032020-03-09 21:39:44 +01001448 MCHBAR8_AND_OR(C0SLEWBASEx(i), ~0x7f, (u8)reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001449 }
1450
1451 reg8 = rcompp - (1 << (srup + 1));
1452 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001453 MCHBAR8_AND_OR(C0SLEWPULUTx(0) + i, ~0x3f, rcomplut[j][0]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001454 }
1455
1456 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1457 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons39ff7032020-03-09 21:39:44 +01001458 MCHBAR8_AND_OR(C0SLEWPULUTx(2) + i, ~0x3f, rcomplut[j][10]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001459 }
1460 }
1461
1462 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001463 MCHBAR8_AND_OR(C0SLEWPULUTx(3) + i, ~0x3f, rcomplut[j][6]);
1464 MCHBAR8_AND_OR(C0SLEWPULUTx(4) + i, ~0x3f, rcomplut[j][6]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001465 }
1466
1467 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001468 MCHBAR8_AND_OR(C0SLEWPULUTx(5) + i, ~0x3f, rcomplut[j][8]);
1469 MCHBAR8_AND_OR(C0SLEWPULUTx(6) + i, ~0x3f, rcomplut[j][8]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001470 }
1471
1472 reg8 = rcompn - (1 << (srun + 1));
1473 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001474 MCHBAR8_AND_OR(C0SLEWPDLUTx(0) + i, ~0x3f, rcomplut[j][1]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001475 }
1476
1477 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1478 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons39ff7032020-03-09 21:39:44 +01001479 MCHBAR8_AND_OR(C0SLEWPDLUTx(2) + i, ~0x3f, rcomplut[j][11]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001480 }
1481 }
1482
1483 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001484 MCHBAR8_AND_OR(C0SLEWPDLUTx(3) + i, ~0x3f, rcomplut[j][7]);
1485 MCHBAR8_AND_OR(C0SLEWPDLUTx(4) + i, ~0x3f, rcomplut[j][7]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001486 }
1487
1488 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001489 MCHBAR8_AND_OR(C0SLEWPDLUTx(5) + i, ~0x3f, rcomplut[j][9]);
1490 MCHBAR8_AND_OR(C0SLEWPDLUTx(6) + i, ~0x3f, rcomplut[j][9]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001491 }
1492 }
Angel Pons39ff7032020-03-09 21:39:44 +01001493 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001494}
1495
Angel Pons39ff7032020-03-09 21:39:44 +01001496/* FIXME: The ODT tables are for DDR2 only! */
Damien Zammit003d15c2015-11-20 17:17:51 +11001497static void sdram_odt(struct sysinfo *s)
1498{
1499 u8 rankindex = 0;
1500
Angel Pons39ff7032020-03-09 21:39:44 +01001501 static const u16 odt_rankctrl[16] = {
1502 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1503 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1504 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1505 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1506 };
1507 static const u16 odt_matrix[16] = {
1508 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1509 0x0000, 0x0011, 0x0000, 0x0011, 0x0000, 0x4444, 0x0000, 0x4444,
1510 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1511 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4444, 0x0000, 0x4444,
1512 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001513
1514 switch (s->dimms[0].ranks) {
1515 case 0:
1516 if (s->dimms[1].ranks == 0) {
1517 rankindex = 0;
1518 } else if (s->dimms[1].ranks == 1) {
1519 rankindex = 4;
1520 } else if (s->dimms[1].ranks == 2) {
1521 rankindex = 12;
1522 }
1523 break;
1524 case 1:
1525 if (s->dimms[1].ranks == 0) {
1526 rankindex = 1;
1527 } else if (s->dimms[1].ranks == 1) {
1528 rankindex = 5;
1529 } else if (s->dimms[1].ranks == 2) {
1530 rankindex = 13;
1531 }
1532 break;
1533 case 2:
1534 if (s->dimms[1].ranks == 0) {
1535 rankindex = 3;
1536 } else if (s->dimms[1].ranks == 1) {
1537 rankindex = 7;
1538 } else if (s->dimms[1].ranks == 2) {
1539 rankindex = 15;
1540 }
1541 break;
1542 }
1543
Angel Pons39ff7032020-03-09 21:39:44 +01001544 /* Program the ODT Matrix */
1545 MCHBAR16(C0ODT) = odt_matrix[rankindex];
1546
1547 /* Program the ODT Rank Control */
1548 MCHBAR16(C0ODTRKCTRL) = odt_rankctrl[rankindex];
Damien Zammit003d15c2015-11-20 17:17:51 +11001549}
1550
1551static void sdram_mmap(struct sysinfo *s)
1552{
Angel Pons39ff7032020-03-09 21:39:44 +01001553 TABLE u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000, 0xc00001, 0xf00000};
1554 TABLE u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101, 0x1010000, 0x1010101};
1555 TABLE u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1556 TABLE u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006, 0x40002, 0x80006};
Damien Zammit003d15c2015-11-20 17:17:51 +11001557
Angel Pons39ff7032020-03-09 21:39:44 +01001558 TABLE u16 tolud[7] = {2048, 2048, 4096, 4096, 8192, 4096, 8192};
1559 TABLE u16 tom[7] = { 2, 2, 4, 4, 8, 4, 8};
1560 TABLE u16 touud[7] = { 128, 128, 256, 256, 512, 256, 512};
1561 TABLE u32 gbsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1562 TABLE u32 bgsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1563 TABLE u32 tsegmb[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
Damien Zammit003d15c2015-11-20 17:17:51 +11001564
1565 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1566 if (s->dimms[0].sides > 1) {
1567 // 2R/NC
Angel Pons39ff7032020-03-09 21:39:44 +01001568 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x300001);
1569 MCHBAR32(C0DRA01) = 0x00000101;
1570 MCHBAR32(C0DRB0) = 0x00040002;
1571 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001572 } else {
1573 // 1R/NC
Angel Pons39ff7032020-03-09 21:39:44 +01001574 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x100001);
1575 MCHBAR32(C0DRA01) = 0x00000001;
1576 MCHBAR32(C0DRB0) = 0x00020002;
1577 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001578 }
1579 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001580 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x300001);
1581 MCHBAR32(C0DRA01) = 0x00000101;
1582 MCHBAR32(C0DRB0) = 0x00040002;
1583 MCHBAR32(C0DRB2) = 0x00040004;
Damien Zammit003d15c2015-11-20 17:17:51 +11001584 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001585 MCHBAR32_AND_OR(C0CKECTRL, ~1, w260[s->dimm_config[0]]);
1586 MCHBAR32(C0DRA01) = w208[s->dimm_config[0]];
1587 MCHBAR32(C0DRB0) = w200[s->dimm_config[0]];
1588 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001589 }
Angel Pons39ff7032020-03-09 21:39:44 +01001590 pci_write_config16(HOST_BRIDGE, 0xb0, tolud[s->dimm_config[0]]);
1591 pci_write_config16(HOST_BRIDGE, 0xa0, tom[s->dimm_config[0]]);
1592 pci_write_config16(HOST_BRIDGE, 0xa2, touud[s->dimm_config[0]]);
1593 pci_write_config32(HOST_BRIDGE, 0xa4, gbsm[s->dimm_config[0]]);
1594 pci_write_config32(HOST_BRIDGE, 0xa8, bgsm[s->dimm_config[0]]);
1595 pci_write_config32(HOST_BRIDGE, 0xac, tsegmb[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001596}
1597
Damien Zammit003d15c2015-11-20 17:17:51 +11001598static void hpet_udelay(u32 del)
1599{
1600 u32 start, finish, now;
1601
1602 del *= 15; /* now in usec */
1603
1604 start = HPET32(0xf0);
1605 finish = start + del;
1606 while (1) {
1607 now = HPET32(0xf0);
1608 if (finish > start) {
1609 if (now >= finish)
1610 break;
1611 } else {
1612 if ((now < start) && (now >= finish)) {
1613 break;
1614 }
1615 }
1616 }
1617}
Damien Zammit003d15c2015-11-20 17:17:51 +11001618
1619static u8 sdram_checkrcompoverride(void)
1620{
1621 u32 xcomp;
1622 u8 aa, bb, a, b, c, d;
1623
Angel Pons39ff7032020-03-09 21:39:44 +01001624 xcomp = MCHBAR32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001625 a = (u8)((xcomp & 0x7f000000) >> 24);
Angel Pons39ff7032020-03-09 21:39:44 +01001626 b = (u8)((xcomp & 0x007f0000) >> 16);
1627 c = (u8)((xcomp & 0x00003f00) >> 8);
1628 d = (u8)((xcomp & 0x0000003f) >> 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001629
1630 if (a > b) {
1631 aa = a - b;
1632 } else {
1633 aa = b - a;
1634 }
1635 if (c > d) {
1636 bb = c - d;
1637 } else {
1638 bb = d - c;
1639 }
Angel Pons39ff7032020-03-09 21:39:44 +01001640 if ((aa > 18) || (bb > 7) || (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
Damien Zammit003d15c2015-11-20 17:17:51 +11001641 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001642 MCHBAR32(RCMEASBUFXOVR) = 0x9718a729;
Damien Zammit003d15c2015-11-20 17:17:51 +11001643 return 1;
1644 }
1645 return 0;
1646}
1647
1648static void sdram_rcompupdate(struct sysinfo *s)
1649{
1650 u8 i, ok;
1651 u32 reg32a, reg32b;
1652
1653 ok = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001654 MCHBAR8_AND(XCOMPDFCTRL, ~(1 << 3));
1655 MCHBAR8_AND(COMPCTRL1, ~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11001656 for (i = 0; i < 3; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001657 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001658 hpet_udelay(1000);
Angel Pons39ff7032020-03-09 21:39:44 +01001659 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1660 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001661 ok |= sdram_checkrcompoverride();
1662 }
1663 if (!ok) {
Angel Pons39ff7032020-03-09 21:39:44 +01001664 reg32a = MCHBAR32(XCOMP);
1665 reg32b = ((reg32a >> 16) & 0x0000ffff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001666 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1667 reg32a |= (1 << 31) | (1 << 15);
Angel Pons39ff7032020-03-09 21:39:44 +01001668 MCHBAR32(RCMEASBUFXOVR) = reg32a;
Damien Zammit003d15c2015-11-20 17:17:51 +11001669 }
Angel Pons39ff7032020-03-09 21:39:44 +01001670 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001671 hpet_udelay(1000);
Angel Pons39ff7032020-03-09 21:39:44 +01001672 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1673 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001674}
1675
1676static void __attribute__((noinline))
1677sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1678{
1679 u32 reg32;
1680
1681 reg32 = jval << 3;
Angel Pons39ff7032020-03-09 21:39:44 +01001682 reg32 |= rank * (1 << 27);
1683 MCHBAR8_AND_OR(C0JEDEC, ~0x3e, jmode);
Damien Zammit003d15c2015-11-20 17:17:51 +11001684 read32((void *)reg32);
1685 barrier();
1686 hpet_udelay(1); // 1us
1687}
1688
1689static void sdram_zqcl(struct sysinfo *s)
1690{
1691 if (s->boot_path == BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01001692 MCHBAR32_OR(C0CKECTRL, 1 << 27);
1693 MCHBAR8_AND_OR(C0JEDEC, ~0x0e, NORMAL_OP_CMD);
1694 MCHBAR8_AND(C0JEDEC, ~0x30);
1695 MCHBAR32_AND_OR(C0REFRCTRL2, ~(3 << 30), 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001696 }
1697}
1698
1699static void sdram_jedecinit(struct sysinfo *s)
1700{
1701 u8 r, i, ch;
1702 u16 reg16, mrs, rttnom;
1703 struct jedeclist {
1704 char debug[15];
1705 u8 cmd;
1706 u16 val;
1707 };
1708
Arthur Heymans6bf13012017-06-10 12:03:27 +02001709 static const struct jedeclist jedec[12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001710 { " NOP ", NOP_CMD, 0 },
1711 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1712 { " EMRS2 ", EMRS2_CMD, 0 },
1713 { " EMRS3 ", EMRS3_CMD, 0 },
1714 { " EMRS1 ", EMRS1_CMD, 0 },
1715 { " DLL RESET ", MRS_CMD, (1 << 8) },
1716 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1717 { " AUTOREFRESH", CBR_CMD, 0 },
1718 { " AUTOREFRESH", CBR_CMD, 0 },
1719 { " INITIALISE ", MRS_CMD, 0 },
1720 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1721 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1722 };
1723
1724 mrs = (s->selected_timings.CAS << 4) |
Angel Pons39ff7032020-03-09 21:39:44 +01001725 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 3;
1726
Damien Zammit003d15c2015-11-20 17:17:51 +11001727 rttnom = (1 << 2);
1728 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1729 rttnom |= (1 << 6);
1730 }
1731
1732 hpet_udelay(200); // 200us
1733 reg16 = 0;
1734 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1735 for (i = 0; i < 12; i++) {
1736 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1737 reg16 = jedec[i].val;
1738 switch (jedec[i].cmd) {
1739 case EMRS1_CMD:
1740 reg16 |= rttnom;
1741 break;
1742 case MRS_CMD:
1743 reg16 |= mrs;
1744 break;
1745 default:
1746 break;
1747 }
1748 sdram_jedec(s, r, jedec[i].cmd, reg16);
1749 PRINTK_DEBUG("done\n");
1750 }
1751 }
1752}
1753
1754static void sdram_misc(struct sysinfo *s)
1755{
1756 u32 reg32;
1757
1758 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001759 reg32 |= (4 << 13);
1760 reg32 |= (6 << 8);
1761 MCHBAR32_AND_OR(C0DYNRDCTRL, ~0x3ff00, reg32);
1762 MCHBAR8_AND(C0DYNRDCTRL, ~(1 << 7));
1763 MCHBAR8_OR(C0REFRCTRL + 3, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001764 if (s->boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01001765 MCHBAR8_AND_OR(C0JEDEC, ~0x0e, NORMAL_OP_CMD);
1766 MCHBAR8_AND(C0JEDEC, ~0x30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001767 } else {
1768 sdram_zqcl(s);
1769 }
1770}
1771
1772static void sdram_checkreset(void)
1773{
1774 u8 pmcon2, pmcon3, reset;
1775
1776 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1777 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1778 pmcon3 &= ~0x2;
1779 if (pmcon2 & 0x80) {
1780 pmcon2 &= ~0x80;
1781 reset = 1;
1782 } else {
1783 pmcon2 |= 0x80;
1784 reset = 0;
1785 }
1786 if (pmcon2 & 0x4) {
1787 pmcon2 |= 0x4;
1788 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1789 pmcon3 |= (1 << 3);
1790 }
1791 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1792 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +02001793 if (reset)
1794 full_reset();
Damien Zammit003d15c2015-11-20 17:17:51 +11001795}
1796
1797static void sdram_dradrb(struct sysinfo *s)
1798{
1799 u8 i, reg8, ch, r;
1800 u32 reg32, ind, c0dra, c0drb, dra;
1801 u16 addr;
1802 i = 0;
Arthur Heymans6bf13012017-06-10 12:03:27 +02001803 static const u8 dratab[2][2][2][4] =
Damien Zammit003d15c2015-11-20 17:17:51 +11001804 {{
1805 {
1806 {0xff, 0xff, 0xff, 0xff},
1807 {0xff, 0x00, 0x02, 0xff}
1808 },
1809 {
1810 {0xff, 0x01, 0xff, 0xff},
1811 {0xff, 0x03, 0xff, 0x06}
1812 }
1813 },
1814 {
1815 {
1816 {0xff, 0xff, 0xff, 0xff},
1817 {0xff, 0x04, 0x06, 0x08}
1818 },
1819 {
1820 {0xff, 0xff, 0xff, 0xff},
1821 {0x05, 0x07, 0x09, 0xff}
1822 }
1823 }};
1824
Arthur Heymans6bf13012017-06-10 12:03:27 +02001825 static const u8 dradrb[10][6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001826 //Row Col Bank Width DRB
1827 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1828 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1829 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1830 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1831 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1832 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1833 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1834 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1835 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1836 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1837 };
1838
1839 reg32 = 0;
1840 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1841 i = r / 2;
1842 PRINTK_DEBUG("RANK %d PRESENT\n", r);
Angel Pons39ff7032020-03-09 21:39:44 +01001843 dra = dratab
1844 [s->dimms[i].banks]
Damien Zammit003d15c2015-11-20 17:17:51 +11001845 [s->dimms[i].width]
1846 [s->dimms[i].cols - 9]
1847 [s->dimms[i].rows - 12];
1848
1849 if (s->dimms[i].banks == 1) {
1850 dra |= (1 << 7);
1851 }
Angel Pons39ff7032020-03-09 21:39:44 +01001852 reg32 |= (dra << (r * 8));
Damien Zammit003d15c2015-11-20 17:17:51 +11001853 }
Angel Pons39ff7032020-03-09 21:39:44 +01001854 MCHBAR32(C0DRA01) = reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +11001855 c0dra = reg32;
1856 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1857
1858 reg32 = 0;
1859 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1860 reg32 |= (1 << r);
1861 }
1862 reg8 = (u8)(reg32 << 4) & 0xf0;
Angel Pons39ff7032020-03-09 21:39:44 +01001863 MCHBAR8_AND_OR(C0CKECTRL + 2, ~0xf0, reg8);
1864
1865 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) || ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1866 MCHBAR8_OR(C0CKECTRL, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001867 }
1868
Angel Pons39ff7032020-03-09 21:39:44 +01001869 addr = C0DRB0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001870 c0drb = 0;
1871 FOR_EACH_RANK(ch, r) {
1872 if (rank_is_populated(s->dimms, ch, r)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001873 ind = (c0dra >> (8 * r)) & 0x7f;
Damien Zammit003d15c2015-11-20 17:17:51 +11001874 c0drb = (u16)(c0drb + dradrb[ind][5]);
1875 s->channel_capacity[0] += dradrb[ind][5] << 6;
1876 }
1877 MCHBAR16(addr) = c0drb;
1878 addr += 2;
1879 }
1880 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1881}
1882
1883static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1884{
Damien Zammit003d15c2015-11-20 17:17:51 +11001885 u8 dqsmatches = 1;
1886 while (count--) {
Angel Pons39ff7032020-03-09 21:39:44 +01001887 MCHBAR8_AND(C0RSTCTL, ~2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001888 hpet_udelay(1);
Angel Pons39ff7032020-03-09 21:39:44 +01001889 MCHBAR8_OR(C0RSTCTL, 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001890 hpet_udelay(1);
1891 barrier();
Elyes HAOUASaf159d42019-05-22 20:19:22 +02001892 read32((void *)strobeaddr);
Damien Zammit003d15c2015-11-20 17:17:51 +11001893 barrier();
1894 hpet_udelay(1);
1895
1896 if (((MCHBAR8(dqshighaddr) & 0x40) >> 6) != highlow) {
1897 dqsmatches = 0;
1898 }
1899 }
1900
1901 return dqsmatches;
1902}
1903
Angel Pons39ff7032020-03-09 21:39:44 +01001904static void rcvenclock(u8 *coarse, u8 *medium, u8 lane)
Damien Zammit003d15c2015-11-20 17:17:51 +11001905{
1906 if (*medium < 3) {
1907 (*medium)++;
Angel Pons39ff7032020-03-09 21:39:44 +01001908 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001909 } else {
1910 *medium = 0;
1911 (*coarse)++;
Angel Pons39ff7032020-03-09 21:39:44 +01001912 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, *coarse << 16);
1913 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)(~3 << (lane * 2)), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001914 }
1915}
1916
1917static void sdram_rcven(struct sysinfo *s)
1918{
Angel Pons39ff7032020-03-09 21:39:44 +01001919 u8 coarse, savecoarse;
1920 u8 medium, savemedium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001921 u8 pi, savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01001922 u8 lane;
1923 u8 lanecoarse[8] = {0};
1924 u8 minlanecoarse = 0xff;
1925 u8 offset;
1926 u8 maxlane = 8;
Arthur Heymans015339f2018-08-20 11:28:58 +02001927 /* Since dra/drb is already set up we know that at address 0x00000000
1928 we will always find the first available rank */
1929 u32 strobeaddr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001930 u32 dqshighaddr;
1931
Angel Pons39ff7032020-03-09 21:39:44 +01001932 MCHBAR8_AND(C0RSTCTL, ~0x0c);
1933 MCHBAR8_AND(CMNDQFIFORST, ~0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11001934
1935 PRINTK_DEBUG("rcven 0\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001936 for (lane = 0; lane < maxlane; lane++) {
1937 PRINTK_DEBUG("rcven lane %d\n", lane);
1938// trylaneagain:
1939 dqshighaddr = C0MISCCTLy(lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001940
Angel Pons39ff7032020-03-09 21:39:44 +01001941 coarse = s->selected_timings.CAS + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11001942 pi = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001943 medium = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001944
Angel Pons39ff7032020-03-09 21:39:44 +01001945 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1946 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001947
Angel Pons39ff7032020-03-09 21:39:44 +01001948 MCHBAR8_AND(C0RXRCVyDLL(lane), ~0x3f);
1949
1950 savecoarse = coarse;
1951 savemedium = medium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001952 savepi = pi;
1953
1954 PRINTK_DEBUG("rcven 0.1\n");
1955
Angel Pons39ff7032020-03-09 21:39:44 +01001956 // XXX comment out
1957 // MCHBAR16_AND_OR(C0RCVMISCCTL1, (u16)~3 << (lane * 2), 1 << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001958
1959 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001960 // printk(BIOS_DEBUG, "coarse=%d medium=%d\n", coarse, medium);
1961 rcvenclock(&coarse, &medium, lane);
1962 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001963 PRINTK_DEBUG("Error: coarse > 0xf\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001964 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001965 break;
1966 }
1967 }
1968 PRINTK_DEBUG("rcven 0.2\n");
1969
Angel Pons39ff7032020-03-09 21:39:44 +01001970 savecoarse = coarse;
1971 savemedium = medium;
1972 rcvenclock(&coarse, &medium, lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001973
1974 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001975 savecoarse = coarse;
1976 savemedium = medium;
1977 rcvenclock(&coarse, &medium, lane);
1978 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001979 PRINTK_DEBUG("Error: coarse > 0xf\n");
1980 //goto trylaneagain;
1981 break;
1982 }
1983 }
1984
1985 PRINTK_DEBUG("rcven 0.3\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001986 coarse = savecoarse;
1987 medium = savemedium;
1988 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1989 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(0x3 << lane * 2), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001990
1991 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1992 savepi = pi;
1993 pi++;
1994 if (pi > s->maxpi) {
Angel Pons39ff7032020-03-09 21:39:44 +01001995 // if (s->nodll) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001996 pi = savepi = s->maxpi;
1997 break;
Angel Pons39ff7032020-03-09 21:39:44 +01001998 // }
Damien Zammit003d15c2015-11-20 17:17:51 +11001999 }
Angel Pons39ff7032020-03-09 21:39:44 +01002000 MCHBAR8_AND_OR(C0RXRCVyDLL(lane), ~0x3f, pi << s->pioffset);
Damien Zammit003d15c2015-11-20 17:17:51 +11002001 }
2002 PRINTK_DEBUG("rcven 0.4\n");
2003
2004 pi = savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01002005 MCHBAR8_AND_OR(C0RXRCVyDLL(lane), ~0x3f, pi << s->pioffset);
2006 rcvenclock(&coarse, &medium, lane);
2007
Damien Zammit003d15c2015-11-20 17:17:51 +11002008 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
2009 PRINTK_DEBUG("Error: DQS not high\n");
Angel Pons39ff7032020-03-09 21:39:44 +01002010 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11002011 }
2012 PRINTK_DEBUG("rcven 0.5\n");
2013 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01002014 coarse--;
2015 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
2016 if (coarse == 0) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +02002017 PRINTK_DEBUG("Error: DQS did not hit 0\n");
Damien Zammit003d15c2015-11-20 17:17:51 +11002018 break;
2019 }
2020 }
2021
2022 PRINTK_DEBUG("rcven 0.6\n");
Angel Pons39ff7032020-03-09 21:39:44 +01002023 rcvenclock(&coarse, &medium, lane);
2024 s->pi[lane] = pi;
2025 lanecoarse[lane] = coarse;
Damien Zammit003d15c2015-11-20 17:17:51 +11002026 }
2027
2028 PRINTK_DEBUG("rcven 1\n");
2029
Angel Pons39ff7032020-03-09 21:39:44 +01002030 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11002031 do {
Angel Pons39ff7032020-03-09 21:39:44 +01002032 lane--;
2033 if (minlanecoarse > lanecoarse[lane]) {
2034 minlanecoarse = lanecoarse[lane];
Damien Zammit003d15c2015-11-20 17:17:51 +11002035 }
Angel Pons39ff7032020-03-09 21:39:44 +01002036 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002037
Angel Pons39ff7032020-03-09 21:39:44 +01002038 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11002039 do {
Angel Pons39ff7032020-03-09 21:39:44 +01002040 lane--;
2041 offset = lanecoarse[lane] - minlanecoarse;
2042 MCHBAR16_AND_OR(C0COARSEDLY0, (u16)(~(3 << (lane * 2))), offset << (lane * 2));
2043 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002044
Angel Pons39ff7032020-03-09 21:39:44 +01002045 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, minlanecoarse << 16);
Damien Zammit003d15c2015-11-20 17:17:51 +11002046
Angel Pons39ff7032020-03-09 21:39:44 +01002047 s->coarsectrl = minlanecoarse;
2048 s->coarsedelay = MCHBAR16(C0COARSEDLY0);
2049 s->mediumphase = MCHBAR16(C0RCVMISCCTL2);
2050 s->readptrdelay = MCHBAR16(C0RCVMISCCTL1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002051
2052 PRINTK_DEBUG("rcven 2\n");
Angel Pons39ff7032020-03-09 21:39:44 +01002053 MCHBAR8_AND(C0RSTCTL, ~0x0e);
2054 MCHBAR8_OR(C0RSTCTL, 0x02);
2055 MCHBAR8_OR(C0RSTCTL, 0x04);
2056 MCHBAR8_OR(C0RSTCTL, 0x08);
Damien Zammit003d15c2015-11-20 17:17:51 +11002057
Angel Pons39ff7032020-03-09 21:39:44 +01002058 MCHBAR8_OR(CMNDQFIFORST, 0x80);
2059 MCHBAR8_AND(CMNDQFIFORST, ~0x80);
2060 MCHBAR8_OR(CMNDQFIFORST, 0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11002061 PRINTK_DEBUG("rcven 3\n");
2062}
2063
Angel Pons39ff7032020-03-09 21:39:44 +01002064/* NOTE: Unless otherwise specified, the values are expressed in MiB */
Damien Zammit003d15c2015-11-20 17:17:51 +11002065static void sdram_mmap_regs(struct sysinfo *s)
2066{
2067 bool reclaim;
Angel Pons39ff7032020-03-09 21:39:44 +01002068 u32 mmiosize, tom, tolud, touud, reclaimbase, reclaimlimit;
2069 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase, tsegsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002070 u16 ggc;
Angel Pons39ff7032020-03-09 21:39:44 +01002071 u16 ggc_to_uma[10] = {0, 1, 4, 8, 16, 32, 48, 64, 128, 256};
2072 u8 ggc_to_gtt[4] = {0, 1, 0, 0};
Damien Zammit003d15c2015-11-20 17:17:51 +11002073
Angel Pons39ff7032020-03-09 21:39:44 +01002074 reclaimbase = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002075 reclaimlimit = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002076
2077 ggc = pci_read_config16(HOST_BRIDGE, GGC);
Damien Zammit51fdb922016-01-18 18:34:52 +11002078 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
Angel Pons39ff7032020-03-09 21:39:44 +01002079
2080 gfxsize = ggc_to_uma[(ggc & 0x00f0) >> 4];
2081
2082 gttsize = ggc_to_gtt[(ggc & 0x0300) >> 8];
2083
Damien Zammit003d15c2015-11-20 17:17:51 +11002084 tom = s->channel_capacity[0];
2085
Angel Pons39ff7032020-03-09 21:39:44 +01002086 /* With GTT always being 1M, TSEG 1M is the only setting that can
Arthur Heymansda44e342019-01-12 01:38:02 +01002087 be covered by SMRR which has alignment requirements. */
Angel Pons39ff7032020-03-09 21:39:44 +01002088 tsegsize = 1;
2089 mmiosize = 1024;
Damien Zammit003d15c2015-11-20 17:17:51 +11002090
2091 reclaim = false;
Angel Pons39ff7032020-03-09 21:39:44 +01002092 tolud = MIN(4096 - mmiosize, tom);
2093 if ((tom - tolud) > 64) {
Arthur Heymansaaebb412017-08-27 18:46:12 +02002094 reclaim = true;
Damien Zammit003d15c2015-11-20 17:17:51 +11002095 }
2096 if (reclaim) {
2097 tolud = tolud & ~0x3f;
Angel Pons39ff7032020-03-09 21:39:44 +01002098 tom = tom & ~0x3f;
2099 reclaimbase = MAX(4096, tom);
2100 reclaimlimit = reclaimbase + (MIN(4096, tom) - tolud) - 0x40;
Damien Zammit003d15c2015-11-20 17:17:51 +11002101 }
2102 touud = tom;
2103 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002104 touud = reclaimlimit + 64;
Damien Zammit003d15c2015-11-20 17:17:51 +11002105 }
2106
Angel Pons39ff7032020-03-09 21:39:44 +01002107 gfxbase = tolud - gfxsize;
2108 gttbase = gfxbase - gttsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002109 tsegbase = gttbase - tsegsize;
2110
2111 /* Program the regs */
Angel Pons39ff7032020-03-09 21:39:44 +01002112 pci_write_config16(HOST_BRIDGE, TOLUD, (u16)(tolud << 4));
2113 pci_write_config16(HOST_BRIDGE, TOM, (u16)(tom >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002114 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002115 pci_write_config16(HOST_BRIDGE, 0x98, (u16)(reclaimbase >> 6));
2116 pci_write_config16(HOST_BRIDGE, 0x9a, (u16)(reclaimlimit >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002117 }
Angel Pons39ff7032020-03-09 21:39:44 +01002118 pci_write_config16(HOST_BRIDGE, TOUUD, (u16)(touud));
2119 pci_write_config32(HOST_BRIDGE, GBSM, gfxbase << 20);
2120 pci_write_config32(HOST_BRIDGE, BGSM, gttbase << 20);
2121 pci_write_config32(HOST_BRIDGE, TSEG, tsegbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002122
Angel Pons39ff7032020-03-09 21:39:44 +01002123 u8 reg8 = pci_read_config8(HOST_BRIDGE, ESMRAMC);
2124 reg8 &= ~0x07;
Arthur Heymansda44e342019-01-12 01:38:02 +01002125 reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
Angel Pons39ff7032020-03-09 21:39:44 +01002126 pci_write_config8(HOST_BRIDGE, ESMRAMC, reg8);
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002127
Damien Zammit51fdb922016-01-18 18:34:52 +11002128 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002129 pci_read_config32(HOST_BRIDGE, GBSM), gfxbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002130 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002131 pci_read_config32(HOST_BRIDGE, BGSM), gttbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002132 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002133 pci_read_config32(HOST_BRIDGE, TSEG), tsegbase << 20);
Damien Zammit003d15c2015-11-20 17:17:51 +11002134}
2135
2136static void sdram_enhancedmode(struct sysinfo *s)
2137{
Angel Pons39ff7032020-03-09 21:39:44 +01002138 u8 reg8, ch, r, fsb_freq, ddr_freq;
Damien Zammit003d15c2015-11-20 17:17:51 +11002139 u32 mask32, reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002140 MCHBAR8_OR(C0ADDCSCTRL, 1);
2141 MCHBAR8_OR(C0REFRCTRL + 3, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002142 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
Angel Pons39ff7032020-03-09 21:39:44 +01002143 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2144 MCHBAR32_AND_OR(WRWMCONFIG, ~mask32, reg32);
2145 MCHBAR8(C0DITCTRL + 1) = 2;
2146 MCHBAR16(C0DITCTRL + 2) = 0x0804;
2147 MCHBAR16(C0DITCTRL + 4) = 0x2010;
2148 MCHBAR8(C0DITCTRL + 6) = 0x40;
2149 MCHBAR16(C0DITCTRL + 8) = 0x091c;
2150 MCHBAR8(C0DITCTRL + 10) = 0xf2;
2151 MCHBAR8_OR(C0BYPCTRL, 1);
2152 MCHBAR8_OR(C0CWBCTRL, 1);
2153 MCHBAR16_OR(C0ARBSPL, 0x0100);
Damien Zammit003d15c2015-11-20 17:17:51 +11002154
Angel Pons26766fd2020-06-08 12:38:19 +02002155 pci_or_config8(HOST_BRIDGE, 0xf0, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01002156 MCHBAR32(SBCTL) = 0x00000002;
2157 MCHBAR32(SBCTL2) = 0x20310002;
2158 MCHBAR32(SLIMCFGTMG) = 0x02020302;
2159 MCHBAR32(HIT0) = 0x001f1806;
2160 MCHBAR32(HIT1) = 0x01102800;
2161 MCHBAR32(HIT2) = 0x07000000;
2162 MCHBAR32(HIT3) = 0x01014010;
2163 MCHBAR32(HIT4) = 0x0f038000;
Angel Pons26766fd2020-06-08 12:38:19 +02002164 pci_and_config8(HOST_BRIDGE, 0xf0, ~1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002165
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002166 u32 nranks, curranksize, maxranksize, dra;
2167 u8 rankmismatch;
Angel Pons39ff7032020-03-09 21:39:44 +01002168 static const u8 drbtab[10] = {0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8, 0x20, 0x10};
Damien Zammit003d15c2015-11-20 17:17:51 +11002169
2170 nranks = 0;
2171 curranksize = 0;
2172 maxranksize = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002173 rankmismatch = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002174
Damien Zammit003d15c2015-11-20 17:17:51 +11002175 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2176 nranks++;
Angel Pons39ff7032020-03-09 21:39:44 +01002177 dra = (u8) ((MCHBAR32(C0DRA01) >> (8 * r)) & 0x7f);
Damien Zammit003d15c2015-11-20 17:17:51 +11002178 curranksize = drbtab[dra];
2179 if (maxranksize == 0) {
2180 maxranksize = curranksize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002181 }
2182 if (curranksize != maxranksize) {
2183 rankmismatch = 1;
2184 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002185 }
2186
2187 reg8 = 0;
2188 switch (nranks) {
2189 case 4:
2190 if (rankmismatch) {
2191 reg8 = 0x64;
2192 } else {
2193 reg8 = 0xa4;
2194 }
2195 break;
2196 case 1:
2197 case 3:
2198 reg8 = 0x64;
2199 break;
2200 case 2:
2201 if (rankmismatch) {
2202 reg8 = 0x64;
2203 } else {
2204 reg8 = 0x24;
2205 }
2206 break;
2207 default:
2208 die("Invalid number of ranks found, halt\n");
2209 break;
2210 }
Angel Pons39ff7032020-03-09 21:39:44 +01002211 MCHBAR8_AND_OR(CHDECMISC, ~0xfc, reg8 & 0xfc);
2212 MCHBAR32_AND(NOACFGBUSCTL, ~0x80000000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002213
Angel Pons39ff7032020-03-09 21:39:44 +01002214 MCHBAR32(HTBONUS0) = 0x0000000f;
2215 MCHBAR8_OR(C0COREBONUS + 4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002216
Angel Pons39ff7032020-03-09 21:39:44 +01002217 MCHBAR32_AND(HIT3, ~0x0e000000);
2218 MCHBAR32_AND_OR(HIT4, ~0x000c0000, 0x00040000);
2219
Damien Zammit003d15c2015-11-20 17:17:51 +11002220 u32 clkcx[2][2][3] = {
Angel Pons39ff7032020-03-09 21:39:44 +01002221 {
2222 {0x00000000, 0x0c080302, 0x08010204}, /* FSB = 667, DDR = 667 */
2223 {0x02040000, 0x08100102, 0x00000000}, /* FSB = 667, DDR = 800 */
2224 },
2225 {
2226 {0x18000000, 0x3021060c, 0x20010208}, /* FSB = 800, DDR = 667 */
2227 {0x00000000, 0x0c090306, 0x00000000}, /* FSB = 800, DDR = 800 */
2228 }
2229 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002230
Angel Pons39ff7032020-03-09 21:39:44 +01002231 fsb_freq = s->selected_timings.fsb_clock;
2232 ddr_freq = s->selected_timings.mem_clock;
2233
2234 MCHBAR32(CLKXSSH2X2MD) = clkcx[fsb_freq][ddr_freq][0];
2235 MCHBAR32(CLKXSSH2X2MD + 4) = clkcx[fsb_freq][ddr_freq][1];
2236 MCHBAR32(CLKXSSH2MCBYP + 4) = clkcx[fsb_freq][ddr_freq][2];
2237
2238 MCHBAR8_AND(HIT4, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11002239}
2240
2241static void sdram_periodic_rcomp(void)
2242{
Angel Pons39ff7032020-03-09 21:39:44 +01002243 MCHBAR8_AND(COMPCTRL1, ~0x02);
2244 while ((MCHBAR32(COMPCTRL1) & 0x80000000) > 0) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002245 ;
2246 }
Angel Pons39ff7032020-03-09 21:39:44 +01002247 MCHBAR16_AND(CSHRMISCCTL, ~0x3000);
2248 MCHBAR8_OR(CMNDQFIFORST, 0x80);
2249 MCHBAR16_AND_OR(XCOMPDFCTRL, ~0x0f, 0x09);
Damien Zammit003d15c2015-11-20 17:17:51 +11002250
Angel Pons39ff7032020-03-09 21:39:44 +01002251 MCHBAR8_OR(COMPCTRL1, 0x82);
Damien Zammit003d15c2015-11-20 17:17:51 +11002252}
2253
2254static void sdram_new_trd(struct sysinfo *s)
2255{
2256 u8 pidelay, i, j, k, cc, trd_perphase[5];
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002257 u8 bypass, freqgb, trd, reg8, txfifo;
Damien Zammit003d15c2015-11-20 17:17:51 +11002258 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2259 u16 tmclk, thclk, buffertocore, postcalib;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002260 static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2261 static const u16 trd_adjust[2][2][5] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11002262 {
2263 {3000, 3000, 0,0,0},
2264 {1000,2000,3000,1500,2500}
2265 },
2266 {
2267 {2000,1000,3000,0,0},
2268 {2500, 2500, 0,0,0}
2269 }};
2270
2271 freqgb = 110;
2272 buffertocore = 5000;
Damien Zammit003d15c2015-11-20 17:17:51 +11002273 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2274 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2275 tmclk = tmclk * 100 / freqgb;
2276 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2277 switch (s->selected_timings.mem_clock) {
2278 case MEM_CLOCK_667MHz:
2279 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2280 cc = 2;
2281 } else {
2282 cc = 3;
2283 }
2284 break;
2285 default:
2286 case MEM_CLOCK_800MHz:
2287 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2288 cc = 5;
2289 } else {
2290 cc = 2;
2291 }
2292 break;
2293 }
2294 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2295 maxrcvendelay = 0;
2296 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2297
2298 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01002299 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 3) * (u32)(tmclk));
2300 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 3) * (u32)(tmclk) / 2);
2301 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 3) * (u32)(tmclk) / 4);
2302 rcvendelay += (u32)(pidelay * s->pi[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002303 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2304 }
2305
Angel Pons39ff7032020-03-09 21:39:44 +01002306 if ((MCHBAR8(HMBYPCP + 3) == 0xff) && (MCHBAR8(HMCCMC) & 0x80)) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002307 bypass = 1;
2308 } else {
2309 bypass = 0;
2310 }
2311
2312 txfifo = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002313 reg8 = (MCHBAR8(CSHRFIFOCTL) & 0x0e) >> 1;
2314 txfifo = txfifo_lut[reg8] & 0x07;
Damien Zammit003d15c2015-11-20 17:17:51 +11002315
2316 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2317 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2318 if (s->async) {
2319 datadelay += tmclk / 2;
2320 }
2321
2322 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2323 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2324
2325 if (j == 0 && k == 0) {
2326 datadelay -= 3084;
2327 }
2328
2329 trd = 0;
2330 for (i = 0; i < cc; i++) {
2331 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2332 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2333 trd_perphase[i] += 1;
2334 if (trd_perphase[i] > trd) {
2335 trd = trd_perphase[i];
2336 }
2337 }
2338
Angel Pons39ff7032020-03-09 21:39:44 +01002339 MCHBAR16_AND_OR(C0STATRDCTRL, ~0x1f00, trd << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11002340}
2341
2342static void sdram_powersettings(struct sysinfo *s)
2343{
2344 u8 j;
2345 u32 reg32;
2346
2347 /* Thermal sensor */
Angel Pons39ff7032020-03-09 21:39:44 +01002348 MCHBAR8(TSC1) = 0x9b;
2349 MCHBAR32_AND_OR(TSTTP, ~0x00ffffff, 0x1d00);
2350 MCHBAR8(THERM1) = 0x08;
2351 MCHBAR8(TSC3) = 0x00;
2352 MCHBAR8_AND_OR(TSC2, ~0x0f, 0x04);
2353 MCHBAR8_AND_OR(THERM1, ~1, 1);
2354 MCHBAR8_AND_OR(TCO, ~0x80, 0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11002355
2356 /* Clock gating */
Angel Pons39ff7032020-03-09 21:39:44 +01002357 MCHBAR32_AND(PMMISC, ~0x00040001);
2358 MCHBAR8_AND(SBCTL3 + 3, ~0x80);
2359 MCHBAR8_AND(CISDCTRL + 3, ~0x80);
2360 MCHBAR16_AND(CICGDIS, ~0x1fff);
2361 MCHBAR32_AND(SBCLKGATECTRL, ~0x0001ffff);
2362 MCHBAR16_AND(HICLKGTCTL, ~0x03ff & 0x06);
2363 MCHBAR32_AND_OR(HTCLKGTCTL, ~0xffffffff, 0x20);
2364 MCHBAR8_AND(TSMISC, ~1);
2365 MCHBAR8(C0WRDPYN) = s->selected_timings.CAS - 1 + 0x15;
2366 MCHBAR16_AND_OR(CLOCKGATINGI, ~0x07fc, 0x0040);
2367 MCHBAR16_AND_OR(CLOCKGATINGII, ~0x0fff, 0x0d00);
2368 MCHBAR16_AND(CLOCKGATINGIII, ~0x0d80);
2369 MCHBAR16(GTDPCGC + 2) = 0xffff;
Damien Zammit003d15c2015-11-20 17:17:51 +11002370
2371 /* Sequencing */
Angel Pons39ff7032020-03-09 21:39:44 +01002372 MCHBAR32(HPWRCTL1) = (MCHBAR32(HPWRCTL1) & ~0x1fffffff) | 0x1f643fff;
2373 MCHBAR32(HPWRCTL2) = (MCHBAR32(HPWRCTL2) & ~0xffffff7f) | 0x02010000;
2374 MCHBAR16(HPWRCTL3) = (MCHBAR16(HPWRCTL3) & ~0x7000) | (3 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11002375
2376 /* Power */
Angel Pons39ff7032020-03-09 21:39:44 +01002377 MCHBAR32(GFXC3C4) = (MCHBAR32(GFXC3C4) & ~0xffff0003) | 0x10100000;
2378 MCHBAR32(PMDSLFRC) = (MCHBAR32(PMDSLFRC) & ~0x0001bff7) | 0x00000078;
2379
2380 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz)
2381 MCHBAR16_AND_OR(PMMSPMRES, ~0x03ff, 0x00c8);
2382 else
2383 MCHBAR16_AND_OR(PMMSPMRES, ~0x03ff, 0x0100);
2384
Damien Zammit003d15c2015-11-20 17:17:51 +11002385 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2386
Angel Pons39ff7032020-03-09 21:39:44 +01002387 MCHBAR32_AND_OR(PMCLKRC, ~0x01fff37f, 0x10810700);
2388 MCHBAR8_AND_OR(PMPXPRC, ~0x07, 1);
2389 MCHBAR8_AND(PMBAK, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11002390
Angel Pons39ff7032020-03-09 21:39:44 +01002391 static const u16 ddr2lut[2][4][2] = {
2392 {
2393 {0x0000, 0x0000},
2394 {0x019A, 0x0039},
2395 {0x0099, 0x1049},
2396 {0x0000, 0x0000},
2397 },
2398 {
2399 {0x0000, 0x0000},
2400 {0x019A, 0x0039},
2401 {0x0099, 0x1049},
2402 {0x0099, 0x2159},
2403 },
2404 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002405
Angel Pons39ff7032020-03-09 21:39:44 +01002406 MCHBAR16(C0C2REG) = 0x7a89;
2407 MCHBAR8(SHC2REGII) = 0xaa;
2408 MCHBAR16(SHC2REGII + 1) = ddr2lut[j][s->selected_timings.CAS - 3][1];
2409 MCHBAR16_AND_OR(SHC2REGI, ~0x7fff, ddr2lut[j][s->selected_timings.CAS - 3][0]);
2410 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0xf000, 0xf000);
2411 MCHBAR8(CSHWRIOBONUSX) = (MCHBAR8(CSHWRIOBONUSX) & ~0x77) | (4 << 4 | 4);
Damien Zammit003d15c2015-11-20 17:17:51 +11002412
Angel Pons39ff7032020-03-09 21:39:44 +01002413 reg32 = s->nodll ? 0x30000000 : 0;
2414
2415 /* FIXME: Compacting this results in changes to the binary */
2416 MCHBAR32(C0COREBONUS) = (MCHBAR32(C0COREBONUS) & ~0x0f000000) | 0x20000000 | reg32;
2417
2418 MCHBAR32_AND_OR(CLOCKGATINGI, ~0x00f00000, 0x00f00000);
2419 MCHBAR32_AND_OR(CLOCKGATINGII - 1, ~0x001ff000, 0xbf << 20);
2420 MCHBAR16_AND_OR(SHC3C4REG2, ~0x1f7f, (0x0b << 8) | (7 << 4) | 0x0b);
2421 MCHBAR16(SHC3C4REG3) = 0x3264;
2422 MCHBAR16_AND_OR(SHC3C4REG4, ~0x3f3f, (0x14 << 8) | 0x0a);
2423
2424 MCHBAR32_OR(C1COREBONUS, 0x80002000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002425}
2426
2427static void sdram_programddr(void)
2428{
Angel Pons39ff7032020-03-09 21:39:44 +01002429 MCHBAR16_AND_OR(CLOCKGATINGII, ~0x03ff, 0x0100);
2430 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0x003f, 0x0010);
2431 MCHBAR16_AND_OR(CLOCKGATINGI, ~0x7000, 0x2000);
2432
2433 MCHBAR8_AND(CSHRPDCTL, ~0x0e);
2434 MCHBAR8_AND(CSHRWRIOMLNS, ~0x0c);
2435 MCHBAR8_AND(C0MISCCTLy(0), ~0x0e);
2436 MCHBAR8_AND(C0MISCCTLy(1), ~0x0e);
2437 MCHBAR8_AND(C0MISCCTLy(2), ~0x0e);
2438 MCHBAR8_AND(C0MISCCTLy(3), ~0x0e);
2439 MCHBAR8_AND(C0MISCCTLy(4), ~0x0e);
2440 MCHBAR8_AND(C0MISCCTLy(5), ~0x0e);
2441 MCHBAR8_AND(C0MISCCTLy(6), ~0x0e);
2442 MCHBAR8_AND(C0MISCCTLy(7), ~0x0e);
2443 MCHBAR8_AND(CSHRWRIOMLNS, ~0x02);
2444
2445 MCHBAR16_AND(CSHRMISCCTL, ~0x0400);
2446 MCHBAR16_AND(CLOCKGATINGIII, ~0x0dc0);
2447 MCHBAR8_AND(C0WRDPYN, ~0x80);
2448 MCHBAR32_AND(C0COREBONUS, ~(1 << 22));
2449 MCHBAR16_AND(CLOCKGATINGI, ~0x80fc);
2450 MCHBAR16_AND(CLOCKGATINGII, ~0x0c00);
2451
2452 MCHBAR8_AND(CSHRPDCTL, ~0x0d);
2453 MCHBAR8_AND(C0MISCCTLy(0), ~1);
2454 MCHBAR8_AND(C0MISCCTLy(1), ~1);
2455 MCHBAR8_AND(C0MISCCTLy(2), ~1);
2456 MCHBAR8_AND(C0MISCCTLy(3), ~1);
2457 MCHBAR8_AND(C0MISCCTLy(4), ~1);
2458 MCHBAR8_AND(C0MISCCTLy(5), ~1);
2459 MCHBAR8_AND(C0MISCCTLy(6), ~1);
2460 MCHBAR8_AND(C0MISCCTLy(7), ~1);
2461
2462 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x00700000, 3 << 20);
2463 MCHBAR32_AND(C0COREBONUS, ~0x00100000);
2464 MCHBAR8_OR(C0DYNSLVDLLEN, 0x1e);
2465 MCHBAR8_OR(C0DYNSLVDLLEN2, 0x03);
2466 MCHBAR32_AND_OR(SHCYCTRKCKEL, ~0x0c000000, 0x04000000);
2467 MCHBAR16_OR(C0STATRDCTRL, 0x6000);
2468 MCHBAR32_OR(C0CKECTRL, 0x00010000);
2469 MCHBAR8_OR(C0COREBONUS, 0x10);
2470 MCHBAR32_OR(CLOCKGATINGI - 1, 0xf << 24);
2471 MCHBAR8_OR(CSHWRIOBONUS, 0x07);
2472 MCHBAR8_OR(C0DYNSLVDLLEN, 0xc0);
2473 MCHBAR8_OR(SHC2REGIII, 7);
2474 MCHBAR16_AND_OR(SHC2MINTM, ~0xffff, 0x0080);
2475 MCHBAR8_AND_OR(SHC2IDLETM, ~0xff, 0x10);
2476 MCHBAR16_OR(C0COREBONUS, 0x01e0);
2477 MCHBAR8_OR(CSHWRIOBONUS, 0x18);
2478 MCHBAR8_OR(CSHRMSTDYNDLLENB, 0x0d);
2479 MCHBAR16_OR(SHC3C4REG1, 0x0a3f);
2480 MCHBAR8_OR(C0STATRDCTRL, 3);
2481 MCHBAR8_AND_OR(C0REFRCTRL2, ~0xff, 0x4a);
2482 MCHBAR8_AND(C0COREBONUS + 4, ~0x60);
2483 MCHBAR16_OR(C0DYNSLVDLLEN, 0x0321);
Damien Zammit003d15c2015-11-20 17:17:51 +11002484}
2485
2486static void sdram_programdqdqs(struct sysinfo *s)
2487{
2488 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2489 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2490 u8 repeat, halfclk, feature, reg8, push;
2491 u16 cwb, pimdclk;
2492 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002493 static const u8 txfifotab[8] = {0, 7, 6, 5, 2, 1, 4, 3};
Damien Zammit003d15c2015-11-20 17:17:51 +11002494
2495 tpi = 3000;
2496 dqdqs_out = 4382;
2497 dqdqs_outdelay = 5083;
2498 dqdqs_delay = 4692;
2499 coretomcp = 0;
2500 txdelay = 0;
2501 halfclk = 0;
2502 tmaxunmask = 0;
2503 tmaxpi = 0;
2504 repeat = 2;
2505 feature = 0;
2506 cwb = 0;
2507 pimdclk = 0;
2508 reg32 = 0;
2509 push = 0;
2510 reg8 = 0;
2511
2512 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2513 refclk = 3000 - mdclk;
2514
Angel Pons39ff7032020-03-09 21:39:44 +01002515 coretomcp = ((MCHBAR8(C0ADDCSCTRL) >> 2) & 0x3) + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002516 coretomcp *= mdclk;
2517
Angel Pons39ff7032020-03-09 21:39:44 +01002518 reg8 = (MCHBAR8(CSHRFIFOCTL) & 0x0e) >> 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002519
2520 while (repeat) {
2521 txdelay = mdclk * (
Angel Pons39ff7032020-03-09 21:39:44 +01002522 ((MCHBAR16(C0GNT2LNCH1) >> 8) & 0x7) +
2523 (MCHBAR8(C0WRDATACTRL) & 0xf) +
2524 (MCHBAR8(C0WRDATACTRL + 1) & 0x1)
Damien Zammit003d15c2015-11-20 17:17:51 +11002525 ) +
Angel Pons39ff7032020-03-09 21:39:44 +01002526 txfifotab[reg8]*(mdclk / 2) +
Damien Zammit003d15c2015-11-20 17:17:51 +11002527 coretomcp +
2528 refclk +
2529 cwb;
Angel Pons39ff7032020-03-09 21:39:44 +01002530 halfclk = (MCHBAR8(C0MISCCTL) >> 1) & 0x1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002531 if (halfclk) {
2532 txdelay -= mdclk / 2;
2533 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2534 } else {
2535 reg32 = dqdqs_outdelay + coretomcp;
2536 }
2537
2538 tmaxunmask = txdelay - mdclk - dqdqs_out;
2539 tmaxpi = tmaxunmask - tpi;
2540
2541 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2542 if (repeat == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01002543 MCHBAR32_AND(C0COREBONUS, ~(1 << 23));
Damien Zammit003d15c2015-11-20 17:17:51 +11002544 }
2545 feature = 1;
2546 repeat = 0;
2547 } else {
2548 repeat--;
Angel Pons39ff7032020-03-09 21:39:44 +01002549 MCHBAR32_OR(C0COREBONUS, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +11002550 cwb = 2 * mdclk;
2551 }
2552 }
2553
2554 if (!feature) {
Angel Pons39ff7032020-03-09 21:39:44 +01002555 MCHBAR8(CLOCKGATINGI) = MCHBAR8(CLOCKGATINGI) & ~0x3;
Damien Zammit003d15c2015-11-20 17:17:51 +11002556 return;
2557 }
Angel Pons39ff7032020-03-09 21:39:44 +01002558 MCHBAR8_OR(CLOCKGATINGI, 3);
2559 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0xf000, pimdclk << 12);
2560 MCHBAR8_AND_OR(CSHWRIOBONUSX, ~0x77, (push << 4) | push);
2561 MCHBAR32_AND_OR(C0COREBONUS, ~0x0f000000, 0x03000000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002562}
2563
2564/**
2565 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2566 */
2567void sdram_initialize(int boot_path, const u8 *spd_addresses)
2568{
2569 struct sysinfo si;
Angel Pons39ff7032020-03-09 21:39:44 +01002570 const char *boot_str[] = {"Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002571
2572 PRINTK_DEBUG("Setting up RAM controller.\n");
2573
2574 memset(&si, 0, sizeof(si));
2575
2576 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002577 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002578 si.spd_map[0] = spd_addresses[0];
2579 si.spd_map[1] = spd_addresses[1];
2580 si.spd_map[2] = spd_addresses[2];
2581 si.spd_map[3] = spd_addresses[3];
2582
2583 sdram_read_spds(&si);
2584
2585 /* Choose Common Frequency */
2586 sdram_detect_ram_speed(&si);
2587
2588 /* Determine smallest common tRAS, tRP, tRCD, etc */
2589 sdram_detect_smallest_params(&si);
2590
2591 /* Enable HPET */
2592 enable_hpet();
Damien Zammit003d15c2015-11-20 17:17:51 +11002593
Angel Pons39ff7032020-03-09 21:39:44 +01002594 MCHBAR16_OR(CPCTL, 1 << 15);
Damien Zammit003d15c2015-11-20 17:17:51 +11002595
Damien Zammit003d15c2015-11-20 17:17:51 +11002596 sdram_clk_crossing(&si);
2597
2598 sdram_checkreset();
2599 PRINTK_DEBUG("Done checkreset\n");
2600
2601 sdram_clkmode(&si);
2602 PRINTK_DEBUG("Done clkmode\n");
2603
2604 sdram_timings(&si);
2605 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2606
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002607 if (si.boot_path != BOOT_PATH_RESET) {
2608 sdram_dlltiming(&si);
2609 PRINTK_DEBUG("Done dlltiming\n");
2610 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002611
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002612 if (si.boot_path != BOOT_PATH_RESET) {
2613 sdram_rcomp(&si);
2614 PRINTK_DEBUG("Done RCOMP\n");
2615 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002616
2617 sdram_odt(&si);
2618 PRINTK_DEBUG("Done odt\n");
2619
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002620 if (si.boot_path != BOOT_PATH_RESET) {
Angel Pons39ff7032020-03-09 21:39:44 +01002621 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002622 ;
2623 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002624
2625 sdram_mmap(&si);
2626 PRINTK_DEBUG("Done mmap\n");
2627
Angel Pons39ff7032020-03-09 21:39:44 +01002628 /* Enable DDR IO buffer */
2629 MCHBAR8_AND_OR(C0IOBUFACTCTL, ~0x3f, 0x08);
2630 MCHBAR8_OR(C0RSTCTL, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002631
2632 sdram_rcompupdate(&si);
2633 PRINTK_DEBUG("Done RCOMP update\n");
2634
Angel Pons39ff7032020-03-09 21:39:44 +01002635 MCHBAR8_OR(HIT4, 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11002636
2637 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01002638 MCHBAR32_OR(C0CKECTRL, 1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002639
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002640 sdram_jedecinit(&si);
2641 PRINTK_DEBUG("Done MRS\n");
2642 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002643
2644 sdram_misc(&si);
2645 PRINTK_DEBUG("Done misc\n");
2646
2647 sdram_zqcl(&si);
2648 PRINTK_DEBUG("Done zqcl\n");
2649
2650 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01002651 MCHBAR32_OR(C0REFRCTRL2, 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002652 }
2653
2654 sdram_dradrb(&si);
2655 PRINTK_DEBUG("Done dradrb\n");
2656
2657 sdram_rcven(&si);
2658 PRINTK_DEBUG("Done rcven\n");
2659
2660 sdram_new_trd(&si);
2661 PRINTK_DEBUG("Done tRD\n");
2662
2663 sdram_mmap_regs(&si);
2664 PRINTK_DEBUG("Done mmap regs\n");
2665
2666 sdram_enhancedmode(&si);
2667 PRINTK_DEBUG("Done enhanced mode\n");
2668
2669 sdram_powersettings(&si);
2670 PRINTK_DEBUG("Done power settings\n");
2671
2672 sdram_programddr();
2673 PRINTK_DEBUG("Done programming ddr\n");
2674
2675 sdram_programdqdqs(&si);
2676 PRINTK_DEBUG("Done programming dqdqs\n");
2677
2678 sdram_periodic_rcomp();
2679 PRINTK_DEBUG("Done periodic RCOMP\n");
2680
2681 /* Set init done */
Angel Pons39ff7032020-03-09 21:39:44 +01002682 MCHBAR32_OR(C0REFRCTRL2, 1 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002683
2684 /* Tell ICH7 that we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002685 pci_and_config8(PCI_DEV(0, 0x1f, 0), 0xa2, (u8)~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11002686
2687 /* Tell northbridge we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002688 pci_or_config8(HOST_BRIDGE, 0xf4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002689
2690 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2691}