blob: 31086d4d2fc3ac1b7054d8c0d611a1c925a5d636 [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
Angel Pons0aeaee72021-03-26 17:57:46 +0100505 mchbar_setbits32(PMSTS, 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +0100506
Angel Pons0aeaee72021-03-26 17:57:46 +0100507 reg32 = (mchbar_read32(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 Pons0aeaee72021-03-26 17:57:46 +0100514 mchbar_write32(CLKCFG, reg32);
Angel Pons39ff7032020-03-09 21:39:44 +0100515
Angel Pons0aeaee72021-03-26 17:57:46 +0100516 s->selected_timings.mem_clock = ((mchbar_read32(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 Pons0aeaee72021-03-26 17:57:46 +0100550 mchbar_write32(HMCCMP, clkcross[fsb_freq][ddr_freq][0]);
551 mchbar_write32(HMDCMP, clkcross[fsb_freq][ddr_freq][1]);
552 mchbar_write32(HMBYPCP, clkcross[fsb_freq][ddr_freq][2]);
553 mchbar_write32(HMCCPEXT, 0);
554 mchbar_write32(HMDCPEXT, clkcross[fsb_freq][ddr_freq][3]);
Angel Pons39ff7032020-03-09 21:39:44 +0100555
Angel Pons0aeaee72021-03-26 17:57:46 +0100556 mchbar_setbits32(HMCCMC, 1 << 7);
Angel Pons39ff7032020-03-09 21:39:44 +0100557
558 if ((fsb_freq == 0) && (ddr_freq == 1)) {
Angel Pons0aeaee72021-03-26 17:57:46 +0100559 mchbar_write8(CLKXSSH2MCBYPPHAS, 0);
560 mchbar_write32(CLKXSSH2MD, 0);
561 mchbar_write32(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 Pons0aeaee72021-03-26 17:57:46 +0100587 mchbar_write32(CLKXSSH2MCBYP, clkcross2[fsb_freq][ddr_freq][0]);
588 mchbar_write32(CLKXSSH2MCRDQ, clkcross2[fsb_freq][ddr_freq][0]);
589 mchbar_write32(CLKXSSH2MCRDCST, clkcross2[fsb_freq][ddr_freq][0]);
590 mchbar_write32(CLKXSSH2MCBYP + 4, clkcross2[fsb_freq][ddr_freq][1]);
591 mchbar_write32(CLKXSSH2MCRDQ + 4, clkcross2[fsb_freq][ddr_freq][1]);
592 mchbar_write32(CLKXSSH2MCRDCST + 4, clkcross2[fsb_freq][ddr_freq][1]);
593 mchbar_write32(CLKXSSMC2H, clkcross2[fsb_freq][ddr_freq][2]);
594 mchbar_write32(CLKXSSMC2H + 4, clkcross2[fsb_freq][ddr_freq][3]);
595 mchbar_write32(CLKXSSMC2HALT, clkcross2[fsb_freq][ddr_freq][4]);
596 mchbar_write32(CLKXSSMC2HALT + 4, clkcross2[fsb_freq][ddr_freq][5]);
597 mchbar_write32(CLKXSSH2X2MD, clkcross2[fsb_freq][ddr_freq][6]);
598 mchbar_write32(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 Pons0aeaee72021-03-26 17:57:46 +0100606 mchbar_clrbits16(CSHRMISCCTL1, 1 << 8);
607 mchbar_clrbits8(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 Pons0aeaee72021-03-26 17:57:46 +0100617 mchbar_clrsetbits16(MPLLCTL, 0x033f, mpll_ctl);
Damien Zammit003d15c2015-11-20 17:17:51 +1100618
Angel Pons0aeaee72021-03-26 17:57:46 +0100619 mchbar_write32(C0GNT2LNCH1, 0x58001117);
620 mchbar_setbits32(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 Pons0aeaee72021-03-26 17:57:46 +0100627 mchbar_write32(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 Pons0aeaee72021-03-26 17:57:46 +0100652 mchbar_write8(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 Pons0aeaee72021-03-26 17:57:46 +0100672 mchbar_setbits8(C0PVCFG, 3);
673 mchbar_write16(C0CYCTRKPCHG, (wl + 4 + s->selected_timings.tWR) << 6 |
674 (2 + MAX(s->selected_timings.tRTP, 2)) << 2 | 1);
Angel Pons39ff7032020-03-09 21:39:44 +0100675
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? */
Angel Pons0aeaee72021-03-26 17:57:46 +0100684 mchbar_write16(C0CYCTRKACT + 0, (u16)(reg32));
685 mchbar_write16(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 */
Angel Pons0aeaee72021-03-26 17:57:46 +0100688 reg16 = (mchbar_read16(C0CYCTRKACT + 2) & 0x0fc0) >> 6;
689 mchbar_clrsetbits16(SHCYCTRKCKEL, 0x3f << 7, reg16 << 7);
Damien Zammit003d15c2015-11-20 17:17:51 +1100690
691 reg16 = (s->selected_timings.tRCD << 12) | (4 << 8) | (ta2 << 4) | ta4;
Angel Pons0aeaee72021-03-26 17:57:46 +0100692 mchbar_write16(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 Pons0aeaee72021-03-26 17:57:46 +0100696 mchbar_write32(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? */
Angel Pons0aeaee72021-03-26 17:57:46 +0100701 mchbar_write8(C0CYCTRKREFR + 0, (u8)(reg16));
702 mchbar_write8(C0CYCTRKREFR + 1, (u8)(reg16 >> 8));
Damien Zammit003d15c2015-11-20 17:17:51 +1100703
Angel Pons0aeaee72021-03-26 17:57:46 +0100704 mchbar_clrsetbits16(C0CKECTRL, 0x1ff << 1, 100 << 1);
705 mchbar_clrsetbits8(C0CYCTRKPCHG2, 0x3f, s->selected_timings.tRAS);
706 mchbar_write16(C0ARBCTRL, 0x2310);
707 mchbar_clrsetbits8(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);
Angel Pons0aeaee72021-03-26 17:57:46 +0100720 mchbar_clrsetbits16(C0STATRDCTRL, 0x1f << 8, 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 Pons0aeaee72021-03-26 17:57:46 +0100729 mchbar_clrsetbits16(C0WRDATACTRL, 0x1ff, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100730
Angel Pons0aeaee72021-03-26 17:57:46 +0100731 mchbar_write16(C0RDQCTRL, 0x1585);
732 mchbar_clrbits8(C0PWLRCTRL, 0x1f);
Angel Pons39ff7032020-03-09 21:39:44 +0100733
734 /* rdmodwr_window[5..0] = CL+4+5 265[13..8] (264[21..16]) */
Angel Pons0aeaee72021-03-26 17:57:46 +0100735 mchbar_clrsetbits16(C0PWLRCTRL, 0x3f << 8, (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 Pons0aeaee72021-03-26 17:57:46 +0100744 mchbar_clrsetbits32(C0REFRCTRL2, 0xfffff << 8, 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 */
Angel Pons0aeaee72021-03-26 17:57:46 +0100747 mchbar_write8(C0REFRCTRL + 3, 0);
748 mchbar_clrsetbits16(C0REFCTRL, 0x3fff, reg16);
Angel Pons39ff7032020-03-09 21:39:44 +0100749
750 /* NPUT Static Mode */
Angel Pons0aeaee72021-03-26 17:57:46 +0100751 mchbar_setbits8(C0DYNRDCTRL, 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +0100752
Angel Pons0aeaee72021-03-26 17:57:46 +0100753 mchbar_clrsetbits32(C0STATRDCTRL, 0x7f << 24, 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 Pons0aeaee72021-03-26 17:57:46 +0100757 mchbar_setbits32(C0STATRDCTRL, 1 << 24);
Damien Zammit003d15c2015-11-20 17:17:51 +1100758 }
759
Angel Pons0aeaee72021-03-26 17:57:46 +0100760 mchbar_clrbits8(C0RDFIFOCTRL, 3);
761 mchbar_clrsetbits16(C0WRDATACTRL, 0x1f << 10, (wl + 10) << 10);
762 mchbar_clrsetbits32(C0CKECTRL, 7 << 24 | 7 << 17, 3 << 24 | 3 << 17);
Damien Zammit003d15c2015-11-20 17:17:51 +1100763 reg16 = 0x15 << 6;
764 reg16 |= 0x1f;
765 reg16 |= (0x6 << 12);
Angel Pons0aeaee72021-03-26 17:57:46 +0100766 mchbar_clrsetbits16(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 */
Angel Pons0aeaee72021-03-26 17:57:46 +0100769 mchbar_clrsetbits32(C0REFRCTRL2, 3 << 28, reg32 << 8);
770 mchbar_clrsetbits8(C0REFRCTRL + 3, 0xfa, reg32 >> 24);
771 mchbar_clrbits8(C0JEDEC, 1 << 7);
772 mchbar_clrbits8(C0DYNRDCTRL, 3 << 1);
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;
Angel Pons0aeaee72021-03-26 17:57:46 +0100776 mchbar_write32(C0WRWMFLSH, reg32);
777 mchbar_clrsetbits16(C0WRWMFLSH + 4, 0x1ff, 8 << 3 | 6 >> 2);
778 mchbar_setbits16(SHPENDREG, 0x1c00 | 0x1f << 5);
Angel Pons39ff7032020-03-09 21:39:44 +0100779
780 /* FIXME: Why not do a single word write? */
Angel Pons0aeaee72021-03-26 17:57:46 +0100781 mchbar_clrsetbits8(SHPAGECTRL, 0xff, 0x40);
782 mchbar_clrsetbits8(SHPAGECTRL + 1, 0x07, 0x05);
783 mchbar_setbits8(SHCMPLWRCMD, 0x1f);
Angel Pons39ff7032020-03-09 21:39:44 +0100784
785 reg8 = (3 << 6);
Damien Zammit003d15c2015-11-20 17:17:51 +1100786 reg8 |= (s->dt0mode << 4);
787 reg8 |= 0x0c;
Angel Pons0aeaee72021-03-26 17:57:46 +0100788 mchbar_clrsetbits8(SHBONUSREG, 0xdf, reg8);
789 mchbar_clrbits8(CSHRWRIOMLNS, 1 << 1);
790 mchbar_clrsetbits8(C0MISCTM, 0x07, 0x02);
791 mchbar_clrsetbits16(C0BYPCTRL, 0xff << 2, 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);
Angel Pons0aeaee72021-03-26 17:57:46 +0100795 mchbar_clrsetbits32(WRWMCONFIG, 0xffb << 20, reg32);
Angel Pons39ff7032020-03-09 21:39:44 +0100796
Angel Pons0aeaee72021-03-26 17:57:46 +0100797 reg8 = (u8) ((mchbar_read16(C0CYCTRKACT) & 0xe000) >> 13);
798 reg8 |= (u8) ((mchbar_read16(C0CYCTRKACT + 2) & 1) << 3);
799 mchbar_clrsetbits8(BYPACTSF, 0xf << 4, reg8 << 4);
Angel Pons39ff7032020-03-09 21:39:44 +0100800
Angel Pons0aeaee72021-03-26 17:57:46 +0100801 reg8 = (u8) ((mchbar_read32(C0CYCTRKRD) & 0x000f0000) >> 17);
802 mchbar_clrsetbits8(BYPACTSF, 0xf, reg8);
Angel Pons39ff7032020-03-09 21:39:44 +0100803
804 /* FIXME: Why not clear everything at once? */
Angel Pons0aeaee72021-03-26 17:57:46 +0100805 mchbar_clrbits8(BYPKNRULE, 0xfc);
806 mchbar_clrbits8(BYPKNRULE, 0x03);
807 mchbar_clrbits8(SHBONUSREG, 0x03);
808 mchbar_setbits8(C0BYPCTRL, 1 << 0);
809 mchbar_setbits16(CSHRMISCCTL1, 1 << 9);
Angel Pons39ff7032020-03-09 21:39:44 +0100810
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 */
Angel Pons0aeaee72021-03-26 17:57:46 +0100813 mchbar_clrsetbits32(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 */
Angel Pons0aeaee72021-03-26 17:57:46 +0100816 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, (s->selected_timings.CAS + 1) << 16);
Angel Pons39ff7032020-03-09 21:39:44 +0100817
818 /* Program RCVEN delay with DLL-safe settings */
Damien Zammit003d15c2015-11-20 17:17:51 +1100819 for (i = 0; i < 8; i++) {
Angel Pons0aeaee72021-03-26 17:57:46 +0100820 mchbar_clrbits8(C0RXRCVyDLL(i), 0x3f);
Angel Pons39ff7032020-03-09 21:39:44 +0100821 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 Pons0aeaee72021-03-26 17:57:46 +0100825 mchbar_clrbits8(C0DLLPIEN, 1 << 0); /* Power up receiver */
826 mchbar_setbits8(C0DLLPIEN, 1 << 1); /* Enable RCVEN DLL */
827 mchbar_setbits8(C0DLLPIEN, 1 << 2); /* Enable receiver DQS DLL */
828 mchbar_setbits32(C0COREBONUS, 0x000c0400);
829 mchbar_setbits32(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 Pons0aeaee72021-03-26 17:57:46 +0100835 mchbar_clrsetbits16(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
Angel Pons0aeaee72021-03-26 17:57:46 +0100840 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +0100846 mchbar_clrsetbits32(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
Angel Pons0aeaee72021-03-26 17:57:46 +0100851 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +0100861 mchbar_clrsetbits8(C0CMDTX1, 3 << 5, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100862
863 reg8 = pll->clkdelay[f][i] << 4;
Angel Pons0aeaee72021-03-26 17:57:46 +0100864 mchbar_clrsetbits8(C0CMDTX2, 3 << 4, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100865
866 reg8 = pll->pi[f][i];
Angel Pons0aeaee72021-03-26 17:57:46 +0100867 mchbar_clrsetbits8(C0TXCMD0DLL, 0x3f, reg8);
868 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +0100884 mchbar_clrsetbits32(C0CTLTX2, 0x01bf0000, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100885
886 reg8 = pll->pi[f][i];
Angel Pons0aeaee72021-03-26 17:57:46 +0100887 mchbar_clrsetbits8(C0TXCTL0DLL, 0x3f, reg8);
888 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +0100897 mchbar_clrsetbits32(C0CMDTX2, 0xff << 8, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100898
899 reg8 = pll->pi[f][i];
Angel Pons0aeaee72021-03-26 17:57:46 +0100900 mchbar_clrsetbits8(C0TXCTL2DLL, 0x3f, reg8);
901 mchbar_clrsetbits8(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
Angel Pons0aeaee72021-03-26 17:57:46 +0100918 mchbar_clrsetbits32(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);
Angel Pons0aeaee72021-03-26 17:57:46 +0100921 mchbar_clrsetbits32(C0DQSDQRyTX3(rank), 1 << (dqs * 2 + 17) | 1 << (dqs * 2 + 16),
Angel Pons39ff7032020-03-09 21:39:44 +0100922 reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100923
924 reg8 = pll->pi[f][clk];
Angel Pons0aeaee72021-03-26 17:57:46 +0100925 mchbar_clrsetbits8(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
Angel Pons0aeaee72021-03-26 17:57:46 +0100942 mchbar_clrsetbits32(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 Pons0aeaee72021-03-26 17:57:46 +0100945 mchbar_clrsetbits32(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 Pons0aeaee72021-03-26 17:57:46 +0100948 mchbar_clrsetbits8(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 */
Angel Pons0aeaee72021-03-26 17:57:46 +01001039 mchbar_clrbits8(CSHRDQSCMN, 1 << 7);
1040 mchbar_clrsetbits16(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 Pons0aeaee72021-03-26 17:57:46 +01001063 mchbar_setbits16(CSHRPDCTL, 1 << 15);
1064 mchbar_clrbits8(CSHRPDCTL, 1 << 7);
1065 mchbar_setbits8(CSHRPDCTL, 1 << 3);
1066 mchbar_setbits8(CSHRPDCTL, 1 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001067
Angel Pons39ff7032020-03-09 21:39:44 +01001068 /* Start hardware HMC calibration */
Angel Pons0aeaee72021-03-26 17:57:46 +01001069 mchbar_setbits8(CSHRPDCTL, 1 << 7);
Angel Pons39ff7032020-03-09 21:39:44 +01001070
1071 /* Busy-wait until calibration is done */
Angel Pons0aeaee72021-03-26 17:57:46 +01001072 while ((mchbar_read8(CSHRPDCTL) & (1 << 2)) == 0)
Angel Pons39ff7032020-03-09 21:39:44 +01001073 ;
1074
1075 /* If hardware HMC calibration failed */
Angel Pons0aeaee72021-03-26 17:57:46 +01001076 reg8 = (mchbar_read8(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 Pons0aeaee72021-03-26 17:57:46 +01001094 mchbar_clrsetbits32(CSHRMSTRCTL1, 0x0fffffff, reg32);
1095 mchbar_setbits32(CSHRMSTRCTL1, 1 << 23);
1096 mchbar_setbits32(CSHRMSTRCTL1, 1 << 15);
1097 mchbar_clrbits32(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! */
Angel Pons0aeaee72021-03-26 17:57:46 +01001101 mchbar_setbits16(CSHRMSTRCTL0, 1 << 0);
1102 mchbar_setbits16(CSHRMSTRCTL0, 1 << 2);
1103 mchbar_setbits16(CSHRMSTRCTL0, 1 << 4);
1104 mchbar_setbits16(CSHRMSTRCTL0, 1 << 8);
1105 mchbar_setbits16(CSHRMSTRCTL0, 1 << 10);
1106 mchbar_setbits16(CSHRMSTRCTL0, 1 << 12);
1107 mchbar_setbits16(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! */
Angel Pons0aeaee72021-03-26 17:57:46 +01001110 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 0);
1111 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 2);
1112 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 4);
1113 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 8);
1114 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 10);
1115 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 12);
1116 mchbar_clrbits16(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 Pons0aeaee72021-03-26 17:57:46 +01001121 mchbar_clrsetbits8(CREFPI, 0x3f, 0x07);
Damien Zammit003d15c2015-11-20 17:17:51 +11001122 } else {
Angel Pons0aeaee72021-03-26 17:57:46 +01001123 mchbar_clrbits8(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 */
Angel Pons0aeaee72021-03-26 17:57:46 +01001129 mchbar_setbits16(C0DLLPIEN, 1 << 11);
1130 mchbar_setbits16(C0DLLPIEN, 1 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11001131
1132 for (i = 0; i < 8; i++) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001133 mchbar_setbits16(C0DLLPIEN, (1 << 10) >> i);
Damien Zammit003d15c2015-11-20 17:17:51 +11001134 }
Angel Pons39ff7032020-03-09 21:39:44 +01001135 /* Enable DQ/DQS output */
Angel Pons0aeaee72021-03-26 17:57:46 +01001136 mchbar_setbits8(C0SLVDLLOUTEN, 1 << 0);
1137 mchbar_write16(CSPDSLVWT, 0x5005);
1138 mchbar_clrsetbits16(CSHRPDCTL2, 0x1f1f, 0x051a);
1139 mchbar_clrsetbits16(CSHRPDCTL5, 0xbf3f, 0x9010);
Damien Zammit003d15c2015-11-20 17:17:51 +11001140
1141 if (s->nodll) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001142 mchbar_clrsetbits8(CSHRPDCTL3, 0x7f, 0x6b);
Damien Zammit003d15c2015-11-20 17:17:51 +11001143 } else {
Angel Pons0aeaee72021-03-26 17:57:46 +01001144 mchbar_clrsetbits8(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 */
Angel Pons0aeaee72021-03-26 17:57:46 +01001148 mchbar_clrbits32(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 */
Angel Pons0aeaee72021-03-26 17:57:46 +01001151 mchbar_clrbits8(C0MISCCTL, 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001152
Angel Pons39ff7032020-03-09 21:39:44 +01001153 /* Disable (gate) mdclk and mdclkb */
Angel Pons0aeaee72021-03-26 17:57:46 +01001154 mchbar_setbits8(CSHWRIOBONUS, 3 << 6);
Jacob Garberd10680b2019-06-11 14:13:04 -06001155
Angel Pons39ff7032020-03-09 21:39:44 +01001156 /* Select mdmclk */
Angel Pons0aeaee72021-03-26 17:57:46 +01001157 mchbar_clrbits8(CSHWRIOBONUS, 1 << 5);
Damien Zammit003d15c2015-11-20 17:17:51 +11001158
Angel Pons39ff7032020-03-09 21:39:44 +01001159 /* Ungate mdclk */
Angel Pons0aeaee72021-03-26 17:57:46 +01001160 mchbar_clrsetbits8(CSHWRIOBONUS, 3 << 6, 1 << 6);
1161 mchbar_clrsetbits8(CSHRFIFOCTL, 0x3f, 0x1a);
Angel Pons39ff7032020-03-09 21:39:44 +01001162
1163 /* Enable the write pointer count */
Angel Pons0aeaee72021-03-26 17:57:46 +01001164 mchbar_setbits8(CSHRFIFOCTL, 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +01001165
1166 /* Set the DDR3 Reset Enable bit */
Angel Pons0aeaee72021-03-26 17:57:46 +01001167 mchbar_setbits8(CSHRDDR3CTL, 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +01001168
1169 /* Configure DQS-DQ Transmit */
Angel Pons0aeaee72021-03-26 17:57:46 +01001170 mchbar_write32(CSHRDQSTXPGM, 0x00551803);
Angel Pons39ff7032020-03-09 21:39:44 +01001171
1172 reg8 = 0; /* Switch all clocks on anyway */
1173
1174 /* Enable clock groups depending on rank population */
Angel Pons0aeaee72021-03-26 17:57:46 +01001175 mchbar_clrsetbits32(C0CKTX, 0x3f << 24, reg8 << 24);
Angel Pons39ff7032020-03-09 21:39:44 +01001176
1177 /* Enable DDR command output buffers from core */
Angel Pons0aeaee72021-03-26 17:57:46 +01001178 mchbar_clrbits8(0x594, 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +01001179
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 Pons0aeaee72021-03-26 17:57:46 +01001193 mchbar_setbits16(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 Pons0aeaee72021-03-26 17:57:46 +01001328 mchbar_clrsetbits8(C0RCOMPCTRLx(i), 1 << 0, reg8);
1329 mchbar_clrbits8(C0RCOMPCTRLx(i), 1 << 1);
Angel Pons39ff7032020-03-09 21:39:44 +01001330
1331 reg16 = rcompslew;
Angel Pons0aeaee72021-03-26 17:57:46 +01001332 mchbar_clrsetbits16(C0RCOMPCTRLx(i), 0xf << 12, reg16 << 12);
Angel Pons39ff7032020-03-09 21:39:44 +01001333
Angel Pons0aeaee72021-03-26 17:57:46 +01001334 mchbar_write8(C0RCOMPMULTx(i), rcompstr[i]);
1335 mchbar_write16(C0SCOMPVREFx(i), rcompscomp[i]);
1336 mchbar_clrsetbits8(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? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001339 mchbar_clrsetbits16(C0RCOMPCTRLx(i), 0xf << 12, reg16 << 12);
Angel Pons39ff7032020-03-09 21:39:44 +01001340
Angel Pons0aeaee72021-03-26 17:57:46 +01001341 mchbar_write8(C0RCOMPMULTx(i), rcompstr2[s->dimm_config[0]]);
1342 mchbar_write16(C0SCOMPVREFx(i), rcompscomp2[s->dimm_config[0]]);
1343 mchbar_clrsetbits8(C0DCOMPx(i), 0x03, rcompdelay2[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001344 }
1345
Angel Pons0aeaee72021-03-26 17:57:46 +01001346 mchbar_clrbits16(C0SLEWBASEx(i), 0x7f7f);
Angel Pons39ff7032020-03-09 21:39:44 +01001347
1348 /* FIXME: Why not do a single dword write? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001349 mchbar_clrbits16(C0SLEWPULUTx(i), 0x3f3f);
1350 mchbar_clrbits16(C0SLEWPULUTx(i) + 2, 0x3f3f);
Angel Pons39ff7032020-03-09 21:39:44 +01001351
1352 /* FIXME: Why not do a single dword write? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001353 mchbar_clrbits16(C0SLEWPDLUTx(i), 0x3f3f);
1354 mchbar_clrbits16(C0SLEWPDLUTx(i) + 2, 0x3f3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001355 }
1356
Angel Pons39ff7032020-03-09 21:39:44 +01001357 /* FIXME: Hardcoded */
Angel Pons0aeaee72021-03-26 17:57:46 +01001358 mchbar_clrsetbits8(C0ODTRECORDX, 0x3f, 0x36);
1359 mchbar_clrsetbits8(C0DQSODTRECORDX, 0x3f, 0x36);
Damien Zammit003d15c2015-11-20 17:17:51 +11001360
Angel Pons39ff7032020-03-09 21:39:44 +01001361 FOR_EACH_RCOMP_GROUP(i) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001362 mchbar_clrbits8(C0RCOMPCTRLx(i), 3 << 5);
1363 mchbar_clrbits16(C0RCOMPCTRLx(i) + 2, 0x0706);
1364 mchbar_clrbits16(C0RCOMPOSVx(i), 0x7f7f);
1365 mchbar_clrbits16(C0SCOMPOFFx(i), 0x3f3f);
1366 mchbar_clrbits16(C0DCOMPOFFx(i), 0x1f1f);
1367 mchbar_clrbits8(C0DCOMPOFFx(i) + 2, 0x1f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001368 }
1369
Angel Pons0aeaee72021-03-26 17:57:46 +01001370 mchbar_clrbits16(C0ODTRECORDX, 0xffc0);
1371 mchbar_clrbits16(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? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001374 mchbar_clrbits16(C0DQSODTRECORDX, 0xffc0);
1375 mchbar_clrbits16(C0DQSODTRECORDX + 2, 0x000f);
Angel Pons39ff7032020-03-09 21:39:44 +01001376
1377 FOR_EACH_RCOMP_GROUP(i) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001378 mchbar_write16(C0SCOMPOVRx(i), rcompf[i]);
Angel Pons39ff7032020-03-09 21:39:44 +01001379
1380 /* FIXME: Why not do a single dword write? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001381 mchbar_write16(C0DCOMPOVRx(i) + 0, 0x1219);
1382 mchbar_write16(C0DCOMPOVRx(i) + 2, 0x000c);
Damien Zammit003d15c2015-11-20 17:17:51 +11001383 }
1384
Angel Pons0aeaee72021-03-26 17:57:46 +01001385 mchbar_clrsetbits32(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? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001388 mchbar_clrsetbits16(XCOMPSDR0BNS, 0x1f << 8, 0x12 << 8);
1389 mchbar_clrsetbits8(XCOMPSDR0BNS, 0x1f << 0, 0x12 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +01001390
Angel Pons0aeaee72021-03-26 17:57:46 +01001391 mchbar_write32(COMPCTRL3, 0x007c9007);
1392 mchbar_write32(OFREQDELSEL, rcomp1);
1393 mchbar_write16(XCOMPCMNBNS, 0x1f7f);
1394 mchbar_write32(COMPCTRL2, rcomp2);
1395 mchbar_clrsetbits16(XCOMPDFCTRL, 0xf, 1);
1396 mchbar_write16(ZQCALCTRL, 0x0134);
1397 mchbar_write32(COMPCTRL1, 0x4c293600);
Angel Pons39ff7032020-03-09 21:39:44 +01001398
Angel Pons0aeaee72021-03-26 17:57:46 +01001399 mchbar_clrsetbits8(COMPCTRL1 + 3, 0x44, 1 << 6 | 1 << 2);
1400 mchbar_clrbits16(XCOMPSDR0BNS, 1 << 13);
1401 mchbar_clrbits8(XCOMPSDR0BNS, 1 << 5);
Angel Pons39ff7032020-03-09 21:39:44 +01001402
1403 FOR_EACH_RCOMP_GROUP(i) {
Angel Pons07ccc8d2021-03-26 19:07:49 +01001404 /* POR values are zero */
Angel Pons0aeaee72021-03-26 17:57:46 +01001405 mchbar_clrbits8(C0RCOMPCTRLx(i) + 2, 0x71);
Damien Zammit003d15c2015-11-20 17:17:51 +11001406 }
1407
Angel Pons0aeaee72021-03-26 17:57:46 +01001408 if ((mchbar_read32(COMPCTRL1) & (1 << 30)) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001409 /* Start COMP */
Angel Pons0aeaee72021-03-26 17:57:46 +01001410 mchbar_setbits8(COMPCTRL1, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001411
Angel Pons39ff7032020-03-09 21:39:44 +01001412 /* Wait until COMP is done */
Angel Pons0aeaee72021-03-26 17:57:46 +01001413 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
Angel Pons39ff7032020-03-09 21:39:44 +01001414 ;
1415
Angel Pons0aeaee72021-03-26 17:57:46 +01001416 reg32 = mchbar_read32(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) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001421 srup = (mchbar_read8(C0RCOMPCTRLx(i) + 1) & 0xc0) >> 6;
1422 srun = (mchbar_read8(C0RCOMPCTRLx(i) + 1) & 0x30) >> 4;
Angel Pons39ff7032020-03-09 21:39:44 +01001423
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 Pons0aeaee72021-03-26 17:57:46 +01001426 mchbar_clrsetbits16(C0SLEWBASEx(i), 0x7f << 8, reg16);
Angel Pons39ff7032020-03-09 21:39:44 +01001427
Damien Zammit003d15c2015-11-20 17:17:51 +11001428 reg16 = (u16)(rcompn - (1 << (srun + 1)));
Angel Pons0aeaee72021-03-26 17:57:46 +01001429 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +01001434 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +01001439 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +01001444 mchbar_clrsetbits8(C0SLEWPULUTx(3) + i, 0x3f, rcomplut[j][6]);
1445 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +01001449 mchbar_clrsetbits8(C0SLEWPULUTx(5) + i, 0x3f, rcomplut[j][8]);
1450 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +01001455 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +01001460 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +01001465 mchbar_clrsetbits8(C0SLEWPDLUTx(3) + i, 0x3f, rcomplut[j][7]);
1466 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +01001470 mchbar_clrsetbits8(C0SLEWPDLUTx(5) + i, 0x3f, rcomplut[j][9]);
1471 mchbar_clrsetbits8(C0SLEWPDLUTx(6) + i, 0x3f, rcomplut[j][9]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001472 }
1473 }
Angel Pons0aeaee72021-03-26 17:57:46 +01001474 mchbar_setbits8(COMPCTRL1, 1 << 0);
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 */
Angel Pons0aeaee72021-03-26 17:57:46 +01001526 mchbar_write16(C0ODT, odt_matrix[rankindex]);
Angel Pons39ff7032020-03-09 21:39:44 +01001527
1528 /* Program the ODT Rank Control */
Angel Pons0aeaee72021-03-26 17:57:46 +01001529 mchbar_write16(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 Pons0aeaee72021-03-26 17:57:46 +01001549 mchbar_clrsetbits32(C0CKECTRL, 1, 0x300001);
1550 mchbar_write32(C0DRA01, 0x00000101);
1551 mchbar_write32(C0DRB0, 0x00040002);
1552 mchbar_write32(C0DRB2, w204[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001553 } else {
1554 // 1R/NC
Angel Pons0aeaee72021-03-26 17:57:46 +01001555 mchbar_clrsetbits32(C0CKECTRL, 1, 0x100001);
1556 mchbar_write32(C0DRA01, 0x00000001);
1557 mchbar_write32(C0DRB0, 0x00020002);
1558 mchbar_write32(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 Pons0aeaee72021-03-26 17:57:46 +01001561 mchbar_clrsetbits32(C0CKECTRL, 1, 0x300001);
1562 mchbar_write32(C0DRA01, 0x00000101);
1563 mchbar_write32(C0DRB0, 0x00040002);
1564 mchbar_write32(C0DRB2, 0x00040004);
Damien Zammit003d15c2015-11-20 17:17:51 +11001565 } else {
Angel Pons0aeaee72021-03-26 17:57:46 +01001566 mchbar_clrsetbits32(C0CKECTRL, 1, w260[s->dimm_config[0]]);
1567 mchbar_write32(C0DRA01, w208[s->dimm_config[0]]);
1568 mchbar_write32(C0DRB0, w200[s->dimm_config[0]]);
1569 mchbar_write32(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 Pons0aeaee72021-03-26 17:57:46 +01001584 xcomp = mchbar_read32(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 Pons0aeaee72021-03-26 17:57:46 +01001602 mchbar_write32(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 Pons0aeaee72021-03-26 17:57:46 +01001614 mchbar_clrbits8(XCOMPDFCTRL, 1 << 3);
1615 mchbar_clrbits8(COMPCTRL1, 1 << 7);
Damien Zammit003d15c2015-11-20 17:17:51 +11001616 for (i = 0; i < 3; i++) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001617 mchbar_setbits8(COMPCTRL1, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001618 hpet_udelay(1000);
Angel Pons0aeaee72021-03-26 17:57:46 +01001619 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
Angel Pons39ff7032020-03-09 21:39:44 +01001620 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001621 ok |= sdram_checkrcompoverride();
1622 }
1623 if (!ok) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001624 reg32a = mchbar_read32(XCOMP);
Angel Pons39ff7032020-03-09 21:39:44 +01001625 reg32b = ((reg32a >> 16) & 0x0000ffff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001626 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1627 reg32a |= (1 << 31) | (1 << 15);
Angel Pons0aeaee72021-03-26 17:57:46 +01001628 mchbar_write32(RCMEASBUFXOVR, reg32a);
Damien Zammit003d15c2015-11-20 17:17:51 +11001629 }
Angel Pons0aeaee72021-03-26 17:57:46 +01001630 mchbar_setbits8(COMPCTRL1, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001631 hpet_udelay(1000);
Angel Pons0aeaee72021-03-26 17:57:46 +01001632 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
Angel Pons39ff7032020-03-09 21:39:44 +01001633 ;
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);
Angel Pons0aeaee72021-03-26 17:57:46 +01001643 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +01001652 mchbar_setbits32(C0CKECTRL, 1 << 27);
1653 mchbar_clrsetbits8(C0JEDEC, 0x0e, NORMAL_OP_CMD);
1654 mchbar_clrbits8(C0JEDEC, 3 << 4);
1655 mchbar_clrsetbits32(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);
Angel Pons0aeaee72021-03-26 17:57:46 +01001721 mchbar_clrsetbits32(C0DYNRDCTRL, 0x3ff << 8, reg32);
1722 mchbar_clrbits8(C0DYNRDCTRL, 1 << 7);
1723 mchbar_setbits8(C0REFRCTRL + 3, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001724 if (s->boot_path != BOOT_PATH_RESUME) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001725 mchbar_clrsetbits8(C0JEDEC, 0x0e, NORMAL_OP_CMD);
1726 mchbar_clrbits8(C0JEDEC, 3 << 4);
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 Pons0aeaee72021-03-26 17:57:46 +01001814 mchbar_write32(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 Pons0aeaee72021-03-26 17:57:46 +01001823 mchbar_clrsetbits8(C0CKECTRL + 2, 0xf0, reg8);
Angel Pons39ff7032020-03-09 21:39:44 +01001824
1825 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) || ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001826 mchbar_setbits8(C0CKECTRL, 1 << 0);
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 }
Angel Pons0aeaee72021-03-26 17:57:46 +01001837 mchbar_write16(addr, c0drb);
Damien Zammit003d15c2015-11-20 17:17:51 +11001838 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 Pons0aeaee72021-03-26 17:57:46 +01001847 mchbar_clrbits8(C0RSTCTL, 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001848 hpet_udelay(1);
Angel Pons0aeaee72021-03-26 17:57:46 +01001849 mchbar_setbits8(C0RSTCTL, 1 << 1);
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
Angel Pons0aeaee72021-03-26 17:57:46 +01001856 if (((mchbar_read8(dqshighaddr) & (1 << 6)) >> 6) != highlow) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001857 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 Pons0aeaee72021-03-26 17:57:46 +01001872 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, *coarse << 16);
Angel Pons39ff7032020-03-09 21:39:44 +01001873 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 Pons0aeaee72021-03-26 17:57:46 +01001892 mchbar_clrbits8(C0RSTCTL, 3 << 2);
1893 mchbar_clrbits8(CMNDQFIFORST, 1 << 7);
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 Pons0aeaee72021-03-26 17:57:46 +01001905 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
Angel Pons39ff7032020-03-09 21:39:44 +01001906 MCHBAR16_AND_OR(C0RCVMISCCTL2, (u16)~(3 << (lane * 2)), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001907
Angel Pons0aeaee72021-03-26 17:57:46 +01001908 mchbar_clrbits8(C0RXRCVyDLL(lane), 0x3f);
Angel Pons39ff7032020-03-09 21:39:44 +01001909
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;
Angel Pons0aeaee72021-03-26 17:57:46 +01001948 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
Angel Pons39ff7032020-03-09 21:39:44 +01001949 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 Pons0aeaee72021-03-26 17:57:46 +01001960 mchbar_clrsetbits8(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 Pons0aeaee72021-03-26 17:57:46 +01001965 mchbar_clrsetbits8(C0RXRCVyDLL(lane), 0x3f, pi << s->pioffset);
Angel Pons39ff7032020-03-09 21:39:44 +01001966 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--;
Angel Pons0aeaee72021-03-26 17:57:46 +01001975 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
Angel Pons39ff7032020-03-09 21:39:44 +01001976 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 Pons0aeaee72021-03-26 17:57:46 +01002005 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, minlanecoarse << 16);
Damien Zammit003d15c2015-11-20 17:17:51 +11002006
Angel Pons39ff7032020-03-09 21:39:44 +01002007 s->coarsectrl = minlanecoarse;
Angel Pons0aeaee72021-03-26 17:57:46 +01002008 s->coarsedelay = mchbar_read16(C0COARSEDLY0);
2009 s->mediumphase = mchbar_read16(C0RCVMISCCTL2);
2010 s->readptrdelay = mchbar_read16(C0RCVMISCCTL1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002011
2012 PRINTK_DEBUG("rcven 2\n");
Angel Pons0aeaee72021-03-26 17:57:46 +01002013 mchbar_clrbits8(C0RSTCTL, 7 << 1);
2014 mchbar_setbits8(C0RSTCTL, 1 << 1);
2015 mchbar_setbits8(C0RSTCTL, 1 << 2);
2016 mchbar_setbits8(C0RSTCTL, 1 << 3);
Damien Zammit003d15c2015-11-20 17:17:51 +11002017
Angel Pons0aeaee72021-03-26 17:57:46 +01002018 mchbar_setbits8(CMNDQFIFORST, 1 << 7);
2019 mchbar_clrbits8(CMNDQFIFORST, 1 << 7);
2020 mchbar_setbits8(CMNDQFIFORST, 1 << 7);
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 Pons0aeaee72021-03-26 17:57:46 +01002100 mchbar_setbits8(C0ADDCSCTRL, 1 << 0);
2101 mchbar_setbits8(C0REFRCTRL + 3, 1 << 0);
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;
Angel Pons0aeaee72021-03-26 17:57:46 +01002104 mchbar_clrsetbits32(WRWMCONFIG, mask32, reg32);
2105 mchbar_write8(C0DITCTRL + 1, 2);
2106 mchbar_write16(C0DITCTRL + 2, 0x0804);
2107 mchbar_write16(C0DITCTRL + 4, 0x2010);
2108 mchbar_write8(C0DITCTRL + 6, 0x40);
2109 mchbar_write16(C0DITCTRL + 8, 0x091c);
2110 mchbar_write8(C0DITCTRL + 10, 0xf2);
2111 mchbar_setbits8(C0BYPCTRL, 1 << 0);
2112 mchbar_setbits8(C0CWBCTRL, 1 << 0);
2113 mchbar_setbits16(C0ARBSPL, 1 << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11002114
Angel Pons26766fd2020-06-08 12:38:19 +02002115 pci_or_config8(HOST_BRIDGE, 0xf0, 1);
Angel Pons0aeaee72021-03-26 17:57:46 +01002116 mchbar_write32(SBCTL, 0x00000002);
2117 mchbar_write32(SBCTL2, 0x20310002);
2118 mchbar_write32(SLIMCFGTMG, 0x02020302);
2119 mchbar_write32(HIT0, 0x001f1806);
2120 mchbar_write32(HIT1, 0x01102800);
2121 mchbar_write32(HIT2, 0x07000000);
2122 mchbar_write32(HIT3, 0x01014010);
2123 mchbar_write32(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 Pons0aeaee72021-03-26 17:57:46 +01002137 dra = (u8) ((mchbar_read32(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 Pons0aeaee72021-03-26 17:57:46 +01002171 mchbar_clrsetbits8(CHDECMISC, 0xfc, reg8 & 0xfc);
2172 mchbar_clrbits32(NOACFGBUSCTL, 1 << 31);
Damien Zammit003d15c2015-11-20 17:17:51 +11002173
Angel Pons0aeaee72021-03-26 17:57:46 +01002174 mchbar_write32(HTBONUS0, 0xf);
2175 mchbar_setbits8(C0COREBONUS + 4, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002176
Angel Pons0aeaee72021-03-26 17:57:46 +01002177 mchbar_clrbits32(HIT3, 7 << 25);
2178 mchbar_clrsetbits32(HIT4, 3 << 18, 1 << 18);
Angel Pons39ff7032020-03-09 21:39:44 +01002179
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
Angel Pons0aeaee72021-03-26 17:57:46 +01002194 mchbar_write32(CLKXSSH2X2MD + 0, clkcx[fsb_freq][ddr_freq][0]);
2195 mchbar_write32(CLKXSSH2X2MD + 4, clkcx[fsb_freq][ddr_freq][1]);
2196 mchbar_write32(CLKXSSH2MCBYP + 4, clkcx[fsb_freq][ddr_freq][2]);
Angel Pons39ff7032020-03-09 21:39:44 +01002197
Angel Pons0aeaee72021-03-26 17:57:46 +01002198 mchbar_clrbits8(HIT4, 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002199}
2200
2201static void sdram_periodic_rcomp(void)
2202{
Angel Pons0aeaee72021-03-26 17:57:46 +01002203 mchbar_clrbits8(COMPCTRL1, 1 << 1);
2204 while ((mchbar_read32(COMPCTRL1) & (1 << 31)) > 0) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002205 ;
2206 }
Angel Pons0aeaee72021-03-26 17:57:46 +01002207 mchbar_clrbits16(CSHRMISCCTL, 3 << 12);
2208 mchbar_setbits8(CMNDQFIFORST, 1 << 7);
2209 mchbar_clrsetbits16(XCOMPDFCTRL, 0x0f, 0x09);
Damien Zammit003d15c2015-11-20 17:17:51 +11002210
Angel Pons0aeaee72021-03-26 17:57:46 +01002211 mchbar_setbits8(COMPCTRL1, 1 << 7 | 1 << 1);
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 Pons0aeaee72021-03-26 17:57:46 +01002266 if ((mchbar_read8(HMBYPCP + 3) == 0xff) && (mchbar_read8(HMCCMC) & (1 << 7))) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002267 bypass = 1;
2268 } else {
2269 bypass = 0;
2270 }
2271
2272 txfifo = 0;
Angel Pons0aeaee72021-03-26 17:57:46 +01002273 reg8 = (mchbar_read8(CSHRFIFOCTL) & 0x0e) >> 1;
Angel Pons39ff7032020-03-09 21:39:44 +01002274 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 Pons0aeaee72021-03-26 17:57:46 +01002299 mchbar_clrsetbits16(C0STATRDCTRL, 0x1f << 8, 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 Pons0aeaee72021-03-26 17:57:46 +01002308 mchbar_write8(TSC1, 0x9b);
2309 mchbar_clrsetbits32(TSTTP, 0x00ffffff, 0x1d00);
2310 mchbar_write8(THERM1, 0x08);
2311 mchbar_write8(TSC3, 0);
2312 mchbar_clrsetbits8(TSC2, 0x0f, 0x04);
2313 mchbar_clrsetbits8(THERM1, 1, 1);
2314 mchbar_clrsetbits8(TCO, 1 << 7, 1 << 7);
Damien Zammit003d15c2015-11-20 17:17:51 +11002315
2316 /* Clock gating */
Angel Pons0aeaee72021-03-26 17:57:46 +01002317 mchbar_clrbits32(PMMISC, 1 << 18 | 1 << 0);
2318 mchbar_clrbits8(SBCTL3 + 3, 1 << 7);
2319 mchbar_clrbits8(CISDCTRL + 3, 1 << 7);
2320 mchbar_clrbits16(CICGDIS, 0x1fff);
2321 mchbar_clrbits32(SBCLKGATECTRL, 0x1ffff);
2322 mchbar_clrsetbits16(HICLKGTCTL, 0x03ff, 0x06);
2323 mchbar_clrsetbits32(HTCLKGTCTL, ~0, 0x20);
2324 mchbar_clrbits8(TSMISC, 1 << 0);
2325 mchbar_write8(C0WRDPYN, s->selected_timings.CAS - 1 + 0x15);
2326 mchbar_clrsetbits16(CLOCKGATINGI, 0x07fc, 0x0040);
2327 mchbar_clrsetbits16(CLOCKGATINGII, 0x0fff, 0x0d00);
2328 mchbar_clrbits16(CLOCKGATINGIII, 0x0d80);
2329 mchbar_write16(GTDPCGC + 2, 0xffff);
Damien Zammit003d15c2015-11-20 17:17:51 +11002330
2331 /* Sequencing */
Angel Pons0aeaee72021-03-26 17:57:46 +01002332 mchbar_clrsetbits32(HPWRCTL1, 0x1fffffff, 0x1f643fff);
2333 mchbar_clrsetbits32(HPWRCTL2, 0xffffff7f, 0x02010000);
2334 mchbar_clrsetbits16(HPWRCTL3, 7 << 12, 3 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11002335
2336 /* Power */
Angel Pons0aeaee72021-03-26 17:57:46 +01002337 mchbar_clrsetbits32(GFXC3C4, 0xffff0003, 0x10100000);
2338 mchbar_clrsetbits32(PMDSLFRC, 0x0001bff7, 0x00000078);
Angel Pons39ff7032020-03-09 21:39:44 +01002339
2340 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz)
Angel Pons0aeaee72021-03-26 17:57:46 +01002341 mchbar_clrsetbits16(PMMSPMRES, 0x03ff, 0x00c8);
Angel Pons39ff7032020-03-09 21:39:44 +01002342 else
Angel Pons0aeaee72021-03-26 17:57:46 +01002343 mchbar_clrsetbits16(PMMSPMRES, 0x03ff, 0x0100);
Angel Pons39ff7032020-03-09 21:39:44 +01002344
Damien Zammit003d15c2015-11-20 17:17:51 +11002345 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2346
Angel Pons0aeaee72021-03-26 17:57:46 +01002347 mchbar_clrsetbits32(PMCLKRC, 0x01fff37f, 0x10810700);
2348 mchbar_clrsetbits8(PMPXPRC, 7, 1);
2349 mchbar_clrbits8(PMBAK, 1 << 1);
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 Pons0aeaee72021-03-26 17:57:46 +01002366 mchbar_write16(C0C2REG, 0x7a89);
2367 mchbar_write8(SHC2REGII, 0xaa);
2368 mchbar_write16(SHC2REGII + 1, ddr2lut[j][s->selected_timings.CAS - 3][1]);
2369 mchbar_clrsetbits16(SHC2REGI, 0x7fff, ddr2lut[j][s->selected_timings.CAS - 3][0]);
2370 mchbar_clrsetbits16(CLOCKGATINGIII, 0xf000, 0xf000);
2371 mchbar_clrsetbits8(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 */
Angel Pons0aeaee72021-03-26 17:57:46 +01002376 mchbar_write32(C0COREBONUS,
2377 (mchbar_read32(C0COREBONUS) & ~(0xf << 24)) | 1 << 29 | reg32);
Angel Pons39ff7032020-03-09 21:39:44 +01002378
Angel Pons0aeaee72021-03-26 17:57:46 +01002379 mchbar_clrsetbits32(CLOCKGATINGI, 0xf << 20, 0xf << 20);
2380 mchbar_clrsetbits32(CLOCKGATINGII - 1, 0x001ff000, 0xbf << 20);
2381 mchbar_clrsetbits16(SHC3C4REG2, 0x1f7f, 0x0b << 8 | 7 << 4 | 0x0b);
2382 mchbar_write16(SHC3C4REG3, 0x3264);
2383 mchbar_clrsetbits16(SHC3C4REG4, 0x3f3f, 0x14 << 8 | 0x0a);
Angel Pons39ff7032020-03-09 21:39:44 +01002384
Angel Pons0aeaee72021-03-26 17:57:46 +01002385 mchbar_setbits32(C1COREBONUS, 1 << 31 | 1 << 13);
Damien Zammit003d15c2015-11-20 17:17:51 +11002386}
2387
2388static void sdram_programddr(void)
2389{
Angel Pons0aeaee72021-03-26 17:57:46 +01002390 mchbar_clrsetbits16(CLOCKGATINGII, 0x03ff, 0x0100);
2391 mchbar_clrsetbits16(CLOCKGATINGIII, 0x003f, 0x0010);
2392 mchbar_clrsetbits16(CLOCKGATINGI, 0x7000, 0x2000);
Angel Pons39ff7032020-03-09 21:39:44 +01002393
Angel Pons0aeaee72021-03-26 17:57:46 +01002394 mchbar_clrbits8(CSHRPDCTL, 7 << 1);
2395 mchbar_clrbits8(CSHRWRIOMLNS, 3 << 2);
2396 mchbar_clrbits8(C0MISCCTLy(0), 7 << 1);
2397 mchbar_clrbits8(C0MISCCTLy(1), 7 << 1);
2398 mchbar_clrbits8(C0MISCCTLy(2), 7 << 1);
2399 mchbar_clrbits8(C0MISCCTLy(3), 7 << 1);
2400 mchbar_clrbits8(C0MISCCTLy(4), 7 << 1);
2401 mchbar_clrbits8(C0MISCCTLy(5), 7 << 1);
2402 mchbar_clrbits8(C0MISCCTLy(6), 7 << 1);
2403 mchbar_clrbits8(C0MISCCTLy(7), 7 << 1);
2404 mchbar_clrbits8(CSHRWRIOMLNS, 1 << 1);
Angel Pons39ff7032020-03-09 21:39:44 +01002405
Angel Pons0aeaee72021-03-26 17:57:46 +01002406 mchbar_clrbits16(CSHRMISCCTL, 1 << 10);
2407 mchbar_clrbits16(CLOCKGATINGIII, 0x0dc0);
2408 mchbar_clrbits8(C0WRDPYN, 1 << 7);
2409 mchbar_clrbits32(C0COREBONUS, 1 << 22);
2410 mchbar_clrbits16(CLOCKGATINGI, 0x80fc);
2411 mchbar_clrbits16(CLOCKGATINGII, 0x0c00);
Angel Pons39ff7032020-03-09 21:39:44 +01002412
Angel Pons0aeaee72021-03-26 17:57:46 +01002413 mchbar_clrbits8(CSHRPDCTL, 0x0d);
2414 mchbar_clrbits8(C0MISCCTLy(0), 1 << 0);
2415 mchbar_clrbits8(C0MISCCTLy(1), 1 << 0);
2416 mchbar_clrbits8(C0MISCCTLy(2), 1 << 0);
2417 mchbar_clrbits8(C0MISCCTLy(3), 1 << 0);
2418 mchbar_clrbits8(C0MISCCTLy(4), 1 << 0);
2419 mchbar_clrbits8(C0MISCCTLy(5), 1 << 0);
2420 mchbar_clrbits8(C0MISCCTLy(6), 1 << 0);
2421 mchbar_clrbits8(C0MISCCTLy(7), 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +01002422
Angel Pons0aeaee72021-03-26 17:57:46 +01002423 mchbar_clrsetbits32(C0STATRDCTRL, 7 << 20, 3 << 20);
2424 mchbar_clrbits32(C0COREBONUS, 1 << 20);
2425 mchbar_setbits8(C0DYNSLVDLLEN, 0x1e);
2426 mchbar_setbits8(C0DYNSLVDLLEN2, 0x03);
2427 mchbar_clrsetbits32(SHCYCTRKCKEL, 3 << 26, 1 << 26);
2428 mchbar_setbits16(C0STATRDCTRL, 3 << 13);
2429 mchbar_setbits32(C0CKECTRL, 1 << 16);
2430 mchbar_setbits8(C0COREBONUS, 1 << 4);
2431 mchbar_setbits32(CLOCKGATINGI - 1, 0xf << 24);
2432 mchbar_setbits8(CSHWRIOBONUS, 7);
2433 mchbar_setbits8(C0DYNSLVDLLEN, 3 << 6);
2434 mchbar_setbits8(SHC2REGIII, 7);
2435 mchbar_clrsetbits16(SHC2MINTM, ~0, 1 << 7);
2436 mchbar_clrsetbits8(SHC2IDLETM, 0xff, 0x10);
2437 mchbar_setbits16(C0COREBONUS, 0xf << 5);
2438 mchbar_setbits8(CSHWRIOBONUS, 3 << 3);
2439 mchbar_setbits8(CSHRMSTDYNDLLENB, 0x0d);
2440 mchbar_setbits16(SHC3C4REG1, 0x0a3f);
2441 mchbar_setbits8(C0STATRDCTRL, 3);
2442 mchbar_clrsetbits8(C0REFRCTRL2, 0xff, 0x4a);
2443 mchbar_clrbits8(C0COREBONUS + 4, 3 << 5);
2444 mchbar_setbits16(C0DYNSLVDLLEN, 0x0321);
Damien Zammit003d15c2015-11-20 17:17:51 +11002445}
2446
2447static void sdram_programdqdqs(struct sysinfo *s)
2448{
2449 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2450 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2451 u8 repeat, halfclk, feature, reg8, push;
2452 u16 cwb, pimdclk;
2453 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002454 static const u8 txfifotab[8] = {0, 7, 6, 5, 2, 1, 4, 3};
Damien Zammit003d15c2015-11-20 17:17:51 +11002455
2456 tpi = 3000;
2457 dqdqs_out = 4382;
2458 dqdqs_outdelay = 5083;
2459 dqdqs_delay = 4692;
2460 coretomcp = 0;
2461 txdelay = 0;
2462 halfclk = 0;
2463 tmaxunmask = 0;
2464 tmaxpi = 0;
2465 repeat = 2;
2466 feature = 0;
2467 cwb = 0;
2468 pimdclk = 0;
2469 reg32 = 0;
2470 push = 0;
2471 reg8 = 0;
2472
2473 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2474 refclk = 3000 - mdclk;
2475
Angel Pons0aeaee72021-03-26 17:57:46 +01002476 coretomcp = ((mchbar_read8(C0ADDCSCTRL) >> 2) & 0x3) + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002477 coretomcp *= mdclk;
2478
Angel Pons0aeaee72021-03-26 17:57:46 +01002479 reg8 = (mchbar_read8(CSHRFIFOCTL) & 0x0e) >> 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002480
2481 while (repeat) {
2482 txdelay = mdclk * (
Angel Pons0aeaee72021-03-26 17:57:46 +01002483 ((mchbar_read16(C0GNT2LNCH1) >> 8) & 0x7) +
2484 (mchbar_read8(C0WRDATACTRL) & 0xf) +
2485 (mchbar_read8(C0WRDATACTRL + 1) & 0x1)
Damien Zammit003d15c2015-11-20 17:17:51 +11002486 ) +
Angel Pons39ff7032020-03-09 21:39:44 +01002487 txfifotab[reg8]*(mdclk / 2) +
Damien Zammit003d15c2015-11-20 17:17:51 +11002488 coretomcp +
2489 refclk +
2490 cwb;
Angel Pons0aeaee72021-03-26 17:57:46 +01002491 halfclk = (mchbar_read8(C0MISCCTL) >> 1) & 0x1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002492 if (halfclk) {
2493 txdelay -= mdclk / 2;
2494 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2495 } else {
2496 reg32 = dqdqs_outdelay + coretomcp;
2497 }
2498
2499 tmaxunmask = txdelay - mdclk - dqdqs_out;
2500 tmaxpi = tmaxunmask - tpi;
2501
2502 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2503 if (repeat == 2) {
Angel Pons0aeaee72021-03-26 17:57:46 +01002504 mchbar_clrbits32(C0COREBONUS, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +11002505 }
2506 feature = 1;
2507 repeat = 0;
2508 } else {
2509 repeat--;
Angel Pons0aeaee72021-03-26 17:57:46 +01002510 mchbar_setbits32(C0COREBONUS, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +11002511 cwb = 2 * mdclk;
2512 }
2513 }
2514
2515 if (!feature) {
Angel Pons0aeaee72021-03-26 17:57:46 +01002516 mchbar_clrbits8(CLOCKGATINGI, 3);
Damien Zammit003d15c2015-11-20 17:17:51 +11002517 return;
2518 }
Angel Pons0aeaee72021-03-26 17:57:46 +01002519 mchbar_setbits8(CLOCKGATINGI, 3);
2520 mchbar_clrsetbits16(CLOCKGATINGIII, 0xf << 12, pimdclk << 12);
2521 mchbar_clrsetbits8(CSHWRIOBONUSX, 0x77, push << 4 | push);
2522 mchbar_clrsetbits32(C0COREBONUS, 0xf << 24, 3 << 24);
Damien Zammit003d15c2015-11-20 17:17:51 +11002523}
2524
2525/**
2526 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2527 */
2528void sdram_initialize(int boot_path, const u8 *spd_addresses)
2529{
2530 struct sysinfo si;
Angel Pons39ff7032020-03-09 21:39:44 +01002531 const char *boot_str[] = {"Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002532
2533 PRINTK_DEBUG("Setting up RAM controller.\n");
2534
2535 memset(&si, 0, sizeof(si));
2536
2537 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002538 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002539 si.spd_map[0] = spd_addresses[0];
2540 si.spd_map[1] = spd_addresses[1];
2541 si.spd_map[2] = spd_addresses[2];
2542 si.spd_map[3] = spd_addresses[3];
2543
2544 sdram_read_spds(&si);
2545
2546 /* Choose Common Frequency */
2547 sdram_detect_ram_speed(&si);
2548
2549 /* Determine smallest common tRAS, tRP, tRCD, etc */
2550 sdram_detect_smallest_params(&si);
2551
2552 /* Enable HPET */
2553 enable_hpet();
Damien Zammit003d15c2015-11-20 17:17:51 +11002554
Angel Pons0aeaee72021-03-26 17:57:46 +01002555 mchbar_setbits16(CPCTL, 1 << 15);
Damien Zammit003d15c2015-11-20 17:17:51 +11002556
Damien Zammit003d15c2015-11-20 17:17:51 +11002557 sdram_clk_crossing(&si);
2558
2559 sdram_checkreset();
2560 PRINTK_DEBUG("Done checkreset\n");
2561
2562 sdram_clkmode(&si);
2563 PRINTK_DEBUG("Done clkmode\n");
2564
2565 sdram_timings(&si);
2566 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2567
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002568 if (si.boot_path != BOOT_PATH_RESET) {
2569 sdram_dlltiming(&si);
2570 PRINTK_DEBUG("Done dlltiming\n");
2571 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002572
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002573 if (si.boot_path != BOOT_PATH_RESET) {
2574 sdram_rcomp(&si);
2575 PRINTK_DEBUG("Done RCOMP\n");
2576 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002577
2578 sdram_odt(&si);
2579 PRINTK_DEBUG("Done odt\n");
2580
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002581 if (si.boot_path != BOOT_PATH_RESET) {
Angel Pons0aeaee72021-03-26 17:57:46 +01002582 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002583 ;
2584 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002585
2586 sdram_mmap(&si);
2587 PRINTK_DEBUG("Done mmap\n");
2588
Angel Pons39ff7032020-03-09 21:39:44 +01002589 /* Enable DDR IO buffer */
Angel Pons0aeaee72021-03-26 17:57:46 +01002590 mchbar_clrsetbits8(C0IOBUFACTCTL, 0x3f, 0x08);
2591 mchbar_setbits8(C0RSTCTL, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002592
2593 sdram_rcompupdate(&si);
2594 PRINTK_DEBUG("Done RCOMP update\n");
2595
Angel Pons0aeaee72021-03-26 17:57:46 +01002596 mchbar_setbits8(HIT4, 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002597
2598 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons0aeaee72021-03-26 17:57:46 +01002599 mchbar_setbits32(C0CKECTRL, 1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002600
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002601 sdram_jedecinit(&si);
2602 PRINTK_DEBUG("Done MRS\n");
2603 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002604
2605 sdram_misc(&si);
2606 PRINTK_DEBUG("Done misc\n");
2607
2608 sdram_zqcl(&si);
2609 PRINTK_DEBUG("Done zqcl\n");
2610
2611 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons0aeaee72021-03-26 17:57:46 +01002612 mchbar_setbits32(C0REFRCTRL2, 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002613 }
2614
2615 sdram_dradrb(&si);
2616 PRINTK_DEBUG("Done dradrb\n");
2617
2618 sdram_rcven(&si);
2619 PRINTK_DEBUG("Done rcven\n");
2620
2621 sdram_new_trd(&si);
2622 PRINTK_DEBUG("Done tRD\n");
2623
2624 sdram_mmap_regs(&si);
2625 PRINTK_DEBUG("Done mmap regs\n");
2626
2627 sdram_enhancedmode(&si);
2628 PRINTK_DEBUG("Done enhanced mode\n");
2629
2630 sdram_powersettings(&si);
2631 PRINTK_DEBUG("Done power settings\n");
2632
2633 sdram_programddr();
2634 PRINTK_DEBUG("Done programming ddr\n");
2635
2636 sdram_programdqdqs(&si);
2637 PRINTK_DEBUG("Done programming dqdqs\n");
2638
2639 sdram_periodic_rcomp();
2640 PRINTK_DEBUG("Done periodic RCOMP\n");
2641
2642 /* Set init done */
Angel Pons0aeaee72021-03-26 17:57:46 +01002643 mchbar_setbits32(C0REFRCTRL2, 1 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002644
2645 /* Tell ICH7 that we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002646 pci_and_config8(PCI_DEV(0, 0x1f, 0), 0xa2, (u8)~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11002647
2648 /* Tell northbridge we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002649 pci_or_config8(HOST_BRIDGE, 0xf4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002650
2651 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2652}