blob: 391aa829025025d3ff386b64bc4aa17a020462e0 [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 Ponse7a68ec2021-03-26 18:56:16 +0100846 MCHBAR32_AND_OR(C0CKTX, ~0x00030880,
Damien Zammit003d15c2015-11-20 17:17:51 +1100847 (pll->clkdelay[f][i] << 16) |
848 (pll->dben[f][i] << 11) |
Angel Pons39ff7032020-03-09 21:39:44 +0100849 (pll->dbsel[f][i] << 7));
850
851 MCHBAR8_AND_OR(C0TXCK1DLL, ~0x3f, pll->pi[f][i]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100852}
853
Angel Pons39ff7032020-03-09 21:39:44 +0100854/* Program CMD0 and CMD1 registers for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200855static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100856{
857 u8 reg8;
Angel Pons39ff7032020-03-09 21:39:44 +0100858 /* Clock Group Index 3 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100859 reg8 = pll->dbsel[f][i] << 5;
860 reg8 |= pll->dben[f][i] << 6;
Angel Pons39ff7032020-03-09 21:39:44 +0100861 MCHBAR8_AND_OR(C0CMDTX1, ~0x60, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100862
863 reg8 = pll->clkdelay[f][i] << 4;
Angel Pons39ff7032020-03-09 21:39:44 +0100864 MCHBAR8_AND_OR(C0CMDTX2, ~0x30, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100865
866 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100867 MCHBAR8_AND_OR(C0TXCMD0DLL, ~0x3f, reg8);
868 MCHBAR8_AND_OR(C0TXCMD1DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100869}
870
Angel Pons39ff7032020-03-09 21:39:44 +0100871/* Program CTRL registers for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200872static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100873{
874 u8 reg8;
875 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +0100876
877 /* CTRL0 and CTRL1 */
878 reg32 = ((u32) pll->dbsel[f][i]) << 20;
879 reg32 |= ((u32) pll->dben[f][i]) << 21;
Damien Zammit003d15c2015-11-20 17:17:51 +1100880 reg32 |= ((u32) pll->dbsel[f][i]) << 22;
Angel Pons39ff7032020-03-09 21:39:44 +0100881 reg32 |= ((u32) pll->dben[f][i]) << 23;
Damien Zammit003d15c2015-11-20 17:17:51 +1100882 reg32 |= ((u32) pll->clkdelay[f][i]) << 24;
883 reg32 |= ((u32) pll->clkdelay[f][i]) << 27;
Angel Pons39ff7032020-03-09 21:39:44 +0100884 MCHBAR32_AND_OR(C0CTLTX2, ~0x01bf0000, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100885
886 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100887 MCHBAR8_AND_OR(C0TXCTL0DLL, ~0x3f, reg8);
888 MCHBAR8_AND_OR(C0TXCTL1DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100889
Angel Pons39ff7032020-03-09 21:39:44 +0100890 /* CTRL2 and CTRL3 */
891 reg32 = ((u32) pll->dbsel[f][i]) << 12;
892 reg32 |= ((u32) pll->dben[f][i]) << 13;
Damien Zammit003d15c2015-11-20 17:17:51 +1100893 reg32 |= ((u32) pll->dbsel[f][i]) << 8;
Angel Pons39ff7032020-03-09 21:39:44 +0100894 reg32 |= ((u32) pll->dben[f][i]) << 9;
Damien Zammit003d15c2015-11-20 17:17:51 +1100895 reg32 |= ((u32) pll->clkdelay[f][i]) << 14;
896 reg32 |= ((u32) pll->clkdelay[f][i]) << 10;
Angel Pons39ff7032020-03-09 21:39:44 +0100897 MCHBAR32_AND_OR(C0CMDTX2, ~0xff00, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100898
899 reg8 = pll->pi[f][i];
Angel Pons39ff7032020-03-09 21:39:44 +0100900 MCHBAR8_AND_OR(C0TXCTL2DLL, ~0x3f, reg8);
901 MCHBAR8_AND_OR(C0TXCTL3DLL, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100902}
903
904static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
905{
906 u8 rank, dqs, reg8, j;
907 u32 reg32;
908
Angel Pons39ff7032020-03-09 21:39:44 +0100909 j = clk - 40;
910 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100911 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100912 rank = j % 4;
913 dqs = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100914
Angel Pons39ff7032020-03-09 21:39:44 +0100915 reg32 |= ((u32) pll->dben[f][clk]) << (dqs + 9);
Damien Zammit003d15c2015-11-20 17:17:51 +1100916 reg32 |= ((u32) pll->dbsel[f][clk]) << dqs;
Damien Zammit003d15c2015-11-20 17:17:51 +1100917
Nico Huber12d37682021-02-06 14:39:54 +0100918 MCHBAR32_AND_OR(C0DQSRyTX1(rank), ~((1 << (dqs + 9)) | (1 << dqs)), reg32);
Angel Pons39ff7032020-03-09 21:39:44 +0100919
920 reg32 = ((u32) pll->clkdelay[f][clk]) << ((dqs * 2) + 16);
921 MCHBAR32_AND_OR(C0DQSDQRyTX3(rank), ~((1 << (dqs * 2 + 17)) | (1 << (dqs * 2 + 16))),
922 reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100923
924 reg8 = pll->pi[f][clk];
Angel Pons39ff7032020-03-09 21:39:44 +0100925 MCHBAR8_AND_OR(C0TXDQS0R0DLL + j, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100926}
927
Damien Zammit003d15c2015-11-20 17:17:51 +1100928static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
929{
930 u8 rank, dq, reg8, j;
931 u32 reg32;
932
Angel Pons39ff7032020-03-09 21:39:44 +0100933 j = clk - 8;
934 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100935 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100936 rank = j % 4;
937 dq = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100938
Angel Pons39ff7032020-03-09 21:39:44 +0100939 reg32 |= ((u32) pll->dben[f][clk]) << (dq + 9);
Damien Zammit003d15c2015-11-20 17:17:51 +1100940 reg32 |= ((u32) pll->dbsel[f][clk]) << dq;
Angel Pons39ff7032020-03-09 21:39:44 +0100941
Nico Huber12d37682021-02-06 14:39:54 +0100942 MCHBAR32_AND_OR(C0DQRyTX1(rank), ~((1 << (dq + 9)) | (1 << dq)), reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100943
944 reg32 = ((u32) pll->clkdelay[f][clk]) << (dq*2);
Angel Pons39ff7032020-03-09 21:39:44 +0100945 MCHBAR32_AND_OR(C0DQSDQRyTX3(rank), ~((1 << (dq * 2 + 1)) | (1 << (dq * 2))), reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100946
947 reg8 = pll->pi[f][clk];
Angel Pons39ff7032020-03-09 21:39:44 +0100948 MCHBAR8_AND_OR(C0TXDQ0R0DLL + j, ~0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100949}
950
Angel Pons39ff7032020-03-09 21:39:44 +0100951/* WDLL programming: Perform HPLL/MPLL calibration after write levelization */
Damien Zammit003d15c2015-11-20 17:17:51 +1100952static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
953{
954 struct pllparam pll = {
955 .pi = {
Angel Pons39ff7032020-03-09 21:39:44 +0100956 { /* DDR = 667 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100957 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
958 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
959 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
960 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
961 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Angel Pons39ff7032020-03-09 21:39:44 +0100962 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3,
Damien Zammit003d15c2015-11-20 17:17:51 +1100963 },
Angel Pons39ff7032020-03-09 21:39:44 +0100964 { /* DDR = 800 */
965 53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
Damien Zammit003d15c2015-11-20 17:17:51 +1100966 34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
967 47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
Angel Pons39ff7032020-03-09 21:39:44 +0100968 47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
969 2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
970 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15,
Damien Zammit003d15c2015-11-20 17:17:51 +1100971 }},
972
973 .dben = {
Angel Pons39ff7032020-03-09 21:39:44 +0100974 { /* DDR = 667 */
975 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
976 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
977 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
978 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
979 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
980 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100981 },
Angel Pons39ff7032020-03-09 21:39:44 +0100982 { /* DDR = 800 */
983 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
984 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
985 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
986 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
987 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
988 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100989 }},
990
991 .dbsel = {
Angel Pons39ff7032020-03-09 21:39:44 +0100992 { /* DDR = 667 */
993 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
994 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
995 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
996 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
997 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
998 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100999 },
Angel Pons39ff7032020-03-09 21:39:44 +01001000 { /* DDR = 800 */
1001 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1002 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1003 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1004 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1005 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1006 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001007 }},
1008
1009 .clkdelay = {
Angel Pons39ff7032020-03-09 21:39:44 +01001010 { /* DDR = 667 */
1011 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1012 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1013 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1014 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1015 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1016 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +11001017 },
Angel Pons39ff7032020-03-09 21:39:44 +01001018 { /* DDR = 800 */
1019 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1020 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1021 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1022 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
1023 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1024 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Damien Zammit003d15c2015-11-20 17:17:51 +11001025 }}
1026 };
1027
1028 u8 i, f;
1029 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
1030 f = 0;
1031 } else {
1032 f = 1;
1033 }
1034 for (i = 0; i < 72; i++) {
1035 pll.pi[f][i] += pidelay;
1036 }
1037
Angel Pons39ff7032020-03-09 21:39:44 +01001038 /* Disable Dynamic DQS Slave Setting Per Rank */
1039 MCHBAR8_AND(CSHRDQSCMN, ~(1 << 7));
1040 MCHBAR16_AND_OR(CSHRPDCTL4, ~0x3fff, 0x1fff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001041
1042 sdram_p_clkset0(&pll, f, 0);
1043 sdram_p_clkset1(&pll, f, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01001044 sdram_p_cmd(&pll, f, 2);
1045 sdram_p_ctrl(&pll, f, 4);
1046
Damien Zammit003d15c2015-11-20 17:17:51 +11001047 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001048 sdram_p_dqs(&pll, f, i + 40);
Damien Zammit003d15c2015-11-20 17:17:51 +11001049 }
1050 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001051 sdram_p_dq(&pll, f, i + 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11001052 }
1053}
1054
Angel Pons39ff7032020-03-09 21:39:44 +01001055/* Perform HMC hardware calibration */
Damien Zammit003d15c2015-11-20 17:17:51 +11001056static void sdram_calibratehwpll(struct sysinfo *s)
1057{
1058 u8 reg8;
1059
1060 s->async = 0;
1061 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001062
Angel Pons39ff7032020-03-09 21:39:44 +01001063 MCHBAR16_OR(CSHRPDCTL, 1 << 15);
1064 MCHBAR8_AND(CSHRPDCTL, ~(1 << 7));
1065 MCHBAR8_OR(CSHRPDCTL, 1 << 3);
1066 MCHBAR8_OR(CSHRPDCTL, 1 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001067
Angel Pons39ff7032020-03-09 21:39:44 +01001068 /* Start hardware HMC calibration */
1069 MCHBAR8_OR(CSHRPDCTL, 1 << 7);
1070
1071 /* Busy-wait until calibration is done */
1072 while ((MCHBAR8(CSHRPDCTL) & (1 << 2)) == 0)
1073 ;
1074
1075 /* If hardware HMC calibration failed */
1076 reg8 = (MCHBAR8(CSHRPDCTL) & (1 << 3)) >> 3;
Damien Zammit003d15c2015-11-20 17:17:51 +11001077 if (reg8 != 0) {
1078 s->async = 1;
1079 }
1080}
1081
1082static void sdram_dlltiming(struct sysinfo *s)
1083{
Elyes HAOUAS66b462d2019-01-02 21:11:32 +01001084 u8 reg8, i;
Damien Zammit003d15c2015-11-20 17:17:51 +11001085 u16 reg16;
1086 u32 reg32;
1087
Angel Pons39ff7032020-03-09 21:39:44 +01001088 /* Configure the Master DLL */
Damien Zammit003d15c2015-11-20 17:17:51 +11001089 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +01001090 reg32 = 0x08014227;
Damien Zammit003d15c2015-11-20 17:17:51 +11001091 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001092 reg32 = 0x00014221;
Damien Zammit003d15c2015-11-20 17:17:51 +11001093 }
Angel Pons39ff7032020-03-09 21:39:44 +01001094 MCHBAR32_AND_OR(CSHRMSTRCTL1, ~0x0fffffff, reg32);
1095 MCHBAR32_OR(CSHRMSTRCTL1, 1 << 23);
1096 MCHBAR32_OR(CSHRMSTRCTL1, 1 << 15);
1097 MCHBAR32_AND(CSHRMSTRCTL1, ~(1 << 15));
Damien Zammit003d15c2015-11-20 17:17:51 +11001098
1099 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001100 /* Disable the Master DLLs by setting these bits, IN ORDER! */
1101 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 0);
1102 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 2);
1103 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 4);
1104 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 8);
1105 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 10);
1106 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 12);
1107 MCHBAR16_OR(CSHRMSTRCTL0, 1 << 14);
Damien Zammit003d15c2015-11-20 17:17:51 +11001108 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001109 /* Enable the Master DLLs by clearing these bits, IN ORDER! */
1110 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 0));
1111 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 2));
1112 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 4));
1113 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 8));
1114 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 10));
1115 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 12));
1116 MCHBAR16_AND(CSHRMSTRCTL0, ~(1 << 14));
Damien Zammit003d15c2015-11-20 17:17:51 +11001117 }
1118
Angel Pons39ff7032020-03-09 21:39:44 +01001119 /* Initialize the Transmit DLL PI values in the following sequence. */
Damien Zammit003d15c2015-11-20 17:17:51 +11001120 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001121 MCHBAR8_AND_OR(CREFPI, ~0x3f, 0x07);
Damien Zammit003d15c2015-11-20 17:17:51 +11001122 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001123 MCHBAR8_AND(CREFPI, ~0x3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001124 }
1125
1126 sdram_calibratepll(s, 0); // XXX check
1127
Angel Pons39ff7032020-03-09 21:39:44 +01001128 /* Enable all modular Slave DLL */
1129 MCHBAR16_OR(C0DLLPIEN, 1 << 11);
1130 MCHBAR16_OR(C0DLLPIEN, 1 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11001131
1132 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001133 MCHBAR16_OR(C0DLLPIEN, (1 << 10) >> i);
Damien Zammit003d15c2015-11-20 17:17:51 +11001134 }
Angel Pons39ff7032020-03-09 21:39:44 +01001135 /* Enable DQ/DQS output */
1136 MCHBAR8_OR(C0SLVDLLOUTEN, 1);
1137 MCHBAR16(CSPDSLVWT) = 0x5005;
1138 MCHBAR16_AND_OR(CSHRPDCTL2, ~0x1f1f, 0x051a);
1139 MCHBAR16_AND_OR(CSHRPDCTL5, ~0xbf3f, 0x9010);
Damien Zammit003d15c2015-11-20 17:17:51 +11001140
1141 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001142 MCHBAR8_AND_OR(CSHRPDCTL3, ~0x7f, 0x6b);
Damien Zammit003d15c2015-11-20 17:17:51 +11001143 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001144 MCHBAR8_AND_OR(CSHRPDCTL3, ~0x7f, 0x55);
Damien Zammit003d15c2015-11-20 17:17:51 +11001145 sdram_calibratehwpll(s);
1146 }
Angel Pons39ff7032020-03-09 21:39:44 +01001147 /* Disable Dynamic Diff Amp */
1148 MCHBAR32_AND(C0STATRDCTRL, ~(1 << 22));
Damien Zammit003d15c2015-11-20 17:17:51 +11001149
Angel Pons39ff7032020-03-09 21:39:44 +01001150 /* Now, start initializing the transmit FIFO */
1151 MCHBAR8_AND(C0MISCCTL, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11001152
Angel Pons39ff7032020-03-09 21:39:44 +01001153 /* Disable (gate) mdclk and mdclkb */
1154 MCHBAR8_OR(CSHWRIOBONUS, 0xc0);
Jacob Garberd10680b2019-06-11 14:13:04 -06001155
Angel Pons39ff7032020-03-09 21:39:44 +01001156 /* Select mdmclk */
1157 MCHBAR8_AND(CSHWRIOBONUS, ~(1 << 5));
Damien Zammit003d15c2015-11-20 17:17:51 +11001158
Angel Pons39ff7032020-03-09 21:39:44 +01001159 /* Ungate mdclk */
1160 MCHBAR8_AND_OR(CSHWRIOBONUS, ~0xc0, 1 << 6);
1161 MCHBAR8_AND_OR(CSHRFIFOCTL, ~0x3f, 0x1a);
1162
1163 /* Enable the write pointer count */
1164 MCHBAR8_OR(CSHRFIFOCTL, 1);
1165
1166 /* Set the DDR3 Reset Enable bit */
1167 MCHBAR8_OR(CSHRDDR3CTL, 1);
1168
1169 /* Configure DQS-DQ Transmit */
1170 MCHBAR32(CSHRDQSTXPGM) = 0x00551803;
1171
1172 reg8 = 0; /* Switch all clocks on anyway */
1173
1174 /* Enable clock groups depending on rank population */
1175 MCHBAR32_AND_OR(C0CKTX, ~0x3f000000, reg8 << 24);
1176
1177 /* Enable DDR command output buffers from core */
1178 MCHBAR8_AND(0x594, ~1);
1179
Damien Zammit003d15c2015-11-20 17:17:51 +11001180 reg16 = 0;
1181 if (!rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001182 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001183 }
1184 if (!rank_is_populated(s->dimms, 0, 1)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001185 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001186 }
1187 if (!rank_is_populated(s->dimms, 0, 2)) {
1188 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1189 }
1190 if (!rank_is_populated(s->dimms, 0, 3)) {
1191 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1192 }
Angel Pons39ff7032020-03-09 21:39:44 +01001193 MCHBAR16_OR(C0CTLTX2, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001194}
1195
Angel Pons39ff7032020-03-09 21:39:44 +01001196/* Define a shorter name for these to make the lines fit in 96 characters */
1197#define TABLE static const
1198
1199/* Loop over each RCOMP group, but skip group 1 because it does not exist */
1200#define FOR_EACH_RCOMP_GROUP(idx) for (idx = 0; idx < 7; idx++) if (idx != 1)
1201
1202/* Define accessors for the RCOMP register banks */
1203#define C0RCOMPCTRLx(x) (rcompctl[(x)] + 0x00)
1204#define C0RCOMPMULTx(x) (rcompctl[(x)] + 0x04)
1205#define C0RCOMPOVRx(x) (rcompctl[(x)] + 0x06)
Angel Pons94eea6f2021-02-06 15:03:48 +01001206#define C0RCOMPOSVx(x) (rcompctl[(x)] + 0x0a)
1207#define C0SCOMPVREFx(x) (rcompctl[(x)] + 0x0e)
Angel Pons39ff7032020-03-09 21:39:44 +01001208#define C0SCOMPOVRx(x) (rcompctl[(x)] + 0x10)
1209#define C0SCOMPOFFx(x) (rcompctl[(x)] + 0x12)
1210#define C0DCOMPx(x) (rcompctl[(x)] + 0x14)
1211#define C0SLEWBASEx(x) (rcompctl[(x)] + 0x16)
1212#define C0SLEWPULUTx(x) (rcompctl[(x)] + 0x18)
Angel Pons94eea6f2021-02-06 15:03:48 +01001213#define C0SLEWPDLUTx(x) (rcompctl[(x)] + 0x1c)
Angel Pons39ff7032020-03-09 21:39:44 +01001214#define C0DCOMPOVRx(x) (rcompctl[(x)] + 0x20)
1215#define C0DCOMPOFFx(x) (rcompctl[(x)] + 0x24)
1216
1217/* FIXME: This only applies to DDR2 */
Damien Zammit003d15c2015-11-20 17:17:51 +11001218static void sdram_rcomp(struct sysinfo *s)
1219{
Angel Pons39ff7032020-03-09 21:39:44 +01001220 u8 i, j, reg8, rcompp, rcompn, srup, srun;
Damien Zammit003d15c2015-11-20 17:17:51 +11001221 u16 reg16;
1222 u32 reg32, rcomp1, rcomp2;
1223
Angel Pons39ff7032020-03-09 21:39:44 +01001224 static const u8 rcompslew = 0x0a;
1225 static const u16 rcompctl[7] = {
1226 C0RCOMPCTRL0,
1227 0, /* This register does not exist */
1228 C0RCOMPCTRL2,
1229 C0RCOMPCTRL3,
1230 C0RCOMPCTRL4,
1231 C0RCOMPCTRL5,
1232 C0RCOMPCTRL6,
1233 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001234
Angel Pons39ff7032020-03-09 21:39:44 +01001235 /* RCOMP settings tables = { NC-NC, x16SS, x16DS, x16SS2, x16DS2, x8DS, x8DS2}; */
1236 TABLE u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0};
1237 TABLE u8 rcompstr[7] = { 0x66, 0x00, 0xaa, 0x55, 0x55, 0x77, 0x77};
1238 TABLE u16 rcompscomp[7] = {0xa22a, 0x0000, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a};
1239 TABLE u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1};
1240 TABLE u16 rcompf[7] = {0x1114, 0x0000, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a};
1241 TABLE u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0xaa};
1242 TABLE u16 rcompscomp2[7] = {0x0000, 0xe22e, 0xe22e, 0xe22e, 0x8228, 0xe22e, 0x8228};
1243 TABLE u8 rcompdelay2[7] = { 0, 0, 0, 0, 2, 0, 2};
Damien Zammit003d15c2015-11-20 17:17:51 +11001244
Angel Pons39ff7032020-03-09 21:39:44 +01001245 TABLE u8 rcomplut[64][12] = {
1246 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
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 {10, 9, 12, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1262 {10, 9, 12, 11, 2, 2, 6, 5, 7, 6, 6, 5},
1263 {10, 10, 12, 12, 2, 2, 6, 5, 7, 6, 6, 5},
1264 {10, 10, 12, 12, 2, 2, 6, 6, 7, 7, 6, 6},
1265 {10, 10, 12, 12, 3, 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, 3, 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 {11, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1274 {11, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1275 {12, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1276 {12, 12, 14, 13, 3, 3, 7, 6, 7, 7, 7, 6},
1277 {13, 12, 16, 15, 3, 3, 7, 6, 8, 7, 7, 6},
1278 {13, 14, 16, 15, 4, 3, 7, 7, 8, 8, 7, 7},
1279 {14, 14, 16, 17, 4, 3, 7, 7, 8, 8, 7, 7},
1280 {14, 16, 18, 17, 4, 4, 8, 7, 8, 8, 8, 7},
1281 {15, 16, 18, 19, 4, 4, 8, 7, 9, 8, 8, 7},
1282 {15, 18, 18, 19, 4, 4, 8, 8, 9, 9, 8, 8},
1283 {16, 18, 20, 21, 4, 4, 8, 8, 9, 9, 8, 8},
1284 {16, 19, 20, 21, 5, 4, 9, 8, 10, 9, 9, 8},
1285 {16, 19, 20, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1286 {17, 19, 22, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1287 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1288 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1289 {18, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1290 {18, 21, 24, 25, 5, 5, 9, 9, 11, 10, 9, 9},
1291 {19, 21, 24, 27, 5, 5, 9, 9, 11, 11, 9, 9},
1292 {19, 22, 24, 27, 5, 5, 10, 9, 11, 11, 10, 9},
1293 {20, 22, 24, 27, 6, 5, 10, 10, 11, 11, 10, 10},
1294 {20, 23, 26, 27, 6, 6, 10, 10, 12, 12, 10, 10},
1295 {20, 23, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1296 {21, 24, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1297 {21, 24, 26, 29, 6, 6, 11, 10, 12, 13, 11, 10},
1298 {22, 25, 28, 29, 6, 6, 11, 11, 13, 13, 11, 11},
1299 {22, 25, 28, 31, 6, 6, 11, 11, 13, 13, 11, 11},
1300 {22, 26, 28, 31, 6, 6, 11, 11, 13, 14, 11, 11},
1301 {23, 26, 30, 31, 7, 6, 12, 11, 14, 14, 12, 11},
1302 {23, 27, 30, 33, 7, 7, 12, 12, 14, 14, 12, 12},
1303 {23, 27, 30, 33, 7, 7, 12, 12, 14, 15, 12, 12},
1304 {24, 28, 32, 33, 7, 7, 12, 12, 15, 15, 12, 12},
1305 {24, 28, 32, 33, 7, 7, 12, 12, 15, 16, 12, 12},
1306 {24, 29, 32, 35, 7, 7, 12, 12, 15, 16, 12, 12},
1307 {25, 29, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1308 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1309 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
Damien Zammit003d15c2015-11-20 17:17:51 +11001310 };
1311
1312 srup = 0;
1313 srun = 0;
1314
1315 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001316 rcomp1 = 0x00050431;
1317 } else {
Damien Zammit003d15c2015-11-20 17:17:51 +11001318 rcomp1 = 0x00050542;
1319 }
1320 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
Angel Pons94eea6f2021-02-06 15:03:48 +01001321 rcomp2 = 0x14c42827;
Damien Zammit003d15c2015-11-20 17:17:51 +11001322 } else {
1323 rcomp2 = 0x19042827;
1324 }
1325
Angel Pons39ff7032020-03-09 21:39:44 +01001326 FOR_EACH_RCOMP_GROUP(i) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001327 reg8 = rcompupdate[i];
Angel Pons39ff7032020-03-09 21:39:44 +01001328 MCHBAR8_AND_OR(C0RCOMPCTRLx(i), ~1, reg8);
1329 MCHBAR8_AND(C0RCOMPCTRLx(i), ~2);
1330
1331 reg16 = rcompslew;
1332 MCHBAR16_AND_OR(C0RCOMPCTRLx(i), ~0xf000, reg16 << 12);
1333
1334 MCHBAR8(C0RCOMPMULTx(i)) = rcompstr[i];
1335 MCHBAR16(C0SCOMPVREFx(i)) = rcompscomp[i];
1336 MCHBAR8_AND_OR(C0DCOMPx(i), ~0x03, rcompdelay[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001337 if (i == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01001338 /* FIXME: Why are we rewriting this? */
1339 MCHBAR16_AND_OR(C0RCOMPCTRLx(i), ~0xf000, reg16 << 12);
1340
1341 MCHBAR8(C0RCOMPMULTx(i)) = rcompstr2[s->dimm_config[0]];
1342 MCHBAR16(C0SCOMPVREFx(i)) = rcompscomp2[s->dimm_config[0]];
1343 MCHBAR8_AND_OR(C0DCOMPx(i), ~0x03, rcompdelay2[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001344 }
1345
Angel Pons39ff7032020-03-09 21:39:44 +01001346 MCHBAR16_AND(C0SLEWBASEx(i), ~0x7f7f);
1347
1348 /* FIXME: Why not do a single dword write? */
1349 MCHBAR16_AND(C0SLEWPULUTx(i), ~0x3f3f);
1350 MCHBAR16_AND(C0SLEWPULUTx(i) + 2, ~0x3f3f);
1351
1352 /* FIXME: Why not do a single dword write? */
1353 MCHBAR16_AND(C0SLEWPDLUTx(i), ~0x3f3f);
1354 MCHBAR16_AND(C0SLEWPDLUTx(i) + 2, ~0x3f3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001355 }
1356
Angel Pons39ff7032020-03-09 21:39:44 +01001357 /* FIXME: Hardcoded */
1358 MCHBAR8_AND_OR(C0ODTRECORDX, ~0x3f, 0x36);
1359 MCHBAR8_AND_OR(C0DQSODTRECORDX, ~0x3f, 0x36);
Damien Zammit003d15c2015-11-20 17:17:51 +11001360
Angel Pons39ff7032020-03-09 21:39:44 +01001361 FOR_EACH_RCOMP_GROUP(i) {
1362 MCHBAR8_AND(C0RCOMPCTRLx(i), ~0x60);
1363 MCHBAR16_AND(C0RCOMPCTRLx(i) + 2, ~0x0706);
1364 MCHBAR16_AND(C0RCOMPOSVx(i), ~0x7f7f);
1365 MCHBAR16_AND(C0SCOMPOFFx(i), ~0x3f3f);
1366 MCHBAR16_AND(C0DCOMPOFFx(i), ~0x1f1f);
1367 MCHBAR8_AND(C0DCOMPOFFx(i) + 2, ~0x1f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001368 }
1369
Angel Pons39ff7032020-03-09 21:39:44 +01001370 MCHBAR16_AND(C0ODTRECORDX, ~0xffc0);
1371 MCHBAR16_AND(C0ODTRECORDX + 2, ~0x000f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001372
Angel Pons39ff7032020-03-09 21:39:44 +01001373 /* FIXME: Why not do a single dword write? */
1374 MCHBAR16_AND(C0DQSODTRECORDX, ~0xffc0);
1375 MCHBAR16_AND(C0DQSODTRECORDX + 2, ~0x000f);
1376
1377 FOR_EACH_RCOMP_GROUP(i) {
1378 MCHBAR16(C0SCOMPOVRx(i)) = rcompf[i];
1379
1380 /* FIXME: Why not do a single dword write? */
1381 MCHBAR16(C0DCOMPOVRx(i)) = 0x1219;
1382 MCHBAR16(C0DCOMPOVRx(i) + 2) = 0x000C;
Damien Zammit003d15c2015-11-20 17:17:51 +11001383 }
1384
Angel Pons39ff7032020-03-09 21:39:44 +01001385 MCHBAR32_AND_OR(DCMEASBUFOVR, ~0x001f1f1f, 0x000c1219);
Damien Zammit003d15c2015-11-20 17:17:51 +11001386
Angel Pons39ff7032020-03-09 21:39:44 +01001387 /* FIXME: Why not do a single word write? */
1388 MCHBAR16_AND_OR(XCOMPSDR0BNS, ~0x1f00, 0x1200);
1389 MCHBAR8_AND_OR(XCOMPSDR0BNS, ~0x1f, 0x12);
1390
1391 MCHBAR32(COMPCTRL3) = 0x007C9007;
1392 MCHBAR32(OFREQDELSEL) = rcomp1;
1393 MCHBAR16(XCOMPCMNBNS) = 0x1f7f;
1394 MCHBAR32(COMPCTRL2) = rcomp2;
1395 MCHBAR16_AND_OR(XCOMPDFCTRL, ~0x0f, 1);
1396 MCHBAR16(ZQCALCTRL) = 0x0134;
1397 MCHBAR32(COMPCTRL1) = 0x4C293600;
1398
Angel Pons39ff7032020-03-09 21:39:44 +01001399 MCHBAR8_AND_OR(COMPCTRL1 + 3, ~0x44, (1 << 6) | (1 << 2));
1400 MCHBAR16_AND(XCOMPSDR0BNS, ~(1 << 13));
1401 MCHBAR8_AND(XCOMPSDR0BNS, ~(1 << 5));
1402
1403 FOR_EACH_RCOMP_GROUP(i) {
Angel Pons07ccc8d2021-03-26 19:07:49 +01001404 /* POR values are zero */
1405 MCHBAR8_AND(C0RCOMPCTRLx(i) + 2, ~0x71);
Damien Zammit003d15c2015-11-20 17:17:51 +11001406 }
1407
Angel Pons39ff7032020-03-09 21:39:44 +01001408 if ((MCHBAR32(COMPCTRL1) & (1 << 30)) == 0) {
1409 /* Start COMP */
1410 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001411
Angel Pons39ff7032020-03-09 21:39:44 +01001412 /* Wait until COMP is done */
1413 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1414 ;
1415
1416 reg32 = MCHBAR32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001417 rcompp = (u8) ((reg32 & ~(1 << 31)) >> 24);
1418 rcompn = (u8) ((reg32 & ~(0xff800000)) >> 16);
1419
Angel Pons39ff7032020-03-09 21:39:44 +01001420 FOR_EACH_RCOMP_GROUP(i) {
1421 srup = (MCHBAR8(C0RCOMPCTRLx(i) + 1) & 0xc0) >> 6;
1422 srun = (MCHBAR8(C0RCOMPCTRLx(i) + 1) & 0x30) >> 4;
1423
1424 /* FIXME: Why not do a single word write? */
Damien Zammit003d15c2015-11-20 17:17:51 +11001425 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
Angel Pons39ff7032020-03-09 21:39:44 +01001426 MCHBAR16_AND_OR(C0SLEWBASEx(i), ~0x7f00, reg16);
1427
Damien Zammit003d15c2015-11-20 17:17:51 +11001428 reg16 = (u16)(rcompn - (1 << (srun + 1)));
Angel Pons39ff7032020-03-09 21:39:44 +01001429 MCHBAR8_AND_OR(C0SLEWBASEx(i), ~0x7f, (u8)reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001430 }
1431
1432 reg8 = rcompp - (1 << (srup + 1));
1433 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001434 MCHBAR8_AND_OR(C0SLEWPULUTx(0) + i, ~0x3f, rcomplut[j][0]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001435 }
1436
1437 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1438 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons39ff7032020-03-09 21:39:44 +01001439 MCHBAR8_AND_OR(C0SLEWPULUTx(2) + i, ~0x3f, rcomplut[j][10]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001440 }
1441 }
1442
1443 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001444 MCHBAR8_AND_OR(C0SLEWPULUTx(3) + i, ~0x3f, rcomplut[j][6]);
1445 MCHBAR8_AND_OR(C0SLEWPULUTx(4) + i, ~0x3f, rcomplut[j][6]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001446 }
1447
1448 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001449 MCHBAR8_AND_OR(C0SLEWPULUTx(5) + i, ~0x3f, rcomplut[j][8]);
1450 MCHBAR8_AND_OR(C0SLEWPULUTx(6) + i, ~0x3f, rcomplut[j][8]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001451 }
1452
1453 reg8 = rcompn - (1 << (srun + 1));
1454 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001455 MCHBAR8_AND_OR(C0SLEWPDLUTx(0) + i, ~0x3f, rcomplut[j][1]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001456 }
1457
1458 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1459 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons39ff7032020-03-09 21:39:44 +01001460 MCHBAR8_AND_OR(C0SLEWPDLUTx(2) + i, ~0x3f, rcomplut[j][11]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001461 }
1462 }
1463
1464 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001465 MCHBAR8_AND_OR(C0SLEWPDLUTx(3) + i, ~0x3f, rcomplut[j][7]);
1466 MCHBAR8_AND_OR(C0SLEWPDLUTx(4) + i, ~0x3f, rcomplut[j][7]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001467 }
1468
1469 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001470 MCHBAR8_AND_OR(C0SLEWPDLUTx(5) + i, ~0x3f, rcomplut[j][9]);
1471 MCHBAR8_AND_OR(C0SLEWPDLUTx(6) + i, ~0x3f, rcomplut[j][9]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001472 }
1473 }
Angel Pons39ff7032020-03-09 21:39:44 +01001474 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001475}
1476
Angel Pons39ff7032020-03-09 21:39:44 +01001477/* FIXME: The ODT tables are for DDR2 only! */
Damien Zammit003d15c2015-11-20 17:17:51 +11001478static void sdram_odt(struct sysinfo *s)
1479{
1480 u8 rankindex = 0;
1481
Angel Pons39ff7032020-03-09 21:39:44 +01001482 static const u16 odt_rankctrl[16] = {
1483 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1484 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1485 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1486 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1487 };
1488 static const u16 odt_matrix[16] = {
1489 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1490 0x0000, 0x0011, 0x0000, 0x0011, 0x0000, 0x4444, 0x0000, 0x4444,
1491 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1492 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4444, 0x0000, 0x4444,
1493 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001494
1495 switch (s->dimms[0].ranks) {
1496 case 0:
1497 if (s->dimms[1].ranks == 0) {
1498 rankindex = 0;
1499 } else if (s->dimms[1].ranks == 1) {
1500 rankindex = 4;
1501 } else if (s->dimms[1].ranks == 2) {
1502 rankindex = 12;
1503 }
1504 break;
1505 case 1:
1506 if (s->dimms[1].ranks == 0) {
1507 rankindex = 1;
1508 } else if (s->dimms[1].ranks == 1) {
1509 rankindex = 5;
1510 } else if (s->dimms[1].ranks == 2) {
1511 rankindex = 13;
1512 }
1513 break;
1514 case 2:
1515 if (s->dimms[1].ranks == 0) {
1516 rankindex = 3;
1517 } else if (s->dimms[1].ranks == 1) {
1518 rankindex = 7;
1519 } else if (s->dimms[1].ranks == 2) {
1520 rankindex = 15;
1521 }
1522 break;
1523 }
1524
Angel Pons39ff7032020-03-09 21:39:44 +01001525 /* Program the ODT Matrix */
1526 MCHBAR16(C0ODT) = odt_matrix[rankindex];
1527
1528 /* Program the ODT Rank Control */
1529 MCHBAR16(C0ODTRKCTRL) = odt_rankctrl[rankindex];
Damien Zammit003d15c2015-11-20 17:17:51 +11001530}
1531
1532static void sdram_mmap(struct sysinfo *s)
1533{
Angel Pons39ff7032020-03-09 21:39:44 +01001534 TABLE u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000, 0xc00001, 0xf00000};
1535 TABLE u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101, 0x1010000, 0x1010101};
1536 TABLE u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1537 TABLE u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006, 0x40002, 0x80006};
Damien Zammit003d15c2015-11-20 17:17:51 +11001538
Angel Pons39ff7032020-03-09 21:39:44 +01001539 TABLE u16 tolud[7] = {2048, 2048, 4096, 4096, 8192, 4096, 8192};
1540 TABLE u16 tom[7] = { 2, 2, 4, 4, 8, 4, 8};
1541 TABLE u16 touud[7] = { 128, 128, 256, 256, 512, 256, 512};
1542 TABLE u32 gbsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1543 TABLE u32 bgsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1544 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 +11001545
1546 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1547 if (s->dimms[0].sides > 1) {
1548 // 2R/NC
Angel Pons39ff7032020-03-09 21:39:44 +01001549 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x300001);
1550 MCHBAR32(C0DRA01) = 0x00000101;
1551 MCHBAR32(C0DRB0) = 0x00040002;
1552 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001553 } else {
1554 // 1R/NC
Angel Pons39ff7032020-03-09 21:39:44 +01001555 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x100001);
1556 MCHBAR32(C0DRA01) = 0x00000001;
1557 MCHBAR32(C0DRB0) = 0x00020002;
1558 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001559 }
1560 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001561 MCHBAR32_AND_OR(C0CKECTRL, ~1, 0x300001);
1562 MCHBAR32(C0DRA01) = 0x00000101;
1563 MCHBAR32(C0DRB0) = 0x00040002;
1564 MCHBAR32(C0DRB2) = 0x00040004;
Damien Zammit003d15c2015-11-20 17:17:51 +11001565 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001566 MCHBAR32_AND_OR(C0CKECTRL, ~1, w260[s->dimm_config[0]]);
1567 MCHBAR32(C0DRA01) = w208[s->dimm_config[0]];
1568 MCHBAR32(C0DRB0) = w200[s->dimm_config[0]];
1569 MCHBAR32(C0DRB2) = w204[s->dimm_config[0]];
Damien Zammit003d15c2015-11-20 17:17:51 +11001570 }
Angel Pons39ff7032020-03-09 21:39:44 +01001571 pci_write_config16(HOST_BRIDGE, 0xb0, tolud[s->dimm_config[0]]);
1572 pci_write_config16(HOST_BRIDGE, 0xa0, tom[s->dimm_config[0]]);
1573 pci_write_config16(HOST_BRIDGE, 0xa2, touud[s->dimm_config[0]]);
1574 pci_write_config32(HOST_BRIDGE, 0xa4, gbsm[s->dimm_config[0]]);
1575 pci_write_config32(HOST_BRIDGE, 0xa8, bgsm[s->dimm_config[0]]);
1576 pci_write_config32(HOST_BRIDGE, 0xac, tsegmb[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001577}
1578
Damien Zammit003d15c2015-11-20 17:17:51 +11001579static u8 sdram_checkrcompoverride(void)
1580{
1581 u32 xcomp;
1582 u8 aa, bb, a, b, c, d;
1583
Angel Pons39ff7032020-03-09 21:39:44 +01001584 xcomp = MCHBAR32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001585 a = (u8)((xcomp & 0x7f000000) >> 24);
Angel Pons39ff7032020-03-09 21:39:44 +01001586 b = (u8)((xcomp & 0x007f0000) >> 16);
1587 c = (u8)((xcomp & 0x00003f00) >> 8);
1588 d = (u8)((xcomp & 0x0000003f) >> 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001589
1590 if (a > b) {
1591 aa = a - b;
1592 } else {
1593 aa = b - a;
1594 }
1595 if (c > d) {
1596 bb = c - d;
1597 } else {
1598 bb = d - c;
1599 }
Angel Pons39ff7032020-03-09 21:39:44 +01001600 if ((aa > 18) || (bb > 7) || (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
Damien Zammit003d15c2015-11-20 17:17:51 +11001601 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001602 MCHBAR32(RCMEASBUFXOVR) = 0x9718a729;
Damien Zammit003d15c2015-11-20 17:17:51 +11001603 return 1;
1604 }
1605 return 0;
1606}
1607
1608static void sdram_rcompupdate(struct sysinfo *s)
1609{
1610 u8 i, ok;
1611 u32 reg32a, reg32b;
1612
1613 ok = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001614 MCHBAR8_AND(XCOMPDFCTRL, ~(1 << 3));
1615 MCHBAR8_AND(COMPCTRL1, ~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11001616 for (i = 0; i < 3; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001617 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001618 hpet_udelay(1000);
Angel Pons39ff7032020-03-09 21:39:44 +01001619 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1620 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001621 ok |= sdram_checkrcompoverride();
1622 }
1623 if (!ok) {
Angel Pons39ff7032020-03-09 21:39:44 +01001624 reg32a = MCHBAR32(XCOMP);
1625 reg32b = ((reg32a >> 16) & 0x0000ffff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001626 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1627 reg32a |= (1 << 31) | (1 << 15);
Angel Pons39ff7032020-03-09 21:39:44 +01001628 MCHBAR32(RCMEASBUFXOVR) = reg32a;
Damien Zammit003d15c2015-11-20 17:17:51 +11001629 }
Angel Pons39ff7032020-03-09 21:39:44 +01001630 MCHBAR8_OR(COMPCTRL1, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001631 hpet_udelay(1000);
Angel Pons39ff7032020-03-09 21:39:44 +01001632 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
1633 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001634}
1635
1636static void __attribute__((noinline))
1637sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1638{
1639 u32 reg32;
1640
1641 reg32 = jval << 3;
Angel Pons39ff7032020-03-09 21:39:44 +01001642 reg32 |= rank * (1 << 27);
1643 MCHBAR8_AND_OR(C0JEDEC, ~0x3e, jmode);
Damien Zammit003d15c2015-11-20 17:17:51 +11001644 read32((void *)reg32);
1645 barrier();
1646 hpet_udelay(1); // 1us
1647}
1648
1649static void sdram_zqcl(struct sysinfo *s)
1650{
1651 if (s->boot_path == BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01001652 MCHBAR32_OR(C0CKECTRL, 1 << 27);
1653 MCHBAR8_AND_OR(C0JEDEC, ~0x0e, NORMAL_OP_CMD);
1654 MCHBAR8_AND(C0JEDEC, ~0x30);
1655 MCHBAR32_AND_OR(C0REFRCTRL2, ~(3 << 30), 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001656 }
1657}
1658
1659static void sdram_jedecinit(struct sysinfo *s)
1660{
1661 u8 r, i, ch;
1662 u16 reg16, mrs, rttnom;
1663 struct jedeclist {
1664 char debug[15];
1665 u8 cmd;
1666 u16 val;
1667 };
1668
Arthur Heymans6bf13012017-06-10 12:03:27 +02001669 static const struct jedeclist jedec[12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001670 { " NOP ", NOP_CMD, 0 },
1671 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1672 { " EMRS2 ", EMRS2_CMD, 0 },
1673 { " EMRS3 ", EMRS3_CMD, 0 },
1674 { " EMRS1 ", EMRS1_CMD, 0 },
1675 { " DLL RESET ", MRS_CMD, (1 << 8) },
1676 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1677 { " AUTOREFRESH", CBR_CMD, 0 },
1678 { " AUTOREFRESH", CBR_CMD, 0 },
1679 { " INITIALISE ", MRS_CMD, 0 },
1680 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1681 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1682 };
1683
1684 mrs = (s->selected_timings.CAS << 4) |
Angel Pons39ff7032020-03-09 21:39:44 +01001685 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 3;
1686
Damien Zammit003d15c2015-11-20 17:17:51 +11001687 rttnom = (1 << 2);
1688 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1689 rttnom |= (1 << 6);
1690 }
1691
1692 hpet_udelay(200); // 200us
1693 reg16 = 0;
1694 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1695 for (i = 0; i < 12; i++) {
1696 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1697 reg16 = jedec[i].val;
1698 switch (jedec[i].cmd) {
1699 case EMRS1_CMD:
1700 reg16 |= rttnom;
1701 break;
1702 case MRS_CMD:
1703 reg16 |= mrs;
1704 break;
1705 default:
1706 break;
1707 }
1708 sdram_jedec(s, r, jedec[i].cmd, reg16);
1709 PRINTK_DEBUG("done\n");
1710 }
1711 }
1712}
1713
1714static void sdram_misc(struct sysinfo *s)
1715{
1716 u32 reg32;
1717
1718 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001719 reg32 |= (4 << 13);
1720 reg32 |= (6 << 8);
1721 MCHBAR32_AND_OR(C0DYNRDCTRL, ~0x3ff00, reg32);
1722 MCHBAR8_AND(C0DYNRDCTRL, ~(1 << 7));
1723 MCHBAR8_OR(C0REFRCTRL + 3, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001724 if (s->boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01001725 MCHBAR8_AND_OR(C0JEDEC, ~0x0e, NORMAL_OP_CMD);
1726 MCHBAR8_AND(C0JEDEC, ~0x30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001727 } else {
1728 sdram_zqcl(s);
1729 }
1730}
1731
1732static void sdram_checkreset(void)
1733{
1734 u8 pmcon2, pmcon3, reset;
1735
1736 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1737 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1738 pmcon3 &= ~0x2;
1739 if (pmcon2 & 0x80) {
1740 pmcon2 &= ~0x80;
1741 reset = 1;
1742 } else {
1743 pmcon2 |= 0x80;
1744 reset = 0;
1745 }
1746 if (pmcon2 & 0x4) {
1747 pmcon2 |= 0x4;
1748 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1749 pmcon3 |= (1 << 3);
1750 }
1751 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1752 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +02001753 if (reset)
1754 full_reset();
Damien Zammit003d15c2015-11-20 17:17:51 +11001755}
1756
1757static void sdram_dradrb(struct sysinfo *s)
1758{
1759 u8 i, reg8, ch, r;
1760 u32 reg32, ind, c0dra, c0drb, dra;
1761 u16 addr;
1762 i = 0;
Arthur Heymans6bf13012017-06-10 12:03:27 +02001763 static const u8 dratab[2][2][2][4] =
Damien Zammit003d15c2015-11-20 17:17:51 +11001764 {{
1765 {
1766 {0xff, 0xff, 0xff, 0xff},
1767 {0xff, 0x00, 0x02, 0xff}
1768 },
1769 {
1770 {0xff, 0x01, 0xff, 0xff},
1771 {0xff, 0x03, 0xff, 0x06}
1772 }
1773 },
1774 {
1775 {
1776 {0xff, 0xff, 0xff, 0xff},
1777 {0xff, 0x04, 0x06, 0x08}
1778 },
1779 {
1780 {0xff, 0xff, 0xff, 0xff},
1781 {0x05, 0x07, 0x09, 0xff}
1782 }
1783 }};
1784
Arthur Heymans6bf13012017-06-10 12:03:27 +02001785 static const u8 dradrb[10][6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001786 //Row Col Bank Width DRB
1787 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1788 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1789 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1790 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1791 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1792 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1793 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1794 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1795 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1796 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1797 };
1798
1799 reg32 = 0;
1800 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1801 i = r / 2;
1802 PRINTK_DEBUG("RANK %d PRESENT\n", r);
Angel Pons39ff7032020-03-09 21:39:44 +01001803 dra = dratab
1804 [s->dimms[i].banks]
Damien Zammit003d15c2015-11-20 17:17:51 +11001805 [s->dimms[i].width]
1806 [s->dimms[i].cols - 9]
1807 [s->dimms[i].rows - 12];
1808
1809 if (s->dimms[i].banks == 1) {
1810 dra |= (1 << 7);
1811 }
Angel Pons39ff7032020-03-09 21:39:44 +01001812 reg32 |= (dra << (r * 8));
Damien Zammit003d15c2015-11-20 17:17:51 +11001813 }
Angel Pons39ff7032020-03-09 21:39:44 +01001814 MCHBAR32(C0DRA01) = reg32;
Damien Zammit003d15c2015-11-20 17:17:51 +11001815 c0dra = reg32;
1816 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1817
1818 reg32 = 0;
1819 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1820 reg32 |= (1 << r);
1821 }
1822 reg8 = (u8)(reg32 << 4) & 0xf0;
Angel Pons39ff7032020-03-09 21:39:44 +01001823 MCHBAR8_AND_OR(C0CKECTRL + 2, ~0xf0, reg8);
1824
1825 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) || ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
1826 MCHBAR8_OR(C0CKECTRL, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001827 }
1828
Angel Pons39ff7032020-03-09 21:39:44 +01001829 addr = C0DRB0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001830 c0drb = 0;
1831 FOR_EACH_RANK(ch, r) {
1832 if (rank_is_populated(s->dimms, ch, r)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001833 ind = (c0dra >> (8 * r)) & 0x7f;
Damien Zammit003d15c2015-11-20 17:17:51 +11001834 c0drb = (u16)(c0drb + dradrb[ind][5]);
1835 s->channel_capacity[0] += dradrb[ind][5] << 6;
1836 }
1837 MCHBAR16(addr) = c0drb;
1838 addr += 2;
1839 }
1840 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1841}
1842
1843static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1844{
Damien Zammit003d15c2015-11-20 17:17:51 +11001845 u8 dqsmatches = 1;
1846 while (count--) {
Angel Pons39ff7032020-03-09 21:39:44 +01001847 MCHBAR8_AND(C0RSTCTL, ~2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001848 hpet_udelay(1);
Angel Pons39ff7032020-03-09 21:39:44 +01001849 MCHBAR8_OR(C0RSTCTL, 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001850 hpet_udelay(1);
1851 barrier();
Elyes HAOUASaf159d42019-05-22 20:19:22 +02001852 read32((void *)strobeaddr);
Damien Zammit003d15c2015-11-20 17:17:51 +11001853 barrier();
1854 hpet_udelay(1);
1855
1856 if (((MCHBAR8(dqshighaddr) & 0x40) >> 6) != highlow) {
1857 dqsmatches = 0;
1858 }
1859 }
1860
1861 return dqsmatches;
1862}
1863
Angel Pons39ff7032020-03-09 21:39:44 +01001864static void rcvenclock(u8 *coarse, u8 *medium, u8 lane)
Damien Zammit003d15c2015-11-20 17:17:51 +11001865{
1866 if (*medium < 3) {
1867 (*medium)++;
Angel Pons39ff7032020-03-09 21:39:44 +01001868 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001869 } else {
1870 *medium = 0;
1871 (*coarse)++;
Angel Pons39ff7032020-03-09 21:39:44 +01001872 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, *coarse << 16);
1873 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)(~3 << (lane * 2)), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001874 }
1875}
1876
1877static void sdram_rcven(struct sysinfo *s)
1878{
Angel Pons39ff7032020-03-09 21:39:44 +01001879 u8 coarse, savecoarse;
1880 u8 medium, savemedium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001881 u8 pi, savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01001882 u8 lane;
1883 u8 lanecoarse[8] = {0};
1884 u8 minlanecoarse = 0xff;
1885 u8 offset;
1886 u8 maxlane = 8;
Arthur Heymans015339f2018-08-20 11:28:58 +02001887 /* Since dra/drb is already set up we know that at address 0x00000000
1888 we will always find the first available rank */
1889 u32 strobeaddr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001890 u32 dqshighaddr;
1891
Angel Pons39ff7032020-03-09 21:39:44 +01001892 MCHBAR8_AND(C0RSTCTL, ~0x0c);
1893 MCHBAR8_AND(CMNDQFIFORST, ~0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11001894
1895 PRINTK_DEBUG("rcven 0\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001896 for (lane = 0; lane < maxlane; lane++) {
1897 PRINTK_DEBUG("rcven lane %d\n", lane);
1898// trylaneagain:
1899 dqshighaddr = C0MISCCTLy(lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001900
Angel Pons39ff7032020-03-09 21:39:44 +01001901 coarse = s->selected_timings.CAS + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11001902 pi = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001903 medium = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001904
Angel Pons39ff7032020-03-09 21:39:44 +01001905 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1906 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001907
Angel Pons39ff7032020-03-09 21:39:44 +01001908 MCHBAR8_AND(C0RXRCVyDLL(lane), ~0x3f);
1909
1910 savecoarse = coarse;
1911 savemedium = medium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001912 savepi = pi;
1913
1914 PRINTK_DEBUG("rcven 0.1\n");
1915
Angel Pons39ff7032020-03-09 21:39:44 +01001916 // XXX comment out
1917 // MCHBAR16_AND_OR(C0RCVMISCCTL1, (u16)~3 << (lane * 2), 1 << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001918
1919 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001920 // printk(BIOS_DEBUG, "coarse=%d medium=%d\n", coarse, medium);
1921 rcvenclock(&coarse, &medium, lane);
1922 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001923 PRINTK_DEBUG("Error: coarse > 0xf\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001924 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001925 break;
1926 }
1927 }
1928 PRINTK_DEBUG("rcven 0.2\n");
1929
Angel Pons39ff7032020-03-09 21:39:44 +01001930 savecoarse = coarse;
1931 savemedium = medium;
1932 rcvenclock(&coarse, &medium, lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001933
1934 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001935 savecoarse = coarse;
1936 savemedium = medium;
1937 rcvenclock(&coarse, &medium, lane);
1938 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001939 PRINTK_DEBUG("Error: coarse > 0xf\n");
1940 //goto trylaneagain;
1941 break;
1942 }
1943 }
1944
1945 PRINTK_DEBUG("rcven 0.3\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001946 coarse = savecoarse;
1947 medium = savemedium;
1948 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1949 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(0x3 << lane * 2), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001950
1951 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1952 savepi = pi;
1953 pi++;
1954 if (pi > s->maxpi) {
Angel Pons39ff7032020-03-09 21:39:44 +01001955 // if (s->nodll) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001956 pi = savepi = s->maxpi;
1957 break;
Angel Pons39ff7032020-03-09 21:39:44 +01001958 // }
Damien Zammit003d15c2015-11-20 17:17:51 +11001959 }
Angel Pons39ff7032020-03-09 21:39:44 +01001960 MCHBAR8_AND_OR(C0RXRCVyDLL(lane), ~0x3f, pi << s->pioffset);
Damien Zammit003d15c2015-11-20 17:17:51 +11001961 }
1962 PRINTK_DEBUG("rcven 0.4\n");
1963
1964 pi = savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01001965 MCHBAR8_AND_OR(C0RXRCVyDLL(lane), ~0x3f, pi << s->pioffset);
1966 rcvenclock(&coarse, &medium, lane);
1967
Damien Zammit003d15c2015-11-20 17:17:51 +11001968 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1969 PRINTK_DEBUG("Error: DQS not high\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001970 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001971 }
1972 PRINTK_DEBUG("rcven 0.5\n");
1973 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001974 coarse--;
1975 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, coarse << 16);
1976 if (coarse == 0) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +02001977 PRINTK_DEBUG("Error: DQS did not hit 0\n");
Damien Zammit003d15c2015-11-20 17:17:51 +11001978 break;
1979 }
1980 }
1981
1982 PRINTK_DEBUG("rcven 0.6\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001983 rcvenclock(&coarse, &medium, lane);
1984 s->pi[lane] = pi;
1985 lanecoarse[lane] = coarse;
Damien Zammit003d15c2015-11-20 17:17:51 +11001986 }
1987
1988 PRINTK_DEBUG("rcven 1\n");
1989
Angel Pons39ff7032020-03-09 21:39:44 +01001990 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11001991 do {
Angel Pons39ff7032020-03-09 21:39:44 +01001992 lane--;
1993 if (minlanecoarse > lanecoarse[lane]) {
1994 minlanecoarse = lanecoarse[lane];
Damien Zammit003d15c2015-11-20 17:17:51 +11001995 }
Angel Pons39ff7032020-03-09 21:39:44 +01001996 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001997
Angel Pons39ff7032020-03-09 21:39:44 +01001998 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11001999 do {
Angel Pons39ff7032020-03-09 21:39:44 +01002000 lane--;
2001 offset = lanecoarse[lane] - minlanecoarse;
2002 MCHBAR16_AND_OR(C0COARSEDLY0, (u16)(~(3 << (lane * 2))), offset << (lane * 2));
2003 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002004
Angel Pons39ff7032020-03-09 21:39:44 +01002005 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x000f0000, minlanecoarse << 16);
Damien Zammit003d15c2015-11-20 17:17:51 +11002006
Angel Pons39ff7032020-03-09 21:39:44 +01002007 s->coarsectrl = minlanecoarse;
2008 s->coarsedelay = MCHBAR16(C0COARSEDLY0);
2009 s->mediumphase = MCHBAR16(C0RCVMISCCTL2);
2010 s->readptrdelay = MCHBAR16(C0RCVMISCCTL1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002011
2012 PRINTK_DEBUG("rcven 2\n");
Angel Pons39ff7032020-03-09 21:39:44 +01002013 MCHBAR8_AND(C0RSTCTL, ~0x0e);
2014 MCHBAR8_OR(C0RSTCTL, 0x02);
2015 MCHBAR8_OR(C0RSTCTL, 0x04);
2016 MCHBAR8_OR(C0RSTCTL, 0x08);
Damien Zammit003d15c2015-11-20 17:17:51 +11002017
Angel Pons39ff7032020-03-09 21:39:44 +01002018 MCHBAR8_OR(CMNDQFIFORST, 0x80);
2019 MCHBAR8_AND(CMNDQFIFORST, ~0x80);
2020 MCHBAR8_OR(CMNDQFIFORST, 0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11002021 PRINTK_DEBUG("rcven 3\n");
2022}
2023
Angel Pons39ff7032020-03-09 21:39:44 +01002024/* NOTE: Unless otherwise specified, the values are expressed in MiB */
Damien Zammit003d15c2015-11-20 17:17:51 +11002025static void sdram_mmap_regs(struct sysinfo *s)
2026{
2027 bool reclaim;
Angel Pons39ff7032020-03-09 21:39:44 +01002028 u32 mmiosize, tom, tolud, touud, reclaimbase, reclaimlimit;
2029 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase, tsegsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002030 u16 ggc;
Angel Pons39ff7032020-03-09 21:39:44 +01002031 u16 ggc_to_uma[10] = {0, 1, 4, 8, 16, 32, 48, 64, 128, 256};
2032 u8 ggc_to_gtt[4] = {0, 1, 0, 0};
Damien Zammit003d15c2015-11-20 17:17:51 +11002033
Angel Pons39ff7032020-03-09 21:39:44 +01002034 reclaimbase = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002035 reclaimlimit = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002036
2037 ggc = pci_read_config16(HOST_BRIDGE, GGC);
Damien Zammit51fdb922016-01-18 18:34:52 +11002038 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
Angel Pons39ff7032020-03-09 21:39:44 +01002039
2040 gfxsize = ggc_to_uma[(ggc & 0x00f0) >> 4];
2041
2042 gttsize = ggc_to_gtt[(ggc & 0x0300) >> 8];
2043
Damien Zammit003d15c2015-11-20 17:17:51 +11002044 tom = s->channel_capacity[0];
2045
Angel Pons39ff7032020-03-09 21:39:44 +01002046 /* With GTT always being 1M, TSEG 1M is the only setting that can
Arthur Heymansda44e342019-01-12 01:38:02 +01002047 be covered by SMRR which has alignment requirements. */
Angel Pons39ff7032020-03-09 21:39:44 +01002048 tsegsize = 1;
2049 mmiosize = 1024;
Damien Zammit003d15c2015-11-20 17:17:51 +11002050
2051 reclaim = false;
Angel Pons39ff7032020-03-09 21:39:44 +01002052 tolud = MIN(4096 - mmiosize, tom);
2053 if ((tom - tolud) > 64) {
Arthur Heymansaaebb412017-08-27 18:46:12 +02002054 reclaim = true;
Damien Zammit003d15c2015-11-20 17:17:51 +11002055 }
2056 if (reclaim) {
2057 tolud = tolud & ~0x3f;
Angel Pons39ff7032020-03-09 21:39:44 +01002058 tom = tom & ~0x3f;
2059 reclaimbase = MAX(4096, tom);
2060 reclaimlimit = reclaimbase + (MIN(4096, tom) - tolud) - 0x40;
Damien Zammit003d15c2015-11-20 17:17:51 +11002061 }
2062 touud = tom;
2063 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002064 touud = reclaimlimit + 64;
Damien Zammit003d15c2015-11-20 17:17:51 +11002065 }
2066
Angel Pons39ff7032020-03-09 21:39:44 +01002067 gfxbase = tolud - gfxsize;
2068 gttbase = gfxbase - gttsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002069 tsegbase = gttbase - tsegsize;
2070
2071 /* Program the regs */
Angel Pons39ff7032020-03-09 21:39:44 +01002072 pci_write_config16(HOST_BRIDGE, TOLUD, (u16)(tolud << 4));
2073 pci_write_config16(HOST_BRIDGE, TOM, (u16)(tom >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002074 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002075 pci_write_config16(HOST_BRIDGE, 0x98, (u16)(reclaimbase >> 6));
2076 pci_write_config16(HOST_BRIDGE, 0x9a, (u16)(reclaimlimit >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002077 }
Angel Pons39ff7032020-03-09 21:39:44 +01002078 pci_write_config16(HOST_BRIDGE, TOUUD, (u16)(touud));
2079 pci_write_config32(HOST_BRIDGE, GBSM, gfxbase << 20);
2080 pci_write_config32(HOST_BRIDGE, BGSM, gttbase << 20);
2081 pci_write_config32(HOST_BRIDGE, TSEG, tsegbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002082
Angel Pons39ff7032020-03-09 21:39:44 +01002083 u8 reg8 = pci_read_config8(HOST_BRIDGE, ESMRAMC);
2084 reg8 &= ~0x07;
Arthur Heymansda44e342019-01-12 01:38:02 +01002085 reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
Angel Pons39ff7032020-03-09 21:39:44 +01002086 pci_write_config8(HOST_BRIDGE, ESMRAMC, reg8);
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002087
Damien Zammit51fdb922016-01-18 18:34:52 +11002088 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002089 pci_read_config32(HOST_BRIDGE, GBSM), gfxbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002090 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002091 pci_read_config32(HOST_BRIDGE, BGSM), gttbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002092 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002093 pci_read_config32(HOST_BRIDGE, TSEG), tsegbase << 20);
Damien Zammit003d15c2015-11-20 17:17:51 +11002094}
2095
2096static void sdram_enhancedmode(struct sysinfo *s)
2097{
Angel Pons39ff7032020-03-09 21:39:44 +01002098 u8 reg8, ch, r, fsb_freq, ddr_freq;
Damien Zammit003d15c2015-11-20 17:17:51 +11002099 u32 mask32, reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002100 MCHBAR8_OR(C0ADDCSCTRL, 1);
2101 MCHBAR8_OR(C0REFRCTRL + 3, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002102 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
Angel Pons39ff7032020-03-09 21:39:44 +01002103 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
2104 MCHBAR32_AND_OR(WRWMCONFIG, ~mask32, reg32);
2105 MCHBAR8(C0DITCTRL + 1) = 2;
2106 MCHBAR16(C0DITCTRL + 2) = 0x0804;
2107 MCHBAR16(C0DITCTRL + 4) = 0x2010;
2108 MCHBAR8(C0DITCTRL + 6) = 0x40;
2109 MCHBAR16(C0DITCTRL + 8) = 0x091c;
2110 MCHBAR8(C0DITCTRL + 10) = 0xf2;
2111 MCHBAR8_OR(C0BYPCTRL, 1);
2112 MCHBAR8_OR(C0CWBCTRL, 1);
2113 MCHBAR16_OR(C0ARBSPL, 0x0100);
Damien Zammit003d15c2015-11-20 17:17:51 +11002114
Angel Pons26766fd2020-06-08 12:38:19 +02002115 pci_or_config8(HOST_BRIDGE, 0xf0, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01002116 MCHBAR32(SBCTL) = 0x00000002;
2117 MCHBAR32(SBCTL2) = 0x20310002;
2118 MCHBAR32(SLIMCFGTMG) = 0x02020302;
2119 MCHBAR32(HIT0) = 0x001f1806;
2120 MCHBAR32(HIT1) = 0x01102800;
2121 MCHBAR32(HIT2) = 0x07000000;
2122 MCHBAR32(HIT3) = 0x01014010;
2123 MCHBAR32(HIT4) = 0x0f038000;
Angel Pons26766fd2020-06-08 12:38:19 +02002124 pci_and_config8(HOST_BRIDGE, 0xf0, ~1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002125
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002126 u32 nranks, curranksize, maxranksize, dra;
2127 u8 rankmismatch;
Angel Pons39ff7032020-03-09 21:39:44 +01002128 static const u8 drbtab[10] = {0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8, 0x20, 0x10};
Damien Zammit003d15c2015-11-20 17:17:51 +11002129
2130 nranks = 0;
2131 curranksize = 0;
2132 maxranksize = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002133 rankmismatch = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002134
Damien Zammit003d15c2015-11-20 17:17:51 +11002135 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2136 nranks++;
Angel Pons39ff7032020-03-09 21:39:44 +01002137 dra = (u8) ((MCHBAR32(C0DRA01) >> (8 * r)) & 0x7f);
Damien Zammit003d15c2015-11-20 17:17:51 +11002138 curranksize = drbtab[dra];
2139 if (maxranksize == 0) {
2140 maxranksize = curranksize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002141 }
2142 if (curranksize != maxranksize) {
2143 rankmismatch = 1;
2144 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002145 }
2146
2147 reg8 = 0;
2148 switch (nranks) {
2149 case 4:
2150 if (rankmismatch) {
2151 reg8 = 0x64;
2152 } else {
2153 reg8 = 0xa4;
2154 }
2155 break;
2156 case 1:
2157 case 3:
2158 reg8 = 0x64;
2159 break;
2160 case 2:
2161 if (rankmismatch) {
2162 reg8 = 0x64;
2163 } else {
2164 reg8 = 0x24;
2165 }
2166 break;
2167 default:
2168 die("Invalid number of ranks found, halt\n");
2169 break;
2170 }
Angel Pons39ff7032020-03-09 21:39:44 +01002171 MCHBAR8_AND_OR(CHDECMISC, ~0xfc, reg8 & 0xfc);
2172 MCHBAR32_AND(NOACFGBUSCTL, ~0x80000000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002173
Angel Pons39ff7032020-03-09 21:39:44 +01002174 MCHBAR32(HTBONUS0) = 0x0000000f;
2175 MCHBAR8_OR(C0COREBONUS + 4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002176
Angel Pons39ff7032020-03-09 21:39:44 +01002177 MCHBAR32_AND(HIT3, ~0x0e000000);
2178 MCHBAR32_AND_OR(HIT4, ~0x000c0000, 0x00040000);
2179
Damien Zammit003d15c2015-11-20 17:17:51 +11002180 u32 clkcx[2][2][3] = {
Angel Pons39ff7032020-03-09 21:39:44 +01002181 {
2182 {0x00000000, 0x0c080302, 0x08010204}, /* FSB = 667, DDR = 667 */
2183 {0x02040000, 0x08100102, 0x00000000}, /* FSB = 667, DDR = 800 */
2184 },
2185 {
2186 {0x18000000, 0x3021060c, 0x20010208}, /* FSB = 800, DDR = 667 */
2187 {0x00000000, 0x0c090306, 0x00000000}, /* FSB = 800, DDR = 800 */
2188 }
2189 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002190
Angel Pons39ff7032020-03-09 21:39:44 +01002191 fsb_freq = s->selected_timings.fsb_clock;
2192 ddr_freq = s->selected_timings.mem_clock;
2193
2194 MCHBAR32(CLKXSSH2X2MD) = clkcx[fsb_freq][ddr_freq][0];
2195 MCHBAR32(CLKXSSH2X2MD + 4) = clkcx[fsb_freq][ddr_freq][1];
2196 MCHBAR32(CLKXSSH2MCBYP + 4) = clkcx[fsb_freq][ddr_freq][2];
2197
2198 MCHBAR8_AND(HIT4, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11002199}
2200
2201static void sdram_periodic_rcomp(void)
2202{
Angel Pons39ff7032020-03-09 21:39:44 +01002203 MCHBAR8_AND(COMPCTRL1, ~0x02);
2204 while ((MCHBAR32(COMPCTRL1) & 0x80000000) > 0) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002205 ;
2206 }
Angel Pons39ff7032020-03-09 21:39:44 +01002207 MCHBAR16_AND(CSHRMISCCTL, ~0x3000);
2208 MCHBAR8_OR(CMNDQFIFORST, 0x80);
2209 MCHBAR16_AND_OR(XCOMPDFCTRL, ~0x0f, 0x09);
Damien Zammit003d15c2015-11-20 17:17:51 +11002210
Angel Pons39ff7032020-03-09 21:39:44 +01002211 MCHBAR8_OR(COMPCTRL1, 0x82);
Damien Zammit003d15c2015-11-20 17:17:51 +11002212}
2213
2214static void sdram_new_trd(struct sysinfo *s)
2215{
2216 u8 pidelay, i, j, k, cc, trd_perphase[5];
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002217 u8 bypass, freqgb, trd, reg8, txfifo;
Damien Zammit003d15c2015-11-20 17:17:51 +11002218 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2219 u16 tmclk, thclk, buffertocore, postcalib;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002220 static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2221 static const u16 trd_adjust[2][2][5] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11002222 {
2223 {3000, 3000, 0,0,0},
2224 {1000,2000,3000,1500,2500}
2225 },
2226 {
2227 {2000,1000,3000,0,0},
2228 {2500, 2500, 0,0,0}
2229 }};
2230
2231 freqgb = 110;
2232 buffertocore = 5000;
Damien Zammit003d15c2015-11-20 17:17:51 +11002233 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2234 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2235 tmclk = tmclk * 100 / freqgb;
2236 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2237 switch (s->selected_timings.mem_clock) {
2238 case MEM_CLOCK_667MHz:
2239 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2240 cc = 2;
2241 } else {
2242 cc = 3;
2243 }
2244 break;
2245 default:
2246 case MEM_CLOCK_800MHz:
2247 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2248 cc = 5;
2249 } else {
2250 cc = 2;
2251 }
2252 break;
2253 }
2254 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2255 maxrcvendelay = 0;
2256 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2257
2258 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01002259 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 3) * (u32)(tmclk));
2260 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 3) * (u32)(tmclk) / 2);
2261 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 3) * (u32)(tmclk) / 4);
2262 rcvendelay += (u32)(pidelay * s->pi[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002263 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2264 }
2265
Angel Pons39ff7032020-03-09 21:39:44 +01002266 if ((MCHBAR8(HMBYPCP + 3) == 0xff) && (MCHBAR8(HMCCMC) & 0x80)) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002267 bypass = 1;
2268 } else {
2269 bypass = 0;
2270 }
2271
2272 txfifo = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002273 reg8 = (MCHBAR8(CSHRFIFOCTL) & 0x0e) >> 1;
2274 txfifo = txfifo_lut[reg8] & 0x07;
Damien Zammit003d15c2015-11-20 17:17:51 +11002275
2276 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2277 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2278 if (s->async) {
2279 datadelay += tmclk / 2;
2280 }
2281
2282 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2283 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2284
2285 if (j == 0 && k == 0) {
2286 datadelay -= 3084;
2287 }
2288
2289 trd = 0;
2290 for (i = 0; i < cc; i++) {
2291 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2292 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2293 trd_perphase[i] += 1;
2294 if (trd_perphase[i] > trd) {
2295 trd = trd_perphase[i];
2296 }
2297 }
2298
Angel Pons39ff7032020-03-09 21:39:44 +01002299 MCHBAR16_AND_OR(C0STATRDCTRL, ~0x1f00, trd << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11002300}
2301
2302static void sdram_powersettings(struct sysinfo *s)
2303{
2304 u8 j;
2305 u32 reg32;
2306
2307 /* Thermal sensor */
Angel Pons39ff7032020-03-09 21:39:44 +01002308 MCHBAR8(TSC1) = 0x9b;
2309 MCHBAR32_AND_OR(TSTTP, ~0x00ffffff, 0x1d00);
2310 MCHBAR8(THERM1) = 0x08;
2311 MCHBAR8(TSC3) = 0x00;
2312 MCHBAR8_AND_OR(TSC2, ~0x0f, 0x04);
2313 MCHBAR8_AND_OR(THERM1, ~1, 1);
2314 MCHBAR8_AND_OR(TCO, ~0x80, 0x80);
Damien Zammit003d15c2015-11-20 17:17:51 +11002315
2316 /* Clock gating */
Angel Pons39ff7032020-03-09 21:39:44 +01002317 MCHBAR32_AND(PMMISC, ~0x00040001);
2318 MCHBAR8_AND(SBCTL3 + 3, ~0x80);
2319 MCHBAR8_AND(CISDCTRL + 3, ~0x80);
2320 MCHBAR16_AND(CICGDIS, ~0x1fff);
2321 MCHBAR32_AND(SBCLKGATECTRL, ~0x0001ffff);
Angel Pons7ee1c472021-03-26 18:33:31 +01002322 MCHBAR16_AND_OR(HICLKGTCTL, ~0x03ff, 0x06);
Angel Pons39ff7032020-03-09 21:39:44 +01002323 MCHBAR32_AND_OR(HTCLKGTCTL, ~0xffffffff, 0x20);
2324 MCHBAR8_AND(TSMISC, ~1);
2325 MCHBAR8(C0WRDPYN) = s->selected_timings.CAS - 1 + 0x15;
2326 MCHBAR16_AND_OR(CLOCKGATINGI, ~0x07fc, 0x0040);
2327 MCHBAR16_AND_OR(CLOCKGATINGII, ~0x0fff, 0x0d00);
2328 MCHBAR16_AND(CLOCKGATINGIII, ~0x0d80);
2329 MCHBAR16(GTDPCGC + 2) = 0xffff;
Damien Zammit003d15c2015-11-20 17:17:51 +11002330
2331 /* Sequencing */
Angel Pons39ff7032020-03-09 21:39:44 +01002332 MCHBAR32(HPWRCTL1) = (MCHBAR32(HPWRCTL1) & ~0x1fffffff) | 0x1f643fff;
2333 MCHBAR32(HPWRCTL2) = (MCHBAR32(HPWRCTL2) & ~0xffffff7f) | 0x02010000;
2334 MCHBAR16(HPWRCTL3) = (MCHBAR16(HPWRCTL3) & ~0x7000) | (3 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11002335
2336 /* Power */
Angel Pons39ff7032020-03-09 21:39:44 +01002337 MCHBAR32(GFXC3C4) = (MCHBAR32(GFXC3C4) & ~0xffff0003) | 0x10100000;
2338 MCHBAR32(PMDSLFRC) = (MCHBAR32(PMDSLFRC) & ~0x0001bff7) | 0x00000078;
2339
2340 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz)
2341 MCHBAR16_AND_OR(PMMSPMRES, ~0x03ff, 0x00c8);
2342 else
2343 MCHBAR16_AND_OR(PMMSPMRES, ~0x03ff, 0x0100);
2344
Damien Zammit003d15c2015-11-20 17:17:51 +11002345 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2346
Angel Pons39ff7032020-03-09 21:39:44 +01002347 MCHBAR32_AND_OR(PMCLKRC, ~0x01fff37f, 0x10810700);
2348 MCHBAR8_AND_OR(PMPXPRC, ~0x07, 1);
2349 MCHBAR8_AND(PMBAK, ~0x02);
Damien Zammit003d15c2015-11-20 17:17:51 +11002350
Angel Pons39ff7032020-03-09 21:39:44 +01002351 static const u16 ddr2lut[2][4][2] = {
2352 {
2353 {0x0000, 0x0000},
2354 {0x019A, 0x0039},
2355 {0x0099, 0x1049},
2356 {0x0000, 0x0000},
2357 },
2358 {
2359 {0x0000, 0x0000},
2360 {0x019A, 0x0039},
2361 {0x0099, 0x1049},
2362 {0x0099, 0x2159},
2363 },
2364 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002365
Angel Pons39ff7032020-03-09 21:39:44 +01002366 MCHBAR16(C0C2REG) = 0x7a89;
2367 MCHBAR8(SHC2REGII) = 0xaa;
2368 MCHBAR16(SHC2REGII + 1) = ddr2lut[j][s->selected_timings.CAS - 3][1];
2369 MCHBAR16_AND_OR(SHC2REGI, ~0x7fff, ddr2lut[j][s->selected_timings.CAS - 3][0]);
2370 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0xf000, 0xf000);
2371 MCHBAR8(CSHWRIOBONUSX) = (MCHBAR8(CSHWRIOBONUSX) & ~0x77) | (4 << 4 | 4);
Damien Zammit003d15c2015-11-20 17:17:51 +11002372
Angel Pons39ff7032020-03-09 21:39:44 +01002373 reg32 = s->nodll ? 0x30000000 : 0;
2374
2375 /* FIXME: Compacting this results in changes to the binary */
2376 MCHBAR32(C0COREBONUS) = (MCHBAR32(C0COREBONUS) & ~0x0f000000) | 0x20000000 | reg32;
2377
2378 MCHBAR32_AND_OR(CLOCKGATINGI, ~0x00f00000, 0x00f00000);
2379 MCHBAR32_AND_OR(CLOCKGATINGII - 1, ~0x001ff000, 0xbf << 20);
2380 MCHBAR16_AND_OR(SHC3C4REG2, ~0x1f7f, (0x0b << 8) | (7 << 4) | 0x0b);
2381 MCHBAR16(SHC3C4REG3) = 0x3264;
2382 MCHBAR16_AND_OR(SHC3C4REG4, ~0x3f3f, (0x14 << 8) | 0x0a);
2383
2384 MCHBAR32_OR(C1COREBONUS, 0x80002000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002385}
2386
2387static void sdram_programddr(void)
2388{
Angel Pons39ff7032020-03-09 21:39:44 +01002389 MCHBAR16_AND_OR(CLOCKGATINGII, ~0x03ff, 0x0100);
2390 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0x003f, 0x0010);
2391 MCHBAR16_AND_OR(CLOCKGATINGI, ~0x7000, 0x2000);
2392
2393 MCHBAR8_AND(CSHRPDCTL, ~0x0e);
2394 MCHBAR8_AND(CSHRWRIOMLNS, ~0x0c);
2395 MCHBAR8_AND(C0MISCCTLy(0), ~0x0e);
2396 MCHBAR8_AND(C0MISCCTLy(1), ~0x0e);
2397 MCHBAR8_AND(C0MISCCTLy(2), ~0x0e);
2398 MCHBAR8_AND(C0MISCCTLy(3), ~0x0e);
2399 MCHBAR8_AND(C0MISCCTLy(4), ~0x0e);
2400 MCHBAR8_AND(C0MISCCTLy(5), ~0x0e);
2401 MCHBAR8_AND(C0MISCCTLy(6), ~0x0e);
2402 MCHBAR8_AND(C0MISCCTLy(7), ~0x0e);
2403 MCHBAR8_AND(CSHRWRIOMLNS, ~0x02);
2404
2405 MCHBAR16_AND(CSHRMISCCTL, ~0x0400);
2406 MCHBAR16_AND(CLOCKGATINGIII, ~0x0dc0);
2407 MCHBAR8_AND(C0WRDPYN, ~0x80);
2408 MCHBAR32_AND(C0COREBONUS, ~(1 << 22));
2409 MCHBAR16_AND(CLOCKGATINGI, ~0x80fc);
2410 MCHBAR16_AND(CLOCKGATINGII, ~0x0c00);
2411
2412 MCHBAR8_AND(CSHRPDCTL, ~0x0d);
2413 MCHBAR8_AND(C0MISCCTLy(0), ~1);
2414 MCHBAR8_AND(C0MISCCTLy(1), ~1);
2415 MCHBAR8_AND(C0MISCCTLy(2), ~1);
2416 MCHBAR8_AND(C0MISCCTLy(3), ~1);
2417 MCHBAR8_AND(C0MISCCTLy(4), ~1);
2418 MCHBAR8_AND(C0MISCCTLy(5), ~1);
2419 MCHBAR8_AND(C0MISCCTLy(6), ~1);
2420 MCHBAR8_AND(C0MISCCTLy(7), ~1);
2421
2422 MCHBAR32_AND_OR(C0STATRDCTRL, ~0x00700000, 3 << 20);
2423 MCHBAR32_AND(C0COREBONUS, ~0x00100000);
2424 MCHBAR8_OR(C0DYNSLVDLLEN, 0x1e);
2425 MCHBAR8_OR(C0DYNSLVDLLEN2, 0x03);
2426 MCHBAR32_AND_OR(SHCYCTRKCKEL, ~0x0c000000, 0x04000000);
2427 MCHBAR16_OR(C0STATRDCTRL, 0x6000);
2428 MCHBAR32_OR(C0CKECTRL, 0x00010000);
2429 MCHBAR8_OR(C0COREBONUS, 0x10);
2430 MCHBAR32_OR(CLOCKGATINGI - 1, 0xf << 24);
2431 MCHBAR8_OR(CSHWRIOBONUS, 0x07);
2432 MCHBAR8_OR(C0DYNSLVDLLEN, 0xc0);
2433 MCHBAR8_OR(SHC2REGIII, 7);
2434 MCHBAR16_AND_OR(SHC2MINTM, ~0xffff, 0x0080);
2435 MCHBAR8_AND_OR(SHC2IDLETM, ~0xff, 0x10);
2436 MCHBAR16_OR(C0COREBONUS, 0x01e0);
2437 MCHBAR8_OR(CSHWRIOBONUS, 0x18);
2438 MCHBAR8_OR(CSHRMSTDYNDLLENB, 0x0d);
2439 MCHBAR16_OR(SHC3C4REG1, 0x0a3f);
2440 MCHBAR8_OR(C0STATRDCTRL, 3);
2441 MCHBAR8_AND_OR(C0REFRCTRL2, ~0xff, 0x4a);
2442 MCHBAR8_AND(C0COREBONUS + 4, ~0x60);
2443 MCHBAR16_OR(C0DYNSLVDLLEN, 0x0321);
Damien Zammit003d15c2015-11-20 17:17:51 +11002444}
2445
2446static void sdram_programdqdqs(struct sysinfo *s)
2447{
2448 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2449 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2450 u8 repeat, halfclk, feature, reg8, push;
2451 u16 cwb, pimdclk;
2452 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002453 static const u8 txfifotab[8] = {0, 7, 6, 5, 2, 1, 4, 3};
Damien Zammit003d15c2015-11-20 17:17:51 +11002454
2455 tpi = 3000;
2456 dqdqs_out = 4382;
2457 dqdqs_outdelay = 5083;
2458 dqdqs_delay = 4692;
2459 coretomcp = 0;
2460 txdelay = 0;
2461 halfclk = 0;
2462 tmaxunmask = 0;
2463 tmaxpi = 0;
2464 repeat = 2;
2465 feature = 0;
2466 cwb = 0;
2467 pimdclk = 0;
2468 reg32 = 0;
2469 push = 0;
2470 reg8 = 0;
2471
2472 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2473 refclk = 3000 - mdclk;
2474
Angel Pons39ff7032020-03-09 21:39:44 +01002475 coretomcp = ((MCHBAR8(C0ADDCSCTRL) >> 2) & 0x3) + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002476 coretomcp *= mdclk;
2477
Angel Pons39ff7032020-03-09 21:39:44 +01002478 reg8 = (MCHBAR8(CSHRFIFOCTL) & 0x0e) >> 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002479
2480 while (repeat) {
2481 txdelay = mdclk * (
Angel Pons39ff7032020-03-09 21:39:44 +01002482 ((MCHBAR16(C0GNT2LNCH1) >> 8) & 0x7) +
2483 (MCHBAR8(C0WRDATACTRL) & 0xf) +
2484 (MCHBAR8(C0WRDATACTRL + 1) & 0x1)
Damien Zammit003d15c2015-11-20 17:17:51 +11002485 ) +
Angel Pons39ff7032020-03-09 21:39:44 +01002486 txfifotab[reg8]*(mdclk / 2) +
Damien Zammit003d15c2015-11-20 17:17:51 +11002487 coretomcp +
2488 refclk +
2489 cwb;
Angel Pons39ff7032020-03-09 21:39:44 +01002490 halfclk = (MCHBAR8(C0MISCCTL) >> 1) & 0x1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002491 if (halfclk) {
2492 txdelay -= mdclk / 2;
2493 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2494 } else {
2495 reg32 = dqdqs_outdelay + coretomcp;
2496 }
2497
2498 tmaxunmask = txdelay - mdclk - dqdqs_out;
2499 tmaxpi = tmaxunmask - tpi;
2500
2501 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2502 if (repeat == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01002503 MCHBAR32_AND(C0COREBONUS, ~(1 << 23));
Damien Zammit003d15c2015-11-20 17:17:51 +11002504 }
2505 feature = 1;
2506 repeat = 0;
2507 } else {
2508 repeat--;
Angel Pons39ff7032020-03-09 21:39:44 +01002509 MCHBAR32_OR(C0COREBONUS, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +11002510 cwb = 2 * mdclk;
2511 }
2512 }
2513
2514 if (!feature) {
Angel Pons39ff7032020-03-09 21:39:44 +01002515 MCHBAR8(CLOCKGATINGI) = MCHBAR8(CLOCKGATINGI) & ~0x3;
Damien Zammit003d15c2015-11-20 17:17:51 +11002516 return;
2517 }
Angel Pons39ff7032020-03-09 21:39:44 +01002518 MCHBAR8_OR(CLOCKGATINGI, 3);
2519 MCHBAR16_AND_OR(CLOCKGATINGIII, ~0xf000, pimdclk << 12);
2520 MCHBAR8_AND_OR(CSHWRIOBONUSX, ~0x77, (push << 4) | push);
2521 MCHBAR32_AND_OR(C0COREBONUS, ~0x0f000000, 0x03000000);
Damien Zammit003d15c2015-11-20 17:17:51 +11002522}
2523
2524/**
2525 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2526 */
2527void sdram_initialize(int boot_path, const u8 *spd_addresses)
2528{
2529 struct sysinfo si;
Angel Pons39ff7032020-03-09 21:39:44 +01002530 const char *boot_str[] = {"Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002531
2532 PRINTK_DEBUG("Setting up RAM controller.\n");
2533
2534 memset(&si, 0, sizeof(si));
2535
2536 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002537 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002538 si.spd_map[0] = spd_addresses[0];
2539 si.spd_map[1] = spd_addresses[1];
2540 si.spd_map[2] = spd_addresses[2];
2541 si.spd_map[3] = spd_addresses[3];
2542
2543 sdram_read_spds(&si);
2544
2545 /* Choose Common Frequency */
2546 sdram_detect_ram_speed(&si);
2547
2548 /* Determine smallest common tRAS, tRP, tRCD, etc */
2549 sdram_detect_smallest_params(&si);
2550
2551 /* Enable HPET */
2552 enable_hpet();
Damien Zammit003d15c2015-11-20 17:17:51 +11002553
Angel Pons39ff7032020-03-09 21:39:44 +01002554 MCHBAR16_OR(CPCTL, 1 << 15);
Damien Zammit003d15c2015-11-20 17:17:51 +11002555
Damien Zammit003d15c2015-11-20 17:17:51 +11002556 sdram_clk_crossing(&si);
2557
2558 sdram_checkreset();
2559 PRINTK_DEBUG("Done checkreset\n");
2560
2561 sdram_clkmode(&si);
2562 PRINTK_DEBUG("Done clkmode\n");
2563
2564 sdram_timings(&si);
2565 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2566
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002567 if (si.boot_path != BOOT_PATH_RESET) {
2568 sdram_dlltiming(&si);
2569 PRINTK_DEBUG("Done dlltiming\n");
2570 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002571
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002572 if (si.boot_path != BOOT_PATH_RESET) {
2573 sdram_rcomp(&si);
2574 PRINTK_DEBUG("Done RCOMP\n");
2575 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002576
2577 sdram_odt(&si);
2578 PRINTK_DEBUG("Done odt\n");
2579
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002580 if (si.boot_path != BOOT_PATH_RESET) {
Angel Pons39ff7032020-03-09 21:39:44 +01002581 while ((MCHBAR8(COMPCTRL1) & 1) != 0)
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002582 ;
2583 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002584
2585 sdram_mmap(&si);
2586 PRINTK_DEBUG("Done mmap\n");
2587
Angel Pons39ff7032020-03-09 21:39:44 +01002588 /* Enable DDR IO buffer */
2589 MCHBAR8_AND_OR(C0IOBUFACTCTL, ~0x3f, 0x08);
2590 MCHBAR8_OR(C0RSTCTL, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002591
2592 sdram_rcompupdate(&si);
2593 PRINTK_DEBUG("Done RCOMP update\n");
2594
Angel Pons39ff7032020-03-09 21:39:44 +01002595 MCHBAR8_OR(HIT4, 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11002596
2597 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01002598 MCHBAR32_OR(C0CKECTRL, 1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002599
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002600 sdram_jedecinit(&si);
2601 PRINTK_DEBUG("Done MRS\n");
2602 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002603
2604 sdram_misc(&si);
2605 PRINTK_DEBUG("Done misc\n");
2606
2607 sdram_zqcl(&si);
2608 PRINTK_DEBUG("Done zqcl\n");
2609
2610 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons39ff7032020-03-09 21:39:44 +01002611 MCHBAR32_OR(C0REFRCTRL2, 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002612 }
2613
2614 sdram_dradrb(&si);
2615 PRINTK_DEBUG("Done dradrb\n");
2616
2617 sdram_rcven(&si);
2618 PRINTK_DEBUG("Done rcven\n");
2619
2620 sdram_new_trd(&si);
2621 PRINTK_DEBUG("Done tRD\n");
2622
2623 sdram_mmap_regs(&si);
2624 PRINTK_DEBUG("Done mmap regs\n");
2625
2626 sdram_enhancedmode(&si);
2627 PRINTK_DEBUG("Done enhanced mode\n");
2628
2629 sdram_powersettings(&si);
2630 PRINTK_DEBUG("Done power settings\n");
2631
2632 sdram_programddr();
2633 PRINTK_DEBUG("Done programming ddr\n");
2634
2635 sdram_programdqdqs(&si);
2636 PRINTK_DEBUG("Done programming dqdqs\n");
2637
2638 sdram_periodic_rcomp();
2639 PRINTK_DEBUG("Done periodic RCOMP\n");
2640
2641 /* Set init done */
Angel Pons39ff7032020-03-09 21:39:44 +01002642 MCHBAR32_OR(C0REFRCTRL2, 1 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002643
2644 /* Tell ICH7 that we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002645 pci_and_config8(PCI_DEV(0, 0x1f, 0), 0xa2, (u8)~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11002646
2647 /* Tell northbridge we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002648 pci_or_config8(HOST_BRIDGE, 0xf4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002649
2650 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2651}