blob: 7c6d2b8040ac43659d36908b6fcb0197b028023d [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>
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +02006#include <device/smbus_host.h>
Elyes HAOUASf97c1c92019-12-03 18:22:06 +01007#include <commonlib/helpers.h>
Damien Zammit003d15c2015-11-20 17:17:51 +11008#include <console/console.h>
Damien Zammit003d15c2015-11-20 17:17:51 +11009#include <delay.h>
Damien Zammit003d15c2015-11-20 17:17:51 +110010#include <lib.h>
Angel Ponseef43432021-01-12 22:25:28 +010011#include <southbridge/intel/common/hpet.h>
Damien Zammit003d15c2015-11-20 17:17:51 +110012#include "pineview.h"
13#include "raminit.h"
Damien Zammit003d15c2015-11-20 17:17:51 +110014#include <spd.h>
15#include <string.h>
16
Angel Pons39ff7032020-03-09 21:39:44 +010017/* Debugging macros */
Julius Wernercd49cce2019-03-05 16:53:33 -080018#if CONFIG(DEBUG_RAM_SETUP)
Damien Zammit003d15c2015-11-20 17:17:51 +110019#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
20#else
21#define PRINTK_DEBUG(x...)
22#endif
23
24#define MAX_TCLK_667 0x30
25#define MAX_TCLK_800 0x25
26#define MAX_TAC_667 0x45
27#define MAX_TAC_800 0x40
28
29#define NOP_CMD (1 << 1)
30#define PRE_CHARGE_CMD (1 << 2)
31#define MRS_CMD ((1 << 2) | (1 << 1))
32#define EMRS_CMD (1 << 3)
33#define EMRS1_CMD (EMRS_CMD | (1 << 4))
34#define EMRS2_CMD (EMRS_CMD | (1 << 5))
35#define EMRS3_CMD (EMRS_CMD | (1 << 5) | (1 << 4))
36#define ZQCAL_CMD ((1 << 3) | (1 << 1))
37#define CBR_CMD ((1 << 3) | (1 << 2))
38#define NORMAL_OP_CMD ((1 << 3) | (1 << 2) | (1 << 1))
39
40#define UBDIMM 1
41#define SODIMM 2
42
43#define TOTAL_CHANNELS 1
44#define TOTAL_DIMMS 2
45
46#define DIMM_IS_POPULATED(dimms, idx) (dimms[idx].card_type != 0)
47#define IF_DIMM_POPULATED(dimms, idx) if (dimms[idx].card_type != 0)
Elyes HAOUASa342f392018-10-17 10:56:26 +020048#define ONLY_DIMMA_IS_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110049 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
50 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3)))
Elyes HAOUASa342f392018-10-17 10:56:26 +020051#define ONLY_DIMMB_IS_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110052 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3) && \
53 !DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2)))
Elyes HAOUASa342f392018-10-17 10:56:26 +020054#define BOTH_DIMMS_ARE_POPULATED(dimms, ch) (\
Damien Zammit003d15c2015-11-20 17:17:51 +110055 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \
56 (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3))))
57#define FOR_EACH_DIMM(idx) \
58 for (idx = 0; idx < TOTAL_DIMMS; ++idx)
59#define FOR_EACH_POPULATED_DIMM(dimms, idx) \
60 FOR_EACH_DIMM(idx) IF_DIMM_POPULATED(dimms, idx)
61#define CHANNEL_IS_POPULATED(dimms, idx) ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0))
62#define CHANNEL_IS_CARDF(dimms, idx) ((dimms[idx<<1].card_type == 0xf) || (dimms[(idx<<1) + 1].card_type == 0xf))
63#define IF_CHANNEL_POPULATED(dimms, idx) if ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0))
64#define FOR_EACH_CHANNEL(idx) \
65 for (idx = 0; idx < TOTAL_CHANNELS; ++idx)
66#define FOR_EACH_POPULATED_CHANNEL(dimms, idx) \
67 FOR_EACH_CHANNEL(idx) IF_CHANNEL_POPULATED(dimms, idx)
68
69#define RANKS_PER_CHANNEL 4
70
71#define FOR_EACH_RANK_IN_CHANNEL(r) \
72 for (r = 0; r < RANKS_PER_CHANNEL; ++r)
73#define FOR_EACH_POPULATED_RANK_IN_CHANNEL(dimms, ch, r) \
74 FOR_EACH_RANK_IN_CHANNEL(r) if (rank_is_populated(dimms, ch, r))
75#define FOR_EACH_RANK(ch, r) \
76 FOR_EACH_CHANNEL(ch) FOR_EACH_RANK_IN_CHANNEL(r)
77#define FOR_EACH_POPULATED_RANK(dimms, ch, r) \
78 FOR_EACH_RANK(ch, r) if (rank_is_populated(dimms, ch, r))
79
80static bool rank_is_populated(struct dimminfo dimms[], u8 ch, u8 r)
81{
82 return ((dimms[ch<<1].card_type && ((r) < dimms[ch<<1].ranks))
83 || (dimms[(ch<<1) + 1].card_type
84 && ((r) >= 2)
85 && ((r) < (dimms[(ch<<1) + 1].ranks + 2))));
86}
87
88static inline void barrier(void)
89{
90 __asm__ __volatile__("": : :"memory");
91}
92
Arthur Heymans097d7532017-04-17 10:14:32 +020093static int decode_spd(struct dimminfo *d, int i)
Damien Zammit003d15c2015-11-20 17:17:51 +110094{
95 d->type = 0;
96 if (d->spd_data[20] == 0x2) {
97 d->type = UBDIMM;
98 } else if (d->spd_data[20] == 0x4) {
99 d->type = SODIMM;
100 }
101 d->sides = (d->spd_data[5] & 0x7) + 1;
102 d->banks = (d->spd_data[17] >> 2) - 1;
103 d->chip_capacity = d->banks;
104 d->rows = d->spd_data[3];// - 12;
105 d->cols = d->spd_data[4];// - 9;
106 d->cas_latencies = 0x78;
107 d->cas_latencies &= d->spd_data[18];
108 if (d->cas_latencies == 0)
109 d->cas_latencies = 7;
110 d->tAAmin = d->spd_data[26];
111 d->tCKmin = d->spd_data[25];
112 d->width = (d->spd_data[13] >> 3) - 1;
113 d->page_size = (d->width+1) * (1 << d->cols); // Bytes
114 d->tRAS = d->spd_data[30];
115 d->tRP = d->spd_data[27];
116 d->tRCD = d->spd_data[29];
117 d->tWR = d->spd_data[36];
118 d->ranks = d->sides; // XXX
Julius Wernercd49cce2019-03-05 16:53:33 -0800119#if CONFIG(DEBUG_RAM_SETUP)
Arthur Heymans097d7532017-04-17 10:14:32 +0200120 const char *ubso[2] = { "UB", "SO" };
Damien Zammit003d15c2015-11-20 17:17:51 +1100121#endif
122 PRINTK_DEBUG("%s-DIMM %d\n", &ubso[d->type][0], i);
123 PRINTK_DEBUG(" Sides : %d\n", d->sides);
124 PRINTK_DEBUG(" Banks : %d\n", d->banks);
125 PRINTK_DEBUG(" Ranks : %d\n", d->ranks);
126 PRINTK_DEBUG(" Rows : %d\n", d->rows);
127 PRINTK_DEBUG(" Cols : %d\n", d->cols);
128 PRINTK_DEBUG(" Page size : %d\n", d->page_size);
129 PRINTK_DEBUG(" Width : %d\n", (d->width + 1) * 8);
130
131 return 0;
132}
133
Angel Pons39ff7032020-03-09 21:39:44 +0100134/*
135 * RAM Config: DIMMB-DIMMA
Damien Zammit003d15c2015-11-20 17:17:51 +1100136 * 0 EMPTY-EMPTY
137 * 1 EMPTY-x16SS
138 * 2 EMPTY-x16DS
139 * 3 x16SS-x16SS
140 * 4 x16DS-x16DS
141 * 5 EMPTY- x8DS
142 * 6 x8DS - x8DS
143 */
144static void find_ramconfig(struct sysinfo *s, u32 chan)
145{
146 if (s->dimms[chan>>1].sides == 0) {
147 // NC
148 if (s->dimms[(chan>>1) + 1].sides == 0) {
149 // NC/NC
150 s->dimm_config[chan] = 0;
151 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
152 // NC/SS
153 if (s->dimms[(chan>>1) + 1].width == 0) {
154 // NC/8SS
155 s->dimm_config[chan] = 1;
156 } else {
157 // NC/16SS
158 s->dimm_config[chan] = 1;
159 }
160 } else {
161 // NC/DS
162 if (s->dimms[(chan>>1) + 1].width == 0) {
163 // NC/8DS
164 s->dimm_config[chan] = 5;
165 } else {
166 // NC/16DS
167 s->dimm_config[chan] = 2;
168 }
169 }
170 } else if (s->dimms[chan>>1].sides == 1) {
171 // SS
172 if (s->dimms[(chan>>1) + 1].sides == 0) {
173 // SS/NC
174 if (s->dimms[chan>>1].width == 0) {
175 // 8SS/NC
176 s->dimm_config[chan] = 1;
177 } else {
178 // 16SS/NC
179 s->dimm_config[chan] = 1;
180 }
181 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
182 // SS/SS
183 if (s->dimms[chan>>1].width == 0) {
184 if (s->dimms[(chan>>1) + 1].width == 0) {
185 // 8SS/8SS
186 s->dimm_config[chan] = 3;
187 } else {
188 // 8SS/16SS
189 die("Mixed Not supported\n");
190 }
191 } else {
192 if (s->dimms[(chan>>1) + 1].width == 0) {
193 // 16SS/8SS
194 die("Mixed Not supported\n");
195 } else {
196 // 16SS/16SS
197 s->dimm_config[chan] = 3;
198 }
199 }
200 } else {
201 // SS/DS
202 if (s->dimms[chan>>1].width == 0) {
203 if (s->dimms[(chan>>1) + 1].width == 0) {
204 // 8SS/8DS
205 die("Mixed Not supported\n");
206 } else {
207 die("Mixed Not supported\n");
208 }
209 } else {
210 if (s->dimms[(chan>>1) + 1].width == 0) {
211 // 16SS/8DS
212 die("Mixed Not supported\n");
213 } else {
214 die("Mixed Not supported\n");
215 }
216 }
217 }
218 } else {
219 // DS
220 if (s->dimms[(chan>>1) + 1].sides == 0) {
221 // DS/NC
222 if (s->dimms[chan>>1].width == 0) {
223 // 8DS/NC
224 s->dimm_config[chan] = 5;
225 } else {
226 s->dimm_config[chan] = 4;
227 }
228 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
229 // DS/SS
230 if (s->dimms[chan>>1].width == 0) {
231 if (s->dimms[(chan>>1) + 1].width == 0) {
232 // 8DS/8SS
233 die("Mixed Not supported\n");
234 } else {
235 // 8DS/16SS
236 die("Mixed Not supported\n");
237 }
238 } else {
239 if (s->dimms[(chan>>1) + 1].width == 0) {
240 die("Mixed Not supported\n");
241 } else {
242 // 16DS/16DS
243 s->dimm_config[chan] = 4;
244 }
245 }
246 } else {
247 // DS/DS
248 if (s->dimms[chan>>1].width == 0 && s->dimms[(chan>>1)+1].width == 0) {
249 // 8DS/8DS
250 s->dimm_config[chan] = 6;
251 }
252 }
253 }
254}
255
256static void sdram_read_spds(struct sysinfo *s)
257{
Arthur Heymans1f6369e2018-08-20 11:27:41 +0200258 u8 i, chan;
Damien Zammit003d15c2015-11-20 17:17:51 +1100259 s->dt0mode = 0;
260 FOR_EACH_DIMM(i) {
Kyösti Mälkkic01a5052019-01-30 09:39:23 +0200261 if (i2c_eeprom_read(s->spd_map[i], 0, 64, s->dimms[i].spd_data) != 64)
Arthur Heymans1f6369e2018-08-20 11:27:41 +0200262 s->dimms[i].card_type = 0;
263
264 s->dimms[i].card_type = s->dimms[i].spd_data[62] & 0x1f;
Damien Zammit003d15c2015-11-20 17:17:51 +1100265 hexdump(s->dimms[i].spd_data, 64);
266 }
267
268 s->spd_type = 0;
269 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
270 switch (s->dimms[i].spd_data[2]) {
271 case 0x8:
272 s->spd_type = DDR2;
273 break;
274 case 0xb:
275 default:
276 die("DIMM type mismatch\n");
277 break;
278 }
279 }
280
281 int err = 1;
282 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Arthur Heymans097d7532017-04-17 10:14:32 +0200283 err = decode_spd(&s->dimms[i], i);
Damien Zammit003d15c2015-11-20 17:17:51 +1100284 s->dt0mode |= (s->dimms[i].spd_data[49] & 0x2) >> 1;
285 }
286 if (err) {
287 die("No memory dimms, halt\n");
288 }
289
290 FOR_EACH_POPULATED_CHANNEL(s->dimms, chan) {
291 find_ramconfig(s, chan);
Angel Pons39ff7032020-03-09 21:39:44 +0100292 PRINTK_DEBUG(" Config[CH%d] : %d\n", chan, s->dimm_config[chan]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100293 }
294}
295
Julius Wernercd49cce2019-03-05 16:53:33 -0800296#if CONFIG(DEBUG_RAM_SETUP)
Damien Zammit003d15c2015-11-20 17:17:51 +1100297static u32 fsb_reg_to_mhz(u32 speed)
298{
299 return (speed * 133) + 667;
300}
301
302static u32 ddr_reg_to_mhz(u32 speed)
303{
Angel Pons39ff7032020-03-09 21:39:44 +0100304 return (speed == 0) ? 667 : (speed == 1) ? 800 : 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100305}
306#endif
307
Jacob Garberb70c7762019-03-25 18:20:06 -0600308// Return the position of the least significant set bit, 0-indexed.
309// 0 does not have a lsb, so return -1 for error.
310static int lsbpos(u8 val)
Damien Zammit003d15c2015-11-20 17:17:51 +1100311{
Jacob Garberb70c7762019-03-25 18:20:06 -0600312 for (int i = 0; i < 8; i++)
313 if (val & (1 << i))
314 return i;
315 return -1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100316}
317
Jacob Garberb70c7762019-03-25 18:20:06 -0600318// Return the position of the most significant set bit, 0-indexed.
319// 0 does not have a msb, so return -1 for error.
320static int msbpos(u8 val)
Damien Zammit003d15c2015-11-20 17:17:51 +1100321{
Jacob Garberb70c7762019-03-25 18:20:06 -0600322 for (int i = 7; i >= 0; i--)
323 if (val & (1 << i))
324 return i;
325 return -1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100326}
327
328static void sdram_detect_smallest_params(struct sysinfo *s)
329{
Arthur Heymans6bf13012017-06-10 12:03:27 +0200330 static const u16 mult[6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100331 3000, // 667
332 2500, // 800
333 };
334
335 u8 i;
Damien Zammit003d15c2015-11-20 17:17:51 +1100336 u32 maxtras = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100337 u32 maxtrp = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100338 u32 maxtrcd = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100339 u32 maxtwr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100340 u32 maxtrfc = 0;
341 u32 maxtwtr = 0;
342 u32 maxtrrd = 0;
343 u32 maxtrtp = 0;
344
345 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Angel Pons39ff7032020-03-09 21:39:44 +0100346 maxtras = MAX(maxtras, (s->dimms[i].spd_data[30] * 1000));
347 maxtrp = MAX(maxtrp, (s->dimms[i].spd_data[27] * 1000) >> 2);
Elyes HAOUASf97c1c92019-12-03 18:22:06 +0100348 maxtrcd = MAX(maxtrcd, (s->dimms[i].spd_data[29] * 1000) >> 2);
Angel Pons39ff7032020-03-09 21:39:44 +0100349 maxtwr = MAX(maxtwr, (s->dimms[i].spd_data[36] * 1000) >> 2);
350 maxtrfc = MAX(maxtrfc, (s->dimms[i].spd_data[42] * 1000) +
351 (s->dimms[i].spd_data[40] & 0xf));
Elyes HAOUASf97c1c92019-12-03 18:22:06 +0100352 maxtwtr = MAX(maxtwtr, (s->dimms[i].spd_data[37] * 1000) >> 2);
353 maxtrrd = MAX(maxtrrd, (s->dimms[i].spd_data[28] * 1000) >> 2);
354 maxtrtp = MAX(maxtrtp, (s->dimms[i].spd_data[38] * 1000) >> 2);
Damien Zammit003d15c2015-11-20 17:17:51 +1100355 }
Arthur Heymans12a4e982017-04-28 20:53:05 +0200356 /*
Angel Pons39ff7032020-03-09 21:39:44 +0100357 * TODO: on DDR3 there might be some minimal required values for some
Arthur Heymans12a4e982017-04-28 20:53:05 +0200358 * Timings: MIN_TRAS = 9, MIN_TRP = 3, MIN_TRCD = 3, MIN_TWR = 3,
359 * MIN_TWTR = 4, MIN_TRRD = 2, MIN_TRTP = 4
360 */
361 s->selected_timings.tRAS = MIN(24, DIV_ROUND_UP(maxtras,
362 mult[s->selected_timings.mem_clock]));
363 s->selected_timings.tRP = MIN(10, DIV_ROUND_UP(maxtrp,
364 mult[s->selected_timings.mem_clock]));
365 s->selected_timings.tRCD = MIN(10, DIV_ROUND_UP(maxtrcd,
366 mult[s->selected_timings.mem_clock]));
367 s->selected_timings.tWR = MIN(15, DIV_ROUND_UP(maxtwr,
368 mult[s->selected_timings.mem_clock]));
369 /* Needs to be even */
370 s->selected_timings.tRFC = 0xfe & (MIN(78, DIV_ROUND_UP(maxtrfc,
371 mult[s->selected_timings.mem_clock])) + 1);
372 s->selected_timings.tWTR = MIN(15, DIV_ROUND_UP(maxtwtr,
373 mult[s->selected_timings.mem_clock]));
374 s->selected_timings.tRRD = MIN(15, DIV_ROUND_UP(maxtrrd,
375 mult[s->selected_timings.mem_clock]));
Arthur Heymans5bb27b72017-08-26 21:24:21 +0200376 s->selected_timings.tRTP = MIN(15, DIV_ROUND_UP(maxtrtp,
Arthur Heymans12a4e982017-04-28 20:53:05 +0200377 mult[s->selected_timings.mem_clock]));
Damien Zammit003d15c2015-11-20 17:17:51 +1100378
379 PRINTK_DEBUG("Selected timings:\n");
380 PRINTK_DEBUG("\tFSB: %dMHz\n", fsb_reg_to_mhz(s->selected_timings.fsb_clock));
381 PRINTK_DEBUG("\tDDR: %dMHz\n", ddr_reg_to_mhz(s->selected_timings.mem_clock));
382
383 PRINTK_DEBUG("\tCAS: %d\n", s->selected_timings.CAS);
384 PRINTK_DEBUG("\ttRAS: %d\n", s->selected_timings.tRAS);
385 PRINTK_DEBUG("\ttRP: %d\n", s->selected_timings.tRP);
386 PRINTK_DEBUG("\ttRCD: %d\n", s->selected_timings.tRCD);
387 PRINTK_DEBUG("\ttWR: %d\n", s->selected_timings.tWR);
388 PRINTK_DEBUG("\ttRFC: %d\n", s->selected_timings.tRFC);
389 PRINTK_DEBUG("\ttWTR: %d\n", s->selected_timings.tWTR);
390 PRINTK_DEBUG("\ttRRD: %d\n", s->selected_timings.tRRD);
391 PRINTK_DEBUG("\ttRTP: %d\n", s->selected_timings.tRTP);
392}
393
394static void sdram_detect_ram_speed(struct sysinfo *s)
395{
396 u8 cas, reg8;
397 u32 reg32;
398 u32 freq = 0;
399 u32 fsb = 0;
400 u8 i;
401 u8 commoncas = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100402 u8 highcas = 0;
403 u8 lowcas = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100404
405 // Core frequency
Angel Pons39ff7032020-03-09 21:39:44 +0100406 fsb = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0x70) >> 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100407 if (fsb) {
408 fsb = 5 - fsb;
409 } else {
410 fsb = FSB_CLOCK_800MHz;
411 }
412
413 // DDR frequency
Angel Pons39ff7032020-03-09 21:39:44 +0100414 freq = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0x80) >> 7;
415 freq |= (pci_read_config8(HOST_BRIDGE, 0xe4) & 0x03) << 1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100416 if (freq) {
417 freq = 6 - freq;
418 } else {
419 freq = MEM_CLOCK_800MHz;
420 }
421
422 // Detect a common CAS latency
423 commoncas = 0xff;
424 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
425 commoncas &= s->dimms[i].spd_data[18];
426 }
427 if (commoncas == 0) {
428 die("No common CAS among dimms\n");
429 }
430
Jacob Garberb70c7762019-03-25 18:20:06 -0600431 // commoncas is nonzero, so these calls will not error
432 u8 msbp = (u8)msbpos(commoncas);
433 u8 lsbp = (u8)lsbpos(commoncas);
434
Damien Zammit003d15c2015-11-20 17:17:51 +1100435 // Start with fastest common CAS
436 cas = 0;
Jacob Garberb70c7762019-03-25 18:20:06 -0600437 highcas = msbp;
Elyes HAOUASf97c1c92019-12-03 18:22:06 +0100438 lowcas = MAX(lsbp, 5);
Damien Zammit003d15c2015-11-20 17:17:51 +1100439
440 while (cas == 0 && highcas >= lowcas) {
441 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
442 switch (freq) {
443 case MEM_CLOCK_800MHz:
Angel Pons39ff7032020-03-09 21:39:44 +0100444 if ((s->dimms[i].spd_data[9] > 0x25) ||
Damien Zammit003d15c2015-11-20 17:17:51 +1100445 (s->dimms[i].spd_data[10] > 0x40)) {
446 // CAS too fast, lower it
447 highcas--;
448 break;
449 } else {
450 cas = highcas;
451 }
452 break;
453 case MEM_CLOCK_667MHz:
454 default:
Angel Pons39ff7032020-03-09 21:39:44 +0100455 if ((s->dimms[i].spd_data[9] > 0x30) ||
Damien Zammit003d15c2015-11-20 17:17:51 +1100456 (s->dimms[i].spd_data[10] > 0x45)) {
457 // CAS too fast, lower it
458 highcas--;
459 break;
460 } else {
461 cas = highcas;
462 }
463 break;
464 }
465 }
466 }
467 if (highcas < lowcas) {
468 // Timings not supported by MCH, lower the frequency
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200469 if (freq == MEM_CLOCK_800MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +1100470 freq--;
471 PRINTK_DEBUG("Run DDR clock speed reduced due to timings\n");
472 } else {
473 die("Timings not supported by MCH\n");
474 }
475 cas = 0;
Jacob Garberb70c7762019-03-25 18:20:06 -0600476 highcas = msbp;
477 lowcas = lsbp;
Damien Zammit003d15c2015-11-20 17:17:51 +1100478 while (cas == 0 && highcas >= lowcas) {
479 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Angel Pons39ff7032020-03-09 21:39:44 +0100480 if ((s->dimms[i].spd_data[9] > 0x30) ||
Jacob Garber78107932019-06-11 12:45:51 -0600481 (s->dimms[i].spd_data[10] > 0x45)) {
482 // CAS too fast, lower it
483 highcas--;
484 } else {
485 cas = highcas;
Damien Zammit003d15c2015-11-20 17:17:51 +1100486 }
487 }
488 }
489 if (cas == 0) {
490 die("Unsupported dimms\n");
491 }
492 }
493
494 s->selected_timings.CAS = cas;
495 s->selected_timings.mem_clock = freq;
496 s->selected_timings.fsb_clock = fsb;
497
Angel Pons39ff7032020-03-09 21:39:44 +0100498 PRINTK_DEBUG("Drive Memory at %dMHz with CAS = %d clocks\n",
499 ddr_reg_to_mhz(s->selected_timings.mem_clock), s->selected_timings.CAS);
Damien Zammit003d15c2015-11-20 17:17:51 +1100500
501 // Set memory frequency
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200502 if (s->boot_path == BOOT_PATH_RESET)
503 return;
Angel Pons39ff7032020-03-09 21:39:44 +0100504
505 MCHBAR32_OR(PMSTS, 1);
506
507 reg32 = (MCHBAR32(CLKCFG) & ~0x70) | (1 << 10);
Damien Zammit003d15c2015-11-20 17:17:51 +1100508 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
509 reg8 = 3;
510 } else {
511 reg8 = 2;
512 }
513 reg32 |= reg8 << 4;
Angel Pons39ff7032020-03-09 21:39:44 +0100514 MCHBAR32(CLKCFG) = reg32;
515
516 s->selected_timings.mem_clock = ((MCHBAR32(CLKCFG) >> 4) & 0x7) - 2;
Damien Zammit003d15c2015-11-20 17:17:51 +1100517 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
518 PRINTK_DEBUG("MCH validated at 800MHz\n");
519 s->nodll = 0;
520 s->maxpi = 63;
521 s->pioffset = 0;
522 } else if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
523 PRINTK_DEBUG("MCH validated at 667MHz\n");
524 s->nodll = 1;
525 s->maxpi = 15;
526 s->pioffset = 1;
527 } else {
528 PRINTK_DEBUG("MCH set to unknown (%02x)\n",
529 (uint8_t) s->selected_timings.mem_clock & 0xff);
530 }
531}
532
Damien Zammit003d15c2015-11-20 17:17:51 +1100533static void sdram_clk_crossing(struct sysinfo *s)
534{
Angel Pons39ff7032020-03-09 21:39:44 +0100535 u8 ddr_freq, fsb_freq;
Arthur Heymans6bf13012017-06-10 12:03:27 +0200536 static const u32 clkcross[2][2][4] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100537 {
Angel Pons39ff7032020-03-09 21:39:44 +0100538 {0xFFFFFFFF, 0x05030305, 0x0000FFFF, 0x00000000}, /* FSB = 667, DDR = 667 */
539 {0x1F1F1F1F, 0x2A1F1FA5, 0x00000000, 0x05000002}, /* FSB = 667, DDR = 800 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100540 },
541 {
Angel Pons39ff7032020-03-09 21:39:44 +0100542 {0x1F1F1F1F, 0x0D07070B, 0x00000000, 0x00000000}, /* FSB = 800, DDR = 667 */
543 {0xFFFFFFFF, 0x05030305, 0x0000FFFF, 0x00000000}, /* FSB = 800, DDR = 800 */
544 },
Damien Zammit003d15c2015-11-20 17:17:51 +1100545 };
Damien Zammit003d15c2015-11-20 17:17:51 +1100546
Angel Pons39ff7032020-03-09 21:39:44 +0100547 ddr_freq = s->selected_timings.mem_clock;
548 fsb_freq = s->selected_timings.fsb_clock;
Damien Zammit003d15c2015-11-20 17:17:51 +1100549
Angel Pons39ff7032020-03-09 21:39:44 +0100550 MCHBAR32(HMCCMP) = clkcross[fsb_freq][ddr_freq][0];
551 MCHBAR32(HMDCMP) = clkcross[fsb_freq][ddr_freq][1];
552 MCHBAR32(HMBYPCP) = clkcross[fsb_freq][ddr_freq][2];
553 MCHBAR32(HMCCPEXT) = 0;
554 MCHBAR32(HMDCPEXT) = clkcross[fsb_freq][ddr_freq][3];
555
556 MCHBAR32_OR(HMCCMC, 1 << 7);
557
558 if ((fsb_freq == 0) && (ddr_freq == 1)) {
559 MCHBAR8(CLKXSSH2MCBYPPHAS) = 0;
560 MCHBAR32(CLKXSSH2MD) = 0;
561 MCHBAR32(CLKXSSH2MD + 4) = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100562 }
563
Arthur Heymans6bf13012017-06-10 12:03:27 +0200564 static const u32 clkcross2[2][2][8] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100565 {
Angel Pons39ff7032020-03-09 21:39:44 +0100566 { // FSB = 667, DDR = 667
567 0x00000000, 0x08010204, 0x00000000, 0x08010204,
568 0x00000000, 0x00000000, 0x00000000, 0x04080102,
569 },
570 { // FSB = 667, DDR = 800
571 0x04080000, 0x10010002, 0x10000000, 0x20010208,
572 0x00000000, 0x00000004, 0x02040000, 0x08100102,
573 },
Damien Zammit003d15c2015-11-20 17:17:51 +1100574 },
575 {
Angel Pons39ff7032020-03-09 21:39:44 +0100576 { // FSB = 800, DDR = 667
577 0x10000000, 0x20010208, 0x04080000, 0x10010002,
578 0x00000000, 0x00000000, 0x08000000, 0x10200204,
579 },
580 { // FSB = 800, DDR = 800
581 0x00000000, 0x08010204, 0x00000000, 0x08010204,
582 0x00000000, 0x00000000, 0x00000000, 0x04080102,
583 },
584 },
Damien Zammit003d15c2015-11-20 17:17:51 +1100585 };
586
Angel Pons39ff7032020-03-09 21:39:44 +0100587 MCHBAR32(CLKXSSH2MCBYP) = clkcross2[fsb_freq][ddr_freq][0];
588 MCHBAR32(CLKXSSH2MCRDQ) = clkcross2[fsb_freq][ddr_freq][0];
589 MCHBAR32(CLKXSSH2MCRDCST) = clkcross2[fsb_freq][ddr_freq][0];
590 MCHBAR32(CLKXSSH2MCBYP + 4) = clkcross2[fsb_freq][ddr_freq][1];
591 MCHBAR32(CLKXSSH2MCRDQ + 4) = clkcross2[fsb_freq][ddr_freq][1];
592 MCHBAR32(CLKXSSH2MCRDCST + 4) = clkcross2[fsb_freq][ddr_freq][1];
593 MCHBAR32(CLKXSSMC2H) = clkcross2[fsb_freq][ddr_freq][2];
594 MCHBAR32(CLKXSSMC2H + 4) = clkcross2[fsb_freq][ddr_freq][3];
595 MCHBAR32(CLKXSSMC2HALT) = clkcross2[fsb_freq][ddr_freq][4];
596 MCHBAR32(CLKXSSMC2HALT + 4) = clkcross2[fsb_freq][ddr_freq][5];
597 MCHBAR32(CLKXSSH2X2MD) = clkcross2[fsb_freq][ddr_freq][6];
598 MCHBAR32(CLKXSSH2X2MD + 4) = clkcross2[fsb_freq][ddr_freq][7];
Damien Zammit003d15c2015-11-20 17:17:51 +1100599}
600
601static void sdram_clkmode(struct sysinfo *s)
602{
Angel Pons39ff7032020-03-09 21:39:44 +0100603 u8 ddr_freq;
604 u16 mpll_ctl;
Damien Zammit003d15c2015-11-20 17:17:51 +1100605
Angel Pons39ff7032020-03-09 21:39:44 +0100606 MCHBAR16_AND(CSHRMISCCTL1, ~(1 << 8));
607 MCHBAR8_AND(CSHRMISCCTL1, ~0x3f);
Damien Zammit003d15c2015-11-20 17:17:51 +1100608
609 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +0100610 ddr_freq = 0;
611 mpll_ctl = 1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100612 } else {
Angel Pons39ff7032020-03-09 21:39:44 +0100613 ddr_freq = 1;
614 mpll_ctl = (1 << 8) | (1 << 5);
Damien Zammit003d15c2015-11-20 17:17:51 +1100615 }
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200616 if (s->boot_path != BOOT_PATH_RESET)
Angel Pons39ff7032020-03-09 21:39:44 +0100617 MCHBAR16_AND_OR(MPLLCTL, ~(0x033f), mpll_ctl);
Damien Zammit003d15c2015-11-20 17:17:51 +1100618
Angel Pons39ff7032020-03-09 21:39:44 +0100619 MCHBAR32(C0GNT2LNCH1) = 0x58001117;
620 MCHBAR32_OR(C0STATRDCTRL, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +1100621
622 const u32 cas_to_reg[2][4] = {
Angel Pons39ff7032020-03-09 21:39:44 +0100623 {0x00000000, 0x00030100, 0x0C240201, 0x00000000}, /* DDR = 667 */
624 {0x00000000, 0x00030100, 0x0C240201, 0x10450302} /* DDR = 800 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100625 };
626
Angel Pons39ff7032020-03-09 21:39:44 +0100627 MCHBAR32(C0GNT2LNCH2) = cas_to_reg[ddr_freq][s->selected_timings.CAS - 3];
Damien Zammit003d15c2015-11-20 17:17:51 +1100628}
629
630static void sdram_timings(struct sysinfo *s)
631{
632 u8 i, j, ch, r, ta1, ta2, ta3, ta4, trp, bank, page, flag;
633 u8 reg8, wl;
634 u16 reg16;
635 u32 reg32, reg2;
Damien Zammit003d15c2015-11-20 17:17:51 +1100636
Angel Pons39ff7032020-03-09 21:39:44 +0100637 static const u8 pagetab[2][2] = {
638 {0x0e, 0x12},
639 {0x10, 0x14},
640 };
641
642 /* Only consider DDR2 */
643 wl = s->selected_timings.CAS - 1;
644 ta1 = ta2 = 6;
645 ta3 = s->selected_timings.CAS;
646 ta4 = 8;
Damien Zammit003d15c2015-11-20 17:17:51 +1100647 s->selected_timings.tRFC = (s->selected_timings.tRFC + 1) & 0xfe;
Angel Pons39ff7032020-03-09 21:39:44 +0100648 trp = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100649 bank = 1;
650 page = 0;
651
Angel Pons39ff7032020-03-09 21:39:44 +0100652 MCHBAR8(C0LATCTRL) = ((wl - 3) << 4) | (s->selected_timings.CAS - 3);
Damien Zammit003d15c2015-11-20 17:17:51 +1100653
654 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
655 i = ch << 1;
656 if (s->dimms[i].banks == 1) {
657 trp = 1;
658 bank = 0;
659 }
660 if (s->dimms[i].page_size == 2048) {
661 page = 1;
662 }
663 }
664 PRINTK_DEBUG("trp=%d bank=%d page=%d\n",trp, bank, page);
665
666 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
667 flag = 0;
668 } else {
669 flag = 1;
670 }
671
Angel Pons39ff7032020-03-09 21:39:44 +0100672 MCHBAR8_OR(C0PVCFG, 0x03);
673 MCHBAR16(C0CYCTRKPCHG) = ((wl + 4 + s->selected_timings.tWR) << 6) |
674 ((2 + MAX(s->selected_timings.tRTP, 2)) << 2) | 1;
675
Damien Zammit003d15c2015-11-20 17:17:51 +1100676 reg32 = (bank << 21) | (s->selected_timings.tRRD << 17) |
Angel Pons39ff7032020-03-09 21:39:44 +0100677 (s->selected_timings.tRP << 13) | ((s->selected_timings.tRP + trp) << 9) |
678 s->selected_timings.tRFC;
679
Damien Zammit003d15c2015-11-20 17:17:51 +1100680 if (bank == 0) {
681 reg32 |= (pagetab[flag][page] << 22);
682 }
Angel Pons39ff7032020-03-09 21:39:44 +0100683 /* FIXME: Why not do a single dword write? */
684 MCHBAR16(C0CYCTRKACT) = (u16) (reg32);
685 MCHBAR16(C0CYCTRKACT + 2) = (u16) (reg32 >> 16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100686
Angel Pons39ff7032020-03-09 21:39:44 +0100687 /* FIXME: Only applies to DDR2 */
688 reg16 = (MCHBAR16(C0CYCTRKACT + 2) & 0x0fc0) >> 6;
689 MCHBAR16_AND_OR(SHCYCTRKCKEL, ~0x1f80, (reg16 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +1100690
691 reg16 = (s->selected_timings.tRCD << 12) | (4 << 8) | (ta2 << 4) | ta4;
Angel Pons39ff7032020-03-09 21:39:44 +0100692 MCHBAR16(C0CYCTRKWR) = reg16;
Damien Zammit003d15c2015-11-20 17:17:51 +1100693
Angel Pons39ff7032020-03-09 21:39:44 +0100694 reg32 = (s->selected_timings.tRCD << 17) | ((wl + 4 + s->selected_timings.tWTR) << 12) |
Damien Zammit003d15c2015-11-20 17:17:51 +1100695 (ta3 << 8) | (4 << 4) | ta1;
Angel Pons39ff7032020-03-09 21:39:44 +0100696 MCHBAR32(C0CYCTRKRD) = reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100697
Angel Pons39ff7032020-03-09 21:39:44 +0100698 reg16 = ((s->selected_timings.tRP + trp) << 9) | s->selected_timings.tRFC;
Damien Zammit003d15c2015-11-20 17:17:51 +1100699
Angel Pons39ff7032020-03-09 21:39:44 +0100700 /* FIXME: Why not do a single word write? */
701 MCHBAR8(C0CYCTRKREFR) = (u8) (reg16);
702 MCHBAR8(C0CYCTRKREFR + 1) = (u8) (reg16 >> 8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100703
Angel Pons39ff7032020-03-09 21:39:44 +0100704 MCHBAR16_AND_OR(C0CKECTRL, ~0x03fe, 100 << 1);
705 MCHBAR8_AND_OR(C0CYCTRKPCHG2, ~0x3f, s->selected_timings.tRAS);
706 MCHBAR16(C0ARBCTRL) = 0x2310;
707 MCHBAR8_AND_OR(C0ADDCSCTRL, ~0x1f, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +1100708
709 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
710 reg32 = 3000;
711 } else {
712 reg32 = 2500;
713 }
714 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
715 reg2 = 6000;
716 } else {
717 reg2 = 5000;
718 }
Angel Pons39ff7032020-03-09 21:39:44 +0100719 reg16 = (u16)((((s->selected_timings.CAS + 7) * (reg32)) / reg2) << 8);
720 MCHBAR16_AND_OR(C0STATRDCTRL, ~0x1f00, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100721
722 flag = 0;
723 if (wl > 2) {
724 flag = 1;
725 }
726 reg16 = (u8) (wl - 1 - flag);
727 reg16 |= reg16 << 4;
728 reg16 |= flag << 8;
Angel Pons39ff7032020-03-09 21:39:44 +0100729 MCHBAR16_AND_OR(C0WRDATACTRL, ~0x01ff, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100730
Angel Pons39ff7032020-03-09 21:39:44 +0100731 MCHBAR16(C0RDQCTRL) = 0x1585;
732 MCHBAR8_AND(C0PWLRCTRL, ~0x1f);
733
734 /* rdmodwr_window[5..0] = CL+4+5 265[13..8] (264[21..16]) */
735 MCHBAR16_AND_OR(C0PWLRCTRL, ~0x3f00, (s->selected_timings.CAS + 9) << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100736
737 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +0100738 reg16 = 0x0514;
739 reg32 = 0x0a28;
Damien Zammit003d15c2015-11-20 17:17:51 +1100740 } else {
Angel Pons39ff7032020-03-09 21:39:44 +0100741 reg16 = 0x0618;
742 reg32 = 0x0c30;
Damien Zammit003d15c2015-11-20 17:17:51 +1100743 }
Angel Pons39ff7032020-03-09 21:39:44 +0100744 MCHBAR32_AND_OR(C0REFRCTRL2, ~0x0fffff00, (0x3f << 22) | (reg32 << 8));
Damien Zammit003d15c2015-11-20 17:17:51 +1100745
Angel Pons39ff7032020-03-09 21:39:44 +0100746 /* FIXME: Is this weird access necessary? Reference code does it */
747 MCHBAR8(C0REFRCTRL + 3) = 0;
748 MCHBAR16_AND_OR(C0REFCTRL, 0xc000, reg16);
749
750 /* NPUT Static Mode */
751 MCHBAR8_OR(C0DYNRDCTRL, 1);
752
753 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x7f000000, 0xb << 25);
Damien Zammit003d15c2015-11-20 17:17:51 +1100754 i = s->selected_timings.mem_clock;
755 j = s->selected_timings.fsb_clock;
756 if (i > j) {
Angel Pons39ff7032020-03-09 21:39:44 +0100757 MCHBAR32_OR(C0STATRDCTRL, 1 << 24);
Damien Zammit003d15c2015-11-20 17:17:51 +1100758 }
759
Angel Pons39ff7032020-03-09 21:39:44 +0100760 MCHBAR8_AND(C0RDFIFOCTRL, ~0x3);
761 MCHBAR16_AND_OR(C0WRDATACTRL, ~0x7c00, (wl + 10) << 10);
762 MCHBAR32_AND_OR(C0CKECTRL, ~0x070e0000, (3 << 24) | (3 << 17));
Damien Zammit003d15c2015-11-20 17:17:51 +1100763 reg16 = 0x15 << 6;
764 reg16 |= 0x1f;
765 reg16 |= (0x6 << 12);
Angel Pons39ff7032020-03-09 21:39:44 +0100766 MCHBAR16_AND_OR(C0REFRCTRL + 4, ~0x7fff, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100767
Angel Pons39ff7032020-03-09 21:39:44 +0100768 reg32 = (0x6 << 27) | (1 << 25); /* FIXME: For DDR3, set BIT26 as well */
769 MCHBAR32_AND_OR(C0REFRCTRL2, ~0x30000000, reg32 << 8);
770 MCHBAR8_AND_OR(C0REFRCTRL + 3, ~0xfa, reg32 >> 24);
771 MCHBAR8_AND(C0JEDEC, ~(1 << 7));
772 MCHBAR8_AND(C0DYNRDCTRL, ~0x6);
Damien Zammit003d15c2015-11-20 17:17:51 +1100773
Angel Pons39ff7032020-03-09 21:39:44 +0100774 /* Note: This is a 64-bit register, [34..30] = 0b00110 is split across two writes */
775 reg32 = ((6 & 3) << 30) | (4 << 25) | (1 << 20) | (8 << 15) | (6 << 10) | (4 << 5) | 1;
776 MCHBAR32(C0WRWMFLSH) = reg32;
777 MCHBAR16_AND_OR(C0WRWMFLSH + 4, ~0x1ff, (8 << 3) | (6 >> 2));
778 MCHBAR16_OR(SHPENDREG, 0x1c00 | (0x1f << 5));
779
780 /* FIXME: Why not do a single word write? */
781 MCHBAR8_AND_OR(SHPAGECTRL, ~0xff, 0x40);
782 MCHBAR8_AND_OR(SHPAGECTRL + 1, ~0x07, 0x05);
783 MCHBAR8_OR(SHCMPLWRCMD, 0x1f);
784
785 reg8 = (3 << 6);
Damien Zammit003d15c2015-11-20 17:17:51 +1100786 reg8 |= (s->dt0mode << 4);
787 reg8 |= 0x0c;
Angel Pons39ff7032020-03-09 21:39:44 +0100788 MCHBAR8_AND_OR(SHBONUSREG, ~0xdf, reg8);
789 MCHBAR8_AND(CSHRWRIOMLNS, ~0x02);
790 MCHBAR8_AND_OR(C0MISCTM, ~0x07, 0x02);
791 MCHBAR16_AND_OR(C0BYPCTRL, ~0x3fc, 4 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +1100792
Angel Pons39ff7032020-03-09 21:39:44 +0100793 /* [31..29] = 0b010 for kN = 2 (2N) */
794 reg32 = (2 << 29) | (1 << 28) | (1 << 23);
795 MCHBAR32_AND_OR(WRWMCONFIG, ~0xffb00000, reg32);
796
797 reg8 = (u8) ((MCHBAR16(C0CYCTRKACT) & 0xe000) >> 13);
798 reg8 |= (u8) ((MCHBAR16(C0CYCTRKACT + 2) & 1) << 3);
799 MCHBAR8_AND_OR(BYPACTSF, ~0xf0, reg8 << 4);
800
801 reg8 = (u8) ((MCHBAR32(C0CYCTRKRD) & 0x000f0000) >> 17);
802 MCHBAR8_AND_OR(BYPACTSF, ~0x0f, reg8);
803
804 /* FIXME: Why not clear everything at once? */
805 MCHBAR8_AND(BYPKNRULE, ~0xfc);
806 MCHBAR8_AND(BYPKNRULE, ~0x03);
807 MCHBAR8_AND(SHBONUSREG, ~0x03);
808 MCHBAR8_OR(C0BYPCTRL, 1);
809 MCHBAR16_OR(CSHRMISCCTL1, 1 << 9);
810
Damien Zammit003d15c2015-11-20 17:17:51 +1100811 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +0100812 /* FIXME: Hardcoded for DDR2 SO-DIMMs */
813 MCHBAR32_AND_OR(C0DLLRCVCTLy(i), ~0x3f3f3f3f, 0x0c0c0c0c);
Damien Zammit003d15c2015-11-20 17:17:51 +1100814 }
Angel Pons39ff7032020-03-09 21:39:44 +0100815 /* RDCS to RCVEN delay: Program coarse common to all bytelanes to default tCL + 1 */
816 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, (s->selected_timings.CAS + 1) << 16);
817
818 /* Program RCVEN delay with DLL-safe settings */
Damien Zammit003d15c2015-11-20 17:17:51 +1100819 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +0100820 MCHBAR8_AND(C0RXRCVyDLL(i), ~0x3f);
821 MCHBAR16_AND(C0RCVMISCCTL2, (u16) ~(3 << (i * 2)));
822 MCHBAR16_AND(C0RCVMISCCTL1, (u16) ~(3 << (i * 2)));
823 MCHBAR16_AND(C0COARSEDLY0, (u16) ~(3 << (i * 2)));
Damien Zammit003d15c2015-11-20 17:17:51 +1100824 }
Angel Pons39ff7032020-03-09 21:39:44 +0100825 MCHBAR8_AND(C0DLLPIEN, ~1); /* Power up receiver */
826 MCHBAR8_OR(C0DLLPIEN, 2); /* Enable RCVEN DLL */
827 MCHBAR8_OR(C0DLLPIEN, 4); /* Enable receiver DQS DLL */
828 MCHBAR32_OR(C0COREBONUS, 0x000c0400);
829 MCHBAR32_OR(C0CMDTX1, 1 << 31);
Damien Zammit003d15c2015-11-20 17:17:51 +1100830}
831
Angel Pons39ff7032020-03-09 21:39:44 +0100832/* Program clkset0's register for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200833static void sdram_p_clkset0(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100834{
Angel Pons39ff7032020-03-09 21:39:44 +0100835 MCHBAR16_AND_OR(C0CKTX, ~0xc440,
Damien Zammit003d15c2015-11-20 17:17:51 +1100836 (pll->clkdelay[f][i] << 14) |
837 (pll->dben[f][i] << 10) |
Angel Pons39ff7032020-03-09 21:39:44 +0100838 (pll->dbsel[f][i] << 6));
839
840 MCHBAR8_AND_OR(C0TXCK0DLL, ~0x3f, pll->pi[f][i]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100841}
842
Angel Pons39ff7032020-03-09 21:39:44 +0100843/* Program clkset1's register for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200844static void sdram_p_clkset1(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100845{
Angel Pons39ff7032020-03-09 21:39:44 +0100846 /* FIXME: This is actually a dword write! */
847 MCHBAR16_AND_OR(C0CKTX, ~0x00030880,
Damien Zammit003d15c2015-11-20 17:17:51 +1100848 (pll->clkdelay[f][i] << 16) |
849 (pll->dben[f][i] << 11) |
Angel Pons39ff7032020-03-09 21:39:44 +0100850 (pll->dbsel[f][i] << 7));
851
852 MCHBAR8_AND_OR(C0TXCK1DLL, ~0x3f, pll->pi[f][i]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100853}
854
Angel Pons39ff7032020-03-09 21:39:44 +0100855/* Program CMD0 and CMD1 registers for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200856static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100857{
858 u8 reg8;
Angel Pons39ff7032020-03-09 21:39:44 +0100859 /* Clock Group Index 3 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100860 reg8 = pll->dbsel[f][i] << 5;
861 reg8 |= pll->dben[f][i] << 6;
Angel Pons39ff7032020-03-09 21:39:44 +0100862 MCHBAR8_AND_OR(C0CMDTX1, ~0x60, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100863
864 reg8 = pll->clkdelay[f][i] << 4;
Angel Pons39ff7032020-03-09 21:39:44 +0100865 MCHBAR8_AND_OR(C0CMDTX2, ~0x30, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100866
867 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100868 MCHBAR8_AND_OR(C0TXCMD0DLL, ~0x3f, reg8);
869 MCHBAR8_AND_OR(C0TXCMD1DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100870}
871
Angel Pons39ff7032020-03-09 21:39:44 +0100872/* Program CTRL registers for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200873static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100874{
875 u8 reg8;
876 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +0100877
878 /* CTRL0 and CTRL1 */
879 reg32 = ((u32) pll->dbsel[f][i]) << 20;
880 reg32 |= ((u32) pll->dben[f][i]) << 21;
Damien Zammit003d15c2015-11-20 17:17:51 +1100881 reg32 |= ((u32) pll->dbsel[f][i]) << 22;
Angel Pons39ff7032020-03-09 21:39:44 +0100882 reg32 |= ((u32) pll->dben[f][i]) << 23;
Damien Zammit003d15c2015-11-20 17:17:51 +1100883 reg32 |= ((u32) pll->clkdelay[f][i]) << 24;
884 reg32 |= ((u32) pll->clkdelay[f][i]) << 27;
Angel Pons39ff7032020-03-09 21:39:44 +0100885 MCHBAR32_AND_OR(C0CTLTX2, ~0x01bf0000, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100886
887 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100888 MCHBAR8_AND_OR(C0TXCTL0DLL, ~0x3f, reg8);
889 MCHBAR8_AND_OR(C0TXCTL1DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100890
Angel Pons39ff7032020-03-09 21:39:44 +0100891 /* CTRL2 and CTRL3 */
892 reg32 = ((u32) pll->dbsel[f][i]) << 12;
893 reg32 |= ((u32) pll->dben[f][i]) << 13;
Damien Zammit003d15c2015-11-20 17:17:51 +1100894 reg32 |= ((u32) pll->dbsel[f][i]) << 8;
Angel Pons39ff7032020-03-09 21:39:44 +0100895 reg32 |= ((u32) pll->dben[f][i]) << 9;
Damien Zammit003d15c2015-11-20 17:17:51 +1100896 reg32 |= ((u32) pll->clkdelay[f][i]) << 14;
897 reg32 |= ((u32) pll->clkdelay[f][i]) << 10;
Angel Pons39ff7032020-03-09 21:39:44 +0100898 MCHBAR32_AND_OR(C0CMDTX2, ~0xff00, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100899
900 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100901 MCHBAR8_AND_OR(C0TXCTL2DLL, ~0x3f, reg8);
902 MCHBAR8_AND_OR(C0TXCTL3DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100903}
904
905static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
906{
907 u8 rank, dqs, reg8, j;
908 u32 reg32;
909
Angel Pons39ff7032020-03-09 21:39:44 +0100910 j = clk - 40;
911 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100912 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100913 rank = j % 4;
914 dqs = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100915
Angel Pons39ff7032020-03-09 21:39:44 +0100916 reg32 |= ((u32) pll->dben[f][clk]) << (dqs + 9);
Damien Zammit003d15c2015-11-20 17:17:51 +1100917 reg32 |= ((u32) pll->dbsel[f][clk]) << dqs;
Damien Zammit003d15c2015-11-20 17:17:51 +1100918
Nico Huber12d37682021-02-06 14:39:54 +0100919 MCHBAR32_AND_OR(C0DQSRyTX1(rank), ~((1 << (dqs + 9)) | (1 << dqs)), reg32);
Angel Pons39ff7032020-03-09 21:39:44 +0100920
921 reg32 = ((u32) pll->clkdelay[f][clk]) << ((dqs * 2) + 16);
922 MCHBAR32_AND_OR(C0DQSDQRyTX3(rank), ~((1 << (dqs * 2 + 17)) | (1 << (dqs * 2 + 16))),
923 reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100924
925 reg8 = pll->pi[f][clk];
Angel Pons39ff7032020-03-09 21:39:44 +0100926 MCHBAR8_AND_OR(C0TXDQS0R0DLL + j, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100927}
928
Damien Zammit003d15c2015-11-20 17:17:51 +1100929static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
930{
931 u8 rank, dq, reg8, j;
932 u32 reg32;
933
Angel Pons39ff7032020-03-09 21:39:44 +0100934 j = clk - 8;
935 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100936 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100937 rank = j % 4;
938 dq = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100939
Angel Pons39ff7032020-03-09 21:39:44 +0100940 reg32 |= ((u32) pll->dben[f][clk]) << (dq + 9);
Damien Zammit003d15c2015-11-20 17:17:51 +1100941 reg32 |= ((u32) pll->dbsel[f][clk]) << dq;
Angel Pons39ff7032020-03-09 21:39:44 +0100942
Nico Huber12d37682021-02-06 14:39:54 +0100943 MCHBAR32_AND_OR(C0DQRyTX1(rank), ~((1 << (dq + 9)) | (1 << dq)), reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100944
945 reg32 = ((u32) pll->clkdelay[f][clk]) << (dq*2);
Angel Pons39ff7032020-03-09 21:39:44 +0100946 MCHBAR32_AND_OR(C0DQSDQRyTX3(rank), ~((1 << (dq * 2 + 1)) | (1 << (dq * 2))), reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100947
948 reg8 = pll->pi[f][clk];
Angel Pons39ff7032020-03-09 21:39:44 +0100949 MCHBAR8_AND_OR(C0TXDQ0R0DLL + j, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100950}
951
Angel Pons39ff7032020-03-09 21:39:44 +0100952/* WDLL programming: Perform HPLL/MPLL calibration after write levelization */
Damien Zammit003d15c2015-11-20 17:17:51 +1100953static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
954{
955 struct pllparam pll = {
956 .pi = {
Angel Pons39ff7032020-03-09 21:39:44 +0100957 { /* DDR = 667 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100958 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
959 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
960 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
961 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
962 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Angel Pons39ff7032020-03-09 21:39:44 +0100963 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3,
Damien Zammit003d15c2015-11-20 17:17:51 +1100964 },
Angel Pons39ff7032020-03-09 21:39:44 +0100965 { /* DDR = 800 */
966 53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
Damien Zammit003d15c2015-11-20 17:17:51 +1100967 34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
968 47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
Angel Pons39ff7032020-03-09 21:39:44 +0100969 47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
970 2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
971 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15,
Damien Zammit003d15c2015-11-20 17:17:51 +1100972 }},
973
974 .dben = {
Angel Pons39ff7032020-03-09 21:39:44 +0100975 { /* DDR = 667 */
976 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
977 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
978 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
979 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
980 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
981 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100982 },
Angel Pons39ff7032020-03-09 21:39:44 +0100983 { /* DDR = 800 */
984 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
985 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
986 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
987 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
988 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
989 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100990 }},
991
992 .dbsel = {
Angel Pons39ff7032020-03-09 21:39:44 +0100993 { /* DDR = 667 */
994 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
995 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
996 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
997 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
998 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
999 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001000 },
Angel Pons39ff7032020-03-09 21:39:44 +01001001 { /* DDR = 800 */
1002 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1003 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1004 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1005 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1006 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1007 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001008 }},
1009
1010 .clkdelay = {
Angel Pons39ff7032020-03-09 21:39:44 +01001011 { /* DDR = 667 */
1012 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1013 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1014 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1015 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1016 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1017 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001018 },
Angel Pons39ff7032020-03-09 21:39:44 +01001019 { /* DDR = 800 */
1020 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1021 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1022 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1023 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1024 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1025 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Damien Zammit003d15c2015-11-20 17:17:51 +11001026 }}
1027 };
1028
1029 u8 i, f;
1030 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1031 f = 0;
1032 } else {
1033 f = 1;
1034 }
1035 for (i = 0; i < 72; i++) {
1036 pll.pi[f][i] += pidelay;
1037 }
1038
Angel Pons39ff7032020-03-09 21:39:44 +01001039 /* Disable Dynamic DQS Slave Setting Per Rank */
1040 MCHBAR8_AND(CSHRDQSCMN, ~(1 << 7));
1041 MCHBAR16_AND_OR(CSHRPDCTL4, ~0x3fff, 0x1fff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001042
1043 sdram_p_clkset0(&pll, f, 0);
1044 sdram_p_clkset1(&pll, f, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01001045 sdram_p_cmd(&pll, f, 2);
1046 sdram_p_ctrl(&pll, f, 4);
1047
Damien Zammit003d15c2015-11-20 17:17:51 +11001048 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001049 sdram_p_dqs(&pll, f, i + 40);
Damien Zammit003d15c2015-11-20 17:17:51 +11001050 }
1051 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001052 sdram_p_dq(&pll, f, i + 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11001053 }
1054}
1055
Angel Pons39ff7032020-03-09 21:39:44 +01001056/* Perform HMC hardware calibration */
Damien Zammit003d15c2015-11-20 17:17:51 +11001057static void sdram_calibratehwpll(struct sysinfo *s)
1058{
1059 u8 reg8;
1060
1061 s->async = 0;
1062 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001063
Angel Pons39ff7032020-03-09 21:39:44 +01001064 MCHBAR16_OR(CSHRPDCTL, 1 << 15);
1065 MCHBAR8_AND(CSHRPDCTL, ~(1 << 7));
1066 MCHBAR8_OR(CSHRPDCTL, 1 << 3);
1067 MCHBAR8_OR(CSHRPDCTL, 1 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001068
Angel Pons39ff7032020-03-09 21:39:44 +01001069 /* Start hardware HMC calibration */
1070 MCHBAR8_OR(CSHRPDCTL, 1 << 7);
1071
1072 /* Busy-wait until calibration is done */
1073 while ((MCHBAR8(CSHRPDCTL) & (1 << 2)) == 0)
1074 ;
1075
1076 /* If hardware HMC calibration failed */
1077 reg8 = (MCHBAR8(CSHRPDCTL) & (1 << 3)) >> 3;
Damien Zammit003d15c2015-11-20 17:17:51 +11001078 if (reg8 != 0) {
1079 s->async = 1;
1080 }
1081}
1082
1083static void sdram_dlltiming(struct sysinfo *s)
1084{
Elyes HAOUAS66b462d2019-01-02 21:11:32 +01001085 u8 reg8, i;
Damien Zammit003d15c2015-11-20 17:17:51 +11001086 u16 reg16;
1087 u32 reg32;
1088
Angel Pons39ff7032020-03-09 21:39:44 +01001089 /* Configure the Master DLL */
Damien Zammit003d15c2015-11-20 17:17:51 +11001090 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +01001091 reg32 = 0x08014227;
Damien Zammit003d15c2015-11-20 17:17:51 +11001092 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001093 reg32 = 0x00014221;
Damien Zammit003d15c2015-11-20 17:17:51 +11001094 }
Angel Pons39ff7032020-03-09 21:39:44 +01001095 MCHBAR32_AND_OR(CSHRMSTRCTL1, ~0x0fffffff, reg32);
1096 MCHBAR32_OR(CSHRMSTRCTL1, 1 << 23);
1097 MCHBAR32_OR(CSHRMSTRCTL1, 1 << 15);
1098 MCHBAR32_AND(CSHRMSTRCTL1, ~(1 << 15));
Damien Zammit003d15c2015-11-20 17:17:51 +11001099
1100 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001101 /* Disable the Master DLLs by setting these bits, IN ORDER! */
1102 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 0);
1103 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 2);
1104 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 4);
1105 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 8);
1106 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 10);
1107 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 12);
1108 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 14);
Damien Zammit003d15c2015-11-20 17:17:51 +11001109 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001110 /* Enable the Master DLLs by clearing these bits, IN ORDER! */
1111 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 0));
1112 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 2));
1113 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 4));
1114 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 8));
1115 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 10));
1116 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 12));
1117 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 14));
Damien Zammit003d15c2015-11-20 17:17:51 +11001118 }
1119
Angel Pons39ff7032020-03-09 21:39:44 +01001120 /* Initialize the Transmit DLL PI values in the following sequence. */
Damien Zammit003d15c2015-11-20 17:17:51 +11001121 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001122 MCHBAR8_AND_OR(CREFPI, ~0x3f, 0x07);
Damien Zammit003d15c2015-11-20 17:17:51 +11001123 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001124 MCHBAR8_AND(CREFPI, ~0x3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001125 }
1126
1127 sdram_calibratepll(s, 0); // XXX check
1128
Angel Pons39ff7032020-03-09 21:39:44 +01001129 /* Enable all modular Slave DLL */
1130 MCHBAR16_OR(C0DLLPIEN, 1 << 11);
1131 MCHBAR16_OR(C0DLLPIEN, 1 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11001132
1133 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001134 MCHBAR16_OR(C0DLLPIEN, (1 << 10) >> i);
Damien Zammit003d15c2015-11-20 17:17:51 +11001135 }
Angel Pons39ff7032020-03-09 21:39:44 +01001136 /* Enable DQ/DQS output */
1137 MCHBAR8_OR(C0SLVDLLOUTEN, 1);
1138 MCHBAR16(CSPDSLVWT) = 0x5005;
1139 MCHBAR16_AND_OR(CSHRPDCTL2, ~0x1f1f, 0x051a);
1140 MCHBAR16_AND_OR(CSHRPDCTL5, ~0xbf3f, 0x9010);
Damien Zammit003d15c2015-11-20 17:17:51 +11001141
1142 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001143 MCHBAR8_AND_OR(CSHRPDCTL3, ~0x7f, 0x6b);
Damien Zammit003d15c2015-11-20 17:17:51 +11001144 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001145 MCHBAR8_AND_OR(CSHRPDCTL3, ~0x7f, 0x55);
Damien Zammit003d15c2015-11-20 17:17:51 +11001146 sdram_calibratehwpll(s);
1147 }
Angel Pons39ff7032020-03-09 21:39:44 +01001148 /* Disable Dynamic Diff Amp */
1149 MCHBAR32_AND(C0STATRDCTRL, ~(1 << 22));
Damien Zammit003d15c2015-11-20 17:17:51 +11001150
Angel Pons39ff7032020-03-09 21:39:44 +01001151 /* Now, start initializing the transmit FIFO */
1152 MCHBAR8_AND(C0MISCCTL, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11001153
Angel Pons39ff7032020-03-09 21:39:44 +01001154 /* Disable (gate) mdclk and mdclkb */
1155 MCHBAR8_OR(CSHWRIOBONUS, 0xc0);
Jacob Garberd10680b2019-06-11 14:13:04 -06001156
Angel Pons39ff7032020-03-09 21:39:44 +01001157 /* Select mdmclk */
1158 MCHBAR8_AND(CSHWRIOBONUS, ~(1 << 5));
Damien Zammit003d15c2015-11-20 17:17:51 +11001159
Angel Pons39ff7032020-03-09 21:39:44 +01001160 /* Ungate mdclk */
1161 MCHBAR8_AND_OR(CSHWRIOBONUS, ~0xc0, 1 << 6);
1162 MCHBAR8_AND_OR(CSHRFIFOCTL, ~0x3f, 0x1a);
1163
1164 /* Enable the write pointer count */
1165 MCHBAR8_OR(CSHRFIFOCTL, 1);
1166
1167 /* Set the DDR3 Reset Enable bit */
1168 MCHBAR8_OR(CSHRDDR3CTL, 1);
1169
1170 /* Configure DQS-DQ Transmit */
1171 MCHBAR32(CSHRDQSTXPGM) = 0x00551803;
1172
1173 reg8 = 0; /* Switch all clocks on anyway */
1174
1175 /* Enable clock groups depending on rank population */
1176 MCHBAR32_AND_OR(C0CKTX, ~0x3f000000, reg8 << 24);
1177
1178 /* Enable DDR command output buffers from core */
1179 MCHBAR8_AND(0x594, ~1);
1180
Damien Zammit003d15c2015-11-20 17:17:51 +11001181 reg16 = 0;
1182 if (!rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001183 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001184 }
1185 if (!rank_is_populated(s->dimms, 0, 1)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001186 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001187 }
1188 if (!rank_is_populated(s->dimms, 0, 2)) {
1189 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1190 }
1191 if (!rank_is_populated(s->dimms, 0, 3)) {
1192 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1193 }
Angel Pons39ff7032020-03-09 21:39:44 +01001194 MCHBAR16_OR(C0CTLTX2, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001195}
1196
Angel Pons39ff7032020-03-09 21:39:44 +01001197/* Define a shorter name for these to make the lines fit in 96 characters */
1198#define TABLE static const
1199
1200/* Loop over each RCOMP group, but skip group 1 because it does not exist */
1201#define FOR_EACH_RCOMP_GROUP(idx) for (idx = 0; idx < 7; idx++) if (idx != 1)
1202
1203/* Define accessors for the RCOMP register banks */
1204#define C0RCOMPCTRLx(x) (rcompctl[(x)] + 0x00)
1205#define C0RCOMPMULTx(x) (rcompctl[(x)] + 0x04)
1206#define C0RCOMPOVRx(x) (rcompctl[(x)] + 0x06)
1207#define C0RCOMPOSVx(x) (rcompctl[(x)] + 0x0A)
1208#define C0SCOMPVREFx(x) (rcompctl[(x)] + 0x0E)
1209#define C0SCOMPOVRx(x) (rcompctl[(x)] + 0x10)
1210#define C0SCOMPOFFx(x) (rcompctl[(x)] + 0x12)
1211#define C0DCOMPx(x) (rcompctl[(x)] + 0x14)
1212#define C0SLEWBASEx(x) (rcompctl[(x)] + 0x16)
1213#define C0SLEWPULUTx(x) (rcompctl[(x)] + 0x18)
1214#define C0SLEWPDLUTx(x) (rcompctl[(x)] + 0x1C)
1215#define C0DCOMPOVRx(x) (rcompctl[(x)] + 0x20)
1216#define C0DCOMPOFFx(x) (rcompctl[(x)] + 0x24)
1217
1218/* FIXME: This only applies to DDR2 */
Damien Zammit003d15c2015-11-20 17:17:51 +11001219static void sdram_rcomp(struct sysinfo *s)
1220{
Angel Pons39ff7032020-03-09 21:39:44 +01001221 u8 i, j, reg8, rcompp, rcompn, srup, srun;
Damien Zammit003d15c2015-11-20 17:17:51 +11001222 u16 reg16;
1223 u32 reg32, rcomp1, rcomp2;
1224
Angel Pons39ff7032020-03-09 21:39:44 +01001225 static const u8 rcompslew = 0x0a;
1226 static const u16 rcompctl[7] = {
1227 C0RCOMPCTRL0,
1228 0, /* This register does not exist */
1229 C0RCOMPCTRL2,
1230 C0RCOMPCTRL3,
1231 C0RCOMPCTRL4,
1232 C0RCOMPCTRL5,
1233 C0RCOMPCTRL6,
1234 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001235
Angel Pons39ff7032020-03-09 21:39:44 +01001236 /* RCOMP settings tables = { NC-NC, x16SS, x16DS, x16SS2, x16DS2, x8DS, x8DS2}; */
1237 TABLE u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0};
1238 TABLE u8 rcompstr[7] = { 0x66, 0x00, 0xaa, 0x55, 0x55, 0x77, 0x77};
1239 TABLE u16 rcompscomp[7] = {0xa22a, 0x0000, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a};
1240 TABLE u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1};
1241 TABLE u16 rcompf[7] = {0x1114, 0x0000, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a};
1242 TABLE u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0xaa};
1243 TABLE u16 rcompscomp2[7] = {0x0000, 0xe22e, 0xe22e, 0xe22e, 0x8228, 0xe22e, 0x8228};
1244 TABLE u8 rcompdelay2[7] = { 0, 0, 0, 0, 2, 0, 2};
Damien Zammit003d15c2015-11-20 17:17:51 +11001245
Angel Pons39ff7032020-03-09 21:39:44 +01001246 TABLE u8 rcomplut[64][12] = {
1247 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1248 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1249 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1250 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1251 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1252 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1253 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1254 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1255 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1256 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1257 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1258 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1259 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1260 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1261 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1262 {10, 9, 12, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1263 {10, 9, 12, 11, 2, 2, 6, 5, 7, 6, 6, 5},
1264 {10, 10, 12, 12, 2, 2, 6, 5, 7, 6, 6, 5},
1265 {10, 10, 12, 12, 2, 2, 6, 6, 7, 7, 6, 6},
1266 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1267 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1268 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1269 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1270 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1271 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1272 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1273 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1274 {11, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1275 {11, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1276 {12, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1277 {12, 12, 14, 13, 3, 3, 7, 6, 7, 7, 7, 6},
1278 {13, 12, 16, 15, 3, 3, 7, 6, 8, 7, 7, 6},
1279 {13, 14, 16, 15, 4, 3, 7, 7, 8, 8, 7, 7},
1280 {14, 14, 16, 17, 4, 3, 7, 7, 8, 8, 7, 7},
1281 {14, 16, 18, 17, 4, 4, 8, 7, 8, 8, 8, 7},
1282 {15, 16, 18, 19, 4, 4, 8, 7, 9, 8, 8, 7},
1283 {15, 18, 18, 19, 4, 4, 8, 8, 9, 9, 8, 8},
1284 {16, 18, 20, 21, 4, 4, 8, 8, 9, 9, 8, 8},
1285 {16, 19, 20, 21, 5, 4, 9, 8, 10, 9, 9, 8},
1286 {16, 19, 20, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1287 {17, 19, 22, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1288 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1289 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1290 {18, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1291 {18, 21, 24, 25, 5, 5, 9, 9, 11, 10, 9, 9},
1292 {19, 21, 24, 27, 5, 5, 9, 9, 11, 11, 9, 9},
1293 {19, 22, 24, 27, 5, 5, 10, 9, 11, 11, 10, 9},
1294 {20, 22, 24, 27, 6, 5, 10, 10, 11, 11, 10, 10},
1295 {20, 23, 26, 27, 6, 6, 10, 10, 12, 12, 10, 10},
1296 {20, 23, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1297 {21, 24, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1298 {21, 24, 26, 29, 6, 6, 11, 10, 12, 13, 11, 10},
1299 {22, 25, 28, 29, 6, 6, 11, 11, 13, 13, 11, 11},
1300 {22, 25, 28, 31, 6, 6, 11, 11, 13, 13, 11, 11},
1301 {22, 26, 28, 31, 6, 6, 11, 11, 13, 14, 11, 11},
1302 {23, 26, 30, 31, 7, 6, 12, 11, 14, 14, 12, 11},
1303 {23, 27, 30, 33, 7, 7, 12, 12, 14, 14, 12, 12},
1304 {23, 27, 30, 33, 7, 7, 12, 12, 14, 15, 12, 12},
1305 {24, 28, 32, 33, 7, 7, 12, 12, 15, 15, 12, 12},
1306 {24, 28, 32, 33, 7, 7, 12, 12, 15, 16, 12, 12},
1307 {24, 29, 32, 35, 7, 7, 12, 12, 15, 16, 12, 12},
1308 {25, 29, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1309 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1310 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
Damien Zammit003d15c2015-11-20 17:17:51 +11001311 };
1312
1313 srup = 0;
1314 srun = 0;
1315
1316 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001317 rcomp1 = 0x00050431;
1318 } else {
Damien Zammit003d15c2015-11-20 17:17:51 +11001319 rcomp1 = 0x00050542;
1320 }
1321 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
1322 rcomp2 = 0x14C42827;
1323 } else {
1324 rcomp2 = 0x19042827;
1325 }
1326
Angel Pons39ff7032020-03-09 21:39:44 +01001327 FOR_EACH_RCOMP_GROUP(i) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001328 reg8 = rcompupdate[i];
Angel Pons39ff7032020-03-09 21:39:44 +01001329 MCHBAR8_AND_OR(C0RCOMPCTRLx(i), ~1, reg8);
1330 MCHBAR8_AND(C0RCOMPCTRLx(i), ~2);
1331
1332 reg16 = rcompslew;
1333 MCHBAR16_AND_OR(C0RCOMPCTRLx(i), ~0xf000, reg16 << 12);
1334
1335 MCHBAR8(C0RCOMPMULTx(i)) = rcompstr[i];
1336 MCHBAR16(C0SCOMPVREFx(i)) = rcompscomp[i];
1337 MCHBAR8_AND_OR(C0DCOMPx(i), ~0x03, rcompdelay[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001338 if (i == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01001339 /* FIXME: Why are we rewriting this? */
1340 MCHBAR16_AND_OR(C0RCOMPCTRLx(i), ~0xf000, reg16 << 12);
1341
1342 MCHBAR8(C0RCOMPMULTx(i)) = rcompstr2[s->dimm_config[0]];
1343 MCHBAR16(C0SCOMPVREFx(i)) = rcompscomp2[s->dimm_config[0]];
1344 MCHBAR8_AND_OR(C0DCOMPx(i), ~0x03, rcompdelay2[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001345 }
1346
Angel Pons39ff7032020-03-09 21:39:44 +01001347 MCHBAR16_AND(C0SLEWBASEx(i), ~0x7f7f);
1348
1349 /* FIXME: Why not do a single dword write? */
1350 MCHBAR16_AND(C0SLEWPULUTx(i), ~0x3f3f);
1351 MCHBAR16_AND(C0SLEWPULUTx(i) + 2, ~0x3f3f);
1352
1353 /* FIXME: Why not do a single dword write? */
1354 MCHBAR16_AND(C0SLEWPDLUTx(i), ~0x3f3f);
1355 MCHBAR16_AND(C0SLEWPDLUTx(i) + 2, ~0x3f3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001356 }
1357
Angel Pons39ff7032020-03-09 21:39:44 +01001358 /* FIXME: Hardcoded */
1359 MCHBAR8_AND_OR(C0ODTRECORDX, ~0x3f, 0x36);
1360 MCHBAR8_AND_OR(C0DQSODTRECORDX, ~0x3f, 0x36);
Damien Zammit003d15c2015-11-20 17:17:51 +11001361
Angel Pons39ff7032020-03-09 21:39:44 +01001362 FOR_EACH_RCOMP_GROUP(i) {
1363 MCHBAR8_AND(C0RCOMPCTRLx(i), ~0x60);
1364 MCHBAR16_AND(C0RCOMPCTRLx(i) + 2, ~0x0706);
1365 MCHBAR16_AND(C0RCOMPOSVx(i), ~0x7f7f);
1366 MCHBAR16_AND(C0SCOMPOFFx(i), ~0x3f3f);
1367 MCHBAR16_AND(C0DCOMPOFFx(i), ~0x1f1f);
1368 MCHBAR8_AND(C0DCOMPOFFx(i) + 2, ~0x1f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001369 }
1370
Angel Pons39ff7032020-03-09 21:39:44 +01001371 MCHBAR16_AND(C0ODTRECORDX, ~0xffc0);
1372 MCHBAR16_AND(C0ODTRECORDX + 2, ~0x000f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001373
Angel Pons39ff7032020-03-09 21:39:44 +01001374 /* FIXME: Why not do a single dword write? */
1375 MCHBAR16_AND(C0DQSODTRECORDX, ~0xffc0);
1376 MCHBAR16_AND(C0DQSODTRECORDX + 2, ~0x000f);
1377
1378 FOR_EACH_RCOMP_GROUP(i) {
1379 MCHBAR16(C0SCOMPOVRx(i)) = rcompf[i];
1380
1381 /* FIXME: Why not do a single dword write? */
1382 MCHBAR16(C0DCOMPOVRx(i)) = 0x1219;
1383 MCHBAR16(C0DCOMPOVRx(i) + 2) = 0x000C;
Damien Zammit003d15c2015-11-20 17:17:51 +11001384 }
1385
Angel Pons39ff7032020-03-09 21:39:44 +01001386 MCHBAR32_AND_OR(DCMEASBUFOVR, ~0x001f1f1f, 0x000c1219);
Damien Zammit003d15c2015-11-20 17:17:51 +11001387
Angel Pons39ff7032020-03-09 21:39:44 +01001388 /* FIXME: Why not do a single word write? */
1389 MCHBAR16_AND_OR(XCOMPSDR0BNS, ~0x1f00, 0x1200);
1390 MCHBAR8_AND_OR(XCOMPSDR0BNS, ~0x1f, 0x12);
1391
1392 MCHBAR32(COMPCTRL3) = 0x007C9007;
1393 MCHBAR32(OFREQDELSEL) = rcomp1;
1394 MCHBAR16(XCOMPCMNBNS) = 0x1f7f;
1395 MCHBAR32(COMPCTRL2) = rcomp2;
1396 MCHBAR16_AND_OR(XCOMPDFCTRL, ~0x0f, 1);
1397 MCHBAR16(ZQCALCTRL) = 0x0134;
1398 MCHBAR32(COMPCTRL1) = 0x4C293600;
1399
1400 /* FIXME: wtf did these MRC guys smoke */
1401 MCHBAR8_AND_OR(COMPCTRL1 + 3, ~0x44, (1 << 6) | (1 << 2));
1402 MCHBAR16_AND(XCOMPSDR0BNS, ~(1 << 13));
1403 MCHBAR8_AND(XCOMPSDR0BNS, ~(1 << 5));
1404
1405 FOR_EACH_RCOMP_GROUP(i) {
1406 /* FIXME: This should be an _AND_OR */
1407 MCHBAR8(C0RCOMPCTRLx(i) + 2) = MCHBAR8(C0RCOMPCTRLx(i)) & ~0x71;
Damien Zammit003d15c2015-11-20 17:17:51 +11001408 }
1409
Angel Pons39ff7032020-03-09 21:39:44 +01001410 if ((MCHBAR32(COMPCTRL1) & (1 << 30)) == 0) {
1411 /* Start COMP */
1412 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001413
Angel Pons39ff7032020-03-09 21:39:44 +01001414 /* Wait until COMP is done */
1415 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1416 ;
1417
1418 reg32 = MCHBAR32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001419 rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1420 rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1421
Angel Pons39ff7032020-03-09 21:39:44 +01001422 FOR_EACH_RCOMP_GROUP(i) {
1423 srup = (MCHBAR8(C0RCOMPCTRLx(i) + 1) & 0xc0) >> 6;
1424 srun = (MCHBAR8(C0RCOMPCTRLx(i) + 1) & 0x30) >> 4;
1425
1426 /* FIXME: Why not do a single word write? */
Damien Zammit003d15c2015-11-20 17:17:51 +11001427 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
Angel Pons39ff7032020-03-09 21:39:44 +01001428 MCHBAR16_AND_OR(C0SLEWBASEx(i), ~0x7f00, reg16);
1429
Damien Zammit003d15c2015-11-20 17:17:51 +11001430 reg16 = (u16)(rcompn - (1 << (srun + 1)));
Angel Pons39ff7032020-03-09 21:39:44 +01001431 MCHBAR8_AND_OR(C0SLEWBASEx(i), ~0x7f, (u8)reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001432 }
1433
1434 reg8 = rcompp - (1 << (srup + 1));
1435 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001436 MCHBAR8_AND_OR(C0SLEWPULUTx(0) + i, ~0x3f, rcomplut[j][0]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001437 }
1438
1439 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1440 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons39ff7032020-03-09 21:39:44 +01001441 MCHBAR8_AND_OR(C0SLEWPULUTx(2) + i, ~0x3f, rcomplut[j][10]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001442 }
1443 }
1444
1445 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001446 MCHBAR8_AND_OR(C0SLEWPULUTx(3) + i, ~0x3f, rcomplut[j][6]);
1447 MCHBAR8_AND_OR(C0SLEWPULUTx(4) + i, ~0x3f, rcomplut[j][6]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001448 }
1449
1450 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001451 MCHBAR8_AND_OR(C0SLEWPULUTx(5) + i, ~0x3f, rcomplut[j][8]);
1452 MCHBAR8_AND_OR(C0SLEWPULUTx(6) + i, ~0x3f, rcomplut[j][8]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001453 }
1454
1455 reg8 = rcompn - (1 << (srun + 1));
1456 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001457 MCHBAR8_AND_OR(C0SLEWPDLUTx(0) + i, ~0x3f, rcomplut[j][1]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001458 }
1459
1460 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1461 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons39ff7032020-03-09 21:39:44 +01001462 MCHBAR8_AND_OR(C0SLEWPDLUTx(2) + i, ~0x3f, rcomplut[j][11]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001463 }
1464 }
1465
1466 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001467 MCHBAR8_AND_OR(C0SLEWPDLUTx(3) + i, ~0x3f, rcomplut[j][7]);
1468 MCHBAR8_AND_OR(C0SLEWPDLUTx(4) + i, ~0x3f, rcomplut[j][7]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001469 }
1470
1471 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001472 MCHBAR8_AND_OR(C0SLEWPDLUTx(5) + i, ~0x3f, rcomplut[j][9]);
1473 MCHBAR8_AND_OR(C0SLEWPDLUTx(6) + i, ~0x3f, rcomplut[j][9]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001474 }
1475 }
Angel Pons39ff7032020-03-09 21:39:44 +01001476 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001477}
1478
Angel Pons39ff7032020-03-09 21:39:44 +01001479/* FIXME: The ODT tables are for DDR2 only! */
Damien Zammit003d15c2015-11-20 17:17:51 +11001480static void sdram_odt(struct sysinfo *s)
1481{
1482 u8 rankindex = 0;
1483
Angel Pons39ff7032020-03-09 21:39:44 +01001484 static const u16 odt_rankctrl[16] = {
1485 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1486 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1487 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1488 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1489 };
1490 static const u16 odt_matrix[16] = {
1491 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1492 0x0000, 0x0011, 0x0000, 0x0011, 0x0000, 0x4444, 0x0000, 0x4444,
1493 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1494 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4444, 0x0000, 0x4444,
1495 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001496
1497 switch (s->dimms[0].ranks) {
1498 case 0:
1499 if (s->dimms[1].ranks == 0) {
1500 rankindex = 0;
1501 } else if (s->dimms[1].ranks == 1) {
1502 rankindex = 4;
1503 } else if (s->dimms[1].ranks == 2) {
1504 rankindex = 12;
1505 }
1506 break;
1507 case 1:
1508 if (s->dimms[1].ranks == 0) {
1509 rankindex = 1;
1510 } else if (s->dimms[1].ranks == 1) {
1511 rankindex = 5;
1512 } else if (s->dimms[1].ranks == 2) {
1513 rankindex = 13;
1514 }
1515 break;
1516 case 2:
1517 if (s->dimms[1].ranks == 0) {
1518 rankindex = 3;
1519 } else if (s->dimms[1].ranks == 1) {
1520 rankindex = 7;
1521 } else if (s->dimms[1].ranks == 2) {
1522 rankindex = 15;
1523 }
1524 break;
1525 }
1526
Angel Pons39ff7032020-03-09 21:39:44 +01001527 /* Program the ODT Matrix */
1528 MCHBAR16(C0ODT) = odt_matrix[rankindex];
1529
1530 /* Program the ODT Rank Control */
1531 MCHBAR16(C0ODTRKCTRL) = odt_rankctrl[rankindex];
Damien Zammit003d15c2015-11-20 17:17:51 +11001532}
1533
1534static void sdram_mmap(struct sysinfo *s)
1535{
Angel Pons39ff7032020-03-09 21:39:44 +01001536 TABLE u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000, 0xc00001, 0xf00000};
1537 TABLE u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101, 0x1010000, 0x1010101};
1538 TABLE u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1539 TABLE u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006, 0x40002, 0x80006};
Damien Zammit003d15c2015-11-20 17:17:51 +11001540
Angel Pons39ff7032020-03-09 21:39:44 +01001541 TABLE u16 tolud[7] = {2048, 2048, 4096, 4096, 8192, 4096, 8192};
1542 TABLE u16 tom[7] = { 2, 2, 4, 4, 8, 4, 8};
1543 TABLE u16 touud[7] = { 128, 128, 256, 256, 512, 256, 512};
1544 TABLE u32 gbsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1545 TABLE u32 bgsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1546 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 +11001547
1548 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1549 if (s->dimms[0].sides > 1) {
1550 // 2R/NC
Angel Pons39ff7032020-03-09 21:39:44 +01001551 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x300001);
1552 MCHBAR32(C0DRA01) = 0x00000101;
1553 MCHBAR32(C0DRB0) = 0x00040002;
1554 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001555 } else {
1556 // 1R/NC
Angel Pons39ff7032020-03-09 21:39:44 +01001557 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x100001);
1558 MCHBAR32(C0DRA01) = 0x00000001;
1559 MCHBAR32(C0DRB0) = 0x00020002;
1560 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001561 }
1562 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001563 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x300001);
1564 MCHBAR32(C0DRA01) = 0x00000101;
1565 MCHBAR32(C0DRB0) = 0x00040002;
1566 MCHBAR32(C0DRB2) = 0x00040004;
Damien Zammit003d15c2015-11-20 17:17:51 +11001567 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001568 MCHBAR32_AND_OR(C0CKECTRL, ~1, w260[s->dimm_config[0]]);
1569 MCHBAR32(C0DRA01) = w208[s->dimm_config[0]];
1570 MCHBAR32(C0DRB0) = w200[s->dimm_config[0]];
1571 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001572 }
Angel Pons39ff7032020-03-09 21:39:44 +01001573 pci_write_config16(HOST_BRIDGE, 0xb0, tolud[s->dimm_config[0]]);
1574 pci_write_config16(HOST_BRIDGE, 0xa0, tom[s->dimm_config[0]]);
1575 pci_write_config16(HOST_BRIDGE, 0xa2, touud[s->dimm_config[0]]);
1576 pci_write_config32(HOST_BRIDGE, 0xa4, gbsm[s->dimm_config[0]]);
1577 pci_write_config32(HOST_BRIDGE, 0xa8, bgsm[s->dimm_config[0]]);
1578 pci_write_config32(HOST_BRIDGE, 0xac, tsegmb[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001579}
1580
Damien Zammit003d15c2015-11-20 17:17:51 +11001581static u8 sdram_checkrcompoverride(void)
1582{
1583 u32 xcomp;
1584 u8 aa, bb, a, b, c, d;
1585
Angel Pons39ff7032020-03-09 21:39:44 +01001586 xcomp = MCHBAR32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001587 a = (u8)((xcomp & 0x7f000000) >> 24);
Angel Pons39ff7032020-03-09 21:39:44 +01001588 b = (u8)((xcomp & 0x007f0000) >> 16);
1589 c = (u8)((xcomp & 0x00003f00) >> 8);
1590 d = (u8)((xcomp & 0x0000003f) >> 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001591
1592 if (a > b) {
1593 aa = a - b;
1594 } else {
1595 aa = b - a;
1596 }
1597 if (c > d) {
1598 bb = c - d;
1599 } else {
1600 bb = d - c;
1601 }
Angel Pons39ff7032020-03-09 21:39:44 +01001602 if ((aa > 18) || (bb > 7) || (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
Damien Zammit003d15c2015-11-20 17:17:51 +11001603 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001604 MCHBAR32(RCMEASBUFXOVR) = 0x9718a729;
Damien Zammit003d15c2015-11-20 17:17:51 +11001605 return 1;
1606 }
1607 return 0;
1608}
1609
1610static void sdram_rcompupdate(struct sysinfo *s)
1611{
1612 u8 i, ok;
1613 u32 reg32a, reg32b;
1614
1615 ok = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001616 MCHBAR8_AND(XCOMPDFCTRL, ~(1 << 3));
1617 MCHBAR8_AND(COMPCTRL1, ~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11001618 for (i = 0; i < 3; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001619 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001620 hpet_udelay(1000);
Angel Pons39ff7032020-03-09 21:39:44 +01001621 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1622 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001623 ok |= sdram_checkrcompoverride();
1624 }
1625 if (!ok) {
Angel Pons39ff7032020-03-09 21:39:44 +01001626 reg32a = MCHBAR32(XCOMP);
1627 reg32b = ((reg32a >> 16) & 0x0000ffff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001628 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1629 reg32a |= (1 << 31) | (1 << 15);
Angel Pons39ff7032020-03-09 21:39:44 +01001630 MCHBAR32(RCMEASBUFXOVR) = reg32a;
Damien Zammit003d15c2015-11-20 17:17:51 +11001631 }
Angel Pons39ff7032020-03-09 21:39:44 +01001632 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001633 hpet_udelay(1000);
Angel Pons39ff7032020-03-09 21:39:44 +01001634 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1635 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001636}
1637
1638static void __attribute__((noinline))
1639sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1640{
1641 u32 reg32;
1642
1643 reg32 = jval << 3;
Angel Pons39ff7032020-03-09 21:39:44 +01001644 reg32 |= rank * (1 << 27);
1645 MCHBAR8_AND_OR(C0JEDEC, ~0x3e, jmode);
Damien Zammit003d15c2015-11-20 17:17:51 +11001646 read32((void *)reg32);
1647 barrier();
1648 hpet_udelay(1); // 1us
1649}
1650
1651static void sdram_zqcl(struct sysinfo *s)
1652{
1653 if (s->boot_path == BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01001654 MCHBAR32_OR(C0CKECTRL, 1 << 27);
1655 MCHBAR8_AND_OR(C0JEDEC, ~0x0e, NORMAL_OP_CMD);
1656 MCHBAR8_AND(C0JEDEC, ~0x30);
1657 MCHBAR32_AND_OR(C0REFRCTRL2, ~(3 << 30), 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001658 }
1659}
1660
1661static void sdram_jedecinit(struct sysinfo *s)
1662{
1663 u8 r, i, ch;
1664 u16 reg16, mrs, rttnom;
1665 struct jedeclist {
1666 char debug[15];
1667 u8 cmd;
1668 u16 val;
1669 };
1670
Arthur Heymans6bf13012017-06-10 12:03:27 +02001671 static const struct jedeclist jedec[12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001672 { " NOP ", NOP_CMD, 0 },
1673 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1674 { " EMRS2 ", EMRS2_CMD, 0 },
1675 { " EMRS3 ", EMRS3_CMD, 0 },
1676 { " EMRS1 ", EMRS1_CMD, 0 },
1677 { " DLL RESET ", MRS_CMD, (1 << 8) },
1678 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1679 { " AUTOREFRESH", CBR_CMD, 0 },
1680 { " AUTOREFRESH", CBR_CMD, 0 },
1681 { " INITIALISE ", MRS_CMD, 0 },
1682 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1683 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1684 };
1685
1686 mrs = (s->selected_timings.CAS << 4) |
Angel Pons39ff7032020-03-09 21:39:44 +01001687 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 3;
1688
Damien Zammit003d15c2015-11-20 17:17:51 +11001689 rttnom = (1 << 2);
1690 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1691 rttnom |= (1 << 6);
1692 }
1693
1694 hpet_udelay(200); // 200us
1695 reg16 = 0;
1696 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1697 for (i = 0; i < 12; i++) {
1698 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1699 reg16 = jedec[i].val;
1700 switch (jedec[i].cmd) {
1701 case EMRS1_CMD:
1702 reg16 |= rttnom;
1703 break;
1704 case MRS_CMD:
1705 reg16 |= mrs;
1706 break;
1707 default:
1708 break;
1709 }
1710 sdram_jedec(s, r, jedec[i].cmd, reg16);
1711 PRINTK_DEBUG("done\n");
1712 }
1713 }
1714}
1715
1716static void sdram_misc(struct sysinfo *s)
1717{
1718 u32 reg32;
1719
1720 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001721 reg32 |= (4 << 13);
1722 reg32 |= (6 << 8);
1723 MCHBAR32_AND_OR(C0DYNRDCTRL, ~0x3ff00, reg32);
1724 MCHBAR8_AND(C0DYNRDCTRL, ~(1 << 7));
1725 MCHBAR8_OR(C0REFRCTRL + 3, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001726 if (s->boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01001727 MCHBAR8_AND_OR(C0JEDEC, ~0x0e, NORMAL_OP_CMD);
1728 MCHBAR8_AND(C0JEDEC, ~0x30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001729 } else {
1730 sdram_zqcl(s);
1731 }
1732}
1733
1734static void sdram_checkreset(void)
1735{
1736 u8 pmcon2, pmcon3, reset;
1737
1738 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1739 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1740 pmcon3 &= ~0x2;
1741 if (pmcon2 & 0x80) {
1742 pmcon2 &= ~0x80;
1743 reset = 1;
1744 } else {
1745 pmcon2 |= 0x80;
1746 reset = 0;
1747 }
1748 if (pmcon2 & 0x4) {
1749 pmcon2 |= 0x4;
1750 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1751 pmcon3 |= (1 << 3);
1752 }
1753 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1754 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +02001755 if (reset)
1756 full_reset();
Damien Zammit003d15c2015-11-20 17:17:51 +11001757}
1758
1759static void sdram_dradrb(struct sysinfo *s)
1760{
1761 u8 i, reg8, ch, r;
1762 u32 reg32, ind, c0dra, c0drb, dra;
1763 u16 addr;
1764 i = 0;
Arthur Heymans6bf13012017-06-10 12:03:27 +02001765 static const u8 dratab[2][2][2][4] =
Damien Zammit003d15c2015-11-20 17:17:51 +11001766 {{
1767 {
1768 {0xff, 0xff, 0xff, 0xff},
1769 {0xff, 0x00, 0x02, 0xff}
1770 },
1771 {
1772 {0xff, 0x01, 0xff, 0xff},
1773 {0xff, 0x03, 0xff, 0x06}
1774 }
1775 },
1776 {
1777 {
1778 {0xff, 0xff, 0xff, 0xff},
1779 {0xff, 0x04, 0x06, 0x08}
1780 },
1781 {
1782 {0xff, 0xff, 0xff, 0xff},
1783 {0x05, 0x07, 0x09, 0xff}
1784 }
1785 }};
1786
Arthur Heymans6bf13012017-06-10 12:03:27 +02001787 static const u8 dradrb[10][6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001788 //Row Col Bank Width DRB
1789 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1790 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1791 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1792 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1793 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1794 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1795 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1796 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1797 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1798 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1799 };
1800
1801 reg32 = 0;
1802 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1803 i = r / 2;
1804 PRINTK_DEBUG("RANK %d PRESENT\n", r);
Angel Pons39ff7032020-03-09 21:39:44 +01001805 dra = dratab
1806 [s->dimms[i].banks]
Damien Zammit003d15c2015-11-20 17:17:51 +11001807 [s->dimms[i].width]
1808 [s->dimms[i].cols - 9]
1809 [s->dimms[i].rows - 12];
1810
1811 if (s->dimms[i].banks == 1) {
1812 dra |= (1 << 7);
1813 }
Angel Pons39ff7032020-03-09 21:39:44 +01001814 reg32 |= (dra << (r * 8));
Damien Zammit003d15c2015-11-20 17:17:51 +11001815 }
Angel Pons39ff7032020-03-09 21:39:44 +01001816 MCHBAR32(C0DRA01) = reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +11001817 c0dra = reg32;
1818 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1819
1820 reg32 = 0;
1821 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1822 reg32 |= (1 << r);
1823 }
1824 reg8 = (u8)(reg32 << 4) & 0xf0;
Angel Pons39ff7032020-03-09 21:39:44 +01001825 MCHBAR8_AND_OR(C0CKECTRL + 2, ~0xf0, reg8);
1826
1827 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) || ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1828 MCHBAR8_OR(C0CKECTRL, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001829 }
1830
Angel Pons39ff7032020-03-09 21:39:44 +01001831 addr = C0DRB0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001832 c0drb = 0;
1833 FOR_EACH_RANK(ch, r) {
1834 if (rank_is_populated(s->dimms, ch, r)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001835 ind = (c0dra >> (8 * r)) & 0x7f;
Damien Zammit003d15c2015-11-20 17:17:51 +11001836 c0drb = (u16)(c0drb + dradrb[ind][5]);
1837 s->channel_capacity[0] += dradrb[ind][5] << 6;
1838 }
1839 MCHBAR16(addr) = c0drb;
1840 addr += 2;
1841 }
1842 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1843}
1844
1845static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1846{
Damien Zammit003d15c2015-11-20 17:17:51 +11001847 u8 dqsmatches = 1;
1848 while (count--) {
Angel Pons39ff7032020-03-09 21:39:44 +01001849 MCHBAR8_AND(C0RSTCTL, ~2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001850 hpet_udelay(1);
Angel Pons39ff7032020-03-09 21:39:44 +01001851 MCHBAR8_OR(C0RSTCTL, 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001852 hpet_udelay(1);
1853 barrier();
Elyes HAOUASaf159d42019-05-22 20:19:22 +02001854 read32((void *)strobeaddr);
Damien Zammit003d15c2015-11-20 17:17:51 +11001855 barrier();
1856 hpet_udelay(1);
1857
1858 if (((MCHBAR8(dqshighaddr) & 0x40) >> 6) != highlow) {
1859 dqsmatches = 0;
1860 }
1861 }
1862
1863 return dqsmatches;
1864}
1865
Angel Pons39ff7032020-03-09 21:39:44 +01001866static void rcvenclock(u8 *coarse, u8 *medium, u8 lane)
Damien Zammit003d15c2015-11-20 17:17:51 +11001867{
1868 if (*medium < 3) {
1869 (*medium)++;
Angel Pons39ff7032020-03-09 21:39:44 +01001870 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001871 } else {
1872 *medium = 0;
1873 (*coarse)++;
Angel Pons39ff7032020-03-09 21:39:44 +01001874 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, *coarse << 16);
1875 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)(~3 << (lane * 2)), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001876 }
1877}
1878
1879static void sdram_rcven(struct sysinfo *s)
1880{
Angel Pons39ff7032020-03-09 21:39:44 +01001881 u8 coarse, savecoarse;
1882 u8 medium, savemedium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001883 u8 pi, savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01001884 u8 lane;
1885 u8 lanecoarse[8] = {0};
1886 u8 minlanecoarse = 0xff;
1887 u8 offset;
1888 u8 maxlane = 8;
Arthur Heymans015339f2018-08-20 11:28:58 +02001889 /* Since dra/drb is already set up we know that at address 0x00000000
1890 we will always find the first available rank */
1891 u32 strobeaddr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001892 u32 dqshighaddr;
1893
Angel Pons39ff7032020-03-09 21:39:44 +01001894 MCHBAR8_AND(C0RSTCTL, ~0x0c);
1895 MCHBAR8_AND(CMNDQFIFORST, ~0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11001896
1897 PRINTK_DEBUG("rcven 0\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001898 for (lane = 0; lane < maxlane; lane++) {
1899 PRINTK_DEBUG("rcven lane %d\n", lane);
1900// trylaneagain:
1901 dqshighaddr = C0MISCCTLy(lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001902
Angel Pons39ff7032020-03-09 21:39:44 +01001903 coarse = s->selected_timings.CAS + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11001904 pi = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001905 medium = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001906
Angel Pons39ff7032020-03-09 21:39:44 +01001907 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1908 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001909
Angel Pons39ff7032020-03-09 21:39:44 +01001910 MCHBAR8_AND(C0RXRCVyDLL(lane), ~0x3f);
1911
1912 savecoarse = coarse;
1913 savemedium = medium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001914 savepi = pi;
1915
1916 PRINTK_DEBUG("rcven 0.1\n");
1917
Angel Pons39ff7032020-03-09 21:39:44 +01001918 // XXX comment out
1919 // MCHBAR16_AND_OR(C0RCVMISCCTL1, (u16)~3 << (lane * 2), 1 << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001920
1921 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001922 // printk(BIOS_DEBUG, "coarse=%d medium=%d\n", coarse, medium);
1923 rcvenclock(&coarse, &medium, lane);
1924 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001925 PRINTK_DEBUG("Error: coarse > 0xf\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001926 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001927 break;
1928 }
1929 }
1930 PRINTK_DEBUG("rcven 0.2\n");
1931
Angel Pons39ff7032020-03-09 21:39:44 +01001932 savecoarse = coarse;
1933 savemedium = medium;
1934 rcvenclock(&coarse, &medium, lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001935
1936 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001937 savecoarse = coarse;
1938 savemedium = medium;
1939 rcvenclock(&coarse, &medium, lane);
1940 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001941 PRINTK_DEBUG("Error: coarse > 0xf\n");
1942 //goto trylaneagain;
1943 break;
1944 }
1945 }
1946
1947 PRINTK_DEBUG("rcven 0.3\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001948 coarse = savecoarse;
1949 medium = savemedium;
1950 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1951 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(0x3 << lane * 2), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001952
1953 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1954 savepi = pi;
1955 pi++;
1956 if (pi > s->maxpi) {
Angel Pons39ff7032020-03-09 21:39:44 +01001957 // if (s->nodll) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001958 pi = savepi = s->maxpi;
1959 break;
Angel Pons39ff7032020-03-09 21:39:44 +01001960 // }
Damien Zammit003d15c2015-11-20 17:17:51 +11001961 }
Angel Pons39ff7032020-03-09 21:39:44 +01001962 MCHBAR8_AND_OR(C0RXRCVyDLL(lane), ~0x3f, pi << s->pioffset);
Damien Zammit003d15c2015-11-20 17:17:51 +11001963 }
1964 PRINTK_DEBUG("rcven 0.4\n");
1965
1966 pi = savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01001967 MCHBAR8_AND_OR(C0RXRCVyDLL(lane), ~0x3f, pi << s->pioffset);
1968 rcvenclock(&coarse, &medium, lane);
1969
Damien Zammit003d15c2015-11-20 17:17:51 +11001970 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1971 PRINTK_DEBUG("Error: DQS not high\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001972 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001973 }
1974 PRINTK_DEBUG("rcven 0.5\n");
1975 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001976 coarse--;
1977 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1978 if (coarse == 0) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +02001979 PRINTK_DEBUG("Error: DQS did not hit 0\n");
Damien Zammit003d15c2015-11-20 17:17:51 +11001980 break;
1981 }
1982 }
1983
1984 PRINTK_DEBUG("rcven 0.6\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001985 rcvenclock(&coarse, &medium, lane);
1986 s->pi[lane] = pi;
1987 lanecoarse[lane] = coarse;
Damien Zammit003d15c2015-11-20 17:17:51 +11001988 }
1989
1990 PRINTK_DEBUG("rcven 1\n");
1991
Angel Pons39ff7032020-03-09 21:39:44 +01001992 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11001993 do {
Angel Pons39ff7032020-03-09 21:39:44 +01001994 lane--;
1995 if (minlanecoarse > lanecoarse[lane]) {
1996 minlanecoarse = lanecoarse[lane];
Damien Zammit003d15c2015-11-20 17:17:51 +11001997 }
Angel Pons39ff7032020-03-09 21:39:44 +01001998 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001999
Angel Pons39ff7032020-03-09 21:39:44 +01002000 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11002001 do {
Angel Pons39ff7032020-03-09 21:39:44 +01002002 lane--;
2003 offset = lanecoarse[lane] - minlanecoarse;
2004 MCHBAR16_AND_OR(C0COARSEDLY0, (u16)(~(3 << (lane * 2))), offset << (lane * 2));
2005 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002006
Angel Pons39ff7032020-03-09 21:39:44 +01002007 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, minlanecoarse << 16);
Damien Zammit003d15c2015-11-20 17:17:51 +11002008
Angel Pons39ff7032020-03-09 21:39:44 +01002009 s->coarsectrl = minlanecoarse;
2010 s->coarsedelay = MCHBAR16(C0COARSEDLY0);
2011 s->mediumphase = MCHBAR16(C0RCVMISCCTL2);
2012 s->readptrdelay = MCHBAR16(C0RCVMISCCTL1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002013
2014 PRINTK_DEBUG("rcven 2\n");
Angel Pons39ff7032020-03-09 21:39:44 +01002015 MCHBAR8_AND(C0RSTCTL, ~0x0e);
2016 MCHBAR8_OR(C0RSTCTL, 0x02);
2017 MCHBAR8_OR(C0RSTCTL, 0x04);
2018 MCHBAR8_OR(C0RSTCTL, 0x08);
Damien Zammit003d15c2015-11-20 17:17:51 +11002019
Angel Pons39ff7032020-03-09 21:39:44 +01002020 MCHBAR8_OR(CMNDQFIFORST, 0x80);
2021 MCHBAR8_AND(CMNDQFIFORST, ~0x80);
2022 MCHBAR8_OR(CMNDQFIFORST, 0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11002023 PRINTK_DEBUG("rcven 3\n");
2024}
2025
Angel Pons39ff7032020-03-09 21:39:44 +01002026/* NOTE: Unless otherwise specified, the values are expressed in MiB */
Damien Zammit003d15c2015-11-20 17:17:51 +11002027static void sdram_mmap_regs(struct sysinfo *s)
2028{
2029 bool reclaim;
Angel Pons39ff7032020-03-09 21:39:44 +01002030 u32 mmiosize, tom, tolud, touud, reclaimbase, reclaimlimit;
2031 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase, tsegsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002032 u16 ggc;
Angel Pons39ff7032020-03-09 21:39:44 +01002033 u16 ggc_to_uma[10] = {0, 1, 4, 8, 16, 32, 48, 64, 128, 256};
2034 u8 ggc_to_gtt[4] = {0, 1, 0, 0};
Damien Zammit003d15c2015-11-20 17:17:51 +11002035
Angel Pons39ff7032020-03-09 21:39:44 +01002036 reclaimbase = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002037 reclaimlimit = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002038
2039 ggc = pci_read_config16(HOST_BRIDGE, GGC);
Damien Zammit51fdb922016-01-18 18:34:52 +11002040 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
Angel Pons39ff7032020-03-09 21:39:44 +01002041
2042 gfxsize = ggc_to_uma[(ggc & 0x00f0) >> 4];
2043
2044 gttsize = ggc_to_gtt[(ggc & 0x0300) >> 8];
2045
Damien Zammit003d15c2015-11-20 17:17:51 +11002046 tom = s->channel_capacity[0];
2047
Angel Pons39ff7032020-03-09 21:39:44 +01002048 /* With GTT always being 1M, TSEG 1M is the only setting that can
Arthur Heymansda44e342019-01-12 01:38:02 +01002049 be covered by SMRR which has alignment requirements. */
Angel Pons39ff7032020-03-09 21:39:44 +01002050 tsegsize = 1;
2051 mmiosize = 1024;
Damien Zammit003d15c2015-11-20 17:17:51 +11002052
2053 reclaim = false;
Angel Pons39ff7032020-03-09 21:39:44 +01002054 tolud = MIN(4096 - mmiosize, tom);
2055 if ((tom - tolud) > 64) {
Arthur Heymansaaebb412017-08-27 18:46:12 +02002056 reclaim = true;
Damien Zammit003d15c2015-11-20 17:17:51 +11002057 }
2058 if (reclaim) {
2059 tolud = tolud & ~0x3f;
Angel Pons39ff7032020-03-09 21:39:44 +01002060 tom = tom & ~0x3f;
2061 reclaimbase = MAX(4096, tom);
2062 reclaimlimit = reclaimbase + (MIN(4096, tom) - tolud) - 0x40;
Damien Zammit003d15c2015-11-20 17:17:51 +11002063 }
2064 touud = tom;
2065 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002066 touud = reclaimlimit + 64;
Damien Zammit003d15c2015-11-20 17:17:51 +11002067 }
2068
Angel Pons39ff7032020-03-09 21:39:44 +01002069 gfxbase = tolud - gfxsize;
2070 gttbase = gfxbase - gttsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002071 tsegbase = gttbase - tsegsize;
2072
2073 /* Program the regs */
Angel Pons39ff7032020-03-09 21:39:44 +01002074 pci_write_config16(HOST_BRIDGE, TOLUD, (u16)(tolud << 4));
2075 pci_write_config16(HOST_BRIDGE, TOM, (u16)(tom >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002076 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002077 pci_write_config16(HOST_BRIDGE, 0x98, (u16)(reclaimbase >> 6));
2078 pci_write_config16(HOST_BRIDGE, 0x9a, (u16)(reclaimlimit >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002079 }
Angel Pons39ff7032020-03-09 21:39:44 +01002080 pci_write_config16(HOST_BRIDGE, TOUUD, (u16)(touud));
2081 pci_write_config32(HOST_BRIDGE, GBSM, gfxbase << 20);
2082 pci_write_config32(HOST_BRIDGE, BGSM, gttbase << 20);
2083 pci_write_config32(HOST_BRIDGE, TSEG, tsegbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002084
Angel Pons39ff7032020-03-09 21:39:44 +01002085 u8 reg8 = pci_read_config8(HOST_BRIDGE, ESMRAMC);
2086 reg8 &= ~0x07;
Arthur Heymansda44e342019-01-12 01:38:02 +01002087 reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
Angel Pons39ff7032020-03-09 21:39:44 +01002088 pci_write_config8(HOST_BRIDGE, ESMRAMC, reg8);
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002089
Damien Zammit51fdb922016-01-18 18:34:52 +11002090 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002091 pci_read_config32(HOST_BRIDGE, GBSM), gfxbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002092 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002093 pci_read_config32(HOST_BRIDGE, BGSM), gttbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002094 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002095 pci_read_config32(HOST_BRIDGE, TSEG), tsegbase << 20);
Damien Zammit003d15c2015-11-20 17:17:51 +11002096}
2097
2098static void sdram_enhancedmode(struct sysinfo *s)
2099{
Angel Pons39ff7032020-03-09 21:39:44 +01002100 u8 reg8, ch, r, fsb_freq, ddr_freq;
Damien Zammit003d15c2015-11-20 17:17:51 +11002101 u32 mask32, reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002102 MCHBAR8_OR(C0ADDCSCTRL, 1);
2103 MCHBAR8_OR(C0REFRCTRL + 3, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002104 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
Angel Pons39ff7032020-03-09 21:39:44 +01002105 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2106 MCHBAR32_AND_OR(WRWMCONFIG, ~mask32, reg32);
2107 MCHBAR8(C0DITCTRL + 1) = 2;
2108 MCHBAR16(C0DITCTRL + 2) = 0x0804;
2109 MCHBAR16(C0DITCTRL + 4) = 0x2010;
2110 MCHBAR8(C0DITCTRL + 6) = 0x40;
2111 MCHBAR16(C0DITCTRL + 8) = 0x091c;
2112 MCHBAR8(C0DITCTRL + 10) = 0xf2;
2113 MCHBAR8_OR(C0BYPCTRL, 1);
2114 MCHBAR8_OR(C0CWBCTRL, 1);
2115 MCHBAR16_OR(C0ARBSPL, 0x0100);
Damien Zammit003d15c2015-11-20 17:17:51 +11002116
Angel Pons26766fd2020-06-08 12:38:19 +02002117 pci_or_config8(HOST_BRIDGE, 0xf0, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01002118 MCHBAR32(SBCTL) = 0x00000002;
2119 MCHBAR32(SBCTL2) = 0x20310002;
2120 MCHBAR32(SLIMCFGTMG) = 0x02020302;
2121 MCHBAR32(HIT0) = 0x001f1806;
2122 MCHBAR32(HIT1) = 0x01102800;
2123 MCHBAR32(HIT2) = 0x07000000;
2124 MCHBAR32(HIT3) = 0x01014010;
2125 MCHBAR32(HIT4) = 0x0f038000;
Angel Pons26766fd2020-06-08 12:38:19 +02002126 pci_and_config8(HOST_BRIDGE, 0xf0, ~1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002127
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002128 u32 nranks, curranksize, maxranksize, dra;
2129 u8 rankmismatch;
Angel Pons39ff7032020-03-09 21:39:44 +01002130 static const u8 drbtab[10] = {0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8, 0x20, 0x10};
Damien Zammit003d15c2015-11-20 17:17:51 +11002131
2132 nranks = 0;
2133 curranksize = 0;
2134 maxranksize = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002135 rankmismatch = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002136
Damien Zammit003d15c2015-11-20 17:17:51 +11002137 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2138 nranks++;
Angel Pons39ff7032020-03-09 21:39:44 +01002139 dra = (u8) ((MCHBAR32(C0DRA01) >> (8 * r)) & 0x7f);
Damien Zammit003d15c2015-11-20 17:17:51 +11002140 curranksize = drbtab[dra];
2141 if (maxranksize == 0) {
2142 maxranksize = curranksize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002143 }
2144 if (curranksize != maxranksize) {
2145 rankmismatch = 1;
2146 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002147 }
2148
2149 reg8 = 0;
2150 switch (nranks) {
2151 case 4:
2152 if (rankmismatch) {
2153 reg8 = 0x64;
2154 } else {
2155 reg8 = 0xa4;
2156 }
2157 break;
2158 case 1:
2159 case 3:
2160 reg8 = 0x64;
2161 break;
2162 case 2:
2163 if (rankmismatch) {
2164 reg8 = 0x64;
2165 } else {
2166 reg8 = 0x24;
2167 }
2168 break;
2169 default:
2170 die("Invalid number of ranks found, halt\n");
2171 break;
2172 }
Angel Pons39ff7032020-03-09 21:39:44 +01002173 MCHBAR8_AND_OR(CHDECMISC, ~0xfc, reg8 & 0xfc);
2174 MCHBAR32_AND(NOACFGBUSCTL, ~0x80000000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002175
Angel Pons39ff7032020-03-09 21:39:44 +01002176 MCHBAR32(HTBONUS0) = 0x0000000f;
2177 MCHBAR8_OR(C0COREBONUS + 4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002178
Angel Pons39ff7032020-03-09 21:39:44 +01002179 MCHBAR32_AND(HIT3, ~0x0e000000);
2180 MCHBAR32_AND_OR(HIT4, ~0x000c0000, 0x00040000);
2181
Damien Zammit003d15c2015-11-20 17:17:51 +11002182 u32 clkcx[2][2][3] = {
Angel Pons39ff7032020-03-09 21:39:44 +01002183 {
2184 {0x00000000, 0x0c080302, 0x08010204}, /* FSB = 667, DDR = 667 */
2185 {0x02040000, 0x08100102, 0x00000000}, /* FSB = 667, DDR = 800 */
2186 },
2187 {
2188 {0x18000000, 0x3021060c, 0x20010208}, /* FSB = 800, DDR = 667 */
2189 {0x00000000, 0x0c090306, 0x00000000}, /* FSB = 800, DDR = 800 */
2190 }
2191 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002192
Angel Pons39ff7032020-03-09 21:39:44 +01002193 fsb_freq = s->selected_timings.fsb_clock;
2194 ddr_freq = s->selected_timings.mem_clock;
2195
2196 MCHBAR32(CLKXSSH2X2MD) = clkcx[fsb_freq][ddr_freq][0];
2197 MCHBAR32(CLKXSSH2X2MD + 4) = clkcx[fsb_freq][ddr_freq][1];
2198 MCHBAR32(CLKXSSH2MCBYP + 4) = clkcx[fsb_freq][ddr_freq][2];
2199
2200 MCHBAR8_AND(HIT4, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11002201}
2202
2203static void sdram_periodic_rcomp(void)
2204{
Angel Pons39ff7032020-03-09 21:39:44 +01002205 MCHBAR8_AND(COMPCTRL1, ~0x02);
2206 while ((MCHBAR32(COMPCTRL1) & 0x80000000) > 0) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002207 ;
2208 }
Angel Pons39ff7032020-03-09 21:39:44 +01002209 MCHBAR16_AND(CSHRMISCCTL, ~0x3000);
2210 MCHBAR8_OR(CMNDQFIFORST, 0x80);
2211 MCHBAR16_AND_OR(XCOMPDFCTRL, ~0x0f, 0x09);
Damien Zammit003d15c2015-11-20 17:17:51 +11002212
Angel Pons39ff7032020-03-09 21:39:44 +01002213 MCHBAR8_OR(COMPCTRL1, 0x82);
Damien Zammit003d15c2015-11-20 17:17:51 +11002214}
2215
2216static void sdram_new_trd(struct sysinfo *s)
2217{
2218 u8 pidelay, i, j, k, cc, trd_perphase[5];
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002219 u8 bypass, freqgb, trd, reg8, txfifo;
Damien Zammit003d15c2015-11-20 17:17:51 +11002220 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2221 u16 tmclk, thclk, buffertocore, postcalib;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002222 static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2223 static const u16 trd_adjust[2][2][5] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11002224 {
2225 {3000, 3000, 0,0,0},
2226 {1000,2000,3000,1500,2500}
2227 },
2228 {
2229 {2000,1000,3000,0,0},
2230 {2500, 2500, 0,0,0}
2231 }};
2232
2233 freqgb = 110;
2234 buffertocore = 5000;
Damien Zammit003d15c2015-11-20 17:17:51 +11002235 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2236 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2237 tmclk = tmclk * 100 / freqgb;
2238 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2239 switch (s->selected_timings.mem_clock) {
2240 case MEM_CLOCK_667MHz:
2241 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2242 cc = 2;
2243 } else {
2244 cc = 3;
2245 }
2246 break;
2247 default:
2248 case MEM_CLOCK_800MHz:
2249 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2250 cc = 5;
2251 } else {
2252 cc = 2;
2253 }
2254 break;
2255 }
2256 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2257 maxrcvendelay = 0;
2258 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2259
2260 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01002261 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 3) * (u32)(tmclk));
2262 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 3) * (u32)(tmclk) / 2);
2263 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 3) * (u32)(tmclk) / 4);
2264 rcvendelay += (u32)(pidelay * s->pi[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002265 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2266 }
2267
Angel Pons39ff7032020-03-09 21:39:44 +01002268 if ((MCHBAR8(HMBYPCP + 3) == 0xff) && (MCHBAR8(HMCCMC) & 0x80)) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002269 bypass = 1;
2270 } else {
2271 bypass = 0;
2272 }
2273
2274 txfifo = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002275 reg8 = (MCHBAR8(CSHRFIFOCTL) & 0x0e) >> 1;
2276 txfifo = txfifo_lut[reg8] & 0x07;
Damien Zammit003d15c2015-11-20 17:17:51 +11002277
2278 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2279 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2280 if (s->async) {
2281 datadelay += tmclk / 2;
2282 }
2283
2284 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2285 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2286
2287 if (j == 0 && k == 0) {
2288 datadelay -= 3084;
2289 }
2290
2291 trd = 0;
2292 for (i = 0; i < cc; i++) {
2293 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2294 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2295 trd_perphase[i] += 1;
2296 if (trd_perphase[i] > trd) {
2297 trd = trd_perphase[i];
2298 }
2299 }
2300
Angel Pons39ff7032020-03-09 21:39:44 +01002301 MCHBAR16_AND_OR(C0STATRDCTRL, ~0x1f00, trd << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11002302}
2303
2304static void sdram_powersettings(struct sysinfo *s)
2305{
2306 u8 j;
2307 u32 reg32;
2308
2309 /* Thermal sensor */
Angel Pons39ff7032020-03-09 21:39:44 +01002310 MCHBAR8(TSC1) = 0x9b;
2311 MCHBAR32_AND_OR(TSTTP, ~0x00ffffff, 0x1d00);
2312 MCHBAR8(THERM1) = 0x08;
2313 MCHBAR8(TSC3) = 0x00;
2314 MCHBAR8_AND_OR(TSC2, ~0x0f, 0x04);
2315 MCHBAR8_AND_OR(THERM1, ~1, 1);
2316 MCHBAR8_AND_OR(TCO, ~0x80, 0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11002317
2318 /* Clock gating */
Angel Pons39ff7032020-03-09 21:39:44 +01002319 MCHBAR32_AND(PMMISC, ~0x00040001);
2320 MCHBAR8_AND(SBCTL3 + 3, ~0x80);
2321 MCHBAR8_AND(CISDCTRL + 3, ~0x80);
2322 MCHBAR16_AND(CICGDIS, ~0x1fff);
2323 MCHBAR32_AND(SBCLKGATECTRL, ~0x0001ffff);
2324 MCHBAR16_AND(HICLKGTCTL, ~0x03ff & 0x06);
2325 MCHBAR32_AND_OR(HTCLKGTCTL, ~0xffffffff, 0x20);
2326 MCHBAR8_AND(TSMISC, ~1);
2327 MCHBAR8(C0WRDPYN) = s->selected_timings.CAS - 1 + 0x15;
2328 MCHBAR16_AND_OR(CLOCKGATINGI, ~0x07fc, 0x0040);
2329 MCHBAR16_AND_OR(CLOCKGATINGII, ~0x0fff, 0x0d00);
2330 MCHBAR16_AND(CLOCKGATINGIII, ~0x0d80);
2331 MCHBAR16(GTDPCGC + 2) = 0xffff;
Damien Zammit003d15c2015-11-20 17:17:51 +11002332
2333 /* Sequencing */
Angel Pons39ff7032020-03-09 21:39:44 +01002334 MCHBAR32(HPWRCTL1) = (MCHBAR32(HPWRCTL1) & ~0x1fffffff) | 0x1f643fff;
2335 MCHBAR32(HPWRCTL2) = (MCHBAR32(HPWRCTL2) & ~0xffffff7f) | 0x02010000;
2336 MCHBAR16(HPWRCTL3) = (MCHBAR16(HPWRCTL3) & ~0x7000) | (3 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11002337
2338 /* Power */
Angel Pons39ff7032020-03-09 21:39:44 +01002339 MCHBAR32(GFXC3C4) = (MCHBAR32(GFXC3C4) & ~0xffff0003) | 0x10100000;
2340 MCHBAR32(PMDSLFRC) = (MCHBAR32(PMDSLFRC) & ~0x0001bff7) | 0x00000078;
2341
2342 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz)
2343 MCHBAR16_AND_OR(PMMSPMRES, ~0x03ff, 0x00c8);
2344 else
2345 MCHBAR16_AND_OR(PMMSPMRES, ~0x03ff, 0x0100);
2346
Damien Zammit003d15c2015-11-20 17:17:51 +11002347 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2348
Angel Pons39ff7032020-03-09 21:39:44 +01002349 MCHBAR32_AND_OR(PMCLKRC, ~0x01fff37f, 0x10810700);
2350 MCHBAR8_AND_OR(PMPXPRC, ~0x07, 1);
2351 MCHBAR8_AND(PMBAK, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11002352
Angel Pons39ff7032020-03-09 21:39:44 +01002353 static const u16 ddr2lut[2][4][2] = {
2354 {
2355 {0x0000, 0x0000},
2356 {0x019A, 0x0039},
2357 {0x0099, 0x1049},
2358 {0x0000, 0x0000},
2359 },
2360 {
2361 {0x0000, 0x0000},
2362 {0x019A, 0x0039},
2363 {0x0099, 0x1049},
2364 {0x0099, 0x2159},
2365 },
2366 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002367
Angel Pons39ff7032020-03-09 21:39:44 +01002368 MCHBAR16(C0C2REG) = 0x7a89;
2369 MCHBAR8(SHC2REGII) = 0xaa;
2370 MCHBAR16(SHC2REGII + 1) = ddr2lut[j][s->selected_timings.CAS - 3][1];
2371 MCHBAR16_AND_OR(SHC2REGI, ~0x7fff, ddr2lut[j][s->selected_timings.CAS - 3][0]);
2372 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0xf000, 0xf000);
2373 MCHBAR8(CSHWRIOBONUSX) = (MCHBAR8(CSHWRIOBONUSX) & ~0x77) | (4 << 4 | 4);
Damien Zammit003d15c2015-11-20 17:17:51 +11002374
Angel Pons39ff7032020-03-09 21:39:44 +01002375 reg32 = s->nodll ? 0x30000000 : 0;
2376
2377 /* FIXME: Compacting this results in changes to the binary */
2378 MCHBAR32(C0COREBONUS) = (MCHBAR32(C0COREBONUS) & ~0x0f000000) | 0x20000000 | reg32;
2379
2380 MCHBAR32_AND_OR(CLOCKGATINGI, ~0x00f00000, 0x00f00000);
2381 MCHBAR32_AND_OR(CLOCKGATINGII - 1, ~0x001ff000, 0xbf << 20);
2382 MCHBAR16_AND_OR(SHC3C4REG2, ~0x1f7f, (0x0b << 8) | (7 << 4) | 0x0b);
2383 MCHBAR16(SHC3C4REG3) = 0x3264;
2384 MCHBAR16_AND_OR(SHC3C4REG4, ~0x3f3f, (0x14 << 8) | 0x0a);
2385
2386 MCHBAR32_OR(C1COREBONUS, 0x80002000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002387}
2388
2389static void sdram_programddr(void)
2390{
Angel Pons39ff7032020-03-09 21:39:44 +01002391 MCHBAR16_AND_OR(CLOCKGATINGII, ~0x03ff, 0x0100);
2392 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0x003f, 0x0010);
2393 MCHBAR16_AND_OR(CLOCKGATINGI, ~0x7000, 0x2000);
2394
2395 MCHBAR8_AND(CSHRPDCTL, ~0x0e);
2396 MCHBAR8_AND(CSHRWRIOMLNS, ~0x0c);
2397 MCHBAR8_AND(C0MISCCTLy(0), ~0x0e);
2398 MCHBAR8_AND(C0MISCCTLy(1), ~0x0e);
2399 MCHBAR8_AND(C0MISCCTLy(2), ~0x0e);
2400 MCHBAR8_AND(C0MISCCTLy(3), ~0x0e);
2401 MCHBAR8_AND(C0MISCCTLy(4), ~0x0e);
2402 MCHBAR8_AND(C0MISCCTLy(5), ~0x0e);
2403 MCHBAR8_AND(C0MISCCTLy(6), ~0x0e);
2404 MCHBAR8_AND(C0MISCCTLy(7), ~0x0e);
2405 MCHBAR8_AND(CSHRWRIOMLNS, ~0x02);
2406
2407 MCHBAR16_AND(CSHRMISCCTL, ~0x0400);
2408 MCHBAR16_AND(CLOCKGATINGIII, ~0x0dc0);
2409 MCHBAR8_AND(C0WRDPYN, ~0x80);
2410 MCHBAR32_AND(C0COREBONUS, ~(1 << 22));
2411 MCHBAR16_AND(CLOCKGATINGI, ~0x80fc);
2412 MCHBAR16_AND(CLOCKGATINGII, ~0x0c00);
2413
2414 MCHBAR8_AND(CSHRPDCTL, ~0x0d);
2415 MCHBAR8_AND(C0MISCCTLy(0), ~1);
2416 MCHBAR8_AND(C0MISCCTLy(1), ~1);
2417 MCHBAR8_AND(C0MISCCTLy(2), ~1);
2418 MCHBAR8_AND(C0MISCCTLy(3), ~1);
2419 MCHBAR8_AND(C0MISCCTLy(4), ~1);
2420 MCHBAR8_AND(C0MISCCTLy(5), ~1);
2421 MCHBAR8_AND(C0MISCCTLy(6), ~1);
2422 MCHBAR8_AND(C0MISCCTLy(7), ~1);
2423
2424 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x00700000, 3 << 20);
2425 MCHBAR32_AND(C0COREBONUS, ~0x00100000);
2426 MCHBAR8_OR(C0DYNSLVDLLEN, 0x1e);
2427 MCHBAR8_OR(C0DYNSLVDLLEN2, 0x03);
2428 MCHBAR32_AND_OR(SHCYCTRKCKEL, ~0x0c000000, 0x04000000);
2429 MCHBAR16_OR(C0STATRDCTRL, 0x6000);
2430 MCHBAR32_OR(C0CKECTRL, 0x00010000);
2431 MCHBAR8_OR(C0COREBONUS, 0x10);
2432 MCHBAR32_OR(CLOCKGATINGI - 1, 0xf << 24);
2433 MCHBAR8_OR(CSHWRIOBONUS, 0x07);
2434 MCHBAR8_OR(C0DYNSLVDLLEN, 0xc0);
2435 MCHBAR8_OR(SHC2REGIII, 7);
2436 MCHBAR16_AND_OR(SHC2MINTM, ~0xffff, 0x0080);
2437 MCHBAR8_AND_OR(SHC2IDLETM, ~0xff, 0x10);
2438 MCHBAR16_OR(C0COREBONUS, 0x01e0);
2439 MCHBAR8_OR(CSHWRIOBONUS, 0x18);
2440 MCHBAR8_OR(CSHRMSTDYNDLLENB, 0x0d);
2441 MCHBAR16_OR(SHC3C4REG1, 0x0a3f);
2442 MCHBAR8_OR(C0STATRDCTRL, 3);
2443 MCHBAR8_AND_OR(C0REFRCTRL2, ~0xff, 0x4a);
2444 MCHBAR8_AND(C0COREBONUS + 4, ~0x60);
2445 MCHBAR16_OR(C0DYNSLVDLLEN, 0x0321);
Damien Zammit003d15c2015-11-20 17:17:51 +11002446}
2447
2448static void sdram_programdqdqs(struct sysinfo *s)
2449{
2450 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2451 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2452 u8 repeat, halfclk, feature, reg8, push;
2453 u16 cwb, pimdclk;
2454 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002455 static const u8 txfifotab[8] = {0, 7, 6, 5, 2, 1, 4, 3};
Damien Zammit003d15c2015-11-20 17:17:51 +11002456
2457 tpi = 3000;
2458 dqdqs_out = 4382;
2459 dqdqs_outdelay = 5083;
2460 dqdqs_delay = 4692;
2461 coretomcp = 0;
2462 txdelay = 0;
2463 halfclk = 0;
2464 tmaxunmask = 0;
2465 tmaxpi = 0;
2466 repeat = 2;
2467 feature = 0;
2468 cwb = 0;
2469 pimdclk = 0;
2470 reg32 = 0;
2471 push = 0;
2472 reg8 = 0;
2473
2474 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2475 refclk = 3000 - mdclk;
2476
Angel Pons39ff7032020-03-09 21:39:44 +01002477 coretomcp = ((MCHBAR8(C0ADDCSCTRL) >> 2) & 0x3) + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002478 coretomcp *= mdclk;
2479
Angel Pons39ff7032020-03-09 21:39:44 +01002480 reg8 = (MCHBAR8(CSHRFIFOCTL) & 0x0e) >> 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002481
2482 while (repeat) {
2483 txdelay = mdclk * (
Angel Pons39ff7032020-03-09 21:39:44 +01002484 ((MCHBAR16(C0GNT2LNCH1) >> 8) & 0x7) +
2485 (MCHBAR8(C0WRDATACTRL) & 0xf) +
2486 (MCHBAR8(C0WRDATACTRL + 1) & 0x1)
Damien Zammit003d15c2015-11-20 17:17:51 +11002487 ) +
Angel Pons39ff7032020-03-09 21:39:44 +01002488 txfifotab[reg8]*(mdclk / 2) +
Damien Zammit003d15c2015-11-20 17:17:51 +11002489 coretomcp +
2490 refclk +
2491 cwb;
Angel Pons39ff7032020-03-09 21:39:44 +01002492 halfclk = (MCHBAR8(C0MISCCTL) >> 1) & 0x1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002493 if (halfclk) {
2494 txdelay -= mdclk / 2;
2495 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2496 } else {
2497 reg32 = dqdqs_outdelay + coretomcp;
2498 }
2499
2500 tmaxunmask = txdelay - mdclk - dqdqs_out;
2501 tmaxpi = tmaxunmask - tpi;
2502
2503 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2504 if (repeat == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01002505 MCHBAR32_AND(C0COREBONUS, ~(1 << 23));
Damien Zammit003d15c2015-11-20 17:17:51 +11002506 }
2507 feature = 1;
2508 repeat = 0;
2509 } else {
2510 repeat--;
Angel Pons39ff7032020-03-09 21:39:44 +01002511 MCHBAR32_OR(C0COREBONUS, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +11002512 cwb = 2 * mdclk;
2513 }
2514 }
2515
2516 if (!feature) {
Angel Pons39ff7032020-03-09 21:39:44 +01002517 MCHBAR8(CLOCKGATINGI) = MCHBAR8(CLOCKGATINGI) & ~0x3;
Damien Zammit003d15c2015-11-20 17:17:51 +11002518 return;
2519 }
Angel Pons39ff7032020-03-09 21:39:44 +01002520 MCHBAR8_OR(CLOCKGATINGI, 3);
2521 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0xf000, pimdclk << 12);
2522 MCHBAR8_AND_OR(CSHWRIOBONUSX, ~0x77, (push << 4) | push);
2523 MCHBAR32_AND_OR(C0COREBONUS, ~0x0f000000, 0x03000000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002524}
2525
2526/**
2527 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2528 */
2529void sdram_initialize(int boot_path, const u8 *spd_addresses)
2530{
2531 struct sysinfo si;
Angel Pons39ff7032020-03-09 21:39:44 +01002532 const char *boot_str[] = {"Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002533
2534 PRINTK_DEBUG("Setting up RAM controller.\n");
2535
2536 memset(&si, 0, sizeof(si));
2537
2538 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002539 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002540 si.spd_map[0] = spd_addresses[0];
2541 si.spd_map[1] = spd_addresses[1];
2542 si.spd_map[2] = spd_addresses[2];
2543 si.spd_map[3] = spd_addresses[3];
2544
2545 sdram_read_spds(&si);
2546
2547 /* Choose Common Frequency */
2548 sdram_detect_ram_speed(&si);
2549
2550 /* Determine smallest common tRAS, tRP, tRCD, etc */
2551 sdram_detect_smallest_params(&si);
2552
2553 /* Enable HPET */
2554 enable_hpet();
Damien Zammit003d15c2015-11-20 17:17:51 +11002555
Angel Pons39ff7032020-03-09 21:39:44 +01002556 MCHBAR16_OR(CPCTL, 1 << 15);
Damien Zammit003d15c2015-11-20 17:17:51 +11002557
Damien Zammit003d15c2015-11-20 17:17:51 +11002558 sdram_clk_crossing(&si);
2559
2560 sdram_checkreset();
2561 PRINTK_DEBUG("Done checkreset\n");
2562
2563 sdram_clkmode(&si);
2564 PRINTK_DEBUG("Done clkmode\n");
2565
2566 sdram_timings(&si);
2567 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2568
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002569 if (si.boot_path != BOOT_PATH_RESET) {
2570 sdram_dlltiming(&si);
2571 PRINTK_DEBUG("Done dlltiming\n");
2572 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002573
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002574 if (si.boot_path != BOOT_PATH_RESET) {
2575 sdram_rcomp(&si);
2576 PRINTK_DEBUG("Done RCOMP\n");
2577 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002578
2579 sdram_odt(&si);
2580 PRINTK_DEBUG("Done odt\n");
2581
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002582 if (si.boot_path != BOOT_PATH_RESET) {
Angel Pons39ff7032020-03-09 21:39:44 +01002583 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002584 ;
2585 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002586
2587 sdram_mmap(&si);
2588 PRINTK_DEBUG("Done mmap\n");
2589
Angel Pons39ff7032020-03-09 21:39:44 +01002590 /* Enable DDR IO buffer */
2591 MCHBAR8_AND_OR(C0IOBUFACTCTL, ~0x3f, 0x08);
2592 MCHBAR8_OR(C0RSTCTL, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002593
2594 sdram_rcompupdate(&si);
2595 PRINTK_DEBUG("Done RCOMP update\n");
2596
Angel Pons39ff7032020-03-09 21:39:44 +01002597 MCHBAR8_OR(HIT4, 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11002598
2599 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01002600 MCHBAR32_OR(C0CKECTRL, 1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002601
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002602 sdram_jedecinit(&si);
2603 PRINTK_DEBUG("Done MRS\n");
2604 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002605
2606 sdram_misc(&si);
2607 PRINTK_DEBUG("Done misc\n");
2608
2609 sdram_zqcl(&si);
2610 PRINTK_DEBUG("Done zqcl\n");
2611
2612 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01002613 MCHBAR32_OR(C0REFRCTRL2, 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002614 }
2615
2616 sdram_dradrb(&si);
2617 PRINTK_DEBUG("Done dradrb\n");
2618
2619 sdram_rcven(&si);
2620 PRINTK_DEBUG("Done rcven\n");
2621
2622 sdram_new_trd(&si);
2623 PRINTK_DEBUG("Done tRD\n");
2624
2625 sdram_mmap_regs(&si);
2626 PRINTK_DEBUG("Done mmap regs\n");
2627
2628 sdram_enhancedmode(&si);
2629 PRINTK_DEBUG("Done enhanced mode\n");
2630
2631 sdram_powersettings(&si);
2632 PRINTK_DEBUG("Done power settings\n");
2633
2634 sdram_programddr();
2635 PRINTK_DEBUG("Done programming ddr\n");
2636
2637 sdram_programdqdqs(&si);
2638 PRINTK_DEBUG("Done programming dqdqs\n");
2639
2640 sdram_periodic_rcomp();
2641 PRINTK_DEBUG("Done periodic RCOMP\n");
2642
2643 /* Set init done */
Angel Pons39ff7032020-03-09 21:39:44 +01002644 MCHBAR32_OR(C0REFRCTRL2, 1 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002645
2646 /* Tell ICH7 that we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002647 pci_and_config8(PCI_DEV(0, 0x1f, 0), 0xa2, (u8)~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11002648
2649 /* Tell northbridge we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002650 pci_or_config8(HOST_BRIDGE, 0xf4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002651
2652 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2653}