blob: 680f3c901be26ed3333191148335366cee8e7373 [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 Pons94eea6f2021-02-06 15:03:48 +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 Pons94eea6f2021-02-06 15:03:48 +0100542 {0x1f1f1f1f, 0x0d07070b, 0x00000000, 0x00000000}, /* FSB = 800, DDR = 667 */
543 {0xffffffff, 0x05030305, 0x0000ffff, 0x00000000}, /* FSB = 800, DDR = 800 */
Angel Pons39ff7032020-03-09 21:39:44 +0100544 },
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 Pons94eea6f2021-02-06 15:03:48 +0100623 {0x00000000, 0x00030100, 0x0c240201, 0x00000000}, /* DDR = 667 */
624 {0x00000000, 0x00030100, 0x0c240201, 0x10450302} /* DDR = 800 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100625 };
626
Angel Pons39ff7032020-03-09 21:39:44 +0100627 MCHBAR32(C0GNT2LNCH2) = cas_to_reg[ddr_freq][s->selected_timings.CAS - 3];
Damien Zammit003d15c2015-11-20 17:17:51 +1100628}
629
630static void sdram_timings(struct sysinfo *s)
631{
632 u8 i, j, ch, r, ta1, ta2, ta3, ta4, trp, bank, page, flag;
633 u8 reg8, wl;
634 u16 reg16;
635 u32 reg32, reg2;
Damien Zammit003d15c2015-11-20 17:17:51 +1100636
Angel Pons39ff7032020-03-09 21:39:44 +0100637 static const u8 pagetab[2][2] = {
638 {0x0e, 0x12},
639 {0x10, 0x14},
640 };
641
642 /* Only consider DDR2 */
643 wl = s->selected_timings.CAS - 1;
644 ta1 = ta2 = 6;
645 ta3 = s->selected_timings.CAS;
646 ta4 = 8;
Damien Zammit003d15c2015-11-20 17:17:51 +1100647 s->selected_timings.tRFC = (s->selected_timings.tRFC + 1) & 0xfe;
Angel Pons39ff7032020-03-09 21:39:44 +0100648 trp = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100649 bank = 1;
650 page = 0;
651
Angel Pons39ff7032020-03-09 21:39:44 +0100652 MCHBAR8(C0LATCTRL) = ((wl - 3) << 4) | (s->selected_timings.CAS - 3);
Damien Zammit003d15c2015-11-20 17:17:51 +1100653
654 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
655 i = ch << 1;
656 if (s->dimms[i].banks == 1) {
657 trp = 1;
658 bank = 0;
659 }
660 if (s->dimms[i].page_size == 2048) {
661 page = 1;
662 }
663 }
664 PRINTK_DEBUG("trp=%d bank=%d page=%d\n",trp, bank, page);
665
666 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
667 flag = 0;
668 } else {
669 flag = 1;
670 }
671
Angel Pons39ff7032020-03-09 21:39:44 +0100672 MCHBAR8_OR(C0PVCFG, 0x03);
673 MCHBAR16(C0CYCTRKPCHG) = ((wl + 4 + s->selected_timings.tWR) << 6) |
674 ((2 + MAX(s->selected_timings.tRTP, 2)) << 2) | 1;
675
Damien Zammit003d15c2015-11-20 17:17:51 +1100676 reg32 = (bank << 21) | (s->selected_timings.tRRD << 17) |
Angel Pons39ff7032020-03-09 21:39:44 +0100677 (s->selected_timings.tRP << 13) | ((s->selected_timings.tRP + trp) << 9) |
678 s->selected_timings.tRFC;
679
Damien Zammit003d15c2015-11-20 17:17:51 +1100680 if (bank == 0) {
681 reg32 |= (pagetab[flag][page] << 22);
682 }
Angel Pons39ff7032020-03-09 21:39:44 +0100683 /* FIXME: Why not do a single dword write? */
684 MCHBAR16(C0CYCTRKACT) = (u16) (reg32);
685 MCHBAR16(C0CYCTRKACT + 2) = (u16) (reg32 >> 16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100686
Angel Pons39ff7032020-03-09 21:39:44 +0100687 /* FIXME: Only applies to DDR2 */
688 reg16 = (MCHBAR16(C0CYCTRKACT + 2) & 0x0fc0) >> 6;
689 MCHBAR16_AND_OR(SHCYCTRKCKEL, ~0x1f80, (reg16 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +1100690
691 reg16 = (s->selected_timings.tRCD << 12) | (4 << 8) | (ta2 << 4) | ta4;
Angel Pons39ff7032020-03-09 21:39:44 +0100692 MCHBAR16(C0CYCTRKWR) = reg16;
Damien Zammit003d15c2015-11-20 17:17:51 +1100693
Angel Pons39ff7032020-03-09 21:39:44 +0100694 reg32 = (s->selected_timings.tRCD << 17) | ((wl + 4 + s->selected_timings.tWTR) << 12) |
Damien Zammit003d15c2015-11-20 17:17:51 +1100695 (ta3 << 8) | (4 << 4) | ta1;
Angel Pons39ff7032020-03-09 21:39:44 +0100696 MCHBAR32(C0CYCTRKRD) = reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +1100697
Angel Pons39ff7032020-03-09 21:39:44 +0100698 reg16 = ((s->selected_timings.tRP + trp) << 9) | s->selected_timings.tRFC;
Damien Zammit003d15c2015-11-20 17:17:51 +1100699
Angel Pons39ff7032020-03-09 21:39:44 +0100700 /* FIXME: Why not do a single word write? */
701 MCHBAR8(C0CYCTRKREFR) = (u8) (reg16);
702 MCHBAR8(C0CYCTRKREFR + 1) = (u8) (reg16 >> 8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100703
Angel Pons39ff7032020-03-09 21:39:44 +0100704 MCHBAR16_AND_OR(C0CKECTRL, ~0x03fe, 100 << 1);
705 MCHBAR8_AND_OR(C0CYCTRKPCHG2, ~0x3f, s->selected_timings.tRAS);
706 MCHBAR16(C0ARBCTRL) = 0x2310;
707 MCHBAR8_AND_OR(C0ADDCSCTRL, ~0x1f, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +1100708
709 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
710 reg32 = 3000;
711 } else {
712 reg32 = 2500;
713 }
714 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
715 reg2 = 6000;
716 } else {
717 reg2 = 5000;
718 }
Angel Pons39ff7032020-03-09 21:39:44 +0100719 reg16 = (u16)((((s->selected_timings.CAS + 7) * (reg32)) / reg2) << 8);
720 MCHBAR16_AND_OR(C0STATRDCTRL, ~0x1f00, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100721
722 flag = 0;
723 if (wl > 2) {
724 flag = 1;
725 }
726 reg16 = (u8) (wl - 1 - flag);
727 reg16 |= reg16 << 4;
728 reg16 |= flag << 8;
Angel Pons39ff7032020-03-09 21:39:44 +0100729 MCHBAR16_AND_OR(C0WRDATACTRL, ~0x01ff, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100730
Angel Pons39ff7032020-03-09 21:39:44 +0100731 MCHBAR16(C0RDQCTRL) = 0x1585;
732 MCHBAR8_AND(C0PWLRCTRL, ~0x1f);
733
734 /* rdmodwr_window[5..0] = CL+4+5 265[13..8] (264[21..16]) */
735 MCHBAR16_AND_OR(C0PWLRCTRL, ~0x3f00, (s->selected_timings.CAS + 9) << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100736
737 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +0100738 reg16 = 0x0514;
739 reg32 = 0x0a28;
Damien Zammit003d15c2015-11-20 17:17:51 +1100740 } else {
Angel Pons39ff7032020-03-09 21:39:44 +0100741 reg16 = 0x0618;
742 reg32 = 0x0c30;
Damien Zammit003d15c2015-11-20 17:17:51 +1100743 }
Angel Pons39ff7032020-03-09 21:39:44 +0100744 MCHBAR32_AND_OR(C0REFRCTRL2, ~0x0fffff00, (0x3f << 22) | (reg32 << 8));
Damien Zammit003d15c2015-11-20 17:17:51 +1100745
Angel Pons39ff7032020-03-09 21:39:44 +0100746 /* FIXME: Is this weird access necessary? Reference code does it */
747 MCHBAR8(C0REFRCTRL + 3) = 0;
748 MCHBAR16_AND_OR(C0REFCTRL, 0xc000, reg16);
749
750 /* NPUT Static Mode */
751 MCHBAR8_OR(C0DYNRDCTRL, 1);
752
753 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x7f000000, 0xb << 25);
Damien Zammit003d15c2015-11-20 17:17:51 +1100754 i = s->selected_timings.mem_clock;
755 j = s->selected_timings.fsb_clock;
756 if (i > j) {
Angel Pons39ff7032020-03-09 21:39:44 +0100757 MCHBAR32_OR(C0STATRDCTRL, 1 << 24);
Damien Zammit003d15c2015-11-20 17:17:51 +1100758 }
759
Angel Pons39ff7032020-03-09 21:39:44 +0100760 MCHBAR8_AND(C0RDFIFOCTRL, ~0x3);
761 MCHBAR16_AND_OR(C0WRDATACTRL, ~0x7c00, (wl + 10) << 10);
762 MCHBAR32_AND_OR(C0CKECTRL, ~0x070e0000, (3 << 24) | (3 << 17));
Damien Zammit003d15c2015-11-20 17:17:51 +1100763 reg16 = 0x15 << 6;
764 reg16 |= 0x1f;
765 reg16 |= (0x6 << 12);
Angel Pons39ff7032020-03-09 21:39:44 +0100766 MCHBAR16_AND_OR(C0REFRCTRL + 4, ~0x7fff, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100767
Angel Pons39ff7032020-03-09 21:39:44 +0100768 reg32 = (0x6 << 27) | (1 << 25); /* FIXME: For DDR3, set BIT26 as well */
769 MCHBAR32_AND_OR(C0REFRCTRL2, ~0x30000000, reg32 << 8);
770 MCHBAR8_AND_OR(C0REFRCTRL + 3, ~0xfa, reg32 >> 24);
771 MCHBAR8_AND(C0JEDEC, ~(1 << 7));
772 MCHBAR8_AND(C0DYNRDCTRL, ~0x6);
Damien Zammit003d15c2015-11-20 17:17:51 +1100773
Angel Pons39ff7032020-03-09 21:39:44 +0100774 /* Note: This is a 64-bit register, [34..30] = 0b00110 is split across two writes */
775 reg32 = ((6 & 3) << 30) | (4 << 25) | (1 << 20) | (8 << 15) | (6 << 10) | (4 << 5) | 1;
776 MCHBAR32(C0WRWMFLSH) = reg32;
777 MCHBAR16_AND_OR(C0WRWMFLSH + 4, ~0x1ff, (8 << 3) | (6 >> 2));
778 MCHBAR16_OR(SHPENDREG, 0x1c00 | (0x1f << 5));
779
780 /* FIXME: Why not do a single word write? */
781 MCHBAR8_AND_OR(SHPAGECTRL, ~0xff, 0x40);
782 MCHBAR8_AND_OR(SHPAGECTRL + 1, ~0x07, 0x05);
783 MCHBAR8_OR(SHCMPLWRCMD, 0x1f);
784
785 reg8 = (3 << 6);
Damien Zammit003d15c2015-11-20 17:17:51 +1100786 reg8 |= (s->dt0mode << 4);
787 reg8 |= 0x0c;
Angel Pons39ff7032020-03-09 21:39:44 +0100788 MCHBAR8_AND_OR(SHBONUSREG, ~0xdf, reg8);
789 MCHBAR8_AND(CSHRWRIOMLNS, ~0x02);
790 MCHBAR8_AND_OR(C0MISCTM, ~0x07, 0x02);
791 MCHBAR16_AND_OR(C0BYPCTRL, ~0x3fc, 4 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +1100792
Angel Pons39ff7032020-03-09 21:39:44 +0100793 /* [31..29] = 0b010 for kN = 2 (2N) */
794 reg32 = (2 << 29) | (1 << 28) | (1 << 23);
795 MCHBAR32_AND_OR(WRWMCONFIG, ~0xffb00000, reg32);
796
797 reg8 = (u8) ((MCHBAR16(C0CYCTRKACT) & 0xe000) >> 13);
798 reg8 |= (u8) ((MCHBAR16(C0CYCTRKACT + 2) & 1) << 3);
799 MCHBAR8_AND_OR(BYPACTSF, ~0xf0, reg8 << 4);
800
801 reg8 = (u8) ((MCHBAR32(C0CYCTRKRD) & 0x000f0000) >> 17);
802 MCHBAR8_AND_OR(BYPACTSF, ~0x0f, reg8);
803
804 /* FIXME: Why not clear everything at once? */
805 MCHBAR8_AND(BYPKNRULE, ~0xfc);
806 MCHBAR8_AND(BYPKNRULE, ~0x03);
807 MCHBAR8_AND(SHBONUSREG, ~0x03);
808 MCHBAR8_OR(C0BYPCTRL, 1);
809 MCHBAR16_OR(CSHRMISCCTL1, 1 << 9);
810
Damien Zammit003d15c2015-11-20 17:17:51 +1100811 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +0100812 /* FIXME: Hardcoded for DDR2 SO-DIMMs */
813 MCHBAR32_AND_OR(C0DLLRCVCTLy(i), ~0x3f3f3f3f, 0x0c0c0c0c);
Damien Zammit003d15c2015-11-20 17:17:51 +1100814 }
Angel Pons39ff7032020-03-09 21:39:44 +0100815 /* RDCS to RCVEN delay: Program coarse common to all bytelanes to default tCL + 1 */
816 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, (s->selected_timings.CAS + 1) << 16);
817
818 /* Program RCVEN delay with DLL-safe settings */
Damien Zammit003d15c2015-11-20 17:17:51 +1100819 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +0100820 MCHBAR8_AND(C0RXRCVyDLL(i), ~0x3f);
821 MCHBAR16_AND(C0RCVMISCCTL2, (u16) ~(3 << (i * 2)));
822 MCHBAR16_AND(C0RCVMISCCTL1, (u16) ~(3 << (i * 2)));
823 MCHBAR16_AND(C0COARSEDLY0, (u16) ~(3 << (i * 2)));
Damien Zammit003d15c2015-11-20 17:17:51 +1100824 }
Angel Pons39ff7032020-03-09 21:39:44 +0100825 MCHBAR8_AND(C0DLLPIEN, ~1); /* Power up receiver */
826 MCHBAR8_OR(C0DLLPIEN, 2); /* Enable RCVEN DLL */
827 MCHBAR8_OR(C0DLLPIEN, 4); /* Enable receiver DQS DLL */
828 MCHBAR32_OR(C0COREBONUS, 0x000c0400);
829 MCHBAR32_OR(C0CMDTX1, 1 << 31);
Damien Zammit003d15c2015-11-20 17:17:51 +1100830}
831
Angel Pons39ff7032020-03-09 21:39:44 +0100832/* Program clkset0's register for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200833static void sdram_p_clkset0(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100834{
Angel Pons39ff7032020-03-09 21:39:44 +0100835 MCHBAR16_AND_OR(C0CKTX, ~0xc440,
Damien Zammit003d15c2015-11-20 17:17:51 +1100836 (pll->clkdelay[f][i] << 14) |
837 (pll->dben[f][i] << 10) |
Angel Pons39ff7032020-03-09 21:39:44 +0100838 (pll->dbsel[f][i] << 6));
839
840 MCHBAR8_AND_OR(C0TXCK0DLL, ~0x3f, pll->pi[f][i]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100841}
842
Angel Pons39ff7032020-03-09 21:39:44 +0100843/* Program clkset1's register for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200844static void sdram_p_clkset1(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100845{
Angel Pons39ff7032020-03-09 21:39:44 +0100846 /* FIXME: This is actually a dword write! */
847 MCHBAR16_AND_OR(C0CKTX, ~0x00030880,
Damien Zammit003d15c2015-11-20 17:17:51 +1100848 (pll->clkdelay[f][i] << 16) |
849 (pll->dben[f][i] << 11) |
Angel Pons39ff7032020-03-09 21:39:44 +0100850 (pll->dbsel[f][i] << 7));
851
852 MCHBAR8_AND_OR(C0TXCK1DLL, ~0x3f, pll->pi[f][i]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100853}
854
Angel Pons39ff7032020-03-09 21:39:44 +0100855/* Program CMD0 and CMD1 registers for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200856static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100857{
858 u8 reg8;
Angel Pons39ff7032020-03-09 21:39:44 +0100859 /* Clock Group Index 3 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100860 reg8 = pll->dbsel[f][i] << 5;
861 reg8 |= pll->dben[f][i] << 6;
Angel Pons39ff7032020-03-09 21:39:44 +0100862 MCHBAR8_AND_OR(C0CMDTX1, ~0x60, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100863
864 reg8 = pll->clkdelay[f][i] << 4;
Angel Pons39ff7032020-03-09 21:39:44 +0100865 MCHBAR8_AND_OR(C0CMDTX2, ~0x30, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100866
867 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100868 MCHBAR8_AND_OR(C0TXCMD0DLL, ~0x3f, reg8);
869 MCHBAR8_AND_OR(C0TXCMD1DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100870}
871
Angel Pons39ff7032020-03-09 21:39:44 +0100872/* Program CTRL registers for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200873static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100874{
875 u8 reg8;
876 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +0100877
878 /* CTRL0 and CTRL1 */
879 reg32 = ((u32) pll->dbsel[f][i]) << 20;
880 reg32 |= ((u32) pll->dben[f][i]) << 21;
Damien Zammit003d15c2015-11-20 17:17:51 +1100881 reg32 |= ((u32) pll->dbsel[f][i]) << 22;
Angel Pons39ff7032020-03-09 21:39:44 +0100882 reg32 |= ((u32) pll->dben[f][i]) << 23;
Damien Zammit003d15c2015-11-20 17:17:51 +1100883 reg32 |= ((u32) pll->clkdelay[f][i]) << 24;
884 reg32 |= ((u32) pll->clkdelay[f][i]) << 27;
Angel Pons39ff7032020-03-09 21:39:44 +0100885 MCHBAR32_AND_OR(C0CTLTX2, ~0x01bf0000, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100886
887 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100888 MCHBAR8_AND_OR(C0TXCTL0DLL, ~0x3f, reg8);
889 MCHBAR8_AND_OR(C0TXCTL1DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100890
Angel Pons39ff7032020-03-09 21:39:44 +0100891 /* CTRL2 and CTRL3 */
892 reg32 = ((u32) pll->dbsel[f][i]) << 12;
893 reg32 |= ((u32) pll->dben[f][i]) << 13;
Damien Zammit003d15c2015-11-20 17:17:51 +1100894 reg32 |= ((u32) pll->dbsel[f][i]) << 8;
Angel Pons39ff7032020-03-09 21:39:44 +0100895 reg32 |= ((u32) pll->dben[f][i]) << 9;
Damien Zammit003d15c2015-11-20 17:17:51 +1100896 reg32 |= ((u32) pll->clkdelay[f][i]) << 14;
897 reg32 |= ((u32) pll->clkdelay[f][i]) << 10;
Angel Pons39ff7032020-03-09 21:39:44 +0100898 MCHBAR32_AND_OR(C0CMDTX2, ~0xff00, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100899
900 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100901 MCHBAR8_AND_OR(C0TXCTL2DLL, ~0x3f, reg8);
902 MCHBAR8_AND_OR(C0TXCTL3DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100903}
904
905static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
906{
907 u8 rank, dqs, reg8, j;
908 u32 reg32;
909
Angel Pons39ff7032020-03-09 21:39:44 +0100910 j = clk - 40;
911 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100912 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100913 rank = j % 4;
914 dqs = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100915
Angel Pons39ff7032020-03-09 21:39:44 +0100916 reg32 |= ((u32) pll->dben[f][clk]) << (dqs + 9);
Damien Zammit003d15c2015-11-20 17:17:51 +1100917 reg32 |= ((u32) pll->dbsel[f][clk]) << dqs;
Damien Zammit003d15c2015-11-20 17:17:51 +1100918
Nico Huber12d37682021-02-06 14:39:54 +0100919 MCHBAR32_AND_OR(C0DQSRyTX1(rank), ~((1 << (dqs + 9)) | (1 << dqs)), reg32);
Angel Pons39ff7032020-03-09 21:39:44 +0100920
921 reg32 = ((u32) pll->clkdelay[f][clk]) << ((dqs * 2) + 16);
922 MCHBAR32_AND_OR(C0DQSDQRyTX3(rank), ~((1 << (dqs * 2 + 17)) | (1 << (dqs * 2 + 16))),
923 reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100924
925 reg8 = pll->pi[f][clk];
Angel Pons39ff7032020-03-09 21:39:44 +0100926 MCHBAR8_AND_OR(C0TXDQS0R0DLL + j, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100927}
928
Damien Zammit003d15c2015-11-20 17:17:51 +1100929static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
930{
931 u8 rank, dq, reg8, j;
932 u32 reg32;
933
Angel Pons39ff7032020-03-09 21:39:44 +0100934 j = clk - 8;
935 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100936 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100937 rank = j % 4;
938 dq = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100939
Angel Pons39ff7032020-03-09 21:39:44 +0100940 reg32 |= ((u32) pll->dben[f][clk]) << (dq + 9);
Damien Zammit003d15c2015-11-20 17:17:51 +1100941 reg32 |= ((u32) pll->dbsel[f][clk]) << dq;
Angel Pons39ff7032020-03-09 21:39:44 +0100942
Nico Huber12d37682021-02-06 14:39:54 +0100943 MCHBAR32_AND_OR(C0DQRyTX1(rank), ~((1 << (dq + 9)) | (1 << dq)), reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100944
945 reg32 = ((u32) pll->clkdelay[f][clk]) << (dq*2);
Angel Pons39ff7032020-03-09 21:39:44 +0100946 MCHBAR32_AND_OR(C0DQSDQRyTX3(rank), ~((1 << (dq * 2 + 1)) | (1 << (dq * 2))), reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100947
948 reg8 = pll->pi[f][clk];
Angel Pons39ff7032020-03-09 21:39:44 +0100949 MCHBAR8_AND_OR(C0TXDQ0R0DLL + j, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100950}
951
Angel Pons39ff7032020-03-09 21:39:44 +0100952/* WDLL programming: Perform HPLL/MPLL calibration after write levelization */
Damien Zammit003d15c2015-11-20 17:17:51 +1100953static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
954{
955 struct pllparam pll = {
956 .pi = {
Angel Pons39ff7032020-03-09 21:39:44 +0100957 { /* DDR = 667 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100958 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
959 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
960 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
961 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
962 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Angel Pons39ff7032020-03-09 21:39:44 +0100963 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3,
Damien Zammit003d15c2015-11-20 17:17:51 +1100964 },
Angel Pons39ff7032020-03-09 21:39:44 +0100965 { /* DDR = 800 */
966 53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
Damien Zammit003d15c2015-11-20 17:17:51 +1100967 34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
968 47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
Angel Pons39ff7032020-03-09 21:39:44 +0100969 47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
970 2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
971 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15,
Damien Zammit003d15c2015-11-20 17:17:51 +1100972 }},
973
974 .dben = {
Angel Pons39ff7032020-03-09 21:39:44 +0100975 { /* DDR = 667 */
976 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
977 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
978 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
979 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
980 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
981 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100982 },
Angel Pons39ff7032020-03-09 21:39:44 +0100983 { /* DDR = 800 */
984 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
985 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
986 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
987 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
988 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
989 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100990 }},
991
992 .dbsel = {
Angel Pons39ff7032020-03-09 21:39:44 +0100993 { /* DDR = 667 */
994 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
995 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
996 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
997 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
998 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
999 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001000 },
Angel Pons39ff7032020-03-09 21:39:44 +01001001 { /* DDR = 800 */
1002 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1003 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1004 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1005 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1006 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1007 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001008 }},
1009
1010 .clkdelay = {
Angel Pons39ff7032020-03-09 21:39:44 +01001011 { /* DDR = 667 */
1012 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1013 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1014 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1015 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1016 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1017 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001018 },
Angel Pons39ff7032020-03-09 21:39:44 +01001019 { /* DDR = 800 */
1020 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1021 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1022 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1023 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1024 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1025 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Damien Zammit003d15c2015-11-20 17:17:51 +11001026 }}
1027 };
1028
1029 u8 i, f;
1030 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1031 f = 0;
1032 } else {
1033 f = 1;
1034 }
1035 for (i = 0; i < 72; i++) {
1036 pll.pi[f][i] += pidelay;
1037 }
1038
Angel Pons39ff7032020-03-09 21:39:44 +01001039 /* Disable Dynamic DQS Slave Setting Per Rank */
1040 MCHBAR8_AND(CSHRDQSCMN, ~(1 << 7));
1041 MCHBAR16_AND_OR(CSHRPDCTL4, ~0x3fff, 0x1fff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001042
1043 sdram_p_clkset0(&pll, f, 0);
1044 sdram_p_clkset1(&pll, f, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01001045 sdram_p_cmd(&pll, f, 2);
1046 sdram_p_ctrl(&pll, f, 4);
1047
Damien Zammit003d15c2015-11-20 17:17:51 +11001048 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001049 sdram_p_dqs(&pll, f, i + 40);
Damien Zammit003d15c2015-11-20 17:17:51 +11001050 }
1051 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001052 sdram_p_dq(&pll, f, i + 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11001053 }
1054}
1055
Angel Pons39ff7032020-03-09 21:39:44 +01001056/* Perform HMC hardware calibration */
Damien Zammit003d15c2015-11-20 17:17:51 +11001057static void sdram_calibratehwpll(struct sysinfo *s)
1058{
1059 u8 reg8;
1060
1061 s->async = 0;
1062 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001063
Angel Pons39ff7032020-03-09 21:39:44 +01001064 MCHBAR16_OR(CSHRPDCTL, 1 << 15);
1065 MCHBAR8_AND(CSHRPDCTL, ~(1 << 7));
1066 MCHBAR8_OR(CSHRPDCTL, 1 << 3);
1067 MCHBAR8_OR(CSHRPDCTL, 1 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001068
Angel Pons39ff7032020-03-09 21:39:44 +01001069 /* Start hardware HMC calibration */
1070 MCHBAR8_OR(CSHRPDCTL, 1 << 7);
1071
1072 /* Busy-wait until calibration is done */
1073 while ((MCHBAR8(CSHRPDCTL) & (1 << 2)) == 0)
1074 ;
1075
1076 /* If hardware HMC calibration failed */
1077 reg8 = (MCHBAR8(CSHRPDCTL) & (1 << 3)) >> 3;
Damien Zammit003d15c2015-11-20 17:17:51 +11001078 if (reg8 != 0) {
1079 s->async = 1;
1080 }
1081}
1082
1083static void sdram_dlltiming(struct sysinfo *s)
1084{
Elyes HAOUAS66b462d2019-01-02 21:11:32 +01001085 u8 reg8, i;
Damien Zammit003d15c2015-11-20 17:17:51 +11001086 u16 reg16;
1087 u32 reg32;
1088
Angel Pons39ff7032020-03-09 21:39:44 +01001089 /* Configure the Master DLL */
Damien Zammit003d15c2015-11-20 17:17:51 +11001090 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +01001091 reg32 = 0x08014227;
Damien Zammit003d15c2015-11-20 17:17:51 +11001092 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001093 reg32 = 0x00014221;
Damien Zammit003d15c2015-11-20 17:17:51 +11001094 }
Angel Pons39ff7032020-03-09 21:39:44 +01001095 MCHBAR32_AND_OR(CSHRMSTRCTL1, ~0x0fffffff, reg32);
1096 MCHBAR32_OR(CSHRMSTRCTL1, 1 << 23);
1097 MCHBAR32_OR(CSHRMSTRCTL1, 1 << 15);
1098 MCHBAR32_AND(CSHRMSTRCTL1, ~(1 << 15));
Damien Zammit003d15c2015-11-20 17:17:51 +11001099
1100 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001101 /* Disable the Master DLLs by setting these bits, IN ORDER! */
1102 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 0);
1103 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 2);
1104 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 4);
1105 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 8);
1106 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 10);
1107 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 12);
1108 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 14);
Damien Zammit003d15c2015-11-20 17:17:51 +11001109 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001110 /* Enable the Master DLLs by clearing these bits, IN ORDER! */
1111 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 0));
1112 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 2));
1113 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 4));
1114 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 8));
1115 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 10));
1116 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 12));
1117 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 14));
Damien Zammit003d15c2015-11-20 17:17:51 +11001118 }
1119
Angel Pons39ff7032020-03-09 21:39:44 +01001120 /* Initialize the Transmit DLL PI values in the following sequence. */
Damien Zammit003d15c2015-11-20 17:17:51 +11001121 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001122 MCHBAR8_AND_OR(CREFPI, ~0x3f, 0x07);
Damien Zammit003d15c2015-11-20 17:17:51 +11001123 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001124 MCHBAR8_AND(CREFPI, ~0x3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001125 }
1126
1127 sdram_calibratepll(s, 0); // XXX check
1128
Angel Pons39ff7032020-03-09 21:39:44 +01001129 /* Enable all modular Slave DLL */
1130 MCHBAR16_OR(C0DLLPIEN, 1 << 11);
1131 MCHBAR16_OR(C0DLLPIEN, 1 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11001132
1133 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001134 MCHBAR16_OR(C0DLLPIEN, (1 << 10) >> i);
Damien Zammit003d15c2015-11-20 17:17:51 +11001135 }
Angel Pons39ff7032020-03-09 21:39:44 +01001136 /* Enable DQ/DQS output */
1137 MCHBAR8_OR(C0SLVDLLOUTEN, 1);
1138 MCHBAR16(CSPDSLVWT) = 0x5005;
1139 MCHBAR16_AND_OR(CSHRPDCTL2, ~0x1f1f, 0x051a);
1140 MCHBAR16_AND_OR(CSHRPDCTL5, ~0xbf3f, 0x9010);
Damien Zammit003d15c2015-11-20 17:17:51 +11001141
1142 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001143 MCHBAR8_AND_OR(CSHRPDCTL3, ~0x7f, 0x6b);
Damien Zammit003d15c2015-11-20 17:17:51 +11001144 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001145 MCHBAR8_AND_OR(CSHRPDCTL3, ~0x7f, 0x55);
Damien Zammit003d15c2015-11-20 17:17:51 +11001146 sdram_calibratehwpll(s);
1147 }
Angel Pons39ff7032020-03-09 21:39:44 +01001148 /* Disable Dynamic Diff Amp */
1149 MCHBAR32_AND(C0STATRDCTRL, ~(1 << 22));
Damien Zammit003d15c2015-11-20 17:17:51 +11001150
Angel Pons39ff7032020-03-09 21:39:44 +01001151 /* Now, start initializing the transmit FIFO */
1152 MCHBAR8_AND(C0MISCCTL, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11001153
Angel Pons39ff7032020-03-09 21:39:44 +01001154 /* Disable (gate) mdclk and mdclkb */
1155 MCHBAR8_OR(CSHWRIOBONUS, 0xc0);
Jacob Garberd10680b2019-06-11 14:13:04 -06001156
Angel Pons39ff7032020-03-09 21:39:44 +01001157 /* Select mdmclk */
1158 MCHBAR8_AND(CSHWRIOBONUS, ~(1 << 5));
Damien Zammit003d15c2015-11-20 17:17:51 +11001159
Angel Pons39ff7032020-03-09 21:39:44 +01001160 /* Ungate mdclk */
1161 MCHBAR8_AND_OR(CSHWRIOBONUS, ~0xc0, 1 << 6);
1162 MCHBAR8_AND_OR(CSHRFIFOCTL, ~0x3f, 0x1a);
1163
1164 /* Enable the write pointer count */
1165 MCHBAR8_OR(CSHRFIFOCTL, 1);
1166
1167 /* Set the DDR3 Reset Enable bit */
1168 MCHBAR8_OR(CSHRDDR3CTL, 1);
1169
1170 /* Configure DQS-DQ Transmit */
1171 MCHBAR32(CSHRDQSTXPGM) = 0x00551803;
1172
1173 reg8 = 0; /* Switch all clocks on anyway */
1174
1175 /* Enable clock groups depending on rank population */
1176 MCHBAR32_AND_OR(C0CKTX, ~0x3f000000, reg8 << 24);
1177
1178 /* Enable DDR command output buffers from core */
1179 MCHBAR8_AND(0x594, ~1);
1180
Damien Zammit003d15c2015-11-20 17:17:51 +11001181 reg16 = 0;
1182 if (!rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001183 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001184 }
1185 if (!rank_is_populated(s->dimms, 0, 1)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001186 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001187 }
1188 if (!rank_is_populated(s->dimms, 0, 2)) {
1189 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1190 }
1191 if (!rank_is_populated(s->dimms, 0, 3)) {
1192 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1193 }
Angel Pons39ff7032020-03-09 21:39:44 +01001194 MCHBAR16_OR(C0CTLTX2, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001195}
1196
Angel Pons39ff7032020-03-09 21:39:44 +01001197/* Define a shorter name for these to make the lines fit in 96 characters */
1198#define TABLE static const
1199
1200/* Loop over each RCOMP group, but skip group 1 because it does not exist */
1201#define FOR_EACH_RCOMP_GROUP(idx) for (idx = 0; idx < 7; idx++) if (idx != 1)
1202
1203/* Define accessors for the RCOMP register banks */
1204#define C0RCOMPCTRLx(x) (rcompctl[(x)] + 0x00)
1205#define C0RCOMPMULTx(x) (rcompctl[(x)] + 0x04)
1206#define C0RCOMPOVRx(x) (rcompctl[(x)] + 0x06)
Angel Pons94eea6f2021-02-06 15:03:48 +01001207#define C0RCOMPOSVx(x) (rcompctl[(x)] + 0x0a)
1208#define C0SCOMPVREFx(x) (rcompctl[(x)] + 0x0e)
Angel Pons39ff7032020-03-09 21:39:44 +01001209#define C0SCOMPOVRx(x) (rcompctl[(x)] + 0x10)
1210#define C0SCOMPOFFx(x) (rcompctl[(x)] + 0x12)
1211#define C0DCOMPx(x) (rcompctl[(x)] + 0x14)
1212#define C0SLEWBASEx(x) (rcompctl[(x)] + 0x16)
1213#define C0SLEWPULUTx(x) (rcompctl[(x)] + 0x18)
Angel Pons94eea6f2021-02-06 15:03:48 +01001214#define C0SLEWPDLUTx(x) (rcompctl[(x)] + 0x1c)
Angel Pons39ff7032020-03-09 21:39:44 +01001215#define C0DCOMPOVRx(x) (rcompctl[(x)] + 0x20)
1216#define C0DCOMPOFFx(x) (rcompctl[(x)] + 0x24)
1217
1218/* FIXME: This only applies to DDR2 */
Damien Zammit003d15c2015-11-20 17:17:51 +11001219static void sdram_rcomp(struct sysinfo *s)
1220{
Angel Pons39ff7032020-03-09 21:39:44 +01001221 u8 i, j, reg8, rcompp, rcompn, srup, srun;
Damien Zammit003d15c2015-11-20 17:17:51 +11001222 u16 reg16;
1223 u32 reg32, rcomp1, rcomp2;
1224
Angel Pons39ff7032020-03-09 21:39:44 +01001225 static const u8 rcompslew = 0x0a;
1226 static const u16 rcompctl[7] = {
1227 C0RCOMPCTRL0,
1228 0, /* This register does not exist */
1229 C0RCOMPCTRL2,
1230 C0RCOMPCTRL3,
1231 C0RCOMPCTRL4,
1232 C0RCOMPCTRL5,
1233 C0RCOMPCTRL6,
1234 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001235
Angel Pons39ff7032020-03-09 21:39:44 +01001236 /* RCOMP settings tables = { NC-NC, x16SS, x16DS, x16SS2, x16DS2, x8DS, x8DS2}; */
1237 TABLE u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0};
1238 TABLE u8 rcompstr[7] = { 0x66, 0x00, 0xaa, 0x55, 0x55, 0x77, 0x77};
1239 TABLE u16 rcompscomp[7] = {0xa22a, 0x0000, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a};
1240 TABLE u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1};
1241 TABLE u16 rcompf[7] = {0x1114, 0x0000, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a};
1242 TABLE u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0xaa};
1243 TABLE u16 rcompscomp2[7] = {0x0000, 0xe22e, 0xe22e, 0xe22e, 0x8228, 0xe22e, 0x8228};
1244 TABLE u8 rcompdelay2[7] = { 0, 0, 0, 0, 2, 0, 2};
Damien Zammit003d15c2015-11-20 17:17:51 +11001245
Angel Pons39ff7032020-03-09 21:39:44 +01001246 TABLE u8 rcomplut[64][12] = {
1247 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1248 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1249 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1250 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1251 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1252 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1253 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1254 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1255 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1256 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1257 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1258 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1259 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1260 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1261 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1262 {10, 9, 12, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1263 {10, 9, 12, 11, 2, 2, 6, 5, 7, 6, 6, 5},
1264 {10, 10, 12, 12, 2, 2, 6, 5, 7, 6, 6, 5},
1265 {10, 10, 12, 12, 2, 2, 6, 6, 7, 7, 6, 6},
1266 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1267 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1268 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1269 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1270 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1271 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1272 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1273 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1274 {11, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1275 {11, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1276 {12, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1277 {12, 12, 14, 13, 3, 3, 7, 6, 7, 7, 7, 6},
1278 {13, 12, 16, 15, 3, 3, 7, 6, 8, 7, 7, 6},
1279 {13, 14, 16, 15, 4, 3, 7, 7, 8, 8, 7, 7},
1280 {14, 14, 16, 17, 4, 3, 7, 7, 8, 8, 7, 7},
1281 {14, 16, 18, 17, 4, 4, 8, 7, 8, 8, 8, 7},
1282 {15, 16, 18, 19, 4, 4, 8, 7, 9, 8, 8, 7},
1283 {15, 18, 18, 19, 4, 4, 8, 8, 9, 9, 8, 8},
1284 {16, 18, 20, 21, 4, 4, 8, 8, 9, 9, 8, 8},
1285 {16, 19, 20, 21, 5, 4, 9, 8, 10, 9, 9, 8},
1286 {16, 19, 20, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1287 {17, 19, 22, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1288 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1289 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1290 {18, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1291 {18, 21, 24, 25, 5, 5, 9, 9, 11, 10, 9, 9},
1292 {19, 21, 24, 27, 5, 5, 9, 9, 11, 11, 9, 9},
1293 {19, 22, 24, 27, 5, 5, 10, 9, 11, 11, 10, 9},
1294 {20, 22, 24, 27, 6, 5, 10, 10, 11, 11, 10, 10},
1295 {20, 23, 26, 27, 6, 6, 10, 10, 12, 12, 10, 10},
1296 {20, 23, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1297 {21, 24, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1298 {21, 24, 26, 29, 6, 6, 11, 10, 12, 13, 11, 10},
1299 {22, 25, 28, 29, 6, 6, 11, 11, 13, 13, 11, 11},
1300 {22, 25, 28, 31, 6, 6, 11, 11, 13, 13, 11, 11},
1301 {22, 26, 28, 31, 6, 6, 11, 11, 13, 14, 11, 11},
1302 {23, 26, 30, 31, 7, 6, 12, 11, 14, 14, 12, 11},
1303 {23, 27, 30, 33, 7, 7, 12, 12, 14, 14, 12, 12},
1304 {23, 27, 30, 33, 7, 7, 12, 12, 14, 15, 12, 12},
1305 {24, 28, 32, 33, 7, 7, 12, 12, 15, 15, 12, 12},
1306 {24, 28, 32, 33, 7, 7, 12, 12, 15, 16, 12, 12},
1307 {24, 29, 32, 35, 7, 7, 12, 12, 15, 16, 12, 12},
1308 {25, 29, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1309 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1310 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
Damien Zammit003d15c2015-11-20 17:17:51 +11001311 };
1312
1313 srup = 0;
1314 srun = 0;
1315
1316 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001317 rcomp1 = 0x00050431;
1318 } else {
Damien Zammit003d15c2015-11-20 17:17:51 +11001319 rcomp1 = 0x00050542;
1320 }
1321 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
Angel Pons94eea6f2021-02-06 15:03:48 +01001322 rcomp2 = 0x14c42827;
Damien Zammit003d15c2015-11-20 17:17:51 +11001323 } else {
1324 rcomp2 = 0x19042827;
1325 }
1326
Angel Pons39ff7032020-03-09 21:39:44 +01001327 FOR_EACH_RCOMP_GROUP(i) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001328 reg8 = rcompupdate[i];
Angel Pons39ff7032020-03-09 21:39:44 +01001329 MCHBAR8_AND_OR(C0RCOMPCTRLx(i), ~1, reg8);
1330 MCHBAR8_AND(C0RCOMPCTRLx(i), ~2);
1331
1332 reg16 = rcompslew;
1333 MCHBAR16_AND_OR(C0RCOMPCTRLx(i), ~0xf000, reg16 << 12);
1334
1335 MCHBAR8(C0RCOMPMULTx(i)) = rcompstr[i];
1336 MCHBAR16(C0SCOMPVREFx(i)) = rcompscomp[i];
1337 MCHBAR8_AND_OR(C0DCOMPx(i), ~0x03, rcompdelay[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001338 if (i == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01001339 /* FIXME: Why are we rewriting this? */
1340 MCHBAR16_AND_OR(C0RCOMPCTRLx(i), ~0xf000, reg16 << 12);
1341
1342 MCHBAR8(C0RCOMPMULTx(i)) = rcompstr2[s->dimm_config[0]];
1343 MCHBAR16(C0SCOMPVREFx(i)) = rcompscomp2[s->dimm_config[0]];
1344 MCHBAR8_AND_OR(C0DCOMPx(i), ~0x03, rcompdelay2[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001345 }
1346
Angel Pons39ff7032020-03-09 21:39:44 +01001347 MCHBAR16_AND(C0SLEWBASEx(i), ~0x7f7f);
1348
1349 /* FIXME: Why not do a single dword write? */
1350 MCHBAR16_AND(C0SLEWPULUTx(i), ~0x3f3f);
1351 MCHBAR16_AND(C0SLEWPULUTx(i) + 2, ~0x3f3f);
1352
1353 /* FIXME: Why not do a single dword write? */
1354 MCHBAR16_AND(C0SLEWPDLUTx(i), ~0x3f3f);
1355 MCHBAR16_AND(C0SLEWPDLUTx(i) + 2, ~0x3f3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001356 }
1357
Angel Pons39ff7032020-03-09 21:39:44 +01001358 /* FIXME: Hardcoded */
1359 MCHBAR8_AND_OR(C0ODTRECORDX, ~0x3f, 0x36);
1360 MCHBAR8_AND_OR(C0DQSODTRECORDX, ~0x3f, 0x36);
Damien Zammit003d15c2015-11-20 17:17:51 +11001361
Angel Pons39ff7032020-03-09 21:39:44 +01001362 FOR_EACH_RCOMP_GROUP(i) {
1363 MCHBAR8_AND(C0RCOMPCTRLx(i), ~0x60);
1364 MCHBAR16_AND(C0RCOMPCTRLx(i) + 2, ~0x0706);
1365 MCHBAR16_AND(C0RCOMPOSVx(i), ~0x7f7f);
1366 MCHBAR16_AND(C0SCOMPOFFx(i), ~0x3f3f);
1367 MCHBAR16_AND(C0DCOMPOFFx(i), ~0x1f1f);
1368 MCHBAR8_AND(C0DCOMPOFFx(i) + 2, ~0x1f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001369 }
1370
Angel Pons39ff7032020-03-09 21:39:44 +01001371 MCHBAR16_AND(C0ODTRECORDX, ~0xffc0);
1372 MCHBAR16_AND(C0ODTRECORDX + 2, ~0x000f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001373
Angel Pons39ff7032020-03-09 21:39:44 +01001374 /* FIXME: Why not do a single dword write? */
1375 MCHBAR16_AND(C0DQSODTRECORDX, ~0xffc0);
1376 MCHBAR16_AND(C0DQSODTRECORDX + 2, ~0x000f);
1377
1378 FOR_EACH_RCOMP_GROUP(i) {
1379 MCHBAR16(C0SCOMPOVRx(i)) = rcompf[i];
1380
1381 /* FIXME: Why not do a single dword write? */
1382 MCHBAR16(C0DCOMPOVRx(i)) = 0x1219;
1383 MCHBAR16(C0DCOMPOVRx(i) + 2) = 0x000C;
Damien Zammit003d15c2015-11-20 17:17:51 +11001384 }
1385
Angel Pons39ff7032020-03-09 21:39:44 +01001386 MCHBAR32_AND_OR(DCMEASBUFOVR, ~0x001f1f1f, 0x000c1219);
Damien Zammit003d15c2015-11-20 17:17:51 +11001387
Angel Pons39ff7032020-03-09 21:39:44 +01001388 /* FIXME: Why not do a single word write? */
1389 MCHBAR16_AND_OR(XCOMPSDR0BNS, ~0x1f00, 0x1200);
1390 MCHBAR8_AND_OR(XCOMPSDR0BNS, ~0x1f, 0x12);
1391
1392 MCHBAR32(COMPCTRL3) = 0x007C9007;
1393 MCHBAR32(OFREQDELSEL) = rcomp1;
1394 MCHBAR16(XCOMPCMNBNS) = 0x1f7f;
1395 MCHBAR32(COMPCTRL2) = rcomp2;
1396 MCHBAR16_AND_OR(XCOMPDFCTRL, ~0x0f, 1);
1397 MCHBAR16(ZQCALCTRL) = 0x0134;
1398 MCHBAR32(COMPCTRL1) = 0x4C293600;
1399
Angel Pons39ff7032020-03-09 21:39:44 +01001400 MCHBAR8_AND_OR(COMPCTRL1 + 3, ~0x44, (1 << 6) | (1 << 2));
1401 MCHBAR16_AND(XCOMPSDR0BNS, ~(1 << 13));
1402 MCHBAR8_AND(XCOMPSDR0BNS, ~(1 << 5));
1403
1404 FOR_EACH_RCOMP_GROUP(i) {
1405 /* FIXME: This should be an _AND_OR */
1406 MCHBAR8(C0RCOMPCTRLx(i) + 2) = MCHBAR8(C0RCOMPCTRLx(i)) & ~0x71;
Damien Zammit003d15c2015-11-20 17:17:51 +11001407 }
1408
Angel Pons39ff7032020-03-09 21:39:44 +01001409 if ((MCHBAR32(COMPCTRL1) & (1 << 30)) == 0) {
1410 /* Start COMP */
1411 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001412
Angel Pons39ff7032020-03-09 21:39:44 +01001413 /* Wait until COMP is done */
1414 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1415 ;
1416
1417 reg32 = MCHBAR32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001418 rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1419 rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1420
Angel Pons39ff7032020-03-09 21:39:44 +01001421 FOR_EACH_RCOMP_GROUP(i) {
1422 srup = (MCHBAR8(C0RCOMPCTRLx(i) + 1) & 0xc0) >> 6;
1423 srun = (MCHBAR8(C0RCOMPCTRLx(i) + 1) & 0x30) >> 4;
1424
1425 /* FIXME: Why not do a single word write? */
Damien Zammit003d15c2015-11-20 17:17:51 +11001426 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
Angel Pons39ff7032020-03-09 21:39:44 +01001427 MCHBAR16_AND_OR(C0SLEWBASEx(i), ~0x7f00, reg16);
1428
Damien Zammit003d15c2015-11-20 17:17:51 +11001429 reg16 = (u16)(rcompn - (1 << (srun + 1)));
Angel Pons39ff7032020-03-09 21:39:44 +01001430 MCHBAR8_AND_OR(C0SLEWBASEx(i), ~0x7f, (u8)reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001431 }
1432
1433 reg8 = rcompp - (1 << (srup + 1));
1434 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001435 MCHBAR8_AND_OR(C0SLEWPULUTx(0) + i, ~0x3f, rcomplut[j][0]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001436 }
1437
1438 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1439 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons39ff7032020-03-09 21:39:44 +01001440 MCHBAR8_AND_OR(C0SLEWPULUTx(2) + i, ~0x3f, rcomplut[j][10]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001441 }
1442 }
1443
1444 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001445 MCHBAR8_AND_OR(C0SLEWPULUTx(3) + i, ~0x3f, rcomplut[j][6]);
1446 MCHBAR8_AND_OR(C0SLEWPULUTx(4) + i, ~0x3f, rcomplut[j][6]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001447 }
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(5) + i, ~0x3f, rcomplut[j][8]);
1451 MCHBAR8_AND_OR(C0SLEWPULUTx(6) + i, ~0x3f, rcomplut[j][8]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001452 }
1453
1454 reg8 = rcompn - (1 << (srun + 1));
1455 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001456 MCHBAR8_AND_OR(C0SLEWPDLUTx(0) + i, ~0x3f, rcomplut[j][1]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001457 }
1458
1459 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1460 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons39ff7032020-03-09 21:39:44 +01001461 MCHBAR8_AND_OR(C0SLEWPDLUTx(2) + i, ~0x3f, rcomplut[j][11]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001462 }
1463 }
1464
1465 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001466 MCHBAR8_AND_OR(C0SLEWPDLUTx(3) + i, ~0x3f, rcomplut[j][7]);
1467 MCHBAR8_AND_OR(C0SLEWPDLUTx(4) + i, ~0x3f, rcomplut[j][7]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001468 }
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(5) + i, ~0x3f, rcomplut[j][9]);
1472 MCHBAR8_AND_OR(C0SLEWPDLUTx(6) + i, ~0x3f, rcomplut[j][9]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001473 }
1474 }
Angel Pons39ff7032020-03-09 21:39:44 +01001475 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001476}
1477
Angel Pons39ff7032020-03-09 21:39:44 +01001478/* FIXME: The ODT tables are for DDR2 only! */
Damien Zammit003d15c2015-11-20 17:17:51 +11001479static void sdram_odt(struct sysinfo *s)
1480{
1481 u8 rankindex = 0;
1482
Angel Pons39ff7032020-03-09 21:39:44 +01001483 static const u16 odt_rankctrl[16] = {
1484 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1485 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1486 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1487 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1488 };
1489 static const u16 odt_matrix[16] = {
1490 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1491 0x0000, 0x0011, 0x0000, 0x0011, 0x0000, 0x4444, 0x0000, 0x4444,
1492 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1493 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4444, 0x0000, 0x4444,
1494 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001495
1496 switch (s->dimms[0].ranks) {
1497 case 0:
1498 if (s->dimms[1].ranks == 0) {
1499 rankindex = 0;
1500 } else if (s->dimms[1].ranks == 1) {
1501 rankindex = 4;
1502 } else if (s->dimms[1].ranks == 2) {
1503 rankindex = 12;
1504 }
1505 break;
1506 case 1:
1507 if (s->dimms[1].ranks == 0) {
1508 rankindex = 1;
1509 } else if (s->dimms[1].ranks == 1) {
1510 rankindex = 5;
1511 } else if (s->dimms[1].ranks == 2) {
1512 rankindex = 13;
1513 }
1514 break;
1515 case 2:
1516 if (s->dimms[1].ranks == 0) {
1517 rankindex = 3;
1518 } else if (s->dimms[1].ranks == 1) {
1519 rankindex = 7;
1520 } else if (s->dimms[1].ranks == 2) {
1521 rankindex = 15;
1522 }
1523 break;
1524 }
1525
Angel Pons39ff7032020-03-09 21:39:44 +01001526 /* Program the ODT Matrix */
1527 MCHBAR16(C0ODT) = odt_matrix[rankindex];
1528
1529 /* Program the ODT Rank Control */
1530 MCHBAR16(C0ODTRKCTRL) = odt_rankctrl[rankindex];
Damien Zammit003d15c2015-11-20 17:17:51 +11001531}
1532
1533static void sdram_mmap(struct sysinfo *s)
1534{
Angel Pons39ff7032020-03-09 21:39:44 +01001535 TABLE u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000, 0xc00001, 0xf00000};
1536 TABLE u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101, 0x1010000, 0x1010101};
1537 TABLE u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1538 TABLE u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006, 0x40002, 0x80006};
Damien Zammit003d15c2015-11-20 17:17:51 +11001539
Angel Pons39ff7032020-03-09 21:39:44 +01001540 TABLE u16 tolud[7] = {2048, 2048, 4096, 4096, 8192, 4096, 8192};
1541 TABLE u16 tom[7] = { 2, 2, 4, 4, 8, 4, 8};
1542 TABLE u16 touud[7] = { 128, 128, 256, 256, 512, 256, 512};
1543 TABLE u32 gbsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1544 TABLE u32 bgsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1545 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 +11001546
1547 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1548 if (s->dimms[0].sides > 1) {
1549 // 2R/NC
Angel Pons39ff7032020-03-09 21:39:44 +01001550 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x300001);
1551 MCHBAR32(C0DRA01) = 0x00000101;
1552 MCHBAR32(C0DRB0) = 0x00040002;
1553 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001554 } else {
1555 // 1R/NC
Angel Pons39ff7032020-03-09 21:39:44 +01001556 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x100001);
1557 MCHBAR32(C0DRA01) = 0x00000001;
1558 MCHBAR32(C0DRB0) = 0x00020002;
1559 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001560 }
1561 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001562 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x300001);
1563 MCHBAR32(C0DRA01) = 0x00000101;
1564 MCHBAR32(C0DRB0) = 0x00040002;
1565 MCHBAR32(C0DRB2) = 0x00040004;
Damien Zammit003d15c2015-11-20 17:17:51 +11001566 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001567 MCHBAR32_AND_OR(C0CKECTRL, ~1, w260[s->dimm_config[0]]);
1568 MCHBAR32(C0DRA01) = w208[s->dimm_config[0]];
1569 MCHBAR32(C0DRB0) = w200[s->dimm_config[0]];
1570 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001571 }
Angel Pons39ff7032020-03-09 21:39:44 +01001572 pci_write_config16(HOST_BRIDGE, 0xb0, tolud[s->dimm_config[0]]);
1573 pci_write_config16(HOST_BRIDGE, 0xa0, tom[s->dimm_config[0]]);
1574 pci_write_config16(HOST_BRIDGE, 0xa2, touud[s->dimm_config[0]]);
1575 pci_write_config32(HOST_BRIDGE, 0xa4, gbsm[s->dimm_config[0]]);
1576 pci_write_config32(HOST_BRIDGE, 0xa8, bgsm[s->dimm_config[0]]);
1577 pci_write_config32(HOST_BRIDGE, 0xac, tsegmb[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001578}
1579
Damien Zammit003d15c2015-11-20 17:17:51 +11001580static u8 sdram_checkrcompoverride(void)
1581{
1582 u32 xcomp;
1583 u8 aa, bb, a, b, c, d;
1584
Angel Pons39ff7032020-03-09 21:39:44 +01001585 xcomp = MCHBAR32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001586 a = (u8)((xcomp & 0x7f000000) >> 24);
Angel Pons39ff7032020-03-09 21:39:44 +01001587 b = (u8)((xcomp & 0x007f0000) >> 16);
1588 c = (u8)((xcomp & 0x00003f00) >> 8);
1589 d = (u8)((xcomp & 0x0000003f) >> 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001590
1591 if (a > b) {
1592 aa = a - b;
1593 } else {
1594 aa = b - a;
1595 }
1596 if (c > d) {
1597 bb = c - d;
1598 } else {
1599 bb = d - c;
1600 }
Angel Pons39ff7032020-03-09 21:39:44 +01001601 if ((aa > 18) || (bb > 7) || (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
Damien Zammit003d15c2015-11-20 17:17:51 +11001602 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001603 MCHBAR32(RCMEASBUFXOVR) = 0x9718a729;
Damien Zammit003d15c2015-11-20 17:17:51 +11001604 return 1;
1605 }
1606 return 0;
1607}
1608
1609static void sdram_rcompupdate(struct sysinfo *s)
1610{
1611 u8 i, ok;
1612 u32 reg32a, reg32b;
1613
1614 ok = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001615 MCHBAR8_AND(XCOMPDFCTRL, ~(1 << 3));
1616 MCHBAR8_AND(COMPCTRL1, ~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11001617 for (i = 0; i < 3; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001618 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001619 hpet_udelay(1000);
Angel Pons39ff7032020-03-09 21:39:44 +01001620 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1621 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001622 ok |= sdram_checkrcompoverride();
1623 }
1624 if (!ok) {
Angel Pons39ff7032020-03-09 21:39:44 +01001625 reg32a = MCHBAR32(XCOMP);
1626 reg32b = ((reg32a >> 16) & 0x0000ffff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001627 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1628 reg32a |= (1 << 31) | (1 << 15);
Angel Pons39ff7032020-03-09 21:39:44 +01001629 MCHBAR32(RCMEASBUFXOVR) = reg32a;
Damien Zammit003d15c2015-11-20 17:17:51 +11001630 }
Angel Pons39ff7032020-03-09 21:39:44 +01001631 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001632 hpet_udelay(1000);
Angel Pons39ff7032020-03-09 21:39:44 +01001633 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1634 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001635}
1636
1637static void __attribute__((noinline))
1638sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1639{
1640 u32 reg32;
1641
1642 reg32 = jval << 3;
Angel Pons39ff7032020-03-09 21:39:44 +01001643 reg32 |= rank * (1 << 27);
1644 MCHBAR8_AND_OR(C0JEDEC, ~0x3e, jmode);
Damien Zammit003d15c2015-11-20 17:17:51 +11001645 read32((void *)reg32);
1646 barrier();
1647 hpet_udelay(1); // 1us
1648}
1649
1650static void sdram_zqcl(struct sysinfo *s)
1651{
1652 if (s->boot_path == BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01001653 MCHBAR32_OR(C0CKECTRL, 1 << 27);
1654 MCHBAR8_AND_OR(C0JEDEC, ~0x0e, NORMAL_OP_CMD);
1655 MCHBAR8_AND(C0JEDEC, ~0x30);
1656 MCHBAR32_AND_OR(C0REFRCTRL2, ~(3 << 30), 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001657 }
1658}
1659
1660static void sdram_jedecinit(struct sysinfo *s)
1661{
1662 u8 r, i, ch;
1663 u16 reg16, mrs, rttnom;
1664 struct jedeclist {
1665 char debug[15];
1666 u8 cmd;
1667 u16 val;
1668 };
1669
Arthur Heymans6bf13012017-06-10 12:03:27 +02001670 static const struct jedeclist jedec[12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001671 { " NOP ", NOP_CMD, 0 },
1672 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1673 { " EMRS2 ", EMRS2_CMD, 0 },
1674 { " EMRS3 ", EMRS3_CMD, 0 },
1675 { " EMRS1 ", EMRS1_CMD, 0 },
1676 { " DLL RESET ", MRS_CMD, (1 << 8) },
1677 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1678 { " AUTOREFRESH", CBR_CMD, 0 },
1679 { " AUTOREFRESH", CBR_CMD, 0 },
1680 { " INITIALISE ", MRS_CMD, 0 },
1681 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1682 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1683 };
1684
1685 mrs = (s->selected_timings.CAS << 4) |
Angel Pons39ff7032020-03-09 21:39:44 +01001686 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 3;
1687
Damien Zammit003d15c2015-11-20 17:17:51 +11001688 rttnom = (1 << 2);
1689 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1690 rttnom |= (1 << 6);
1691 }
1692
1693 hpet_udelay(200); // 200us
1694 reg16 = 0;
1695 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1696 for (i = 0; i < 12; i++) {
1697 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1698 reg16 = jedec[i].val;
1699 switch (jedec[i].cmd) {
1700 case EMRS1_CMD:
1701 reg16 |= rttnom;
1702 break;
1703 case MRS_CMD:
1704 reg16 |= mrs;
1705 break;
1706 default:
1707 break;
1708 }
1709 sdram_jedec(s, r, jedec[i].cmd, reg16);
1710 PRINTK_DEBUG("done\n");
1711 }
1712 }
1713}
1714
1715static void sdram_misc(struct sysinfo *s)
1716{
1717 u32 reg32;
1718
1719 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001720 reg32 |= (4 << 13);
1721 reg32 |= (6 << 8);
1722 MCHBAR32_AND_OR(C0DYNRDCTRL, ~0x3ff00, reg32);
1723 MCHBAR8_AND(C0DYNRDCTRL, ~(1 << 7));
1724 MCHBAR8_OR(C0REFRCTRL + 3, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001725 if (s->boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01001726 MCHBAR8_AND_OR(C0JEDEC, ~0x0e, NORMAL_OP_CMD);
1727 MCHBAR8_AND(C0JEDEC, ~0x30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001728 } else {
1729 sdram_zqcl(s);
1730 }
1731}
1732
1733static void sdram_checkreset(void)
1734{
1735 u8 pmcon2, pmcon3, reset;
1736
1737 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1738 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1739 pmcon3 &= ~0x2;
1740 if (pmcon2 & 0x80) {
1741 pmcon2 &= ~0x80;
1742 reset = 1;
1743 } else {
1744 pmcon2 |= 0x80;
1745 reset = 0;
1746 }
1747 if (pmcon2 & 0x4) {
1748 pmcon2 |= 0x4;
1749 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1750 pmcon3 |= (1 << 3);
1751 }
1752 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1753 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +02001754 if (reset)
1755 full_reset();
Damien Zammit003d15c2015-11-20 17:17:51 +11001756}
1757
1758static void sdram_dradrb(struct sysinfo *s)
1759{
1760 u8 i, reg8, ch, r;
1761 u32 reg32, ind, c0dra, c0drb, dra;
1762 u16 addr;
1763 i = 0;
Arthur Heymans6bf13012017-06-10 12:03:27 +02001764 static const u8 dratab[2][2][2][4] =
Damien Zammit003d15c2015-11-20 17:17:51 +11001765 {{
1766 {
1767 {0xff, 0xff, 0xff, 0xff},
1768 {0xff, 0x00, 0x02, 0xff}
1769 },
1770 {
1771 {0xff, 0x01, 0xff, 0xff},
1772 {0xff, 0x03, 0xff, 0x06}
1773 }
1774 },
1775 {
1776 {
1777 {0xff, 0xff, 0xff, 0xff},
1778 {0xff, 0x04, 0x06, 0x08}
1779 },
1780 {
1781 {0xff, 0xff, 0xff, 0xff},
1782 {0x05, 0x07, 0x09, 0xff}
1783 }
1784 }};
1785
Arthur Heymans6bf13012017-06-10 12:03:27 +02001786 static const u8 dradrb[10][6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001787 //Row Col Bank Width DRB
1788 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1789 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1790 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1791 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1792 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1793 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1794 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1795 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1796 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1797 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1798 };
1799
1800 reg32 = 0;
1801 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1802 i = r / 2;
1803 PRINTK_DEBUG("RANK %d PRESENT\n", r);
Angel Pons39ff7032020-03-09 21:39:44 +01001804 dra = dratab
1805 [s->dimms[i].banks]
Damien Zammit003d15c2015-11-20 17:17:51 +11001806 [s->dimms[i].width]
1807 [s->dimms[i].cols - 9]
1808 [s->dimms[i].rows - 12];
1809
1810 if (s->dimms[i].banks == 1) {
1811 dra |= (1 << 7);
1812 }
Angel Pons39ff7032020-03-09 21:39:44 +01001813 reg32 |= (dra << (r * 8));
Damien Zammit003d15c2015-11-20 17:17:51 +11001814 }
Angel Pons39ff7032020-03-09 21:39:44 +01001815 MCHBAR32(C0DRA01) = reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +11001816 c0dra = reg32;
1817 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1818
1819 reg32 = 0;
1820 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1821 reg32 |= (1 << r);
1822 }
1823 reg8 = (u8)(reg32 << 4) & 0xf0;
Angel Pons39ff7032020-03-09 21:39:44 +01001824 MCHBAR8_AND_OR(C0CKECTRL + 2, ~0xf0, reg8);
1825
1826 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) || ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1827 MCHBAR8_OR(C0CKECTRL, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001828 }
1829
Angel Pons39ff7032020-03-09 21:39:44 +01001830 addr = C0DRB0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001831 c0drb = 0;
1832 FOR_EACH_RANK(ch, r) {
1833 if (rank_is_populated(s->dimms, ch, r)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001834 ind = (c0dra >> (8 * r)) & 0x7f;
Damien Zammit003d15c2015-11-20 17:17:51 +11001835 c0drb = (u16)(c0drb + dradrb[ind][5]);
1836 s->channel_capacity[0] += dradrb[ind][5] << 6;
1837 }
1838 MCHBAR16(addr) = c0drb;
1839 addr += 2;
1840 }
1841 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1842}
1843
1844static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1845{
Damien Zammit003d15c2015-11-20 17:17:51 +11001846 u8 dqsmatches = 1;
1847 while (count--) {
Angel Pons39ff7032020-03-09 21:39:44 +01001848 MCHBAR8_AND(C0RSTCTL, ~2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001849 hpet_udelay(1);
Angel Pons39ff7032020-03-09 21:39:44 +01001850 MCHBAR8_OR(C0RSTCTL, 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001851 hpet_udelay(1);
1852 barrier();
Elyes HAOUASaf159d42019-05-22 20:19:22 +02001853 read32((void *)strobeaddr);
Damien Zammit003d15c2015-11-20 17:17:51 +11001854 barrier();
1855 hpet_udelay(1);
1856
1857 if (((MCHBAR8(dqshighaddr) & 0x40) >> 6) != highlow) {
1858 dqsmatches = 0;
1859 }
1860 }
1861
1862 return dqsmatches;
1863}
1864
Angel Pons39ff7032020-03-09 21:39:44 +01001865static void rcvenclock(u8 *coarse, u8 *medium, u8 lane)
Damien Zammit003d15c2015-11-20 17:17:51 +11001866{
1867 if (*medium < 3) {
1868 (*medium)++;
Angel Pons39ff7032020-03-09 21:39:44 +01001869 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001870 } else {
1871 *medium = 0;
1872 (*coarse)++;
Angel Pons39ff7032020-03-09 21:39:44 +01001873 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, *coarse << 16);
1874 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)(~3 << (lane * 2)), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001875 }
1876}
1877
1878static void sdram_rcven(struct sysinfo *s)
1879{
Angel Pons39ff7032020-03-09 21:39:44 +01001880 u8 coarse, savecoarse;
1881 u8 medium, savemedium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001882 u8 pi, savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01001883 u8 lane;
1884 u8 lanecoarse[8] = {0};
1885 u8 minlanecoarse = 0xff;
1886 u8 offset;
1887 u8 maxlane = 8;
Arthur Heymans015339f2018-08-20 11:28:58 +02001888 /* Since dra/drb is already set up we know that at address 0x00000000
1889 we will always find the first available rank */
1890 u32 strobeaddr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001891 u32 dqshighaddr;
1892
Angel Pons39ff7032020-03-09 21:39:44 +01001893 MCHBAR8_AND(C0RSTCTL, ~0x0c);
1894 MCHBAR8_AND(CMNDQFIFORST, ~0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11001895
1896 PRINTK_DEBUG("rcven 0\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001897 for (lane = 0; lane < maxlane; lane++) {
1898 PRINTK_DEBUG("rcven lane %d\n", lane);
1899// trylaneagain:
1900 dqshighaddr = C0MISCCTLy(lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001901
Angel Pons39ff7032020-03-09 21:39:44 +01001902 coarse = s->selected_timings.CAS + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11001903 pi = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001904 medium = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001905
Angel Pons39ff7032020-03-09 21:39:44 +01001906 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1907 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001908
Angel Pons39ff7032020-03-09 21:39:44 +01001909 MCHBAR8_AND(C0RXRCVyDLL(lane), ~0x3f);
1910
1911 savecoarse = coarse;
1912 savemedium = medium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001913 savepi = pi;
1914
1915 PRINTK_DEBUG("rcven 0.1\n");
1916
Angel Pons39ff7032020-03-09 21:39:44 +01001917 // XXX comment out
1918 // MCHBAR16_AND_OR(C0RCVMISCCTL1, (u16)~3 << (lane * 2), 1 << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001919
1920 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001921 // printk(BIOS_DEBUG, "coarse=%d medium=%d\n", coarse, medium);
1922 rcvenclock(&coarse, &medium, lane);
1923 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001924 PRINTK_DEBUG("Error: coarse > 0xf\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001925 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001926 break;
1927 }
1928 }
1929 PRINTK_DEBUG("rcven 0.2\n");
1930
Angel Pons39ff7032020-03-09 21:39:44 +01001931 savecoarse = coarse;
1932 savemedium = medium;
1933 rcvenclock(&coarse, &medium, lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001934
1935 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001936 savecoarse = coarse;
1937 savemedium = medium;
1938 rcvenclock(&coarse, &medium, lane);
1939 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001940 PRINTK_DEBUG("Error: coarse > 0xf\n");
1941 //goto trylaneagain;
1942 break;
1943 }
1944 }
1945
1946 PRINTK_DEBUG("rcven 0.3\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001947 coarse = savecoarse;
1948 medium = savemedium;
1949 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1950 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(0x3 << lane * 2), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001951
1952 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1953 savepi = pi;
1954 pi++;
1955 if (pi > s->maxpi) {
Angel Pons39ff7032020-03-09 21:39:44 +01001956 // if (s->nodll) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001957 pi = savepi = s->maxpi;
1958 break;
Angel Pons39ff7032020-03-09 21:39:44 +01001959 // }
Damien Zammit003d15c2015-11-20 17:17:51 +11001960 }
Angel Pons39ff7032020-03-09 21:39:44 +01001961 MCHBAR8_AND_OR(C0RXRCVyDLL(lane), ~0x3f, pi << s->pioffset);
Damien Zammit003d15c2015-11-20 17:17:51 +11001962 }
1963 PRINTK_DEBUG("rcven 0.4\n");
1964
1965 pi = savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01001966 MCHBAR8_AND_OR(C0RXRCVyDLL(lane), ~0x3f, pi << s->pioffset);
1967 rcvenclock(&coarse, &medium, lane);
1968
Damien Zammit003d15c2015-11-20 17:17:51 +11001969 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1970 PRINTK_DEBUG("Error: DQS not high\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001971 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001972 }
1973 PRINTK_DEBUG("rcven 0.5\n");
1974 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001975 coarse--;
1976 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1977 if (coarse == 0) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +02001978 PRINTK_DEBUG("Error: DQS did not hit 0\n");
Damien Zammit003d15c2015-11-20 17:17:51 +11001979 break;
1980 }
1981 }
1982
1983 PRINTK_DEBUG("rcven 0.6\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001984 rcvenclock(&coarse, &medium, lane);
1985 s->pi[lane] = pi;
1986 lanecoarse[lane] = coarse;
Damien Zammit003d15c2015-11-20 17:17:51 +11001987 }
1988
1989 PRINTK_DEBUG("rcven 1\n");
1990
Angel Pons39ff7032020-03-09 21:39:44 +01001991 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11001992 do {
Angel Pons39ff7032020-03-09 21:39:44 +01001993 lane--;
1994 if (minlanecoarse > lanecoarse[lane]) {
1995 minlanecoarse = lanecoarse[lane];
Damien Zammit003d15c2015-11-20 17:17:51 +11001996 }
Angel Pons39ff7032020-03-09 21:39:44 +01001997 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001998
Angel Pons39ff7032020-03-09 21:39:44 +01001999 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11002000 do {
Angel Pons39ff7032020-03-09 21:39:44 +01002001 lane--;
2002 offset = lanecoarse[lane] - minlanecoarse;
2003 MCHBAR16_AND_OR(C0COARSEDLY0, (u16)(~(3 << (lane * 2))), offset << (lane * 2));
2004 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002005
Angel Pons39ff7032020-03-09 21:39:44 +01002006 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, minlanecoarse << 16);
Damien Zammit003d15c2015-11-20 17:17:51 +11002007
Angel Pons39ff7032020-03-09 21:39:44 +01002008 s->coarsectrl = minlanecoarse;
2009 s->coarsedelay = MCHBAR16(C0COARSEDLY0);
2010 s->mediumphase = MCHBAR16(C0RCVMISCCTL2);
2011 s->readptrdelay = MCHBAR16(C0RCVMISCCTL1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002012
2013 PRINTK_DEBUG("rcven 2\n");
Angel Pons39ff7032020-03-09 21:39:44 +01002014 MCHBAR8_AND(C0RSTCTL, ~0x0e);
2015 MCHBAR8_OR(C0RSTCTL, 0x02);
2016 MCHBAR8_OR(C0RSTCTL, 0x04);
2017 MCHBAR8_OR(C0RSTCTL, 0x08);
Damien Zammit003d15c2015-11-20 17:17:51 +11002018
Angel Pons39ff7032020-03-09 21:39:44 +01002019 MCHBAR8_OR(CMNDQFIFORST, 0x80);
2020 MCHBAR8_AND(CMNDQFIFORST, ~0x80);
2021 MCHBAR8_OR(CMNDQFIFORST, 0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11002022 PRINTK_DEBUG("rcven 3\n");
2023}
2024
Angel Pons39ff7032020-03-09 21:39:44 +01002025/* NOTE: Unless otherwise specified, the values are expressed in MiB */
Damien Zammit003d15c2015-11-20 17:17:51 +11002026static void sdram_mmap_regs(struct sysinfo *s)
2027{
2028 bool reclaim;
Angel Pons39ff7032020-03-09 21:39:44 +01002029 u32 mmiosize, tom, tolud, touud, reclaimbase, reclaimlimit;
2030 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase, tsegsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002031 u16 ggc;
Angel Pons39ff7032020-03-09 21:39:44 +01002032 u16 ggc_to_uma[10] = {0, 1, 4, 8, 16, 32, 48, 64, 128, 256};
2033 u8 ggc_to_gtt[4] = {0, 1, 0, 0};
Damien Zammit003d15c2015-11-20 17:17:51 +11002034
Angel Pons39ff7032020-03-09 21:39:44 +01002035 reclaimbase = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002036 reclaimlimit = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002037
2038 ggc = pci_read_config16(HOST_BRIDGE, GGC);
Damien Zammit51fdb922016-01-18 18:34:52 +11002039 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
Angel Pons39ff7032020-03-09 21:39:44 +01002040
2041 gfxsize = ggc_to_uma[(ggc & 0x00f0) >> 4];
2042
2043 gttsize = ggc_to_gtt[(ggc & 0x0300) >> 8];
2044
Damien Zammit003d15c2015-11-20 17:17:51 +11002045 tom = s->channel_capacity[0];
2046
Angel Pons39ff7032020-03-09 21:39:44 +01002047 /* With GTT always being 1M, TSEG 1M is the only setting that can
Arthur Heymansda44e342019-01-12 01:38:02 +01002048 be covered by SMRR which has alignment requirements. */
Angel Pons39ff7032020-03-09 21:39:44 +01002049 tsegsize = 1;
2050 mmiosize = 1024;
Damien Zammit003d15c2015-11-20 17:17:51 +11002051
2052 reclaim = false;
Angel Pons39ff7032020-03-09 21:39:44 +01002053 tolud = MIN(4096 - mmiosize, tom);
2054 if ((tom - tolud) > 64) {
Arthur Heymansaaebb412017-08-27 18:46:12 +02002055 reclaim = true;
Damien Zammit003d15c2015-11-20 17:17:51 +11002056 }
2057 if (reclaim) {
2058 tolud = tolud & ~0x3f;
Angel Pons39ff7032020-03-09 21:39:44 +01002059 tom = tom & ~0x3f;
2060 reclaimbase = MAX(4096, tom);
2061 reclaimlimit = reclaimbase + (MIN(4096, tom) - tolud) - 0x40;
Damien Zammit003d15c2015-11-20 17:17:51 +11002062 }
2063 touud = tom;
2064 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002065 touud = reclaimlimit + 64;
Damien Zammit003d15c2015-11-20 17:17:51 +11002066 }
2067
Angel Pons39ff7032020-03-09 21:39:44 +01002068 gfxbase = tolud - gfxsize;
2069 gttbase = gfxbase - gttsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002070 tsegbase = gttbase - tsegsize;
2071
2072 /* Program the regs */
Angel Pons39ff7032020-03-09 21:39:44 +01002073 pci_write_config16(HOST_BRIDGE, TOLUD, (u16)(tolud << 4));
2074 pci_write_config16(HOST_BRIDGE, TOM, (u16)(tom >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002075 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002076 pci_write_config16(HOST_BRIDGE, 0x98, (u16)(reclaimbase >> 6));
2077 pci_write_config16(HOST_BRIDGE, 0x9a, (u16)(reclaimlimit >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002078 }
Angel Pons39ff7032020-03-09 21:39:44 +01002079 pci_write_config16(HOST_BRIDGE, TOUUD, (u16)(touud));
2080 pci_write_config32(HOST_BRIDGE, GBSM, gfxbase << 20);
2081 pci_write_config32(HOST_BRIDGE, BGSM, gttbase << 20);
2082 pci_write_config32(HOST_BRIDGE, TSEG, tsegbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002083
Angel Pons39ff7032020-03-09 21:39:44 +01002084 u8 reg8 = pci_read_config8(HOST_BRIDGE, ESMRAMC);
2085 reg8 &= ~0x07;
Arthur Heymansda44e342019-01-12 01:38:02 +01002086 reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
Angel Pons39ff7032020-03-09 21:39:44 +01002087 pci_write_config8(HOST_BRIDGE, ESMRAMC, reg8);
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002088
Damien Zammit51fdb922016-01-18 18:34:52 +11002089 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002090 pci_read_config32(HOST_BRIDGE, GBSM), gfxbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002091 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002092 pci_read_config32(HOST_BRIDGE, BGSM), gttbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002093 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002094 pci_read_config32(HOST_BRIDGE, TSEG), tsegbase << 20);
Damien Zammit003d15c2015-11-20 17:17:51 +11002095}
2096
2097static void sdram_enhancedmode(struct sysinfo *s)
2098{
Angel Pons39ff7032020-03-09 21:39:44 +01002099 u8 reg8, ch, r, fsb_freq, ddr_freq;
Damien Zammit003d15c2015-11-20 17:17:51 +11002100 u32 mask32, reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002101 MCHBAR8_OR(C0ADDCSCTRL, 1);
2102 MCHBAR8_OR(C0REFRCTRL + 3, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002103 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
Angel Pons39ff7032020-03-09 21:39:44 +01002104 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2105 MCHBAR32_AND_OR(WRWMCONFIG, ~mask32, reg32);
2106 MCHBAR8(C0DITCTRL + 1) = 2;
2107 MCHBAR16(C0DITCTRL + 2) = 0x0804;
2108 MCHBAR16(C0DITCTRL + 4) = 0x2010;
2109 MCHBAR8(C0DITCTRL + 6) = 0x40;
2110 MCHBAR16(C0DITCTRL + 8) = 0x091c;
2111 MCHBAR8(C0DITCTRL + 10) = 0xf2;
2112 MCHBAR8_OR(C0BYPCTRL, 1);
2113 MCHBAR8_OR(C0CWBCTRL, 1);
2114 MCHBAR16_OR(C0ARBSPL, 0x0100);
Damien Zammit003d15c2015-11-20 17:17:51 +11002115
Angel Pons26766fd2020-06-08 12:38:19 +02002116 pci_or_config8(HOST_BRIDGE, 0xf0, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01002117 MCHBAR32(SBCTL) = 0x00000002;
2118 MCHBAR32(SBCTL2) = 0x20310002;
2119 MCHBAR32(SLIMCFGTMG) = 0x02020302;
2120 MCHBAR32(HIT0) = 0x001f1806;
2121 MCHBAR32(HIT1) = 0x01102800;
2122 MCHBAR32(HIT2) = 0x07000000;
2123 MCHBAR32(HIT3) = 0x01014010;
2124 MCHBAR32(HIT4) = 0x0f038000;
Angel Pons26766fd2020-06-08 12:38:19 +02002125 pci_and_config8(HOST_BRIDGE, 0xf0, ~1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002126
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002127 u32 nranks, curranksize, maxranksize, dra;
2128 u8 rankmismatch;
Angel Pons39ff7032020-03-09 21:39:44 +01002129 static const u8 drbtab[10] = {0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8, 0x20, 0x10};
Damien Zammit003d15c2015-11-20 17:17:51 +11002130
2131 nranks = 0;
2132 curranksize = 0;
2133 maxranksize = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002134 rankmismatch = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002135
Damien Zammit003d15c2015-11-20 17:17:51 +11002136 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2137 nranks++;
Angel Pons39ff7032020-03-09 21:39:44 +01002138 dra = (u8) ((MCHBAR32(C0DRA01) >> (8 * r)) & 0x7f);
Damien Zammit003d15c2015-11-20 17:17:51 +11002139 curranksize = drbtab[dra];
2140 if (maxranksize == 0) {
2141 maxranksize = curranksize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002142 }
2143 if (curranksize != maxranksize) {
2144 rankmismatch = 1;
2145 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002146 }
2147
2148 reg8 = 0;
2149 switch (nranks) {
2150 case 4:
2151 if (rankmismatch) {
2152 reg8 = 0x64;
2153 } else {
2154 reg8 = 0xa4;
2155 }
2156 break;
2157 case 1:
2158 case 3:
2159 reg8 = 0x64;
2160 break;
2161 case 2:
2162 if (rankmismatch) {
2163 reg8 = 0x64;
2164 } else {
2165 reg8 = 0x24;
2166 }
2167 break;
2168 default:
2169 die("Invalid number of ranks found, halt\n");
2170 break;
2171 }
Angel Pons39ff7032020-03-09 21:39:44 +01002172 MCHBAR8_AND_OR(CHDECMISC, ~0xfc, reg8 & 0xfc);
2173 MCHBAR32_AND(NOACFGBUSCTL, ~0x80000000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002174
Angel Pons39ff7032020-03-09 21:39:44 +01002175 MCHBAR32(HTBONUS0) = 0x0000000f;
2176 MCHBAR8_OR(C0COREBONUS + 4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002177
Angel Pons39ff7032020-03-09 21:39:44 +01002178 MCHBAR32_AND(HIT3, ~0x0e000000);
2179 MCHBAR32_AND_OR(HIT4, ~0x000c0000, 0x00040000);
2180
Damien Zammit003d15c2015-11-20 17:17:51 +11002181 u32 clkcx[2][2][3] = {
Angel Pons39ff7032020-03-09 21:39:44 +01002182 {
2183 {0x00000000, 0x0c080302, 0x08010204}, /* FSB = 667, DDR = 667 */
2184 {0x02040000, 0x08100102, 0x00000000}, /* FSB = 667, DDR = 800 */
2185 },
2186 {
2187 {0x18000000, 0x3021060c, 0x20010208}, /* FSB = 800, DDR = 667 */
2188 {0x00000000, 0x0c090306, 0x00000000}, /* FSB = 800, DDR = 800 */
2189 }
2190 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002191
Angel Pons39ff7032020-03-09 21:39:44 +01002192 fsb_freq = s->selected_timings.fsb_clock;
2193 ddr_freq = s->selected_timings.mem_clock;
2194
2195 MCHBAR32(CLKXSSH2X2MD) = clkcx[fsb_freq][ddr_freq][0];
2196 MCHBAR32(CLKXSSH2X2MD + 4) = clkcx[fsb_freq][ddr_freq][1];
2197 MCHBAR32(CLKXSSH2MCBYP + 4) = clkcx[fsb_freq][ddr_freq][2];
2198
2199 MCHBAR8_AND(HIT4, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11002200}
2201
2202static void sdram_periodic_rcomp(void)
2203{
Angel Pons39ff7032020-03-09 21:39:44 +01002204 MCHBAR8_AND(COMPCTRL1, ~0x02);
2205 while ((MCHBAR32(COMPCTRL1) & 0x80000000) > 0) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002206 ;
2207 }
Angel Pons39ff7032020-03-09 21:39:44 +01002208 MCHBAR16_AND(CSHRMISCCTL, ~0x3000);
2209 MCHBAR8_OR(CMNDQFIFORST, 0x80);
2210 MCHBAR16_AND_OR(XCOMPDFCTRL, ~0x0f, 0x09);
Damien Zammit003d15c2015-11-20 17:17:51 +11002211
Angel Pons39ff7032020-03-09 21:39:44 +01002212 MCHBAR8_OR(COMPCTRL1, 0x82);
Damien Zammit003d15c2015-11-20 17:17:51 +11002213}
2214
2215static void sdram_new_trd(struct sysinfo *s)
2216{
2217 u8 pidelay, i, j, k, cc, trd_perphase[5];
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002218 u8 bypass, freqgb, trd, reg8, txfifo;
Damien Zammit003d15c2015-11-20 17:17:51 +11002219 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2220 u16 tmclk, thclk, buffertocore, postcalib;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002221 static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2222 static const u16 trd_adjust[2][2][5] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11002223 {
2224 {3000, 3000, 0,0,0},
2225 {1000,2000,3000,1500,2500}
2226 },
2227 {
2228 {2000,1000,3000,0,0},
2229 {2500, 2500, 0,0,0}
2230 }};
2231
2232 freqgb = 110;
2233 buffertocore = 5000;
Damien Zammit003d15c2015-11-20 17:17:51 +11002234 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2235 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2236 tmclk = tmclk * 100 / freqgb;
2237 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2238 switch (s->selected_timings.mem_clock) {
2239 case MEM_CLOCK_667MHz:
2240 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2241 cc = 2;
2242 } else {
2243 cc = 3;
2244 }
2245 break;
2246 default:
2247 case MEM_CLOCK_800MHz:
2248 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2249 cc = 5;
2250 } else {
2251 cc = 2;
2252 }
2253 break;
2254 }
2255 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2256 maxrcvendelay = 0;
2257 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2258
2259 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01002260 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 3) * (u32)(tmclk));
2261 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 3) * (u32)(tmclk) / 2);
2262 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 3) * (u32)(tmclk) / 4);
2263 rcvendelay += (u32)(pidelay * s->pi[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002264 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2265 }
2266
Angel Pons39ff7032020-03-09 21:39:44 +01002267 if ((MCHBAR8(HMBYPCP + 3) == 0xff) && (MCHBAR8(HMCCMC) & 0x80)) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002268 bypass = 1;
2269 } else {
2270 bypass = 0;
2271 }
2272
2273 txfifo = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002274 reg8 = (MCHBAR8(CSHRFIFOCTL) & 0x0e) >> 1;
2275 txfifo = txfifo_lut[reg8] & 0x07;
Damien Zammit003d15c2015-11-20 17:17:51 +11002276
2277 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2278 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2279 if (s->async) {
2280 datadelay += tmclk / 2;
2281 }
2282
2283 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2284 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2285
2286 if (j == 0 && k == 0) {
2287 datadelay -= 3084;
2288 }
2289
2290 trd = 0;
2291 for (i = 0; i < cc; i++) {
2292 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2293 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2294 trd_perphase[i] += 1;
2295 if (trd_perphase[i] > trd) {
2296 trd = trd_perphase[i];
2297 }
2298 }
2299
Angel Pons39ff7032020-03-09 21:39:44 +01002300 MCHBAR16_AND_OR(C0STATRDCTRL, ~0x1f00, trd << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11002301}
2302
2303static void sdram_powersettings(struct sysinfo *s)
2304{
2305 u8 j;
2306 u32 reg32;
2307
2308 /* Thermal sensor */
Angel Pons39ff7032020-03-09 21:39:44 +01002309 MCHBAR8(TSC1) = 0x9b;
2310 MCHBAR32_AND_OR(TSTTP, ~0x00ffffff, 0x1d00);
2311 MCHBAR8(THERM1) = 0x08;
2312 MCHBAR8(TSC3) = 0x00;
2313 MCHBAR8_AND_OR(TSC2, ~0x0f, 0x04);
2314 MCHBAR8_AND_OR(THERM1, ~1, 1);
2315 MCHBAR8_AND_OR(TCO, ~0x80, 0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11002316
2317 /* Clock gating */
Angel Pons39ff7032020-03-09 21:39:44 +01002318 MCHBAR32_AND(PMMISC, ~0x00040001);
2319 MCHBAR8_AND(SBCTL3 + 3, ~0x80);
2320 MCHBAR8_AND(CISDCTRL + 3, ~0x80);
2321 MCHBAR16_AND(CICGDIS, ~0x1fff);
2322 MCHBAR32_AND(SBCLKGATECTRL, ~0x0001ffff);
Angel Pons7ee1c472021-03-26 18:33:31 +01002323 MCHBAR16_AND_OR(HICLKGTCTL, ~0x03ff, 0x06);
Angel Pons39ff7032020-03-09 21:39:44 +01002324 MCHBAR32_AND_OR(HTCLKGTCTL, ~0xffffffff, 0x20);
2325 MCHBAR8_AND(TSMISC, ~1);
2326 MCHBAR8(C0WRDPYN) = s->selected_timings.CAS - 1 + 0x15;
2327 MCHBAR16_AND_OR(CLOCKGATINGI, ~0x07fc, 0x0040);
2328 MCHBAR16_AND_OR(CLOCKGATINGII, ~0x0fff, 0x0d00);
2329 MCHBAR16_AND(CLOCKGATINGIII, ~0x0d80);
2330 MCHBAR16(GTDPCGC + 2) = 0xffff;
Damien Zammit003d15c2015-11-20 17:17:51 +11002331
2332 /* Sequencing */
Angel Pons39ff7032020-03-09 21:39:44 +01002333 MCHBAR32(HPWRCTL1) = (MCHBAR32(HPWRCTL1) & ~0x1fffffff) | 0x1f643fff;
2334 MCHBAR32(HPWRCTL2) = (MCHBAR32(HPWRCTL2) & ~0xffffff7f) | 0x02010000;
2335 MCHBAR16(HPWRCTL3) = (MCHBAR16(HPWRCTL3) & ~0x7000) | (3 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11002336
2337 /* Power */
Angel Pons39ff7032020-03-09 21:39:44 +01002338 MCHBAR32(GFXC3C4) = (MCHBAR32(GFXC3C4) & ~0xffff0003) | 0x10100000;
2339 MCHBAR32(PMDSLFRC) = (MCHBAR32(PMDSLFRC) & ~0x0001bff7) | 0x00000078;
2340
2341 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz)
2342 MCHBAR16_AND_OR(PMMSPMRES, ~0x03ff, 0x00c8);
2343 else
2344 MCHBAR16_AND_OR(PMMSPMRES, ~0x03ff, 0x0100);
2345
Damien Zammit003d15c2015-11-20 17:17:51 +11002346 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2347
Angel Pons39ff7032020-03-09 21:39:44 +01002348 MCHBAR32_AND_OR(PMCLKRC, ~0x01fff37f, 0x10810700);
2349 MCHBAR8_AND_OR(PMPXPRC, ~0x07, 1);
2350 MCHBAR8_AND(PMBAK, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11002351
Angel Pons39ff7032020-03-09 21:39:44 +01002352 static const u16 ddr2lut[2][4][2] = {
2353 {
2354 {0x0000, 0x0000},
2355 {0x019A, 0x0039},
2356 {0x0099, 0x1049},
2357 {0x0000, 0x0000},
2358 },
2359 {
2360 {0x0000, 0x0000},
2361 {0x019A, 0x0039},
2362 {0x0099, 0x1049},
2363 {0x0099, 0x2159},
2364 },
2365 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002366
Angel Pons39ff7032020-03-09 21:39:44 +01002367 MCHBAR16(C0C2REG) = 0x7a89;
2368 MCHBAR8(SHC2REGII) = 0xaa;
2369 MCHBAR16(SHC2REGII + 1) = ddr2lut[j][s->selected_timings.CAS - 3][1];
2370 MCHBAR16_AND_OR(SHC2REGI, ~0x7fff, ddr2lut[j][s->selected_timings.CAS - 3][0]);
2371 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0xf000, 0xf000);
2372 MCHBAR8(CSHWRIOBONUSX) = (MCHBAR8(CSHWRIOBONUSX) & ~0x77) | (4 << 4 | 4);
Damien Zammit003d15c2015-11-20 17:17:51 +11002373
Angel Pons39ff7032020-03-09 21:39:44 +01002374 reg32 = s->nodll ? 0x30000000 : 0;
2375
2376 /* FIXME: Compacting this results in changes to the binary */
2377 MCHBAR32(C0COREBONUS) = (MCHBAR32(C0COREBONUS) & ~0x0f000000) | 0x20000000 | reg32;
2378
2379 MCHBAR32_AND_OR(CLOCKGATINGI, ~0x00f00000, 0x00f00000);
2380 MCHBAR32_AND_OR(CLOCKGATINGII - 1, ~0x001ff000, 0xbf << 20);
2381 MCHBAR16_AND_OR(SHC3C4REG2, ~0x1f7f, (0x0b << 8) | (7 << 4) | 0x0b);
2382 MCHBAR16(SHC3C4REG3) = 0x3264;
2383 MCHBAR16_AND_OR(SHC3C4REG4, ~0x3f3f, (0x14 << 8) | 0x0a);
2384
2385 MCHBAR32_OR(C1COREBONUS, 0x80002000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002386}
2387
2388static void sdram_programddr(void)
2389{
Angel Pons39ff7032020-03-09 21:39:44 +01002390 MCHBAR16_AND_OR(CLOCKGATINGII, ~0x03ff, 0x0100);
2391 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0x003f, 0x0010);
2392 MCHBAR16_AND_OR(CLOCKGATINGI, ~0x7000, 0x2000);
2393
2394 MCHBAR8_AND(CSHRPDCTL, ~0x0e);
2395 MCHBAR8_AND(CSHRWRIOMLNS, ~0x0c);
2396 MCHBAR8_AND(C0MISCCTLy(0), ~0x0e);
2397 MCHBAR8_AND(C0MISCCTLy(1), ~0x0e);
2398 MCHBAR8_AND(C0MISCCTLy(2), ~0x0e);
2399 MCHBAR8_AND(C0MISCCTLy(3), ~0x0e);
2400 MCHBAR8_AND(C0MISCCTLy(4), ~0x0e);
2401 MCHBAR8_AND(C0MISCCTLy(5), ~0x0e);
2402 MCHBAR8_AND(C0MISCCTLy(6), ~0x0e);
2403 MCHBAR8_AND(C0MISCCTLy(7), ~0x0e);
2404 MCHBAR8_AND(CSHRWRIOMLNS, ~0x02);
2405
2406 MCHBAR16_AND(CSHRMISCCTL, ~0x0400);
2407 MCHBAR16_AND(CLOCKGATINGIII, ~0x0dc0);
2408 MCHBAR8_AND(C0WRDPYN, ~0x80);
2409 MCHBAR32_AND(C0COREBONUS, ~(1 << 22));
2410 MCHBAR16_AND(CLOCKGATINGI, ~0x80fc);
2411 MCHBAR16_AND(CLOCKGATINGII, ~0x0c00);
2412
2413 MCHBAR8_AND(CSHRPDCTL, ~0x0d);
2414 MCHBAR8_AND(C0MISCCTLy(0), ~1);
2415 MCHBAR8_AND(C0MISCCTLy(1), ~1);
2416 MCHBAR8_AND(C0MISCCTLy(2), ~1);
2417 MCHBAR8_AND(C0MISCCTLy(3), ~1);
2418 MCHBAR8_AND(C0MISCCTLy(4), ~1);
2419 MCHBAR8_AND(C0MISCCTLy(5), ~1);
2420 MCHBAR8_AND(C0MISCCTLy(6), ~1);
2421 MCHBAR8_AND(C0MISCCTLy(7), ~1);
2422
2423 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x00700000, 3 << 20);
2424 MCHBAR32_AND(C0COREBONUS, ~0x00100000);
2425 MCHBAR8_OR(C0DYNSLVDLLEN, 0x1e);
2426 MCHBAR8_OR(C0DYNSLVDLLEN2, 0x03);
2427 MCHBAR32_AND_OR(SHCYCTRKCKEL, ~0x0c000000, 0x04000000);
2428 MCHBAR16_OR(C0STATRDCTRL, 0x6000);
2429 MCHBAR32_OR(C0CKECTRL, 0x00010000);
2430 MCHBAR8_OR(C0COREBONUS, 0x10);
2431 MCHBAR32_OR(CLOCKGATINGI - 1, 0xf << 24);
2432 MCHBAR8_OR(CSHWRIOBONUS, 0x07);
2433 MCHBAR8_OR(C0DYNSLVDLLEN, 0xc0);
2434 MCHBAR8_OR(SHC2REGIII, 7);
2435 MCHBAR16_AND_OR(SHC2MINTM, ~0xffff, 0x0080);
2436 MCHBAR8_AND_OR(SHC2IDLETM, ~0xff, 0x10);
2437 MCHBAR16_OR(C0COREBONUS, 0x01e0);
2438 MCHBAR8_OR(CSHWRIOBONUS, 0x18);
2439 MCHBAR8_OR(CSHRMSTDYNDLLENB, 0x0d);
2440 MCHBAR16_OR(SHC3C4REG1, 0x0a3f);
2441 MCHBAR8_OR(C0STATRDCTRL, 3);
2442 MCHBAR8_AND_OR(C0REFRCTRL2, ~0xff, 0x4a);
2443 MCHBAR8_AND(C0COREBONUS + 4, ~0x60);
2444 MCHBAR16_OR(C0DYNSLVDLLEN, 0x0321);
Damien Zammit003d15c2015-11-20 17:17:51 +11002445}
2446
2447static void sdram_programdqdqs(struct sysinfo *s)
2448{
2449 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2450 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2451 u8 repeat, halfclk, feature, reg8, push;
2452 u16 cwb, pimdclk;
2453 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002454 static const u8 txfifotab[8] = {0, 7, 6, 5, 2, 1, 4, 3};
Damien Zammit003d15c2015-11-20 17:17:51 +11002455
2456 tpi = 3000;
2457 dqdqs_out = 4382;
2458 dqdqs_outdelay = 5083;
2459 dqdqs_delay = 4692;
2460 coretomcp = 0;
2461 txdelay = 0;
2462 halfclk = 0;
2463 tmaxunmask = 0;
2464 tmaxpi = 0;
2465 repeat = 2;
2466 feature = 0;
2467 cwb = 0;
2468 pimdclk = 0;
2469 reg32 = 0;
2470 push = 0;
2471 reg8 = 0;
2472
2473 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2474 refclk = 3000 - mdclk;
2475
Angel Pons39ff7032020-03-09 21:39:44 +01002476 coretomcp = ((MCHBAR8(C0ADDCSCTRL) >> 2) & 0x3) + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002477 coretomcp *= mdclk;
2478
Angel Pons39ff7032020-03-09 21:39:44 +01002479 reg8 = (MCHBAR8(CSHRFIFOCTL) & 0x0e) >> 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002480
2481 while (repeat) {
2482 txdelay = mdclk * (
Angel Pons39ff7032020-03-09 21:39:44 +01002483 ((MCHBAR16(C0GNT2LNCH1) >> 8) & 0x7) +
2484 (MCHBAR8(C0WRDATACTRL) & 0xf) +
2485 (MCHBAR8(C0WRDATACTRL + 1) & 0x1)
Damien Zammit003d15c2015-11-20 17:17:51 +11002486 ) +
Angel Pons39ff7032020-03-09 21:39:44 +01002487 txfifotab[reg8]*(mdclk / 2) +
Damien Zammit003d15c2015-11-20 17:17:51 +11002488 coretomcp +
2489 refclk +
2490 cwb;
Angel Pons39ff7032020-03-09 21:39:44 +01002491 halfclk = (MCHBAR8(C0MISCCTL) >> 1) & 0x1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002492 if (halfclk) {
2493 txdelay -= mdclk / 2;
2494 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2495 } else {
2496 reg32 = dqdqs_outdelay + coretomcp;
2497 }
2498
2499 tmaxunmask = txdelay - mdclk - dqdqs_out;
2500 tmaxpi = tmaxunmask - tpi;
2501
2502 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2503 if (repeat == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01002504 MCHBAR32_AND(C0COREBONUS, ~(1 << 23));
Damien Zammit003d15c2015-11-20 17:17:51 +11002505 }
2506 feature = 1;
2507 repeat = 0;
2508 } else {
2509 repeat--;
Angel Pons39ff7032020-03-09 21:39:44 +01002510 MCHBAR32_OR(C0COREBONUS, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +11002511 cwb = 2 * mdclk;
2512 }
2513 }
2514
2515 if (!feature) {
Angel Pons39ff7032020-03-09 21:39:44 +01002516 MCHBAR8(CLOCKGATINGI) = MCHBAR8(CLOCKGATINGI) & ~0x3;
Damien Zammit003d15c2015-11-20 17:17:51 +11002517 return;
2518 }
Angel Pons39ff7032020-03-09 21:39:44 +01002519 MCHBAR8_OR(CLOCKGATINGI, 3);
2520 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0xf000, pimdclk << 12);
2521 MCHBAR8_AND_OR(CSHWRIOBONUSX, ~0x77, (push << 4) | push);
2522 MCHBAR32_AND_OR(C0COREBONUS, ~0x0f000000, 0x03000000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002523}
2524
2525/**
2526 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2527 */
2528void sdram_initialize(int boot_path, const u8 *spd_addresses)
2529{
2530 struct sysinfo si;
Angel Pons39ff7032020-03-09 21:39:44 +01002531 const char *boot_str[] = {"Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002532
2533 PRINTK_DEBUG("Setting up RAM controller.\n");
2534
2535 memset(&si, 0, sizeof(si));
2536
2537 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002538 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002539 si.spd_map[0] = spd_addresses[0];
2540 si.spd_map[1] = spd_addresses[1];
2541 si.spd_map[2] = spd_addresses[2];
2542 si.spd_map[3] = spd_addresses[3];
2543
2544 sdram_read_spds(&si);
2545
2546 /* Choose Common Frequency */
2547 sdram_detect_ram_speed(&si);
2548
2549 /* Determine smallest common tRAS, tRP, tRCD, etc */
2550 sdram_detect_smallest_params(&si);
2551
2552 /* Enable HPET */
2553 enable_hpet();
Damien Zammit003d15c2015-11-20 17:17:51 +11002554
Angel Pons39ff7032020-03-09 21:39:44 +01002555 MCHBAR16_OR(CPCTL, 1 << 15);
Damien Zammit003d15c2015-11-20 17:17:51 +11002556
Damien Zammit003d15c2015-11-20 17:17:51 +11002557 sdram_clk_crossing(&si);
2558
2559 sdram_checkreset();
2560 PRINTK_DEBUG("Done checkreset\n");
2561
2562 sdram_clkmode(&si);
2563 PRINTK_DEBUG("Done clkmode\n");
2564
2565 sdram_timings(&si);
2566 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2567
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002568 if (si.boot_path != BOOT_PATH_RESET) {
2569 sdram_dlltiming(&si);
2570 PRINTK_DEBUG("Done dlltiming\n");
2571 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002572
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002573 if (si.boot_path != BOOT_PATH_RESET) {
2574 sdram_rcomp(&si);
2575 PRINTK_DEBUG("Done RCOMP\n");
2576 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002577
2578 sdram_odt(&si);
2579 PRINTK_DEBUG("Done odt\n");
2580
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002581 if (si.boot_path != BOOT_PATH_RESET) {
Angel Pons39ff7032020-03-09 21:39:44 +01002582 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002583 ;
2584 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002585
2586 sdram_mmap(&si);
2587 PRINTK_DEBUG("Done mmap\n");
2588
Angel Pons39ff7032020-03-09 21:39:44 +01002589 /* Enable DDR IO buffer */
2590 MCHBAR8_AND_OR(C0IOBUFACTCTL, ~0x3f, 0x08);
2591 MCHBAR8_OR(C0RSTCTL, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002592
2593 sdram_rcompupdate(&si);
2594 PRINTK_DEBUG("Done RCOMP update\n");
2595
Angel Pons39ff7032020-03-09 21:39:44 +01002596 MCHBAR8_OR(HIT4, 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11002597
2598 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01002599 MCHBAR32_OR(C0CKECTRL, 1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002600
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002601 sdram_jedecinit(&si);
2602 PRINTK_DEBUG("Done MRS\n");
2603 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002604
2605 sdram_misc(&si);
2606 PRINTK_DEBUG("Done misc\n");
2607
2608 sdram_zqcl(&si);
2609 PRINTK_DEBUG("Done zqcl\n");
2610
2611 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01002612 MCHBAR32_OR(C0REFRCTRL2, 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002613 }
2614
2615 sdram_dradrb(&si);
2616 PRINTK_DEBUG("Done dradrb\n");
2617
2618 sdram_rcven(&si);
2619 PRINTK_DEBUG("Done rcven\n");
2620
2621 sdram_new_trd(&si);
2622 PRINTK_DEBUG("Done tRD\n");
2623
2624 sdram_mmap_regs(&si);
2625 PRINTK_DEBUG("Done mmap regs\n");
2626
2627 sdram_enhancedmode(&si);
2628 PRINTK_DEBUG("Done enhanced mode\n");
2629
2630 sdram_powersettings(&si);
2631 PRINTK_DEBUG("Done power settings\n");
2632
2633 sdram_programddr();
2634 PRINTK_DEBUG("Done programming ddr\n");
2635
2636 sdram_programdqdqs(&si);
2637 PRINTK_DEBUG("Done programming dqdqs\n");
2638
2639 sdram_periodic_rcomp();
2640 PRINTK_DEBUG("Done periodic RCOMP\n");
2641
2642 /* Set init done */
Angel Pons39ff7032020-03-09 21:39:44 +01002643 MCHBAR32_OR(C0REFRCTRL2, 1 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002644
2645 /* Tell ICH7 that we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002646 pci_and_config8(PCI_DEV(0, 0x1f, 0), 0xa2, (u8)~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11002647
2648 /* Tell northbridge we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002649 pci_or_config8(HOST_BRIDGE, 0xf4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002650
2651 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2652}