blob: a5a627672a65a59d361fa08493218670a933b3e5 [file] [log] [blame]
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Vladimir Serbinenko.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +010015 */
16
17/* Please don't remove this. It's needed it to do debugging
18 and reverse engineering to support in futur more nehalem variants. */
19#ifndef REAL
20#define REAL 1
21#endif
22
23#if REAL
Kyösti Mälkki931c1dc2014-06-30 09:40:19 +030024#include <stdlib.h>
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +010025#include <console/console.h>
26#include <string.h>
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +010027#include <arch/io.h>
28#include <cpu/x86/msr.h>
29#include <cbmem.h>
30#include <arch/cbfs.h>
31#include <cbfs.h>
32#include <ip_checksum.h>
33#include <pc80/mc146818rtc.h>
34#include <device/pci_def.h>
35#include <arch/cpu.h>
Patrick Georgi546953c2014-11-29 10:38:17 +010036#include <halt.h>
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +010037#include <spd.h>
38#include "raminit.h"
39#include <timestamp.h>
40#include <cpu/x86/mtrr.h>
41#include <cpu/intel/speedstep.h>
42#include <cpu/intel/turbo.h>
Alexander Couzens81c5c762016-03-09 03:13:45 +010043#include <northbridge/intel/common/mrc_cache.h>
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +010044#endif
45
46#if !REAL
47typedef unsigned char u8;
48typedef unsigned short u16;
49typedef unsigned int u32;
50typedef u32 device_t;
51#endif
52
53#include "nehalem.h"
54
55#include "southbridge/intel/ibexpeak/me.h"
56
57#if REAL
58#include <delay.h>
59#endif
60
61#define NORTHBRIDGE PCI_DEV(0, 0, 0)
62#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
63#define GMA PCI_DEV (0, 0x2, 0x0)
64#define HECIDEV PCI_DEV(0, 0x16, 0)
65#define HECIBAR 0x10
66
67#define FOR_ALL_RANKS \
68 for (channel = 0; channel < NUM_CHANNELS; channel++) \
69 for (slot = 0; slot < NUM_SLOTS; slot++) \
70 for (rank = 0; rank < NUM_RANKS; rank++)
71
72#define FOR_POPULATED_RANKS \
73 for (channel = 0; channel < NUM_CHANNELS; channel++) \
74 for (slot = 0; slot < NUM_SLOTS; slot++) \
75 for (rank = 0; rank < NUM_RANKS; rank++) \
76 if (info->populated_ranks[channel][slot][rank])
77
78#define FOR_POPULATED_RANKS_BACKWARDS \
79 for (channel = NUM_CHANNELS - 1; channel >= 0; channel--) \
80 for (slot = 0; slot < NUM_SLOTS; slot++) \
81 for (rank = 0; rank < NUM_RANKS; rank++) \
82 if (info->populated_ranks[channel][slot][rank])
83
84/* [REG_178][CHANNEL][2 * SLOT + RANK][LANE] */
85typedef struct {
86 u8 smallest;
87 u8 largest;
88} timing_bounds_t[2][2][2][9];
89
90struct ram_training {
91 /* [TM][CHANNEL][SLOT][RANK][LANE] */
92 u16 lane_timings[4][2][2][2][9];
93 u16 reg_178;
94 u16 reg_10b;
95
96 u8 reg178_center;
97 u8 reg178_smallest;
98 u8 reg178_largest;
99 timing_bounds_t timing_bounds[2];
100 u16 timing_offset[2][2][2][9];
101 u16 timing2_offset[2][2][2][9];
102 u16 timing2_bounds[2][2][2][9][2];
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +0100103 u8 reg274265[2][3]; /* [CHANNEL][REGISTER] */
104 u8 reg2ca9_bit0;
105 u32 reg_6dc;
106 u32 reg_6e8;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100107};
108
109#if !REAL
110#include "raminit_fake.c"
111#else
112
113#include <lib.h> /* Prototypes */
114
115static inline void write_mchbar32(u32 addr, u32 val)
116{
117 MCHBAR32(addr) = val;
118}
119
120static inline void write_mchbar16(u32 addr, u16 val)
121{
122 MCHBAR16(addr) = val;
123}
124
125static inline void write_mchbar8(u32 addr, u8 val)
126{
127 MCHBAR8(addr) = val;
128}
129
130
131static inline u32 read_mchbar32(u32 addr)
132{
133 return MCHBAR32(addr);
134}
135
136static inline u16 read_mchbar16(u32 addr)
137{
138 return MCHBAR16(addr);
139}
140
141static inline u8 read_mchbar8(u32 addr)
142{
143 return MCHBAR8(addr);
144}
145
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100146static void clflush(u32 addr)
147{
148 asm volatile ("clflush (%0)"::"r" (addr));
149}
150
151typedef struct _u128 {
152 u64 lo;
153 u64 hi;
154} u128;
155
156static void read128(u32 addr, u64 * out)
157{
158 u128 ret;
159 u128 stor;
160 asm volatile ("movdqu %%xmm0, %0\n"
161 "movdqa (%2), %%xmm0\n"
162 "movdqu %%xmm0, %1\n"
163 "movdqu %0, %%xmm0":"+m" (stor), "=m"(ret):"r"(addr));
164 out[0] = ret.lo;
165 out[1] = ret.hi;
166}
167
168#endif
169
170/* OK */
171static void write_1d0(u32 val, u16 addr, int bits, int flag)
172{
173 write_mchbar32(0x1d0, 0);
174 while (read_mchbar32(0x1d0) & 0x800000) ;
175 write_mchbar32(0x1d4,
176 (val & ((1 << bits) - 1)) | (2 << bits) | (flag <<
177 bits));
178 write_mchbar32(0x1d0, 0x40000000 | addr);
179 while (read_mchbar32(0x1d0) & 0x800000) ;
180}
181
182/* OK */
183static u16 read_1d0(u16 addr, int split)
184{
185 u32 val;
186 write_mchbar32(0x1d0, 0);
187 while (read_mchbar32(0x1d0) & 0x800000) ;
188 write_mchbar32(0x1d0,
189 0x80000000 | (((read_mchbar8(0x246) >> 2) & 3) +
190 0x361 - addr));
191 while (read_mchbar32(0x1d0) & 0x800000) ;
192 val = read_mchbar32(0x1d8);
193 write_1d0(0, 0x33d, 0, 0);
194 write_1d0(0, 0x33d, 0, 0);
195 val &= ((1 << split) - 1);
196 // printk (BIOS_ERR, "R1D0C [%x] => %x\n", addr, val);
197 return val;
198}
199
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800200static void write32p(uintptr_t addr, uint32_t val)
201{
202 write32((void *)addr, val);
203}
204
205static uint32_t read32p(uintptr_t addr)
206{
207 return read32((void *)addr);
208}
209
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100210static void sfence(void)
211{
212#if REAL
213 asm volatile ("sfence");
214#endif
215}
216
217static inline u16 get_lane_offset(int slot, int rank, int lane)
218{
219 return 0x124 * lane + ((lane & 4) ? 0x23e : 0) + 11 * rank + 22 * slot -
220 0x452 * (lane == 8);
221}
222
223static inline u16 get_timing_register_addr(int lane, int tm, int slot, int rank)
224{
225 const u16 offs[] = { 0x1d, 0xa8, 0xe6, 0x5c };
226 return get_lane_offset(slot, rank, lane) + offs[(tm + 3) % 4];
227}
228
229#if REAL
230static u32 gav_real(int line, u32 in)
231{
232 // printk (BIOS_DEBUG, "%d: GAV: %x\n", line, in);
233 return in;
234}
235
236#define gav(x) gav_real (__LINE__, (x))
237#endif
238struct raminfo {
239 u16 clock_speed_index; /* clock_speed (REAL, not DDR) / 133.(3) - 3 */
240 u16 fsb_frequency; /* in 1.(1)/2 MHz. */
241 u8 is_x16_module[2][2]; /* [CHANNEL][SLOT] */
242 u8 density[2][2]; /* [CHANNEL][SLOT] */
243 u8 populated_ranks[2][2][2]; /* [CHANNEL][SLOT][RANK] */
244 int rank_start[2][2][2];
245 u8 cas_latency;
246 u8 board_lane_delay[9];
247 u8 use_ecc;
248 u8 revision;
249 u8 max_supported_clock_speed_index;
250 u8 uma_enabled;
251 u8 spd[2][2][151]; /* [CHANNEL][SLOT][BYTE] */
252 u8 silicon_revision;
253 u8 populated_ranks_mask[2];
254 u8 max_slots_used_in_channel;
255 u8 mode4030[2];
256 u16 avg4044[2];
257 u16 max4048[2];
258 unsigned total_memory_mb;
259 unsigned interleaved_part_mb;
260 unsigned non_interleaved_part_mb;
261
262 u32 heci_bar;
263 u64 heci_uma_addr;
264 unsigned memory_reserved_for_heci_mb;
265
266 struct ram_training training;
267 u32 last_500_command[2];
268
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100269 u32 delay46_ps[2];
270 u32 delay54_ps[2];
271 u8 revision_flag_1;
272 u8 some_delay_1_cycle_floor;
273 u8 some_delay_2_halfcycles_ceil;
274 u8 some_delay_3_ps_rounded;
275
276 const struct ram_training *cached_training;
277};
278
279static void
280write_500(struct raminfo *info, int channel, u32 val, u16 addr, int bits,
281 int flag);
282
283/* OK */
284static u16
285read_500(struct raminfo *info, int channel, u16 addr, int split)
286{
287 u32 val;
288 info->last_500_command[channel] = 0x80000000;
289 write_mchbar32(0x500 + (channel << 10), 0);
290 while (read_mchbar32(0x500 + (channel << 10)) & 0x800000) ;
291 write_mchbar32(0x500 + (channel << 10),
292 0x80000000 |
293 (((read_mchbar8(0x246 + (channel << 10)) >> 2) &
294 3) + 0xb88 - addr));
295 while (read_mchbar32(0x500 + (channel << 10)) & 0x800000) ;
296 val = read_mchbar32(0x508 + (channel << 10));
297 return val & ((1 << split) - 1);
298}
299
300/* OK */
301static void
302write_500(struct raminfo *info, int channel, u32 val, u16 addr, int bits,
303 int flag)
304{
305 if (info->last_500_command[channel] == 0x80000000) {
306 info->last_500_command[channel] = 0x40000000;
307 write_500(info, channel, 0, 0xb61, 0, 0);
308 }
309 write_mchbar32(0x500 + (channel << 10), 0);
310 while (read_mchbar32(0x500 + (channel << 10)) & 0x800000) ;
311 write_mchbar32(0x504 + (channel << 10),
312 (val & ((1 << bits) - 1)) | (2 << bits) | (flag <<
313 bits));
314 write_mchbar32(0x500 + (channel << 10), 0x40000000 | addr);
315 while (read_mchbar32(0x500 + (channel << 10)) & 0x800000) ;
316}
317
318static int rw_test(int rank)
319{
320 const u32 mask = 0xf00fc33c;
321 int ok = 0xff;
322 int i;
323 for (i = 0; i < 64; i++)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800324 write32p((rank << 28) | (i << 2), 0);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100325 sfence();
326 for (i = 0; i < 64; i++)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800327 gav(read32p((rank << 28) | (i << 2)));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100328 sfence();
329 for (i = 0; i < 32; i++) {
330 u32 pat = (((mask >> i) & 1) ? 0xffffffff : 0);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800331 write32p((rank << 28) | (i << 3), pat);
332 write32p((rank << 28) | (i << 3) | 4, pat);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100333 }
334 sfence();
335 for (i = 0; i < 32; i++) {
336 u8 pat = (((mask >> i) & 1) ? 0xff : 0);
337 int j;
338 u32 val;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800339 gav(val = read32p((rank << 28) | (i << 3)));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100340 for (j = 0; j < 4; j++)
341 if (((val >> (j * 8)) & 0xff) != pat)
342 ok &= ~(1 << j);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800343 gav(val = read32p((rank << 28) | (i << 3) | 4));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100344 for (j = 0; j < 4; j++)
345 if (((val >> (j * 8)) & 0xff) != pat)
346 ok &= ~(16 << j);
347 }
348 sfence();
349 for (i = 0; i < 64; i++)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800350 write32p((rank << 28) | (i << 2), 0);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100351 sfence();
352 for (i = 0; i < 64; i++)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -0800353 gav(read32p((rank << 28) | (i << 2)));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100354
355 return ok;
356}
357
358static void
359program_timings(struct raminfo *info, u16 base, int channel, int slot, int rank)
360{
361 int lane;
362 for (lane = 0; lane < 8; lane++) {
363 write_500(info, channel,
364 base +
365 info->training.
366 lane_timings[2][channel][slot][rank][lane],
367 get_timing_register_addr(lane, 2, slot, rank), 9, 0);
368 write_500(info, channel,
369 base +
370 info->training.
371 lane_timings[3][channel][slot][rank][lane],
372 get_timing_register_addr(lane, 3, slot, rank), 9, 0);
373 }
374}
375
376static void write_26c(int channel, u16 si)
377{
378 write_mchbar32(0x26c + (channel << 10), 0x03243f35);
379 write_mchbar32(0x268 + (channel << 10), 0xcfc00000 | (si << 9));
380 write_mchbar16(0x2b9 + (channel << 10), si);
381}
382
383static u32 get_580(int channel, u8 addr)
384{
385 u32 ret;
386 gav(read_1d0(0x142, 3));
387 write_mchbar8(0x5ff, 0x0); /* OK */
388 write_mchbar8(0x5ff, 0x80); /* OK */
389 write_mchbar32(0x580 + (channel << 10), 0x8493c012 | addr);
390 write_mchbar8(0x580 + (channel << 10),
391 read_mchbar8(0x580 + (channel << 10)) | 1);
392 while (!((ret = read_mchbar32(0x580 + (channel << 10))) & 0x10000)) ;
393 write_mchbar8(0x580 + (channel << 10),
394 read_mchbar8(0x580 + (channel << 10)) & ~1);
395 return ret;
396}
397
398const int cached_config = 0;
399
400#define NUM_CHANNELS 2
401#define NUM_SLOTS 2
402#define NUM_RANKS 2
403#define RANK_SHIFT 28
404#define CHANNEL_SHIFT 10
405
406#include "raminit_tables.c"
407
408static void seq9(struct raminfo *info, int channel, int slot, int rank)
409{
410 int i, lane;
411
412 for (i = 0; i < 2; i++)
413 for (lane = 0; lane < 8; lane++)
414 write_500(info, channel,
415 info->training.lane_timings[i +
416 1][channel][slot]
417 [rank][lane], get_timing_register_addr(lane,
418 i + 1,
419 slot,
420 rank),
421 9, 0);
422
423 write_1d0(1, 0x103, 6, 1);
424 for (lane = 0; lane < 8; lane++)
425 write_500(info, channel,
426 info->training.
427 lane_timings[0][channel][slot][rank][lane],
428 get_timing_register_addr(lane, 0, slot, rank), 9, 0);
429
430 for (i = 0; i < 2; i++) {
431 for (lane = 0; lane < 8; lane++)
432 write_500(info, channel,
433 info->training.lane_timings[i +
434 1][channel][slot]
435 [rank][lane], get_timing_register_addr(lane,
436 i + 1,
437 slot,
438 rank),
439 9, 0);
440 gav(get_580(channel, ((i + 1) << 2) | (rank << 5)));
441 }
442
443 gav(read_1d0(0x142, 3)); // = 0x10408118
444 write_mchbar8(0x5ff, 0x0); /* OK */
445 write_mchbar8(0x5ff, 0x80); /* OK */
446 write_1d0(0x2, 0x142, 3, 1);
447 for (lane = 0; lane < 8; lane++) {
448 // printk (BIOS_ERR, "before: %x\n", info->training.lane_timings[2][channel][slot][rank][lane]);
449 info->training.lane_timings[2][channel][slot][rank][lane] =
450 read_500(info, channel,
451 get_timing_register_addr(lane, 2, slot, rank), 9);
452 //printk (BIOS_ERR, "after: %x\n", info->training.lane_timings[2][channel][slot][rank][lane]);
453 info->training.lane_timings[3][channel][slot][rank][lane] =
454 info->training.lane_timings[2][channel][slot][rank][lane] +
455 0x20;
456 }
457}
458
459static int count_ranks_in_channel(struct raminfo *info, int channel)
460{
461 int slot, rank;
462 int res = 0;
463 for (slot = 0; slot < NUM_SLOTS; slot++)
464 for (rank = 0; rank < NUM_SLOTS; rank++)
465 res += info->populated_ranks[channel][slot][rank];
466 return res;
467}
468
469static void
470config_rank(struct raminfo *info, int s3resume, int channel, int slot, int rank)
471{
472 int add;
473
474 write_1d0(0, 0x178, 7, 1);
475 seq9(info, channel, slot, rank);
476 program_timings(info, 0x80, channel, slot, rank);
477
478 if (channel == 0)
479 add = count_ranks_in_channel(info, 1);
480 else
481 add = 0;
482 if (!s3resume)
483 gav(rw_test(rank + add));
484 program_timings(info, 0x00, channel, slot, rank);
485 if (!s3resume)
486 gav(rw_test(rank + add));
487 if (!s3resume)
488 gav(rw_test(rank + add));
489 write_1d0(0, 0x142, 3, 1);
490 write_1d0(0, 0x103, 6, 1);
491
492 gav(get_580(channel, 0xc | (rank << 5)));
493 gav(read_1d0(0x142, 3));
494
495 write_mchbar8(0x5ff, 0x0); /* OK */
496 write_mchbar8(0x5ff, 0x80); /* OK */
497}
498
499static void set_4cf(struct raminfo *info, int channel, u8 val)
500{
501 gav(read_500(info, channel, 0x4cf, 4)); // = 0xc2300cf9
502 write_500(info, channel, val, 0x4cf, 4, 1);
503 gav(read_500(info, channel, 0x659, 4)); // = 0x80300839
504 write_500(info, channel, val, 0x659, 4, 1);
505 gav(read_500(info, channel, 0x697, 4)); // = 0x80300839
506 write_500(info, channel, val, 0x697, 4, 1);
507}
508
509static void set_334(int zero)
510{
511 int j, k, channel;
512 const u32 val3[] = { 0x2a2b2a2b, 0x26272627, 0x2e2f2e2f, 0x2a2b };
513 u32 vd8[2][16];
514
515 for (channel = 0; channel < NUM_CHANNELS; channel++) {
516 for (j = 0; j < 4; j++) {
517 u32 a = (j == 1) ? 0x29292929 : 0x31313131;
518 u32 lmask = (j == 3) ? 0xffff : 0xffffffff;
519 u16 c;
520 if ((j == 0 || j == 3) && zero)
521 c = 0;
522 else if (j == 3)
523 c = 0x5f;
524 else
525 c = 0x5f5f;
526
527 for (k = 0; k < 2; k++) {
528 write_mchbar32(0x138 + 8 * k,
529 (channel << 26) | (j << 24));
530 gav(vd8[1][(channel << 3) | (j << 1) | k] =
531 read_mchbar32(0x138 + 8 * k));
532 gav(vd8[0][(channel << 3) | (j << 1) | k] =
533 read_mchbar32(0x13c + 8 * k));
534 }
535
536 write_mchbar32(0x334 + (channel << 10) + (j * 0x44),
537 zero ? 0 : val3[j]);
538 write_mchbar32(0x32c + (channel << 10) + (j * 0x44),
539 zero ? 0 : (0x18191819 & lmask));
540 write_mchbar16(0x34a + (channel << 10) + (j * 0x44), c);
541 write_mchbar32(0x33c + (channel << 10) + (j * 0x44),
542 zero ? 0 : (a & lmask));
543 write_mchbar32(0x344 + (channel << 10) + (j * 0x44),
544 zero ? 0 : (a & lmask));
545 }
546 }
547
548 write_mchbar32(0x130, read_mchbar32(0x130) | 1); /* OK */
549 while (read_mchbar8(0x130) & 1) ; /* OK */
550}
551
552static void rmw_1d0(u16 addr, u32 and, u32 or, int split, int flag)
553{
554 u32 v;
555 v = read_1d0(addr, split);
556 write_1d0((v & and) | or, addr, split, flag);
557}
558
559static int find_highest_bit_set(u16 val)
560{
561 int i;
562 for (i = 15; i >= 0; i--)
563 if (val & (1 << i))
564 return i;
565 return -1;
566}
567
568static int find_lowest_bit_set32(u32 val)
569{
570 int i;
571 for (i = 0; i < 32; i++)
572 if (val & (1 << i))
573 return i;
574 return -1;
575}
576
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100577enum {
578 DEVICE_TYPE = 2,
579 MODULE_TYPE = 3,
580 DENSITY = 4,
581 RANKS_AND_DQ = 7,
582 MEMORY_BUS_WIDTH = 8,
583 TIMEBASE_DIVIDEND = 10,
584 TIMEBASE_DIVISOR = 11,
585 CYCLETIME = 12,
586
587 CAS_LATENCIES_LSB = 14,
588 CAS_LATENCIES_MSB = 15,
589 CAS_LATENCY_TIME = 16,
590 THERMAL_AND_REFRESH = 31,
591 REFERENCE_RAW_CARD_USED = 62,
592 RANK1_ADDRESS_MAPPING = 63
593};
594
595static void calculate_timings(struct raminfo *info)
596{
597 unsigned cycletime;
598 unsigned cas_latency_time;
599 unsigned supported_cas_latencies;
600 unsigned channel, slot;
601 unsigned clock_speed_index;
602 unsigned min_cas_latency;
603 unsigned cas_latency;
604 unsigned max_clock_index;
605
606 /* Find common CAS latency */
607 supported_cas_latencies = 0x3fe;
608 for (channel = 0; channel < NUM_CHANNELS; channel++)
609 for (slot = 0; slot < NUM_SLOTS; slot++)
610 if (info->populated_ranks[channel][slot][0])
611 supported_cas_latencies &=
612 2 *
613 (info->
614 spd[channel][slot][CAS_LATENCIES_LSB] |
615 (info->
616 spd[channel][slot][CAS_LATENCIES_MSB] <<
617 8));
618
619 max_clock_index = min(3, info->max_supported_clock_speed_index);
620
621 cycletime = min_cycletime[max_clock_index];
622 cas_latency_time = min_cas_latency_time[max_clock_index];
623
624 for (channel = 0; channel < NUM_CHANNELS; channel++)
625 for (slot = 0; slot < NUM_SLOTS; slot++)
626 if (info->populated_ranks[channel][slot][0]) {
627 unsigned timebase;
628 timebase =
629 1000 *
630 info->
631 spd[channel][slot][TIMEBASE_DIVIDEND] /
632 info->spd[channel][slot][TIMEBASE_DIVISOR];
633 cycletime =
634 max(cycletime,
635 timebase *
636 info->spd[channel][slot][CYCLETIME]);
637 cas_latency_time =
638 max(cas_latency_time,
639 timebase *
640 info->
641 spd[channel][slot][CAS_LATENCY_TIME]);
642 }
643 for (clock_speed_index = 0; clock_speed_index < 3; clock_speed_index++) {
644 if (cycletime == min_cycletime[clock_speed_index])
645 break;
646 if (cycletime > min_cycletime[clock_speed_index]) {
647 clock_speed_index--;
648 cycletime = min_cycletime[clock_speed_index];
649 break;
650 }
651 }
Edward O'Callaghan7116ac82014-07-08 01:53:24 +1000652 min_cas_latency = CEIL_DIV(cas_latency_time, cycletime);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +0100653 cas_latency = 0;
654 while (supported_cas_latencies) {
655 cas_latency = find_highest_bit_set(supported_cas_latencies) + 3;
656 if (cas_latency <= min_cas_latency)
657 break;
658 supported_cas_latencies &=
659 ~(1 << find_highest_bit_set(supported_cas_latencies));
660 }
661
662 if (cas_latency != min_cas_latency && clock_speed_index)
663 clock_speed_index--;
664
665 if (cas_latency * min_cycletime[clock_speed_index] > 20000)
666 die("Couldn't configure DRAM");
667 info->clock_speed_index = clock_speed_index;
668 info->cas_latency = cas_latency;
669}
670
671static void program_base_timings(struct raminfo *info)
672{
673 unsigned channel;
674 unsigned slot, rank, lane;
675 unsigned extended_silicon_revision;
676 int i;
677
678 extended_silicon_revision = info->silicon_revision;
679 if (info->silicon_revision == 0)
680 for (channel = 0; channel < NUM_CHANNELS; channel++)
681 for (slot = 0; slot < NUM_SLOTS; slot++)
682 if ((info->
683 spd[channel][slot][MODULE_TYPE] & 0xF) ==
684 3)
685 extended_silicon_revision = 4;
686
687 for (channel = 0; channel < NUM_CHANNELS; channel++) {
688 for (slot = 0; slot < NUM_SLOTS; slot++)
689 for (rank = 0; rank < NUM_SLOTS; rank++) {
690 int card_timing_2;
691 if (!info->populated_ranks[channel][slot][rank])
692 continue;
693
694 for (lane = 0; lane < 9; lane++) {
695 int tm_reg;
696 int card_timing;
697
698 card_timing = 0;
699 if ((info->
700 spd[channel][slot][MODULE_TYPE] &
701 0xF) == 3) {
702 int reference_card;
703 reference_card =
704 info->
705 spd[channel][slot]
706 [REFERENCE_RAW_CARD_USED] &
707 0x1f;
708 if (reference_card == 3)
709 card_timing =
710 u16_ffd1188[0][lane]
711 [info->
712 clock_speed_index];
713 if (reference_card == 5)
714 card_timing =
715 u16_ffd1188[1][lane]
716 [info->
717 clock_speed_index];
718 }
719
720 info->training.
721 lane_timings[0][channel][slot][rank]
722 [lane] =
723 u8_FFFD1218[info->
724 clock_speed_index];
725 info->training.
726 lane_timings[1][channel][slot][rank]
727 [lane] = 256;
728
729 for (tm_reg = 2; tm_reg < 4; tm_reg++)
730 info->training.
731 lane_timings[tm_reg]
732 [channel][slot][rank][lane]
733 =
734 u8_FFFD1240[channel]
735 [extended_silicon_revision]
736 [lane][2 * slot +
737 rank][info->
738 clock_speed_index]
739 + info->max4048[channel]
740 +
741 u8_FFFD0C78[channel]
742 [extended_silicon_revision]
743 [info->
744 mode4030[channel]][slot]
745 [rank][info->
746 clock_speed_index]
747 + card_timing;
748 for (tm_reg = 0; tm_reg < 4; tm_reg++)
749 write_500(info, channel,
750 info->training.
751 lane_timings[tm_reg]
752 [channel][slot][rank]
753 [lane],
754 get_timing_register_addr
755 (lane, tm_reg, slot,
756 rank), 9, 0);
757 }
758
759 card_timing_2 = 0;
760 if (!(extended_silicon_revision != 4
761 || (info->
762 populated_ranks_mask[channel] & 5) ==
763 5)) {
764 if ((info->
765 spd[channel][slot]
766 [REFERENCE_RAW_CARD_USED] & 0x1F)
767 == 3)
768 card_timing_2 =
769 u16_FFFE0EB8[0][info->
770 clock_speed_index];
771 if ((info->
772 spd[channel][slot]
773 [REFERENCE_RAW_CARD_USED] & 0x1F)
774 == 5)
775 card_timing_2 =
776 u16_FFFE0EB8[1][info->
777 clock_speed_index];
778 }
779
780 for (i = 0; i < 3; i++)
781 write_500(info, channel,
782 (card_timing_2 +
783 info->max4048[channel]
784 +
785 u8_FFFD0EF8[channel]
786 [extended_silicon_revision]
787 [info->
788 mode4030[channel]][info->
789 clock_speed_index]),
790 u16_fffd0c50[i][slot][rank],
791 8, 1);
792 write_500(info, channel,
793 (info->max4048[channel] +
794 u8_FFFD0C78[channel]
795 [extended_silicon_revision][info->
796 mode4030
797 [channel]]
798 [slot][rank][info->
799 clock_speed_index]),
800 u16_fffd0c70[slot][rank], 7, 1);
801 }
802 if (!info->populated_ranks_mask[channel])
803 continue;
804 for (i = 0; i < 3; i++)
805 write_500(info, channel,
806 (info->max4048[channel] +
807 info->avg4044[channel]
808 +
809 u8_FFFD17E0[channel]
810 [extended_silicon_revision][info->
811 mode4030
812 [channel]][info->
813 clock_speed_index]),
814 u16_fffd0c68[i], 8, 1);
815 }
816}
817
818static unsigned int fsbcycle_ps(struct raminfo *info)
819{
820 return 900000 / info->fsb_frequency;
821}
822
823/* The time of DDR transfer in ps. */
824static unsigned int halfcycle_ps(struct raminfo *info)
825{
826 return 3750 / (info->clock_speed_index + 3);
827}
828
829/* The time of clock cycle in ps. */
830static unsigned int cycle_ps(struct raminfo *info)
831{
832 return 2 * halfcycle_ps(info);
833}
834
835/* Frequency in 1.(1)=10/9 MHz units. */
836static unsigned frequency_11(struct raminfo *info)
837{
838 return (info->clock_speed_index + 3) * 120;
839}
840
841/* Frequency in 0.1 MHz units. */
842static unsigned frequency_01(struct raminfo *info)
843{
844 return 100 * frequency_11(info) / 9;
845}
846
847static unsigned ps_to_halfcycles(struct raminfo *info, unsigned int ps)
848{
849 return (frequency_11(info) * 2) * ps / 900000;
850}
851
852static unsigned ns_to_cycles(struct raminfo *info, unsigned int ns)
853{
854 return (frequency_11(info)) * ns / 900;
855}
856
857static void compute_derived_timings(struct raminfo *info)
858{
859 unsigned channel, slot, rank;
860 int extended_silicon_revision;
861 int some_delay_1_ps;
862 int some_delay_2_ps;
863 int some_delay_2_halfcycles_ceil;
864 int some_delay_2_halfcycles_floor;
865 int some_delay_3_ps;
866 int some_delay_3_halfcycles;
867 int some_delay_3_ps_rounded;
868 int some_delay_1_cycle_ceil;
869 int some_delay_1_cycle_floor;
870
871 some_delay_3_halfcycles = 0;
872 some_delay_3_ps_rounded = 0;
873 extended_silicon_revision = info->silicon_revision;
874 if (!info->silicon_revision)
875 for (channel = 0; channel < NUM_CHANNELS; channel++)
876 for (slot = 0; slot < NUM_SLOTS; slot++)
877 if ((info->
878 spd[channel][slot][MODULE_TYPE] & 0xF) ==
879 3)
880 extended_silicon_revision = 4;
881 if (info->board_lane_delay[7] < 5)
882 info->board_lane_delay[7] = 5;
883 info->revision_flag_1 = 2;
884 if (info->silicon_revision == 2 || info->silicon_revision == 3)
885 info->revision_flag_1 = 0;
886 if (info->revision < 16)
887 info->revision_flag_1 = 0;
888
889 if (info->revision < 8)
890 info->revision_flag_1 = 0;
891 if (info->revision >= 8 && (info->silicon_revision == 0
892 || info->silicon_revision == 1))
893 some_delay_2_ps = 735;
894 else
895 some_delay_2_ps = 750;
896
897 if (info->revision >= 0x10 && (info->silicon_revision == 0
898 || info->silicon_revision == 1))
899 some_delay_1_ps = 3929;
900 else
901 some_delay_1_ps = 3490;
902
903 some_delay_1_cycle_floor = some_delay_1_ps / cycle_ps(info);
904 some_delay_1_cycle_ceil = some_delay_1_ps / cycle_ps(info);
905 if (some_delay_1_ps % cycle_ps(info))
906 some_delay_1_cycle_ceil++;
907 else
908 some_delay_1_cycle_floor--;
909 info->some_delay_1_cycle_floor = some_delay_1_cycle_floor;
910 if (info->revision_flag_1)
911 some_delay_2_ps = halfcycle_ps(info) >> 6;
912 some_delay_2_ps +=
913 max(some_delay_1_ps - 30,
914 2 * halfcycle_ps(info) * (some_delay_1_cycle_ceil - 1) + 1000) +
915 375;
916 some_delay_3_ps =
917 halfcycle_ps(info) - some_delay_2_ps % halfcycle_ps(info);
918 if (info->revision_flag_1) {
919 if (some_delay_3_ps < 150)
920 some_delay_3_halfcycles = 0;
921 else
922 some_delay_3_halfcycles =
923 (some_delay_3_ps << 6) / halfcycle_ps(info);
924 some_delay_3_ps_rounded =
925 halfcycle_ps(info) * some_delay_3_halfcycles >> 6;
926 }
927 some_delay_2_halfcycles_ceil =
928 (some_delay_2_ps + halfcycle_ps(info) - 1) / halfcycle_ps(info) -
929 2 * (some_delay_1_cycle_ceil - 1);
930 if (info->revision_flag_1 && some_delay_3_ps < 150)
931 some_delay_2_halfcycles_ceil++;
932 some_delay_2_halfcycles_floor = some_delay_2_halfcycles_ceil;
933 if (info->revision < 0x10)
934 some_delay_2_halfcycles_floor =
935 some_delay_2_halfcycles_ceil - 1;
936 if (!info->revision_flag_1)
937 some_delay_2_halfcycles_floor++;
938 info->some_delay_2_halfcycles_ceil = some_delay_2_halfcycles_ceil;
939 info->some_delay_3_ps_rounded = some_delay_3_ps_rounded;
940 if ((info->populated_ranks[0][0][0] && info->populated_ranks[0][1][0])
941 || (info->populated_ranks[1][0][0]
942 && info->populated_ranks[1][1][0]))
943 info->max_slots_used_in_channel = 2;
944 else
945 info->max_slots_used_in_channel = 1;
946 for (channel = 0; channel < 2; channel++)
947 write_mchbar32(0x244 + (channel << 10),
948 ((info->revision < 8) ? 1 : 0x200)
949 | ((2 - info->max_slots_used_in_channel) << 17) |
950 (channel << 21) | (info->
951 some_delay_1_cycle_floor <<
952 18) | 0x9510);
953 if (info->max_slots_used_in_channel == 1) {
954 info->mode4030[0] = (count_ranks_in_channel(info, 0) == 2);
955 info->mode4030[1] = (count_ranks_in_channel(info, 1) == 2);
956 } else {
957 info->mode4030[0] = ((count_ranks_in_channel(info, 0) == 1) || (count_ranks_in_channel(info, 0) == 2)) ? 2 : 3; /* 2 if 1 or 2 ranks */
958 info->mode4030[1] = ((count_ranks_in_channel(info, 1) == 1)
959 || (count_ranks_in_channel(info, 1) ==
960 2)) ? 2 : 3;
961 }
962 for (channel = 0; channel < NUM_CHANNELS; channel++) {
963 int max_of_unk;
964 int min_of_unk_2;
965
966 int i, count;
967 int sum;
968
969 if (!info->populated_ranks_mask[channel])
970 continue;
971
972 max_of_unk = 0;
973 min_of_unk_2 = 32767;
974
975 sum = 0;
976 count = 0;
977 for (i = 0; i < 3; i++) {
978 int unk1;
979 if (info->revision < 8)
980 unk1 =
981 u8_FFFD1891[0][channel][info->
982 clock_speed_index]
983 [i];
984 else if (!
985 (info->revision >= 0x10
986 || info->revision_flag_1))
987 unk1 =
988 u8_FFFD1891[1][channel][info->
989 clock_speed_index]
990 [i];
991 else
992 unk1 = 0;
993 for (slot = 0; slot < NUM_SLOTS; slot++)
994 for (rank = 0; rank < NUM_RANKS; rank++) {
995 int a = 0;
996 int b = 0;
997
998 if (!info->
999 populated_ranks[channel][slot]
1000 [rank])
1001 continue;
1002 if (extended_silicon_revision == 4
1003 && (info->
1004 populated_ranks_mask[channel] &
1005 5) != 5) {
1006 if ((info->
1007 spd[channel][slot]
1008 [REFERENCE_RAW_CARD_USED] &
1009 0x1F) == 3) {
1010 a = u16_ffd1178[0]
1011 [info->
1012 clock_speed_index];
1013 b = u16_fe0eb8[0][info->
1014 clock_speed_index];
1015 } else
1016 if ((info->
1017 spd[channel][slot]
1018 [REFERENCE_RAW_CARD_USED]
1019 & 0x1F) == 5) {
1020 a = u16_ffd1178[1]
1021 [info->
1022 clock_speed_index];
1023 b = u16_fe0eb8[1][info->
1024 clock_speed_index];
1025 }
1026 }
1027 min_of_unk_2 = min(min_of_unk_2, a);
1028 min_of_unk_2 = min(min_of_unk_2, b);
1029 if (rank == 0) {
1030 sum += a;
1031 count++;
1032 }
1033 {
1034 int t;
1035 t = b +
1036 u8_FFFD0EF8[channel]
1037 [extended_silicon_revision]
1038 [info->
1039 mode4030[channel]][info->
1040 clock_speed_index];
1041 if (unk1 >= t)
1042 max_of_unk =
1043 max(max_of_unk,
1044 unk1 - t);
1045 }
1046 }
1047 {
1048 int t =
1049 u8_FFFD17E0[channel]
1050 [extended_silicon_revision][info->
1051 mode4030
1052 [channel]]
1053 [info->clock_speed_index] + min_of_unk_2;
1054 if (unk1 >= t)
1055 max_of_unk = max(max_of_unk, unk1 - t);
1056 }
1057 }
1058
1059 info->avg4044[channel] = sum / count;
1060 info->max4048[channel] = max_of_unk;
1061 }
1062}
1063
1064static void jedec_read(struct raminfo *info,
1065 int channel, int slot, int rank,
1066 int total_rank, u8 addr3, unsigned int value)
1067{
1068 /* Handle mirrored mapping. */
1069 if ((rank & 1) && (info->spd[channel][slot][RANK1_ADDRESS_MAPPING] & 1))
1070 addr3 =
1071 (addr3 & 0xCF) | ((addr3 & 0x10) << 1) | ((addr3 >> 1) &
1072 0x10);
1073 write_mchbar8(0x271, addr3 | (read_mchbar8(0x271) & 0xC1));
1074 write_mchbar8(0x671, addr3 | (read_mchbar8(0x671) & 0xC1));
1075
1076 /* Handle mirrored mapping. */
1077 if ((rank & 1) && (info->spd[channel][slot][RANK1_ADDRESS_MAPPING] & 1))
1078 value =
1079 (value & ~0x1f8) | ((value >> 1) & 0xa8) | ((value & 0xa8)
1080 << 1);
1081
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001082 read32p((value << 3) | (total_rank << 28));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001083
1084 write_mchbar8(0x271, (read_mchbar8(0x271) & 0xC3) | 2);
1085 write_mchbar8(0x671, (read_mchbar8(0x671) & 0xC3) | 2);
1086
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001087 read32p(total_rank << 28);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001088}
1089
1090enum {
1091 MR1_RZQ12 = 512,
1092 MR1_RZQ2 = 64,
1093 MR1_RZQ4 = 4,
1094 MR1_ODS34OHM = 2
1095};
1096
1097enum {
1098 MR0_BT_INTERLEAVED = 8,
1099 MR0_DLL_RESET_ON = 256
1100};
1101
1102enum {
1103 MR2_RTT_WR_DISABLED = 0,
1104 MR2_RZQ2 = 1 << 10
1105};
1106
1107static void jedec_init(struct raminfo *info)
1108{
1109 int write_recovery;
1110 int channel, slot, rank;
1111 int total_rank;
1112 int dll_on;
1113 int self_refresh_temperature;
1114 int auto_self_refresh;
1115
1116 auto_self_refresh = 1;
1117 self_refresh_temperature = 1;
1118 if (info->board_lane_delay[3] <= 10) {
1119 if (info->board_lane_delay[3] <= 8)
1120 write_recovery = info->board_lane_delay[3] - 4;
1121 else
1122 write_recovery = 5;
1123 } else {
1124 write_recovery = 6;
1125 }
1126 FOR_POPULATED_RANKS {
1127 auto_self_refresh &=
1128 (info->spd[channel][slot][THERMAL_AND_REFRESH] >> 2) & 1;
1129 self_refresh_temperature &=
1130 info->spd[channel][slot][THERMAL_AND_REFRESH] & 1;
1131 }
1132 if (auto_self_refresh == 1)
1133 self_refresh_temperature = 0;
1134
1135 dll_on = ((info->silicon_revision != 2 && info->silicon_revision != 3)
1136 || (info->populated_ranks[0][0][0]
1137 && info->populated_ranks[0][1][0])
1138 || (info->populated_ranks[1][0][0]
1139 && info->populated_ranks[1][1][0]));
1140
1141 total_rank = 0;
1142
1143 for (channel = NUM_CHANNELS - 1; channel >= 0; channel--) {
1144 int rtt, rtt_wr = MR2_RTT_WR_DISABLED;
1145 int rzq_reg58e;
1146
1147 if (info->silicon_revision == 2 || info->silicon_revision == 3) {
1148 rzq_reg58e = 64;
1149 rtt = MR1_RZQ2;
1150 if (info->clock_speed_index != 0) {
1151 rzq_reg58e = 4;
1152 if (info->populated_ranks_mask[channel] == 3)
1153 rtt = MR1_RZQ4;
1154 }
1155 } else {
1156 if ((info->populated_ranks_mask[channel] & 5) == 5) {
1157 rtt = MR1_RZQ12;
1158 rzq_reg58e = 64;
1159 rtt_wr = MR2_RZQ2;
1160 } else {
1161 rzq_reg58e = 4;
1162 rtt = MR1_RZQ4;
1163 }
1164 }
1165
1166 write_mchbar16(0x588 + (channel << 10), 0x0);
1167 write_mchbar16(0x58a + (channel << 10), 0x4);
1168 write_mchbar16(0x58c + (channel << 10), rtt | MR1_ODS34OHM);
1169 write_mchbar16(0x58e + (channel << 10), rzq_reg58e | 0x82);
1170 write_mchbar16(0x590 + (channel << 10), 0x1282);
1171
1172 for (slot = 0; slot < NUM_SLOTS; slot++)
1173 for (rank = 0; rank < NUM_RANKS; rank++)
1174 if (info->populated_ranks[channel][slot][rank]) {
1175 jedec_read(info, channel, slot, rank,
1176 total_rank, 0x28,
1177 rtt_wr | (info->
1178 clock_speed_index
1179 << 3)
1180 | (auto_self_refresh << 6) |
1181 (self_refresh_temperature <<
1182 7));
1183 jedec_read(info, channel, slot, rank,
1184 total_rank, 0x38, 0);
1185 jedec_read(info, channel, slot, rank,
1186 total_rank, 0x18,
1187 rtt | MR1_ODS34OHM);
1188 jedec_read(info, channel, slot, rank,
1189 total_rank, 6,
1190 (dll_on << 12) |
1191 (write_recovery << 9)
1192 | ((info->cas_latency - 4) <<
1193 4) | MR0_BT_INTERLEAVED |
1194 MR0_DLL_RESET_ON);
1195 total_rank++;
1196 }
1197 }
1198}
1199
1200static void program_modules_memory_map(struct raminfo *info, int pre_jedec)
1201{
1202 unsigned channel, slot, rank;
1203 unsigned int total_mb[2] = { 0, 0 }; /* total memory per channel in MB */
1204 unsigned int channel_0_non_interleaved;
1205
1206 FOR_ALL_RANKS {
1207 if (info->populated_ranks[channel][slot][rank]) {
1208 total_mb[channel] +=
1209 pre_jedec ? 256 : (256 << info->
1210 density[channel][slot] >> info->
1211 is_x16_module[channel][slot]);
1212 write_mchbar8(0x208 + rank + 2 * slot + (channel << 10),
1213 (pre_jedec ? (1 | ((1 + 1) << 1))
1214 : (info->
1215 is_x16_module[channel][slot] |
1216 ((info->density[channel][slot] +
1217 1) << 1))) | 0x80);
1218 }
1219 write_mchbar16(0x200 + (channel << 10) + 4 * slot + 2 * rank,
1220 total_mb[channel] >> 6);
1221 }
1222
1223 info->total_memory_mb = total_mb[0] + total_mb[1];
1224
1225 info->interleaved_part_mb =
1226 pre_jedec ? 0 : 2 * min(total_mb[0], total_mb[1]);
1227 info->non_interleaved_part_mb =
1228 total_mb[0] + total_mb[1] - info->interleaved_part_mb;
1229 channel_0_non_interleaved = total_mb[0] - info->interleaved_part_mb / 2;
1230 write_mchbar32(0x100,
1231 channel_0_non_interleaved | (info->
1232 non_interleaved_part_mb <<
1233 16));
1234 if (!pre_jedec)
1235 write_mchbar16(0x104, info->interleaved_part_mb);
1236}
1237
1238static void program_board_delay(struct raminfo *info)
1239{
1240 int cas_latency_shift;
1241 int some_delay_ns;
1242 int some_delay_3_half_cycles;
1243
1244 unsigned channel, i;
1245 int high_multiplier;
1246 int lane_3_delay;
1247 int cas_latency_derived;
1248
1249 high_multiplier = 0;
1250 some_delay_ns = 200;
1251 some_delay_3_half_cycles = 4;
1252 cas_latency_shift = info->silicon_revision == 0
1253 || info->silicon_revision == 1 ? 1 : 0;
1254 if (info->revision < 8) {
1255 some_delay_ns = 600;
1256 cas_latency_shift = 0;
1257 }
1258 {
1259 int speed_bit;
1260 speed_bit =
1261 ((info->clock_speed_index > 1
1262 || (info->silicon_revision != 2
1263 && info->silicon_revision != 3))) ^ (info->revision >=
1264 0x10);
1265 write_500(info, 0, speed_bit | ((!info->use_ecc) << 1), 0x60e,
1266 3, 1);
1267 write_500(info, 1, speed_bit | ((!info->use_ecc) << 1), 0x60e,
1268 3, 1);
1269 if (info->revision >= 0x10 && info->clock_speed_index <= 1
1270 && (info->silicon_revision == 2
1271 || info->silicon_revision == 3))
1272 rmw_1d0(0x116, 5, 2, 4, 1);
1273 }
1274 write_mchbar32(0x120,
1275 (1 << (info->max_slots_used_in_channel + 28)) |
1276 0x188e7f9f);
1277
1278 write_mchbar8(0x124,
1279 info->board_lane_delay[4] +
1280 ((frequency_01(info) + 999) / 1000));
1281 write_mchbar16(0x125, 0x1360);
1282 write_mchbar8(0x127, 0x40);
1283 if (info->fsb_frequency < frequency_11(info) / 2) {
1284 unsigned some_delay_2_half_cycles;
1285 high_multiplier = 1;
1286 some_delay_2_half_cycles = ps_to_halfcycles(info,
1287 ((3 *
1288 fsbcycle_ps(info))
1289 >> 1) +
1290 (halfcycle_ps(info)
1291 *
1292 reg178_min[info->
1293 clock_speed_index]
1294 >> 6)
1295 +
1296 4 *
1297 halfcycle_ps(info)
1298 + 2230);
1299 some_delay_3_half_cycles =
1300 min((some_delay_2_half_cycles +
1301 (frequency_11(info) * 2) * (28 -
1302 some_delay_2_half_cycles) /
1303 (frequency_11(info) * 2 -
1304 4 * (info->fsb_frequency))) >> 3, 7);
1305 }
1306 if (read_mchbar8(0x2ca9) & 1)
1307 some_delay_3_half_cycles = 3;
1308 for (channel = 0; channel < NUM_CHANNELS; channel++) {
1309 write_mchbar32(0x220 + (channel << 10),
1310 read_mchbar32(0x220 +
1311 (channel << 10)) | 0x18001117);
1312 write_mchbar32(0x224 + (channel << 10),
1313 (info->max_slots_used_in_channel - 1)
1314 |
1315 ((info->cas_latency - 5 -
1316 info->clock_speed_index) << 21)
1317 |
1318 ((info->max_slots_used_in_channel +
1319 info->cas_latency - cas_latency_shift -
1320 4) << 16)
1321 | ((info->cas_latency - cas_latency_shift - 4) <<
1322 26)
1323 |
1324 ((info->cas_latency - info->clock_speed_index +
1325 info->max_slots_used_in_channel - 6) << 8));
1326 write_mchbar32(0x228 + (channel << 10),
1327 info->max_slots_used_in_channel);
1328 write_mchbar8(0x239 + (channel << 10), 32);
1329 write_mchbar32(0x248 + (channel << 10),
1330 (high_multiplier << 24) |
1331 (some_delay_3_half_cycles << 25) | 0x840000);
1332 write_mchbar32(0x278 + (channel << 10), 0xc362042);
1333 write_mchbar32(0x27c + (channel << 10), 0x8b000062);
1334 write_mchbar32(0x24c + (channel << 10),
1335 ((! !info->
1336 clock_speed_index) << 17) | (((2 +
1337 info->
1338 clock_speed_index
1339 -
1340 (! !info->
1341 clock_speed_index)))
1342 << 12) | 0x10200);
1343
1344 write_mchbar8(0x267 + (channel << 10), 0x4);
1345 write_mchbar16(0x272 + (channel << 10), 0x155);
1346 write_mchbar32(0x2bc + (channel << 10),
1347 (read_mchbar32(0x2bc + (channel << 10)) &
1348 0xFF000000)
1349 | 0x707070);
1350
1351 write_500(info, channel,
1352 ((!info->populated_ranks[channel][1][1])
1353 | (!info->populated_ranks[channel][1][0] << 1)
1354 | (!info->populated_ranks[channel][0][1] << 2)
1355 | (!info->populated_ranks[channel][0][0] << 3)),
1356 0x4c9, 4, 1);
1357 }
1358
1359 write_mchbar8(0x2c4, ((1 + (info->clock_speed_index != 0)) << 6) | 0xC);
1360 {
1361 u8 freq_divisor = 2;
1362 if (info->fsb_frequency == frequency_11(info))
1363 freq_divisor = 3;
1364 else if (2 * info->fsb_frequency < 3 * (frequency_11(info) / 2))
1365 freq_divisor = 1;
1366 else
1367 freq_divisor = 2;
1368 write_mchbar32(0x2c0, (freq_divisor << 11) | 0x6009c400);
1369 }
1370
1371 if (info->board_lane_delay[3] <= 10) {
1372 if (info->board_lane_delay[3] <= 8)
1373 lane_3_delay = info->board_lane_delay[3];
1374 else
1375 lane_3_delay = 10;
1376 } else {
1377 lane_3_delay = 12;
1378 }
1379 cas_latency_derived = info->cas_latency - info->clock_speed_index + 2;
1380 if (info->clock_speed_index > 1)
1381 cas_latency_derived++;
1382 for (channel = 0; channel < NUM_CHANNELS; channel++) {
1383 write_mchbar32(0x240 + (channel << 10),
1384 ((info->clock_speed_index ==
1385 0) * 0x11000) | 0x1002100 | ((2 +
1386 info->
1387 clock_speed_index)
1388 << 4) | (info->
1389 cas_latency
1390 - 3));
1391 write_500(info, channel, (info->clock_speed_index << 1) | 1,
1392 0x609, 6, 1);
1393 write_500(info, channel,
1394 info->clock_speed_index + 2 * info->cas_latency - 7,
1395 0x601, 6, 1);
1396
1397 write_mchbar32(0x250 + (channel << 10),
1398 ((lane_3_delay + info->clock_speed_index +
1399 9) << 6)
1400 | (info->board_lane_delay[7] << 2) | (info->
1401 board_lane_delay
1402 [4] << 16)
1403 | (info->board_lane_delay[1] << 25) | (info->
1404 board_lane_delay
1405 [1] << 29)
1406 | 1);
1407 write_mchbar32(0x254 + (channel << 10),
1408 (info->
1409 board_lane_delay[1] >> 3) | ((info->
1410 board_lane_delay
1411 [8] +
1412 4 *
1413 info->
1414 use_ecc) << 6) |
1415 0x80 | (info->board_lane_delay[6] << 1) | (info->
1416 board_lane_delay
1417 [2] <<
1418 28) |
1419 (cas_latency_derived << 16) | 0x4700000);
1420 write_mchbar32(0x258 + (channel << 10),
1421 ((info->board_lane_delay[5] +
1422 info->clock_speed_index +
1423 9) << 12) | ((info->clock_speed_index -
1424 info->cas_latency + 12) << 8)
1425 | (info->board_lane_delay[2] << 17) | (info->
1426 board_lane_delay
1427 [4] << 24)
1428 | 0x47);
1429 write_mchbar32(0x25c + (channel << 10),
1430 (info->board_lane_delay[1] << 1) | (info->
1431 board_lane_delay
1432 [0] << 8) |
1433 0x1da50000);
1434 write_mchbar8(0x264 + (channel << 10), 0xff);
1435 write_mchbar8(0x5f8 + (channel << 10),
1436 (cas_latency_shift << 3) | info->use_ecc);
1437 }
1438
1439 program_modules_memory_map(info, 1);
1440
1441 write_mchbar16(0x610,
1442 (min(ns_to_cycles(info, some_delay_ns) / 2, 127) << 9)
1443 | (read_mchbar16(0x610) & 0x1C3) | 0x3C);
1444 write_mchbar16(0x612, read_mchbar16(0x612) | 0x100);
1445 write_mchbar16(0x214, read_mchbar16(0x214) | 0x3E00);
1446 for (i = 0; i < 8; i++) {
1447 pcie_write_config32(PCI_DEV (QUICKPATH_BUS, 0, 1), 0x80 + 4 * i,
1448 (info->total_memory_mb - 64) | !i | 2);
1449 pcie_write_config32(PCI_DEV (QUICKPATH_BUS, 0, 1), 0xc0 + 4 * i, 0);
1450 }
1451}
1452
1453#define BETTER_MEMORY_MAP 0
1454
1455static void program_total_memory_map(struct raminfo *info)
1456{
1457 unsigned int TOM, TOLUD, TOUUD;
1458 unsigned int quickpath_reserved;
1459 unsigned int REMAPbase;
1460 unsigned int uma_base_igd;
1461 unsigned int uma_base_gtt;
1462 int memory_remap;
1463 unsigned int memory_map[8];
1464 int i;
1465 unsigned int current_limit;
1466 unsigned int tseg_base;
1467 int uma_size_igd = 0, uma_size_gtt = 0;
1468
1469 memset(memory_map, 0, sizeof(memory_map));
1470
1471#if REAL
1472 if (info->uma_enabled) {
1473 u16 t = pcie_read_config16(NORTHBRIDGE, D0F0_GGC);
1474 gav(t);
1475 const int uma_sizes_gtt[16] =
1476 { 0, 1, 0, 2, 0, 0, 0, 0, 0, 2, 3, 4, 42, 42, 42, 42 };
1477 /* Igd memory */
1478 const int uma_sizes_igd[16] = {
1479 0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352,
1480 256, 512
1481 };
1482
1483 uma_size_igd = uma_sizes_igd[(t >> 4) & 0xF];
1484 uma_size_gtt = uma_sizes_gtt[(t >> 8) & 0xF];
1485 }
1486#endif
1487
1488 TOM = info->total_memory_mb;
1489 if (TOM == 4096)
1490 TOM = 4032;
1491 TOUUD = ALIGN_DOWN(TOM - info->memory_reserved_for_heci_mb, 64);
1492 TOLUD = ALIGN_DOWN(min(3072 + ALIGN_UP(uma_size_igd + uma_size_gtt, 64)
1493 , TOUUD), 64);
1494 memory_remap = 0;
1495 if (TOUUD - TOLUD > 64) {
1496 memory_remap = 1;
1497 REMAPbase = max(4096, TOUUD);
1498 TOUUD = TOUUD - TOLUD + 4096;
1499 }
1500 if (TOUUD > 4096)
1501 memory_map[2] = TOUUD | 1;
1502 quickpath_reserved = 0;
1503
1504 {
1505 u32 t;
1506
1507 gav(t = pcie_read_config32(PCI_DEV(QUICKPATH_BUS, 0, 1), 0x68));
1508 if (t & 0x800)
1509 quickpath_reserved =
1510 (1 << find_lowest_bit_set32(t >> 20));
1511 }
1512 if (memory_remap)
1513 TOUUD -= quickpath_reserved;
1514
1515#if !REAL
1516 if (info->uma_enabled) {
1517 u16 t = pcie_read_config16(NORTHBRIDGE, D0F0_GGC);
1518 gav(t);
1519 const int uma_sizes_gtt[16] =
1520 { 0, 1, 0, 2, 0, 0, 0, 0, 0, 2, 3, 4, 42, 42, 42, 42 };
1521 /* Igd memory */
1522 const int uma_sizes_igd[16] = {
1523 0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352,
1524 256, 512
1525 };
1526
1527 uma_size_igd = uma_sizes_igd[(t >> 4) & 0xF];
1528 uma_size_gtt = uma_sizes_gtt[(t >> 8) & 0xF];
1529 }
1530#endif
1531
1532 uma_base_igd = TOLUD - uma_size_igd;
1533 uma_base_gtt = uma_base_igd - uma_size_gtt;
1534 tseg_base = ALIGN_DOWN(uma_base_gtt, 64) - (CONFIG_SMM_TSEG_SIZE >> 20);
1535 if (!memory_remap)
1536 tseg_base -= quickpath_reserved;
1537 tseg_base = ALIGN_DOWN(tseg_base, 8);
1538
1539 pcie_write_config16(NORTHBRIDGE, D0F0_TOLUD, TOLUD << 4);
1540 pcie_write_config16(NORTHBRIDGE, D0F0_TOM, TOM >> 6);
1541 if (memory_remap) {
1542 pcie_write_config16(NORTHBRIDGE, D0F0_REMAPBASE, REMAPbase >> 6);
1543 pcie_write_config16(NORTHBRIDGE, D0F0_REMAPLIMIT, (TOUUD - 64) >> 6);
1544 }
1545 pcie_write_config16(NORTHBRIDGE, D0F0_TOUUD, TOUUD);
1546
1547 if (info->uma_enabled) {
1548 pcie_write_config32(NORTHBRIDGE, D0F0_IGD_BASE, uma_base_igd << 20);
1549 pcie_write_config32(NORTHBRIDGE, D0F0_GTT_BASE, uma_base_gtt << 20);
1550 }
1551 pcie_write_config32(NORTHBRIDGE, TSEG, tseg_base << 20);
1552
1553 current_limit = 0;
1554 memory_map[0] = ALIGN_DOWN(uma_base_gtt, 64) | 1;
1555 memory_map[1] = 4096;
1556 for (i = 0; i < ARRAY_SIZE(memory_map); i++) {
1557 current_limit = max(current_limit, memory_map[i] & ~1);
1558 pcie_write_config32(PCI_DEV(QUICKPATH_BUS, 0, 1), 4 * i + 0x80,
1559 (memory_map[i] & 1) | ALIGN_DOWN(current_limit -
1560 1, 64) | 2);
1561 pcie_write_config32(PCI_DEV(QUICKPATH_BUS, 0, 1), 4 * i + 0xc0, 0);
1562 }
1563}
1564
1565static void collect_system_info(struct raminfo *info)
1566{
1567 u32 capid0[3];
1568 int i;
1569 unsigned channel;
1570
1571 /* Wait for some bit, maybe TXT clear. */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001572 while (!(read8((u8 *)0xfed40000) & (1 << 7))) ;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001573
1574 if (!info->heci_bar)
1575 gav(info->heci_bar =
1576 pcie_read_config32(HECIDEV, HECIBAR) & 0xFFFFFFF8);
1577 if (!info->memory_reserved_for_heci_mb) {
1578 /* Wait for ME to be ready */
1579 intel_early_me_init();
1580 info->memory_reserved_for_heci_mb = intel_early_me_uma_size();
1581 }
1582
1583 for (i = 0; i < 3; i++)
1584 gav(capid0[i] =
1585 pcie_read_config32(NORTHBRIDGE, D0F0_CAPID0 | (i << 2)));
1586 gav(info->revision = pcie_read_config8(NORTHBRIDGE, PCI_REVISION_ID));
1587 info->max_supported_clock_speed_index = (~capid0[1] & 7);
1588
1589 if ((capid0[1] >> 11) & 1)
1590 info->uma_enabled = 0;
1591 else
1592 gav(info->uma_enabled =
1593 pcie_read_config8(NORTHBRIDGE, D0F0_DEVEN) & 8);
1594 /* Unrecognised: [0000:fffd3d2d] 37f81.37f82 ! CPUID: eax: 00000001; ecx: 00000e00 => 00020655.00010800.029ae3ff.bfebfbff */
1595 info->silicon_revision = 0;
1596
1597 if (capid0[2] & 2) {
1598 info->silicon_revision = 0;
1599 info->max_supported_clock_speed_index = 2;
1600 for (channel = 0; channel < NUM_CHANNELS; channel++)
1601 if (info->populated_ranks[channel][0][0]
1602 && (info->spd[channel][0][MODULE_TYPE] & 0xf) ==
1603 3) {
1604 info->silicon_revision = 2;
1605 info->max_supported_clock_speed_index = 1;
1606 }
1607 } else {
1608 switch (((capid0[2] >> 18) & 1) + 2 * ((capid0[1] >> 3) & 1)) {
1609 case 1:
1610 case 2:
1611 info->silicon_revision = 3;
1612 break;
1613 case 3:
1614 info->silicon_revision = 0;
1615 break;
1616 case 0:
1617 info->silicon_revision = 2;
1618 break;
1619 }
1620 switch (pcie_read_config16(NORTHBRIDGE, PCI_DEVICE_ID)) {
1621 case 0x40:
1622 info->silicon_revision = 0;
1623 break;
1624 case 0x48:
1625 info->silicon_revision = 1;
1626 break;
1627 }
1628 }
1629}
1630
1631static void write_training_data(struct raminfo *info)
1632{
1633 int tm, channel, slot, rank, lane;
1634 if (info->revision < 8)
1635 return;
1636
1637 for (tm = 0; tm < 4; tm++)
1638 for (channel = 0; channel < NUM_CHANNELS; channel++)
1639 for (slot = 0; slot < NUM_SLOTS; slot++)
1640 for (rank = 0; rank < NUM_RANKS; rank++)
1641 for (lane = 0; lane < 9; lane++)
1642 write_500(info, channel,
1643 info->
1644 cached_training->
1645 lane_timings[tm]
1646 [channel][slot][rank]
1647 [lane],
1648 get_timing_register_addr
1649 (lane, tm, slot,
1650 rank), 9, 0);
1651 write_1d0(info->cached_training->reg_178, 0x178, 7, 1);
1652 write_1d0(info->cached_training->reg_10b, 0x10b, 6, 1);
1653}
1654
1655static void dump_timings(struct raminfo *info)
1656{
1657#if REAL
1658 int channel, slot, rank, lane, i;
1659 printk(BIOS_DEBUG, "Timings:\n");
1660 FOR_POPULATED_RANKS {
1661 printk(BIOS_DEBUG, "channel %d, slot %d, rank %d\n", channel,
1662 slot, rank);
1663 for (lane = 0; lane < 9; lane++) {
1664 printk(BIOS_DEBUG, "lane %d: ", lane);
1665 for (i = 0; i < 4; i++) {
1666 printk(BIOS_DEBUG, "%x (%x) ",
1667 read_500(info, channel,
1668 get_timing_register_addr
1669 (lane, i, slot, rank),
1670 9),
1671 info->training.
1672 lane_timings[i][channel][slot][rank]
1673 [lane]);
1674 }
1675 printk(BIOS_DEBUG, "\n");
1676 }
1677 }
1678 printk(BIOS_DEBUG, "[178] = %x (%x)\n", read_1d0(0x178, 7),
1679 info->training.reg_178);
1680 printk(BIOS_DEBUG, "[10b] = %x (%x)\n", read_1d0(0x10b, 6),
1681 info->training.reg_10b);
1682#endif
1683}
1684
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01001685/* Read timings and other registers that need to be restored verbatim and
1686 put them to CBMEM.
1687 */
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001688static void save_timings(struct raminfo *info)
1689{
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001690 struct ram_training train;
1691 struct mrc_data_container *mrcdata;
1692 int output_len = ALIGN(sizeof(train), 16);
1693 int channel, slot, rank, lane, i;
1694
1695 train = info->training;
1696 FOR_POPULATED_RANKS for (lane = 0; lane < 9; lane++)
1697 for (i = 0; i < 4; i++)
1698 train.lane_timings[i][channel][slot][rank][lane] =
1699 read_500(info, channel,
1700 get_timing_register_addr(lane, i, slot,
1701 rank), 9);
1702 train.reg_178 = read_1d0(0x178, 7);
1703 train.reg_10b = read_1d0(0x10b, 6);
1704
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01001705 for (channel = 0; channel < NUM_CHANNELS; channel++) {
1706 u32 reg32;
1707 reg32 = read_mchbar32 ((channel << 10) + 0x274);
1708 train.reg274265[channel][0] = reg32 >> 16;
1709 train.reg274265[channel][1] = reg32 & 0xffff;
1710 train.reg274265[channel][2] = read_mchbar16 ((channel << 10) + 0x265) >> 8;
1711 }
1712 train.reg2ca9_bit0 = read_mchbar8(0x2ca9) & 1;
1713 train.reg_6dc = read_mchbar32 (0x6dc);
1714 train.reg_6e8 = read_mchbar32 (0x6e8);
1715
1716 printk (BIOS_SPEW, "[6dc] = %x\n", train.reg_6dc);
1717 printk (BIOS_SPEW, "[6e8] = %x\n", train.reg_6e8);
1718
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001719 /* Save the MRC S3 restore data to cbmem */
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001720 mrcdata = cbmem_add
1721 (CBMEM_ID_MRCDATA, output_len + sizeof(struct mrc_data_container));
1722
Kyösti Mälkki743a2182014-06-15 15:59:44 +03001723 if (mrcdata != NULL) {
1724 printk(BIOS_DEBUG, "Relocate MRC DATA from %p to %p (%u bytes)\n",
1725 &train, mrcdata, output_len);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001726
Kyösti Mälkki743a2182014-06-15 15:59:44 +03001727 mrcdata->mrc_signature = MRC_DATA_SIGNATURE;
1728 mrcdata->mrc_data_size = output_len;
1729 mrcdata->reserved = 0;
1730 memcpy(mrcdata->mrc_data, &train, sizeof(train));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001731
Kyösti Mälkki743a2182014-06-15 15:59:44 +03001732 /* Zero the unused space in aligned buffer. */
1733 if (output_len > sizeof(train))
1734 memset(mrcdata->mrc_data + sizeof(train), 0,
1735 output_len - sizeof(train));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001736
Kyösti Mälkki743a2182014-06-15 15:59:44 +03001737 mrcdata->mrc_checksum = compute_ip_checksum(mrcdata->mrc_data,
1738 mrcdata->mrc_data_size);
1739 }
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001740}
1741
1742#if REAL
1743static const struct ram_training *get_cached_training(void)
1744{
1745 struct mrc_data_container *cont;
1746 cont = find_current_mrc_cache();
1747 if (!cont)
1748 return 0;
1749 return (void *)cont->mrc_data;
1750}
1751#endif
1752
1753/* FIXME: add timeout. */
1754static void wait_heci_ready(void)
1755{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001756 while (!(read32(DEFAULT_HECIBAR + 0xc) & 8)) ; // = 0x8000000c
1757 write32((DEFAULT_HECIBAR + 0x4),
1758 (read32(DEFAULT_HECIBAR + 0x4) & ~0x10) | 0xc);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001759}
1760
1761/* FIXME: add timeout. */
1762static void wait_heci_cb_avail(int len)
1763{
1764 union {
1765 struct mei_csr csr;
1766 u32 raw;
1767 } csr;
1768
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001769 while (!(read32(DEFAULT_HECIBAR + 0xc) & 8)) ;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001770
1771 do
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001772 csr.raw = read32(DEFAULT_HECIBAR + 0x4);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001773 while (len >
1774 csr.csr.buffer_depth - (csr.csr.buffer_write_ptr -
1775 csr.csr.buffer_read_ptr));
1776}
1777
1778static void send_heci_packet(struct mei_header *head, u32 * payload)
1779{
1780 int len = (head->length + 3) / 4;
1781 int i;
1782
1783 wait_heci_cb_avail(len + 1);
1784
1785 /* FIXME: handle leftovers correctly. */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001786 write32(DEFAULT_HECIBAR + 0, *(u32 *) head);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001787 for (i = 0; i < len - 1; i++)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001788 write32(DEFAULT_HECIBAR + 0, payload[i]);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001789
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001790 write32(DEFAULT_HECIBAR + 0, payload[i] & ((1 << (8 * len)) - 1));
1791 write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 0x4);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001792}
1793
1794static void
1795send_heci_message(u8 * msg, int len, u8 hostaddress, u8 clientaddress)
1796{
1797 struct mei_header head;
1798 int maxlen;
1799
1800 wait_heci_ready();
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001801 maxlen = (read32(DEFAULT_HECIBAR + 0x4) >> 24) * 4 - 4;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001802
1803 while (len) {
1804 int cur = len;
1805 if (cur > maxlen) {
1806 cur = maxlen;
1807 head.is_complete = 0;
1808 } else
1809 head.is_complete = 1;
1810 head.length = cur;
1811 head.reserved = 0;
1812 head.client_address = clientaddress;
1813 head.host_address = hostaddress;
1814 send_heci_packet(&head, (u32 *) msg);
1815 len -= cur;
1816 msg += cur;
1817 }
1818}
1819
1820/* FIXME: Add timeout. */
1821static int
1822recv_heci_packet(struct raminfo *info, struct mei_header *head, u32 * packet,
1823 u32 * packet_size)
1824{
1825 union {
1826 struct mei_csr csr;
1827 u32 raw;
1828 } csr;
1829 int i = 0;
1830
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001831 write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 2);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001832 do {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001833 csr.raw = read32(DEFAULT_HECIBAR + 0xc);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001834#if !REAL
1835 if (i++ > 346)
1836 return -1;
1837#endif
1838 }
1839 while (csr.csr.buffer_write_ptr == csr.csr.buffer_read_ptr);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001840 *(u32 *) head = read32(DEFAULT_HECIBAR + 0x8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001841 if (!head->length) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001842 write32(DEFAULT_HECIBAR + 0x4,
1843 read32(DEFAULT_HECIBAR + 0x4) | 2);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001844 *packet_size = 0;
1845 return 0;
1846 }
1847 if (head->length + 4 > 4 * csr.csr.buffer_depth
1848 || head->length > *packet_size) {
1849 *packet_size = 0;
1850 return -1;
1851 }
1852
1853 do
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001854 csr.raw = read32(DEFAULT_HECIBAR + 0xc);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001855 while ((head->length + 3) >> 2 >
1856 csr.csr.buffer_write_ptr - csr.csr.buffer_read_ptr);
1857
1858 for (i = 0; i < (head->length + 3) >> 2; i++)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001859 packet[i++] = read32(DEFAULT_HECIBAR + 0x8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001860 *packet_size = head->length;
1861 if (!csr.csr.ready)
1862 *packet_size = 0;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001863 write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 4);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001864 return 0;
1865}
1866
1867/* FIXME: Add timeout. */
1868static int
1869recv_heci_message(struct raminfo *info, u32 * message, u32 * message_size)
1870{
1871 struct mei_header head;
1872 int current_position;
1873
1874 current_position = 0;
1875 while (1) {
1876 u32 current_size;
1877 current_size = *message_size - current_position;
1878 if (recv_heci_packet
1879 (info, &head, message + (current_position >> 2),
1880 &current_size) == -1)
1881 break;
1882 if (!current_size)
1883 break;
1884 current_position += current_size;
1885 if (head.is_complete) {
1886 *message_size = current_position;
1887 return 0;
1888 }
1889
1890 if (current_position >= *message_size)
1891 break;
1892 }
1893 *message_size = 0;
1894 return -1;
1895}
1896
1897static void send_heci_uma_message(struct raminfo *info)
1898{
1899 struct uma_reply {
1900 u8 group_id;
1901 u8 command;
1902 u8 reserved;
1903 u8 result;
1904 u8 field2;
1905 u8 unk3[0x48 - 4 - 1];
1906 } __attribute__ ((packed)) reply;
1907 struct uma_message {
1908 u8 group_id;
1909 u8 cmd;
1910 u8 reserved;
1911 u8 result;
1912 u32 c2;
1913 u64 heci_uma_addr;
1914 u32 memory_reserved_for_heci_mb;
1915 u16 c3;
1916 } __attribute__ ((packed)) msg = {
1917 0, MKHI_SET_UMA, 0, 0,
1918 0x82,
1919 info->heci_uma_addr, info->memory_reserved_for_heci_mb, 0};
1920 u32 reply_size;
1921
1922 send_heci_message((u8 *) & msg, sizeof(msg), 0, 7);
1923
1924 reply_size = sizeof(reply);
1925 if (recv_heci_message(info, (u32 *) & reply, &reply_size) == -1)
1926 return;
1927
1928 if (reply.command != (MKHI_SET_UMA | (1 << 7)))
1929 die("HECI init failed\n");
1930}
1931
1932static void setup_heci_uma(struct raminfo *info)
1933{
1934 u32 reg44;
1935
1936 reg44 = pcie_read_config32(HECIDEV, 0x44); // = 0x80010020
1937 info->memory_reserved_for_heci_mb = 0;
1938 info->heci_uma_addr = 0;
1939 if (!((reg44 & 0x10000) && !(pcie_read_config32(HECIDEV, 0x40) & 0x20)))
1940 return;
1941
1942 info->heci_bar = pcie_read_config32(HECIDEV, 0x10) & 0xFFFFFFF0;
1943 info->memory_reserved_for_heci_mb = reg44 & 0x3f;
1944 info->heci_uma_addr =
1945 ((u64)
1946 ((((u64) pcie_read_config16(NORTHBRIDGE, D0F0_TOM)) << 6) -
1947 info->memory_reserved_for_heci_mb)) << 20;
1948
1949 pcie_read_config32(NORTHBRIDGE, DMIBAR);
1950 if (info->memory_reserved_for_heci_mb) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001951 write32(DEFAULT_DMIBAR + 0x14,
1952 read32(DEFAULT_DMIBAR + 0x14) & ~0x80);
1953 write32(DEFAULT_RCBA + 0x14,
1954 read32(DEFAULT_RCBA + 0x14) & ~0x80);
1955 write32(DEFAULT_DMIBAR + 0x20,
1956 read32(DEFAULT_DMIBAR + 0x20) & ~0x80);
1957 write32(DEFAULT_RCBA + 0x20,
1958 read32(DEFAULT_RCBA + 0x20) & ~0x80);
1959 write32(DEFAULT_DMIBAR + 0x2c,
1960 read32(DEFAULT_DMIBAR + 0x2c) & ~0x80);
1961 write32(DEFAULT_RCBA + 0x30,
1962 read32(DEFAULT_RCBA + 0x30) & ~0x80);
1963 write32(DEFAULT_DMIBAR + 0x38,
1964 read32(DEFAULT_DMIBAR + 0x38) & ~0x80);
1965 write32(DEFAULT_RCBA + 0x40,
1966 read32(DEFAULT_RCBA + 0x40) & ~0x80);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001967
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001968 write32(DEFAULT_RCBA + 0x40, 0x87000080); // OK
1969 write32(DEFAULT_DMIBAR + 0x38, 0x87000080); // OK
1970 while (read16(DEFAULT_RCBA + 0x46) & 2
1971 && read16(DEFAULT_DMIBAR + 0x3e) & 2) ;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001972 }
1973
1974 write_mchbar32(0x24, 0x10000 + info->memory_reserved_for_heci_mb);
1975
1976 send_heci_uma_message(info);
1977
1978 pcie_write_config32(HECIDEV, 0x10, 0x0);
1979 pcie_write_config8(HECIDEV, 0x4, 0x0);
1980
1981}
1982
1983static int have_match_ranks(struct raminfo *info, int channel, int ranks)
1984{
1985 int ranks_in_channel;
1986 ranks_in_channel = info->populated_ranks[channel][0][0]
1987 + info->populated_ranks[channel][0][1]
1988 + info->populated_ranks[channel][1][0]
1989 + info->populated_ranks[channel][1][1];
1990
1991 /* empty channel */
1992 if (ranks_in_channel == 0)
1993 return 1;
1994
1995 if (ranks_in_channel != ranks)
1996 return 0;
1997 /* single slot */
1998 if (info->populated_ranks[channel][0][0] !=
1999 info->populated_ranks[channel][1][0])
2000 return 1;
2001 if (info->populated_ranks[channel][0][1] !=
2002 info->populated_ranks[channel][1][1])
2003 return 1;
2004 if (info->is_x16_module[channel][0] != info->is_x16_module[channel][1])
2005 return 0;
2006 if (info->density[channel][0] != info->density[channel][1])
2007 return 0;
2008 return 1;
2009}
2010
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002011static void read_4090(struct raminfo *info)
2012{
2013 int i, channel, slot, rank, lane;
2014 for (i = 0; i < 2; i++)
2015 for (slot = 0; slot < NUM_SLOTS; slot++)
2016 for (rank = 0; rank < NUM_RANKS; rank++)
2017 for (lane = 0; lane < 9; lane++)
2018 info->training.
2019 lane_timings[0][i][slot][rank][lane]
2020 = 32;
2021
2022 for (i = 1; i < 4; i++)
2023 for (channel = 0; channel < NUM_CHANNELS; channel++)
2024 for (slot = 0; slot < NUM_SLOTS; slot++)
2025 for (rank = 0; rank < NUM_RANKS; rank++)
2026 for (lane = 0; lane < 9; lane++) {
2027 info->training.
2028 lane_timings[i][channel]
2029 [slot][rank][lane] =
2030 read_500(info, channel,
2031 get_timing_register_addr
2032 (lane, i, slot,
2033 rank), 9)
2034 + (i == 1) * 11; // !!!!
2035 }
2036
2037}
2038
2039static u32 get_etalon2(int flip, u32 addr)
2040{
2041 const u16 invmask[] = {
2042 0xaaaa, 0x6db6, 0x4924, 0xeeee, 0xcccc, 0x8888, 0x7bde, 0x739c,
2043 0x6318, 0x4210, 0xefbe, 0xcf3c, 0x8e38, 0x0c30, 0x0820
2044 };
2045 u32 ret;
2046 u32 comp4 = addr / 480;
2047 addr %= 480;
2048 u32 comp1 = addr & 0xf;
2049 u32 comp2 = (addr >> 4) & 1;
2050 u32 comp3 = addr >> 5;
2051
2052 if (comp4)
2053 ret = 0x1010101 << (comp4 - 1);
2054 else
2055 ret = 0;
2056 if (flip ^ (((invmask[comp3] >> comp1) ^ comp2) & 1))
2057 ret = ~ret;
2058
2059 return ret;
2060}
2061
2062static void disable_cache(void)
2063{
2064 msr_t msr = {.lo = 0, .hi = 0 };
2065
Alexandru Gagniuc86091f92015-09-30 20:23:09 -07002066 wrmsr(MTRR_PHYS_BASE(3), msr);
2067 wrmsr(MTRR_PHYS_MASK(3), msr);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002068}
2069
2070static void enable_cache(unsigned int base, unsigned int size)
2071{
2072 msr_t msr;
2073 msr.lo = base | MTRR_TYPE_WRPROT;
2074 msr.hi = 0;
Alexandru Gagniuc86091f92015-09-30 20:23:09 -07002075 wrmsr(MTRR_PHYS_BASE(3), msr);
2076 msr.lo = ((~(ALIGN_DOWN(size + 4096, 4096) - 1) | MTRR_DEF_TYPE_EN)
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002077 & 0xffffffff);
2078 msr.hi = 0x0000000f;
Alexandru Gagniuc86091f92015-09-30 20:23:09 -07002079 wrmsr(MTRR_PHYS_MASK(3), msr);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002080}
2081
2082static void flush_cache(u32 start, u32 size)
2083{
2084 u32 end;
2085 u32 addr;
2086
2087 end = start + (ALIGN_DOWN(size + 4096, 4096));
2088 for (addr = start; addr < end; addr += 64)
2089 clflush(addr);
2090}
2091
2092static void clear_errors(void)
2093{
2094 pcie_write_config8(NORTHBRIDGE, 0xc0, 0x01);
2095}
2096
2097static void write_testing(struct raminfo *info, int totalrank, int flip)
2098{
2099 int nwrites = 0;
2100 /* in 8-byte units. */
2101 u32 offset;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08002102 u8 *base;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002103
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08002104 base = (u8 *)(totalrank << 28);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002105 for (offset = 0; offset < 9 * 480; offset += 2) {
2106 write32(base + offset * 8, get_etalon2(flip, offset));
2107 write32(base + offset * 8 + 4, get_etalon2(flip, offset));
2108 write32(base + offset * 8 + 8, get_etalon2(flip, offset + 1));
2109 write32(base + offset * 8 + 12, get_etalon2(flip, offset + 1));
2110 nwrites += 4;
2111 if (nwrites >= 320) {
2112 clear_errors();
2113 nwrites = 0;
2114 }
2115 }
2116}
2117
2118static u8 check_testing(struct raminfo *info, u8 total_rank, int flip)
2119{
2120 u8 failmask = 0;
2121 int i;
2122 int comp1, comp2, comp3;
2123 u32 failxor[2] = { 0, 0 };
2124
2125 enable_cache((total_rank << 28), 1728 * 5 * 4);
2126
2127 for (comp3 = 0; comp3 < 9 && failmask != 0xff; comp3++) {
2128 for (comp1 = 0; comp1 < 4; comp1++)
2129 for (comp2 = 0; comp2 < 60; comp2++) {
2130 u32 re[4];
2131 u32 curroffset =
2132 comp3 * 8 * 60 + 2 * comp1 + 8 * comp2;
2133 read128((total_rank << 28) | (curroffset << 3),
2134 (u64 *) re);
2135 failxor[0] |=
2136 get_etalon2(flip, curroffset) ^ re[0];
2137 failxor[1] |=
2138 get_etalon2(flip, curroffset) ^ re[1];
2139 failxor[0] |=
2140 get_etalon2(flip, curroffset | 1) ^ re[2];
2141 failxor[1] |=
2142 get_etalon2(flip, curroffset | 1) ^ re[3];
2143 }
2144 for (i = 0; i < 8; i++)
2145 if ((0xff << (8 * (i % 4))) & failxor[i / 4])
2146 failmask |= 1 << i;
2147 }
2148 disable_cache();
2149 flush_cache((total_rank << 28), 1728 * 5 * 4);
2150 return failmask;
2151}
2152
2153const u32 seed1[0x18] = {
2154 0x3a9d5ab5, 0x576cb65b, 0x555773b6, 0x2ab772ee,
2155 0x555556ee, 0x3a9d5ab5, 0x576cb65b, 0x555773b6,
2156 0x2ab772ee, 0x555556ee, 0x5155a555, 0x5155a555,
2157 0x5155a555, 0x5155a555, 0x3a9d5ab5, 0x576cb65b,
2158 0x555773b6, 0x2ab772ee, 0x555556ee, 0x55d6b4a5,
2159 0x366d6b3a, 0x2ae5ddbb, 0x3b9ddbb7, 0x55d6b4a5,
2160};
2161
2162static u32 get_seed2(int a, int b)
2163{
2164 const u32 seed2[5] = {
2165 0x55555555, 0x33333333, 0x2e555a55, 0x55555555,
2166 0x5b6db6db,
2167 };
2168 u32 r;
2169 r = seed2[(a + (a >= 10)) / 5];
2170 return b ? ~r : r;
2171}
2172
2173static int make_shift(int comp2, int comp5, int x)
2174{
2175 const u8 seed3[32] = {
2176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2177 0x00, 0x00, 0x38, 0x1c, 0x3c, 0x18, 0x38, 0x38,
2178 0x38, 0x38, 0x38, 0x38, 0x0f, 0x0f, 0x0f, 0x0f,
2179 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
2180 };
2181
2182 return (comp2 - ((seed3[comp5] >> (x & 7)) & 1)) & 0x1f;
2183}
2184
2185static u32 get_etalon(int flip, u32 addr)
2186{
2187 u32 mask_byte = 0;
2188 int comp1 = (addr >> 1) & 1;
2189 int comp2 = (addr >> 3) & 0x1f;
2190 int comp3 = (addr >> 8) & 0xf;
2191 int comp4 = (addr >> 12) & 0xf;
2192 int comp5 = (addr >> 16) & 0x1f;
2193 u32 mask_bit = ~(0x10001 << comp3);
2194 u32 part1;
2195 u32 part2;
2196 int byte;
2197
2198 part2 =
2199 ((seed1[comp5] >>
2200 make_shift(comp2, comp5,
2201 (comp3 >> 3) | (comp1 << 2) | 2)) & 1) ^ flip;
2202 part1 =
2203 ((seed1[comp5] >>
2204 make_shift(comp2, comp5,
2205 (comp3 >> 3) | (comp1 << 2) | 0)) & 1) ^ flip;
2206
2207 for (byte = 0; byte < 4; byte++)
2208 if ((get_seed2(comp5, comp4) >>
2209 make_shift(comp2, comp5, (byte | (comp1 << 2)))) & 1)
2210 mask_byte |= 0xff << (8 * byte);
2211
2212 return (mask_bit & mask_byte) | (part1 << comp3) | (part2 <<
2213 (comp3 + 16));
2214}
2215
2216static void
2217write_testing_type2(struct raminfo *info, u8 totalrank, u8 region, u8 block,
2218 char flip)
2219{
2220 int i;
2221 for (i = 0; i < 2048; i++)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08002222 write32p((totalrank << 28) | (region << 25) | (block << 16) |
2223 (i << 2), get_etalon(flip, (block << 16) | (i << 2)));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002224}
2225
2226static u8
2227check_testing_type2(struct raminfo *info, u8 totalrank, u8 region, u8 block,
2228 char flip)
2229{
2230 u8 failmask = 0;
2231 u32 failxor[2];
2232 int i;
2233 int comp1, comp2, comp3;
2234
2235 failxor[0] = 0;
2236 failxor[1] = 0;
2237
2238 enable_cache(totalrank << 28, 134217728);
2239 for (comp3 = 0; comp3 < 2 && failmask != 0xff; comp3++) {
2240 for (comp1 = 0; comp1 < 16; comp1++)
2241 for (comp2 = 0; comp2 < 64; comp2++) {
2242 u32 addr =
2243 (totalrank << 28) | (region << 25) | (block
2244 << 16)
2245 | (comp3 << 12) | (comp2 << 6) | (comp1 <<
2246 2);
2247 failxor[comp1 & 1] |=
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08002248 read32p(addr) ^ get_etalon(flip, addr);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002249 }
2250 for (i = 0; i < 8; i++)
2251 if ((0xff << (8 * (i % 4))) & failxor[i / 4])
2252 failmask |= 1 << i;
2253 }
2254 disable_cache();
2255 flush_cache((totalrank << 28) | (region << 25) | (block << 16), 16384);
2256 return failmask;
2257}
2258
2259static int check_bounded(unsigned short *vals, u16 bound)
2260{
2261 int i;
2262
2263 for (i = 0; i < 8; i++)
2264 if (vals[i] < bound)
2265 return 0;
2266 return 1;
2267}
2268
2269enum state {
2270 BEFORE_USABLE = 0, AT_USABLE = 1, AT_MARGIN = 2, COMPLETE = 3
2271};
2272
2273static int validate_state(enum state *in)
2274{
2275 int i;
2276 for (i = 0; i < 8; i++)
2277 if (in[i] != COMPLETE)
2278 return 0;
2279 return 1;
2280}
2281
2282static void
2283do_fsm(enum state *state, u16 * counter,
2284 u8 fail_mask, int margin, int uplimit,
2285 u8 * res_low, u8 * res_high, u8 val)
2286{
2287 int lane;
2288
2289 for (lane = 0; lane < 8; lane++) {
2290 int is_fail = (fail_mask >> lane) & 1;
2291 switch (state[lane]) {
2292 case BEFORE_USABLE:
2293 if (!is_fail) {
2294 counter[lane] = 1;
2295 state[lane] = AT_USABLE;
2296 break;
2297 }
2298 counter[lane] = 0;
2299 state[lane] = BEFORE_USABLE;
2300 break;
2301 case AT_USABLE:
2302 if (!is_fail) {
2303 ++counter[lane];
2304 if (counter[lane] >= margin) {
2305 state[lane] = AT_MARGIN;
2306 res_low[lane] = val - margin + 1;
2307 break;
2308 }
2309 state[lane] = 1;
2310 break;
2311 }
2312 counter[lane] = 0;
2313 state[lane] = BEFORE_USABLE;
2314 break;
2315 case AT_MARGIN:
2316 if (is_fail) {
2317 state[lane] = COMPLETE;
2318 res_high[lane] = val - 1;
2319 } else {
2320 counter[lane]++;
2321 state[lane] = AT_MARGIN;
2322 if (val == uplimit) {
2323 state[lane] = COMPLETE;
2324 res_high[lane] = uplimit;
2325 }
2326 }
2327 break;
2328 case COMPLETE:
2329 break;
2330 }
2331 }
2332}
2333
2334static void
2335train_ram_at_178(struct raminfo *info, u8 channel, int slot, int rank,
2336 u8 total_rank, u8 reg_178, int first_run, int niter,
2337 timing_bounds_t * timings)
2338{
2339 int lane;
2340 enum state state[8];
2341 u16 count[8];
2342 u8 lower_usable[8];
2343 u8 upper_usable[8];
2344 unsigned short num_sucessfully_checked[8];
2345 u8 secondary_total_rank;
2346 u8 reg1b3;
2347
2348 if (info->populated_ranks_mask[1]) {
2349 if (channel == 1)
2350 secondary_total_rank =
2351 info->populated_ranks[1][0][0] +
2352 info->populated_ranks[1][0][1]
2353 + info->populated_ranks[1][1][0] +
2354 info->populated_ranks[1][1][1];
2355 else
2356 secondary_total_rank = 0;
2357 } else
2358 secondary_total_rank = total_rank;
2359
2360 {
2361 int i;
2362 for (i = 0; i < 8; i++)
2363 state[i] = BEFORE_USABLE;
2364 }
2365
2366 if (!first_run) {
2367 int is_all_ok = 1;
2368 for (lane = 0; lane < 8; lane++)
2369 if (timings[reg_178][channel][slot][rank][lane].
2370 smallest ==
2371 timings[reg_178][channel][slot][rank][lane].
2372 largest) {
2373 timings[reg_178][channel][slot][rank][lane].
2374 smallest = 0;
2375 timings[reg_178][channel][slot][rank][lane].
2376 largest = 0;
2377 is_all_ok = 0;
2378 }
2379 if (is_all_ok) {
2380 int i;
2381 for (i = 0; i < 8; i++)
2382 state[i] = COMPLETE;
2383 }
2384 }
2385
2386 for (reg1b3 = 0; reg1b3 < 0x30 && !validate_state(state); reg1b3++) {
2387 u8 failmask = 0;
2388 write_1d0(reg1b3 ^ 32, 0x1b3, 6, 1);
2389 write_1d0(reg1b3 ^ 32, 0x1a3, 6, 1);
2390 failmask = check_testing(info, total_rank, 0);
2391 write_mchbar32(0xfb0, read_mchbar32(0xfb0) | 0x00030000);
2392 do_fsm(state, count, failmask, 5, 47, lower_usable,
2393 upper_usable, reg1b3);
2394 }
2395
2396 if (reg1b3) {
2397 write_1d0(0, 0x1b3, 6, 1);
2398 write_1d0(0, 0x1a3, 6, 1);
2399 for (lane = 0; lane < 8; lane++) {
2400 if (state[lane] == COMPLETE) {
2401 timings[reg_178][channel][slot][rank][lane].
2402 smallest =
2403 lower_usable[lane] +
2404 (info->training.
2405 lane_timings[0][channel][slot][rank][lane]
2406 & 0x3F) - 32;
2407 timings[reg_178][channel][slot][rank][lane].
2408 largest =
2409 upper_usable[lane] +
2410 (info->training.
2411 lane_timings[0][channel][slot][rank][lane]
2412 & 0x3F) - 32;
2413 }
2414 }
2415 }
2416
2417 if (!first_run) {
2418 for (lane = 0; lane < 8; lane++)
2419 if (state[lane] == COMPLETE) {
2420 write_500(info, channel,
2421 timings[reg_178][channel][slot][rank]
2422 [lane].smallest,
2423 get_timing_register_addr(lane, 0,
2424 slot, rank),
2425 9, 1);
2426 write_500(info, channel,
2427 timings[reg_178][channel][slot][rank]
2428 [lane].smallest +
2429 info->training.
2430 lane_timings[1][channel][slot][rank]
2431 [lane]
2432 -
2433 info->training.
2434 lane_timings[0][channel][slot][rank]
2435 [lane], get_timing_register_addr(lane,
2436 1,
2437 slot,
2438 rank),
2439 9, 1);
2440 num_sucessfully_checked[lane] = 0;
2441 } else
2442 num_sucessfully_checked[lane] = -1;
2443
2444 do {
2445 u8 failmask = 0;
2446 int i;
2447 for (i = 0; i < niter; i++) {
2448 if (failmask == 0xFF)
2449 break;
2450 failmask |=
2451 check_testing_type2(info, total_rank, 2, i,
2452 0);
2453 failmask |=
2454 check_testing_type2(info, total_rank, 3, i,
2455 1);
2456 }
2457 write_mchbar32(0xfb0,
2458 read_mchbar32(0xfb0) | 0x00030000);
2459 for (lane = 0; lane < 8; lane++)
2460 if (num_sucessfully_checked[lane] != 0xffff) {
2461 if ((1 << lane) & failmask) {
2462 if (timings[reg_178][channel]
2463 [slot][rank][lane].
2464 largest <=
2465 timings[reg_178][channel]
2466 [slot][rank][lane].smallest)
2467 num_sucessfully_checked
2468 [lane] = -1;
2469 else {
2470 num_sucessfully_checked
2471 [lane] = 0;
2472 timings[reg_178]
2473 [channel][slot]
2474 [rank][lane].
2475 smallest++;
2476 write_500(info, channel,
2477 timings
2478 [reg_178]
2479 [channel]
2480 [slot][rank]
2481 [lane].
2482 smallest,
2483 get_timing_register_addr
2484 (lane, 0,
2485 slot, rank),
2486 9, 1);
2487 write_500(info, channel,
2488 timings
2489 [reg_178]
2490 [channel]
2491 [slot][rank]
2492 [lane].
2493 smallest +
2494 info->
2495 training.
2496 lane_timings
2497 [1][channel]
2498 [slot][rank]
2499 [lane]
2500 -
2501 info->
2502 training.
2503 lane_timings
2504 [0][channel]
2505 [slot][rank]
2506 [lane],
2507 get_timing_register_addr
2508 (lane, 1,
2509 slot, rank),
2510 9, 1);
2511 }
2512 } else
2513 num_sucessfully_checked[lane]++;
2514 }
2515 }
2516 while (!check_bounded(num_sucessfully_checked, 2));
2517
2518 for (lane = 0; lane < 8; lane++)
2519 if (state[lane] == COMPLETE) {
2520 write_500(info, channel,
2521 timings[reg_178][channel][slot][rank]
2522 [lane].largest,
2523 get_timing_register_addr(lane, 0,
2524 slot, rank),
2525 9, 1);
2526 write_500(info, channel,
2527 timings[reg_178][channel][slot][rank]
2528 [lane].largest +
2529 info->training.
2530 lane_timings[1][channel][slot][rank]
2531 [lane]
2532 -
2533 info->training.
2534 lane_timings[0][channel][slot][rank]
2535 [lane], get_timing_register_addr(lane,
2536 1,
2537 slot,
2538 rank),
2539 9, 1);
2540 num_sucessfully_checked[lane] = 0;
2541 } else
2542 num_sucessfully_checked[lane] = -1;
2543
2544 do {
2545 int failmask = 0;
2546 int i;
2547 for (i = 0; i < niter; i++) {
2548 if (failmask == 0xFF)
2549 break;
2550 failmask |=
2551 check_testing_type2(info, total_rank, 2, i,
2552 0);
2553 failmask |=
2554 check_testing_type2(info, total_rank, 3, i,
2555 1);
2556 }
2557
2558 write_mchbar32(0xfb0,
2559 read_mchbar32(0xfb0) | 0x00030000);
2560 for (lane = 0; lane < 8; lane++) {
2561 if (num_sucessfully_checked[lane] != 0xffff) {
2562 if ((1 << lane) & failmask) {
2563 if (timings[reg_178][channel]
2564 [slot][rank][lane].
2565 largest <=
2566 timings[reg_178][channel]
2567 [slot][rank][lane].
2568 smallest) {
2569 num_sucessfully_checked
2570 [lane] = -1;
2571 } else {
2572 num_sucessfully_checked
2573 [lane] = 0;
2574 timings[reg_178]
2575 [channel][slot]
2576 [rank][lane].
2577 largest--;
2578 write_500(info, channel,
2579 timings
2580 [reg_178]
2581 [channel]
2582 [slot][rank]
2583 [lane].
2584 largest,
2585 get_timing_register_addr
2586 (lane, 0,
2587 slot, rank),
2588 9, 1);
2589 write_500(info, channel,
2590 timings
2591 [reg_178]
2592 [channel]
2593 [slot][rank]
2594 [lane].
2595 largest +
2596 info->
2597 training.
2598 lane_timings
2599 [1][channel]
2600 [slot][rank]
2601 [lane]
2602 -
2603 info->
2604 training.
2605 lane_timings
2606 [0][channel]
2607 [slot][rank]
2608 [lane],
2609 get_timing_register_addr
2610 (lane, 1,
2611 slot, rank),
2612 9, 1);
2613 }
2614 } else
2615 num_sucessfully_checked[lane]++;
2616 }
2617 }
2618 }
2619 while (!check_bounded(num_sucessfully_checked, 3));
2620
2621 for (lane = 0; lane < 8; lane++) {
2622 write_500(info, channel,
2623 info->training.
2624 lane_timings[0][channel][slot][rank][lane],
2625 get_timing_register_addr(lane, 0, slot, rank),
2626 9, 1);
2627 write_500(info, channel,
2628 info->training.
2629 lane_timings[1][channel][slot][rank][lane],
2630 get_timing_register_addr(lane, 1, slot, rank),
2631 9, 1);
2632 if (timings[reg_178][channel][slot][rank][lane].
2633 largest <=
2634 timings[reg_178][channel][slot][rank][lane].
2635 smallest) {
2636 timings[reg_178][channel][slot][rank][lane].
2637 largest = 0;
2638 timings[reg_178][channel][slot][rank][lane].
2639 smallest = 0;
2640 }
2641 }
2642 }
2643}
2644
2645static void set_10b(struct raminfo *info, u8 val)
2646{
2647 int channel;
2648 int slot, rank;
2649 int lane;
2650
2651 if (read_1d0(0x10b, 6) == val)
2652 return;
2653
2654 write_1d0(val, 0x10b, 6, 1);
2655
2656 FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 9; lane++) {
2657 u16 reg_500;
2658 reg_500 = read_500(info, channel,
2659 get_timing_register_addr(lane, 0, slot,
2660 rank), 9);
2661 if (val == 1) {
2662 if (lut16[info->clock_speed_index] <= reg_500)
2663 reg_500 -= lut16[info->clock_speed_index];
2664 else
2665 reg_500 = 0;
2666 } else {
2667 reg_500 += lut16[info->clock_speed_index];
2668 }
2669 write_500(info, channel, reg_500,
2670 get_timing_register_addr(lane, 0, slot, rank), 9, 1);
2671 }
2672}
2673
2674static void set_ecc(int onoff)
2675{
2676 int channel;
2677 for (channel = 0; channel < NUM_CHANNELS; channel++) {
2678 u8 t;
2679 t = read_mchbar8((channel << 10) + 0x5f8);
2680 if (onoff)
2681 t |= 1;
2682 else
2683 t &= ~1;
2684 write_mchbar8((channel << 10) + 0x5f8, t);
2685 }
2686}
2687
2688static void set_178(u8 val)
2689{
2690 if (val >= 31)
2691 val = val - 31;
2692 else
2693 val = 63 - val;
2694
2695 write_1d0(2 * val, 0x178, 7, 1);
2696}
2697
2698static void
2699write_500_timings_type(struct raminfo *info, int channel, int slot, int rank,
2700 int type)
2701{
2702 int lane;
2703
2704 for (lane = 0; lane < 8; lane++)
2705 write_500(info, channel,
2706 info->training.
2707 lane_timings[type][channel][slot][rank][lane],
2708 get_timing_register_addr(lane, type, slot, rank), 9,
2709 0);
2710}
2711
2712static void
2713try_timing_offsets(struct raminfo *info, int channel,
2714 int slot, int rank, int totalrank)
2715{
2716 u16 count[8];
2717 enum state state[8];
2718 u8 lower_usable[8], upper_usable[8];
2719 int lane;
2720 int i;
2721 int flip = 1;
2722 int timing_offset;
2723
2724 for (i = 0; i < 8; i++)
2725 state[i] = BEFORE_USABLE;
2726
2727 memset(count, 0, sizeof(count));
2728
2729 for (lane = 0; lane < 8; lane++)
2730 write_500(info, channel,
2731 info->training.
2732 lane_timings[2][channel][slot][rank][lane] + 32,
2733 get_timing_register_addr(lane, 3, slot, rank), 9, 1);
2734
2735 for (timing_offset = 0; !validate_state(state) && timing_offset < 64;
2736 timing_offset++) {
2737 u8 failmask;
2738 write_1d0(timing_offset ^ 32, 0x1bb, 6, 1);
2739 failmask = 0;
2740 for (i = 0; i < 2 && failmask != 0xff; i++) {
2741 flip = !flip;
2742 write_testing(info, totalrank, flip);
2743 failmask |= check_testing(info, totalrank, flip);
2744 }
2745 do_fsm(state, count, failmask, 10, 63, lower_usable,
2746 upper_usable, timing_offset);
2747 }
2748 write_1d0(0, 0x1bb, 6, 1);
2749 dump_timings(info);
2750 if (!validate_state(state))
2751 die("Couldn't discover DRAM timings (1)\n");
2752
2753 for (lane = 0; lane < 8; lane++) {
2754 u8 bias = 0;
2755
2756 if (info->silicon_revision) {
2757 int usable_length;
2758
2759 usable_length = upper_usable[lane] - lower_usable[lane];
2760 if (usable_length >= 20) {
2761 bias = usable_length / 2 - 10;
2762 if (bias >= 2)
2763 bias = 2;
2764 }
2765 }
2766 write_500(info, channel,
2767 info->training.
2768 lane_timings[2][channel][slot][rank][lane] +
2769 (upper_usable[lane] + lower_usable[lane]) / 2 - bias,
2770 get_timing_register_addr(lane, 3, slot, rank), 9, 1);
2771 info->training.timing2_bounds[channel][slot][rank][lane][0] =
2772 info->training.lane_timings[2][channel][slot][rank][lane] +
2773 lower_usable[lane];
2774 info->training.timing2_bounds[channel][slot][rank][lane][1] =
2775 info->training.lane_timings[2][channel][slot][rank][lane] +
2776 upper_usable[lane];
2777 info->training.timing2_offset[channel][slot][rank][lane] =
2778 info->training.lane_timings[2][channel][slot][rank][lane];
2779 }
2780}
2781
2782static u8
2783choose_training(struct raminfo *info, int channel, int slot, int rank,
2784 int lane, timing_bounds_t * timings, u8 center_178)
2785{
2786 u16 central_weight;
2787 u16 side_weight;
2788 unsigned int sum = 0, count = 0;
2789 u8 span;
2790 u8 lower_margin, upper_margin;
2791 u8 reg_178;
2792 u8 result;
2793
2794 span = 12;
2795 central_weight = 20;
2796 side_weight = 20;
2797 if (info->silicon_revision == 1 && channel == 1) {
2798 central_weight = 5;
2799 side_weight = 20;
2800 if ((info->
2801 populated_ranks_mask[1] ^ (info->
2802 populated_ranks_mask[1] >> 2)) &
2803 1)
2804 span = 18;
2805 }
2806 if ((info->populated_ranks_mask[0] & 5) == 5) {
2807 central_weight = 20;
2808 side_weight = 20;
2809 }
2810 if (info->clock_speed_index >= 2
2811 && (info->populated_ranks_mask[0] & 5) == 5 && slot == 1) {
2812 if (info->silicon_revision == 1) {
2813 switch (channel) {
2814 case 0:
2815 if (lane == 1) {
2816 central_weight = 10;
2817 side_weight = 20;
2818 }
2819 break;
2820 case 1:
2821 if (lane == 6) {
2822 side_weight = 5;
2823 central_weight = 20;
2824 }
2825 break;
2826 }
2827 }
2828 if (info->silicon_revision == 0 && channel == 0 && lane == 0) {
2829 side_weight = 5;
2830 central_weight = 20;
2831 }
2832 }
2833 for (reg_178 = center_178 - span; reg_178 <= center_178 + span;
2834 reg_178 += span) {
2835 u8 smallest;
2836 u8 largest;
2837 largest = timings[reg_178][channel][slot][rank][lane].largest;
2838 smallest = timings[reg_178][channel][slot][rank][lane].smallest;
2839 if (largest - smallest + 1 >= 5) {
2840 unsigned int weight;
2841 if (reg_178 == center_178)
2842 weight = central_weight;
2843 else
2844 weight = side_weight;
2845 sum += weight * (largest + smallest);
2846 count += weight;
2847 }
2848 }
2849 dump_timings(info);
2850 if (count == 0)
2851 die("Couldn't discover DRAM timings (2)\n");
2852 result = sum / (2 * count);
2853 lower_margin =
2854 result - timings[center_178][channel][slot][rank][lane].smallest;
2855 upper_margin =
2856 timings[center_178][channel][slot][rank][lane].largest - result;
2857 if (upper_margin < 10 && lower_margin > 10)
2858 result -= min(lower_margin - 10, 10 - upper_margin);
2859 if (upper_margin > 10 && lower_margin < 10)
2860 result += min(upper_margin - 10, 10 - lower_margin);
2861 return result;
2862}
2863
2864#define STANDARD_MIN_MARGIN 5
2865
2866static u8 choose_reg178(struct raminfo *info, timing_bounds_t * timings)
2867{
2868 u16 margin[64];
2869 int lane, rank, slot, channel;
2870 u8 reg178;
2871 int count = 0, sum = 0;
2872
2873 for (reg178 = reg178_min[info->clock_speed_index];
2874 reg178 < reg178_max[info->clock_speed_index];
2875 reg178 += reg178_step[info->clock_speed_index]) {
2876 margin[reg178] = -1;
2877 FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 8; lane++) {
2878 int curmargin =
2879 timings[reg178][channel][slot][rank][lane].largest -
2880 timings[reg178][channel][slot][rank][lane].
2881 smallest + 1;
2882 if (curmargin < margin[reg178])
2883 margin[reg178] = curmargin;
2884 }
2885 if (margin[reg178] >= STANDARD_MIN_MARGIN) {
2886 u16 weight;
2887 weight = margin[reg178] - STANDARD_MIN_MARGIN;
2888 sum += weight * reg178;
2889 count += weight;
2890 }
2891 }
2892 dump_timings(info);
2893 if (count == 0)
2894 die("Couldn't discover DRAM timings (3)\n");
2895
2896 u8 threshold;
2897
2898 for (threshold = 30; threshold >= 5; threshold--) {
2899 int usable_length = 0;
2900 int smallest_fount = 0;
2901 for (reg178 = reg178_min[info->clock_speed_index];
2902 reg178 < reg178_max[info->clock_speed_index];
2903 reg178 += reg178_step[info->clock_speed_index])
2904 if (margin[reg178] >= threshold) {
2905 usable_length +=
2906 reg178_step[info->clock_speed_index];
2907 info->training.reg178_largest =
2908 reg178 -
2909 2 * reg178_step[info->clock_speed_index];
2910
2911 if (!smallest_fount) {
2912 smallest_fount = 1;
2913 info->training.reg178_smallest =
2914 reg178 +
2915 reg178_step[info->
2916 clock_speed_index];
2917 }
2918 }
2919 if (usable_length >= 0x21)
2920 break;
2921 }
2922
2923 return sum / count;
2924}
2925
2926static int check_cached_sanity(struct raminfo *info)
2927{
2928 int lane;
2929 int slot, rank;
2930 int channel;
2931
2932 if (!info->cached_training)
2933 return 0;
2934
2935 for (channel = 0; channel < NUM_CHANNELS; channel++)
2936 for (slot = 0; slot < NUM_SLOTS; slot++)
2937 for (rank = 0; rank < NUM_RANKS; rank++)
2938 for (lane = 0; lane < 8 + info->use_ecc; lane++) {
2939 u16 cached_value, estimation_value;
2940 cached_value =
2941 info->cached_training->
2942 lane_timings[1][channel][slot][rank]
2943 [lane];
2944 if (cached_value >= 0x18
2945 && cached_value <= 0x1E7) {
2946 estimation_value =
2947 info->training.
2948 lane_timings[1][channel]
2949 [slot][rank][lane];
2950 if (estimation_value <
2951 cached_value - 24)
2952 return 0;
2953 if (estimation_value >
2954 cached_value + 24)
2955 return 0;
2956 }
2957 }
2958 return 1;
2959}
2960
2961static int try_cached_training(struct raminfo *info)
2962{
2963 u8 saved_243[2];
2964 u8 tm;
2965
2966 int channel, slot, rank, lane;
2967 int flip = 1;
2968 int i, j;
2969
2970 if (!check_cached_sanity(info))
2971 return 0;
2972
2973 info->training.reg178_center = info->cached_training->reg178_center;
2974 info->training.reg178_smallest = info->cached_training->reg178_smallest;
2975 info->training.reg178_largest = info->cached_training->reg178_largest;
2976 memcpy(&info->training.timing_bounds,
2977 &info->cached_training->timing_bounds,
2978 sizeof(info->training.timing_bounds));
2979 memcpy(&info->training.timing_offset,
2980 &info->cached_training->timing_offset,
2981 sizeof(info->training.timing_offset));
2982
2983 write_1d0(2, 0x142, 3, 1);
2984 saved_243[0] = read_mchbar8(0x243);
2985 saved_243[1] = read_mchbar8(0x643);
2986 write_mchbar8(0x243, saved_243[0] | 2);
2987 write_mchbar8(0x643, saved_243[1] | 2);
2988 set_ecc(0);
2989 pcie_write_config16(NORTHBRIDGE, 0xc8, 3);
2990 if (read_1d0(0x10b, 6) & 1)
2991 set_10b(info, 0);
2992 for (tm = 0; tm < 2; tm++) {
2993 int totalrank;
2994
2995 set_178(tm ? info->cached_training->reg178_largest : info->
2996 cached_training->reg178_smallest);
2997
2998 totalrank = 0;
2999 /* Check timing ranges. With i == 0 we check smallest one and with
3000 i == 1 the largest bound. With j == 0 we check that on the bound
3001 it still works whereas with j == 1 we check that just outside of
3002 bound we fail.
3003 */
3004 FOR_POPULATED_RANKS_BACKWARDS {
3005 for (i = 0; i < 2; i++) {
3006 for (lane = 0; lane < 8; lane++) {
3007 write_500(info, channel,
3008 info->cached_training->
3009 timing2_bounds[channel][slot]
3010 [rank][lane][i],
3011 get_timing_register_addr(lane,
3012 3,
3013 slot,
3014 rank),
3015 9, 1);
3016
3017 if (!i)
3018 write_500(info, channel,
3019 info->
3020 cached_training->
3021 timing2_offset
3022 [channel][slot][rank]
3023 [lane],
3024 get_timing_register_addr
3025 (lane, 2, slot, rank),
3026 9, 1);
3027 write_500(info, channel,
3028 i ? info->cached_training->
3029 timing_bounds[tm][channel]
3030 [slot][rank][lane].
3031 largest : info->
3032 cached_training->
3033 timing_bounds[tm][channel]
3034 [slot][rank][lane].smallest,
3035 get_timing_register_addr(lane,
3036 0,
3037 slot,
3038 rank),
3039 9, 1);
3040 write_500(info, channel,
3041 info->cached_training->
3042 timing_offset[channel][slot]
3043 [rank][lane] +
3044 (i ? info->cached_training->
3045 timing_bounds[tm][channel]
3046 [slot][rank][lane].
3047 largest : info->
3048 cached_training->
3049 timing_bounds[tm][channel]
3050 [slot][rank][lane].
3051 smallest) - 64,
3052 get_timing_register_addr(lane,
3053 1,
3054 slot,
3055 rank),
3056 9, 1);
3057 }
3058 for (j = 0; j < 2; j++) {
3059 u8 failmask;
3060 u8 expected_failmask;
3061 char reg1b3;
3062
3063 reg1b3 = (j == 1) + 4;
3064 reg1b3 =
3065 j == i ? reg1b3 : (-reg1b3) & 0x3f;
3066 write_1d0(reg1b3, 0x1bb, 6, 1);
3067 write_1d0(reg1b3, 0x1b3, 6, 1);
3068 write_1d0(reg1b3, 0x1a3, 6, 1);
3069
3070 flip = !flip;
3071 write_testing(info, totalrank, flip);
3072 failmask =
3073 check_testing(info, totalrank,
3074 flip);
3075 expected_failmask =
3076 j == 0 ? 0x00 : 0xff;
3077 if (failmask != expected_failmask)
3078 goto fail;
3079 }
3080 }
3081 totalrank++;
3082 }
3083 }
3084
3085 set_178(info->cached_training->reg178_center);
3086 if (info->use_ecc)
3087 set_ecc(1);
3088 write_training_data(info);
3089 write_1d0(0, 322, 3, 1);
3090 info->training = *info->cached_training;
3091
3092 write_1d0(0, 0x1bb, 6, 1);
3093 write_1d0(0, 0x1b3, 6, 1);
3094 write_1d0(0, 0x1a3, 6, 1);
3095 write_mchbar8(0x243, saved_243[0]);
3096 write_mchbar8(0x643, saved_243[1]);
3097
3098 return 1;
3099
3100fail:
3101 FOR_POPULATED_RANKS {
3102 write_500_timings_type(info, channel, slot, rank, 1);
3103 write_500_timings_type(info, channel, slot, rank, 2);
3104 write_500_timings_type(info, channel, slot, rank, 3);
3105 }
3106
3107 write_1d0(0, 0x1bb, 6, 1);
3108 write_1d0(0, 0x1b3, 6, 1);
3109 write_1d0(0, 0x1a3, 6, 1);
3110 write_mchbar8(0x243, saved_243[0]);
3111 write_mchbar8(0x643, saved_243[1]);
3112
3113 return 0;
3114}
3115
3116static void do_ram_training(struct raminfo *info)
3117{
3118 u8 saved_243[2];
3119 int totalrank = 0;
3120 u8 reg_178;
3121 int niter;
3122
3123 timing_bounds_t timings[64];
3124 int lane, rank, slot, channel;
3125 u8 reg178_center;
3126
3127 write_1d0(2, 0x142, 3, 1);
3128 saved_243[0] = read_mchbar8(0x243);
3129 saved_243[1] = read_mchbar8(0x643);
3130 write_mchbar8(0x243, saved_243[0] | 2);
3131 write_mchbar8(0x643, saved_243[1] | 2);
3132 switch (info->clock_speed_index) {
3133 case 0:
3134 niter = 5;
3135 break;
3136 case 1:
3137 niter = 10;
3138 break;
3139 default:
3140 niter = 19;
3141 break;
3142 }
3143 set_ecc(0);
3144
3145 FOR_POPULATED_RANKS_BACKWARDS {
3146 int i;
3147
3148 write_500_timings_type(info, channel, slot, rank, 0);
3149
3150 write_testing(info, totalrank, 0);
3151 for (i = 0; i < niter; i++) {
3152 write_testing_type2(info, totalrank, 2, i, 0);
3153 write_testing_type2(info, totalrank, 3, i, 1);
3154 }
3155 pcie_write_config8(NORTHBRIDGE, 0xc0, 0x01);
3156 totalrank++;
3157 }
3158
3159 if (reg178_min[info->clock_speed_index] <
3160 reg178_max[info->clock_speed_index])
3161 memset(timings[reg178_min[info->clock_speed_index]], 0,
3162 sizeof(timings[0]) *
3163 (reg178_max[info->clock_speed_index] -
3164 reg178_min[info->clock_speed_index]));
3165 for (reg_178 = reg178_min[info->clock_speed_index];
3166 reg_178 < reg178_max[info->clock_speed_index];
3167 reg_178 += reg178_step[info->clock_speed_index]) {
3168 totalrank = 0;
3169 set_178(reg_178);
3170 for (channel = NUM_CHANNELS - 1; channel >= 0; channel--)
3171 for (slot = 0; slot < NUM_SLOTS; slot++)
3172 for (rank = 0; rank < NUM_RANKS; rank++) {
3173 memset(&timings[reg_178][channel][slot]
3174 [rank][0].smallest, 0, 16);
3175 if (info->
3176 populated_ranks[channel][slot]
3177 [rank]) {
3178 train_ram_at_178(info, channel,
3179 slot, rank,
3180 totalrank,
3181 reg_178, 1,
3182 niter,
3183 timings);
3184 totalrank++;
3185 }
3186 }
3187 }
3188
3189 reg178_center = choose_reg178(info, timings);
3190
3191 FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 8; lane++) {
3192 info->training.timing_bounds[0][channel][slot][rank][lane].
3193 smallest =
3194 timings[info->training.
3195 reg178_smallest][channel][slot][rank][lane].
3196 smallest;
3197 info->training.timing_bounds[0][channel][slot][rank][lane].
3198 largest =
3199 timings[info->training.
3200 reg178_smallest][channel][slot][rank][lane].largest;
3201 info->training.timing_bounds[1][channel][slot][rank][lane].
3202 smallest =
3203 timings[info->training.
3204 reg178_largest][channel][slot][rank][lane].smallest;
3205 info->training.timing_bounds[1][channel][slot][rank][lane].
3206 largest =
3207 timings[info->training.
3208 reg178_largest][channel][slot][rank][lane].largest;
3209 info->training.timing_offset[channel][slot][rank][lane] =
3210 info->training.lane_timings[1][channel][slot][rank][lane]
3211 -
3212 info->training.lane_timings[0][channel][slot][rank][lane] +
3213 64;
3214 }
3215
3216 if (info->silicon_revision == 1
3217 && (info->
3218 populated_ranks_mask[1] ^ (info->
3219 populated_ranks_mask[1] >> 2)) & 1) {
3220 int ranks_after_channel1;
3221
3222 totalrank = 0;
3223 for (reg_178 = reg178_center - 18;
3224 reg_178 <= reg178_center + 18; reg_178 += 18) {
3225 totalrank = 0;
3226 set_178(reg_178);
3227 for (slot = 0; slot < NUM_SLOTS; slot++)
3228 for (rank = 0; rank < NUM_RANKS; rank++) {
3229 if (info->
3230 populated_ranks[1][slot][rank]) {
3231 train_ram_at_178(info, 1, slot,
3232 rank,
3233 totalrank,
3234 reg_178, 0,
3235 niter,
3236 timings);
3237 totalrank++;
3238 }
3239 }
3240 }
3241 ranks_after_channel1 = totalrank;
3242
3243 for (reg_178 = reg178_center - 12;
3244 reg_178 <= reg178_center + 12; reg_178 += 12) {
3245 totalrank = ranks_after_channel1;
3246 set_178(reg_178);
3247 for (slot = 0; slot < NUM_SLOTS; slot++)
3248 for (rank = 0; rank < NUM_RANKS; rank++)
3249 if (info->
3250 populated_ranks[0][slot][rank]) {
3251 train_ram_at_178(info, 0, slot,
3252 rank,
3253 totalrank,
3254 reg_178, 0,
3255 niter,
3256 timings);
3257 totalrank++;
3258 }
3259
3260 }
3261 } else {
3262 for (reg_178 = reg178_center - 12;
3263 reg_178 <= reg178_center + 12; reg_178 += 12) {
3264 totalrank = 0;
3265 set_178(reg_178);
3266 FOR_POPULATED_RANKS_BACKWARDS {
3267 train_ram_at_178(info, channel, slot, rank,
3268 totalrank, reg_178, 0, niter,
3269 timings);
3270 totalrank++;
3271 }
3272 }
3273 }
3274
3275 set_178(reg178_center);
3276 FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 8; lane++) {
3277 u16 tm0;
3278
3279 tm0 =
3280 choose_training(info, channel, slot, rank, lane, timings,
3281 reg178_center);
3282 write_500(info, channel, tm0,
3283 get_timing_register_addr(lane, 0, slot, rank), 9, 1);
3284 write_500(info, channel,
3285 tm0 +
3286 info->training.
3287 lane_timings[1][channel][slot][rank][lane] -
3288 info->training.
3289 lane_timings[0][channel][slot][rank][lane],
3290 get_timing_register_addr(lane, 1, slot, rank), 9, 1);
3291 }
3292
3293 totalrank = 0;
3294 FOR_POPULATED_RANKS_BACKWARDS {
3295 try_timing_offsets(info, channel, slot, rank, totalrank);
3296 totalrank++;
3297 }
3298 write_mchbar8(0x243, saved_243[0]);
3299 write_mchbar8(0x643, saved_243[1]);
3300 write_1d0(0, 0x142, 3, 1);
3301 info->training.reg178_center = reg178_center;
3302}
3303
3304static void ram_training(struct raminfo *info)
3305{
3306 u16 saved_fc4;
3307
3308 saved_fc4 = read_mchbar16(0xfc4);
3309 write_mchbar16(0xfc4, 0xffff);
3310
3311 if (info->revision >= 8)
3312 read_4090(info);
3313
3314 if (!try_cached_training(info))
3315 do_ram_training(info);
3316 if ((info->silicon_revision == 2 || info->silicon_revision == 3)
3317 && info->clock_speed_index < 2)
3318 set_10b(info, 1);
3319 write_mchbar16(0xfc4, saved_fc4);
3320}
3321
3322static unsigned gcd(unsigned a, unsigned b)
3323{
3324 unsigned t;
3325 if (a > b) {
3326 t = a;
3327 a = b;
3328 b = t;
3329 }
3330 /* invariant a < b. */
3331 while (a) {
3332 t = b % a;
3333 b = a;
3334 a = t;
3335 }
3336 return b;
3337}
3338
3339static inline int div_roundup(int a, int b)
3340{
Edward O'Callaghan7116ac82014-07-08 01:53:24 +10003341 return CEIL_DIV(a, b);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003342}
3343
3344static unsigned lcm(unsigned a, unsigned b)
3345{
3346 return (a * b) / gcd(a, b);
3347}
3348
3349struct stru1 {
3350 u8 freqs_reversed;
3351 u8 freq_diff_reduced;
3352 u8 freq_min_reduced;
3353 u8 divisor_f4_to_fmax;
3354 u8 divisor_f3_to_fmax;
3355 u8 freq4_to_max_remainder;
3356 u8 freq3_to_2_remainder;
3357 u8 freq3_to_2_remaindera;
3358 u8 freq4_to_2_remainder;
3359 int divisor_f3_to_f1, divisor_f4_to_f2;
3360 int common_time_unit_ps;
3361 int freq_max_reduced;
3362};
3363
3364static void
3365compute_frequence_ratios(struct raminfo *info, u16 freq1, u16 freq2,
3366 int num_cycles_2, int num_cycles_1, int round_it,
3367 int add_freqs, struct stru1 *result)
3368{
3369 int g;
3370 int common_time_unit_ps;
3371 int freq1_reduced, freq2_reduced;
3372 int freq_min_reduced;
3373 int freq_max_reduced;
3374 int freq3, freq4;
3375
3376 g = gcd(freq1, freq2);
3377 freq1_reduced = freq1 / g;
3378 freq2_reduced = freq2 / g;
3379 freq_min_reduced = min(freq1_reduced, freq2_reduced);
3380 freq_max_reduced = max(freq1_reduced, freq2_reduced);
3381
3382 common_time_unit_ps = div_roundup(900000, lcm(freq1, freq2));
3383 freq3 = div_roundup(num_cycles_2, common_time_unit_ps) - 1;
3384 freq4 = div_roundup(num_cycles_1, common_time_unit_ps) - 1;
3385 if (add_freqs) {
3386 freq3 += freq2_reduced;
3387 freq4 += freq1_reduced;
3388 }
3389
3390 if (round_it) {
3391 result->freq3_to_2_remainder = 0;
3392 result->freq3_to_2_remaindera = 0;
3393 result->freq4_to_max_remainder = 0;
3394 result->divisor_f4_to_f2 = 0;
3395 result->divisor_f3_to_f1 = 0;
3396 } else {
3397 if (freq2_reduced < freq1_reduced) {
3398 result->freq3_to_2_remainder =
3399 result->freq3_to_2_remaindera =
3400 freq3 % freq1_reduced - freq1_reduced + 1;
3401 result->freq4_to_max_remainder =
3402 -(freq4 % freq1_reduced);
3403 result->divisor_f3_to_f1 = freq3 / freq1_reduced;
3404 result->divisor_f4_to_f2 =
3405 (freq4 -
3406 (freq1_reduced - freq2_reduced)) / freq2_reduced;
3407 result->freq4_to_2_remainder =
3408 -(char)((freq1_reduced - freq2_reduced) +
3409 ((u8) freq4 -
3410 (freq1_reduced -
3411 freq2_reduced)) % (u8) freq2_reduced);
3412 } else {
3413 if (freq2_reduced > freq1_reduced) {
3414 result->freq4_to_max_remainder =
3415 (freq4 % freq2_reduced) - freq2_reduced + 1;
3416 result->freq4_to_2_remainder =
3417 freq4 % freq_max_reduced -
3418 freq_max_reduced + 1;
3419 } else {
3420 result->freq4_to_max_remainder =
3421 -(freq4 % freq2_reduced);
3422 result->freq4_to_2_remainder =
3423 -(char)(freq4 % freq_max_reduced);
3424 }
3425 result->divisor_f4_to_f2 = freq4 / freq2_reduced;
3426 result->divisor_f3_to_f1 =
3427 (freq3 -
3428 (freq2_reduced - freq1_reduced)) / freq1_reduced;
3429 result->freq3_to_2_remainder = -(freq3 % freq2_reduced);
3430 result->freq3_to_2_remaindera =
3431 -(char)((freq_max_reduced - freq_min_reduced) +
3432 (freq3 -
3433 (freq_max_reduced -
3434 freq_min_reduced)) % freq1_reduced);
3435 }
3436 }
3437 result->divisor_f3_to_fmax = freq3 / freq_max_reduced;
3438 result->divisor_f4_to_fmax = freq4 / freq_max_reduced;
3439 if (round_it) {
3440 if (freq2_reduced > freq1_reduced) {
3441 if (freq3 % freq_max_reduced)
3442 result->divisor_f3_to_fmax++;
3443 }
3444 if (freq2_reduced < freq1_reduced) {
3445 if (freq4 % freq_max_reduced)
3446 result->divisor_f4_to_fmax++;
3447 }
3448 }
3449 result->freqs_reversed = (freq2_reduced < freq1_reduced);
3450 result->freq_diff_reduced = freq_max_reduced - freq_min_reduced;
3451 result->freq_min_reduced = freq_min_reduced;
3452 result->common_time_unit_ps = common_time_unit_ps;
3453 result->freq_max_reduced = freq_max_reduced;
3454}
3455
3456static void
3457set_2d5x_reg(struct raminfo *info, u16 reg, u16 freq1, u16 freq2,
3458 int num_cycles_2, int num_cycles_1, int num_cycles_3,
3459 int num_cycles_4, int reverse)
3460{
3461 struct stru1 vv;
3462 char multiplier;
3463
3464 compute_frequence_ratios(info, freq1, freq2, num_cycles_2, num_cycles_1,
3465 0, 1, &vv);
3466
3467 multiplier =
3468 div_roundup(max
3469 (div_roundup(num_cycles_2, vv.common_time_unit_ps) +
3470 div_roundup(num_cycles_3, vv.common_time_unit_ps),
3471 div_roundup(num_cycles_1,
3472 vv.common_time_unit_ps) +
3473 div_roundup(num_cycles_4, vv.common_time_unit_ps))
3474 + vv.freq_min_reduced - 1, vv.freq_max_reduced) - 1;
3475
3476 u32 y =
3477 (u8) ((vv.freq_max_reduced - vv.freq_min_reduced) +
3478 vv.freq_max_reduced * multiplier)
3479 | (vv.
3480 freqs_reversed << 8) | ((u8) (vv.freq_min_reduced *
3481 multiplier) << 16) | ((u8) (vv.
3482 freq_min_reduced
3483 *
3484 multiplier)
3485 << 24);
3486 u32 x =
3487 vv.freq3_to_2_remaindera | (vv.freq4_to_2_remainder << 8) | (vv.
3488 divisor_f3_to_f1
3489 << 16)
3490 | (vv.divisor_f4_to_f2 << 20) | (vv.freq_min_reduced << 24);
3491 if (reverse) {
3492 write_mchbar32(reg, y);
3493 write_mchbar32(reg + 4, x);
3494 } else {
3495 write_mchbar32(reg + 4, y);
3496 write_mchbar32(reg, x);
3497 }
3498}
3499
3500static void
3501set_6d_reg(struct raminfo *info, u16 reg, u16 freq1, u16 freq2,
3502 int num_cycles_1, int num_cycles_2, int num_cycles_3,
3503 int num_cycles_4)
3504{
3505 struct stru1 ratios1;
3506 struct stru1 ratios2;
3507
3508 compute_frequence_ratios(info, freq1, freq2, num_cycles_1, num_cycles_2,
3509 0, 1, &ratios2);
3510 compute_frequence_ratios(info, freq1, freq2, num_cycles_3, num_cycles_4,
3511 0, 1, &ratios1);
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003512 printk (BIOS_SPEW, "[%x] <= %x\n", reg,
3513 ratios1.freq4_to_max_remainder | (ratios2.
3514 freq4_to_max_remainder
3515 << 8)
3516 | (ratios1.divisor_f4_to_fmax << 16) | (ratios2.
3517 divisor_f4_to_fmax
3518 << 20));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003519 write_mchbar32(reg,
3520 ratios1.freq4_to_max_remainder | (ratios2.
3521 freq4_to_max_remainder
3522 << 8)
3523 | (ratios1.divisor_f4_to_fmax << 16) | (ratios2.
3524 divisor_f4_to_fmax
3525 << 20));
3526}
3527
3528static void
3529set_2dx8_reg(struct raminfo *info, u16 reg, u8 mode, u16 freq1, u16 freq2,
3530 int num_cycles_2, int num_cycles_1, int round_it, int add_freqs)
3531{
3532 struct stru1 ratios;
3533
3534 compute_frequence_ratios(info, freq1, freq2, num_cycles_2, num_cycles_1,
3535 round_it, add_freqs, &ratios);
3536 switch (mode) {
3537 case 0:
3538 write_mchbar32(reg + 4,
3539 ratios.freq_diff_reduced | (ratios.
3540 freqs_reversed <<
3541 8));
3542 write_mchbar32(reg,
3543 ratios.freq3_to_2_remainder | (ratios.
3544 freq4_to_max_remainder
3545 << 8)
3546 | (ratios.divisor_f3_to_fmax << 16) | (ratios.
3547 divisor_f4_to_fmax
3548 << 20) |
3549 (ratios.freq_min_reduced << 24));
3550 break;
3551
3552 case 1:
3553 write_mchbar32(reg,
3554 ratios.freq3_to_2_remainder | (ratios.
3555 divisor_f3_to_fmax
3556 << 16));
3557 break;
3558
3559 case 2:
3560 write_mchbar32(reg,
3561 ratios.freq3_to_2_remainder | (ratios.
3562 freq4_to_max_remainder
3563 << 8) | (ratios.
3564 divisor_f3_to_fmax
3565 << 16) |
3566 (ratios.divisor_f4_to_fmax << 20));
3567 break;
3568
3569 case 4:
3570 write_mchbar32(reg, (ratios.divisor_f3_to_fmax << 4)
3571 | (ratios.divisor_f4_to_fmax << 8) | (ratios.
3572 freqs_reversed
3573 << 12) |
3574 (ratios.freq_min_reduced << 16) | (ratios.
3575 freq_diff_reduced
3576 << 24));
3577 break;
3578 }
3579}
3580
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003581static void set_2dxx_series(struct raminfo *info, int s3resume)
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003582{
3583 set_2dx8_reg(info, 0x2d00, 0, 0x78, frequency_11(info) / 2, 1359, 1005,
3584 0, 1);
3585 set_2dx8_reg(info, 0x2d08, 0, 0x78, 0x78, 3273, 5033, 1, 1);
3586 set_2dx8_reg(info, 0x2d10, 0, 0x78, info->fsb_frequency, 1475, 1131, 0,
3587 1);
3588 set_2dx8_reg(info, 0x2d18, 0, 2 * info->fsb_frequency,
3589 frequency_11(info), 1231, 1524, 0, 1);
3590 set_2dx8_reg(info, 0x2d20, 0, 2 * info->fsb_frequency,
3591 frequency_11(info) / 2, 1278, 2008, 0, 1);
3592 set_2dx8_reg(info, 0x2d28, 0, info->fsb_frequency, frequency_11(info),
3593 1167, 1539, 0, 1);
3594 set_2dx8_reg(info, 0x2d30, 0, info->fsb_frequency,
3595 frequency_11(info) / 2, 1403, 1318, 0, 1);
3596 set_2dx8_reg(info, 0x2d38, 0, info->fsb_frequency, 0x78, 3460, 5363, 1,
3597 1);
3598 set_2dx8_reg(info, 0x2d40, 0, info->fsb_frequency, 0x3c, 2792, 5178, 1,
3599 1);
3600 set_2dx8_reg(info, 0x2d48, 0, 2 * info->fsb_frequency, 0x78, 2738, 4610,
3601 1, 1);
3602 set_2dx8_reg(info, 0x2d50, 0, info->fsb_frequency, 0x78, 2819, 5932, 1,
3603 1);
3604 set_2dx8_reg(info, 0x6d4, 1, info->fsb_frequency,
3605 frequency_11(info) / 2, 4000, 0, 0, 0);
3606 set_2dx8_reg(info, 0x6d8, 2, info->fsb_frequency,
3607 frequency_11(info) / 2, 4000, 4000, 0, 0);
3608
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003609 if (s3resume) {
3610 printk (BIOS_SPEW, "[6dc] <= %x\n", info->cached_training->reg_6dc);
3611 write_mchbar32(0x6dc, info->cached_training->reg_6dc);
3612 } else
3613 set_6d_reg(info, 0x6dc, 2 * info->fsb_frequency, frequency_11(info), 0,
3614 info->delay46_ps[0], 0,
3615 info->delay54_ps[0]);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003616 set_2dx8_reg(info, 0x6e0, 1, 2 * info->fsb_frequency,
3617 frequency_11(info), 2500, 0, 0, 0);
3618 set_2dx8_reg(info, 0x6e4, 1, 2 * info->fsb_frequency,
3619 frequency_11(info) / 2, 3500, 0, 0, 0);
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003620 if (s3resume) {
3621 printk (BIOS_SPEW, "[6e8] <= %x\n", info->cached_training->reg_6e8);
3622 write_mchbar32(0x6e8, info->cached_training->reg_6e8);
3623 } else
3624 set_6d_reg(info, 0x6e8, 2 * info->fsb_frequency, frequency_11(info), 0,
3625 info->delay46_ps[1], 0,
3626 info->delay54_ps[1]);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003627 set_2d5x_reg(info, 0x2d58, 0x78, 0x78, 864, 1195, 762, 786, 0);
3628 set_2d5x_reg(info, 0x2d60, 0x195, info->fsb_frequency, 1352, 725, 455,
3629 470, 0);
3630 set_2d5x_reg(info, 0x2d68, 0x195, 0x3c, 2707, 5632, 3277, 2207, 0);
3631 set_2d5x_reg(info, 0x2d70, 0x195, frequency_11(info) / 2, 1276, 758,
3632 454, 459, 0);
3633 set_2d5x_reg(info, 0x2d78, 0x195, 0x78, 1021, 799, 510, 513, 0);
3634 set_2d5x_reg(info, 0x2d80, info->fsb_frequency, 0xe1, 0, 2862, 2579,
3635 2588, 0);
3636 set_2d5x_reg(info, 0x2d88, info->fsb_frequency, 0xe1, 0, 2690, 2405,
3637 2405, 0);
3638 set_2d5x_reg(info, 0x2da0, 0x78, 0xe1, 0, 2560, 2264, 2251, 0);
3639 set_2d5x_reg(info, 0x2da8, 0x195, frequency_11(info), 1060, 775, 484,
3640 480, 0);
3641 set_2d5x_reg(info, 0x2db0, 0x195, 0x78, 4183, 6023, 2217, 2048, 0);
3642 write_mchbar32(0x2dbc, ((frequency_11(info) / 2) - 1) | 0xe00000);
3643 write_mchbar32(0x2db8, ((info->fsb_frequency - 1) << 16) | 0x77);
3644}
3645
3646static u16 get_max_timing(struct raminfo *info, int channel)
3647{
3648 int slot, rank, lane;
3649 u16 ret = 0;
3650
3651 if ((read_mchbar8(0x2ca8) >> 2) < 1)
3652 return 384;
3653
3654 if (info->revision < 8)
3655 return 256;
3656
3657 for (slot = 0; slot < NUM_SLOTS; slot++)
3658 for (rank = 0; rank < NUM_RANKS; rank++)
3659 if (info->populated_ranks[channel][slot][rank])
3660 for (lane = 0; lane < 8 + info->use_ecc; lane++)
3661 ret = max(ret, read_500(info, channel,
3662 get_timing_register_addr
3663 (lane, 0, slot,
3664 rank), 9));
3665 return ret;
3666}
3667
3668static void set_274265(struct raminfo *info)
3669{
3670 int delay_a_ps, delay_b_ps, delay_c_ps, delay_d_ps;
3671 int delay_e_ps, delay_e_cycles, delay_f_cycles;
3672 int delay_e_over_cycle_ps;
3673 int cycletime_ps;
3674 int channel;
3675
3676 delay_a_ps = 4 * halfcycle_ps(info) + 6 * fsbcycle_ps(info);
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003677 info->training.reg2ca9_bit0 = 0;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003678 for (channel = 0; channel < NUM_CHANNELS; channel++) {
3679 cycletime_ps =
3680 900000 / lcm(2 * info->fsb_frequency, frequency_11(info));
3681 delay_d_ps =
3682 (halfcycle_ps(info) * get_max_timing(info, channel) >> 6)
3683 - info->some_delay_3_ps_rounded + 200;
3684 if (!
3685 ((info->silicon_revision == 0
3686 || info->silicon_revision == 1)
3687 && (info->revision >= 8)))
3688 delay_d_ps += halfcycle_ps(info) * 2;
3689 delay_d_ps +=
3690 halfcycle_ps(info) * (!info->revision_flag_1 +
3691 info->some_delay_2_halfcycles_ceil +
3692 2 * info->some_delay_1_cycle_floor +
3693 info->clock_speed_index +
3694 2 * info->cas_latency - 7 + 11);
3695 delay_d_ps += info->revision >= 8 ? 2758 : 4428;
3696
3697 write_mchbar32(0x140,
3698 (read_mchbar32(0x140) & 0xfaffffff) | 0x2000000);
3699 write_mchbar32(0x138,
3700 (read_mchbar32(0x138) & 0xfaffffff) | 0x2000000);
3701 if ((read_mchbar8(0x144) & 0x1f) > 0x13)
3702 delay_d_ps += 650;
3703 delay_c_ps = delay_d_ps + 1800;
3704 if (delay_c_ps <= delay_a_ps)
3705 delay_e_ps = 0;
3706 else
3707 delay_e_ps =
3708 cycletime_ps * div_roundup(delay_c_ps - delay_a_ps,
3709 cycletime_ps);
3710
3711 delay_e_over_cycle_ps = delay_e_ps % (2 * halfcycle_ps(info));
3712 delay_e_cycles = delay_e_ps / (2 * halfcycle_ps(info));
3713 delay_f_cycles =
3714 div_roundup(2500 - delay_e_over_cycle_ps,
3715 2 * halfcycle_ps(info));
3716 if (delay_f_cycles > delay_e_cycles) {
3717 info->delay46_ps[channel] = delay_e_ps;
3718 delay_e_cycles = 0;
3719 } else {
3720 info->delay46_ps[channel] =
3721 delay_e_over_cycle_ps +
3722 2 * halfcycle_ps(info) * delay_f_cycles;
3723 delay_e_cycles -= delay_f_cycles;
3724 }
3725
3726 if (info->delay46_ps[channel] < 2500) {
3727 info->delay46_ps[channel] = 2500;
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003728 info->training.reg2ca9_bit0 = 1;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003729 }
3730 delay_b_ps = halfcycle_ps(info) + delay_c_ps;
3731 if (delay_b_ps <= delay_a_ps)
3732 delay_b_ps = 0;
3733 else
3734 delay_b_ps -= delay_a_ps;
3735 info->delay54_ps[channel] =
3736 cycletime_ps * div_roundup(delay_b_ps,
3737 cycletime_ps) -
3738 2 * halfcycle_ps(info) * delay_e_cycles;
3739 if (info->delay54_ps[channel] < 2500)
3740 info->delay54_ps[channel] = 2500;
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003741 info->training.reg274265[channel][0] = delay_e_cycles;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003742 if (delay_d_ps + 7 * halfcycle_ps(info) <=
3743 24 * halfcycle_ps(info))
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003744 info->training.reg274265[channel][1] = 0;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003745 else
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003746 info->training.reg274265[channel][1] =
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003747 div_roundup(delay_d_ps + 7 * halfcycle_ps(info),
3748 4 * halfcycle_ps(info)) - 6;
3749 write_mchbar32((channel << 10) + 0x274,
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003750 info->training.reg274265[channel][1]
3751 | (info->training.reg274265[channel][0] << 16));
3752 info->training.reg274265[channel][2] =
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003753 div_roundup(delay_c_ps + 3 * fsbcycle_ps(info),
3754 4 * halfcycle_ps(info)) + 1;
3755 write_mchbar16((channel << 10) + 0x265,
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003756 info->training.reg274265[channel][2] << 8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003757 }
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003758 if (info->training.reg2ca9_bit0)
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003759 write_mchbar8(0x2ca9, read_mchbar8(0x2ca9) | 1);
3760 else
3761 write_mchbar8(0x2ca9, read_mchbar8(0x2ca9) & ~1);
3762}
3763
3764static void restore_274265(struct raminfo *info)
3765{
3766 int channel;
3767
3768 for (channel = 0; channel < NUM_CHANNELS; channel++) {
3769 write_mchbar32((channel << 10) + 0x274,
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003770 (info->cached_training->reg274265[channel][0] << 16)
3771 | info->cached_training->reg274265[channel][1]);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003772 write_mchbar16((channel << 10) + 0x265,
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003773 info->cached_training->reg274265[channel][2] << 8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003774 }
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003775 if (info->cached_training->reg2ca9_bit0)
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003776 write_mchbar8(0x2ca9, read_mchbar8(0x2ca9) | 1);
3777 else
3778 write_mchbar8(0x2ca9, read_mchbar8(0x2ca9) & ~1);
3779}
3780
3781#if REAL
3782static void dmi_setup(void)
3783{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08003784 gav(read8(DEFAULT_DMIBAR + 0x254));
3785 write8(DEFAULT_DMIBAR + 0x254, 0x1);
3786 write16(DEFAULT_DMIBAR + 0x1b8, 0x18f2);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003787 read_mchbar16(0x48);
3788 write_mchbar16(0x48, 0x2);
3789
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08003790 write32(DEFAULT_DMIBAR + 0xd68, read32(DEFAULT_DMIBAR + 0xd68) | 0x08000000);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003791
3792 outl((gav(inl(DEFAULT_GPIOBASE | 0x38)) & ~0x140000) | 0x400000,
3793 DEFAULT_GPIOBASE | 0x38);
3794 gav(inb(DEFAULT_GPIOBASE | 0xe)); // = 0xfdcaff6e
3795}
3796#endif
3797
Vladimir Serbinenko9817a372014-02-19 22:07:12 +01003798void chipset_init(const int s3resume)
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003799{
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003800 u8 x2ca8;
Vladimir Serbinenko55391c42014-08-03 14:51:00 +02003801 u16 ggc;
3802 u8 gfxsize;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003803
Vladimir Serbinenko9817a372014-02-19 22:07:12 +01003804 x2ca8 = read_mchbar8(0x2ca8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003805 if ((x2ca8 & 1) || (x2ca8 == 8 && !s3resume)) {
3806 printk(BIOS_DEBUG, "soft reset detected, rebooting properly\n");
3807 write_mchbar8(0x2ca8, 0);
Vladimir Serbinenkoe1eef692014-02-19 22:08:51 +01003808 outb(0x6, 0xcf9);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003809#if REAL
Patrick Georgi546953c2014-11-29 10:38:17 +01003810 halt();
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003811#else
3812 printf("CP5\n");
3813 exit(0);
3814#endif
3815 }
3816#if !REAL
3817 if (!s3resume) {
3818 pre_raminit_3(x2ca8);
3819 }
Vladimir Serbinenkof62669c2014-01-09 10:59:38 +01003820 pre_raminit_4a(x2ca8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003821#endif
3822
3823 dmi_setup();
3824
3825 write_mchbar16(0x1170, 0xa880);
3826 write_mchbar8(0x11c1, 0x1);
3827 write_mchbar16(0x1170, 0xb880);
3828 read_mchbar8(0x1210);
3829 write_mchbar8(0x1210, 0x84);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003830
Vladimir Serbinenko55391c42014-08-03 14:51:00 +02003831 if (get_option(&gfxsize, "gfx_uma_size") != CB_SUCCESS) {
3832 /* 0 for 32MB */
3833 gfxsize = 0;
3834 }
3835
3836 ggc = 0xb00 | ((gfxsize + 5) << 4);
3837
3838 pcie_write_config16(NORTHBRIDGE, D0F0_GGC, ggc | 2);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003839
3840 u16 deven;
3841 deven = pcie_read_config16(NORTHBRIDGE, D0F0_DEVEN); // = 0x3
3842
3843 if (deven & 8) {
3844 write_mchbar8(0x2c30, 0x20);
3845 pcie_read_config8(NORTHBRIDGE, 0x8); // = 0x18
3846 write_mchbar16(0x2c30, read_mchbar16(0x2c30) | 0x200);
3847 write_mchbar16(0x2c32, 0x434);
3848 read_mchbar32(0x2c44);
3849 write_mchbar32(0x2c44, 0x1053687);
3850 pcie_read_config8(GMA, 0x62); // = 0x2
3851 pcie_write_config8(GMA, 0x62, 0x2);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08003852 read8(DEFAULT_RCBA + 0x2318);
3853 write8(DEFAULT_RCBA + 0x2318, 0x47);
3854 read8(DEFAULT_RCBA + 0x2320);
3855 write8(DEFAULT_RCBA + 0x2320, 0xfc);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003856 }
3857
3858 read_mchbar32(0x30);
3859 write_mchbar32(0x30, 0x40);
3860
Vladimir Serbinenko55391c42014-08-03 14:51:00 +02003861 pcie_write_config16(NORTHBRIDGE, D0F0_GGC, ggc);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08003862 gav(read32(DEFAULT_RCBA + 0x3428));
3863 write32(DEFAULT_RCBA + 0x3428, 0x1d);
Vladimir Serbinenko9817a372014-02-19 22:07:12 +01003864}
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003865
Vladimir Serbinenko9817a372014-02-19 22:07:12 +01003866void raminit(const int s3resume, const u8 *spd_addrmap)
3867{
3868 unsigned channel, slot, lane, rank;
3869 int i;
3870 struct raminfo info;
3871 u8 x2ca8;
3872 u16 deven;
Vladimir Serbinenkob16f0922014-06-07 16:27:27 +02003873 int cbmem_wasnot_inited;
Vladimir Serbinenko9817a372014-02-19 22:07:12 +01003874
3875 x2ca8 = read_mchbar8(0x2ca8);
3876 deven = pcie_read_config16(NORTHBRIDGE, D0F0_DEVEN);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003877
3878 memset(&info, 0x5a, sizeof(info));
3879
3880 info.last_500_command[0] = 0;
3881 info.last_500_command[1] = 0;
3882
3883 info.fsb_frequency = 135 * 2;
3884 info.board_lane_delay[0] = 0x14;
3885 info.board_lane_delay[1] = 0x07;
3886 info.board_lane_delay[2] = 0x07;
3887 info.board_lane_delay[3] = 0x08;
3888 info.board_lane_delay[4] = 0x56;
3889 info.board_lane_delay[5] = 0x04;
3890 info.board_lane_delay[6] = 0x04;
3891 info.board_lane_delay[7] = 0x05;
3892 info.board_lane_delay[8] = 0x10;
3893
3894 info.training.reg_178 = 0;
3895 info.training.reg_10b = 0;
3896
3897 info.heci_bar = 0;
3898 info.memory_reserved_for_heci_mb = 0;
3899
3900 /* before SPD */
3901 timestamp_add_now(101);
3902
3903 if (!s3resume || REAL) {
3904 pcie_read_config8(SOUTHBRIDGE, GEN_PMCON_2); // = 0x80
3905
3906 collect_system_info(&info);
3907
3908#if REAL
3909 /* Enable SMBUS. */
3910 enable_smbus();
3911#endif
3912
3913 memset(&info.populated_ranks, 0, sizeof(info.populated_ranks));
3914
3915 info.use_ecc = 1;
3916 for (channel = 0; channel < NUM_CHANNELS; channel++)
Vladimir Serbinenko2ab8ec72014-02-20 14:34:56 +01003917 for (slot = 0; slot < NUM_SLOTS; slot++) {
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003918 int v;
3919 int try;
3920 int addr;
3921 const u8 useful_addresses[] = {
3922 DEVICE_TYPE,
3923 MODULE_TYPE,
3924 DENSITY,
3925 RANKS_AND_DQ,
3926 MEMORY_BUS_WIDTH,
3927 TIMEBASE_DIVIDEND,
3928 TIMEBASE_DIVISOR,
3929 CYCLETIME,
3930 CAS_LATENCIES_LSB,
3931 CAS_LATENCIES_MSB,
3932 CAS_LATENCY_TIME,
3933 0x11, 0x12, 0x13, 0x14, 0x15,
3934 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
3935 0x1c, 0x1d,
3936 THERMAL_AND_REFRESH,
3937 0x20,
3938 REFERENCE_RAW_CARD_USED,
3939 RANK1_ADDRESS_MAPPING,
3940 0x75, 0x76, 0x77, 0x78,
3941 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e,
3942 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84,
3943 0x85, 0x86, 0x87, 0x88,
3944 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
3945 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94,
3946 0x95
3947 };
Vladimir Serbinenko902626c2014-02-16 17:22:26 +01003948 if (!spd_addrmap[2 * channel + slot])
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003949 continue;
3950 for (try = 0; try < 5; try++) {
Vladimir Serbinenko902626c2014-02-16 17:22:26 +01003951 v = smbus_read_byte(spd_addrmap[2 * channel + slot],
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003952 DEVICE_TYPE);
3953 if (v >= 0)
3954 break;
3955 }
3956 if (v < 0)
3957 continue;
3958 for (addr = 0;
3959 addr <
3960 sizeof(useful_addresses) /
3961 sizeof(useful_addresses[0]); addr++)
3962 gav(info.
3963 spd[channel][0][useful_addresses
3964 [addr]] =
Vladimir Serbinenko902626c2014-02-16 17:22:26 +01003965 smbus_read_byte(spd_addrmap[2 * channel + slot],
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003966 useful_addresses
3967 [addr]));
3968 if (info.spd[channel][0][DEVICE_TYPE] != 11)
3969 die("Only DDR3 is supported");
3970
3971 v = info.spd[channel][0][RANKS_AND_DQ];
3972 info.populated_ranks[channel][0][0] = 1;
3973 info.populated_ranks[channel][0][1] =
3974 ((v >> 3) & 7);
3975 if (((v >> 3) & 7) > 1)
3976 die("At most 2 ranks are supported");
3977 if ((v & 7) == 0 || (v & 7) > 2)
3978 die("Only x8 and x16 modules are supported");
3979 if ((info.
3980 spd[channel][slot][MODULE_TYPE] & 0xF) != 2
3981 && (info.
3982 spd[channel][slot][MODULE_TYPE] & 0xF)
3983 != 3)
3984 die("Registered memory is not supported");
3985 info.is_x16_module[channel][0] = (v & 7) - 1;
3986 info.density[channel][slot] =
3987 info.spd[channel][slot][DENSITY] & 0xF;
3988 if (!
3989 (info.
3990 spd[channel][slot][MEMORY_BUS_WIDTH] &
3991 0x18))
3992 info.use_ecc = 0;
3993 }
3994
3995 gav(0x55);
3996
3997 for (channel = 0; channel < NUM_CHANNELS; channel++) {
3998 int v = 0;
3999 for (slot = 0; slot < NUM_SLOTS; slot++)
4000 for (rank = 0; rank < NUM_RANKS; rank++)
4001 v |= info.
4002 populated_ranks[channel][slot][rank]
4003 << (2 * slot + rank);
4004 info.populated_ranks_mask[channel] = v;
4005 }
4006
4007 gav(0x55);
4008
4009 gav(pcie_read_config32(NORTHBRIDGE, D0F0_CAPID0 + 4));
4010 }
4011
4012 /* after SPD */
4013 timestamp_add_now(102);
4014
4015 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) & 0xfc);
4016#if !REAL
Alexandru Gagniuc86091f92015-09-30 20:23:09 -07004017 rdmsr (MTRR_PHYS_MASK (3));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004018#endif
4019
4020 collect_system_info(&info);
4021 calculate_timings(&info);
4022
4023#if !REAL
4024 pcie_write_config8(NORTHBRIDGE, 0xdf, 0x82);
4025#endif
4026
4027 if (!s3resume) {
4028 u8 reg8 = pcie_read_config8(SOUTHBRIDGE, GEN_PMCON_2);
4029 if (x2ca8 == 0 && (reg8 & 0x80)) {
4030 /* Don't enable S4-assertion stretch. Makes trouble on roda/rk9.
4031 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
4032 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8 | 0x08);
4033 */
4034
4035 /* Clear bit7. */
4036
4037 pci_write_config8(SOUTHBRIDGE, GEN_PMCON_2,
4038 (reg8 & ~(1 << 7)));
4039
4040 printk(BIOS_INFO,
4041 "Interrupted RAM init, reset required.\n");
4042 outb(0x6, 0xcf9);
4043#if REAL
Patrick Georgi546953c2014-11-29 10:38:17 +01004044 halt();
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004045#endif
4046 }
4047 }
4048#if !REAL
4049 gav(read_mchbar8(0x2ca8)); ///!!!!
4050#endif
4051
4052 if (!s3resume && x2ca8 == 0)
4053 pcie_write_config8(SOUTHBRIDGE, GEN_PMCON_2,
4054 pcie_read_config8(SOUTHBRIDGE, GEN_PMCON_2) | 0x80);
4055
4056 compute_derived_timings(&info);
4057
4058 if (x2ca8 == 0) {
4059 gav(read_mchbar8(0x164));
4060 write_mchbar8(0x164, 0x26);
4061 write_mchbar16(0x2c20, 0x10);
4062 }
4063
4064 write_mchbar32(0x18b4, read_mchbar32(0x18b4) | 0x210000); /* OK */
4065 write_mchbar32(0x1890, read_mchbar32(0x1890) | 0x2000000); /* OK */
4066 write_mchbar32(0x18b4, read_mchbar32(0x18b4) | 0x8000);
4067
4068 gav(pcie_read_config32(PCI_DEV(0xff, 2, 1), 0x50)); // !!!!
4069 pcie_write_config8(PCI_DEV(0xff, 2, 1), 0x54, 0x12);
4070
4071 gav(read_mchbar16(0x2c10)); // !!!!
4072 write_mchbar16(0x2c10, 0x412);
4073 gav(read_mchbar16(0x2c10)); // !!!!
4074 write_mchbar16(0x2c12, read_mchbar16(0x2c12) | 0x100); /* OK */
4075
4076 gav(read_mchbar8(0x2ca8)); // !!!!
4077 write_mchbar32(0x1804,
4078 (read_mchbar32(0x1804) & 0xfffffffc) | 0x8400080);
4079
4080 pcie_read_config32(PCI_DEV(0xff, 2, 1), 0x6c); // !!!!
4081 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0x6c, 0x40a0a0);
4082 gav(read_mchbar32(0x1c04)); // !!!!
4083 gav(read_mchbar32(0x1804)); // !!!!
4084
4085 if (x2ca8 == 0) {
4086 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) | 1);
4087 }
4088
4089 write_mchbar32(0x18d8, 0x120000);
4090 write_mchbar32(0x18dc, 0x30a484a);
4091 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xe0, 0x0);
4092 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xf4, 0x9444a);
4093 write_mchbar32(0x18d8, 0x40000);
4094 write_mchbar32(0x18dc, 0xb000000);
4095 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xe0, 0x60000);
4096 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xf4, 0x0);
4097 write_mchbar32(0x18d8, 0x180000);
4098 write_mchbar32(0x18dc, 0xc0000142);
4099 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xe0, 0x20000);
4100 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xf4, 0x142);
4101 write_mchbar32(0x18d8, 0x1e0000);
4102
4103 gav(read_mchbar32(0x18dc)); // !!!!
4104 write_mchbar32(0x18dc, 0x3);
4105 gav(read_mchbar32(0x18dc)); // !!!!
4106
4107 if (x2ca8 == 0) {
4108 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) | 1); // guess
4109 }
4110
4111 write_mchbar32(0x188c, 0x20bc09);
4112 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xd0, 0x40b0c09);
4113 write_mchbar32(0x1a10, 0x4200010e);
4114 write_mchbar32(0x18b8, read_mchbar32(0x18b8) | 0x200);
4115 gav(read_mchbar32(0x1918)); // !!!!
4116 write_mchbar32(0x1918, 0x332);
4117
4118 gav(read_mchbar32(0x18b8)); // !!!!
4119 write_mchbar32(0x18b8, 0xe00);
4120 gav(read_mchbar32(0x182c)); // !!!!
4121 write_mchbar32(0x182c, 0x10202);
4122 gav(pcie_read_config32(PCI_DEV(0xff, 2, 1), 0x94)); // !!!!
4123 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0x94, 0x10202);
4124 write_mchbar32(0x1a1c, read_mchbar32(0x1a1c) & 0x8fffffff);
4125 write_mchbar32(0x1a70, read_mchbar32(0x1a70) | 0x100000);
4126
4127 write_mchbar32(0x18b4, read_mchbar32(0x18b4) & 0xffff7fff);
4128 gav(read_mchbar32(0x1a68)); // !!!!
4129 write_mchbar32(0x1a68, 0x343800);
4130 gav(read_mchbar32(0x1e68)); // !!!!
4131 gav(read_mchbar32(0x1a68)); // !!!!
4132
4133 if (x2ca8 == 0) {
4134 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) | 1); // guess
4135 }
4136
4137 pcie_read_config32(PCI_DEV(0xff, 2, 0), 0x048); // !!!!
4138 pcie_write_config32(PCI_DEV(0xff, 2, 0), 0x048, 0x140000);
4139 pcie_read_config32(PCI_DEV(0xff, 2, 0), 0x058); // !!!!
4140 pcie_write_config32(PCI_DEV(0xff, 2, 0), 0x058, 0x64555);
4141 pcie_read_config32(PCI_DEV(0xff, 2, 0), 0x058); // !!!!
4142 pcie_read_config32(PCI_DEV (0xff, 0, 0), 0xd0); // !!!!
4143 pcie_write_config32(PCI_DEV (0xff, 0, 0), 0xd0, 0x180);
4144 gav(read_mchbar32(0x1af0)); // !!!!
4145 gav(read_mchbar32(0x1af0)); // !!!!
4146 write_mchbar32(0x1af0, 0x1f020003);
4147 gav(read_mchbar32(0x1af0)); // !!!!
4148
Edward O'Callaghan42b716f2014-06-26 21:38:52 +10004149 if (x2ca8 == 0) {
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004150 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) | 1); // guess
4151 }
4152
4153 gav(read_mchbar32(0x1890)); // !!!!
4154 write_mchbar32(0x1890, 0x80102);
4155 gav(read_mchbar32(0x18b4)); // !!!!
4156 write_mchbar32(0x18b4, 0x216000);
4157 write_mchbar32(0x18a4, 0x22222222);
4158 write_mchbar32(0x18a8, 0x22222222);
4159 write_mchbar32(0x18ac, 0x22222);
4160
4161 udelay(1000);
4162
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01004163 info.cached_training = get_cached_training();
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004164
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01004165 if (x2ca8 == 0) {
4166 int j;
4167 if (s3resume && info.cached_training) {
4168 restore_274265(&info);
4169 printk(BIOS_DEBUG, "reg2ca9_bit0 = %x\n",
4170 info.cached_training->reg2ca9_bit0);
4171 for (i = 0; i < 2; i++)
4172 for (j = 0; j < 3; j++)
4173 printk(BIOS_DEBUG, "reg274265[%d][%d] = %x\n",
4174 i, j, info.cached_training->reg274265[i][j]);
4175 } else {
4176 set_274265(&info);
4177 printk(BIOS_DEBUG, "reg2ca9_bit0 = %x\n",
4178 info.training.reg2ca9_bit0);
4179 for (i = 0; i < 2; i++)
4180 for (j = 0; j < 3; j++)
4181 printk(BIOS_DEBUG, "reg274265[%d][%d] = %x\n",
4182 i, j, info.training.reg274265[i][j]);
4183 }
4184
4185 set_2dxx_series(&info, s3resume);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004186
4187 if (!(deven & 8)) {
4188 read_mchbar32(0x2cb0);
4189 write_mchbar32(0x2cb0, 0x40);
4190 }
4191
4192 udelay(1000);
4193
4194 if (deven & 8) {
4195 write_mchbar32(0xff8, 0x1800 | read_mchbar32(0xff8));
4196 read_mchbar32(0x2cb0);
4197 write_mchbar32(0x2cb0, 0x00);
4198 pcie_read_config8(PCI_DEV (0, 0x2, 0x0), 0x4c);
4199 pcie_read_config8(PCI_DEV (0, 0x2, 0x0), 0x4c);
4200 pcie_read_config8(PCI_DEV (0, 0x2, 0x0), 0x4e);
4201
4202 read_mchbar8(0x1150);
4203 read_mchbar8(0x1151);
4204 read_mchbar8(0x1022);
4205 read_mchbar8(0x16d0);
4206 write_mchbar32(0x1300, 0x60606060);
4207 write_mchbar32(0x1304, 0x60606060);
4208 write_mchbar32(0x1308, 0x78797a7b);
4209 write_mchbar32(0x130c, 0x7c7d7e7f);
4210 write_mchbar32(0x1310, 0x60606060);
4211 write_mchbar32(0x1314, 0x60606060);
4212 write_mchbar32(0x1318, 0x60606060);
4213 write_mchbar32(0x131c, 0x60606060);
4214 write_mchbar32(0x1320, 0x50515253);
4215 write_mchbar32(0x1324, 0x54555657);
4216 write_mchbar32(0x1328, 0x58595a5b);
4217 write_mchbar32(0x132c, 0x5c5d5e5f);
4218 write_mchbar32(0x1330, 0x40414243);
4219 write_mchbar32(0x1334, 0x44454647);
4220 write_mchbar32(0x1338, 0x48494a4b);
4221 write_mchbar32(0x133c, 0x4c4d4e4f);
4222 write_mchbar32(0x1340, 0x30313233);
4223 write_mchbar32(0x1344, 0x34353637);
4224 write_mchbar32(0x1348, 0x38393a3b);
4225 write_mchbar32(0x134c, 0x3c3d3e3f);
4226 write_mchbar32(0x1350, 0x20212223);
4227 write_mchbar32(0x1354, 0x24252627);
4228 write_mchbar32(0x1358, 0x28292a2b);
4229 write_mchbar32(0x135c, 0x2c2d2e2f);
4230 write_mchbar32(0x1360, 0x10111213);
4231 write_mchbar32(0x1364, 0x14151617);
4232 write_mchbar32(0x1368, 0x18191a1b);
4233 write_mchbar32(0x136c, 0x1c1d1e1f);
4234 write_mchbar32(0x1370, 0x10203);
4235 write_mchbar32(0x1374, 0x4050607);
4236 write_mchbar32(0x1378, 0x8090a0b);
4237 write_mchbar32(0x137c, 0xc0d0e0f);
4238 write_mchbar8(0x11cc, 0x4e);
4239 write_mchbar32(0x1110, 0x73970404);
4240 write_mchbar32(0x1114, 0x72960404);
4241 write_mchbar32(0x1118, 0x6f950404);
4242 write_mchbar32(0x111c, 0x6d940404);
4243 write_mchbar32(0x1120, 0x6a930404);
4244 write_mchbar32(0x1124, 0x68a41404);
4245 write_mchbar32(0x1128, 0x66a21404);
4246 write_mchbar32(0x112c, 0x63a01404);
4247 write_mchbar32(0x1130, 0x609e1404);
4248 write_mchbar32(0x1134, 0x5f9c1404);
4249 write_mchbar32(0x1138, 0x5c961404);
4250 write_mchbar32(0x113c, 0x58a02404);
4251 write_mchbar32(0x1140, 0x54942404);
4252 write_mchbar32(0x1190, 0x900080a);
4253 write_mchbar16(0x11c0, 0xc40b);
4254 write_mchbar16(0x11c2, 0x303);
4255 write_mchbar16(0x11c4, 0x301);
4256 read_mchbar32(0x1190);
4257 write_mchbar32(0x1190, 0x8900080a);
4258 write_mchbar32(0x11b8, 0x70c3000);
4259 write_mchbar8(0x11ec, 0xa);
4260 write_mchbar16(0x1100, 0x800);
4261 read_mchbar32(0x11bc);
4262 write_mchbar32(0x11bc, 0x1e84800);
4263 write_mchbar16(0x11ca, 0xfa);
4264 write_mchbar32(0x11e4, 0x4e20);
4265 write_mchbar8(0x11bc, 0xf);
4266 write_mchbar16(0x11da, 0x19);
4267 write_mchbar16(0x11ba, 0x470c);
4268 write_mchbar32(0x1680, 0xe6ffe4ff);
4269 write_mchbar32(0x1684, 0xdeffdaff);
4270 write_mchbar32(0x1688, 0xd4ffd0ff);
4271 write_mchbar32(0x168c, 0xccffc6ff);
4272 write_mchbar32(0x1690, 0xc0ffbeff);
4273 write_mchbar32(0x1694, 0xb8ffb0ff);
4274 write_mchbar32(0x1698, 0xa8ff0000);
4275 write_mchbar32(0x169c, 0xc00);
4276 write_mchbar32(0x1290, 0x5000000);
4277 }
4278
4279 write_mchbar32(0x124c, 0x15040d00);
4280 write_mchbar32(0x1250, 0x7f0000);
4281 write_mchbar32(0x1254, 0x1e220004);
4282 write_mchbar32(0x1258, 0x4000004);
4283 write_mchbar32(0x1278, 0x0);
4284 write_mchbar32(0x125c, 0x0);
4285 write_mchbar32(0x1260, 0x0);
4286 write_mchbar32(0x1264, 0x0);
4287 write_mchbar32(0x1268, 0x0);
4288 write_mchbar32(0x126c, 0x0);
4289 write_mchbar32(0x1270, 0x0);
4290 write_mchbar32(0x1274, 0x0);
4291 }
4292
4293 if ((deven & 8) && x2ca8 == 0) {
4294 write_mchbar16(0x1214, 0x320);
4295 write_mchbar32(0x1600, 0x40000000);
4296 read_mchbar32(0x11f4);
4297 write_mchbar32(0x11f4, 0x10000000);
4298 read_mchbar16(0x1230);
4299 write_mchbar16(0x1230, 0x8000);
4300 write_mchbar32(0x1400, 0x13040020);
4301 write_mchbar32(0x1404, 0xe090120);
4302 write_mchbar32(0x1408, 0x5120220);
4303 write_mchbar32(0x140c, 0x5120330);
4304 write_mchbar32(0x1410, 0xe090220);
4305 write_mchbar32(0x1414, 0x1010001);
4306 write_mchbar32(0x1418, 0x1110000);
4307 write_mchbar32(0x141c, 0x9020020);
4308 write_mchbar32(0x1420, 0xd090220);
4309 write_mchbar32(0x1424, 0x2090220);
4310 write_mchbar32(0x1428, 0x2090330);
4311 write_mchbar32(0x142c, 0xd090220);
4312 write_mchbar32(0x1430, 0x1010001);
4313 write_mchbar32(0x1434, 0x1110000);
4314 write_mchbar32(0x1438, 0x11040020);
4315 write_mchbar32(0x143c, 0x4030220);
4316 write_mchbar32(0x1440, 0x1060220);
4317 write_mchbar32(0x1444, 0x1060330);
4318 write_mchbar32(0x1448, 0x4030220);
4319 write_mchbar32(0x144c, 0x1010001);
4320 write_mchbar32(0x1450, 0x1110000);
4321 write_mchbar32(0x1454, 0x4010020);
4322 write_mchbar32(0x1458, 0xb090220);
4323 write_mchbar32(0x145c, 0x1090220);
4324 write_mchbar32(0x1460, 0x1090330);
4325 write_mchbar32(0x1464, 0xb090220);
4326 write_mchbar32(0x1468, 0x1010001);
4327 write_mchbar32(0x146c, 0x1110000);
4328 write_mchbar32(0x1470, 0xf040020);
4329 write_mchbar32(0x1474, 0xa090220);
4330 write_mchbar32(0x1478, 0x1120220);
4331 write_mchbar32(0x147c, 0x1120330);
4332 write_mchbar32(0x1480, 0xa090220);
4333 write_mchbar32(0x1484, 0x1010001);
4334 write_mchbar32(0x1488, 0x1110000);
4335 write_mchbar32(0x148c, 0x7020020);
4336 write_mchbar32(0x1490, 0x1010220);
4337 write_mchbar32(0x1494, 0x10210);
4338 write_mchbar32(0x1498, 0x10320);
4339 write_mchbar32(0x149c, 0x1010220);
4340 write_mchbar32(0x14a0, 0x1010001);
4341 write_mchbar32(0x14a4, 0x1110000);
4342 write_mchbar32(0x14a8, 0xd040020);
4343 write_mchbar32(0x14ac, 0x8090220);
4344 write_mchbar32(0x14b0, 0x1111310);
4345 write_mchbar32(0x14b4, 0x1111420);
4346 write_mchbar32(0x14b8, 0x8090220);
4347 write_mchbar32(0x14bc, 0x1010001);
4348 write_mchbar32(0x14c0, 0x1110000);
4349 write_mchbar32(0x14c4, 0x3010020);
4350 write_mchbar32(0x14c8, 0x7090220);
4351 write_mchbar32(0x14cc, 0x1081310);
4352 write_mchbar32(0x14d0, 0x1081420);
4353 write_mchbar32(0x14d4, 0x7090220);
4354 write_mchbar32(0x14d8, 0x1010001);
4355 write_mchbar32(0x14dc, 0x1110000);
4356 write_mchbar32(0x14e0, 0xb040020);
4357 write_mchbar32(0x14e4, 0x2030220);
4358 write_mchbar32(0x14e8, 0x1051310);
4359 write_mchbar32(0x14ec, 0x1051420);
4360 write_mchbar32(0x14f0, 0x2030220);
4361 write_mchbar32(0x14f4, 0x1010001);
4362 write_mchbar32(0x14f8, 0x1110000);
4363 write_mchbar32(0x14fc, 0x5020020);
4364 write_mchbar32(0x1500, 0x5090220);
4365 write_mchbar32(0x1504, 0x2071310);
4366 write_mchbar32(0x1508, 0x2071420);
4367 write_mchbar32(0x150c, 0x5090220);
4368 write_mchbar32(0x1510, 0x1010001);
4369 write_mchbar32(0x1514, 0x1110000);
4370 write_mchbar32(0x1518, 0x7040120);
4371 write_mchbar32(0x151c, 0x2090220);
4372 write_mchbar32(0x1520, 0x70b1210);
4373 write_mchbar32(0x1524, 0x70b1310);
4374 write_mchbar32(0x1528, 0x2090220);
4375 write_mchbar32(0x152c, 0x1010001);
4376 write_mchbar32(0x1530, 0x1110000);
4377 write_mchbar32(0x1534, 0x1010110);
4378 write_mchbar32(0x1538, 0x1081310);
4379 write_mchbar32(0x153c, 0x5041200);
4380 write_mchbar32(0x1540, 0x5041310);
4381 write_mchbar32(0x1544, 0x1081310);
4382 write_mchbar32(0x1548, 0x1010001);
4383 write_mchbar32(0x154c, 0x1110000);
4384 write_mchbar32(0x1550, 0x1040120);
4385 write_mchbar32(0x1554, 0x4051210);
4386 write_mchbar32(0x1558, 0xd051200);
4387 write_mchbar32(0x155c, 0xd051200);
4388 write_mchbar32(0x1560, 0x4051210);
4389 write_mchbar32(0x1564, 0x1010001);
4390 write_mchbar32(0x1568, 0x1110000);
4391 write_mchbar16(0x1222, 0x220a);
4392 write_mchbar16(0x123c, 0x1fc0);
4393 write_mchbar16(0x1220, 0x1388);
4394 }
4395
4396 read_mchbar32(0x2c80); // !!!!
4397 write_mchbar32(0x2c80, 0x1053688);
4398 read_mchbar32(0x1c04); // !!!!
4399 write_mchbar32(0x1804, 0x406080);
4400
4401 read_mchbar8(0x2ca8);
4402
4403 if (x2ca8 == 0) {
4404 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) & ~3);
4405 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) + 4);
4406 write_mchbar32(0x1af0, read_mchbar32(0x1af0) | 0x10);
4407#if REAL
Patrick Georgi546953c2014-11-29 10:38:17 +01004408 halt();
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004409#else
4410 printf("CP5\n");
4411 exit(0);
4412#endif
4413 }
4414
4415 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8));
4416 read_mchbar32(0x2c80); // !!!!
4417 write_mchbar32(0x2c80, 0x53688);
4418 pcie_write_config32(PCI_DEV (0xff, 0, 0), 0x60, 0x20220);
4419 read_mchbar16(0x2c20); // !!!!
4420 read_mchbar16(0x2c10); // !!!!
4421 read_mchbar16(0x2c00); // !!!!
4422 write_mchbar16(0x2c00, 0x8c0);
4423 udelay(1000);
4424 write_1d0(0, 0x33d, 0, 0);
4425 write_500(&info, 0, 0, 0xb61, 0, 0);
4426 write_500(&info, 1, 0, 0xb61, 0, 0);
4427 write_mchbar32(0x1a30, 0x0);
4428 write_mchbar32(0x1a34, 0x0);
4429 write_mchbar16(0x614,
4430 0xb5b | (info.populated_ranks[1][0][0] *
4431 0x404) | (info.populated_ranks[0][0][0] *
4432 0xa0));
4433 write_mchbar16(0x616, 0x26a);
4434 write_mchbar32(0x134, 0x856000);
4435 write_mchbar32(0x160, 0x5ffffff);
4436 read_mchbar32(0x114); // !!!!
4437 write_mchbar32(0x114, 0xc2024440);
4438 read_mchbar32(0x118); // !!!!
4439 write_mchbar32(0x118, 0x4);
4440 for (channel = 0; channel < NUM_CHANNELS; channel++)
4441 write_mchbar32(0x260 + (channel << 10),
4442 0x30809ff |
4443 ((info.
4444 populated_ranks_mask[channel] & 3) << 20));
4445 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4446 write_mchbar16(0x31c + (channel << 10), 0x101);
4447 write_mchbar16(0x360 + (channel << 10), 0x909);
4448 write_mchbar16(0x3a4 + (channel << 10), 0x101);
4449 write_mchbar16(0x3e8 + (channel << 10), 0x101);
4450 write_mchbar32(0x320 + (channel << 10), 0x29002900);
4451 write_mchbar32(0x324 + (channel << 10), 0x0);
4452 write_mchbar32(0x368 + (channel << 10), 0x32003200);
4453 write_mchbar16(0x352 + (channel << 10), 0x505);
4454 write_mchbar16(0x354 + (channel << 10), 0x3c3c);
4455 write_mchbar16(0x356 + (channel << 10), 0x1040);
4456 write_mchbar16(0x39a + (channel << 10), 0x73e4);
4457 write_mchbar16(0x3de + (channel << 10), 0x77ed);
4458 write_mchbar16(0x422 + (channel << 10), 0x1040);
4459 }
4460
4461 write_1d0(0x4, 0x151, 4, 1);
4462 write_1d0(0, 0x142, 3, 1);
4463 rdmsr(0x1ac); // !!!!
4464 write_500(&info, 1, 1, 0x6b3, 4, 1);
4465 write_500(&info, 1, 1, 0x6cf, 4, 1);
4466
4467 rmw_1d0(0x21c, 0x38, 0, 6, 1);
4468
4469 write_1d0(((!info.populated_ranks[1][0][0]) << 1) | ((!info.
4470 populated_ranks[0]
4471 [0][0]) << 0),
4472 0x1d1, 3, 1);
4473 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4474 write_mchbar16(0x38e + (channel << 10), 0x5f5f);
4475 write_mchbar16(0x3d2 + (channel << 10), 0x5f5f);
4476 }
4477
4478 set_334(0);
4479
4480 program_base_timings(&info);
4481
4482 write_mchbar8(0x5ff, read_mchbar8(0x5ff) | 0x80); /* OK */
4483
4484 write_1d0(0x2, 0x1d5, 2, 1);
4485 write_1d0(0x20, 0x166, 7, 1);
4486 write_1d0(0x0, 0xeb, 3, 1);
4487 write_1d0(0x0, 0xf3, 6, 1);
4488
4489 for (channel = 0; channel < NUM_CHANNELS; channel++)
4490 for (lane = 0; lane < 9; lane++) {
4491 u16 addr = 0x125 + get_lane_offset(0, 0, lane);
4492 u8 a;
4493 a = read_500(&info, channel, addr, 6); // = 0x20040080 //!!!!
4494 write_500(&info, channel, a, addr, 6, 1);
4495 }
4496
4497 udelay(1000);
4498
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004499 if (s3resume) {
4500 if (info.cached_training == NULL) {
4501 u32 reg32;
4502 printk(BIOS_ERR,
4503 "Couldn't find training data. Rebooting\n");
4504 reg32 = inl(DEFAULT_PMBASE + 0x04);
4505 outl(reg32 & ~(7 << 10), DEFAULT_PMBASE + 0x04);
4506 outb(0xe, 0xcf9);
4507
4508#if REAL
Patrick Georgi546953c2014-11-29 10:38:17 +01004509 halt();
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004510#else
4511 printf("CP5\n");
4512 exit(0);
4513#endif
4514 }
4515 int tm;
4516 info.training = *info.cached_training;
4517 for (tm = 0; tm < 4; tm++)
4518 for (channel = 0; channel < NUM_CHANNELS; channel++)
4519 for (slot = 0; slot < NUM_SLOTS; slot++)
4520 for (rank = 0; rank < NUM_RANKS; rank++)
4521 for (lane = 0; lane < 9; lane++)
4522 write_500(&info,
4523 channel,
4524 info.training.
4525 lane_timings
4526 [tm][channel]
4527 [slot][rank]
4528 [lane],
4529 get_timing_register_addr
4530 (lane, tm,
4531 slot, rank),
4532 9, 0);
4533 write_1d0(info.cached_training->reg_178, 0x178, 7, 1);
4534 write_1d0(info.cached_training->reg_10b, 0x10b, 6, 1);
4535 }
4536
4537 read_mchbar32(0x1f4); // !!!!
4538 write_mchbar32(0x1f4, 0x20000);
4539 write_mchbar32(0x1f0, 0x1d000200);
4540 read_mchbar8(0x1f0); // !!!!
4541 write_mchbar8(0x1f0, 0x1);
4542 read_mchbar8(0x1f0); // !!!!
4543
4544 program_board_delay(&info);
4545
4546 write_mchbar8(0x5ff, 0x0); /* OK */
4547 write_mchbar8(0x5ff, 0x80); /* OK */
4548 write_mchbar8(0x5f4, 0x1); /* OK */
4549
4550 write_mchbar32(0x130, read_mchbar32(0x130) & 0xfffffffd); // | 2 when ?
4551 while (read_mchbar32(0x130) & 1) ;
4552 gav(read_1d0(0x14b, 7)); // = 0x81023100
4553 write_1d0(0x30, 0x14b, 7, 1);
4554 read_1d0(0xd6, 6); // = 0xfa008080 // !!!!
4555 write_1d0(7, 0xd6, 6, 1);
4556 read_1d0(0x328, 6); // = 0xfa018080 // !!!!
4557 write_1d0(7, 0x328, 6, 1);
4558
4559 for (channel = 0; channel < NUM_CHANNELS; channel++)
4560 set_4cf(&info, channel,
4561 info.populated_ranks[channel][0][0] ? 8 : 0);
4562
4563 read_1d0(0x116, 4); // = 0x4040432 // !!!!
4564 write_1d0(2, 0x116, 4, 1);
4565 read_1d0(0xae, 6); // = 0xe8088080 // !!!!
4566 write_1d0(0, 0xae, 6, 1);
4567 read_1d0(0x300, 4); // = 0x48088080 // !!!!
4568 write_1d0(0, 0x300, 6, 1);
4569 read_mchbar16(0x356); // !!!!
4570 write_mchbar16(0x356, 0x1040);
4571 read_mchbar16(0x756); // !!!!
4572 write_mchbar16(0x756, 0x1040);
4573 write_mchbar32(0x140, read_mchbar32(0x140) & ~0x07000000);
4574 write_mchbar32(0x138, read_mchbar32(0x138) & ~0x07000000);
4575 write_mchbar32(0x130, 0x31111301);
Vladimir Serbinenko25fc5322014-12-07 13:05:44 +01004576 /* Wait until REG130b0 is 1. */
4577 while (read_mchbar32(0x130) & 1)
4578 ;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004579
4580 {
4581 u32 t;
4582 u8 val_a1;
4583 val_a1 = read_1d0(0xa1, 6); // = 0x1cf4040 // !!!!
4584 t = read_1d0(0x2f3, 6); // = 0x10a4040 // !!!!
4585 rmw_1d0(0x320, 0x07,
4586 (t & 4) | ((t & 8) >> 2) | ((t & 0x10) >> 4), 6, 1);
4587 rmw_1d0(0x14b, 0x78,
4588 ((((val_a1 >> 2) & 4) | (val_a1 & 8)) >> 2) | (val_a1 &
4589 4), 7,
4590 1);
4591 rmw_1d0(0xce, 0x38,
4592 ((((val_a1 >> 2) & 4) | (val_a1 & 8)) >> 2) | (val_a1 &
4593 4), 6,
4594 1);
4595 }
4596
4597 for (channel = 0; channel < NUM_CHANNELS; channel++)
4598 set_4cf(&info, channel,
4599 info.populated_ranks[channel][0][0] ? 9 : 1);
4600
4601 rmw_1d0(0x116, 0xe, 1, 4, 1); // = 0x4040432 // !!!!
4602 read_mchbar32(0x144); // !!!!
4603 write_1d0(2, 0xae, 6, 1);
4604 write_1d0(2, 0x300, 6, 1);
4605 write_1d0(2, 0x121, 3, 1);
4606 read_1d0(0xd6, 6); // = 0xfa00c0c7 // !!!!
4607 write_1d0(4, 0xd6, 6, 1);
4608 read_1d0(0x328, 6); // = 0xfa00c0c7 // !!!!
4609 write_1d0(4, 0x328, 6, 1);
4610
4611 for (channel = 0; channel < NUM_CHANNELS; channel++)
4612 set_4cf(&info, channel,
4613 info.populated_ranks[channel][0][0] ? 9 : 0);
4614
4615 write_mchbar32(0x130,
4616 0x11111301 | (info.
4617 populated_ranks[1][0][0] << 30) | (info.
4618 populated_ranks
4619 [0][0]
4620 [0] <<
4621 29));
4622 while (read_mchbar8(0x130) & 1) ; // !!!!
4623 read_1d0(0xa1, 6); // = 0x1cf4054 // !!!!
4624 read_1d0(0x2f3, 6); // = 0x10a4054 // !!!!
4625 read_1d0(0x21c, 6); // = 0xafa00c0 // !!!!
4626 write_1d0(0, 0x21c, 6, 1);
4627 read_1d0(0x14b, 7); // = 0x810231b0 // !!!!
4628 write_1d0(0x35, 0x14b, 7, 1);
4629
4630 for (channel = 0; channel < NUM_CHANNELS; channel++)
4631 set_4cf(&info, channel,
4632 info.populated_ranks[channel][0][0] ? 0xb : 0x2);
4633
4634 set_334(1);
4635
4636 write_mchbar8(0x1e8, 0x4); /* OK */
4637
4638 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4639 write_500(&info, channel,
4640 0x3 & ~(info.populated_ranks_mask[channel]), 0x6b7, 2,
4641 1);
4642 write_500(&info, channel, 0x3, 0x69b, 2, 1);
4643 }
4644 write_mchbar32(0x2d0, (read_mchbar32(0x2d0) & 0xff2c01ff) | 0x200000); /* OK */
4645 write_mchbar16(0x6c0, 0x14a0); /* OK */
4646 write_mchbar32(0x6d0, (read_mchbar32(0x6d0) & 0xff0080ff) | 0x8000); /* OK */
4647 write_mchbar16(0x232, 0x8);
4648 write_mchbar32(0x234, (read_mchbar32(0x234) & 0xfffbfffb) | 0x40004); /* 0x40004 or 0 depending on ? */
4649 write_mchbar32(0x34, (read_mchbar32(0x34) & 0xfffffffd) | 5); /* OK */
4650 write_mchbar32(0x128, 0x2150d05);
4651 write_mchbar8(0x12c, 0x1f); /* OK */
4652 write_mchbar8(0x12d, 0x56); /* OK */
4653 write_mchbar8(0x12e, 0x31);
4654 write_mchbar8(0x12f, 0x0); /* OK */
4655 write_mchbar8(0x271, 0x2); /* OK */
4656 write_mchbar8(0x671, 0x2); /* OK */
4657 write_mchbar8(0x1e8, 0x4); /* OK */
4658 for (channel = 0; channel < NUM_CHANNELS; channel++)
4659 write_mchbar32(0x294 + (channel << 10),
4660 (info.populated_ranks_mask[channel] & 3) << 16);
4661 write_mchbar32(0x134, (read_mchbar32(0x134) & 0xfc01ffff) | 0x10000); /* OK */
4662 write_mchbar32(0x134, (read_mchbar32(0x134) & 0xfc85ffff) | 0x850000); /* OK */
4663 for (channel = 0; channel < NUM_CHANNELS; channel++)
4664 write_mchbar32(0x260 + (channel << 10),
4665 (read_mchbar32(0x260 + (channel << 10)) &
4666 ~0xf00000) | 0x8000000 | ((info.
4667 populated_ranks_mask
4668 [channel] & 3) <<
4669 20));
4670
4671 if (!s3resume)
4672 jedec_init(&info);
4673
4674 int totalrank = 0;
4675 for (channel = 0; channel < NUM_CHANNELS; channel++)
4676 for (slot = 0; slot < NUM_SLOTS; slot++)
4677 for (rank = 0; rank < NUM_RANKS; rank++)
4678 if (info.populated_ranks[channel][slot][rank]) {
4679 jedec_read(&info, channel, slot, rank,
4680 totalrank, 0xa, 0x400);
4681 totalrank++;
4682 }
4683
4684 write_mchbar8(0x12c, 0x9f);
4685
4686 read_mchbar8(0x271); // 2 // !!!!
4687 write_mchbar8(0x271, 0xe);
4688 read_mchbar8(0x671); // !!!!
4689 write_mchbar8(0x671, 0xe);
4690
4691 if (!s3resume) {
4692 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4693 write_mchbar32(0x294 + (channel << 10),
4694 (info.
4695 populated_ranks_mask[channel] & 3) <<
4696 16);
4697 write_mchbar16(0x298 + (channel << 10),
4698 (info.
4699 populated_ranks[channel][0][0]) | (info.
4700 populated_ranks
4701 [channel]
4702 [0]
4703 [1]
4704 <<
4705 5));
4706 write_mchbar32(0x29c + (channel << 10), 0x77a);
4707 }
4708 read_mchbar32(0x2c0); /// !!!
4709 write_mchbar32(0x2c0, 0x6009cc00);
4710
4711 {
4712 u8 a, b;
4713 a = read_mchbar8(0x243); // !!!!
4714 b = read_mchbar8(0x643); // !!!!
4715 write_mchbar8(0x243, a | 2);
4716 write_mchbar8(0x643, b | 2);
4717 }
4718
4719 write_1d0(7, 0x19b, 3, 1);
4720 write_1d0(7, 0x1c0, 3, 1);
4721 write_1d0(4, 0x1c6, 4, 1);
4722 write_1d0(4, 0x1cc, 4, 1);
4723 read_1d0(0x151, 4); // = 0x408c6d74 // !!!!
4724 write_1d0(4, 0x151, 4, 1);
4725 write_mchbar32(0x584, 0xfffff);
4726 write_mchbar32(0x984, 0xfffff);
4727
4728 for (channel = 0; channel < NUM_CHANNELS; channel++)
4729 for (slot = 0; slot < NUM_SLOTS; slot++)
4730 for (rank = 0; rank < NUM_RANKS; rank++)
4731 if (info.
4732 populated_ranks[channel][slot]
4733 [rank])
4734 config_rank(&info, s3resume,
4735 channel, slot,
4736 rank);
4737
4738 write_mchbar8(0x243, 0x1);
4739 write_mchbar8(0x643, 0x1);
4740 }
4741
4742 /* was == 1 but is common */
4743 pcie_write_config16(NORTHBRIDGE, 0xc8, 3);
4744 write_26c(0, 0x820);
4745 write_26c(1, 0x820);
4746 write_mchbar32(0x130, read_mchbar32(0x130) | 2);
4747 /* end */
4748
4749 if (s3resume) {
4750 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4751 write_mchbar32(0x294 + (channel << 10),
4752 (info.
4753 populated_ranks_mask[channel] & 3) <<
4754 16);
4755 write_mchbar16(0x298 + (channel << 10),
4756 (info.
4757 populated_ranks[channel][0][0]) | (info.
4758 populated_ranks
4759 [channel]
4760 [0]
4761 [1]
4762 <<
4763 5));
4764 write_mchbar32(0x29c + (channel << 10), 0x77a);
4765 }
4766 read_mchbar32(0x2c0); /// !!!
4767 write_mchbar32(0x2c0, 0x6009cc00);
4768 }
4769
4770 write_mchbar32(0xfa4, read_mchbar32(0xfa4) & ~0x01000002);
4771 write_mchbar32(0xfb0, 0x2000e019);
4772
4773#if !REAL
4774 printf("CP16\n");
4775#endif
4776
4777 /* Before training. */
4778 timestamp_add_now(103);
4779
4780 if (!s3resume)
4781 ram_training(&info);
4782
4783 /* After training. */
Paul Menzel9e817bf2015-05-28 07:32:48 +02004784 timestamp_add_now(104);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004785
4786 dump_timings(&info);
4787
4788#if 0
4789 ram_check(0x100000, 0x200000);
4790#endif
4791 program_modules_memory_map(&info, 0);
4792 program_total_memory_map(&info);
4793
4794 if (info.non_interleaved_part_mb != 0 && info.interleaved_part_mb != 0)
4795 write_mchbar8(0x111, 0x20 | (0 << 2) | (1 << 6) | (0 << 7));
4796 else if (have_match_ranks(&info, 0, 4) && have_match_ranks(&info, 1, 4))
4797 write_mchbar8(0x111, 0x20 | (3 << 2) | (0 << 6) | (1 << 7));
4798 else if (have_match_ranks(&info, 0, 2) && have_match_ranks(&info, 1, 2))
4799 write_mchbar8(0x111, 0x20 | (3 << 2) | (0 << 6) | (0 << 7));
4800 else
4801 write_mchbar8(0x111, 0x20 | (3 << 2) | (1 << 6) | (0 << 7));
4802
4803 write_mchbar32(0xfac, read_mchbar32(0xfac) & ~0x80000000); // OK
4804 write_mchbar32(0xfb4, 0x4800); // OK
4805 write_mchbar32(0xfb8, (info.revision < 8) ? 0x20 : 0x0); // OK
4806 write_mchbar32(0xe94, 0x7ffff); // OK
4807 write_mchbar32(0xfc0, 0x80002040); // OK
4808 write_mchbar32(0xfc4, 0x701246); // OK
4809 write_mchbar8(0xfc8, read_mchbar8(0xfc8) & ~0x70); // OK
4810 write_mchbar32(0xe5c, 0x1000000 | read_mchbar32(0xe5c)); // OK
4811 write_mchbar32(0x1a70, (read_mchbar32(0x1a70) | 0x00200000) & ~0x00100000); // OK
4812 write_mchbar32(0x50, 0x700b0); // OK
4813 write_mchbar32(0x3c, 0x10); // OK
4814 write_mchbar8(0x1aa8, (read_mchbar8(0x1aa8) & ~0x35) | 0xa); // OK
4815 write_mchbar8(0xff4, read_mchbar8(0xff4) | 0x2); // OK
4816 write_mchbar32(0xff8, (read_mchbar32(0xff8) & ~0xe008) | 0x1020); // OK
4817
4818#if REAL
4819 write_mchbar32(0xd00, IOMMU_BASE2 | 1);
4820 write_mchbar32(0xd40, IOMMU_BASE1 | 1);
4821 write_mchbar32(0xdc0, IOMMU_BASE4 | 1);
4822
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08004823 write32p(IOMMU_BASE1 | 0xffc, 0x80000000);
4824 write32p(IOMMU_BASE2 | 0xffc, 0xc0000000);
4825 write32p(IOMMU_BASE4 | 0xffc, 0x80000000);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004826
4827#else
4828 {
4829 u32 eax;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08004830 eax = read32p(0xffc + (read_mchbar32(0xd00) & ~1)) | 0x08000000; // = 0xe911714b// OK
4831 write32p(0xffc + (read_mchbar32(0xd00) & ~1), eax); // OK
4832 eax = read32p(0xffc + (read_mchbar32(0xdc0) & ~1)) | 0x40000000; // = 0xe911714b// OK
4833 write32p(0xffc + (read_mchbar32(0xdc0) & ~1), eax); // OK
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004834 }
4835#endif
4836
4837 {
4838 u32 eax;
4839
4840 eax = info.fsb_frequency / 9;
4841 write_mchbar32(0xfcc, (read_mchbar32(0xfcc) & 0xfffc0000) | (eax * 0x280) | (eax * 0x5000) | eax | 0x40000); // OK
4842 write_mchbar32(0x20, 0x33001); //OK
4843 }
4844
4845 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4846 write_mchbar32(0x220 + (channel << 10), read_mchbar32(0x220 + (channel << 10)) & ~0x7770); //OK
4847 if (info.max_slots_used_in_channel == 1)
4848 write_mchbar16(0x237 + (channel << 10), (read_mchbar16(0x237 + (channel << 10)) | 0x0201)); //OK
4849 else
4850 write_mchbar16(0x237 + (channel << 10), (read_mchbar16(0x237 + (channel << 10)) & ~0x0201)); //OK
4851
4852 write_mchbar8(0x241 + (channel << 10), read_mchbar8(0x241 + (channel << 10)) | 1); // OK
4853
4854 if (info.clock_speed_index <= 1
4855 && (info.silicon_revision == 2
4856 || info.silicon_revision == 3))
4857 write_mchbar32(0x248 + (channel << 10), (read_mchbar32(0x248 + (channel << 10)) | 0x00102000)); // OK
4858 else
4859 write_mchbar32(0x248 + (channel << 10), (read_mchbar32(0x248 + (channel << 10)) & ~0x00102000)); // OK
4860 }
4861
4862 write_mchbar32(0x115, read_mchbar32(0x115) | 0x1000000); // OK
4863
4864 {
4865 u8 al;
4866 al = 0xd;
4867 if (!(info.silicon_revision == 0 || info.silicon_revision == 1))
4868 al += 2;
4869 al |= ((1 << (info.max_slots_used_in_channel - 1)) - 1) << 4;
4870 write_mchbar32(0x210, (al << 16) | 0x20); // OK
4871 }
4872
4873 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4874 write_mchbar32(0x288 + (channel << 10), 0x70605040); // OK
4875 write_mchbar32(0x28c + (channel << 10), 0xfffec080); // OK
4876 write_mchbar32(0x290 + (channel << 10), 0x282091c | ((info.max_slots_used_in_channel - 1) << 0x16)); // OK
4877 }
4878 u32 reg1c;
4879 pcie_read_config32(NORTHBRIDGE, 0x40); // = DEFAULT_EPBAR | 0x001 // OK
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08004880 reg1c = read32p(DEFAULT_EPBAR | 0x01c); // = 0x8001 // OK
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004881 pcie_read_config32(NORTHBRIDGE, 0x40); // = DEFAULT_EPBAR | 0x001 // OK
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08004882 write32p(DEFAULT_EPBAR | 0x01c, reg1c); // OK
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004883 read_mchbar8(0xe08); // = 0x0
4884 pcie_read_config32(NORTHBRIDGE, 0xe4); // = 0x316126
4885 write_mchbar8(0x1210, read_mchbar8(0x1210) | 2); // OK
4886 write_mchbar32(0x1200, 0x8800440); // OK
4887 write_mchbar32(0x1204, 0x53ff0453); // OK
4888 write_mchbar32(0x1208, 0x19002043); // OK
4889 write_mchbar16(0x1214, 0x320); // OK
4890
4891 if (info.revision == 0x10 || info.revision == 0x11) {
4892 write_mchbar16(0x1214, 0x220); // OK
4893 write_mchbar8(0x1210, read_mchbar8(0x1210) | 0x40); // OK
4894 }
4895
4896 write_mchbar8(0x1214, read_mchbar8(0x1214) | 0x4); // OK
4897 write_mchbar8(0x120c, 0x1); // OK
4898 write_mchbar8(0x1218, 0x3); // OK
4899 write_mchbar8(0x121a, 0x3); // OK
4900 write_mchbar8(0x121c, 0x3); // OK
4901 write_mchbar16(0xc14, 0x0); // OK
4902 write_mchbar16(0xc20, 0x0); // OK
4903 write_mchbar32(0x1c, 0x0); // OK
4904
4905 /* revision dependent here. */
4906
4907 write_mchbar16(0x1230, read_mchbar16(0x1230) | 0x1f07); // OK
4908
4909 if (info.uma_enabled)
4910 write_mchbar32(0x11f4, read_mchbar32(0x11f4) | 0x10000000); // OK
4911
4912 write_mchbar16(0x1230, read_mchbar16(0x1230) | 0x8000); // OK
4913 write_mchbar8(0x1214, read_mchbar8(0x1214) | 1); // OK
4914
4915 u8 bl, ebpb;
4916 u16 reg_1020;
4917
4918 reg_1020 = read_mchbar32(0x1020); // = 0x6c733c // OK
4919 write_mchbar8(0x1070, 0x1); // OK
4920
4921 write_mchbar32(0x1000, 0x100); // OK
4922 write_mchbar8(0x1007, 0x0); // OK
4923
4924 if (reg_1020 != 0) {
4925 write_mchbar16(0x1018, 0x0); // OK
4926 bl = reg_1020 >> 8;
4927 ebpb = reg_1020 & 0xff;
4928 } else {
4929 ebpb = 0;
4930 bl = 8;
4931 }
4932
4933 rdmsr(0x1a2);
4934
4935 write_mchbar32(0x1014, 0xffffffff); // OK
4936
4937 write_mchbar32(0x1010, ((((ebpb + 0x7d) << 7) / bl) & 0xff) * (! !reg_1020)); // OK
4938
4939 write_mchbar8(0x101c, 0xb8); // OK
4940
4941 write_mchbar8(0x123e, (read_mchbar8(0x123e) & 0xf) | 0x60); // OK
4942 if (reg_1020 != 0) {
4943 write_mchbar32(0x123c, (read_mchbar32(0x123c) & ~0x00900000) | 0x600000); // OK
4944 write_mchbar8(0x101c, 0xb8); // OK
4945 }
4946
4947 setup_heci_uma(&info);
4948
4949 if (info.uma_enabled) {
4950 u16 ax;
4951 write_mchbar32(0x11b0, read_mchbar32(0x11b0) | 0x4000); // OK
4952 write_mchbar32(0x11b4, read_mchbar32(0x11b4) | 0x4000); // OK
4953 write_mchbar16(0x1190, read_mchbar16(0x1190) | 0x4000); // OK
4954
4955 ax = read_mchbar16(0x1190) & 0xf00; // = 0x480a // OK
4956 write_mchbar16(0x1170, ax | (read_mchbar16(0x1170) & 0x107f) | 0x4080); // OK
4957 write_mchbar16(0x1170, read_mchbar16(0x1170) | 0x1000); // OK
4958#if REAL
4959 udelay(1000);
4960#endif
4961 u16 ecx;
4962 for (ecx = 0xffff; ecx && (read_mchbar16(0x1170) & 0x1000); ecx--) ; // OK
4963 write_mchbar16(0x1190, read_mchbar16(0x1190) & ~0x4000); // OK
4964 }
4965
4966 pcie_write_config8(SOUTHBRIDGE, GEN_PMCON_2,
4967 pcie_read_config8(SOUTHBRIDGE, GEN_PMCON_2) & ~0x80);
4968 udelay(10000);
Vladimir Serbinenkoc7db28c2014-02-19 22:09:33 +01004969 write_mchbar16(0x2ca8, 0x8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004970
4971#if REAL
4972 udelay(1000);
4973 dump_timings(&info);
Vladimir Serbinenkob16f0922014-06-07 16:27:27 +02004974 cbmem_wasnot_inited = cbmem_recovery(s3resume);
4975
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004976 if (!s3resume)
4977 save_timings(&info);
Vladimir Serbinenkob16f0922014-06-07 16:27:27 +02004978 if (s3resume && cbmem_wasnot_inited) {
4979 u32 reg32;
4980 printk(BIOS_ERR, "Failed S3 resume.\n");
4981 ram_check(0x100000, 0x200000);
4982
4983 /* Clear SLP_TYPE. */
4984 reg32 = inl(DEFAULT_PMBASE + 0x04);
4985 outl(reg32 & ~(7 << 10), DEFAULT_PMBASE + 0x04);
4986
4987 /* Failed S3 resume, reset to come up cleanly */
4988 outb(0xe, 0xcf9);
Patrick Georgi546953c2014-11-29 10:38:17 +01004989 halt();
Vladimir Serbinenkob16f0922014-06-07 16:27:27 +02004990 }
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004991#endif
4992}