blob: dbc373d1fb87a88b66af9d2b23a392cc4a30373e [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) {
Elyes Haouas3a54f4a2022-12-05 18:49:40 +0100152 // NC/{8,16}SS
153 s->dimm_config[chan] = 1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100154 } else {
155 // NC/DS
156 if (s->dimms[(chan>>1) + 1].width == 0) {
157 // NC/8DS
158 s->dimm_config[chan] = 5;
159 } else {
160 // NC/16DS
161 s->dimm_config[chan] = 2;
162 }
163 }
164 } else if (s->dimms[chan>>1].sides == 1) {
165 // SS
166 if (s->dimms[(chan>>1) + 1].sides == 0) {
Elyes Haouas3a54f4a2022-12-05 18:49:40 +0100167 // {8,16}SS/NC
168 s->dimm_config[chan] = 1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100169 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
170 // SS/SS
171 if (s->dimms[chan>>1].width == 0) {
172 if (s->dimms[(chan>>1) + 1].width == 0) {
173 // 8SS/8SS
174 s->dimm_config[chan] = 3;
175 } else {
176 // 8SS/16SS
177 die("Mixed Not supported\n");
178 }
179 } else {
180 if (s->dimms[(chan>>1) + 1].width == 0) {
181 // 16SS/8SS
182 die("Mixed Not supported\n");
183 } else {
184 // 16SS/16SS
185 s->dimm_config[chan] = 3;
186 }
187 }
188 } else {
Elyes Haouas3a54f4a2022-12-05 18:49:40 +0100189 // {8,16}SS/8DS
190 die("Mixed Not supported\n");
Damien Zammit003d15c2015-11-20 17:17:51 +1100191 }
192 } else {
193 // DS
194 if (s->dimms[(chan>>1) + 1].sides == 0) {
195 // DS/NC
196 if (s->dimms[chan>>1].width == 0) {
197 // 8DS/NC
198 s->dimm_config[chan] = 5;
199 } else {
200 s->dimm_config[chan] = 4;
201 }
202 } else if (s->dimms[(chan>>1) + 1].sides == 1) {
Elyes Haouas3a54f4a2022-12-05 18:49:40 +0100203 // 8DS/{8,16}SS
Damien Zammit003d15c2015-11-20 17:17:51 +1100204 if (s->dimms[chan>>1].width == 0) {
Elyes Haouas3a54f4a2022-12-05 18:49:40 +0100205 die("Mixed Not supported\n");
Damien Zammit003d15c2015-11-20 17:17:51 +1100206 } else {
207 if (s->dimms[(chan>>1) + 1].width == 0) {
208 die("Mixed Not supported\n");
209 } else {
210 // 16DS/16DS
211 s->dimm_config[chan] = 4;
212 }
213 }
214 } else {
215 // DS/DS
216 if (s->dimms[chan>>1].width == 0 && s->dimms[(chan>>1)+1].width == 0) {
217 // 8DS/8DS
218 s->dimm_config[chan] = 6;
219 }
220 }
221 }
222}
223
224static void sdram_read_spds(struct sysinfo *s)
225{
Arthur Heymans1f6369e2018-08-20 11:27:41 +0200226 u8 i, chan;
Damien Zammit003d15c2015-11-20 17:17:51 +1100227 s->dt0mode = 0;
228 FOR_EACH_DIMM(i) {
Kyösti Mälkkic01a5052019-01-30 09:39:23 +0200229 if (i2c_eeprom_read(s->spd_map[i], 0, 64, s->dimms[i].spd_data) != 64)
Arthur Heymans1f6369e2018-08-20 11:27:41 +0200230 s->dimms[i].card_type = 0;
231
232 s->dimms[i].card_type = s->dimms[i].spd_data[62] & 0x1f;
Damien Zammit003d15c2015-11-20 17:17:51 +1100233 hexdump(s->dimms[i].spd_data, 64);
234 }
235
236 s->spd_type = 0;
237 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
238 switch (s->dimms[i].spd_data[2]) {
239 case 0x8:
240 s->spd_type = DDR2;
241 break;
242 case 0xb:
243 default:
244 die("DIMM type mismatch\n");
245 break;
246 }
247 }
248
249 int err = 1;
250 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Arthur Heymans097d7532017-04-17 10:14:32 +0200251 err = decode_spd(&s->dimms[i], i);
Damien Zammit003d15c2015-11-20 17:17:51 +1100252 s->dt0mode |= (s->dimms[i].spd_data[49] & 0x2) >> 1;
253 }
254 if (err) {
255 die("No memory dimms, halt\n");
256 }
257
258 FOR_EACH_POPULATED_CHANNEL(s->dimms, chan) {
259 find_ramconfig(s, chan);
Angel Pons39ff7032020-03-09 21:39:44 +0100260 PRINTK_DEBUG(" Config[CH%d] : %d\n", chan, s->dimm_config[chan]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100261 }
262}
263
Julius Wernercd49cce2019-03-05 16:53:33 -0800264#if CONFIG(DEBUG_RAM_SETUP)
Damien Zammit003d15c2015-11-20 17:17:51 +1100265static u32 fsb_reg_to_mhz(u32 speed)
266{
267 return (speed * 133) + 667;
268}
269
270static u32 ddr_reg_to_mhz(u32 speed)
271{
Angel Pons39ff7032020-03-09 21:39:44 +0100272 return (speed == 0) ? 667 : (speed == 1) ? 800 : 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100273}
274#endif
275
Jacob Garberb70c7762019-03-25 18:20:06 -0600276// Return the position of the least significant set bit, 0-indexed.
277// 0 does not have a lsb, so return -1 for error.
278static int lsbpos(u8 val)
Damien Zammit003d15c2015-11-20 17:17:51 +1100279{
Jacob Garberb70c7762019-03-25 18:20:06 -0600280 for (int i = 0; i < 8; i++)
281 if (val & (1 << i))
282 return i;
283 return -1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100284}
285
Jacob Garberb70c7762019-03-25 18:20:06 -0600286// Return the position of the most significant set bit, 0-indexed.
287// 0 does not have a msb, so return -1 for error.
288static int msbpos(u8 val)
Damien Zammit003d15c2015-11-20 17:17:51 +1100289{
Jacob Garberb70c7762019-03-25 18:20:06 -0600290 for (int i = 7; i >= 0; i--)
291 if (val & (1 << i))
292 return i;
293 return -1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100294}
295
296static void sdram_detect_smallest_params(struct sysinfo *s)
297{
Arthur Heymans6bf13012017-06-10 12:03:27 +0200298 static const u16 mult[6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100299 3000, // 667
300 2500, // 800
301 };
302
303 u8 i;
Damien Zammit003d15c2015-11-20 17:17:51 +1100304 u32 maxtras = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100305 u32 maxtrp = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100306 u32 maxtrcd = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100307 u32 maxtwr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100308 u32 maxtrfc = 0;
309 u32 maxtwtr = 0;
310 u32 maxtrrd = 0;
311 u32 maxtrtp = 0;
312
313 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Angel Pons39ff7032020-03-09 21:39:44 +0100314 maxtras = MAX(maxtras, (s->dimms[i].spd_data[30] * 1000));
315 maxtrp = MAX(maxtrp, (s->dimms[i].spd_data[27] * 1000) >> 2);
Elyes HAOUASf97c1c92019-12-03 18:22:06 +0100316 maxtrcd = MAX(maxtrcd, (s->dimms[i].spd_data[29] * 1000) >> 2);
Angel Pons39ff7032020-03-09 21:39:44 +0100317 maxtwr = MAX(maxtwr, (s->dimms[i].spd_data[36] * 1000) >> 2);
318 maxtrfc = MAX(maxtrfc, (s->dimms[i].spd_data[42] * 1000) +
319 (s->dimms[i].spd_data[40] & 0xf));
Elyes HAOUASf97c1c92019-12-03 18:22:06 +0100320 maxtwtr = MAX(maxtwtr, (s->dimms[i].spd_data[37] * 1000) >> 2);
321 maxtrrd = MAX(maxtrrd, (s->dimms[i].spd_data[28] * 1000) >> 2);
322 maxtrtp = MAX(maxtrtp, (s->dimms[i].spd_data[38] * 1000) >> 2);
Damien Zammit003d15c2015-11-20 17:17:51 +1100323 }
Arthur Heymans12a4e982017-04-28 20:53:05 +0200324 /*
Angel Pons39ff7032020-03-09 21:39:44 +0100325 * TODO: on DDR3 there might be some minimal required values for some
Arthur Heymans12a4e982017-04-28 20:53:05 +0200326 * Timings: MIN_TRAS = 9, MIN_TRP = 3, MIN_TRCD = 3, MIN_TWR = 3,
327 * MIN_TWTR = 4, MIN_TRRD = 2, MIN_TRTP = 4
328 */
329 s->selected_timings.tRAS = MIN(24, DIV_ROUND_UP(maxtras,
330 mult[s->selected_timings.mem_clock]));
331 s->selected_timings.tRP = MIN(10, DIV_ROUND_UP(maxtrp,
332 mult[s->selected_timings.mem_clock]));
333 s->selected_timings.tRCD = MIN(10, DIV_ROUND_UP(maxtrcd,
334 mult[s->selected_timings.mem_clock]));
335 s->selected_timings.tWR = MIN(15, DIV_ROUND_UP(maxtwr,
336 mult[s->selected_timings.mem_clock]));
337 /* Needs to be even */
338 s->selected_timings.tRFC = 0xfe & (MIN(78, DIV_ROUND_UP(maxtrfc,
339 mult[s->selected_timings.mem_clock])) + 1);
340 s->selected_timings.tWTR = MIN(15, DIV_ROUND_UP(maxtwtr,
341 mult[s->selected_timings.mem_clock]));
342 s->selected_timings.tRRD = MIN(15, DIV_ROUND_UP(maxtrrd,
343 mult[s->selected_timings.mem_clock]));
Arthur Heymans5bb27b72017-08-26 21:24:21 +0200344 s->selected_timings.tRTP = MIN(15, DIV_ROUND_UP(maxtrtp,
Arthur Heymans12a4e982017-04-28 20:53:05 +0200345 mult[s->selected_timings.mem_clock]));
Damien Zammit003d15c2015-11-20 17:17:51 +1100346
347 PRINTK_DEBUG("Selected timings:\n");
348 PRINTK_DEBUG("\tFSB: %dMHz\n", fsb_reg_to_mhz(s->selected_timings.fsb_clock));
349 PRINTK_DEBUG("\tDDR: %dMHz\n", ddr_reg_to_mhz(s->selected_timings.mem_clock));
350
351 PRINTK_DEBUG("\tCAS: %d\n", s->selected_timings.CAS);
352 PRINTK_DEBUG("\ttRAS: %d\n", s->selected_timings.tRAS);
353 PRINTK_DEBUG("\ttRP: %d\n", s->selected_timings.tRP);
354 PRINTK_DEBUG("\ttRCD: %d\n", s->selected_timings.tRCD);
355 PRINTK_DEBUG("\ttWR: %d\n", s->selected_timings.tWR);
356 PRINTK_DEBUG("\ttRFC: %d\n", s->selected_timings.tRFC);
357 PRINTK_DEBUG("\ttWTR: %d\n", s->selected_timings.tWTR);
358 PRINTK_DEBUG("\ttRRD: %d\n", s->selected_timings.tRRD);
359 PRINTK_DEBUG("\ttRTP: %d\n", s->selected_timings.tRTP);
360}
361
362static void sdram_detect_ram_speed(struct sysinfo *s)
363{
364 u8 cas, reg8;
365 u32 reg32;
366 u32 freq = 0;
367 u32 fsb = 0;
368 u8 i;
369 u8 commoncas = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100370 u8 highcas = 0;
371 u8 lowcas = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100372
373 // Core frequency
Angel Pons39ff7032020-03-09 21:39:44 +0100374 fsb = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0x70) >> 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100375 if (fsb) {
376 fsb = 5 - fsb;
377 } else {
378 fsb = FSB_CLOCK_800MHz;
379 }
380
381 // DDR frequency
Angel Pons39ff7032020-03-09 21:39:44 +0100382 freq = (pci_read_config8(HOST_BRIDGE, 0xe3) & 0x80) >> 7;
383 freq |= (pci_read_config8(HOST_BRIDGE, 0xe4) & 0x03) << 1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100384 if (freq) {
385 freq = 6 - freq;
386 } else {
387 freq = MEM_CLOCK_800MHz;
388 }
389
390 // Detect a common CAS latency
391 commoncas = 0xff;
392 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
393 commoncas &= s->dimms[i].spd_data[18];
394 }
395 if (commoncas == 0) {
396 die("No common CAS among dimms\n");
397 }
398
Jacob Garberb70c7762019-03-25 18:20:06 -0600399 // commoncas is nonzero, so these calls will not error
400 u8 msbp = (u8)msbpos(commoncas);
401 u8 lsbp = (u8)lsbpos(commoncas);
402
Damien Zammit003d15c2015-11-20 17:17:51 +1100403 // Start with fastest common CAS
404 cas = 0;
Jacob Garberb70c7762019-03-25 18:20:06 -0600405 highcas = msbp;
Elyes HAOUASf97c1c92019-12-03 18:22:06 +0100406 lowcas = MAX(lsbp, 5);
Damien Zammit003d15c2015-11-20 17:17:51 +1100407
408 while (cas == 0 && highcas >= lowcas) {
409 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
410 switch (freq) {
411 case MEM_CLOCK_800MHz:
Angel Pons39ff7032020-03-09 21:39:44 +0100412 if ((s->dimms[i].spd_data[9] > 0x25) ||
Damien Zammit003d15c2015-11-20 17:17:51 +1100413 (s->dimms[i].spd_data[10] > 0x40)) {
414 // CAS too fast, lower it
415 highcas--;
416 break;
417 } else {
418 cas = highcas;
419 }
420 break;
421 case MEM_CLOCK_667MHz:
422 default:
Angel Pons39ff7032020-03-09 21:39:44 +0100423 if ((s->dimms[i].spd_data[9] > 0x30) ||
Damien Zammit003d15c2015-11-20 17:17:51 +1100424 (s->dimms[i].spd_data[10] > 0x45)) {
425 // CAS too fast, lower it
426 highcas--;
427 break;
428 } else {
429 cas = highcas;
430 }
431 break;
432 }
433 }
434 }
435 if (highcas < lowcas) {
436 // Timings not supported by MCH, lower the frequency
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200437 if (freq == MEM_CLOCK_800MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +1100438 freq--;
439 PRINTK_DEBUG("Run DDR clock speed reduced due to timings\n");
440 } else {
441 die("Timings not supported by MCH\n");
442 }
443 cas = 0;
Jacob Garberb70c7762019-03-25 18:20:06 -0600444 highcas = msbp;
445 lowcas = lsbp;
Damien Zammit003d15c2015-11-20 17:17:51 +1100446 while (cas == 0 && highcas >= lowcas) {
447 FOR_EACH_POPULATED_DIMM(s->dimms, i) {
Angel Pons39ff7032020-03-09 21:39:44 +0100448 if ((s->dimms[i].spd_data[9] > 0x30) ||
Jacob Garber78107932019-06-11 12:45:51 -0600449 (s->dimms[i].spd_data[10] > 0x45)) {
450 // CAS too fast, lower it
451 highcas--;
452 } else {
453 cas = highcas;
Damien Zammit003d15c2015-11-20 17:17:51 +1100454 }
455 }
456 }
457 if (cas == 0) {
458 die("Unsupported dimms\n");
459 }
460 }
461
462 s->selected_timings.CAS = cas;
463 s->selected_timings.mem_clock = freq;
464 s->selected_timings.fsb_clock = fsb;
465
Angel Pons39ff7032020-03-09 21:39:44 +0100466 PRINTK_DEBUG("Drive Memory at %dMHz with CAS = %d clocks\n",
467 ddr_reg_to_mhz(s->selected_timings.mem_clock), s->selected_timings.CAS);
Damien Zammit003d15c2015-11-20 17:17:51 +1100468
469 // Set memory frequency
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200470 if (s->boot_path == BOOT_PATH_RESET)
471 return;
Angel Pons39ff7032020-03-09 21:39:44 +0100472
Angel Pons0aeaee72021-03-26 17:57:46 +0100473 mchbar_setbits32(PMSTS, 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +0100474
Angel Pons0aeaee72021-03-26 17:57:46 +0100475 reg32 = (mchbar_read32(CLKCFG) & ~0x70) | (1 << 10);
Damien Zammit003d15c2015-11-20 17:17:51 +1100476 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
477 reg8 = 3;
478 } else {
479 reg8 = 2;
480 }
481 reg32 |= reg8 << 4;
Angel Pons0aeaee72021-03-26 17:57:46 +0100482 mchbar_write32(CLKCFG, reg32);
Angel Pons39ff7032020-03-09 21:39:44 +0100483
Angel Pons0aeaee72021-03-26 17:57:46 +0100484 s->selected_timings.mem_clock = ((mchbar_read32(CLKCFG) >> 4) & 0x7) - 2;
Damien Zammit003d15c2015-11-20 17:17:51 +1100485 if (s->selected_timings.mem_clock == MEM_CLOCK_800MHz) {
486 PRINTK_DEBUG("MCH validated at 800MHz\n");
487 s->nodll = 0;
488 s->maxpi = 63;
489 s->pioffset = 0;
490 } else if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
491 PRINTK_DEBUG("MCH validated at 667MHz\n");
492 s->nodll = 1;
493 s->maxpi = 15;
494 s->pioffset = 1;
495 } else {
496 PRINTK_DEBUG("MCH set to unknown (%02x)\n",
Elyes Haouas3a998072022-11-18 15:11:02 +0100497 (uint8_t)s->selected_timings.mem_clock & 0xff);
Damien Zammit003d15c2015-11-20 17:17:51 +1100498 }
499}
500
Damien Zammit003d15c2015-11-20 17:17:51 +1100501static void sdram_clk_crossing(struct sysinfo *s)
502{
Angel Pons39ff7032020-03-09 21:39:44 +0100503 u8 ddr_freq, fsb_freq;
Arthur Heymans6bf13012017-06-10 12:03:27 +0200504 static const u32 clkcross[2][2][4] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100505 {
Angel Pons94eea6f2021-02-06 15:03:48 +0100506 {0xffffffff, 0x05030305, 0x0000ffff, 0x00000000}, /* FSB = 667, DDR = 667 */
507 {0x1f1f1f1f, 0x2a1f1fa5, 0x00000000, 0x05000002}, /* FSB = 667, DDR = 800 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100508 },
509 {
Angel Pons94eea6f2021-02-06 15:03:48 +0100510 {0x1f1f1f1f, 0x0d07070b, 0x00000000, 0x00000000}, /* FSB = 800, DDR = 667 */
511 {0xffffffff, 0x05030305, 0x0000ffff, 0x00000000}, /* FSB = 800, DDR = 800 */
Angel Pons39ff7032020-03-09 21:39:44 +0100512 },
Damien Zammit003d15c2015-11-20 17:17:51 +1100513 };
Damien Zammit003d15c2015-11-20 17:17:51 +1100514
Angel Pons39ff7032020-03-09 21:39:44 +0100515 ddr_freq = s->selected_timings.mem_clock;
516 fsb_freq = s->selected_timings.fsb_clock;
Damien Zammit003d15c2015-11-20 17:17:51 +1100517
Angel Pons0aeaee72021-03-26 17:57:46 +0100518 mchbar_write32(HMCCMP, clkcross[fsb_freq][ddr_freq][0]);
519 mchbar_write32(HMDCMP, clkcross[fsb_freq][ddr_freq][1]);
520 mchbar_write32(HMBYPCP, clkcross[fsb_freq][ddr_freq][2]);
521 mchbar_write32(HMCCPEXT, 0);
522 mchbar_write32(HMDCPEXT, clkcross[fsb_freq][ddr_freq][3]);
Angel Pons39ff7032020-03-09 21:39:44 +0100523
Angel Pons0aeaee72021-03-26 17:57:46 +0100524 mchbar_setbits32(HMCCMC, 1 << 7);
Angel Pons39ff7032020-03-09 21:39:44 +0100525
526 if ((fsb_freq == 0) && (ddr_freq == 1)) {
Angel Pons0aeaee72021-03-26 17:57:46 +0100527 mchbar_write8(CLKXSSH2MCBYPPHAS, 0);
528 mchbar_write32(CLKXSSH2MD, 0);
529 mchbar_write32(CLKXSSH2MD + 4, 0);
Damien Zammit003d15c2015-11-20 17:17:51 +1100530 }
531
Arthur Heymans6bf13012017-06-10 12:03:27 +0200532 static const u32 clkcross2[2][2][8] = {
Damien Zammit003d15c2015-11-20 17:17:51 +1100533 {
Angel Pons39ff7032020-03-09 21:39:44 +0100534 { // FSB = 667, DDR = 667
535 0x00000000, 0x08010204, 0x00000000, 0x08010204,
536 0x00000000, 0x00000000, 0x00000000, 0x04080102,
537 },
538 { // FSB = 667, DDR = 800
539 0x04080000, 0x10010002, 0x10000000, 0x20010208,
540 0x00000000, 0x00000004, 0x02040000, 0x08100102,
541 },
Damien Zammit003d15c2015-11-20 17:17:51 +1100542 },
543 {
Angel Pons39ff7032020-03-09 21:39:44 +0100544 { // FSB = 800, DDR = 667
545 0x10000000, 0x20010208, 0x04080000, 0x10010002,
546 0x00000000, 0x00000000, 0x08000000, 0x10200204,
547 },
548 { // FSB = 800, DDR = 800
549 0x00000000, 0x08010204, 0x00000000, 0x08010204,
550 0x00000000, 0x00000000, 0x00000000, 0x04080102,
551 },
552 },
Damien Zammit003d15c2015-11-20 17:17:51 +1100553 };
554
Angel Pons0aeaee72021-03-26 17:57:46 +0100555 mchbar_write32(CLKXSSH2MCBYP, clkcross2[fsb_freq][ddr_freq][0]);
556 mchbar_write32(CLKXSSH2MCRDQ, clkcross2[fsb_freq][ddr_freq][0]);
557 mchbar_write32(CLKXSSH2MCRDCST, clkcross2[fsb_freq][ddr_freq][0]);
558 mchbar_write32(CLKXSSH2MCBYP + 4, clkcross2[fsb_freq][ddr_freq][1]);
559 mchbar_write32(CLKXSSH2MCRDQ + 4, clkcross2[fsb_freq][ddr_freq][1]);
560 mchbar_write32(CLKXSSH2MCRDCST + 4, clkcross2[fsb_freq][ddr_freq][1]);
561 mchbar_write32(CLKXSSMC2H, clkcross2[fsb_freq][ddr_freq][2]);
562 mchbar_write32(CLKXSSMC2H + 4, clkcross2[fsb_freq][ddr_freq][3]);
563 mchbar_write32(CLKXSSMC2HALT, clkcross2[fsb_freq][ddr_freq][4]);
564 mchbar_write32(CLKXSSMC2HALT + 4, clkcross2[fsb_freq][ddr_freq][5]);
565 mchbar_write32(CLKXSSH2X2MD, clkcross2[fsb_freq][ddr_freq][6]);
566 mchbar_write32(CLKXSSH2X2MD + 4, clkcross2[fsb_freq][ddr_freq][7]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100567}
568
569static void sdram_clkmode(struct sysinfo *s)
570{
Angel Pons39ff7032020-03-09 21:39:44 +0100571 u8 ddr_freq;
572 u16 mpll_ctl;
Damien Zammit003d15c2015-11-20 17:17:51 +1100573
Angel Pons0aeaee72021-03-26 17:57:46 +0100574 mchbar_clrbits16(CSHRMISCCTL1, 1 << 8);
575 mchbar_clrbits8(CSHRMISCCTL1, 0x3f);
Damien Zammit003d15c2015-11-20 17:17:51 +1100576
577 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +0100578 ddr_freq = 0;
579 mpll_ctl = 1;
Damien Zammit003d15c2015-11-20 17:17:51 +1100580 } else {
Angel Pons39ff7032020-03-09 21:39:44 +0100581 ddr_freq = 1;
582 mpll_ctl = (1 << 8) | (1 << 5);
Damien Zammit003d15c2015-11-20 17:17:51 +1100583 }
Arthur Heymans00fd3ff2017-04-17 17:50:40 +0200584 if (s->boot_path != BOOT_PATH_RESET)
Angel Pons0aeaee72021-03-26 17:57:46 +0100585 mchbar_clrsetbits16(MPLLCTL, 0x033f, mpll_ctl);
Damien Zammit003d15c2015-11-20 17:17:51 +1100586
Angel Pons0aeaee72021-03-26 17:57:46 +0100587 mchbar_write32(C0GNT2LNCH1, 0x58001117);
588 mchbar_setbits32(C0STATRDCTRL, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +1100589
590 const u32 cas_to_reg[2][4] = {
Angel Pons94eea6f2021-02-06 15:03:48 +0100591 {0x00000000, 0x00030100, 0x0c240201, 0x00000000}, /* DDR = 667 */
592 {0x00000000, 0x00030100, 0x0c240201, 0x10450302} /* DDR = 800 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100593 };
594
Angel Pons0aeaee72021-03-26 17:57:46 +0100595 mchbar_write32(C0GNT2LNCH2, cas_to_reg[ddr_freq][s->selected_timings.CAS - 3]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100596}
597
598static void sdram_timings(struct sysinfo *s)
599{
600 u8 i, j, ch, r, ta1, ta2, ta3, ta4, trp, bank, page, flag;
601 u8 reg8, wl;
602 u16 reg16;
603 u32 reg32, reg2;
Damien Zammit003d15c2015-11-20 17:17:51 +1100604
Angel Pons39ff7032020-03-09 21:39:44 +0100605 static const u8 pagetab[2][2] = {
606 {0x0e, 0x12},
607 {0x10, 0x14},
608 };
609
610 /* Only consider DDR2 */
611 wl = s->selected_timings.CAS - 1;
612 ta1 = ta2 = 6;
613 ta3 = s->selected_timings.CAS;
614 ta4 = 8;
Damien Zammit003d15c2015-11-20 17:17:51 +1100615 s->selected_timings.tRFC = (s->selected_timings.tRFC + 1) & 0xfe;
Angel Pons39ff7032020-03-09 21:39:44 +0100616 trp = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100617 bank = 1;
618 page = 0;
619
Angel Pons0aeaee72021-03-26 17:57:46 +0100620 mchbar_write8(C0LATCTRL, (wl - 3) << 4 | (s->selected_timings.CAS - 3));
Damien Zammit003d15c2015-11-20 17:17:51 +1100621
622 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
623 i = ch << 1;
624 if (s->dimms[i].banks == 1) {
625 trp = 1;
626 bank = 0;
627 }
628 if (s->dimms[i].page_size == 2048) {
629 page = 1;
630 }
631 }
632 PRINTK_DEBUG("trp=%d bank=%d page=%d\n",trp, bank, page);
633
634 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
635 flag = 0;
636 } else {
637 flag = 1;
638 }
639
Angel Pons0aeaee72021-03-26 17:57:46 +0100640 mchbar_setbits8(C0PVCFG, 3);
641 mchbar_write16(C0CYCTRKPCHG, (wl + 4 + s->selected_timings.tWR) << 6 |
642 (2 + MAX(s->selected_timings.tRTP, 2)) << 2 | 1);
Angel Pons39ff7032020-03-09 21:39:44 +0100643
Damien Zammit003d15c2015-11-20 17:17:51 +1100644 reg32 = (bank << 21) | (s->selected_timings.tRRD << 17) |
Angel Pons39ff7032020-03-09 21:39:44 +0100645 (s->selected_timings.tRP << 13) | ((s->selected_timings.tRP + trp) << 9) |
646 s->selected_timings.tRFC;
647
Damien Zammit003d15c2015-11-20 17:17:51 +1100648 if (bank == 0) {
649 reg32 |= (pagetab[flag][page] << 22);
650 }
Angel Pons39ff7032020-03-09 21:39:44 +0100651 /* FIXME: Why not do a single dword write? */
Angel Pons0aeaee72021-03-26 17:57:46 +0100652 mchbar_write16(C0CYCTRKACT + 0, (u16)(reg32));
653 mchbar_write16(C0CYCTRKACT + 2, (u16)(reg32 >> 16));
Damien Zammit003d15c2015-11-20 17:17:51 +1100654
Angel Pons39ff7032020-03-09 21:39:44 +0100655 /* FIXME: Only applies to DDR2 */
Angel Pons0aeaee72021-03-26 17:57:46 +0100656 reg16 = (mchbar_read16(C0CYCTRKACT + 2) & 0x0fc0) >> 6;
657 mchbar_clrsetbits16(SHCYCTRKCKEL, 0x3f << 7, reg16 << 7);
Damien Zammit003d15c2015-11-20 17:17:51 +1100658
659 reg16 = (s->selected_timings.tRCD << 12) | (4 << 8) | (ta2 << 4) | ta4;
Angel Pons0aeaee72021-03-26 17:57:46 +0100660 mchbar_write16(C0CYCTRKWR, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100661
Angel Pons39ff7032020-03-09 21:39:44 +0100662 reg32 = (s->selected_timings.tRCD << 17) | ((wl + 4 + s->selected_timings.tWTR) << 12) |
Damien Zammit003d15c2015-11-20 17:17:51 +1100663 (ta3 << 8) | (4 << 4) | ta1;
Angel Pons0aeaee72021-03-26 17:57:46 +0100664 mchbar_write32(C0CYCTRKRD, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100665
Angel Pons39ff7032020-03-09 21:39:44 +0100666 reg16 = ((s->selected_timings.tRP + trp) << 9) | s->selected_timings.tRFC;
Damien Zammit003d15c2015-11-20 17:17:51 +1100667
Angel Pons39ff7032020-03-09 21:39:44 +0100668 /* FIXME: Why not do a single word write? */
Angel Pons0aeaee72021-03-26 17:57:46 +0100669 mchbar_write8(C0CYCTRKREFR + 0, (u8)(reg16));
670 mchbar_write8(C0CYCTRKREFR + 1, (u8)(reg16 >> 8));
Damien Zammit003d15c2015-11-20 17:17:51 +1100671
Angel Pons0aeaee72021-03-26 17:57:46 +0100672 mchbar_clrsetbits16(C0CKECTRL, 0x1ff << 1, 100 << 1);
673 mchbar_clrsetbits8(C0CYCTRKPCHG2, 0x3f, s->selected_timings.tRAS);
674 mchbar_write16(C0ARBCTRL, 0x2310);
675 mchbar_clrsetbits8(C0ADDCSCTRL, 0x1f, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +1100676
677 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
678 reg32 = 3000;
679 } else {
680 reg32 = 2500;
681 }
682 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
683 reg2 = 6000;
684 } else {
685 reg2 = 5000;
686 }
Angel Pons39ff7032020-03-09 21:39:44 +0100687 reg16 = (u16)((((s->selected_timings.CAS + 7) * (reg32)) / reg2) << 8);
Angel Pons0aeaee72021-03-26 17:57:46 +0100688 mchbar_clrsetbits16(C0STATRDCTRL, 0x1f << 8, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100689
690 flag = 0;
691 if (wl > 2) {
692 flag = 1;
693 }
Elyes Haouas3a998072022-11-18 15:11:02 +0100694 reg16 = (u8)(wl - 1 - flag);
Damien Zammit003d15c2015-11-20 17:17:51 +1100695 reg16 |= reg16 << 4;
696 reg16 |= flag << 8;
Angel Pons0aeaee72021-03-26 17:57:46 +0100697 mchbar_clrsetbits16(C0WRDATACTRL, 0x1ff, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100698
Angel Pons0aeaee72021-03-26 17:57:46 +0100699 mchbar_write16(C0RDQCTRL, 0x1585);
700 mchbar_clrbits8(C0PWLRCTRL, 0x1f);
Angel Pons39ff7032020-03-09 21:39:44 +0100701
702 /* rdmodwr_window[5..0] = CL+4+5 265[13..8] (264[21..16]) */
Angel Pons0aeaee72021-03-26 17:57:46 +0100703 mchbar_clrsetbits16(C0PWLRCTRL, 0x3f << 8, (s->selected_timings.CAS + 9) << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100704
705 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +0100706 reg16 = 0x0514;
707 reg32 = 0x0a28;
Damien Zammit003d15c2015-11-20 17:17:51 +1100708 } else {
Angel Pons39ff7032020-03-09 21:39:44 +0100709 reg16 = 0x0618;
710 reg32 = 0x0c30;
Damien Zammit003d15c2015-11-20 17:17:51 +1100711 }
Angel Pons0aeaee72021-03-26 17:57:46 +0100712 mchbar_clrsetbits32(C0REFRCTRL2, 0xfffff << 8, 0x3f << 22 | reg32 << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100713
Angel Pons39ff7032020-03-09 21:39:44 +0100714 /* FIXME: Is this weird access necessary? Reference code does it */
Angel Pons0aeaee72021-03-26 17:57:46 +0100715 mchbar_write8(C0REFRCTRL + 3, 0);
716 mchbar_clrsetbits16(C0REFCTRL, 0x3fff, reg16);
Angel Pons39ff7032020-03-09 21:39:44 +0100717
718 /* NPUT Static Mode */
Angel Pons0aeaee72021-03-26 17:57:46 +0100719 mchbar_setbits8(C0DYNRDCTRL, 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +0100720
Angel Pons0aeaee72021-03-26 17:57:46 +0100721 mchbar_clrsetbits32(C0STATRDCTRL, 0x7f << 24, 0xb << 25);
Damien Zammit003d15c2015-11-20 17:17:51 +1100722 i = s->selected_timings.mem_clock;
723 j = s->selected_timings.fsb_clock;
724 if (i > j) {
Angel Pons0aeaee72021-03-26 17:57:46 +0100725 mchbar_setbits32(C0STATRDCTRL, 1 << 24);
Damien Zammit003d15c2015-11-20 17:17:51 +1100726 }
727
Angel Pons0aeaee72021-03-26 17:57:46 +0100728 mchbar_clrbits8(C0RDFIFOCTRL, 3);
729 mchbar_clrsetbits16(C0WRDATACTRL, 0x1f << 10, (wl + 10) << 10);
730 mchbar_clrsetbits32(C0CKECTRL, 7 << 24 | 7 << 17, 3 << 24 | 3 << 17);
Damien Zammit003d15c2015-11-20 17:17:51 +1100731 reg16 = 0x15 << 6;
732 reg16 |= 0x1f;
733 reg16 |= (0x6 << 12);
Angel Pons0aeaee72021-03-26 17:57:46 +0100734 mchbar_clrsetbits16(C0REFRCTRL + 4, 0x7fff, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +1100735
Angel Pons39ff7032020-03-09 21:39:44 +0100736 reg32 = (0x6 << 27) | (1 << 25); /* FIXME: For DDR3, set BIT26 as well */
Angel Pons0aeaee72021-03-26 17:57:46 +0100737 mchbar_clrsetbits32(C0REFRCTRL2, 3 << 28, reg32 << 8);
738 mchbar_clrsetbits8(C0REFRCTRL + 3, 0xfa, reg32 >> 24);
739 mchbar_clrbits8(C0JEDEC, 1 << 7);
740 mchbar_clrbits8(C0DYNRDCTRL, 3 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +1100741
Angel Pons39ff7032020-03-09 21:39:44 +0100742 /* Note: This is a 64-bit register, [34..30] = 0b00110 is split across two writes */
743 reg32 = ((6 & 3) << 30) | (4 << 25) | (1 << 20) | (8 << 15) | (6 << 10) | (4 << 5) | 1;
Angel Pons0aeaee72021-03-26 17:57:46 +0100744 mchbar_write32(C0WRWMFLSH, reg32);
745 mchbar_clrsetbits16(C0WRWMFLSH + 4, 0x1ff, 8 << 3 | 6 >> 2);
746 mchbar_setbits16(SHPENDREG, 0x1c00 | 0x1f << 5);
Angel Pons39ff7032020-03-09 21:39:44 +0100747
748 /* FIXME: Why not do a single word write? */
Angel Pons0aeaee72021-03-26 17:57:46 +0100749 mchbar_clrsetbits8(SHPAGECTRL, 0xff, 0x40);
750 mchbar_clrsetbits8(SHPAGECTRL + 1, 0x07, 0x05);
751 mchbar_setbits8(SHCMPLWRCMD, 0x1f);
Angel Pons39ff7032020-03-09 21:39:44 +0100752
753 reg8 = (3 << 6);
Damien Zammit003d15c2015-11-20 17:17:51 +1100754 reg8 |= (s->dt0mode << 4);
755 reg8 |= 0x0c;
Angel Pons0aeaee72021-03-26 17:57:46 +0100756 mchbar_clrsetbits8(SHBONUSREG, 0xdf, reg8);
757 mchbar_clrbits8(CSHRWRIOMLNS, 1 << 1);
758 mchbar_clrsetbits8(C0MISCTM, 0x07, 0x02);
759 mchbar_clrsetbits16(C0BYPCTRL, 0xff << 2, 4 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +1100760
Angel Pons39ff7032020-03-09 21:39:44 +0100761 /* [31..29] = 0b010 for kN = 2 (2N) */
762 reg32 = (2 << 29) | (1 << 28) | (1 << 23);
Angel Pons0aeaee72021-03-26 17:57:46 +0100763 mchbar_clrsetbits32(WRWMCONFIG, 0xffb << 20, reg32);
Angel Pons39ff7032020-03-09 21:39:44 +0100764
Elyes Haouas3a998072022-11-18 15:11:02 +0100765 reg8 = (u8)((mchbar_read16(C0CYCTRKACT) & 0xe000) >> 13);
766 reg8 |= (u8)((mchbar_read16(C0CYCTRKACT + 2) & 1) << 3);
Angel Pons0aeaee72021-03-26 17:57:46 +0100767 mchbar_clrsetbits8(BYPACTSF, 0xf << 4, reg8 << 4);
Angel Pons39ff7032020-03-09 21:39:44 +0100768
Elyes Haouas3a998072022-11-18 15:11:02 +0100769 reg8 = (u8)((mchbar_read32(C0CYCTRKRD) & 0x000f0000) >> 17);
Angel Pons0aeaee72021-03-26 17:57:46 +0100770 mchbar_clrsetbits8(BYPACTSF, 0xf, reg8);
Angel Pons39ff7032020-03-09 21:39:44 +0100771
772 /* FIXME: Why not clear everything at once? */
Angel Pons0aeaee72021-03-26 17:57:46 +0100773 mchbar_clrbits8(BYPKNRULE, 0xfc);
774 mchbar_clrbits8(BYPKNRULE, 0x03);
775 mchbar_clrbits8(SHBONUSREG, 0x03);
776 mchbar_setbits8(C0BYPCTRL, 1 << 0);
777 mchbar_setbits16(CSHRMISCCTL1, 1 << 9);
Angel Pons39ff7032020-03-09 21:39:44 +0100778
Damien Zammit003d15c2015-11-20 17:17:51 +1100779 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +0100780 /* FIXME: Hardcoded for DDR2 SO-DIMMs */
Angel Pons0aeaee72021-03-26 17:57:46 +0100781 mchbar_clrsetbits32(C0DLLRCVCTLy(i), 0x3f3f3f3f, 0x0c0c0c0c);
Damien Zammit003d15c2015-11-20 17:17:51 +1100782 }
Angel Pons39ff7032020-03-09 21:39:44 +0100783 /* RDCS to RCVEN delay: Program coarse common to all bytelanes to default tCL + 1 */
Angel Pons0aeaee72021-03-26 17:57:46 +0100784 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, (s->selected_timings.CAS + 1) << 16);
Angel Pons39ff7032020-03-09 21:39:44 +0100785
786 /* Program RCVEN delay with DLL-safe settings */
Damien Zammit003d15c2015-11-20 17:17:51 +1100787 for (i = 0; i < 8; i++) {
Angel Pons0aeaee72021-03-26 17:57:46 +0100788 mchbar_clrbits8(C0RXRCVyDLL(i), 0x3f);
Angel Pons11cabea2021-03-26 22:41:54 +0100789 mchbar_clrbits16(C0RCVMISCCTL2, 3 << (i * 2));
790 mchbar_clrbits16(C0RCVMISCCTL1, 3 << (i * 2));
791 mchbar_clrbits16(C0COARSEDLY0, 3 << (i * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +1100792 }
Angel Pons0aeaee72021-03-26 17:57:46 +0100793 mchbar_clrbits8(C0DLLPIEN, 1 << 0); /* Power up receiver */
794 mchbar_setbits8(C0DLLPIEN, 1 << 1); /* Enable RCVEN DLL */
795 mchbar_setbits8(C0DLLPIEN, 1 << 2); /* Enable receiver DQS DLL */
796 mchbar_setbits32(C0COREBONUS, 0x000c0400);
797 mchbar_setbits32(C0CMDTX1, 1 << 31);
Damien Zammit003d15c2015-11-20 17:17:51 +1100798}
799
Angel Pons39ff7032020-03-09 21:39:44 +0100800/* Program clkset0's register for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200801static void sdram_p_clkset0(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100802{
Angel Pons0aeaee72021-03-26 17:57:46 +0100803 mchbar_clrsetbits16(C0CKTX, 0xc440,
Damien Zammit003d15c2015-11-20 17:17:51 +1100804 (pll->clkdelay[f][i] << 14) |
805 (pll->dben[f][i] << 10) |
Angel Pons39ff7032020-03-09 21:39:44 +0100806 (pll->dbsel[f][i] << 6));
807
Angel Pons0aeaee72021-03-26 17:57:46 +0100808 mchbar_clrsetbits8(C0TXCK0DLL, 0x3f, pll->pi[f][i]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100809}
810
Angel Pons39ff7032020-03-09 21:39:44 +0100811/* Program clkset1's register for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200812static void sdram_p_clkset1(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100813{
Angel Pons0aeaee72021-03-26 17:57:46 +0100814 mchbar_clrsetbits32(C0CKTX, 0x00030880,
Damien Zammit003d15c2015-11-20 17:17:51 +1100815 (pll->clkdelay[f][i] << 16) |
816 (pll->dben[f][i] << 11) |
Angel Pons39ff7032020-03-09 21:39:44 +0100817 (pll->dbsel[f][i] << 7));
818
Angel Pons0aeaee72021-03-26 17:57:46 +0100819 mchbar_clrsetbits8(C0TXCK1DLL, 0x3f, pll->pi[f][i]);
Damien Zammit003d15c2015-11-20 17:17:51 +1100820}
821
Angel Pons39ff7032020-03-09 21:39:44 +0100822/* Program CMD0 and CMD1 registers for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200823static void sdram_p_cmd(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100824{
825 u8 reg8;
Angel Pons39ff7032020-03-09 21:39:44 +0100826 /* Clock Group Index 3 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100827 reg8 = pll->dbsel[f][i] << 5;
828 reg8 |= pll->dben[f][i] << 6;
Angel Pons0aeaee72021-03-26 17:57:46 +0100829 mchbar_clrsetbits8(C0CMDTX1, 3 << 5, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100830
831 reg8 = pll->clkdelay[f][i] << 4;
Angel Pons0aeaee72021-03-26 17:57:46 +0100832 mchbar_clrsetbits8(C0CMDTX2, 3 << 4, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100833
834 reg8 = pll->pi[f][i];
Angel Pons0aeaee72021-03-26 17:57:46 +0100835 mchbar_clrsetbits8(C0TXCMD0DLL, 0x3f, reg8);
836 mchbar_clrsetbits8(C0TXCMD1DLL, 0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100837}
838
Angel Pons39ff7032020-03-09 21:39:44 +0100839/* Program CTRL registers for Kcoarse, Tap, PI, DBEn and DBSel */
Arthur Heymans6bf13012017-06-10 12:03:27 +0200840static void sdram_p_ctrl(const struct pllparam *pll, u8 f, u8 i)
Damien Zammit003d15c2015-11-20 17:17:51 +1100841{
842 u8 reg8;
843 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +0100844
845 /* CTRL0 and CTRL1 */
Elyes Haouas3a998072022-11-18 15:11:02 +0100846 reg32 = ((u32)pll->dbsel[f][i]) << 20;
847 reg32 |= ((u32)pll->dben[f][i]) << 21;
848 reg32 |= ((u32)pll->dbsel[f][i]) << 22;
849 reg32 |= ((u32)pll->dben[f][i]) << 23;
850 reg32 |= ((u32)pll->clkdelay[f][i]) << 24;
851 reg32 |= ((u32)pll->clkdelay[f][i]) << 27;
Angel Pons0aeaee72021-03-26 17:57:46 +0100852 mchbar_clrsetbits32(C0CTLTX2, 0x01bf0000, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100853
854 reg8 = pll->pi[f][i];
Angel Pons0aeaee72021-03-26 17:57:46 +0100855 mchbar_clrsetbits8(C0TXCTL0DLL, 0x3f, reg8);
856 mchbar_clrsetbits8(C0TXCTL1DLL, 0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100857
Angel Pons39ff7032020-03-09 21:39:44 +0100858 /* CTRL2 and CTRL3 */
Elyes Haouas3a998072022-11-18 15:11:02 +0100859 reg32 = ((u32)pll->dbsel[f][i]) << 12;
860 reg32 |= ((u32)pll->dben[f][i]) << 13;
861 reg32 |= ((u32)pll->dbsel[f][i]) << 8;
862 reg32 |= ((u32)pll->dben[f][i]) << 9;
863 reg32 |= ((u32)pll->clkdelay[f][i]) << 14;
864 reg32 |= ((u32)pll->clkdelay[f][i]) << 10;
Angel Pons0aeaee72021-03-26 17:57:46 +0100865 mchbar_clrsetbits32(C0CMDTX2, 0xff << 8, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100866
867 reg8 = pll->pi[f][i];
Angel Pons0aeaee72021-03-26 17:57:46 +0100868 mchbar_clrsetbits8(C0TXCTL2DLL, 0x3f, reg8);
869 mchbar_clrsetbits8(C0TXCTL3DLL, 0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100870}
871
872static void sdram_p_dqs(struct pllparam *pll, u8 f, u8 clk)
873{
874 u8 rank, dqs, reg8, j;
875 u32 reg32;
876
Angel Pons39ff7032020-03-09 21:39:44 +0100877 j = clk - 40;
878 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100879 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100880 rank = j % 4;
881 dqs = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100882
Elyes Haouas3a998072022-11-18 15:11:02 +0100883 reg32 |= ((u32)pll->dben[f][clk]) << (dqs + 9);
884 reg32 |= ((u32)pll->dbsel[f][clk]) << dqs;
Damien Zammit003d15c2015-11-20 17:17:51 +1100885
Angel Pons0aeaee72021-03-26 17:57:46 +0100886 mchbar_clrsetbits32(C0DQSRyTX1(rank), 1 << (dqs + 9) | 1 << dqs, reg32);
Angel Pons39ff7032020-03-09 21:39:44 +0100887
Elyes Haouas3a998072022-11-18 15:11:02 +0100888 reg32 = ((u32)pll->clkdelay[f][clk]) << ((dqs * 2) + 16);
Angel Pons0aeaee72021-03-26 17:57:46 +0100889 mchbar_clrsetbits32(C0DQSDQRyTX3(rank), 1 << (dqs * 2 + 17) | 1 << (dqs * 2 + 16),
Angel Pons39ff7032020-03-09 21:39:44 +0100890 reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100891
892 reg8 = pll->pi[f][clk];
Angel Pons0aeaee72021-03-26 17:57:46 +0100893 mchbar_clrsetbits8(C0TXDQS0R0DLL + j, 0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100894}
895
Damien Zammit003d15c2015-11-20 17:17:51 +1100896static void sdram_p_dq(struct pllparam *pll, u8 f, u8 clk)
897{
898 u8 rank, dq, reg8, j;
899 u32 reg32;
900
Angel Pons39ff7032020-03-09 21:39:44 +0100901 j = clk - 8;
902 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +1100903 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +0100904 rank = j % 4;
905 dq = j / 4;
Damien Zammit003d15c2015-11-20 17:17:51 +1100906
Elyes Haouas3a998072022-11-18 15:11:02 +0100907 reg32 |= ((u32)pll->dben[f][clk]) << (dq + 9);
908 reg32 |= ((u32)pll->dbsel[f][clk]) << dq;
Angel Pons39ff7032020-03-09 21:39:44 +0100909
Angel Pons0aeaee72021-03-26 17:57:46 +0100910 mchbar_clrsetbits32(C0DQRyTX1(rank), 1 << (dq + 9) | 1 << dq, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100911
Elyes Haouas3a998072022-11-18 15:11:02 +0100912 reg32 = ((u32)pll->clkdelay[f][clk]) << (dq*2);
Angel Pons0aeaee72021-03-26 17:57:46 +0100913 mchbar_clrsetbits32(C0DQSDQRyTX3(rank), 1 << (dq * 2 + 1) | 1 << (dq * 2), reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +1100914
915 reg8 = pll->pi[f][clk];
Angel Pons0aeaee72021-03-26 17:57:46 +0100916 mchbar_clrsetbits8(C0TXDQ0R0DLL + j, 0x3f, reg8);
Damien Zammit003d15c2015-11-20 17:17:51 +1100917}
918
Angel Pons39ff7032020-03-09 21:39:44 +0100919/* WDLL programming: Perform HPLL/MPLL calibration after write levelization */
Damien Zammit003d15c2015-11-20 17:17:51 +1100920static void sdram_calibratepll(struct sysinfo *s, u8 pidelay)
921{
922 struct pllparam pll = {
923 .pi = {
Angel Pons39ff7032020-03-09 21:39:44 +0100924 { /* DDR = 667 */
Damien Zammit003d15c2015-11-20 17:17:51 +1100925 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
926 7, 7, 7, 7, 4, 4, 4, 4, 4, 4, 4, 4,
927 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
928 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
929 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Angel Pons39ff7032020-03-09 21:39:44 +0100930 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3,
Damien Zammit003d15c2015-11-20 17:17:51 +1100931 },
Angel Pons39ff7032020-03-09 21:39:44 +0100932 { /* DDR = 800 */
933 53, 53, 10, 10, 5, 5, 5, 5, 27, 27, 27, 27,
Damien Zammit003d15c2015-11-20 17:17:51 +1100934 34, 34, 34, 34, 34, 34, 34, 34, 39, 39, 39, 39,
935 47, 47, 47, 47, 44, 44, 44, 44, 47, 47, 47, 47,
Angel Pons39ff7032020-03-09 21:39:44 +0100936 47, 47, 47, 47, 59, 59, 59, 59, 2, 2, 2, 2,
937 2, 2, 2, 2, 7, 7, 7, 7, 15, 15, 15, 15,
938 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15,
Damien Zammit003d15c2015-11-20 17:17:51 +1100939 }},
940
941 .dben = {
Angel Pons39ff7032020-03-09 21:39:44 +0100942 { /* DDR = 667 */
943 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
944 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
945 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
946 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
947 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
948 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100949 },
Angel Pons39ff7032020-03-09 21:39:44 +0100950 { /* DDR = 800 */
951 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
952 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
953 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
954 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
955 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
956 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100957 }},
958
959 .dbsel = {
Angel Pons39ff7032020-03-09 21:39:44 +0100960 { /* DDR = 667 */
961 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
962 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
963 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
964 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
965 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100967 },
Angel Pons39ff7032020-03-09 21:39:44 +0100968 { /* DDR = 800 */
969 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
970 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
971 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
972 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
973 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
974 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100975 }},
976
977 .clkdelay = {
Angel Pons39ff7032020-03-09 21:39:44 +0100978 { /* DDR = 667 */
979 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
980 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
981 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
982 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
983 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
984 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Damien Zammit003d15c2015-11-20 17:17:51 +1100985 },
Angel Pons39ff7032020-03-09 21:39:44 +0100986 { /* DDR = 800 */
987 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
988 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
989 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
990 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
991 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
992 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Damien Zammit003d15c2015-11-20 17:17:51 +1100993 }}
994 };
995
996 u8 i, f;
997 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
998 f = 0;
999 } else {
1000 f = 1;
1001 }
1002 for (i = 0; i < 72; i++) {
1003 pll.pi[f][i] += pidelay;
1004 }
1005
Angel Pons39ff7032020-03-09 21:39:44 +01001006 /* Disable Dynamic DQS Slave Setting Per Rank */
Angel Pons0aeaee72021-03-26 17:57:46 +01001007 mchbar_clrbits8(CSHRDQSCMN, 1 << 7);
1008 mchbar_clrsetbits16(CSHRPDCTL4, 0x3fff, 0x1fff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001009
1010 sdram_p_clkset0(&pll, f, 0);
1011 sdram_p_clkset1(&pll, f, 1);
Angel Pons39ff7032020-03-09 21:39:44 +01001012 sdram_p_cmd(&pll, f, 2);
1013 sdram_p_ctrl(&pll, f, 4);
1014
Damien Zammit003d15c2015-11-20 17:17:51 +11001015 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001016 sdram_p_dqs(&pll, f, i + 40);
Damien Zammit003d15c2015-11-20 17:17:51 +11001017 }
1018 for (i = 0; i < 32; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01001019 sdram_p_dq(&pll, f, i + 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11001020 }
1021}
1022
Angel Pons39ff7032020-03-09 21:39:44 +01001023/* Perform HMC hardware calibration */
Damien Zammit003d15c2015-11-20 17:17:51 +11001024static void sdram_calibratehwpll(struct sysinfo *s)
1025{
1026 u8 reg8;
1027
1028 s->async = 0;
1029 reg8 = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001030
Angel Pons0aeaee72021-03-26 17:57:46 +01001031 mchbar_setbits16(CSHRPDCTL, 1 << 15);
1032 mchbar_clrbits8(CSHRPDCTL, 1 << 7);
1033 mchbar_setbits8(CSHRPDCTL, 1 << 3);
1034 mchbar_setbits8(CSHRPDCTL, 1 << 2);
Damien Zammit003d15c2015-11-20 17:17:51 +11001035
Angel Pons39ff7032020-03-09 21:39:44 +01001036 /* Start hardware HMC calibration */
Angel Pons0aeaee72021-03-26 17:57:46 +01001037 mchbar_setbits8(CSHRPDCTL, 1 << 7);
Angel Pons39ff7032020-03-09 21:39:44 +01001038
1039 /* Busy-wait until calibration is done */
Angel Pons0aeaee72021-03-26 17:57:46 +01001040 while ((mchbar_read8(CSHRPDCTL) & (1 << 2)) == 0)
Angel Pons39ff7032020-03-09 21:39:44 +01001041 ;
1042
1043 /* If hardware HMC calibration failed */
Angel Pons0aeaee72021-03-26 17:57:46 +01001044 reg8 = (mchbar_read8(CSHRPDCTL) & (1 << 3)) >> 3;
Damien Zammit003d15c2015-11-20 17:17:51 +11001045 if (reg8 != 0) {
1046 s->async = 1;
1047 }
1048}
1049
1050static void sdram_dlltiming(struct sysinfo *s)
1051{
Elyes HAOUAS66b462d2019-01-02 21:11:32 +01001052 u8 reg8, i;
Damien Zammit003d15c2015-11-20 17:17:51 +11001053 u16 reg16;
1054 u32 reg32;
1055
Angel Pons39ff7032020-03-09 21:39:44 +01001056 /* Configure the Master DLL */
Damien Zammit003d15c2015-11-20 17:17:51 +11001057 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Angel Pons39ff7032020-03-09 21:39:44 +01001058 reg32 = 0x08014227;
Damien Zammit003d15c2015-11-20 17:17:51 +11001059 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001060 reg32 = 0x00014221;
Damien Zammit003d15c2015-11-20 17:17:51 +11001061 }
Angel Pons0aeaee72021-03-26 17:57:46 +01001062 mchbar_clrsetbits32(CSHRMSTRCTL1, 0x0fffffff, reg32);
1063 mchbar_setbits32(CSHRMSTRCTL1, 1 << 23);
1064 mchbar_setbits32(CSHRMSTRCTL1, 1 << 15);
1065 mchbar_clrbits32(CSHRMSTRCTL1, 1 << 15);
Damien Zammit003d15c2015-11-20 17:17:51 +11001066
1067 if (s->nodll) {
Angel Pons39ff7032020-03-09 21:39:44 +01001068 /* Disable the Master DLLs by setting these bits, IN ORDER! */
Angel Pons0aeaee72021-03-26 17:57:46 +01001069 mchbar_setbits16(CSHRMSTRCTL0, 1 << 0);
1070 mchbar_setbits16(CSHRMSTRCTL0, 1 << 2);
1071 mchbar_setbits16(CSHRMSTRCTL0, 1 << 4);
1072 mchbar_setbits16(CSHRMSTRCTL0, 1 << 8);
1073 mchbar_setbits16(CSHRMSTRCTL0, 1 << 10);
1074 mchbar_setbits16(CSHRMSTRCTL0, 1 << 12);
1075 mchbar_setbits16(CSHRMSTRCTL0, 1 << 14);
Damien Zammit003d15c2015-11-20 17:17:51 +11001076 } else {
Angel Pons39ff7032020-03-09 21:39:44 +01001077 /* Enable the Master DLLs by clearing these bits, IN ORDER! */
Angel Pons0aeaee72021-03-26 17:57:46 +01001078 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 0);
1079 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 2);
1080 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 4);
1081 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 8);
1082 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 10);
1083 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 12);
1084 mchbar_clrbits16(CSHRMSTRCTL0, 1 << 14);
Damien Zammit003d15c2015-11-20 17:17:51 +11001085 }
1086
Angel Pons39ff7032020-03-09 21:39:44 +01001087 /* Initialize the Transmit DLL PI values in the following sequence. */
Damien Zammit003d15c2015-11-20 17:17:51 +11001088 if (s->nodll) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001089 mchbar_clrsetbits8(CREFPI, 0x3f, 0x07);
Damien Zammit003d15c2015-11-20 17:17:51 +11001090 } else {
Angel Pons0aeaee72021-03-26 17:57:46 +01001091 mchbar_clrbits8(CREFPI, 0x3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001092 }
1093
1094 sdram_calibratepll(s, 0); // XXX check
1095
Angel Pons39ff7032020-03-09 21:39:44 +01001096 /* Enable all modular Slave DLL */
Angel Pons0aeaee72021-03-26 17:57:46 +01001097 mchbar_setbits16(C0DLLPIEN, 1 << 11);
1098 mchbar_setbits16(C0DLLPIEN, 1 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11001099
1100 for (i = 0; i < 8; i++) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001101 mchbar_setbits16(C0DLLPIEN, (1 << 10) >> i);
Damien Zammit003d15c2015-11-20 17:17:51 +11001102 }
Angel Pons39ff7032020-03-09 21:39:44 +01001103 /* Enable DQ/DQS output */
Angel Pons0aeaee72021-03-26 17:57:46 +01001104 mchbar_setbits8(C0SLVDLLOUTEN, 1 << 0);
1105 mchbar_write16(CSPDSLVWT, 0x5005);
1106 mchbar_clrsetbits16(CSHRPDCTL2, 0x1f1f, 0x051a);
1107 mchbar_clrsetbits16(CSHRPDCTL5, 0xbf3f, 0x9010);
Damien Zammit003d15c2015-11-20 17:17:51 +11001108
1109 if (s->nodll) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001110 mchbar_clrsetbits8(CSHRPDCTL3, 0x7f, 0x6b);
Damien Zammit003d15c2015-11-20 17:17:51 +11001111 } else {
Angel Pons0aeaee72021-03-26 17:57:46 +01001112 mchbar_clrsetbits8(CSHRPDCTL3, 0x7f, 0x55);
Damien Zammit003d15c2015-11-20 17:17:51 +11001113 sdram_calibratehwpll(s);
1114 }
Angel Pons39ff7032020-03-09 21:39:44 +01001115 /* Disable Dynamic Diff Amp */
Angel Pons0aeaee72021-03-26 17:57:46 +01001116 mchbar_clrbits32(C0STATRDCTRL, 1 << 22);
Damien Zammit003d15c2015-11-20 17:17:51 +11001117
Angel Pons39ff7032020-03-09 21:39:44 +01001118 /* Now, start initializing the transmit FIFO */
Angel Pons0aeaee72021-03-26 17:57:46 +01001119 mchbar_clrbits8(C0MISCCTL, 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001120
Angel Pons39ff7032020-03-09 21:39:44 +01001121 /* Disable (gate) mdclk and mdclkb */
Angel Pons0aeaee72021-03-26 17:57:46 +01001122 mchbar_setbits8(CSHWRIOBONUS, 3 << 6);
Jacob Garberd10680b2019-06-11 14:13:04 -06001123
Angel Pons39ff7032020-03-09 21:39:44 +01001124 /* Select mdmclk */
Angel Pons0aeaee72021-03-26 17:57:46 +01001125 mchbar_clrbits8(CSHWRIOBONUS, 1 << 5);
Damien Zammit003d15c2015-11-20 17:17:51 +11001126
Angel Pons39ff7032020-03-09 21:39:44 +01001127 /* Ungate mdclk */
Angel Pons0aeaee72021-03-26 17:57:46 +01001128 mchbar_clrsetbits8(CSHWRIOBONUS, 3 << 6, 1 << 6);
1129 mchbar_clrsetbits8(CSHRFIFOCTL, 0x3f, 0x1a);
Angel Pons39ff7032020-03-09 21:39:44 +01001130
1131 /* Enable the write pointer count */
Angel Pons0aeaee72021-03-26 17:57:46 +01001132 mchbar_setbits8(CSHRFIFOCTL, 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +01001133
1134 /* Set the DDR3 Reset Enable bit */
Angel Pons0aeaee72021-03-26 17:57:46 +01001135 mchbar_setbits8(CSHRDDR3CTL, 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +01001136
1137 /* Configure DQS-DQ Transmit */
Angel Pons0aeaee72021-03-26 17:57:46 +01001138 mchbar_write32(CSHRDQSTXPGM, 0x00551803);
Angel Pons39ff7032020-03-09 21:39:44 +01001139
1140 reg8 = 0; /* Switch all clocks on anyway */
1141
1142 /* Enable clock groups depending on rank population */
Angel Pons0aeaee72021-03-26 17:57:46 +01001143 mchbar_clrsetbits32(C0CKTX, 0x3f << 24, reg8 << 24);
Angel Pons39ff7032020-03-09 21:39:44 +01001144
1145 /* Enable DDR command output buffers from core */
Angel Pons0aeaee72021-03-26 17:57:46 +01001146 mchbar_clrbits8(0x594, 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +01001147
Damien Zammit003d15c2015-11-20 17:17:51 +11001148 reg16 = 0;
1149 if (!rank_is_populated(s->dimms, 0, 0)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001150 reg16 |= (1 << 8) | (1 << 4) | (1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001151 }
1152 if (!rank_is_populated(s->dimms, 0, 1)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001153 reg16 |= (1 << 9) | (1 << 5) | (1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001154 }
1155 if (!rank_is_populated(s->dimms, 0, 2)) {
1156 reg16 |= (1 << 10) | (1 << 6) | (1 << 2);
1157 }
1158 if (!rank_is_populated(s->dimms, 0, 3)) {
1159 reg16 |= (1 << 11) | (1 << 7) | (1 << 3);
1160 }
Angel Pons0aeaee72021-03-26 17:57:46 +01001161 mchbar_setbits16(C0CTLTX2, reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001162}
1163
Angel Pons39ff7032020-03-09 21:39:44 +01001164/* Define a shorter name for these to make the lines fit in 96 characters */
1165#define TABLE static const
1166
1167/* Loop over each RCOMP group, but skip group 1 because it does not exist */
1168#define FOR_EACH_RCOMP_GROUP(idx) for (idx = 0; idx < 7; idx++) if (idx != 1)
1169
1170/* Define accessors for the RCOMP register banks */
1171#define C0RCOMPCTRLx(x) (rcompctl[(x)] + 0x00)
1172#define C0RCOMPMULTx(x) (rcompctl[(x)] + 0x04)
1173#define C0RCOMPOVRx(x) (rcompctl[(x)] + 0x06)
Angel Pons94eea6f2021-02-06 15:03:48 +01001174#define C0RCOMPOSVx(x) (rcompctl[(x)] + 0x0a)
1175#define C0SCOMPVREFx(x) (rcompctl[(x)] + 0x0e)
Angel Pons39ff7032020-03-09 21:39:44 +01001176#define C0SCOMPOVRx(x) (rcompctl[(x)] + 0x10)
1177#define C0SCOMPOFFx(x) (rcompctl[(x)] + 0x12)
1178#define C0DCOMPx(x) (rcompctl[(x)] + 0x14)
1179#define C0SLEWBASEx(x) (rcompctl[(x)] + 0x16)
1180#define C0SLEWPULUTx(x) (rcompctl[(x)] + 0x18)
Angel Pons94eea6f2021-02-06 15:03:48 +01001181#define C0SLEWPDLUTx(x) (rcompctl[(x)] + 0x1c)
Angel Pons39ff7032020-03-09 21:39:44 +01001182#define C0DCOMPOVRx(x) (rcompctl[(x)] + 0x20)
1183#define C0DCOMPOFFx(x) (rcompctl[(x)] + 0x24)
1184
1185/* FIXME: This only applies to DDR2 */
Damien Zammit003d15c2015-11-20 17:17:51 +11001186static void sdram_rcomp(struct sysinfo *s)
1187{
Angel Pons39ff7032020-03-09 21:39:44 +01001188 u8 i, j, reg8, rcompp, rcompn, srup, srun;
Damien Zammit003d15c2015-11-20 17:17:51 +11001189 u16 reg16;
1190 u32 reg32, rcomp1, rcomp2;
1191
Angel Pons39ff7032020-03-09 21:39:44 +01001192 static const u8 rcompslew = 0x0a;
1193 static const u16 rcompctl[7] = {
1194 C0RCOMPCTRL0,
1195 0, /* This register does not exist */
1196 C0RCOMPCTRL2,
1197 C0RCOMPCTRL3,
1198 C0RCOMPCTRL4,
1199 C0RCOMPCTRL5,
1200 C0RCOMPCTRL6,
1201 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001202
Angel Pons39ff7032020-03-09 21:39:44 +01001203 /* RCOMP settings tables = { NC-NC, x16SS, x16DS, x16SS2, x16DS2, x8DS, x8DS2}; */
1204 TABLE u8 rcompupdate[7] = { 0, 0, 0, 1, 1, 0, 0};
1205 TABLE u8 rcompstr[7] = { 0x66, 0x00, 0xaa, 0x55, 0x55, 0x77, 0x77};
1206 TABLE u16 rcompscomp[7] = {0xa22a, 0x0000, 0xe22e, 0xe22e, 0xe22e, 0xa22a, 0xa22a};
1207 TABLE u8 rcompdelay[7] = { 1, 0, 0, 0, 0, 1, 1};
1208 TABLE u16 rcompf[7] = {0x1114, 0x0000, 0x0505, 0x0909, 0x0909, 0x0a0a, 0x0a0a};
1209 TABLE u8 rcompstr2[7] = { 0x00, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0xaa};
1210 TABLE u16 rcompscomp2[7] = {0x0000, 0xe22e, 0xe22e, 0xe22e, 0x8228, 0xe22e, 0x8228};
1211 TABLE u8 rcompdelay2[7] = { 0, 0, 0, 0, 2, 0, 2};
Damien Zammit003d15c2015-11-20 17:17:51 +11001212
Angel Pons39ff7032020-03-09 21:39:44 +01001213 TABLE u8 rcomplut[64][12] = {
1214 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1215 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1216 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1217 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1218 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1219 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1220 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1221 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1222 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1223 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1224 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1225 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1226 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1227 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1228 { 9, 9, 11, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1229 {10, 9, 12, 11, 2, 2, 5, 5, 6, 6, 5, 5},
1230 {10, 9, 12, 11, 2, 2, 6, 5, 7, 6, 6, 5},
1231 {10, 10, 12, 12, 2, 2, 6, 5, 7, 6, 6, 5},
1232 {10, 10, 12, 12, 2, 2, 6, 6, 7, 7, 6, 6},
1233 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1234 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1235 {10, 10, 12, 12, 3, 2, 6, 6, 7, 7, 6, 6},
1236 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1237 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1238 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1239 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1240 {10, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1241 {11, 10, 12, 12, 3, 3, 6, 6, 7, 7, 6, 6},
1242 {11, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1243 {12, 10, 14, 13, 3, 3, 6, 6, 7, 7, 6, 6},
1244 {12, 12, 14, 13, 3, 3, 7, 6, 7, 7, 7, 6},
1245 {13, 12, 16, 15, 3, 3, 7, 6, 8, 7, 7, 6},
1246 {13, 14, 16, 15, 4, 3, 7, 7, 8, 8, 7, 7},
1247 {14, 14, 16, 17, 4, 3, 7, 7, 8, 8, 7, 7},
1248 {14, 16, 18, 17, 4, 4, 8, 7, 8, 8, 8, 7},
1249 {15, 16, 18, 19, 4, 4, 8, 7, 9, 8, 8, 7},
1250 {15, 18, 18, 19, 4, 4, 8, 8, 9, 9, 8, 8},
1251 {16, 18, 20, 21, 4, 4, 8, 8, 9, 9, 8, 8},
1252 {16, 19, 20, 21, 5, 4, 9, 8, 10, 9, 9, 8},
1253 {16, 19, 20, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1254 {17, 19, 22, 23, 5, 5, 9, 9, 10, 10, 9, 9},
1255 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1256 {17, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1257 {18, 20, 22, 25, 5, 5, 9, 9, 10, 10, 9, 9},
1258 {18, 21, 24, 25, 5, 5, 9, 9, 11, 10, 9, 9},
1259 {19, 21, 24, 27, 5, 5, 9, 9, 11, 11, 9, 9},
1260 {19, 22, 24, 27, 5, 5, 10, 9, 11, 11, 10, 9},
1261 {20, 22, 24, 27, 6, 5, 10, 10, 11, 11, 10, 10},
1262 {20, 23, 26, 27, 6, 6, 10, 10, 12, 12, 10, 10},
1263 {20, 23, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1264 {21, 24, 26, 29, 6, 6, 10, 10, 12, 12, 10, 10},
1265 {21, 24, 26, 29, 6, 6, 11, 10, 12, 13, 11, 10},
1266 {22, 25, 28, 29, 6, 6, 11, 11, 13, 13, 11, 11},
1267 {22, 25, 28, 31, 6, 6, 11, 11, 13, 13, 11, 11},
1268 {22, 26, 28, 31, 6, 6, 11, 11, 13, 14, 11, 11},
1269 {23, 26, 30, 31, 7, 6, 12, 11, 14, 14, 12, 11},
1270 {23, 27, 30, 33, 7, 7, 12, 12, 14, 14, 12, 12},
1271 {23, 27, 30, 33, 7, 7, 12, 12, 14, 15, 12, 12},
1272 {24, 28, 32, 33, 7, 7, 12, 12, 15, 15, 12, 12},
1273 {24, 28, 32, 33, 7, 7, 12, 12, 15, 16, 12, 12},
1274 {24, 29, 32, 35, 7, 7, 12, 12, 15, 16, 12, 12},
1275 {25, 29, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1276 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
1277 {25, 30, 32, 35, 7, 7, 12, 12, 15, 17, 12, 12},
Damien Zammit003d15c2015-11-20 17:17:51 +11001278 };
1279
1280 srup = 0;
1281 srun = 0;
1282
1283 if (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001284 rcomp1 = 0x00050431;
1285 } else {
Damien Zammit003d15c2015-11-20 17:17:51 +11001286 rcomp1 = 0x00050542;
1287 }
1288 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
Angel Pons94eea6f2021-02-06 15:03:48 +01001289 rcomp2 = 0x14c42827;
Damien Zammit003d15c2015-11-20 17:17:51 +11001290 } else {
1291 rcomp2 = 0x19042827;
1292 }
1293
Angel Pons39ff7032020-03-09 21:39:44 +01001294 FOR_EACH_RCOMP_GROUP(i) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001295 reg8 = rcompupdate[i];
Angel Pons0aeaee72021-03-26 17:57:46 +01001296 mchbar_clrsetbits8(C0RCOMPCTRLx(i), 1 << 0, reg8);
1297 mchbar_clrbits8(C0RCOMPCTRLx(i), 1 << 1);
Angel Pons39ff7032020-03-09 21:39:44 +01001298
1299 reg16 = rcompslew;
Angel Pons0aeaee72021-03-26 17:57:46 +01001300 mchbar_clrsetbits16(C0RCOMPCTRLx(i), 0xf << 12, reg16 << 12);
Angel Pons39ff7032020-03-09 21:39:44 +01001301
Angel Pons0aeaee72021-03-26 17:57:46 +01001302 mchbar_write8(C0RCOMPMULTx(i), rcompstr[i]);
1303 mchbar_write16(C0SCOMPVREFx(i), rcompscomp[i]);
1304 mchbar_clrsetbits8(C0DCOMPx(i), 0x03, rcompdelay[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001305 if (i == 2) {
Angel Pons39ff7032020-03-09 21:39:44 +01001306 /* FIXME: Why are we rewriting this? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001307 mchbar_clrsetbits16(C0RCOMPCTRLx(i), 0xf << 12, reg16 << 12);
Angel Pons39ff7032020-03-09 21:39:44 +01001308
Angel Pons0aeaee72021-03-26 17:57:46 +01001309 mchbar_write8(C0RCOMPMULTx(i), rcompstr2[s->dimm_config[0]]);
1310 mchbar_write16(C0SCOMPVREFx(i), rcompscomp2[s->dimm_config[0]]);
1311 mchbar_clrsetbits8(C0DCOMPx(i), 0x03, rcompdelay2[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001312 }
1313
Angel Pons0aeaee72021-03-26 17:57:46 +01001314 mchbar_clrbits16(C0SLEWBASEx(i), 0x7f7f);
Angel Pons39ff7032020-03-09 21:39:44 +01001315
1316 /* FIXME: Why not do a single dword write? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001317 mchbar_clrbits16(C0SLEWPULUTx(i), 0x3f3f);
1318 mchbar_clrbits16(C0SLEWPULUTx(i) + 2, 0x3f3f);
Angel Pons39ff7032020-03-09 21:39:44 +01001319
1320 /* FIXME: Why not do a single dword write? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001321 mchbar_clrbits16(C0SLEWPDLUTx(i), 0x3f3f);
1322 mchbar_clrbits16(C0SLEWPDLUTx(i) + 2, 0x3f3f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001323 }
1324
Angel Pons39ff7032020-03-09 21:39:44 +01001325 /* FIXME: Hardcoded */
Angel Pons0aeaee72021-03-26 17:57:46 +01001326 mchbar_clrsetbits8(C0ODTRECORDX, 0x3f, 0x36);
1327 mchbar_clrsetbits8(C0DQSODTRECORDX, 0x3f, 0x36);
Damien Zammit003d15c2015-11-20 17:17:51 +11001328
Angel Pons39ff7032020-03-09 21:39:44 +01001329 FOR_EACH_RCOMP_GROUP(i) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001330 mchbar_clrbits8(C0RCOMPCTRLx(i), 3 << 5);
1331 mchbar_clrbits16(C0RCOMPCTRLx(i) + 2, 0x0706);
1332 mchbar_clrbits16(C0RCOMPOSVx(i), 0x7f7f);
1333 mchbar_clrbits16(C0SCOMPOFFx(i), 0x3f3f);
1334 mchbar_clrbits16(C0DCOMPOFFx(i), 0x1f1f);
1335 mchbar_clrbits8(C0DCOMPOFFx(i) + 2, 0x1f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001336 }
1337
Angel Pons0aeaee72021-03-26 17:57:46 +01001338 mchbar_clrbits16(C0ODTRECORDX, 0xffc0);
1339 mchbar_clrbits16(C0ODTRECORDX + 2, 0x000f);
Damien Zammit003d15c2015-11-20 17:17:51 +11001340
Angel Pons39ff7032020-03-09 21:39:44 +01001341 /* FIXME: Why not do a single dword write? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001342 mchbar_clrbits16(C0DQSODTRECORDX, 0xffc0);
1343 mchbar_clrbits16(C0DQSODTRECORDX + 2, 0x000f);
Angel Pons39ff7032020-03-09 21:39:44 +01001344
1345 FOR_EACH_RCOMP_GROUP(i) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001346 mchbar_write16(C0SCOMPOVRx(i), rcompf[i]);
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_write16(C0DCOMPOVRx(i) + 0, 0x1219);
1350 mchbar_write16(C0DCOMPOVRx(i) + 2, 0x000c);
Damien Zammit003d15c2015-11-20 17:17:51 +11001351 }
1352
Angel Pons0aeaee72021-03-26 17:57:46 +01001353 mchbar_clrsetbits32(DCMEASBUFOVR, 0x001f1f1f, 0x000c1219);
Damien Zammit003d15c2015-11-20 17:17:51 +11001354
Angel Pons39ff7032020-03-09 21:39:44 +01001355 /* FIXME: Why not do a single word write? */
Angel Pons0aeaee72021-03-26 17:57:46 +01001356 mchbar_clrsetbits16(XCOMPSDR0BNS, 0x1f << 8, 0x12 << 8);
1357 mchbar_clrsetbits8(XCOMPSDR0BNS, 0x1f << 0, 0x12 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +01001358
Angel Pons0aeaee72021-03-26 17:57:46 +01001359 mchbar_write32(COMPCTRL3, 0x007c9007);
1360 mchbar_write32(OFREQDELSEL, rcomp1);
1361 mchbar_write16(XCOMPCMNBNS, 0x1f7f);
1362 mchbar_write32(COMPCTRL2, rcomp2);
1363 mchbar_clrsetbits16(XCOMPDFCTRL, 0xf, 1);
1364 mchbar_write16(ZQCALCTRL, 0x0134);
1365 mchbar_write32(COMPCTRL1, 0x4c293600);
Angel Pons39ff7032020-03-09 21:39:44 +01001366
Angel Pons0aeaee72021-03-26 17:57:46 +01001367 mchbar_clrsetbits8(COMPCTRL1 + 3, 0x44, 1 << 6 | 1 << 2);
1368 mchbar_clrbits16(XCOMPSDR0BNS, 1 << 13);
1369 mchbar_clrbits8(XCOMPSDR0BNS, 1 << 5);
Angel Pons39ff7032020-03-09 21:39:44 +01001370
1371 FOR_EACH_RCOMP_GROUP(i) {
Angel Pons07ccc8d2021-03-26 19:07:49 +01001372 /* POR values are zero */
Angel Pons0aeaee72021-03-26 17:57:46 +01001373 mchbar_clrbits8(C0RCOMPCTRLx(i) + 2, 0x71);
Damien Zammit003d15c2015-11-20 17:17:51 +11001374 }
1375
Angel Pons0aeaee72021-03-26 17:57:46 +01001376 if ((mchbar_read32(COMPCTRL1) & (1 << 30)) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001377 /* Start COMP */
Angel Pons0aeaee72021-03-26 17:57:46 +01001378 mchbar_setbits8(COMPCTRL1, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001379
Angel Pons39ff7032020-03-09 21:39:44 +01001380 /* Wait until COMP is done */
Angel Pons0aeaee72021-03-26 17:57:46 +01001381 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
Angel Pons39ff7032020-03-09 21:39:44 +01001382 ;
1383
Angel Pons0aeaee72021-03-26 17:57:46 +01001384 reg32 = mchbar_read32(XCOMP);
Elyes Haouas3a998072022-11-18 15:11:02 +01001385 rcompp = (u8)((reg32 & ~(1 << 31)) >> 24);
1386 rcompn = (u8)((reg32 & ~(0xff800000)) >> 16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001387
Angel Pons39ff7032020-03-09 21:39:44 +01001388 FOR_EACH_RCOMP_GROUP(i) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001389 srup = (mchbar_read8(C0RCOMPCTRLx(i) + 1) & 0xc0) >> 6;
1390 srun = (mchbar_read8(C0RCOMPCTRLx(i) + 1) & 0x30) >> 4;
Angel Pons39ff7032020-03-09 21:39:44 +01001391
1392 /* FIXME: Why not do a single word write? */
Damien Zammit003d15c2015-11-20 17:17:51 +11001393 reg16 = (u16)(rcompp - (1 << (srup + 1))) << 8;
Angel Pons0aeaee72021-03-26 17:57:46 +01001394 mchbar_clrsetbits16(C0SLEWBASEx(i), 0x7f << 8, reg16);
Angel Pons39ff7032020-03-09 21:39:44 +01001395
Damien Zammit003d15c2015-11-20 17:17:51 +11001396 reg16 = (u16)(rcompn - (1 << (srun + 1)));
Angel Pons0aeaee72021-03-26 17:57:46 +01001397 mchbar_clrsetbits8(C0SLEWBASEx(i), 0x7f, (u8)reg16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001398 }
1399
1400 reg8 = rcompp - (1 << (srup + 1));
1401 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001402 mchbar_clrsetbits8(C0SLEWPULUTx(0) + i, 0x3f, rcomplut[j][0]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001403 }
1404
1405 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
1406 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001407 mchbar_clrsetbits8(C0SLEWPULUTx(2) + i, 0x3f, rcomplut[j][10]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001408 }
1409 }
1410
1411 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001412 mchbar_clrsetbits8(C0SLEWPULUTx(3) + i, 0x3f, rcomplut[j][6]);
1413 mchbar_clrsetbits8(C0SLEWPULUTx(4) + i, 0x3f, rcomplut[j][6]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001414 }
1415
1416 for (i = 0, j = reg8; i < 4; i++, j += (1 << srup)) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001417 mchbar_clrsetbits8(C0SLEWPULUTx(5) + i, 0x3f, rcomplut[j][8]);
1418 mchbar_clrsetbits8(C0SLEWPULUTx(6) + i, 0x3f, rcomplut[j][8]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001419 }
1420
1421 reg8 = rcompn - (1 << (srun + 1));
1422 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001423 mchbar_clrsetbits8(C0SLEWPDLUTx(0) + i, 0x3f, rcomplut[j][1]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001424 }
1425
1426 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
1427 if (s->dimm_config[0] < 3 || s->dimm_config[0] == 5) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001428 mchbar_clrsetbits8(C0SLEWPDLUTx(2) + i, 0x3f, rcomplut[j][11]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001429 }
1430 }
1431
1432 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001433 mchbar_clrsetbits8(C0SLEWPDLUTx(3) + i, 0x3f, rcomplut[j][7]);
1434 mchbar_clrsetbits8(C0SLEWPDLUTx(4) + i, 0x3f, rcomplut[j][7]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001435 }
1436
1437 for (i = 0, j = reg8; i < 4; i++, j += (1 << srun)) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001438 mchbar_clrsetbits8(C0SLEWPDLUTx(5) + i, 0x3f, rcomplut[j][9]);
1439 mchbar_clrsetbits8(C0SLEWPDLUTx(6) + i, 0x3f, rcomplut[j][9]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001440 }
1441 }
Angel Pons0aeaee72021-03-26 17:57:46 +01001442 mchbar_setbits8(COMPCTRL1, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001443}
1444
Angel Pons39ff7032020-03-09 21:39:44 +01001445/* FIXME: The ODT tables are for DDR2 only! */
Damien Zammit003d15c2015-11-20 17:17:51 +11001446static void sdram_odt(struct sysinfo *s)
1447{
1448 u8 rankindex = 0;
1449
Angel Pons39ff7032020-03-09 21:39:44 +01001450 static const u16 odt_rankctrl[16] = {
1451 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1452 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1453 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1454 0x0000, 0x0000, 0x0000, 0x0000, 0x0044, 0x1111, 0x0000, 0x1111,
1455 };
1456 static const u16 odt_matrix[16] = {
1457 /* NC_NC, 1R_NC, NV, 2R_NC, NC_1R, 1R_1R, NV, 2R_1R, */
1458 0x0000, 0x0011, 0x0000, 0x0011, 0x0000, 0x4444, 0x0000, 0x4444,
1459 /* NV, NV, NV, NV, NC_2R, 1R_2R, NV, 2R_2R, */
1460 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4444, 0x0000, 0x4444,
1461 };
Damien Zammit003d15c2015-11-20 17:17:51 +11001462
1463 switch (s->dimms[0].ranks) {
1464 case 0:
1465 if (s->dimms[1].ranks == 0) {
1466 rankindex = 0;
1467 } else if (s->dimms[1].ranks == 1) {
1468 rankindex = 4;
1469 } else if (s->dimms[1].ranks == 2) {
1470 rankindex = 12;
1471 }
1472 break;
1473 case 1:
1474 if (s->dimms[1].ranks == 0) {
1475 rankindex = 1;
1476 } else if (s->dimms[1].ranks == 1) {
1477 rankindex = 5;
1478 } else if (s->dimms[1].ranks == 2) {
1479 rankindex = 13;
1480 }
1481 break;
1482 case 2:
1483 if (s->dimms[1].ranks == 0) {
1484 rankindex = 3;
1485 } else if (s->dimms[1].ranks == 1) {
1486 rankindex = 7;
1487 } else if (s->dimms[1].ranks == 2) {
1488 rankindex = 15;
1489 }
1490 break;
1491 }
1492
Angel Pons39ff7032020-03-09 21:39:44 +01001493 /* Program the ODT Matrix */
Angel Pons0aeaee72021-03-26 17:57:46 +01001494 mchbar_write16(C0ODT, odt_matrix[rankindex]);
Angel Pons39ff7032020-03-09 21:39:44 +01001495
1496 /* Program the ODT Rank Control */
Angel Pons0aeaee72021-03-26 17:57:46 +01001497 mchbar_write16(C0ODTRKCTRL, odt_rankctrl[rankindex]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001498}
1499
1500static void sdram_mmap(struct sysinfo *s)
1501{
Angel Pons39ff7032020-03-09 21:39:44 +01001502 TABLE u32 w260[7] = {0, 0x400001, 0xc00001, 0x500000, 0xf00000, 0xc00001, 0xf00000};
1503 TABLE u32 w208[7] = {0, 0x10000, 0x1010000, 0x10001, 0x1010101, 0x1010000, 0x1010101};
1504 TABLE u32 w200[7] = {0, 0, 0, 0x20002, 0x40002, 0, 0x40002};
1505 TABLE u32 w204[7] = {0, 0x20002, 0x40002, 0x40004, 0x80006, 0x40002, 0x80006};
Damien Zammit003d15c2015-11-20 17:17:51 +11001506
Angel Pons39ff7032020-03-09 21:39:44 +01001507 TABLE u16 tolud[7] = {2048, 2048, 4096, 4096, 8192, 4096, 8192};
1508 TABLE u16 tom[7] = { 2, 2, 4, 4, 8, 4, 8};
1509 TABLE u16 touud[7] = { 128, 128, 256, 256, 512, 256, 512};
1510 TABLE u32 gbsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1511 TABLE u32 bgsm[7] = {1 << 27, 1 << 27, 1 << 28, 1 << 27, 1 << 29, 1 << 28, 1 << 29};
1512 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 +11001513
1514 if ((s->dimm_config[0] < 3) && rank_is_populated(s->dimms, 0, 0)) {
1515 if (s->dimms[0].sides > 1) {
1516 // 2R/NC
Angel Pons0aeaee72021-03-26 17:57:46 +01001517 mchbar_clrsetbits32(C0CKECTRL, 1, 0x300001);
1518 mchbar_write32(C0DRA01, 0x00000101);
1519 mchbar_write32(C0DRB0, 0x00040002);
1520 mchbar_write32(C0DRB2, w204[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001521 } else {
1522 // 1R/NC
Angel Pons0aeaee72021-03-26 17:57:46 +01001523 mchbar_clrsetbits32(C0CKECTRL, 1, 0x100001);
1524 mchbar_write32(C0DRA01, 0x00000001);
1525 mchbar_write32(C0DRB0, 0x00020002);
1526 mchbar_write32(C0DRB2, w204[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001527 }
1528 } else if ((s->dimm_config[0] == 5) && rank_is_populated(s->dimms, 0, 0)) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001529 mchbar_clrsetbits32(C0CKECTRL, 1, 0x300001);
1530 mchbar_write32(C0DRA01, 0x00000101);
1531 mchbar_write32(C0DRB0, 0x00040002);
1532 mchbar_write32(C0DRB2, 0x00040004);
Damien Zammit003d15c2015-11-20 17:17:51 +11001533 } else {
Angel Pons0aeaee72021-03-26 17:57:46 +01001534 mchbar_clrsetbits32(C0CKECTRL, 1, w260[s->dimm_config[0]]);
1535 mchbar_write32(C0DRA01, w208[s->dimm_config[0]]);
1536 mchbar_write32(C0DRB0, w200[s->dimm_config[0]]);
1537 mchbar_write32(C0DRB2, w204[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001538 }
Angel Pons39ff7032020-03-09 21:39:44 +01001539 pci_write_config16(HOST_BRIDGE, 0xb0, tolud[s->dimm_config[0]]);
1540 pci_write_config16(HOST_BRIDGE, 0xa0, tom[s->dimm_config[0]]);
1541 pci_write_config16(HOST_BRIDGE, 0xa2, touud[s->dimm_config[0]]);
1542 pci_write_config32(HOST_BRIDGE, 0xa4, gbsm[s->dimm_config[0]]);
1543 pci_write_config32(HOST_BRIDGE, 0xa8, bgsm[s->dimm_config[0]]);
1544 pci_write_config32(HOST_BRIDGE, 0xac, tsegmb[s->dimm_config[0]]);
Damien Zammit003d15c2015-11-20 17:17:51 +11001545}
1546
Damien Zammit003d15c2015-11-20 17:17:51 +11001547static u8 sdram_checkrcompoverride(void)
1548{
1549 u32 xcomp;
1550 u8 aa, bb, a, b, c, d;
1551
Angel Pons0aeaee72021-03-26 17:57:46 +01001552 xcomp = mchbar_read32(XCOMP);
Damien Zammit003d15c2015-11-20 17:17:51 +11001553 a = (u8)((xcomp & 0x7f000000) >> 24);
Angel Pons39ff7032020-03-09 21:39:44 +01001554 b = (u8)((xcomp & 0x007f0000) >> 16);
1555 c = (u8)((xcomp & 0x00003f00) >> 8);
1556 d = (u8)((xcomp & 0x0000003f) >> 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001557
1558 if (a > b) {
1559 aa = a - b;
1560 } else {
1561 aa = b - a;
1562 }
1563 if (c > d) {
1564 bb = c - d;
1565 } else {
1566 bb = d - c;
1567 }
Angel Pons39ff7032020-03-09 21:39:44 +01001568 if ((aa > 18) || (bb > 7) || (a <= 5) || (b <= 5) || (c <= 5) || (d <= 5) ||
Damien Zammit003d15c2015-11-20 17:17:51 +11001569 (a >= 0x7a) || (b >= 0x7a) || (c >= 0x3a) || (d >= 0x3a)) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001570 mchbar_write32(RCMEASBUFXOVR, 0x9718a729);
Damien Zammit003d15c2015-11-20 17:17:51 +11001571 return 1;
1572 }
1573 return 0;
1574}
1575
1576static void sdram_rcompupdate(struct sysinfo *s)
1577{
1578 u8 i, ok;
1579 u32 reg32a, reg32b;
1580
1581 ok = 0;
Angel Pons0aeaee72021-03-26 17:57:46 +01001582 mchbar_clrbits8(XCOMPDFCTRL, 1 << 3);
1583 mchbar_clrbits8(COMPCTRL1, 1 << 7);
Damien Zammit003d15c2015-11-20 17:17:51 +11001584 for (i = 0; i < 3; i++) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001585 mchbar_setbits8(COMPCTRL1, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001586 hpet_udelay(1000);
Angel Pons0aeaee72021-03-26 17:57:46 +01001587 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
Angel Pons39ff7032020-03-09 21:39:44 +01001588 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001589 ok |= sdram_checkrcompoverride();
1590 }
1591 if (!ok) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001592 reg32a = mchbar_read32(XCOMP);
Angel Pons39ff7032020-03-09 21:39:44 +01001593 reg32b = ((reg32a >> 16) & 0x0000ffff);
Damien Zammit003d15c2015-11-20 17:17:51 +11001594 reg32a = ((reg32a << 16) & 0xffff0000) | reg32b;
1595 reg32a |= (1 << 31) | (1 << 15);
Angel Pons0aeaee72021-03-26 17:57:46 +01001596 mchbar_write32(RCMEASBUFXOVR, reg32a);
Damien Zammit003d15c2015-11-20 17:17:51 +11001597 }
Angel Pons0aeaee72021-03-26 17:57:46 +01001598 mchbar_setbits8(COMPCTRL1, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001599 hpet_udelay(1000);
Angel Pons0aeaee72021-03-26 17:57:46 +01001600 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
Angel Pons39ff7032020-03-09 21:39:44 +01001601 ;
Damien Zammit003d15c2015-11-20 17:17:51 +11001602}
1603
1604static void __attribute__((noinline))
1605sdram_jedec(struct sysinfo *s, u8 rank, u8 jmode, u16 jval)
1606{
1607 u32 reg32;
1608
1609 reg32 = jval << 3;
Angel Pons39ff7032020-03-09 21:39:44 +01001610 reg32 |= rank * (1 << 27);
Angel Pons0aeaee72021-03-26 17:57:46 +01001611 mchbar_clrsetbits8(C0JEDEC, 0x3e, jmode);
Elyes Haouasa361d352022-12-03 13:33:48 +01001612 read32p(reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +11001613 barrier();
1614 hpet_udelay(1); // 1us
1615}
1616
1617static void sdram_zqcl(struct sysinfo *s)
1618{
1619 if (s->boot_path == BOOT_PATH_RESUME) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001620 mchbar_setbits32(C0CKECTRL, 1 << 27);
1621 mchbar_clrsetbits8(C0JEDEC, 0x0e, NORMAL_OP_CMD);
1622 mchbar_clrbits8(C0JEDEC, 3 << 4);
1623 mchbar_clrsetbits32(C0REFRCTRL2, 3 << 30, 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11001624 }
1625}
1626
1627static void sdram_jedecinit(struct sysinfo *s)
1628{
1629 u8 r, i, ch;
1630 u16 reg16, mrs, rttnom;
1631 struct jedeclist {
1632 char debug[15];
1633 u8 cmd;
1634 u16 val;
1635 };
1636
Arthur Heymans6bf13012017-06-10 12:03:27 +02001637 static const struct jedeclist jedec[12] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001638 { " NOP ", NOP_CMD, 0 },
1639 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1640 { " EMRS2 ", EMRS2_CMD, 0 },
1641 { " EMRS3 ", EMRS3_CMD, 0 },
1642 { " EMRS1 ", EMRS1_CMD, 0 },
1643 { " DLL RESET ", MRS_CMD, (1 << 8) },
1644 { " PRE CHARGE ", PRE_CHARGE_CMD, 0 },
1645 { " AUTOREFRESH", CBR_CMD, 0 },
1646 { " AUTOREFRESH", CBR_CMD, 0 },
1647 { " INITIALISE ", MRS_CMD, 0 },
1648 { " EMRS1 OCD ", EMRS1_CMD, (1 << 9) | (1 << 8) | (1 << 7) },
1649 { " EMRS1 EXIT ", EMRS1_CMD, 0 }
1650 };
1651
1652 mrs = (s->selected_timings.CAS << 4) |
Angel Pons39ff7032020-03-09 21:39:44 +01001653 ((s->selected_timings.tWR - 1) << 9) | (1 << 3) | (1 << 1) | 3;
1654
Damien Zammit003d15c2015-11-20 17:17:51 +11001655 rttnom = (1 << 2);
1656 if (rank_is_populated(s->dimms, 0, 0) && rank_is_populated(s->dimms, 0, 2)) {
1657 rttnom |= (1 << 6);
1658 }
1659
1660 hpet_udelay(200); // 200us
1661 reg16 = 0;
1662 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1663 for (i = 0; i < 12; i++) {
1664 PRINTK_DEBUG("Rank:%d Jedec:%14s...", r, jedec[i].debug);
1665 reg16 = jedec[i].val;
1666 switch (jedec[i].cmd) {
1667 case EMRS1_CMD:
1668 reg16 |= rttnom;
1669 break;
1670 case MRS_CMD:
1671 reg16 |= mrs;
1672 break;
1673 default:
1674 break;
1675 }
1676 sdram_jedec(s, r, jedec[i].cmd, reg16);
1677 PRINTK_DEBUG("done\n");
1678 }
1679 }
1680}
1681
1682static void sdram_misc(struct sysinfo *s)
1683{
1684 u32 reg32;
1685
1686 reg32 = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001687 reg32 |= (4 << 13);
1688 reg32 |= (6 << 8);
Angel Pons0aeaee72021-03-26 17:57:46 +01001689 mchbar_clrsetbits32(C0DYNRDCTRL, 0x3ff << 8, reg32);
1690 mchbar_clrbits8(C0DYNRDCTRL, 1 << 7);
1691 mchbar_setbits8(C0REFRCTRL + 3, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001692 if (s->boot_path != BOOT_PATH_RESUME) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001693 mchbar_clrsetbits8(C0JEDEC, 0x0e, NORMAL_OP_CMD);
1694 mchbar_clrbits8(C0JEDEC, 3 << 4);
Damien Zammit003d15c2015-11-20 17:17:51 +11001695 } else {
1696 sdram_zqcl(s);
1697 }
1698}
1699
1700static void sdram_checkreset(void)
1701{
1702 u8 pmcon2, pmcon3, reset;
1703
1704 pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
1705 pmcon3 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
1706 pmcon3 &= ~0x2;
1707 if (pmcon2 & 0x80) {
1708 pmcon2 &= ~0x80;
1709 reset = 1;
1710 } else {
1711 pmcon2 |= 0x80;
1712 reset = 0;
1713 }
1714 if (pmcon2 & 0x4) {
1715 pmcon2 |= 0x4;
1716 pmcon3 = (pmcon3 & ~0x30) | 0x30;
1717 pmcon3 |= (1 << 3);
1718 }
1719 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
1720 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, pmcon3);
Elyes HAOUAS1bc7b6e2019-05-05 16:29:41 +02001721 if (reset)
1722 full_reset();
Damien Zammit003d15c2015-11-20 17:17:51 +11001723}
1724
1725static void sdram_dradrb(struct sysinfo *s)
1726{
1727 u8 i, reg8, ch, r;
1728 u32 reg32, ind, c0dra, c0drb, dra;
1729 u16 addr;
1730 i = 0;
Arthur Heymans6bf13012017-06-10 12:03:27 +02001731 static const u8 dratab[2][2][2][4] =
Damien Zammit003d15c2015-11-20 17:17:51 +11001732 {{
1733 {
1734 {0xff, 0xff, 0xff, 0xff},
1735 {0xff, 0x00, 0x02, 0xff}
1736 },
1737 {
1738 {0xff, 0x01, 0xff, 0xff},
1739 {0xff, 0x03, 0xff, 0x06}
1740 }
1741 },
1742 {
1743 {
1744 {0xff, 0xff, 0xff, 0xff},
1745 {0xff, 0x04, 0x06, 0x08}
1746 },
1747 {
1748 {0xff, 0xff, 0xff, 0xff},
1749 {0x05, 0x07, 0x09, 0xff}
1750 }
1751 }};
1752
Arthur Heymans6bf13012017-06-10 12:03:27 +02001753 static const u8 dradrb[10][6] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11001754 //Row Col Bank Width DRB
1755 {0x01, 0x01, 0x00, 0x08, 0, 0x04},
1756 {0x01, 0x00, 0x00, 0x10, 0, 0x02},
1757 {0x02, 0x01, 0x00, 0x08, 1, 0x08},
1758 {0x01, 0x01, 0x00, 0x10, 1, 0x04},
1759 {0x01, 0x01, 0x01, 0x08, 1, 0x08},
1760 {0x00, 0x01, 0x01, 0x10, 1, 0x04},
1761 {0x02, 0x01, 0x01, 0x08, 2, 0x10},
1762 {0x01, 0x01, 0x01, 0x10, 2, 0x08},
1763 {0x03, 0x01, 0x01, 0x08, 3, 0x20},
1764 {0x02, 0x01, 0x01, 0x10, 3, 0x10},
1765 };
1766
1767 reg32 = 0;
1768 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1769 i = r / 2;
1770 PRINTK_DEBUG("RANK %d PRESENT\n", r);
Angel Pons39ff7032020-03-09 21:39:44 +01001771 dra = dratab
1772 [s->dimms[i].banks]
Damien Zammit003d15c2015-11-20 17:17:51 +11001773 [s->dimms[i].width]
1774 [s->dimms[i].cols - 9]
1775 [s->dimms[i].rows - 12];
1776
1777 if (s->dimms[i].banks == 1) {
1778 dra |= (1 << 7);
1779 }
Angel Pons39ff7032020-03-09 21:39:44 +01001780 reg32 |= (dra << (r * 8));
Damien Zammit003d15c2015-11-20 17:17:51 +11001781 }
Angel Pons0aeaee72021-03-26 17:57:46 +01001782 mchbar_write32(C0DRA01, reg32);
Damien Zammit003d15c2015-11-20 17:17:51 +11001783 c0dra = reg32;
1784 PRINTK_DEBUG("C0DRA = 0x%08x\n", c0dra);
1785
1786 reg32 = 0;
1787 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
1788 reg32 |= (1 << r);
1789 }
1790 reg8 = (u8)(reg32 << 4) & 0xf0;
Angel Pons0aeaee72021-03-26 17:57:46 +01001791 mchbar_clrsetbits8(C0CKECTRL + 2, 0xf0, reg8);
Angel Pons39ff7032020-03-09 21:39:44 +01001792
1793 if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0) || ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001794 mchbar_setbits8(C0CKECTRL, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001795 }
1796
Angel Pons39ff7032020-03-09 21:39:44 +01001797 addr = C0DRB0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001798 c0drb = 0;
1799 FOR_EACH_RANK(ch, r) {
1800 if (rank_is_populated(s->dimms, ch, r)) {
Angel Pons39ff7032020-03-09 21:39:44 +01001801 ind = (c0dra >> (8 * r)) & 0x7f;
Damien Zammit003d15c2015-11-20 17:17:51 +11001802 c0drb = (u16)(c0drb + dradrb[ind][5]);
1803 s->channel_capacity[0] += dradrb[ind][5] << 6;
1804 }
Angel Pons0aeaee72021-03-26 17:57:46 +01001805 mchbar_write16(addr, c0drb);
Damien Zammit003d15c2015-11-20 17:17:51 +11001806 addr += 2;
1807 }
1808 printk(BIOS_DEBUG, "Total memory = %dMB\n", s->channel_capacity[0]);
1809}
1810
1811static u8 sampledqs(u32 dqshighaddr, u32 strobeaddr, u8 highlow, u8 count)
1812{
Damien Zammit003d15c2015-11-20 17:17:51 +11001813 u8 dqsmatches = 1;
1814 while (count--) {
Angel Pons0aeaee72021-03-26 17:57:46 +01001815 mchbar_clrbits8(C0RSTCTL, 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001816 hpet_udelay(1);
Angel Pons0aeaee72021-03-26 17:57:46 +01001817 mchbar_setbits8(C0RSTCTL, 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001818 hpet_udelay(1);
1819 barrier();
Elyes Haouasa361d352022-12-03 13:33:48 +01001820 read32p(strobeaddr);
Damien Zammit003d15c2015-11-20 17:17:51 +11001821 barrier();
1822 hpet_udelay(1);
1823
Angel Pons0aeaee72021-03-26 17:57:46 +01001824 if (((mchbar_read8(dqshighaddr) & (1 << 6)) >> 6) != highlow) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001825 dqsmatches = 0;
1826 }
1827 }
1828
1829 return dqsmatches;
1830}
1831
Angel Pons39ff7032020-03-09 21:39:44 +01001832static void rcvenclock(u8 *coarse, u8 *medium, u8 lane)
Damien Zammit003d15c2015-11-20 17:17:51 +11001833{
1834 if (*medium < 3) {
1835 (*medium)++;
Angel Pons11cabea2021-03-26 22:41:54 +01001836 mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001837 } else {
1838 *medium = 0;
1839 (*coarse)++;
Angel Pons0aeaee72021-03-26 17:57:46 +01001840 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, *coarse << 16);
Angel Pons11cabea2021-03-26 22:41:54 +01001841 mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), *medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001842 }
1843}
1844
1845static void sdram_rcven(struct sysinfo *s)
1846{
Angel Pons39ff7032020-03-09 21:39:44 +01001847 u8 coarse, savecoarse;
1848 u8 medium, savemedium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001849 u8 pi, savepi;
Angel Pons39ff7032020-03-09 21:39:44 +01001850 u8 lane;
1851 u8 lanecoarse[8] = {0};
1852 u8 minlanecoarse = 0xff;
1853 u8 offset;
1854 u8 maxlane = 8;
Arthur Heymans015339f2018-08-20 11:28:58 +02001855 /* Since dra/drb is already set up we know that at address 0x00000000
1856 we will always find the first available rank */
1857 u32 strobeaddr = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001858 u32 dqshighaddr;
1859
Angel Pons0aeaee72021-03-26 17:57:46 +01001860 mchbar_clrbits8(C0RSTCTL, 3 << 2);
1861 mchbar_clrbits8(CMNDQFIFORST, 1 << 7);
Damien Zammit003d15c2015-11-20 17:17:51 +11001862
1863 PRINTK_DEBUG("rcven 0\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001864 for (lane = 0; lane < maxlane; lane++) {
1865 PRINTK_DEBUG("rcven lane %d\n", lane);
1866// trylaneagain:
1867 dqshighaddr = C0MISCCTLy(lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001868
Angel Pons39ff7032020-03-09 21:39:44 +01001869 coarse = s->selected_timings.CAS + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11001870 pi = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01001871 medium = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11001872
Angel Pons0aeaee72021-03-26 17:57:46 +01001873 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
Angel Pons11cabea2021-03-26 22:41:54 +01001874 mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001875
Angel Pons0aeaee72021-03-26 17:57:46 +01001876 mchbar_clrbits8(C0RXRCVyDLL(lane), 0x3f);
Angel Pons39ff7032020-03-09 21:39:44 +01001877
1878 savecoarse = coarse;
1879 savemedium = medium;
Damien Zammit003d15c2015-11-20 17:17:51 +11001880 savepi = pi;
1881
1882 PRINTK_DEBUG("rcven 0.1\n");
1883
Angel Pons39ff7032020-03-09 21:39:44 +01001884 // XXX comment out
Angel Pons11cabea2021-03-26 22:41:54 +01001885 // mchbar_clrsetbits16(C0RCVMISCCTL1, 3 << (lane * 2), 1 << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001886
1887 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001888 // printk(BIOS_DEBUG, "coarse=%d medium=%d\n", coarse, medium);
1889 rcvenclock(&coarse, &medium, lane);
1890 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001891 PRINTK_DEBUG("Error: coarse > 0xf\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001892 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001893 break;
1894 }
1895 }
1896 PRINTK_DEBUG("rcven 0.2\n");
1897
Angel Pons39ff7032020-03-09 21:39:44 +01001898 savecoarse = coarse;
1899 savemedium = medium;
1900 rcvenclock(&coarse, &medium, lane);
Damien Zammit003d15c2015-11-20 17:17:51 +11001901
1902 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001903 savecoarse = coarse;
1904 savemedium = medium;
1905 rcvenclock(&coarse, &medium, lane);
1906 if (coarse > 0xf) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001907 PRINTK_DEBUG("Error: coarse > 0xf\n");
1908 //goto trylaneagain;
1909 break;
1910 }
1911 }
1912
1913 PRINTK_DEBUG("rcven 0.3\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001914 coarse = savecoarse;
1915 medium = savemedium;
Angel Pons0aeaee72021-03-26 17:57:46 +01001916 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
Angel Pons11cabea2021-03-26 22:41:54 +01001917 mchbar_clrsetbits16(C0RCVMISCCTL2, 3 << (lane * 2), medium << (lane * 2));
Damien Zammit003d15c2015-11-20 17:17:51 +11001918
1919 while (sampledqs(dqshighaddr, strobeaddr, 1, 3) == 0) {
1920 savepi = pi;
1921 pi++;
1922 if (pi > s->maxpi) {
Angel Pons39ff7032020-03-09 21:39:44 +01001923 // if (s->nodll) {
Damien Zammit003d15c2015-11-20 17:17:51 +11001924 pi = savepi = s->maxpi;
1925 break;
Angel Pons39ff7032020-03-09 21:39:44 +01001926 // }
Damien Zammit003d15c2015-11-20 17:17:51 +11001927 }
Angel Pons0aeaee72021-03-26 17:57:46 +01001928 mchbar_clrsetbits8(C0RXRCVyDLL(lane), 0x3f, pi << s->pioffset);
Damien Zammit003d15c2015-11-20 17:17:51 +11001929 }
1930 PRINTK_DEBUG("rcven 0.4\n");
1931
1932 pi = savepi;
Angel Pons0aeaee72021-03-26 17:57:46 +01001933 mchbar_clrsetbits8(C0RXRCVyDLL(lane), 0x3f, pi << s->pioffset);
Angel Pons39ff7032020-03-09 21:39:44 +01001934 rcvenclock(&coarse, &medium, lane);
1935
Damien Zammit003d15c2015-11-20 17:17:51 +11001936 if (sampledqs(dqshighaddr, strobeaddr, 1, 1) == 0) {
1937 PRINTK_DEBUG("Error: DQS not high\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001938 // goto trylaneagain;
Damien Zammit003d15c2015-11-20 17:17:51 +11001939 }
1940 PRINTK_DEBUG("rcven 0.5\n");
1941 while (sampledqs(dqshighaddr, strobeaddr, 0, 3) == 0) {
Angel Pons39ff7032020-03-09 21:39:44 +01001942 coarse--;
Angel Pons0aeaee72021-03-26 17:57:46 +01001943 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, coarse << 16);
Angel Pons39ff7032020-03-09 21:39:44 +01001944 if (coarse == 0) {
Elyes HAOUAS3d450002018-08-09 18:55:58 +02001945 PRINTK_DEBUG("Error: DQS did not hit 0\n");
Damien Zammit003d15c2015-11-20 17:17:51 +11001946 break;
1947 }
1948 }
1949
1950 PRINTK_DEBUG("rcven 0.6\n");
Angel Pons39ff7032020-03-09 21:39:44 +01001951 rcvenclock(&coarse, &medium, lane);
1952 s->pi[lane] = pi;
1953 lanecoarse[lane] = coarse;
Damien Zammit003d15c2015-11-20 17:17:51 +11001954 }
1955
1956 PRINTK_DEBUG("rcven 1\n");
1957
Angel Pons39ff7032020-03-09 21:39:44 +01001958 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11001959 do {
Angel Pons39ff7032020-03-09 21:39:44 +01001960 lane--;
1961 if (minlanecoarse > lanecoarse[lane]) {
1962 minlanecoarse = lanecoarse[lane];
Damien Zammit003d15c2015-11-20 17:17:51 +11001963 }
Angel Pons39ff7032020-03-09 21:39:44 +01001964 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001965
Angel Pons39ff7032020-03-09 21:39:44 +01001966 lane = maxlane;
Damien Zammit003d15c2015-11-20 17:17:51 +11001967 do {
Angel Pons39ff7032020-03-09 21:39:44 +01001968 lane--;
1969 offset = lanecoarse[lane] - minlanecoarse;
Angel Pons11cabea2021-03-26 22:41:54 +01001970 mchbar_clrsetbits16(C0COARSEDLY0, 3 << (lane * 2), offset << (lane * 2));
Angel Pons39ff7032020-03-09 21:39:44 +01001971 } while (lane != 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11001972
Angel Pons0aeaee72021-03-26 17:57:46 +01001973 mchbar_clrsetbits32(C0STATRDCTRL, 0xf << 16, minlanecoarse << 16);
Damien Zammit003d15c2015-11-20 17:17:51 +11001974
Angel Pons39ff7032020-03-09 21:39:44 +01001975 s->coarsectrl = minlanecoarse;
Angel Pons0aeaee72021-03-26 17:57:46 +01001976 s->coarsedelay = mchbar_read16(C0COARSEDLY0);
1977 s->mediumphase = mchbar_read16(C0RCVMISCCTL2);
1978 s->readptrdelay = mchbar_read16(C0RCVMISCCTL1);
Damien Zammit003d15c2015-11-20 17:17:51 +11001979
1980 PRINTK_DEBUG("rcven 2\n");
Angel Pons0aeaee72021-03-26 17:57:46 +01001981 mchbar_clrbits8(C0RSTCTL, 7 << 1);
1982 mchbar_setbits8(C0RSTCTL, 1 << 1);
1983 mchbar_setbits8(C0RSTCTL, 1 << 2);
1984 mchbar_setbits8(C0RSTCTL, 1 << 3);
Damien Zammit003d15c2015-11-20 17:17:51 +11001985
Angel Pons0aeaee72021-03-26 17:57:46 +01001986 mchbar_setbits8(CMNDQFIFORST, 1 << 7);
1987 mchbar_clrbits8(CMNDQFIFORST, 1 << 7);
1988 mchbar_setbits8(CMNDQFIFORST, 1 << 7);
Damien Zammit003d15c2015-11-20 17:17:51 +11001989 PRINTK_DEBUG("rcven 3\n");
1990}
1991
Angel Pons39ff7032020-03-09 21:39:44 +01001992/* NOTE: Unless otherwise specified, the values are expressed in MiB */
Damien Zammit003d15c2015-11-20 17:17:51 +11001993static void sdram_mmap_regs(struct sysinfo *s)
1994{
1995 bool reclaim;
Angel Pons39ff7032020-03-09 21:39:44 +01001996 u32 mmiosize, tom, tolud, touud, reclaimbase, reclaimlimit;
1997 u32 gfxbase, gfxsize, gttbase, gttsize, tsegbase, tsegsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11001998 u16 ggc;
Angel Pons39ff7032020-03-09 21:39:44 +01001999 u16 ggc_to_uma[10] = {0, 1, 4, 8, 16, 32, 48, 64, 128, 256};
2000 u8 ggc_to_gtt[4] = {0, 1, 0, 0};
Damien Zammit003d15c2015-11-20 17:17:51 +11002001
Angel Pons39ff7032020-03-09 21:39:44 +01002002 reclaimbase = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002003 reclaimlimit = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002004
2005 ggc = pci_read_config16(HOST_BRIDGE, GGC);
Damien Zammit51fdb922016-01-18 18:34:52 +11002006 printk(BIOS_DEBUG, "GGC = 0x%04x\n", ggc);
Angel Pons39ff7032020-03-09 21:39:44 +01002007
2008 gfxsize = ggc_to_uma[(ggc & 0x00f0) >> 4];
2009
2010 gttsize = ggc_to_gtt[(ggc & 0x0300) >> 8];
2011
Damien Zammit003d15c2015-11-20 17:17:51 +11002012 tom = s->channel_capacity[0];
2013
Angel Pons39ff7032020-03-09 21:39:44 +01002014 /* With GTT always being 1M, TSEG 1M is the only setting that can
Arthur Heymansda44e342019-01-12 01:38:02 +01002015 be covered by SMRR which has alignment requirements. */
Angel Pons39ff7032020-03-09 21:39:44 +01002016 tsegsize = 1;
2017 mmiosize = 1024;
Damien Zammit003d15c2015-11-20 17:17:51 +11002018
2019 reclaim = false;
Angel Pons39ff7032020-03-09 21:39:44 +01002020 tolud = MIN(4096 - mmiosize, tom);
2021 if ((tom - tolud) > 64) {
Arthur Heymansaaebb412017-08-27 18:46:12 +02002022 reclaim = true;
Damien Zammit003d15c2015-11-20 17:17:51 +11002023 }
2024 if (reclaim) {
2025 tolud = tolud & ~0x3f;
Angel Pons39ff7032020-03-09 21:39:44 +01002026 tom = tom & ~0x3f;
2027 reclaimbase = MAX(4096, tom);
2028 reclaimlimit = reclaimbase + (MIN(4096, tom) - tolud) - 0x40;
Damien Zammit003d15c2015-11-20 17:17:51 +11002029 }
2030 touud = tom;
2031 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002032 touud = reclaimlimit + 64;
Damien Zammit003d15c2015-11-20 17:17:51 +11002033 }
2034
Angel Pons39ff7032020-03-09 21:39:44 +01002035 gfxbase = tolud - gfxsize;
2036 gttbase = gfxbase - gttsize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002037 tsegbase = gttbase - tsegsize;
2038
2039 /* Program the regs */
Angel Pons39ff7032020-03-09 21:39:44 +01002040 pci_write_config16(HOST_BRIDGE, TOLUD, (u16)(tolud << 4));
2041 pci_write_config16(HOST_BRIDGE, TOM, (u16)(tom >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002042 if (reclaim) {
Angel Pons39ff7032020-03-09 21:39:44 +01002043 pci_write_config16(HOST_BRIDGE, 0x98, (u16)(reclaimbase >> 6));
2044 pci_write_config16(HOST_BRIDGE, 0x9a, (u16)(reclaimlimit >> 6));
Damien Zammit003d15c2015-11-20 17:17:51 +11002045 }
Angel Pons39ff7032020-03-09 21:39:44 +01002046 pci_write_config16(HOST_BRIDGE, TOUUD, (u16)(touud));
2047 pci_write_config32(HOST_BRIDGE, GBSM, gfxbase << 20);
2048 pci_write_config32(HOST_BRIDGE, BGSM, gttbase << 20);
2049 pci_write_config32(HOST_BRIDGE, TSEG, tsegbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002050
Angel Pons39ff7032020-03-09 21:39:44 +01002051 u8 reg8 = pci_read_config8(HOST_BRIDGE, ESMRAMC);
2052 reg8 &= ~0x07;
Arthur Heymansda44e342019-01-12 01:38:02 +01002053 reg8 |= (0 << 1) | (1 << 0); /* 1M and TSEG_Enable */
Angel Pons39ff7032020-03-09 21:39:44 +01002054 pci_write_config8(HOST_BRIDGE, ESMRAMC, reg8);
Arthur Heymans4bdfebd2018-04-09 22:10:33 +02002055
Damien Zammit51fdb922016-01-18 18:34:52 +11002056 printk(BIOS_DEBUG, "GBSM (igd) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002057 pci_read_config32(HOST_BRIDGE, GBSM), gfxbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002058 printk(BIOS_DEBUG, "BGSM (gtt) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002059 pci_read_config32(HOST_BRIDGE, BGSM), gttbase << 20);
Damien Zammit51fdb922016-01-18 18:34:52 +11002060 printk(BIOS_DEBUG, "TSEG (smm) = verified %08x (written %08x)\n",
Angel Pons39ff7032020-03-09 21:39:44 +01002061 pci_read_config32(HOST_BRIDGE, TSEG), tsegbase << 20);
Damien Zammit003d15c2015-11-20 17:17:51 +11002062}
2063
2064static void sdram_enhancedmode(struct sysinfo *s)
2065{
Angel Pons39ff7032020-03-09 21:39:44 +01002066 u8 reg8, ch, r, fsb_freq, ddr_freq;
Damien Zammit003d15c2015-11-20 17:17:51 +11002067 u32 mask32, reg32;
Angel Pons0aeaee72021-03-26 17:57:46 +01002068 mchbar_setbits8(C0ADDCSCTRL, 1 << 0);
2069 mchbar_setbits8(C0REFRCTRL + 3, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002070 mask32 = (0x1f << 15) | (0x1f << 10) | (0x1f << 5) | 0x1f;
Angel Pons39ff7032020-03-09 21:39:44 +01002071 reg32 = (0x1e << 15) | (0x10 << 10) | (0x1e << 5) | 0x10;
Angel Pons0aeaee72021-03-26 17:57:46 +01002072 mchbar_clrsetbits32(WRWMCONFIG, mask32, reg32);
2073 mchbar_write8(C0DITCTRL + 1, 2);
2074 mchbar_write16(C0DITCTRL + 2, 0x0804);
2075 mchbar_write16(C0DITCTRL + 4, 0x2010);
2076 mchbar_write8(C0DITCTRL + 6, 0x40);
2077 mchbar_write16(C0DITCTRL + 8, 0x091c);
2078 mchbar_write8(C0DITCTRL + 10, 0xf2);
2079 mchbar_setbits8(C0BYPCTRL, 1 << 0);
2080 mchbar_setbits8(C0CWBCTRL, 1 << 0);
2081 mchbar_setbits16(C0ARBSPL, 1 << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11002082
Angel Pons26766fd2020-06-08 12:38:19 +02002083 pci_or_config8(HOST_BRIDGE, 0xf0, 1);
Angel Pons0aeaee72021-03-26 17:57:46 +01002084 mchbar_write32(SBCTL, 0x00000002);
2085 mchbar_write32(SBCTL2, 0x20310002);
2086 mchbar_write32(SLIMCFGTMG, 0x02020302);
2087 mchbar_write32(HIT0, 0x001f1806);
2088 mchbar_write32(HIT1, 0x01102800);
2089 mchbar_write32(HIT2, 0x07000000);
2090 mchbar_write32(HIT3, 0x01014010);
2091 mchbar_write32(HIT4, 0x0f038000);
Angel Pons26766fd2020-06-08 12:38:19 +02002092 pci_and_config8(HOST_BRIDGE, 0xf0, ~1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002093
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002094 u32 nranks, curranksize, maxranksize, dra;
2095 u8 rankmismatch;
Angel Pons39ff7032020-03-09 21:39:44 +01002096 static const u8 drbtab[10] = {0x4, 0x2, 0x8, 0x4, 0x8, 0x4, 0x10, 0x8, 0x20, 0x10};
Damien Zammit003d15c2015-11-20 17:17:51 +11002097
2098 nranks = 0;
2099 curranksize = 0;
2100 maxranksize = 0;
Damien Zammit003d15c2015-11-20 17:17:51 +11002101 rankmismatch = 0;
Angel Pons39ff7032020-03-09 21:39:44 +01002102
Damien Zammit003d15c2015-11-20 17:17:51 +11002103 FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {
2104 nranks++;
Elyes Haouas3a998072022-11-18 15:11:02 +01002105 dra = (u8)((mchbar_read32(C0DRA01) >> (8 * r)) & 0x7f);
Damien Zammit003d15c2015-11-20 17:17:51 +11002106 curranksize = drbtab[dra];
2107 if (maxranksize == 0) {
2108 maxranksize = curranksize;
Damien Zammit003d15c2015-11-20 17:17:51 +11002109 }
2110 if (curranksize != maxranksize) {
2111 rankmismatch = 1;
2112 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002113 }
2114
2115 reg8 = 0;
2116 switch (nranks) {
2117 case 4:
2118 if (rankmismatch) {
2119 reg8 = 0x64;
2120 } else {
2121 reg8 = 0xa4;
2122 }
2123 break;
2124 case 1:
2125 case 3:
2126 reg8 = 0x64;
2127 break;
2128 case 2:
2129 if (rankmismatch) {
2130 reg8 = 0x64;
2131 } else {
2132 reg8 = 0x24;
2133 }
2134 break;
2135 default:
2136 die("Invalid number of ranks found, halt\n");
2137 break;
2138 }
Angel Pons0aeaee72021-03-26 17:57:46 +01002139 mchbar_clrsetbits8(CHDECMISC, 0xfc, reg8 & 0xfc);
2140 mchbar_clrbits32(NOACFGBUSCTL, 1 << 31);
Damien Zammit003d15c2015-11-20 17:17:51 +11002141
Angel Pons0aeaee72021-03-26 17:57:46 +01002142 mchbar_write32(HTBONUS0, 0xf);
2143 mchbar_setbits8(C0COREBONUS + 4, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002144
Angel Pons0aeaee72021-03-26 17:57:46 +01002145 mchbar_clrbits32(HIT3, 7 << 25);
2146 mchbar_clrsetbits32(HIT4, 3 << 18, 1 << 18);
Angel Pons39ff7032020-03-09 21:39:44 +01002147
Damien Zammit003d15c2015-11-20 17:17:51 +11002148 u32 clkcx[2][2][3] = {
Angel Pons39ff7032020-03-09 21:39:44 +01002149 {
2150 {0x00000000, 0x0c080302, 0x08010204}, /* FSB = 667, DDR = 667 */
2151 {0x02040000, 0x08100102, 0x00000000}, /* FSB = 667, DDR = 800 */
2152 },
2153 {
2154 {0x18000000, 0x3021060c, 0x20010208}, /* FSB = 800, DDR = 667 */
2155 {0x00000000, 0x0c090306, 0x00000000}, /* FSB = 800, DDR = 800 */
2156 }
2157 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002158
Angel Pons39ff7032020-03-09 21:39:44 +01002159 fsb_freq = s->selected_timings.fsb_clock;
2160 ddr_freq = s->selected_timings.mem_clock;
2161
Angel Pons0aeaee72021-03-26 17:57:46 +01002162 mchbar_write32(CLKXSSH2X2MD + 0, clkcx[fsb_freq][ddr_freq][0]);
2163 mchbar_write32(CLKXSSH2X2MD + 4, clkcx[fsb_freq][ddr_freq][1]);
2164 mchbar_write32(CLKXSSH2MCBYP + 4, clkcx[fsb_freq][ddr_freq][2]);
Angel Pons39ff7032020-03-09 21:39:44 +01002165
Angel Pons0aeaee72021-03-26 17:57:46 +01002166 mchbar_clrbits8(HIT4, 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002167}
2168
2169static void sdram_periodic_rcomp(void)
2170{
Angel Pons0aeaee72021-03-26 17:57:46 +01002171 mchbar_clrbits8(COMPCTRL1, 1 << 1);
2172 while ((mchbar_read32(COMPCTRL1) & (1 << 31)) > 0) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002173 ;
2174 }
Angel Pons0aeaee72021-03-26 17:57:46 +01002175 mchbar_clrbits16(CSHRMISCCTL, 3 << 12);
2176 mchbar_setbits8(CMNDQFIFORST, 1 << 7);
2177 mchbar_clrsetbits16(XCOMPDFCTRL, 0x0f, 0x09);
Damien Zammit003d15c2015-11-20 17:17:51 +11002178
Angel Pons0aeaee72021-03-26 17:57:46 +01002179 mchbar_setbits8(COMPCTRL1, 1 << 7 | 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002180}
2181
2182static void sdram_new_trd(struct sysinfo *s)
2183{
2184 u8 pidelay, i, j, k, cc, trd_perphase[5];
Elyes HAOUAS0f49dd22019-04-23 22:12:10 +02002185 u8 bypass, freqgb, trd, reg8, txfifo;
Damien Zammit003d15c2015-11-20 17:17:51 +11002186 u32 reg32, datadelay, tio, rcvendelay, maxrcvendelay;
2187 u16 tmclk, thclk, buffertocore, postcalib;
Arthur Heymans6bf13012017-06-10 12:03:27 +02002188 static const u8 txfifo_lut[8] = { 0, 7, 6, 5, 2, 1, 4, 3 };
2189 static const u16 trd_adjust[2][2][5] = {
Damien Zammit003d15c2015-11-20 17:17:51 +11002190 {
2191 {3000, 3000, 0,0,0},
2192 {1000,2000,3000,1500,2500}
2193 },
2194 {
2195 {2000,1000,3000,0,0},
2196 {2500, 2500, 0,0,0}
2197 }};
2198
2199 freqgb = 110;
2200 buffertocore = 5000;
Damien Zammit003d15c2015-11-20 17:17:51 +11002201 postcalib = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 1250 : 500;
2202 tmclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2203 tmclk = tmclk * 100 / freqgb;
2204 thclk = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 6000 : 5000;
2205 switch (s->selected_timings.mem_clock) {
2206 case MEM_CLOCK_667MHz:
2207 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2208 cc = 2;
2209 } else {
2210 cc = 3;
2211 }
2212 break;
2213 default:
2214 case MEM_CLOCK_800MHz:
2215 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) {
2216 cc = 5;
2217 } else {
2218 cc = 2;
2219 }
2220 break;
2221 }
2222 tio = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 2700 : 3240;
2223 maxrcvendelay = 0;
2224 pidelay = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 24 : 20;
2225
2226 for (i = 0; i < 8; i++) {
Angel Pons39ff7032020-03-09 21:39:44 +01002227 rcvendelay = ((u32)((s->coarsedelay >> (i << 1)) & 3) * (u32)(tmclk));
2228 rcvendelay += ((u32)((s->readptrdelay >> (i << 1)) & 3) * (u32)(tmclk) / 2);
2229 rcvendelay += ((u32)((s->mediumphase >> (i << 1)) & 3) * (u32)(tmclk) / 4);
2230 rcvendelay += (u32)(pidelay * s->pi[i]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002231 maxrcvendelay = MAX(maxrcvendelay, rcvendelay);
2232 }
2233
Angel Pons0aeaee72021-03-26 17:57:46 +01002234 if ((mchbar_read8(HMBYPCP + 3) == 0xff) && (mchbar_read8(HMCCMC) & (1 << 7))) {
Damien Zammit003d15c2015-11-20 17:17:51 +11002235 bypass = 1;
2236 } else {
2237 bypass = 0;
2238 }
2239
2240 txfifo = 0;
Angel Pons0aeaee72021-03-26 17:57:46 +01002241 reg8 = (mchbar_read8(CSHRFIFOCTL) & 0x0e) >> 1;
Angel Pons39ff7032020-03-09 21:39:44 +01002242 txfifo = txfifo_lut[reg8] & 0x07;
Damien Zammit003d15c2015-11-20 17:17:51 +11002243
2244 datadelay = tmclk * (2*txfifo + 4*s->coarsectrl + 4*(bypass-1) + 13) / 4
2245 + tio + maxrcvendelay + pidelay + buffertocore + postcalib;
2246 if (s->async) {
2247 datadelay += tmclk / 2;
2248 }
2249
2250 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2251 k = (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz) ? 0 : 1;
2252
2253 if (j == 0 && k == 0) {
2254 datadelay -= 3084;
2255 }
2256
2257 trd = 0;
2258 for (i = 0; i < cc; i++) {
2259 reg32 = datadelay - (trd_adjust[k][j][i] * 100 / freqgb);
2260 trd_perphase[i] = (u8)(reg32 / thclk) - 2;
2261 trd_perphase[i] += 1;
2262 if (trd_perphase[i] > trd) {
2263 trd = trd_perphase[i];
2264 }
2265 }
2266
Angel Pons0aeaee72021-03-26 17:57:46 +01002267 mchbar_clrsetbits16(C0STATRDCTRL, 0x1f << 8, trd << 8);
Damien Zammit003d15c2015-11-20 17:17:51 +11002268}
2269
2270static void sdram_powersettings(struct sysinfo *s)
2271{
2272 u8 j;
2273 u32 reg32;
2274
2275 /* Thermal sensor */
Angel Pons0aeaee72021-03-26 17:57:46 +01002276 mchbar_write8(TSC1, 0x9b);
2277 mchbar_clrsetbits32(TSTTP, 0x00ffffff, 0x1d00);
2278 mchbar_write8(THERM1, 0x08);
2279 mchbar_write8(TSC3, 0);
2280 mchbar_clrsetbits8(TSC2, 0x0f, 0x04);
2281 mchbar_clrsetbits8(THERM1, 1, 1);
2282 mchbar_clrsetbits8(TCO, 1 << 7, 1 << 7);
Damien Zammit003d15c2015-11-20 17:17:51 +11002283
2284 /* Clock gating */
Angel Pons0aeaee72021-03-26 17:57:46 +01002285 mchbar_clrbits32(PMMISC, 1 << 18 | 1 << 0);
2286 mchbar_clrbits8(SBCTL3 + 3, 1 << 7);
2287 mchbar_clrbits8(CISDCTRL + 3, 1 << 7);
2288 mchbar_clrbits16(CICGDIS, 0x1fff);
2289 mchbar_clrbits32(SBCLKGATECTRL, 0x1ffff);
2290 mchbar_clrsetbits16(HICLKGTCTL, 0x03ff, 0x06);
2291 mchbar_clrsetbits32(HTCLKGTCTL, ~0, 0x20);
2292 mchbar_clrbits8(TSMISC, 1 << 0);
2293 mchbar_write8(C0WRDPYN, s->selected_timings.CAS - 1 + 0x15);
2294 mchbar_clrsetbits16(CLOCKGATINGI, 0x07fc, 0x0040);
2295 mchbar_clrsetbits16(CLOCKGATINGII, 0x0fff, 0x0d00);
2296 mchbar_clrbits16(CLOCKGATINGIII, 0x0d80);
2297 mchbar_write16(GTDPCGC + 2, 0xffff);
Damien Zammit003d15c2015-11-20 17:17:51 +11002298
2299 /* Sequencing */
Angel Pons0aeaee72021-03-26 17:57:46 +01002300 mchbar_clrsetbits32(HPWRCTL1, 0x1fffffff, 0x1f643fff);
2301 mchbar_clrsetbits32(HPWRCTL2, 0xffffff7f, 0x02010000);
2302 mchbar_clrsetbits16(HPWRCTL3, 7 << 12, 3 << 12);
Damien Zammit003d15c2015-11-20 17:17:51 +11002303
2304 /* Power */
Angel Pons0aeaee72021-03-26 17:57:46 +01002305 mchbar_clrsetbits32(GFXC3C4, 0xffff0003, 0x10100000);
2306 mchbar_clrsetbits32(PMDSLFRC, 0x0001bff7, 0x00000078);
Angel Pons39ff7032020-03-09 21:39:44 +01002307
2308 if (s->selected_timings.fsb_clock == FSB_CLOCK_667MHz)
Angel Pons0aeaee72021-03-26 17:57:46 +01002309 mchbar_clrsetbits16(PMMSPMRES, 0x03ff, 0x00c8);
Angel Pons39ff7032020-03-09 21:39:44 +01002310 else
Angel Pons0aeaee72021-03-26 17:57:46 +01002311 mchbar_clrsetbits16(PMMSPMRES, 0x03ff, 0x0100);
Angel Pons39ff7032020-03-09 21:39:44 +01002312
Damien Zammit003d15c2015-11-20 17:17:51 +11002313 j = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 0 : 1;
2314
Angel Pons0aeaee72021-03-26 17:57:46 +01002315 mchbar_clrsetbits32(PMCLKRC, 0x01fff37f, 0x10810700);
2316 mchbar_clrsetbits8(PMPXPRC, 7, 1);
2317 mchbar_clrbits8(PMBAK, 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002318
Angel Pons39ff7032020-03-09 21:39:44 +01002319 static const u16 ddr2lut[2][4][2] = {
2320 {
2321 {0x0000, 0x0000},
2322 {0x019A, 0x0039},
2323 {0x0099, 0x1049},
2324 {0x0000, 0x0000},
2325 },
2326 {
2327 {0x0000, 0x0000},
2328 {0x019A, 0x0039},
2329 {0x0099, 0x1049},
2330 {0x0099, 0x2159},
2331 },
2332 };
Damien Zammit003d15c2015-11-20 17:17:51 +11002333
Angel Pons0aeaee72021-03-26 17:57:46 +01002334 mchbar_write16(C0C2REG, 0x7a89);
2335 mchbar_write8(SHC2REGII, 0xaa);
2336 mchbar_write16(SHC2REGII + 1, ddr2lut[j][s->selected_timings.CAS - 3][1]);
2337 mchbar_clrsetbits16(SHC2REGI, 0x7fff, ddr2lut[j][s->selected_timings.CAS - 3][0]);
2338 mchbar_clrsetbits16(CLOCKGATINGIII, 0xf000, 0xf000);
2339 mchbar_clrsetbits8(CSHWRIOBONUSX, 0x77, 4 << 4 | 4);
Damien Zammit003d15c2015-11-20 17:17:51 +11002340
Angel Pons39ff7032020-03-09 21:39:44 +01002341 reg32 = s->nodll ? 0x30000000 : 0;
2342
Angel Pons11cabea2021-03-26 22:41:54 +01002343 mchbar_clrsetbits32(C0COREBONUS, 0xf << 24, 1 << 29 | reg32);
Angel Pons39ff7032020-03-09 21:39:44 +01002344
Angel Pons0aeaee72021-03-26 17:57:46 +01002345 mchbar_clrsetbits32(CLOCKGATINGI, 0xf << 20, 0xf << 20);
2346 mchbar_clrsetbits32(CLOCKGATINGII - 1, 0x001ff000, 0xbf << 20);
2347 mchbar_clrsetbits16(SHC3C4REG2, 0x1f7f, 0x0b << 8 | 7 << 4 | 0x0b);
2348 mchbar_write16(SHC3C4REG3, 0x3264);
2349 mchbar_clrsetbits16(SHC3C4REG4, 0x3f3f, 0x14 << 8 | 0x0a);
Angel Pons39ff7032020-03-09 21:39:44 +01002350
Angel Pons0aeaee72021-03-26 17:57:46 +01002351 mchbar_setbits32(C1COREBONUS, 1 << 31 | 1 << 13);
Damien Zammit003d15c2015-11-20 17:17:51 +11002352}
2353
2354static void sdram_programddr(void)
2355{
Angel Pons0aeaee72021-03-26 17:57:46 +01002356 mchbar_clrsetbits16(CLOCKGATINGII, 0x03ff, 0x0100);
2357 mchbar_clrsetbits16(CLOCKGATINGIII, 0x003f, 0x0010);
2358 mchbar_clrsetbits16(CLOCKGATINGI, 0x7000, 0x2000);
Angel Pons39ff7032020-03-09 21:39:44 +01002359
Angel Pons0aeaee72021-03-26 17:57:46 +01002360 mchbar_clrbits8(CSHRPDCTL, 7 << 1);
2361 mchbar_clrbits8(CSHRWRIOMLNS, 3 << 2);
2362 mchbar_clrbits8(C0MISCCTLy(0), 7 << 1);
2363 mchbar_clrbits8(C0MISCCTLy(1), 7 << 1);
2364 mchbar_clrbits8(C0MISCCTLy(2), 7 << 1);
2365 mchbar_clrbits8(C0MISCCTLy(3), 7 << 1);
2366 mchbar_clrbits8(C0MISCCTLy(4), 7 << 1);
2367 mchbar_clrbits8(C0MISCCTLy(5), 7 << 1);
2368 mchbar_clrbits8(C0MISCCTLy(6), 7 << 1);
2369 mchbar_clrbits8(C0MISCCTLy(7), 7 << 1);
2370 mchbar_clrbits8(CSHRWRIOMLNS, 1 << 1);
Angel Pons39ff7032020-03-09 21:39:44 +01002371
Angel Pons0aeaee72021-03-26 17:57:46 +01002372 mchbar_clrbits16(CSHRMISCCTL, 1 << 10);
2373 mchbar_clrbits16(CLOCKGATINGIII, 0x0dc0);
2374 mchbar_clrbits8(C0WRDPYN, 1 << 7);
2375 mchbar_clrbits32(C0COREBONUS, 1 << 22);
2376 mchbar_clrbits16(CLOCKGATINGI, 0x80fc);
2377 mchbar_clrbits16(CLOCKGATINGII, 0x0c00);
Angel Pons39ff7032020-03-09 21:39:44 +01002378
Angel Pons0aeaee72021-03-26 17:57:46 +01002379 mchbar_clrbits8(CSHRPDCTL, 0x0d);
2380 mchbar_clrbits8(C0MISCCTLy(0), 1 << 0);
2381 mchbar_clrbits8(C0MISCCTLy(1), 1 << 0);
2382 mchbar_clrbits8(C0MISCCTLy(2), 1 << 0);
2383 mchbar_clrbits8(C0MISCCTLy(3), 1 << 0);
2384 mchbar_clrbits8(C0MISCCTLy(4), 1 << 0);
2385 mchbar_clrbits8(C0MISCCTLy(5), 1 << 0);
2386 mchbar_clrbits8(C0MISCCTLy(6), 1 << 0);
2387 mchbar_clrbits8(C0MISCCTLy(7), 1 << 0);
Angel Pons39ff7032020-03-09 21:39:44 +01002388
Angel Pons0aeaee72021-03-26 17:57:46 +01002389 mchbar_clrsetbits32(C0STATRDCTRL, 7 << 20, 3 << 20);
2390 mchbar_clrbits32(C0COREBONUS, 1 << 20);
2391 mchbar_setbits8(C0DYNSLVDLLEN, 0x1e);
2392 mchbar_setbits8(C0DYNSLVDLLEN2, 0x03);
2393 mchbar_clrsetbits32(SHCYCTRKCKEL, 3 << 26, 1 << 26);
2394 mchbar_setbits16(C0STATRDCTRL, 3 << 13);
2395 mchbar_setbits32(C0CKECTRL, 1 << 16);
2396 mchbar_setbits8(C0COREBONUS, 1 << 4);
2397 mchbar_setbits32(CLOCKGATINGI - 1, 0xf << 24);
2398 mchbar_setbits8(CSHWRIOBONUS, 7);
2399 mchbar_setbits8(C0DYNSLVDLLEN, 3 << 6);
2400 mchbar_setbits8(SHC2REGIII, 7);
2401 mchbar_clrsetbits16(SHC2MINTM, ~0, 1 << 7);
2402 mchbar_clrsetbits8(SHC2IDLETM, 0xff, 0x10);
2403 mchbar_setbits16(C0COREBONUS, 0xf << 5);
2404 mchbar_setbits8(CSHWRIOBONUS, 3 << 3);
2405 mchbar_setbits8(CSHRMSTDYNDLLENB, 0x0d);
2406 mchbar_setbits16(SHC3C4REG1, 0x0a3f);
2407 mchbar_setbits8(C0STATRDCTRL, 3);
2408 mchbar_clrsetbits8(C0REFRCTRL2, 0xff, 0x4a);
2409 mchbar_clrbits8(C0COREBONUS + 4, 3 << 5);
2410 mchbar_setbits16(C0DYNSLVDLLEN, 0x0321);
Damien Zammit003d15c2015-11-20 17:17:51 +11002411}
2412
2413static void sdram_programdqdqs(struct sysinfo *s)
2414{
2415 u16 mdclk, tpi, refclk, dqdqs_out, dqdqs_outdelay, dqdqs_delay;
2416 u32 coretomcp, txdelay, tmaxunmask, tmaxpi;
2417 u8 repeat, halfclk, feature, reg8, push;
2418 u16 cwb, pimdclk;
2419 u32 reg32;
Angel Pons39ff7032020-03-09 21:39:44 +01002420 static const u8 txfifotab[8] = {0, 7, 6, 5, 2, 1, 4, 3};
Damien Zammit003d15c2015-11-20 17:17:51 +11002421
2422 tpi = 3000;
2423 dqdqs_out = 4382;
2424 dqdqs_outdelay = 5083;
2425 dqdqs_delay = 4692;
2426 coretomcp = 0;
2427 txdelay = 0;
2428 halfclk = 0;
2429 tmaxunmask = 0;
2430 tmaxpi = 0;
2431 repeat = 2;
2432 feature = 0;
2433 cwb = 0;
2434 pimdclk = 0;
2435 reg32 = 0;
2436 push = 0;
2437 reg8 = 0;
2438
2439 mdclk = (s->selected_timings.mem_clock == MEM_CLOCK_667MHz) ? 3000 : 2500;
2440 refclk = 3000 - mdclk;
2441
Angel Pons0aeaee72021-03-26 17:57:46 +01002442 coretomcp = ((mchbar_read8(C0ADDCSCTRL) >> 2) & 0x3) + 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002443 coretomcp *= mdclk;
2444
Angel Pons0aeaee72021-03-26 17:57:46 +01002445 reg8 = (mchbar_read8(CSHRFIFOCTL) & 0x0e) >> 1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002446
2447 while (repeat) {
2448 txdelay = mdclk * (
Angel Pons0aeaee72021-03-26 17:57:46 +01002449 ((mchbar_read16(C0GNT2LNCH1) >> 8) & 0x7) +
2450 (mchbar_read8(C0WRDATACTRL) & 0xf) +
2451 (mchbar_read8(C0WRDATACTRL + 1) & 0x1)
Damien Zammit003d15c2015-11-20 17:17:51 +11002452 ) +
Angel Pons39ff7032020-03-09 21:39:44 +01002453 txfifotab[reg8]*(mdclk / 2) +
Damien Zammit003d15c2015-11-20 17:17:51 +11002454 coretomcp +
2455 refclk +
2456 cwb;
Angel Pons0aeaee72021-03-26 17:57:46 +01002457 halfclk = (mchbar_read8(C0MISCCTL) >> 1) & 0x1;
Damien Zammit003d15c2015-11-20 17:17:51 +11002458 if (halfclk) {
2459 txdelay -= mdclk / 2;
2460 reg32 = dqdqs_outdelay + coretomcp - mdclk / 2;
2461 } else {
2462 reg32 = dqdqs_outdelay + coretomcp;
2463 }
2464
2465 tmaxunmask = txdelay - mdclk - dqdqs_out;
2466 tmaxpi = tmaxunmask - tpi;
2467
2468 if ((tmaxunmask >= reg32) && tmaxpi >= dqdqs_delay) {
2469 if (repeat == 2) {
Angel Pons0aeaee72021-03-26 17:57:46 +01002470 mchbar_clrbits32(C0COREBONUS, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +11002471 }
2472 feature = 1;
2473 repeat = 0;
2474 } else {
2475 repeat--;
Angel Pons0aeaee72021-03-26 17:57:46 +01002476 mchbar_setbits32(C0COREBONUS, 1 << 23);
Damien Zammit003d15c2015-11-20 17:17:51 +11002477 cwb = 2 * mdclk;
2478 }
2479 }
2480
2481 if (!feature) {
Angel Pons0aeaee72021-03-26 17:57:46 +01002482 mchbar_clrbits8(CLOCKGATINGI, 3);
Damien Zammit003d15c2015-11-20 17:17:51 +11002483 return;
2484 }
Angel Pons0aeaee72021-03-26 17:57:46 +01002485 mchbar_setbits8(CLOCKGATINGI, 3);
2486 mchbar_clrsetbits16(CLOCKGATINGIII, 0xf << 12, pimdclk << 12);
2487 mchbar_clrsetbits8(CSHWRIOBONUSX, 0x77, push << 4 | push);
2488 mchbar_clrsetbits32(C0COREBONUS, 0xf << 24, 3 << 24);
Damien Zammit003d15c2015-11-20 17:17:51 +11002489}
2490
2491/**
2492 * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3
2493 */
2494void sdram_initialize(int boot_path, const u8 *spd_addresses)
2495{
2496 struct sysinfo si;
Angel Pons39ff7032020-03-09 21:39:44 +01002497 const char *boot_str[] = {"Normal", "Reset", "Resume"};
Damien Zammit003d15c2015-11-20 17:17:51 +11002498
2499 PRINTK_DEBUG("Setting up RAM controller.\n");
2500
2501 memset(&si, 0, sizeof(si));
2502
2503 si.boot_path = boot_path;
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002504 printk(BIOS_DEBUG, "Boot path: %s\n", boot_str[boot_path]);
Damien Zammit003d15c2015-11-20 17:17:51 +11002505 si.spd_map[0] = spd_addresses[0];
2506 si.spd_map[1] = spd_addresses[1];
2507 si.spd_map[2] = spd_addresses[2];
2508 si.spd_map[3] = spd_addresses[3];
2509
2510 sdram_read_spds(&si);
2511
2512 /* Choose Common Frequency */
2513 sdram_detect_ram_speed(&si);
2514
2515 /* Determine smallest common tRAS, tRP, tRCD, etc */
2516 sdram_detect_smallest_params(&si);
2517
2518 /* Enable HPET */
2519 enable_hpet();
Damien Zammit003d15c2015-11-20 17:17:51 +11002520
Angel Pons0aeaee72021-03-26 17:57:46 +01002521 mchbar_setbits16(CPCTL, 1 << 15);
Damien Zammit003d15c2015-11-20 17:17:51 +11002522
Damien Zammit003d15c2015-11-20 17:17:51 +11002523 sdram_clk_crossing(&si);
2524
2525 sdram_checkreset();
2526 PRINTK_DEBUG("Done checkreset\n");
2527
2528 sdram_clkmode(&si);
2529 PRINTK_DEBUG("Done clkmode\n");
2530
2531 sdram_timings(&si);
2532 PRINTK_DEBUG("Done timings (dqs dll enabled)\n");
2533
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002534 if (si.boot_path != BOOT_PATH_RESET) {
2535 sdram_dlltiming(&si);
2536 PRINTK_DEBUG("Done dlltiming\n");
2537 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002538
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002539 if (si.boot_path != BOOT_PATH_RESET) {
2540 sdram_rcomp(&si);
2541 PRINTK_DEBUG("Done RCOMP\n");
2542 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002543
2544 sdram_odt(&si);
2545 PRINTK_DEBUG("Done odt\n");
2546
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002547 if (si.boot_path != BOOT_PATH_RESET) {
Angel Pons0aeaee72021-03-26 17:57:46 +01002548 while ((mchbar_read8(COMPCTRL1) & 1) != 0)
Arthur Heymans00fd3ff2017-04-17 17:50:40 +02002549 ;
2550 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002551
2552 sdram_mmap(&si);
2553 PRINTK_DEBUG("Done mmap\n");
2554
Angel Pons39ff7032020-03-09 21:39:44 +01002555 /* Enable DDR IO buffer */
Angel Pons0aeaee72021-03-26 17:57:46 +01002556 mchbar_clrsetbits8(C0IOBUFACTCTL, 0x3f, 0x08);
2557 mchbar_setbits8(C0RSTCTL, 1 << 0);
Damien Zammit003d15c2015-11-20 17:17:51 +11002558
2559 sdram_rcompupdate(&si);
2560 PRINTK_DEBUG("Done RCOMP update\n");
2561
Angel Pons0aeaee72021-03-26 17:57:46 +01002562 mchbar_setbits8(HIT4, 1 << 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002563
2564 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons0aeaee72021-03-26 17:57:46 +01002565 mchbar_setbits32(C0CKECTRL, 1 << 27);
Damien Zammit003d15c2015-11-20 17:17:51 +11002566
Arthur Heymansd2ca9d12017-04-22 16:19:56 +02002567 sdram_jedecinit(&si);
2568 PRINTK_DEBUG("Done MRS\n");
2569 }
Damien Zammit003d15c2015-11-20 17:17:51 +11002570
2571 sdram_misc(&si);
2572 PRINTK_DEBUG("Done misc\n");
2573
2574 sdram_zqcl(&si);
2575 PRINTK_DEBUG("Done zqcl\n");
2576
2577 if (si.boot_path != BOOT_PATH_RESUME) {
Angel Pons0aeaee72021-03-26 17:57:46 +01002578 mchbar_setbits32(C0REFRCTRL2, 3 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002579 }
2580
2581 sdram_dradrb(&si);
2582 PRINTK_DEBUG("Done dradrb\n");
2583
2584 sdram_rcven(&si);
2585 PRINTK_DEBUG("Done rcven\n");
2586
2587 sdram_new_trd(&si);
2588 PRINTK_DEBUG("Done tRD\n");
2589
2590 sdram_mmap_regs(&si);
2591 PRINTK_DEBUG("Done mmap regs\n");
2592
2593 sdram_enhancedmode(&si);
2594 PRINTK_DEBUG("Done enhanced mode\n");
2595
2596 sdram_powersettings(&si);
2597 PRINTK_DEBUG("Done power settings\n");
2598
2599 sdram_programddr();
2600 PRINTK_DEBUG("Done programming ddr\n");
2601
2602 sdram_programdqdqs(&si);
2603 PRINTK_DEBUG("Done programming dqdqs\n");
2604
2605 sdram_periodic_rcomp();
2606 PRINTK_DEBUG("Done periodic RCOMP\n");
2607
2608 /* Set init done */
Angel Pons0aeaee72021-03-26 17:57:46 +01002609 mchbar_setbits32(C0REFRCTRL2, 1 << 30);
Damien Zammit003d15c2015-11-20 17:17:51 +11002610
2611 /* Tell ICH7 that we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002612 pci_and_config8(PCI_DEV(0, 0x1f, 0), 0xa2, (u8)~(1 << 7));
Damien Zammit003d15c2015-11-20 17:17:51 +11002613
2614 /* Tell northbridge we're done */
Angel Pons26766fd2020-06-08 12:38:19 +02002615 pci_or_config8(HOST_BRIDGE, 0xf4, 1);
Damien Zammit003d15c2015-11-20 17:17:51 +11002616
2617 printk(BIOS_DEBUG, "RAM initialization finished.\n");
2618}