blob: dd728e8a47ee706b83ba6859b793da5f54264ccd [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
Angel Pons39ff7032020-03-09 21:39:44 +0100919 /* FIXME: Somehow, touching this changes the binary... */
920 MCHBAR32(C0DQSRyTX1(rank)) = (MCHBAR32(0x5b4 + (rank * 4))
921 & ~((1 << (dqs + 9)) | (1 << dqs))) | reg32;
922
923 reg32 = ((u32) pll->clkdelay[f][clk]) << ((dqs * 2) + 16);
924 MCHBAR32_AND_OR(C0DQSDQRyTX3(rank), ~((1 << (dqs * 2 + 17)) | (1 << (dqs * 2 + 16))),
925 reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100926
927 reg8 = pll->pi[f][clk];
Angel Pons39ff7032020-03-09 21:39:44 +0100928 MCHBAR8_AND_OR(C0TXDQS0R0DLL + j, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100929}
930
Damien Zammit003d15c2015-11-20 17:17:51 +1100931static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
932{
933 u8 rank, dq, reg8, j;
934 u32 reg32;
935
Angel Pons39ff7032020-03-09 21:39:44 +0100936 j = clk - 8;
937 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100938 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100939 rank = j % 4;
940 dq = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100941
Angel Pons39ff7032020-03-09 21:39:44 +0100942 reg32 |= ((u32) pll->dben[f][clk]) << (dq + 9);
Damien Zammit003d15c2015-11-20 17:17:51 +1100943 reg32 |= ((u32) pll->dbsel[f][clk]) << dq;
Angel Pons39ff7032020-03-09 21:39:44 +0100944
945 /* FIXME: Somehow, touching this changes the binary... */
946 MCHBAR32(C0DQRyTX1(rank)) = (MCHBAR32(0x5a4 + rank * 4)
947 & ~((1 << (dq + 9)) | (1 << dq))) | reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100948
949 reg32 = ((u32) pll->clkdelay[f][clk]) << (dq*2);
Angel Pons39ff7032020-03-09 21:39:44 +0100950 MCHBAR32_AND_OR(C0DQSDQRyTX3(rank), ~((1 << (dq * 2 + 1)) | (1 << (dq * 2))), reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100951
952 reg8 = pll->pi[f][clk];
Angel Pons39ff7032020-03-09 21:39:44 +0100953 MCHBAR8_AND_OR(C0TXDQ0R0DLL + j, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100954}
955
Angel Pons39ff7032020-03-09 21:39:44 +0100956/* WDLL programming: Perform HPLL/MPLL calibration after write levelization */
Damien Zammit003d15c2015-11-20 17:17:51 +1100957static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
958{
959 struct pllparam pll = {
960 .pi = {
Angel Pons39ff7032020-03-09 21:39:44 +0100961 { /* DDR = 667 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100962 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
963 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
964 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
965 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Angel Pons39ff7032020-03-09 21:39:44 +0100967 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3,
Damien Zammit003d15c2015-11-20 17:17:51 +1100968 },
Angel Pons39ff7032020-03-09 21:39:44 +0100969 { /* DDR = 800 */
970 53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
Damien Zammit003d15c2015-11-20 17:17:51 +1100971 34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
972 47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
Angel Pons39ff7032020-03-09 21:39:44 +0100973 47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
974 2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
975 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15,
Damien Zammit003d15c2015-11-20 17:17:51 +1100976 }},
977
978 .dben = {
Angel Pons39ff7032020-03-09 21:39:44 +0100979 { /* DDR = 667 */
980 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
981 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
982 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
983 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
984 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
985 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100986 },
Angel Pons39ff7032020-03-09 21:39:44 +0100987 { /* DDR = 800 */
988 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
989 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
990 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
991 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
992 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
993 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100994 }},
995
996 .dbsel = {
Angel Pons39ff7032020-03-09 21:39:44 +0100997 { /* DDR = 667 */
998 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
999 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1000 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1001 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1002 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1003 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001004 },
Angel Pons39ff7032020-03-09 21:39:44 +01001005 { /* DDR = 800 */
1006 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1007 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1008 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1009 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1010 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1011 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001012 }},
1013
1014 .clkdelay = {
Angel Pons39ff7032020-03-09 21:39:44 +01001015 { /* DDR = 667 */
1016 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1017 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1018 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1019 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1020 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1021 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001022 },
Angel Pons39ff7032020-03-09 21:39:44 +01001023 { /* DDR = 800 */
1024 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1025 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1026 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1027 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1028 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1029 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Damien Zammit003d15c2015-11-20 17:17:51 +11001030 }}
1031 };
1032
1033 u8 i, f;
1034 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1035 f = 0;
1036 } else {
1037 f = 1;
1038 }
1039 for (i = 0; i < 72; i++) {
1040 pll.pi[f][i] += pidelay;
1041 }
1042
Angel Pons39ff7032020-03-09 21:39:44 +01001043 /* Disable Dynamic DQS Slave Setting Per Rank */
1044 MCHBAR8_AND(CSHRDQSCMN, ~(1 << 7));
1045 MCHBAR16_AND_OR(CSHRPDCTL4, ~0x3fff, 0x1fff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001046
1047 sdram_p_clkset0(&pll, f, 0);
1048 sdram_p_clkset1(&pll, f, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01001049 sdram_p_cmd(&pll, f, 2);
1050 sdram_p_ctrl(&pll, f, 4);
1051
Damien Zammit003d15c2015-11-20 17:17:51 +11001052 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001053 sdram_p_dqs(&pll, f, i + 40);
Damien Zammit003d15c2015-11-20 17:17:51 +11001054 }
1055 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001056 sdram_p_dq(&pll, f, i + 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11001057 }
1058}
1059
Angel Pons39ff7032020-03-09 21:39:44 +01001060/* Perform HMC hardware calibration */
Damien Zammit003d15c2015-11-20 17:17:51 +11001061static void sdram_calibratehwpll(struct sysinfo *s)
1062{
1063 u8 reg8;
1064
1065 s->async = 0;
1066 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001067
Angel Pons39ff7032020-03-09 21:39:44 +01001068 MCHBAR16_OR(CSHRPDCTL, 1 << 15);
1069 MCHBAR8_AND(CSHRPDCTL, ~(1 << 7));
1070 MCHBAR8_OR(CSHRPDCTL, 1 << 3);
1071 MCHBAR8_OR(CSHRPDCTL, 1 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001072
Angel Pons39ff7032020-03-09 21:39:44 +01001073 /* Start hardware HMC calibration */
1074 MCHBAR8_OR(CSHRPDCTL, 1 << 7);
1075
1076 /* Busy-wait until calibration is done */
1077 while ((MCHBAR8(CSHRPDCTL) & (1 << 2)) == 0)
1078 ;
1079
1080 /* If hardware HMC calibration failed */
1081 reg8 = (MCHBAR8(CSHRPDCTL) & (1 << 3)) >> 3;
Damien Zammit003d15c2015-11-20 17:17:51 +11001082 if (reg8 != 0) {
1083 s->async = 1;
1084 }
1085}
1086
1087static void sdram_dlltiming(struct sysinfo *s)
1088{
Elyes HAOUAS66b462d2019-01-02 21:11:32 +01001089 u8 reg8, i;
Damien Zammit003d15c2015-11-20 17:17:51 +11001090 u16 reg16;
1091 u32 reg32;
1092
Angel Pons39ff7032020-03-09 21:39:44 +01001093 /* Configure the Master DLL */
Damien Zammit003d15c2015-11-20 17:17:51 +11001094 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +01001095 reg32 = 0x08014227;
Damien Zammit003d15c2015-11-20 17:17:51 +11001096 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001097 reg32 = 0x00014221;
Damien Zammit003d15c2015-11-20 17:17:51 +11001098 }
Angel Pons39ff7032020-03-09 21:39:44 +01001099 MCHBAR32_AND_OR(CSHRMSTRCTL1, ~0x0fffffff, reg32);
1100 MCHBAR32_OR(CSHRMSTRCTL1, 1 << 23);
1101 MCHBAR32_OR(CSHRMSTRCTL1, 1 << 15);
1102 MCHBAR32_AND(CSHRMSTRCTL1, ~(1 << 15));
Damien Zammit003d15c2015-11-20 17:17:51 +11001103
1104 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001105 /* Disable the Master DLLs by setting these bits, IN ORDER! */
1106 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 0);
1107 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 2);
1108 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 4);
1109 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 8);
1110 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 10);
1111 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 12);
1112 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 14);
Damien Zammit003d15c2015-11-20 17:17:51 +11001113 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001114 /* Enable the Master DLLs by clearing these bits, IN ORDER! */
1115 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 0));
1116 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 2));
1117 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 4));
1118 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 8));
1119 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 10));
1120 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 12));
1121 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 14));
Damien Zammit003d15c2015-11-20 17:17:51 +11001122 }
1123
Angel Pons39ff7032020-03-09 21:39:44 +01001124 /* Initialize the Transmit DLL PI values in the following sequence. */
Damien Zammit003d15c2015-11-20 17:17:51 +11001125 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001126 MCHBAR8_AND_OR(CREFPI, ~0x3f, 0x07);
Damien Zammit003d15c2015-11-20 17:17:51 +11001127 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001128 MCHBAR8_AND(CREFPI, ~0x3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001129 }
1130
1131 sdram_calibratepll(s, 0); // XXX check
1132
Angel Pons39ff7032020-03-09 21:39:44 +01001133 /* Enable all modular Slave DLL */
1134 MCHBAR16_OR(C0DLLPIEN, 1 << 11);
1135 MCHBAR16_OR(C0DLLPIEN, 1 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11001136
1137 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001138 MCHBAR16_OR(C0DLLPIEN, (1 << 10) >> i);
Damien Zammit003d15c2015-11-20 17:17:51 +11001139 }
Angel Pons39ff7032020-03-09 21:39:44 +01001140 /* Enable DQ/DQS output */
1141 MCHBAR8_OR(C0SLVDLLOUTEN, 1);
1142 MCHBAR16(CSPDSLVWT) = 0x5005;
1143 MCHBAR16_AND_OR(CSHRPDCTL2, ~0x1f1f, 0x051a);
1144 MCHBAR16_AND_OR(CSHRPDCTL5, ~0xbf3f, 0x9010);
Damien Zammit003d15c2015-11-20 17:17:51 +11001145
1146 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001147 MCHBAR8_AND_OR(CSHRPDCTL3, ~0x7f, 0x6b);
Damien Zammit003d15c2015-11-20 17:17:51 +11001148 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001149 MCHBAR8_AND_OR(CSHRPDCTL3, ~0x7f, 0x55);
Damien Zammit003d15c2015-11-20 17:17:51 +11001150 sdram_calibratehwpll(s);
1151 }
Angel Pons39ff7032020-03-09 21:39:44 +01001152 /* Disable Dynamic Diff Amp */
1153 MCHBAR32_AND(C0STATRDCTRL, ~(1 << 22));
Damien Zammit003d15c2015-11-20 17:17:51 +11001154
Angel Pons39ff7032020-03-09 21:39:44 +01001155 /* Now, start initializing the transmit FIFO */
1156 MCHBAR8_AND(C0MISCCTL, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11001157
Angel Pons39ff7032020-03-09 21:39:44 +01001158 /* Disable (gate) mdclk and mdclkb */
1159 MCHBAR8_OR(CSHWRIOBONUS, 0xc0);
Jacob Garberd10680b2019-06-11 14:13:04 -06001160
Angel Pons39ff7032020-03-09 21:39:44 +01001161 /* Select mdmclk */
1162 MCHBAR8_AND(CSHWRIOBONUS, ~(1 << 5));
Damien Zammit003d15c2015-11-20 17:17:51 +11001163
Angel Pons39ff7032020-03-09 21:39:44 +01001164 /* Ungate mdclk */
1165 MCHBAR8_AND_OR(CSHWRIOBONUS, ~0xc0, 1 << 6);
1166 MCHBAR8_AND_OR(CSHRFIFOCTL, ~0x3f, 0x1a);
1167
1168 /* Enable the write pointer count */
1169 MCHBAR8_OR(CSHRFIFOCTL, 1);
1170
1171 /* Set the DDR3 Reset Enable bit */
1172 MCHBAR8_OR(CSHRDDR3CTL, 1);
1173
1174 /* Configure DQS-DQ Transmit */
1175 MCHBAR32(CSHRDQSTXPGM) = 0x00551803;
1176
1177 reg8 = 0; /* Switch all clocks on anyway */
1178
1179 /* Enable clock groups depending on rank population */
1180 MCHBAR32_AND_OR(C0CKTX, ~0x3f000000, reg8 << 24);
1181
1182 /* Enable DDR command output buffers from core */
1183 MCHBAR8_AND(0x594, ~1);
1184
Damien Zammit003d15c2015-11-20 17:17:51 +11001185 reg16 = 0;
1186 if (!rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001187 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001188 }
1189 if (!rank_is_populated(s->dimms, 0, 1)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001190 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001191 }
1192 if (!rank_is_populated(s->dimms, 0, 2)) {
1193 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1194 }
1195 if (!rank_is_populated(s->dimms, 0, 3)) {
1196 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1197 }
Angel Pons39ff7032020-03-09 21:39:44 +01001198 MCHBAR16_OR(C0CTLTX2, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001199}
1200
Angel Pons39ff7032020-03-09 21:39:44 +01001201/* Define a shorter name for these to make the lines fit in 96 characters */
1202#define TABLE static const
1203
1204/* Loop over each RCOMP group, but skip group 1 because it does not exist */
1205#define FOR_EACH_RCOMP_GROUP(idx) for (idx = 0; idx < 7; idx++) if (idx != 1)
1206
1207/* Define accessors for the RCOMP register banks */
1208#define C0RCOMPCTRLx(x) (rcompctl[(x)] + 0x00)
1209#define C0RCOMPMULTx(x) (rcompctl[(x)] + 0x04)
1210#define C0RCOMPOVRx(x) (rcompctl[(x)] + 0x06)
1211#define C0RCOMPOSVx(x) (rcompctl[(x)] + 0x0A)
1212#define C0SCOMPVREFx(x) (rcompctl[(x)] + 0x0E)
1213#define C0SCOMPOVRx(x) (rcompctl[(x)] + 0x10)
1214#define C0SCOMPOFFx(x) (rcompctl[(x)] + 0x12)
1215#define C0DCOMPx(x) (rcompctl[(x)] + 0x14)
1216#define C0SLEWBASEx(x) (rcompctl[(x)] + 0x16)
1217#define C0SLEWPULUTx(x) (rcompctl[(x)] + 0x18)
1218#define C0SLEWPDLUTx(x) (rcompctl[(x)] + 0x1C)
1219#define C0DCOMPOVRx(x) (rcompctl[(x)] + 0x20)
1220#define C0DCOMPOFFx(x) (rcompctl[(x)] + 0x24)
1221
1222/* FIXME: This only applies to DDR2 */
Damien Zammit003d15c2015-11-20 17:17:51 +11001223static void sdram_rcomp(struct sysinfo *s)
1224{
Angel Pons39ff7032020-03-09 21:39:44 +01001225 u8 i, j, reg8, rcompp, rcompn, srup, srun;
Damien Zammit003d15c2015-11-20 17:17:51 +11001226 u16 reg16;
1227 u32 reg32, rcomp1, rcomp2;
1228
Angel Pons39ff7032020-03-09 21:39:44 +01001229 static const u8 rcompslew = 0x0a;
1230 static const u16 rcompctl[7] = {
1231 C0RCOMPCTRL0,
1232 0, /* This register does not exist */
1233 C0RCOMPCTRL2,
1234 C0RCOMPCTRL3,
1235 C0RCOMPCTRL4,
1236 C0RCOMPCTRL5,
1237 C0RCOMPCTRL6,
1238 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001239
Angel Pons39ff7032020-03-09 21:39:44 +01001240 /* RCOMP settings tables = { NC-NC, x16SS, x16DS, x16SS2, x16DS2, x8DS, x8DS2}; */
1241 TABLE u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0};
1242 TABLE u8 rcompstr[7] = { 0x66, 0x00, 0xaa, 0x55, 0x55, 0x77, 0x77};
1243 TABLE u16 rcompscomp[7] = {0xa22a, 0x0000, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a};
1244 TABLE u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1};
1245 TABLE u16 rcompf[7] = {0x1114, 0x0000, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a};
1246 TABLE u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0xaa};
1247 TABLE u16 rcompscomp2[7] = {0x0000, 0xe22e, 0xe22e, 0xe22e, 0x8228, 0xe22e, 0x8228};
1248 TABLE u8 rcompdelay2[7] = { 0, 0, 0, 0, 2, 0, 2};
Damien Zammit003d15c2015-11-20 17:17:51 +11001249
Angel Pons39ff7032020-03-09 21:39:44 +01001250 TABLE u8 rcomplut[64][12] = {
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 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1263 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1264 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1265 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1266 {10, 9, 12, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1267 {10, 9, 12, 11, 2, 2, 6, 5, 7, 6, 6, 5},
1268 {10, 10, 12, 12, 2, 2, 6, 5, 7, 6, 6, 5},
1269 {10, 10, 12, 12, 2, 2, 6, 6, 7, 7, 6, 6},
1270 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1271 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1272 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1273 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1274 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1275 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1276 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1277 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1278 {11, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1279 {11, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1280 {12, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1281 {12, 12, 14, 13, 3, 3, 7, 6, 7, 7, 7, 6},
1282 {13, 12, 16, 15, 3, 3, 7, 6, 8, 7, 7, 6},
1283 {13, 14, 16, 15, 4, 3, 7, 7, 8, 8, 7, 7},
1284 {14, 14, 16, 17, 4, 3, 7, 7, 8, 8, 7, 7},
1285 {14, 16, 18, 17, 4, 4, 8, 7, 8, 8, 8, 7},
1286 {15, 16, 18, 19, 4, 4, 8, 7, 9, 8, 8, 7},
1287 {15, 18, 18, 19, 4, 4, 8, 8, 9, 9, 8, 8},
1288 {16, 18, 20, 21, 4, 4, 8, 8, 9, 9, 8, 8},
1289 {16, 19, 20, 21, 5, 4, 9, 8, 10, 9, 9, 8},
1290 {16, 19, 20, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1291 {17, 19, 22, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1292 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1293 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1294 {18, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1295 {18, 21, 24, 25, 5, 5, 9, 9, 11, 10, 9, 9},
1296 {19, 21, 24, 27, 5, 5, 9, 9, 11, 11, 9, 9},
1297 {19, 22, 24, 27, 5, 5, 10, 9, 11, 11, 10, 9},
1298 {20, 22, 24, 27, 6, 5, 10, 10, 11, 11, 10, 10},
1299 {20, 23, 26, 27, 6, 6, 10, 10, 12, 12, 10, 10},
1300 {20, 23, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1301 {21, 24, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1302 {21, 24, 26, 29, 6, 6, 11, 10, 12, 13, 11, 10},
1303 {22, 25, 28, 29, 6, 6, 11, 11, 13, 13, 11, 11},
1304 {22, 25, 28, 31, 6, 6, 11, 11, 13, 13, 11, 11},
1305 {22, 26, 28, 31, 6, 6, 11, 11, 13, 14, 11, 11},
1306 {23, 26, 30, 31, 7, 6, 12, 11, 14, 14, 12, 11},
1307 {23, 27, 30, 33, 7, 7, 12, 12, 14, 14, 12, 12},
1308 {23, 27, 30, 33, 7, 7, 12, 12, 14, 15, 12, 12},
1309 {24, 28, 32, 33, 7, 7, 12, 12, 15, 15, 12, 12},
1310 {24, 28, 32, 33, 7, 7, 12, 12, 15, 16, 12, 12},
1311 {24, 29, 32, 35, 7, 7, 12, 12, 15, 16, 12, 12},
1312 {25, 29, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1313 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1314 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
Damien Zammit003d15c2015-11-20 17:17:51 +11001315 };
1316
1317 srup = 0;
1318 srun = 0;
1319
1320 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001321 rcomp1 = 0x00050431;
1322 } else {
Damien Zammit003d15c2015-11-20 17:17:51 +11001323 rcomp1 = 0x00050542;
1324 }
1325 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
1326 rcomp2 = 0x14C42827;
1327 } else {
1328 rcomp2 = 0x19042827;
1329 }
1330
Angel Pons39ff7032020-03-09 21:39:44 +01001331 FOR_EACH_RCOMP_GROUP(i) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001332 reg8 = rcompupdate[i];
Angel Pons39ff7032020-03-09 21:39:44 +01001333 MCHBAR8_AND_OR(C0RCOMPCTRLx(i), ~1, reg8);
1334 MCHBAR8_AND(C0RCOMPCTRLx(i), ~2);
1335
1336 reg16 = rcompslew;
1337 MCHBAR16_AND_OR(C0RCOMPCTRLx(i), ~0xf000, reg16 << 12);
1338
1339 MCHBAR8(C0RCOMPMULTx(i)) = rcompstr[i];
1340 MCHBAR16(C0SCOMPVREFx(i)) = rcompscomp[i];
1341 MCHBAR8_AND_OR(C0DCOMPx(i), ~0x03, rcompdelay[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001342 if (i == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01001343 /* FIXME: Why are we rewriting this? */
1344 MCHBAR16_AND_OR(C0RCOMPCTRLx(i), ~0xf000, reg16 << 12);
1345
1346 MCHBAR8(C0RCOMPMULTx(i)) = rcompstr2[s->dimm_config[0]];
1347 MCHBAR16(C0SCOMPVREFx(i)) = rcompscomp2[s->dimm_config[0]];
1348 MCHBAR8_AND_OR(C0DCOMPx(i), ~0x03, rcompdelay2[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001349 }
1350
Angel Pons39ff7032020-03-09 21:39:44 +01001351 MCHBAR16_AND(C0SLEWBASEx(i), ~0x7f7f);
1352
1353 /* FIXME: Why not do a single dword write? */
1354 MCHBAR16_AND(C0SLEWPULUTx(i), ~0x3f3f);
1355 MCHBAR16_AND(C0SLEWPULUTx(i) + 2, ~0x3f3f);
1356
1357 /* FIXME: Why not do a single dword write? */
1358 MCHBAR16_AND(C0SLEWPDLUTx(i), ~0x3f3f);
1359 MCHBAR16_AND(C0SLEWPDLUTx(i) + 2, ~0x3f3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001360 }
1361
Angel Pons39ff7032020-03-09 21:39:44 +01001362 /* FIXME: Hardcoded */
1363 MCHBAR8_AND_OR(C0ODTRECORDX, ~0x3f, 0x36);
1364 MCHBAR8_AND_OR(C0DQSODTRECORDX, ~0x3f, 0x36);
Damien Zammit003d15c2015-11-20 17:17:51 +11001365
Angel Pons39ff7032020-03-09 21:39:44 +01001366 FOR_EACH_RCOMP_GROUP(i) {
1367 MCHBAR8_AND(C0RCOMPCTRLx(i), ~0x60);
1368 MCHBAR16_AND(C0RCOMPCTRLx(i) + 2, ~0x0706);
1369 MCHBAR16_AND(C0RCOMPOSVx(i), ~0x7f7f);
1370 MCHBAR16_AND(C0SCOMPOFFx(i), ~0x3f3f);
1371 MCHBAR16_AND(C0DCOMPOFFx(i), ~0x1f1f);
1372 MCHBAR8_AND(C0DCOMPOFFx(i) + 2, ~0x1f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001373 }
1374
Angel Pons39ff7032020-03-09 21:39:44 +01001375 MCHBAR16_AND(C0ODTRECORDX, ~0xffc0);
1376 MCHBAR16_AND(C0ODTRECORDX + 2, ~0x000f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001377
Angel Pons39ff7032020-03-09 21:39:44 +01001378 /* FIXME: Why not do a single dword write? */
1379 MCHBAR16_AND(C0DQSODTRECORDX, ~0xffc0);
1380 MCHBAR16_AND(C0DQSODTRECORDX + 2, ~0x000f);
1381
1382 FOR_EACH_RCOMP_GROUP(i) {
1383 MCHBAR16(C0SCOMPOVRx(i)) = rcompf[i];
1384
1385 /* FIXME: Why not do a single dword write? */
1386 MCHBAR16(C0DCOMPOVRx(i)) = 0x1219;
1387 MCHBAR16(C0DCOMPOVRx(i) + 2) = 0x000C;
Damien Zammit003d15c2015-11-20 17:17:51 +11001388 }
1389
Angel Pons39ff7032020-03-09 21:39:44 +01001390 MCHBAR32_AND_OR(DCMEASBUFOVR, ~0x001f1f1f, 0x000c1219);
Damien Zammit003d15c2015-11-20 17:17:51 +11001391
Angel Pons39ff7032020-03-09 21:39:44 +01001392 /* FIXME: Why not do a single word write? */
1393 MCHBAR16_AND_OR(XCOMPSDR0BNS, ~0x1f00, 0x1200);
1394 MCHBAR8_AND_OR(XCOMPSDR0BNS, ~0x1f, 0x12);
1395
1396 MCHBAR32(COMPCTRL3) = 0x007C9007;
1397 MCHBAR32(OFREQDELSEL) = rcomp1;
1398 MCHBAR16(XCOMPCMNBNS) = 0x1f7f;
1399 MCHBAR32(COMPCTRL2) = rcomp2;
1400 MCHBAR16_AND_OR(XCOMPDFCTRL, ~0x0f, 1);
1401 MCHBAR16(ZQCALCTRL) = 0x0134;
1402 MCHBAR32(COMPCTRL1) = 0x4C293600;
1403
1404 /* FIXME: wtf did these MRC guys smoke */
1405 MCHBAR8_AND_OR(COMPCTRL1 + 3, ~0x44, (1 << 6) | (1 << 2));
1406 MCHBAR16_AND(XCOMPSDR0BNS, ~(1 << 13));
1407 MCHBAR8_AND(XCOMPSDR0BNS, ~(1 << 5));
1408
1409 FOR_EACH_RCOMP_GROUP(i) {
1410 /* FIXME: This should be an _AND_OR */
1411 MCHBAR8(C0RCOMPCTRLx(i) + 2) = MCHBAR8(C0RCOMPCTRLx(i)) & ~0x71;
Damien Zammit003d15c2015-11-20 17:17:51 +11001412 }
1413
Angel Pons39ff7032020-03-09 21:39:44 +01001414 if ((MCHBAR32(COMPCTRL1) & (1 << 30)) == 0) {
1415 /* Start COMP */
1416 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001417
Angel Pons39ff7032020-03-09 21:39:44 +01001418 /* Wait until COMP is done */
1419 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1420 ;
1421
1422 reg32 = MCHBAR32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001423 rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1424 rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1425
Angel Pons39ff7032020-03-09 21:39:44 +01001426 FOR_EACH_RCOMP_GROUP(i) {
1427 srup = (MCHBAR8(C0RCOMPCTRLx(i) + 1) & 0xc0) >> 6;
1428 srun = (MCHBAR8(C0RCOMPCTRLx(i) + 1) & 0x30) >> 4;
1429
1430 /* FIXME: Why not do a single word write? */
Damien Zammit003d15c2015-11-20 17:17:51 +11001431 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
Angel Pons39ff7032020-03-09 21:39:44 +01001432 MCHBAR16_AND_OR(C0SLEWBASEx(i), ~0x7f00, reg16);
1433
Damien Zammit003d15c2015-11-20 17:17:51 +11001434 reg16 = (u16)(rcompn - (1 << (srun + 1)));
Angel Pons39ff7032020-03-09 21:39:44 +01001435 MCHBAR8_AND_OR(C0SLEWBASEx(i), ~0x7f, (u8)reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001436 }
1437
1438 reg8 = rcompp - (1 << (srup + 1));
1439 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001440 MCHBAR8_AND_OR(C0SLEWPULUTx(0) + i, ~0x3f, rcomplut[j][0]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001441 }
1442
1443 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1444 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons39ff7032020-03-09 21:39:44 +01001445 MCHBAR8_AND_OR(C0SLEWPULUTx(2) + i, ~0x3f, rcomplut[j][10]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001446 }
1447 }
1448
1449 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001450 MCHBAR8_AND_OR(C0SLEWPULUTx(3) + i, ~0x3f, rcomplut[j][6]);
1451 MCHBAR8_AND_OR(C0SLEWPULUTx(4) + i, ~0x3f, rcomplut[j][6]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001452 }
1453
1454 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001455 MCHBAR8_AND_OR(C0SLEWPULUTx(5) + i, ~0x3f, rcomplut[j][8]);
1456 MCHBAR8_AND_OR(C0SLEWPULUTx(6) + i, ~0x3f, rcomplut[j][8]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001457 }
1458
1459 reg8 = rcompn - (1 << (srun + 1));
1460 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001461 MCHBAR8_AND_OR(C0SLEWPDLUTx(0) + i, ~0x3f, rcomplut[j][1]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001462 }
1463
1464 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1465 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons39ff7032020-03-09 21:39:44 +01001466 MCHBAR8_AND_OR(C0SLEWPDLUTx(2) + i, ~0x3f, rcomplut[j][11]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001467 }
1468 }
1469
1470 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001471 MCHBAR8_AND_OR(C0SLEWPDLUTx(3) + i, ~0x3f, rcomplut[j][7]);
1472 MCHBAR8_AND_OR(C0SLEWPDLUTx(4) + i, ~0x3f, rcomplut[j][7]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001473 }
1474
1475 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001476 MCHBAR8_AND_OR(C0SLEWPDLUTx(5) + i, ~0x3f, rcomplut[j][9]);
1477 MCHBAR8_AND_OR(C0SLEWPDLUTx(6) + i, ~0x3f, rcomplut[j][9]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001478 }
1479 }
Angel Pons39ff7032020-03-09 21:39:44 +01001480 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001481}
1482
Angel Pons39ff7032020-03-09 21:39:44 +01001483/* FIXME: The ODT tables are for DDR2 only! */
Damien Zammit003d15c2015-11-20 17:17:51 +11001484static void sdram_odt(struct sysinfo *s)
1485{
1486 u8 rankindex = 0;
1487
Angel Pons39ff7032020-03-09 21:39:44 +01001488 static const u16 odt_rankctrl[16] = {
1489 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1490 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1491 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1492 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1493 };
1494 static const u16 odt_matrix[16] = {
1495 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1496 0x0000, 0x0011, 0x0000, 0x0011, 0x0000, 0x4444, 0x0000, 0x4444,
1497 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1498 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4444, 0x0000, 0x4444,
1499 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001500
1501 switch (s->dimms[0].ranks) {
1502 case 0:
1503 if (s->dimms[1].ranks == 0) {
1504 rankindex = 0;
1505 } else if (s->dimms[1].ranks == 1) {
1506 rankindex = 4;
1507 } else if (s->dimms[1].ranks == 2) {
1508 rankindex = 12;
1509 }
1510 break;
1511 case 1:
1512 if (s->dimms[1].ranks == 0) {
1513 rankindex = 1;
1514 } else if (s->dimms[1].ranks == 1) {
1515 rankindex = 5;
1516 } else if (s->dimms[1].ranks == 2) {
1517 rankindex = 13;
1518 }
1519 break;
1520 case 2:
1521 if (s->dimms[1].ranks == 0) {
1522 rankindex = 3;
1523 } else if (s->dimms[1].ranks == 1) {
1524 rankindex = 7;
1525 } else if (s->dimms[1].ranks == 2) {
1526 rankindex = 15;
1527 }
1528 break;
1529 }
1530
Angel Pons39ff7032020-03-09 21:39:44 +01001531 /* Program the ODT Matrix */
1532 MCHBAR16(C0ODT) = odt_matrix[rankindex];
1533
1534 /* Program the ODT Rank Control */
1535 MCHBAR16(C0ODTRKCTRL) = odt_rankctrl[rankindex];
Damien Zammit003d15c2015-11-20 17:17:51 +11001536}
1537
1538static void sdram_mmap(struct sysinfo *s)
1539{
Angel Pons39ff7032020-03-09 21:39:44 +01001540 TABLE u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000, 0xc00001, 0xf00000};
1541 TABLE u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101, 0x1010000, 0x1010101};
1542 TABLE u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1543 TABLE u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006, 0x40002, 0x80006};
Damien Zammit003d15c2015-11-20 17:17:51 +11001544
Angel Pons39ff7032020-03-09 21:39:44 +01001545 TABLE u16 tolud[7] = {2048, 2048, 4096, 4096, 8192, 4096, 8192};
1546 TABLE u16 tom[7] = { 2, 2, 4, 4, 8, 4, 8};
1547 TABLE u16 touud[7] = { 128, 128, 256, 256, 512, 256, 512};
1548 TABLE u32 gbsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1549 TABLE u32 bgsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1550 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 +11001551
1552 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1553 if (s->dimms[0].sides > 1) {
1554 // 2R/NC
Angel Pons39ff7032020-03-09 21:39:44 +01001555 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x300001);
1556 MCHBAR32(C0DRA01) = 0x00000101;
1557 MCHBAR32(C0DRB0) = 0x00040002;
1558 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001559 } else {
1560 // 1R/NC
Angel Pons39ff7032020-03-09 21:39:44 +01001561 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x100001);
1562 MCHBAR32(C0DRA01) = 0x00000001;
1563 MCHBAR32(C0DRB0) = 0x00020002;
1564 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001565 }
1566 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001567 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x300001);
1568 MCHBAR32(C0DRA01) = 0x00000101;
1569 MCHBAR32(C0DRB0) = 0x00040002;
1570 MCHBAR32(C0DRB2) = 0x00040004;
Damien Zammit003d15c2015-11-20 17:17:51 +11001571 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001572 MCHBAR32_AND_OR(C0CKECTRL, ~1, w260[s->dimm_config[0]]);
1573 MCHBAR32(C0DRA01) = w208[s->dimm_config[0]];
1574 MCHBAR32(C0DRB0) = w200[s->dimm_config[0]];
1575 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001576 }
Angel Pons39ff7032020-03-09 21:39:44 +01001577 pci_write_config16(HOST_BRIDGE, 0xb0, tolud[s->dimm_config[0]]);
1578 pci_write_config16(HOST_BRIDGE, 0xa0, tom[s->dimm_config[0]]);
1579 pci_write_config16(HOST_BRIDGE, 0xa2, touud[s->dimm_config[0]]);
1580 pci_write_config32(HOST_BRIDGE, 0xa4, gbsm[s->dimm_config[0]]);
1581 pci_write_config32(HOST_BRIDGE, 0xa8, bgsm[s->dimm_config[0]]);
1582 pci_write_config32(HOST_BRIDGE, 0xac, tsegmb[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001583}
1584
Damien Zammit003d15c2015-11-20 17:17:51 +11001585static u8 sdram_checkrcompoverride(void)
1586{
1587 u32 xcomp;
1588 u8 aa, bb, a, b, c, d;
1589
Angel Pons39ff7032020-03-09 21:39:44 +01001590 xcomp = MCHBAR32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001591 a = (u8)((xcomp & 0x7f000000) >> 24);
Angel Pons39ff7032020-03-09 21:39:44 +01001592 b = (u8)((xcomp & 0x007f0000) >> 16);
1593 c = (u8)((xcomp & 0x00003f00) >> 8);
1594 d = (u8)((xcomp & 0x0000003f) >> 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001595
1596 if (a > b) {
1597 aa = a - b;
1598 } else {
1599 aa = b - a;
1600 }
1601 if (c > d) {
1602 bb = c - d;
1603 } else {
1604 bb = d - c;
1605 }
Angel Pons39ff7032020-03-09 21:39:44 +01001606 if ((aa > 18) || (bb > 7) || (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
Damien Zammit003d15c2015-11-20 17:17:51 +11001607 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001608 MCHBAR32(RCMEASBUFXOVR) = 0x9718a729;
Damien Zammit003d15c2015-11-20 17:17:51 +11001609 return 1;
1610 }
1611 return 0;
1612}
1613
1614static void sdram_rcompupdate(struct sysinfo *s)
1615{
1616 u8 i, ok;
1617 u32 reg32a, reg32b;
1618
1619 ok = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001620 MCHBAR8_AND(XCOMPDFCTRL, ~(1 << 3));
1621 MCHBAR8_AND(COMPCTRL1, ~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11001622 for (i = 0; i < 3; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001623 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001624 hpet_udelay(1000);
Angel Pons39ff7032020-03-09 21:39:44 +01001625 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1626 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001627 ok |= sdram_checkrcompoverride();
1628 }
1629 if (!ok) {
Angel Pons39ff7032020-03-09 21:39:44 +01001630 reg32a = MCHBAR32(XCOMP);
1631 reg32b = ((reg32a >> 16) & 0x0000ffff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001632 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1633 reg32a |= (1 << 31) | (1 << 15);
Angel Pons39ff7032020-03-09 21:39:44 +01001634 MCHBAR32(RCMEASBUFXOVR) = reg32a;
Damien Zammit003d15c2015-11-20 17:17:51 +11001635 }
Angel Pons39ff7032020-03-09 21:39:44 +01001636 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001637 hpet_udelay(1000);
Angel Pons39ff7032020-03-09 21:39:44 +01001638 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1639 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001640}
1641
1642static void __attribute__((noinline))
1643sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1644{
1645 u32 reg32;
1646
1647 reg32 = jval << 3;
Angel Pons39ff7032020-03-09 21:39:44 +01001648 reg32 |= rank * (1 << 27);
1649 MCHBAR8_AND_OR(C0JEDEC, ~0x3e, jmode);
Damien Zammit003d15c2015-11-20 17:17:51 +11001650 read32((void *)reg32);
1651 barrier();
1652 hpet_udelay(1); // 1us
1653}
1654
1655static void sdram_zqcl(struct sysinfo *s)
1656{
1657 if (s->boot_path == BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01001658 MCHBAR32_OR(C0CKECTRL, 1 << 27);
1659 MCHBAR8_AND_OR(C0JEDEC, ~0x0e, NORMAL_OP_CMD);
1660 MCHBAR8_AND(C0JEDEC, ~0x30);
1661 MCHBAR32_AND_OR(C0REFRCTRL2, ~(3 << 30), 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001662 }
1663}
1664
1665static void sdram_jedecinit(struct sysinfo *s)
1666{
1667 u8 r, i, ch;
1668 u16 reg16, mrs, rttnom;
1669 struct jedeclist {
1670 char debug[15];
1671 u8 cmd;
1672 u16 val;
1673 };
1674
Arthur Heymans6bf13012017-06-10 12:03:27 +02001675 static const struct jedeclist jedec[12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001676 { " NOP ", NOP_CMD, 0 },
1677 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1678 { " EMRS2 ", EMRS2_CMD, 0 },
1679 { " EMRS3 ", EMRS3_CMD, 0 },
1680 { " EMRS1 ", EMRS1_CMD, 0 },
1681 { " DLL RESET ", MRS_CMD, (1 << 8) },
1682 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1683 { " AUTOREFRESH", CBR_CMD, 0 },
1684 { " AUTOREFRESH", CBR_CMD, 0 },
1685 { " INITIALISE ", MRS_CMD, 0 },
1686 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1687 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1688 };
1689
1690 mrs = (s->selected_timings.CAS << 4) |
Angel Pons39ff7032020-03-09 21:39:44 +01001691 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 3;
1692
Damien Zammit003d15c2015-11-20 17:17:51 +11001693 rttnom = (1 << 2);
1694 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1695 rttnom |= (1 << 6);
1696 }
1697
1698 hpet_udelay(200); // 200us
1699 reg16 = 0;
1700 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1701 for (i = 0; i < 12; i++) {
1702 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1703 reg16 = jedec[i].val;
1704 switch (jedec[i].cmd) {
1705 case EMRS1_CMD:
1706 reg16 |= rttnom;
1707 break;
1708 case MRS_CMD:
1709 reg16 |= mrs;
1710 break;
1711 default:
1712 break;
1713 }
1714 sdram_jedec(s, r, jedec[i].cmd, reg16);
1715 PRINTK_DEBUG("done\n");
1716 }
1717 }
1718}
1719
1720static void sdram_misc(struct sysinfo *s)
1721{
1722 u32 reg32;
1723
1724 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001725 reg32 |= (4 << 13);
1726 reg32 |= (6 << 8);
1727 MCHBAR32_AND_OR(C0DYNRDCTRL, ~0x3ff00, reg32);
1728 MCHBAR8_AND(C0DYNRDCTRL, ~(1 << 7));
1729 MCHBAR8_OR(C0REFRCTRL + 3, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001730 if (s->boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01001731 MCHBAR8_AND_OR(C0JEDEC, ~0x0e, NORMAL_OP_CMD);
1732 MCHBAR8_AND(C0JEDEC, ~0x30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001733 } else {
1734 sdram_zqcl(s);
1735 }
1736}
1737
1738static void sdram_checkreset(void)
1739{
1740 u8 pmcon2, pmcon3, reset;
1741
1742 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1743 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1744 pmcon3 &= ~0x2;
1745 if (pmcon2 & 0x80) {
1746 pmcon2 &= ~0x80;
1747 reset = 1;
1748 } else {
1749 pmcon2 |= 0x80;
1750 reset = 0;
1751 }
1752 if (pmcon2 & 0x4) {
1753 pmcon2 |= 0x4;
1754 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1755 pmcon3 |= (1 << 3);
1756 }
1757 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1758 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +02001759 if (reset)
1760 full_reset();
Damien Zammit003d15c2015-11-20 17:17:51 +11001761}
1762
1763static void sdram_dradrb(struct sysinfo *s)
1764{
1765 u8 i, reg8, ch, r;
1766 u32 reg32, ind, c0dra, c0drb, dra;
1767 u16 addr;
1768 i = 0;
Arthur Heymans6bf13012017-06-10 12:03:27 +02001769 static const u8 dratab[2][2][2][4] =
Damien Zammit003d15c2015-11-20 17:17:51 +11001770 {{
1771 {
1772 {0xff, 0xff, 0xff, 0xff},
1773 {0xff, 0x00, 0x02, 0xff}
1774 },
1775 {
1776 {0xff, 0x01, 0xff, 0xff},
1777 {0xff, 0x03, 0xff, 0x06}
1778 }
1779 },
1780 {
1781 {
1782 {0xff, 0xff, 0xff, 0xff},
1783 {0xff, 0x04, 0x06, 0x08}
1784 },
1785 {
1786 {0xff, 0xff, 0xff, 0xff},
1787 {0x05, 0x07, 0x09, 0xff}
1788 }
1789 }};
1790
Arthur Heymans6bf13012017-06-10 12:03:27 +02001791 static const u8 dradrb[10][6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001792 //Row Col Bank Width DRB
1793 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1794 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1795 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1796 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1797 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1798 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1799 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1800 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1801 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1802 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1803 };
1804
1805 reg32 = 0;
1806 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1807 i = r / 2;
1808 PRINTK_DEBUG("RANK %d PRESENT\n", r);
Angel Pons39ff7032020-03-09 21:39:44 +01001809 dra = dratab
1810 [s->dimms[i].banks]
Damien Zammit003d15c2015-11-20 17:17:51 +11001811 [s->dimms[i].width]
1812 [s->dimms[i].cols - 9]
1813 [s->dimms[i].rows - 12];
1814
1815 if (s->dimms[i].banks == 1) {
1816 dra |= (1 << 7);
1817 }
Angel Pons39ff7032020-03-09 21:39:44 +01001818 reg32 |= (dra << (r * 8));
Damien Zammit003d15c2015-11-20 17:17:51 +11001819 }
Angel Pons39ff7032020-03-09 21:39:44 +01001820 MCHBAR32(C0DRA01) = reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +11001821 c0dra = reg32;
1822 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1823
1824 reg32 = 0;
1825 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1826 reg32 |= (1 << r);
1827 }
1828 reg8 = (u8)(reg32 << 4) & 0xf0;
Angel Pons39ff7032020-03-09 21:39:44 +01001829 MCHBAR8_AND_OR(C0CKECTRL + 2, ~0xf0, reg8);
1830
1831 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) || ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1832 MCHBAR8_OR(C0CKECTRL, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001833 }
1834
Angel Pons39ff7032020-03-09 21:39:44 +01001835 addr = C0DRB0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001836 c0drb = 0;
1837 FOR_EACH_RANK(ch, r) {
1838 if (rank_is_populated(s->dimms, ch, r)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001839 ind = (c0dra >> (8 * r)) & 0x7f;
Damien Zammit003d15c2015-11-20 17:17:51 +11001840 c0drb = (u16)(c0drb + dradrb[ind][5]);
1841 s->channel_capacity[0] += dradrb[ind][5] << 6;
1842 }
1843 MCHBAR16(addr) = c0drb;
1844 addr += 2;
1845 }
1846 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1847}
1848
1849static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1850{
Damien Zammit003d15c2015-11-20 17:17:51 +11001851 u8 dqsmatches = 1;
1852 while (count--) {
Angel Pons39ff7032020-03-09 21:39:44 +01001853 MCHBAR8_AND(C0RSTCTL, ~2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001854 hpet_udelay(1);
Angel Pons39ff7032020-03-09 21:39:44 +01001855 MCHBAR8_OR(C0RSTCTL, 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001856 hpet_udelay(1);
1857 barrier();
Elyes HAOUASaf159d42019-05-22 20:19:22 +02001858 read32((void *)strobeaddr);
Damien Zammit003d15c2015-11-20 17:17:51 +11001859 barrier();
1860 hpet_udelay(1);
1861
1862 if (((MCHBAR8(dqshighaddr) & 0x40) >> 6) != highlow) {
1863 dqsmatches = 0;
1864 }
1865 }
1866
1867 return dqsmatches;
1868}
1869
Angel Pons39ff7032020-03-09 21:39:44 +01001870static void rcvenclock(u8 *coarse, u8 *medium, u8 lane)
Damien Zammit003d15c2015-11-20 17:17:51 +11001871{
1872 if (*medium < 3) {
1873 (*medium)++;
Angel Pons39ff7032020-03-09 21:39:44 +01001874 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001875 } else {
1876 *medium = 0;
1877 (*coarse)++;
Angel Pons39ff7032020-03-09 21:39:44 +01001878 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, *coarse << 16);
1879 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)(~3 << (lane * 2)), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001880 }
1881}
1882
1883static void sdram_rcven(struct sysinfo *s)
1884{
Angel Pons39ff7032020-03-09 21:39:44 +01001885 u8 coarse, savecoarse;
1886 u8 medium, savemedium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001887 u8 pi, savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01001888 u8 lane;
1889 u8 lanecoarse[8] = {0};
1890 u8 minlanecoarse = 0xff;
1891 u8 offset;
1892 u8 maxlane = 8;
Arthur Heymans015339f2018-08-20 11:28:58 +02001893 /* Since dra/drb is already set up we know that at address 0x00000000
1894 we will always find the first available rank */
1895 u32 strobeaddr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001896 u32 dqshighaddr;
1897
Angel Pons39ff7032020-03-09 21:39:44 +01001898 MCHBAR8_AND(C0RSTCTL, ~0x0c);
1899 MCHBAR8_AND(CMNDQFIFORST, ~0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11001900
1901 PRINTK_DEBUG("rcven 0\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001902 for (lane = 0; lane < maxlane; lane++) {
1903 PRINTK_DEBUG("rcven lane %d\n", lane);
1904// trylaneagain:
1905 dqshighaddr = C0MISCCTLy(lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001906
Angel Pons39ff7032020-03-09 21:39:44 +01001907 coarse = s->selected_timings.CAS + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11001908 pi = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001909 medium = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001910
Angel Pons39ff7032020-03-09 21:39:44 +01001911 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1912 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001913
Angel Pons39ff7032020-03-09 21:39:44 +01001914 MCHBAR8_AND(C0RXRCVyDLL(lane), ~0x3f);
1915
1916 savecoarse = coarse;
1917 savemedium = medium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001918 savepi = pi;
1919
1920 PRINTK_DEBUG("rcven 0.1\n");
1921
Angel Pons39ff7032020-03-09 21:39:44 +01001922 // XXX comment out
1923 // MCHBAR16_AND_OR(C0RCVMISCCTL1, (u16)~3 << (lane * 2), 1 << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001924
1925 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001926 // printk(BIOS_DEBUG, "coarse=%d medium=%d\n", coarse, medium);
1927 rcvenclock(&coarse, &medium, lane);
1928 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001929 PRINTK_DEBUG("Error: coarse > 0xf\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001930 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001931 break;
1932 }
1933 }
1934 PRINTK_DEBUG("rcven 0.2\n");
1935
Angel Pons39ff7032020-03-09 21:39:44 +01001936 savecoarse = coarse;
1937 savemedium = medium;
1938 rcvenclock(&coarse, &medium, lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001939
1940 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001941 savecoarse = coarse;
1942 savemedium = medium;
1943 rcvenclock(&coarse, &medium, lane);
1944 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001945 PRINTK_DEBUG("Error: coarse > 0xf\n");
1946 //goto trylaneagain;
1947 break;
1948 }
1949 }
1950
1951 PRINTK_DEBUG("rcven 0.3\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001952 coarse = savecoarse;
1953 medium = savemedium;
1954 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1955 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(0x3 << lane * 2), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001956
1957 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1958 savepi = pi;
1959 pi++;
1960 if (pi > s->maxpi) {
Angel Pons39ff7032020-03-09 21:39:44 +01001961 // if (s->nodll) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001962 pi = savepi = s->maxpi;
1963 break;
Angel Pons39ff7032020-03-09 21:39:44 +01001964 // }
Damien Zammit003d15c2015-11-20 17:17:51 +11001965 }
Angel Pons39ff7032020-03-09 21:39:44 +01001966 MCHBAR8_AND_OR(C0RXRCVyDLL(lane), ~0x3f, pi << s->pioffset);
Damien Zammit003d15c2015-11-20 17:17:51 +11001967 }
1968 PRINTK_DEBUG("rcven 0.4\n");
1969
1970 pi = savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01001971 MCHBAR8_AND_OR(C0RXRCVyDLL(lane), ~0x3f, pi << s->pioffset);
1972 rcvenclock(&coarse, &medium, lane);
1973
Damien Zammit003d15c2015-11-20 17:17:51 +11001974 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1975 PRINTK_DEBUG("Error: DQS not high\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001976 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001977 }
1978 PRINTK_DEBUG("rcven 0.5\n");
1979 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001980 coarse--;
1981 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1982 if (coarse == 0) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +02001983 PRINTK_DEBUG("Error: DQS did not hit 0\n");
Damien Zammit003d15c2015-11-20 17:17:51 +11001984 break;
1985 }
1986 }
1987
1988 PRINTK_DEBUG("rcven 0.6\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001989 rcvenclock(&coarse, &medium, lane);
1990 s->pi[lane] = pi;
1991 lanecoarse[lane] = coarse;
Damien Zammit003d15c2015-11-20 17:17:51 +11001992 }
1993
1994 PRINTK_DEBUG("rcven 1\n");
1995
Angel Pons39ff7032020-03-09 21:39:44 +01001996 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11001997 do {
Angel Pons39ff7032020-03-09 21:39:44 +01001998 lane--;
1999 if (minlanecoarse > lanecoarse[lane]) {
2000 minlanecoarse = lanecoarse[lane];
Damien Zammit003d15c2015-11-20 17:17:51 +11002001 }
Angel Pons39ff7032020-03-09 21:39:44 +01002002 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002003
Angel Pons39ff7032020-03-09 21:39:44 +01002004 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11002005 do {
Angel Pons39ff7032020-03-09 21:39:44 +01002006 lane--;
2007 offset = lanecoarse[lane] - minlanecoarse;
2008 MCHBAR16_AND_OR(C0COARSEDLY0, (u16)(~(3 << (lane * 2))), offset << (lane * 2));
2009 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002010
Angel Pons39ff7032020-03-09 21:39:44 +01002011 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, minlanecoarse << 16);
Damien Zammit003d15c2015-11-20 17:17:51 +11002012
Angel Pons39ff7032020-03-09 21:39:44 +01002013 s->coarsectrl = minlanecoarse;
2014 s->coarsedelay = MCHBAR16(C0COARSEDLY0);
2015 s->mediumphase = MCHBAR16(C0RCVMISCCTL2);
2016 s->readptrdelay = MCHBAR16(C0RCVMISCCTL1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002017
2018 PRINTK_DEBUG("rcven 2\n");
Angel Pons39ff7032020-03-09 21:39:44 +01002019 MCHBAR8_AND(C0RSTCTL, ~0x0e);
2020 MCHBAR8_OR(C0RSTCTL, 0x02);
2021 MCHBAR8_OR(C0RSTCTL, 0x04);
2022 MCHBAR8_OR(C0RSTCTL, 0x08);
Damien Zammit003d15c2015-11-20 17:17:51 +11002023
Angel Pons39ff7032020-03-09 21:39:44 +01002024 MCHBAR8_OR(CMNDQFIFORST, 0x80);
2025 MCHBAR8_AND(CMNDQFIFORST, ~0x80);
2026 MCHBAR8_OR(CMNDQFIFORST, 0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11002027 PRINTK_DEBUG("rcven 3\n");
2028}
2029
Angel Pons39ff7032020-03-09 21:39:44 +01002030/* NOTE: Unless otherwise specified, the values are expressed in MiB */
Damien Zammit003d15c2015-11-20 17:17:51 +11002031static void sdram_mmap_regs(struct sysinfo *s)
2032{
2033 bool reclaim;
Angel Pons39ff7032020-03-09 21:39:44 +01002034 u32 mmiosize, tom, tolud, touud, reclaimbase, reclaimlimit;
2035 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase, tsegsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002036 u16 ggc;
Angel Pons39ff7032020-03-09 21:39:44 +01002037 u16 ggc_to_uma[10] = {0, 1, 4, 8, 16, 32, 48, 64, 128, 256};
2038 u8 ggc_to_gtt[4] = {0, 1, 0, 0};
Damien Zammit003d15c2015-11-20 17:17:51 +11002039
Angel Pons39ff7032020-03-09 21:39:44 +01002040 reclaimbase = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002041 reclaimlimit = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002042
2043 ggc = pci_read_config16(HOST_BRIDGE, GGC);
Damien Zammit51fdb922016-01-18 18:34:52 +11002044 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
Angel Pons39ff7032020-03-09 21:39:44 +01002045
2046 gfxsize = ggc_to_uma[(ggc & 0x00f0) >> 4];
2047
2048 gttsize = ggc_to_gtt[(ggc & 0x0300) >> 8];
2049
Damien Zammit003d15c2015-11-20 17:17:51 +11002050 tom = s->channel_capacity[0];
2051
Angel Pons39ff7032020-03-09 21:39:44 +01002052 /* With GTT always being 1M, TSEG 1M is the only setting that can
Arthur Heymansda44e342019-01-12 01:38:02 +01002053 be covered by SMRR which has alignment requirements. */
Angel Pons39ff7032020-03-09 21:39:44 +01002054 tsegsize = 1;
2055 mmiosize = 1024;
Damien Zammit003d15c2015-11-20 17:17:51 +11002056
2057 reclaim = false;
Angel Pons39ff7032020-03-09 21:39:44 +01002058 tolud = MIN(4096 - mmiosize, tom);
2059 if ((tom - tolud) > 64) {
Arthur Heymansaaebb412017-08-27 18:46:12 +02002060 reclaim = true;
Damien Zammit003d15c2015-11-20 17:17:51 +11002061 }
2062 if (reclaim) {
2063 tolud = tolud & ~0x3f;
Angel Pons39ff7032020-03-09 21:39:44 +01002064 tom = tom & ~0x3f;
2065 reclaimbase = MAX(4096, tom);
2066 reclaimlimit = reclaimbase + (MIN(4096, tom) - tolud) - 0x40;
Damien Zammit003d15c2015-11-20 17:17:51 +11002067 }
2068 touud = tom;
2069 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002070 touud = reclaimlimit + 64;
Damien Zammit003d15c2015-11-20 17:17:51 +11002071 }
2072
Angel Pons39ff7032020-03-09 21:39:44 +01002073 gfxbase = tolud - gfxsize;
2074 gttbase = gfxbase - gttsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002075 tsegbase = gttbase - tsegsize;
2076
2077 /* Program the regs */
Angel Pons39ff7032020-03-09 21:39:44 +01002078 pci_write_config16(HOST_BRIDGE, TOLUD, (u16)(tolud << 4));
2079 pci_write_config16(HOST_BRIDGE, TOM, (u16)(tom >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002080 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002081 pci_write_config16(HOST_BRIDGE, 0x98, (u16)(reclaimbase >> 6));
2082 pci_write_config16(HOST_BRIDGE, 0x9a, (u16)(reclaimlimit >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002083 }
Angel Pons39ff7032020-03-09 21:39:44 +01002084 pci_write_config16(HOST_BRIDGE, TOUUD, (u16)(touud));
2085 pci_write_config32(HOST_BRIDGE, GBSM, gfxbase << 20);
2086 pci_write_config32(HOST_BRIDGE, BGSM, gttbase << 20);
2087 pci_write_config32(HOST_BRIDGE, TSEG, tsegbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002088
Angel Pons39ff7032020-03-09 21:39:44 +01002089 u8 reg8 = pci_read_config8(HOST_BRIDGE, ESMRAMC);
2090 reg8 &= ~0x07;
Arthur Heymansda44e342019-01-12 01:38:02 +01002091 reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
Angel Pons39ff7032020-03-09 21:39:44 +01002092 pci_write_config8(HOST_BRIDGE, ESMRAMC, reg8);
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002093
Damien Zammit51fdb922016-01-18 18:34:52 +11002094 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002095 pci_read_config32(HOST_BRIDGE, GBSM), gfxbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002096 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002097 pci_read_config32(HOST_BRIDGE, BGSM), gttbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002098 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002099 pci_read_config32(HOST_BRIDGE, TSEG), tsegbase << 20);
Damien Zammit003d15c2015-11-20 17:17:51 +11002100}
2101
2102static void sdram_enhancedmode(struct sysinfo *s)
2103{
Angel Pons39ff7032020-03-09 21:39:44 +01002104 u8 reg8, ch, r, fsb_freq, ddr_freq;
Damien Zammit003d15c2015-11-20 17:17:51 +11002105 u32 mask32, reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002106 MCHBAR8_OR(C0ADDCSCTRL, 1);
2107 MCHBAR8_OR(C0REFRCTRL + 3, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002108 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
Angel Pons39ff7032020-03-09 21:39:44 +01002109 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2110 MCHBAR32_AND_OR(WRWMCONFIG, ~mask32, reg32);
2111 MCHBAR8(C0DITCTRL + 1) = 2;
2112 MCHBAR16(C0DITCTRL + 2) = 0x0804;
2113 MCHBAR16(C0DITCTRL + 4) = 0x2010;
2114 MCHBAR8(C0DITCTRL + 6) = 0x40;
2115 MCHBAR16(C0DITCTRL + 8) = 0x091c;
2116 MCHBAR8(C0DITCTRL + 10) = 0xf2;
2117 MCHBAR8_OR(C0BYPCTRL, 1);
2118 MCHBAR8_OR(C0CWBCTRL, 1);
2119 MCHBAR16_OR(C0ARBSPL, 0x0100);
Damien Zammit003d15c2015-11-20 17:17:51 +11002120
Angel Pons26766fd2020-06-08 12:38:19 +02002121 pci_or_config8(HOST_BRIDGE, 0xf0, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01002122 MCHBAR32(SBCTL) = 0x00000002;
2123 MCHBAR32(SBCTL2) = 0x20310002;
2124 MCHBAR32(SLIMCFGTMG) = 0x02020302;
2125 MCHBAR32(HIT0) = 0x001f1806;
2126 MCHBAR32(HIT1) = 0x01102800;
2127 MCHBAR32(HIT2) = 0x07000000;
2128 MCHBAR32(HIT3) = 0x01014010;
2129 MCHBAR32(HIT4) = 0x0f038000;
Angel Pons26766fd2020-06-08 12:38:19 +02002130 pci_and_config8(HOST_BRIDGE, 0xf0, ~1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002131
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002132 u32 nranks, curranksize, maxranksize, dra;
2133 u8 rankmismatch;
Angel Pons39ff7032020-03-09 21:39:44 +01002134 static const u8 drbtab[10] = {0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8, 0x20, 0x10};
Damien Zammit003d15c2015-11-20 17:17:51 +11002135
2136 nranks = 0;
2137 curranksize = 0;
2138 maxranksize = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002139 rankmismatch = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002140
Damien Zammit003d15c2015-11-20 17:17:51 +11002141 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2142 nranks++;
Angel Pons39ff7032020-03-09 21:39:44 +01002143 dra = (u8) ((MCHBAR32(C0DRA01) >> (8 * r)) & 0x7f);
Damien Zammit003d15c2015-11-20 17:17:51 +11002144 curranksize = drbtab[dra];
2145 if (maxranksize == 0) {
2146 maxranksize = curranksize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002147 }
2148 if (curranksize != maxranksize) {
2149 rankmismatch = 1;
2150 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002151 }
2152
2153 reg8 = 0;
2154 switch (nranks) {
2155 case 4:
2156 if (rankmismatch) {
2157 reg8 = 0x64;
2158 } else {
2159 reg8 = 0xa4;
2160 }
2161 break;
2162 case 1:
2163 case 3:
2164 reg8 = 0x64;
2165 break;
2166 case 2:
2167 if (rankmismatch) {
2168 reg8 = 0x64;
2169 } else {
2170 reg8 = 0x24;
2171 }
2172 break;
2173 default:
2174 die("Invalid number of ranks found, halt\n");
2175 break;
2176 }
Angel Pons39ff7032020-03-09 21:39:44 +01002177 MCHBAR8_AND_OR(CHDECMISC, ~0xfc, reg8 & 0xfc);
2178 MCHBAR32_AND(NOACFGBUSCTL, ~0x80000000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002179
Angel Pons39ff7032020-03-09 21:39:44 +01002180 MCHBAR32(HTBONUS0) = 0x0000000f;
2181 MCHBAR8_OR(C0COREBONUS + 4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002182
Angel Pons39ff7032020-03-09 21:39:44 +01002183 MCHBAR32_AND(HIT3, ~0x0e000000);
2184 MCHBAR32_AND_OR(HIT4, ~0x000c0000, 0x00040000);
2185
Damien Zammit003d15c2015-11-20 17:17:51 +11002186 u32 clkcx[2][2][3] = {
Angel Pons39ff7032020-03-09 21:39:44 +01002187 {
2188 {0x00000000, 0x0c080302, 0x08010204}, /* FSB = 667, DDR = 667 */
2189 {0x02040000, 0x08100102, 0x00000000}, /* FSB = 667, DDR = 800 */
2190 },
2191 {
2192 {0x18000000, 0x3021060c, 0x20010208}, /* FSB = 800, DDR = 667 */
2193 {0x00000000, 0x0c090306, 0x00000000}, /* FSB = 800, DDR = 800 */
2194 }
2195 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002196
Angel Pons39ff7032020-03-09 21:39:44 +01002197 fsb_freq = s->selected_timings.fsb_clock;
2198 ddr_freq = s->selected_timings.mem_clock;
2199
2200 MCHBAR32(CLKXSSH2X2MD) = clkcx[fsb_freq][ddr_freq][0];
2201 MCHBAR32(CLKXSSH2X2MD + 4) = clkcx[fsb_freq][ddr_freq][1];
2202 MCHBAR32(CLKXSSH2MCBYP + 4) = clkcx[fsb_freq][ddr_freq][2];
2203
2204 MCHBAR8_AND(HIT4, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11002205}
2206
2207static void sdram_periodic_rcomp(void)
2208{
Angel Pons39ff7032020-03-09 21:39:44 +01002209 MCHBAR8_AND(COMPCTRL1, ~0x02);
2210 while ((MCHBAR32(COMPCTRL1) & 0x80000000) > 0) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002211 ;
2212 }
Angel Pons39ff7032020-03-09 21:39:44 +01002213 MCHBAR16_AND(CSHRMISCCTL, ~0x3000);
2214 MCHBAR8_OR(CMNDQFIFORST, 0x80);
2215 MCHBAR16_AND_OR(XCOMPDFCTRL, ~0x0f, 0x09);
Damien Zammit003d15c2015-11-20 17:17:51 +11002216
Angel Pons39ff7032020-03-09 21:39:44 +01002217 MCHBAR8_OR(COMPCTRL1, 0x82);
Damien Zammit003d15c2015-11-20 17:17:51 +11002218}
2219
2220static void sdram_new_trd(struct sysinfo *s)
2221{
2222 u8 pidelay, i, j, k, cc, trd_perphase[5];
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002223 u8 bypass, freqgb, trd, reg8, txfifo;
Damien Zammit003d15c2015-11-20 17:17:51 +11002224 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2225 u16 tmclk, thclk, buffertocore, postcalib;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002226 static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2227 static const u16 trd_adjust[2][2][5] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11002228 {
2229 {3000, 3000, 0,0,0},
2230 {1000,2000,3000,1500,2500}
2231 },
2232 {
2233 {2000,1000,3000,0,0},
2234 {2500, 2500, 0,0,0}
2235 }};
2236
2237 freqgb = 110;
2238 buffertocore = 5000;
Damien Zammit003d15c2015-11-20 17:17:51 +11002239 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2240 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2241 tmclk = tmclk * 100 / freqgb;
2242 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2243 switch (s->selected_timings.mem_clock) {
2244 case MEM_CLOCK_667MHz:
2245 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2246 cc = 2;
2247 } else {
2248 cc = 3;
2249 }
2250 break;
2251 default:
2252 case MEM_CLOCK_800MHz:
2253 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2254 cc = 5;
2255 } else {
2256 cc = 2;
2257 }
2258 break;
2259 }
2260 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2261 maxrcvendelay = 0;
2262 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2263
2264 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01002265 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 3) * (u32)(tmclk));
2266 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 3) * (u32)(tmclk) / 2);
2267 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 3) * (u32)(tmclk) / 4);
2268 rcvendelay += (u32)(pidelay * s->pi[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002269 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2270 }
2271
Angel Pons39ff7032020-03-09 21:39:44 +01002272 if ((MCHBAR8(HMBYPCP + 3) == 0xff) && (MCHBAR8(HMCCMC) & 0x80)) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002273 bypass = 1;
2274 } else {
2275 bypass = 0;
2276 }
2277
2278 txfifo = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002279 reg8 = (MCHBAR8(CSHRFIFOCTL) & 0x0e) >> 1;
2280 txfifo = txfifo_lut[reg8] & 0x07;
Damien Zammit003d15c2015-11-20 17:17:51 +11002281
2282 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2283 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2284 if (s->async) {
2285 datadelay += tmclk / 2;
2286 }
2287
2288 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2289 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2290
2291 if (j == 0 && k == 0) {
2292 datadelay -= 3084;
2293 }
2294
2295 trd = 0;
2296 for (i = 0; i < cc; i++) {
2297 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2298 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2299 trd_perphase[i] += 1;
2300 if (trd_perphase[i] > trd) {
2301 trd = trd_perphase[i];
2302 }
2303 }
2304
Angel Pons39ff7032020-03-09 21:39:44 +01002305 MCHBAR16_AND_OR(C0STATRDCTRL, ~0x1f00, trd << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11002306}
2307
2308static void sdram_powersettings(struct sysinfo *s)
2309{
2310 u8 j;
2311 u32 reg32;
2312
2313 /* Thermal sensor */
Angel Pons39ff7032020-03-09 21:39:44 +01002314 MCHBAR8(TSC1) = 0x9b;
2315 MCHBAR32_AND_OR(TSTTP, ~0x00ffffff, 0x1d00);
2316 MCHBAR8(THERM1) = 0x08;
2317 MCHBAR8(TSC3) = 0x00;
2318 MCHBAR8_AND_OR(TSC2, ~0x0f, 0x04);
2319 MCHBAR8_AND_OR(THERM1, ~1, 1);
2320 MCHBAR8_AND_OR(TCO, ~0x80, 0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11002321
2322 /* Clock gating */
Angel Pons39ff7032020-03-09 21:39:44 +01002323 MCHBAR32_AND(PMMISC, ~0x00040001);
2324 MCHBAR8_AND(SBCTL3 + 3, ~0x80);
2325 MCHBAR8_AND(CISDCTRL + 3, ~0x80);
2326 MCHBAR16_AND(CICGDIS, ~0x1fff);
2327 MCHBAR32_AND(SBCLKGATECTRL, ~0x0001ffff);
2328 MCHBAR16_AND(HICLKGTCTL, ~0x03ff & 0x06);
2329 MCHBAR32_AND_OR(HTCLKGTCTL, ~0xffffffff, 0x20);
2330 MCHBAR8_AND(TSMISC, ~1);
2331 MCHBAR8(C0WRDPYN) = s->selected_timings.CAS - 1 + 0x15;
2332 MCHBAR16_AND_OR(CLOCKGATINGI, ~0x07fc, 0x0040);
2333 MCHBAR16_AND_OR(CLOCKGATINGII, ~0x0fff, 0x0d00);
2334 MCHBAR16_AND(CLOCKGATINGIII, ~0x0d80);
2335 MCHBAR16(GTDPCGC + 2) = 0xffff;
Damien Zammit003d15c2015-11-20 17:17:51 +11002336
2337 /* Sequencing */
Angel Pons39ff7032020-03-09 21:39:44 +01002338 MCHBAR32(HPWRCTL1) = (MCHBAR32(HPWRCTL1) & ~0x1fffffff) | 0x1f643fff;
2339 MCHBAR32(HPWRCTL2) = (MCHBAR32(HPWRCTL2) & ~0xffffff7f) | 0x02010000;
2340 MCHBAR16(HPWRCTL3) = (MCHBAR16(HPWRCTL3) & ~0x7000) | (3 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11002341
2342 /* Power */
Angel Pons39ff7032020-03-09 21:39:44 +01002343 MCHBAR32(GFXC3C4) = (MCHBAR32(GFXC3C4) & ~0xffff0003) | 0x10100000;
2344 MCHBAR32(PMDSLFRC) = (MCHBAR32(PMDSLFRC) & ~0x0001bff7) | 0x00000078;
2345
2346 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz)
2347 MCHBAR16_AND_OR(PMMSPMRES, ~0x03ff, 0x00c8);
2348 else
2349 MCHBAR16_AND_OR(PMMSPMRES, ~0x03ff, 0x0100);
2350
Damien Zammit003d15c2015-11-20 17:17:51 +11002351 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2352
Angel Pons39ff7032020-03-09 21:39:44 +01002353 MCHBAR32_AND_OR(PMCLKRC, ~0x01fff37f, 0x10810700);
2354 MCHBAR8_AND_OR(PMPXPRC, ~0x07, 1);
2355 MCHBAR8_AND(PMBAK, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11002356
Angel Pons39ff7032020-03-09 21:39:44 +01002357 static const u16 ddr2lut[2][4][2] = {
2358 {
2359 {0x0000, 0x0000},
2360 {0x019A, 0x0039},
2361 {0x0099, 0x1049},
2362 {0x0000, 0x0000},
2363 },
2364 {
2365 {0x0000, 0x0000},
2366 {0x019A, 0x0039},
2367 {0x0099, 0x1049},
2368 {0x0099, 0x2159},
2369 },
2370 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002371
Angel Pons39ff7032020-03-09 21:39:44 +01002372 MCHBAR16(C0C2REG) = 0x7a89;
2373 MCHBAR8(SHC2REGII) = 0xaa;
2374 MCHBAR16(SHC2REGII + 1) = ddr2lut[j][s->selected_timings.CAS - 3][1];
2375 MCHBAR16_AND_OR(SHC2REGI, ~0x7fff, ddr2lut[j][s->selected_timings.CAS - 3][0]);
2376 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0xf000, 0xf000);
2377 MCHBAR8(CSHWRIOBONUSX) = (MCHBAR8(CSHWRIOBONUSX) & ~0x77) | (4 << 4 | 4);
Damien Zammit003d15c2015-11-20 17:17:51 +11002378
Angel Pons39ff7032020-03-09 21:39:44 +01002379 reg32 = s->nodll ? 0x30000000 : 0;
2380
2381 /* FIXME: Compacting this results in changes to the binary */
2382 MCHBAR32(C0COREBONUS) = (MCHBAR32(C0COREBONUS) & ~0x0f000000) | 0x20000000 | reg32;
2383
2384 MCHBAR32_AND_OR(CLOCKGATINGI, ~0x00f00000, 0x00f00000);
2385 MCHBAR32_AND_OR(CLOCKGATINGII - 1, ~0x001ff000, 0xbf << 20);
2386 MCHBAR16_AND_OR(SHC3C4REG2, ~0x1f7f, (0x0b << 8) | (7 << 4) | 0x0b);
2387 MCHBAR16(SHC3C4REG3) = 0x3264;
2388 MCHBAR16_AND_OR(SHC3C4REG4, ~0x3f3f, (0x14 << 8) | 0x0a);
2389
2390 MCHBAR32_OR(C1COREBONUS, 0x80002000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002391}
2392
2393static void sdram_programddr(void)
2394{
Angel Pons39ff7032020-03-09 21:39:44 +01002395 MCHBAR16_AND_OR(CLOCKGATINGII, ~0x03ff, 0x0100);
2396 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0x003f, 0x0010);
2397 MCHBAR16_AND_OR(CLOCKGATINGI, ~0x7000, 0x2000);
2398
2399 MCHBAR8_AND(CSHRPDCTL, ~0x0e);
2400 MCHBAR8_AND(CSHRWRIOMLNS, ~0x0c);
2401 MCHBAR8_AND(C0MISCCTLy(0), ~0x0e);
2402 MCHBAR8_AND(C0MISCCTLy(1), ~0x0e);
2403 MCHBAR8_AND(C0MISCCTLy(2), ~0x0e);
2404 MCHBAR8_AND(C0MISCCTLy(3), ~0x0e);
2405 MCHBAR8_AND(C0MISCCTLy(4), ~0x0e);
2406 MCHBAR8_AND(C0MISCCTLy(5), ~0x0e);
2407 MCHBAR8_AND(C0MISCCTLy(6), ~0x0e);
2408 MCHBAR8_AND(C0MISCCTLy(7), ~0x0e);
2409 MCHBAR8_AND(CSHRWRIOMLNS, ~0x02);
2410
2411 MCHBAR16_AND(CSHRMISCCTL, ~0x0400);
2412 MCHBAR16_AND(CLOCKGATINGIII, ~0x0dc0);
2413 MCHBAR8_AND(C0WRDPYN, ~0x80);
2414 MCHBAR32_AND(C0COREBONUS, ~(1 << 22));
2415 MCHBAR16_AND(CLOCKGATINGI, ~0x80fc);
2416 MCHBAR16_AND(CLOCKGATINGII, ~0x0c00);
2417
2418 MCHBAR8_AND(CSHRPDCTL, ~0x0d);
2419 MCHBAR8_AND(C0MISCCTLy(0), ~1);
2420 MCHBAR8_AND(C0MISCCTLy(1), ~1);
2421 MCHBAR8_AND(C0MISCCTLy(2), ~1);
2422 MCHBAR8_AND(C0MISCCTLy(3), ~1);
2423 MCHBAR8_AND(C0MISCCTLy(4), ~1);
2424 MCHBAR8_AND(C0MISCCTLy(5), ~1);
2425 MCHBAR8_AND(C0MISCCTLy(6), ~1);
2426 MCHBAR8_AND(C0MISCCTLy(7), ~1);
2427
2428 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x00700000, 3 << 20);
2429 MCHBAR32_AND(C0COREBONUS, ~0x00100000);
2430 MCHBAR8_OR(C0DYNSLVDLLEN, 0x1e);
2431 MCHBAR8_OR(C0DYNSLVDLLEN2, 0x03);
2432 MCHBAR32_AND_OR(SHCYCTRKCKEL, ~0x0c000000, 0x04000000);
2433 MCHBAR16_OR(C0STATRDCTRL, 0x6000);
2434 MCHBAR32_OR(C0CKECTRL, 0x00010000);
2435 MCHBAR8_OR(C0COREBONUS, 0x10);
2436 MCHBAR32_OR(CLOCKGATINGI - 1, 0xf << 24);
2437 MCHBAR8_OR(CSHWRIOBONUS, 0x07);
2438 MCHBAR8_OR(C0DYNSLVDLLEN, 0xc0);
2439 MCHBAR8_OR(SHC2REGIII, 7);
2440 MCHBAR16_AND_OR(SHC2MINTM, ~0xffff, 0x0080);
2441 MCHBAR8_AND_OR(SHC2IDLETM, ~0xff, 0x10);
2442 MCHBAR16_OR(C0COREBONUS, 0x01e0);
2443 MCHBAR8_OR(CSHWRIOBONUS, 0x18);
2444 MCHBAR8_OR(CSHRMSTDYNDLLENB, 0x0d);
2445 MCHBAR16_OR(SHC3C4REG1, 0x0a3f);
2446 MCHBAR8_OR(C0STATRDCTRL, 3);
2447 MCHBAR8_AND_OR(C0REFRCTRL2, ~0xff, 0x4a);
2448 MCHBAR8_AND(C0COREBONUS + 4, ~0x60);
2449 MCHBAR16_OR(C0DYNSLVDLLEN, 0x0321);
Damien Zammit003d15c2015-11-20 17:17:51 +11002450}
2451
2452static void sdram_programdqdqs(struct sysinfo *s)
2453{
2454 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2455 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2456 u8 repeat, halfclk, feature, reg8, push;
2457 u16 cwb, pimdclk;
2458 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002459 static const u8 txfifotab[8] = {0, 7, 6, 5, 2, 1, 4, 3};
Damien Zammit003d15c2015-11-20 17:17:51 +11002460
2461 tpi = 3000;
2462 dqdqs_out = 4382;
2463 dqdqs_outdelay = 5083;
2464 dqdqs_delay = 4692;
2465 coretomcp = 0;
2466 txdelay = 0;
2467 halfclk = 0;
2468 tmaxunmask = 0;
2469 tmaxpi = 0;
2470 repeat = 2;
2471 feature = 0;
2472 cwb = 0;
2473 pimdclk = 0;
2474 reg32 = 0;
2475 push = 0;
2476 reg8 = 0;
2477
2478 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2479 refclk = 3000 - mdclk;
2480
Angel Pons39ff7032020-03-09 21:39:44 +01002481 coretomcp = ((MCHBAR8(C0ADDCSCTRL) >> 2) & 0x3) + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002482 coretomcp *= mdclk;
2483
Angel Pons39ff7032020-03-09 21:39:44 +01002484 reg8 = (MCHBAR8(CSHRFIFOCTL) & 0x0e) >> 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002485
2486 while (repeat) {
2487 txdelay = mdclk * (
Angel Pons39ff7032020-03-09 21:39:44 +01002488 ((MCHBAR16(C0GNT2LNCH1) >> 8) & 0x7) +
2489 (MCHBAR8(C0WRDATACTRL) & 0xf) +
2490 (MCHBAR8(C0WRDATACTRL + 1) & 0x1)
Damien Zammit003d15c2015-11-20 17:17:51 +11002491 ) +
Angel Pons39ff7032020-03-09 21:39:44 +01002492 txfifotab[reg8]*(mdclk / 2) +
Damien Zammit003d15c2015-11-20 17:17:51 +11002493 coretomcp +
2494 refclk +
2495 cwb;
Angel Pons39ff7032020-03-09 21:39:44 +01002496 halfclk = (MCHBAR8(C0MISCCTL) >> 1) & 0x1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002497 if (halfclk) {
2498 txdelay -= mdclk / 2;
2499 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2500 } else {
2501 reg32 = dqdqs_outdelay + coretomcp;
2502 }
2503
2504 tmaxunmask = txdelay - mdclk - dqdqs_out;
2505 tmaxpi = tmaxunmask - tpi;
2506
2507 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2508 if (repeat == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01002509 MCHBAR32_AND(C0COREBONUS, ~(1 << 23));
Damien Zammit003d15c2015-11-20 17:17:51 +11002510 }
2511 feature = 1;
2512 repeat = 0;
2513 } else {
2514 repeat--;
Angel Pons39ff7032020-03-09 21:39:44 +01002515 MCHBAR32_OR(C0COREBONUS, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +11002516 cwb = 2 * mdclk;
2517 }
2518 }
2519
2520 if (!feature) {
Angel Pons39ff7032020-03-09 21:39:44 +01002521 MCHBAR8(CLOCKGATINGI) = MCHBAR8(CLOCKGATINGI) & ~0x3;
Damien Zammit003d15c2015-11-20 17:17:51 +11002522 return;
2523 }
Angel Pons39ff7032020-03-09 21:39:44 +01002524 MCHBAR8_OR(CLOCKGATINGI, 3);
2525 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0xf000, pimdclk << 12);
2526 MCHBAR8_AND_OR(CSHWRIOBONUSX, ~0x77, (push << 4) | push);
2527 MCHBAR32_AND_OR(C0COREBONUS, ~0x0f000000, 0x03000000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002528}
2529
2530/**
2531 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2532 */
2533void sdram_initialize(int boot_path, const u8 *spd_addresses)
2534{
2535 struct sysinfo si;
Angel Pons39ff7032020-03-09 21:39:44 +01002536 const char *boot_str[] = {"Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002537
2538 PRINTK_DEBUG("Setting up RAM controller.\n");
2539
2540 memset(&si, 0, sizeof(si));
2541
2542 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002543 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002544 si.spd_map[0] = spd_addresses[0];
2545 si.spd_map[1] = spd_addresses[1];
2546 si.spd_map[2] = spd_addresses[2];
2547 si.spd_map[3] = spd_addresses[3];
2548
2549 sdram_read_spds(&si);
2550
2551 /* Choose Common Frequency */
2552 sdram_detect_ram_speed(&si);
2553
2554 /* Determine smallest common tRAS, tRP, tRCD, etc */
2555 sdram_detect_smallest_params(&si);
2556
2557 /* Enable HPET */
2558 enable_hpet();
Damien Zammit003d15c2015-11-20 17:17:51 +11002559
Angel Pons39ff7032020-03-09 21:39:44 +01002560 MCHBAR16_OR(CPCTL, 1 << 15);
Damien Zammit003d15c2015-11-20 17:17:51 +11002561
Damien Zammit003d15c2015-11-20 17:17:51 +11002562 sdram_clk_crossing(&si);
2563
2564 sdram_checkreset();
2565 PRINTK_DEBUG("Done checkreset\n");
2566
2567 sdram_clkmode(&si);
2568 PRINTK_DEBUG("Done clkmode\n");
2569
2570 sdram_timings(&si);
2571 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2572
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002573 if (si.boot_path != BOOT_PATH_RESET) {
2574 sdram_dlltiming(&si);
2575 PRINTK_DEBUG("Done dlltiming\n");
2576 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002577
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002578 if (si.boot_path != BOOT_PATH_RESET) {
2579 sdram_rcomp(&si);
2580 PRINTK_DEBUG("Done RCOMP\n");
2581 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002582
2583 sdram_odt(&si);
2584 PRINTK_DEBUG("Done odt\n");
2585
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002586 if (si.boot_path != BOOT_PATH_RESET) {
Angel Pons39ff7032020-03-09 21:39:44 +01002587 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002588 ;
2589 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002590
2591 sdram_mmap(&si);
2592 PRINTK_DEBUG("Done mmap\n");
2593
Angel Pons39ff7032020-03-09 21:39:44 +01002594 /* Enable DDR IO buffer */
2595 MCHBAR8_AND_OR(C0IOBUFACTCTL, ~0x3f, 0x08);
2596 MCHBAR8_OR(C0RSTCTL, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002597
2598 sdram_rcompupdate(&si);
2599 PRINTK_DEBUG("Done RCOMP update\n");
2600
Angel Pons39ff7032020-03-09 21:39:44 +01002601 MCHBAR8_OR(HIT4, 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11002602
2603 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01002604 MCHBAR32_OR(C0CKECTRL, 1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002605
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002606 sdram_jedecinit(&si);
2607 PRINTK_DEBUG("Done MRS\n");
2608 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002609
2610 sdram_misc(&si);
2611 PRINTK_DEBUG("Done misc\n");
2612
2613 sdram_zqcl(&si);
2614 PRINTK_DEBUG("Done zqcl\n");
2615
2616 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01002617 MCHBAR32_OR(C0REFRCTRL2, 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002618 }
2619
2620 sdram_dradrb(&si);
2621 PRINTK_DEBUG("Done dradrb\n");
2622
2623 sdram_rcven(&si);
2624 PRINTK_DEBUG("Done rcven\n");
2625
2626 sdram_new_trd(&si);
2627 PRINTK_DEBUG("Done tRD\n");
2628
2629 sdram_mmap_regs(&si);
2630 PRINTK_DEBUG("Done mmap regs\n");
2631
2632 sdram_enhancedmode(&si);
2633 PRINTK_DEBUG("Done enhanced mode\n");
2634
2635 sdram_powersettings(&si);
2636 PRINTK_DEBUG("Done power settings\n");
2637
2638 sdram_programddr();
2639 PRINTK_DEBUG("Done programming ddr\n");
2640
2641 sdram_programdqdqs(&si);
2642 PRINTK_DEBUG("Done programming dqdqs\n");
2643
2644 sdram_periodic_rcomp();
2645 PRINTK_DEBUG("Done periodic RCOMP\n");
2646
2647 /* Set init done */
Angel Pons39ff7032020-03-09 21:39:44 +01002648 MCHBAR32_OR(C0REFRCTRL2, 1 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002649
2650 /* Tell ICH7 that we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002651 pci_and_config8(PCI_DEV(0, 0x1f, 0), 0xa2, (u8)~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11002652
2653 /* Tell northbridge we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002654 pci_or_config8(HOST_BRIDGE, 0xf4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002655
2656 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2657}