blob: 0549de766abae75a0ff97f769123056c35cb4495 [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;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001691 int channel, slot, rank, lane, i;
1692
1693 train = info->training;
1694 FOR_POPULATED_RANKS for (lane = 0; lane < 9; lane++)
1695 for (i = 0; i < 4; i++)
1696 train.lane_timings[i][channel][slot][rank][lane] =
1697 read_500(info, channel,
1698 get_timing_register_addr(lane, i, slot,
1699 rank), 9);
1700 train.reg_178 = read_1d0(0x178, 7);
1701 train.reg_10b = read_1d0(0x10b, 6);
1702
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01001703 for (channel = 0; channel < NUM_CHANNELS; channel++) {
1704 u32 reg32;
1705 reg32 = read_mchbar32 ((channel << 10) + 0x274);
1706 train.reg274265[channel][0] = reg32 >> 16;
1707 train.reg274265[channel][1] = reg32 & 0xffff;
1708 train.reg274265[channel][2] = read_mchbar16 ((channel << 10) + 0x265) >> 8;
1709 }
1710 train.reg2ca9_bit0 = read_mchbar8(0x2ca9) & 1;
1711 train.reg_6dc = read_mchbar32 (0x6dc);
1712 train.reg_6e8 = read_mchbar32 (0x6e8);
1713
1714 printk (BIOS_SPEW, "[6dc] = %x\n", train.reg_6dc);
1715 printk (BIOS_SPEW, "[6e8] = %x\n", train.reg_6e8);
1716
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001717 /* Save the MRC S3 restore data to cbmem */
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02001718 store_current_mrc_cache(&train, sizeof(train));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001719}
1720
1721#if REAL
1722static const struct ram_training *get_cached_training(void)
1723{
1724 struct mrc_data_container *cont;
1725 cont = find_current_mrc_cache();
1726 if (!cont)
1727 return 0;
1728 return (void *)cont->mrc_data;
1729}
1730#endif
1731
1732/* FIXME: add timeout. */
1733static void wait_heci_ready(void)
1734{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001735 while (!(read32(DEFAULT_HECIBAR + 0xc) & 8)) ; // = 0x8000000c
1736 write32((DEFAULT_HECIBAR + 0x4),
1737 (read32(DEFAULT_HECIBAR + 0x4) & ~0x10) | 0xc);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001738}
1739
1740/* FIXME: add timeout. */
1741static void wait_heci_cb_avail(int len)
1742{
1743 union {
1744 struct mei_csr csr;
1745 u32 raw;
1746 } csr;
1747
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001748 while (!(read32(DEFAULT_HECIBAR + 0xc) & 8)) ;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001749
1750 do
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001751 csr.raw = read32(DEFAULT_HECIBAR + 0x4);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001752 while (len >
1753 csr.csr.buffer_depth - (csr.csr.buffer_write_ptr -
1754 csr.csr.buffer_read_ptr));
1755}
1756
1757static void send_heci_packet(struct mei_header *head, u32 * payload)
1758{
1759 int len = (head->length + 3) / 4;
1760 int i;
1761
1762 wait_heci_cb_avail(len + 1);
1763
1764 /* FIXME: handle leftovers correctly. */
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001765 write32(DEFAULT_HECIBAR + 0, *(u32 *) head);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001766 for (i = 0; i < len - 1; i++)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001767 write32(DEFAULT_HECIBAR + 0, payload[i]);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001768
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001769 write32(DEFAULT_HECIBAR + 0, payload[i] & ((1 << (8 * len)) - 1));
1770 write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 0x4);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001771}
1772
1773static void
1774send_heci_message(u8 * msg, int len, u8 hostaddress, u8 clientaddress)
1775{
1776 struct mei_header head;
1777 int maxlen;
1778
1779 wait_heci_ready();
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001780 maxlen = (read32(DEFAULT_HECIBAR + 0x4) >> 24) * 4 - 4;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001781
1782 while (len) {
1783 int cur = len;
1784 if (cur > maxlen) {
1785 cur = maxlen;
1786 head.is_complete = 0;
1787 } else
1788 head.is_complete = 1;
1789 head.length = cur;
1790 head.reserved = 0;
1791 head.client_address = clientaddress;
1792 head.host_address = hostaddress;
1793 send_heci_packet(&head, (u32 *) msg);
1794 len -= cur;
1795 msg += cur;
1796 }
1797}
1798
1799/* FIXME: Add timeout. */
1800static int
1801recv_heci_packet(struct raminfo *info, struct mei_header *head, u32 * packet,
1802 u32 * packet_size)
1803{
1804 union {
1805 struct mei_csr csr;
1806 u32 raw;
1807 } csr;
1808 int i = 0;
1809
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001810 write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 2);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001811 do {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001812 csr.raw = read32(DEFAULT_HECIBAR + 0xc);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001813#if !REAL
1814 if (i++ > 346)
1815 return -1;
1816#endif
1817 }
1818 while (csr.csr.buffer_write_ptr == csr.csr.buffer_read_ptr);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001819 *(u32 *) head = read32(DEFAULT_HECIBAR + 0x8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001820 if (!head->length) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001821 write32(DEFAULT_HECIBAR + 0x4,
1822 read32(DEFAULT_HECIBAR + 0x4) | 2);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001823 *packet_size = 0;
1824 return 0;
1825 }
1826 if (head->length + 4 > 4 * csr.csr.buffer_depth
1827 || head->length > *packet_size) {
1828 *packet_size = 0;
1829 return -1;
1830 }
1831
1832 do
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001833 csr.raw = read32(DEFAULT_HECIBAR + 0xc);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001834 while ((head->length + 3) >> 2 >
1835 csr.csr.buffer_write_ptr - csr.csr.buffer_read_ptr);
1836
1837 for (i = 0; i < (head->length + 3) >> 2; i++)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001838 packet[i++] = read32(DEFAULT_HECIBAR + 0x8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001839 *packet_size = head->length;
1840 if (!csr.csr.ready)
1841 *packet_size = 0;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001842 write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 4);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001843 return 0;
1844}
1845
1846/* FIXME: Add timeout. */
1847static int
1848recv_heci_message(struct raminfo *info, u32 * message, u32 * message_size)
1849{
1850 struct mei_header head;
1851 int current_position;
1852
1853 current_position = 0;
1854 while (1) {
1855 u32 current_size;
1856 current_size = *message_size - current_position;
1857 if (recv_heci_packet
1858 (info, &head, message + (current_position >> 2),
1859 &current_size) == -1)
1860 break;
1861 if (!current_size)
1862 break;
1863 current_position += current_size;
1864 if (head.is_complete) {
1865 *message_size = current_position;
1866 return 0;
1867 }
1868
1869 if (current_position >= *message_size)
1870 break;
1871 }
1872 *message_size = 0;
1873 return -1;
1874}
1875
1876static void send_heci_uma_message(struct raminfo *info)
1877{
1878 struct uma_reply {
1879 u8 group_id;
1880 u8 command;
1881 u8 reserved;
1882 u8 result;
1883 u8 field2;
1884 u8 unk3[0x48 - 4 - 1];
1885 } __attribute__ ((packed)) reply;
1886 struct uma_message {
1887 u8 group_id;
1888 u8 cmd;
1889 u8 reserved;
1890 u8 result;
1891 u32 c2;
1892 u64 heci_uma_addr;
1893 u32 memory_reserved_for_heci_mb;
1894 u16 c3;
1895 } __attribute__ ((packed)) msg = {
1896 0, MKHI_SET_UMA, 0, 0,
1897 0x82,
1898 info->heci_uma_addr, info->memory_reserved_for_heci_mb, 0};
1899 u32 reply_size;
1900
1901 send_heci_message((u8 *) & msg, sizeof(msg), 0, 7);
1902
1903 reply_size = sizeof(reply);
1904 if (recv_heci_message(info, (u32 *) & reply, &reply_size) == -1)
1905 return;
1906
1907 if (reply.command != (MKHI_SET_UMA | (1 << 7)))
1908 die("HECI init failed\n");
1909}
1910
1911static void setup_heci_uma(struct raminfo *info)
1912{
1913 u32 reg44;
1914
1915 reg44 = pcie_read_config32(HECIDEV, 0x44); // = 0x80010020
1916 info->memory_reserved_for_heci_mb = 0;
1917 info->heci_uma_addr = 0;
1918 if (!((reg44 & 0x10000) && !(pcie_read_config32(HECIDEV, 0x40) & 0x20)))
1919 return;
1920
1921 info->heci_bar = pcie_read_config32(HECIDEV, 0x10) & 0xFFFFFFF0;
1922 info->memory_reserved_for_heci_mb = reg44 & 0x3f;
1923 info->heci_uma_addr =
1924 ((u64)
1925 ((((u64) pcie_read_config16(NORTHBRIDGE, D0F0_TOM)) << 6) -
1926 info->memory_reserved_for_heci_mb)) << 20;
1927
1928 pcie_read_config32(NORTHBRIDGE, DMIBAR);
1929 if (info->memory_reserved_for_heci_mb) {
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001930 write32(DEFAULT_DMIBAR + 0x14,
1931 read32(DEFAULT_DMIBAR + 0x14) & ~0x80);
1932 write32(DEFAULT_RCBA + 0x14,
1933 read32(DEFAULT_RCBA + 0x14) & ~0x80);
1934 write32(DEFAULT_DMIBAR + 0x20,
1935 read32(DEFAULT_DMIBAR + 0x20) & ~0x80);
1936 write32(DEFAULT_RCBA + 0x20,
1937 read32(DEFAULT_RCBA + 0x20) & ~0x80);
1938 write32(DEFAULT_DMIBAR + 0x2c,
1939 read32(DEFAULT_DMIBAR + 0x2c) & ~0x80);
1940 write32(DEFAULT_RCBA + 0x30,
1941 read32(DEFAULT_RCBA + 0x30) & ~0x80);
1942 write32(DEFAULT_DMIBAR + 0x38,
1943 read32(DEFAULT_DMIBAR + 0x38) & ~0x80);
1944 write32(DEFAULT_RCBA + 0x40,
1945 read32(DEFAULT_RCBA + 0x40) & ~0x80);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001946
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08001947 write32(DEFAULT_RCBA + 0x40, 0x87000080); // OK
1948 write32(DEFAULT_DMIBAR + 0x38, 0x87000080); // OK
1949 while (read16(DEFAULT_RCBA + 0x46) & 2
1950 && read16(DEFAULT_DMIBAR + 0x3e) & 2) ;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001951 }
1952
1953 write_mchbar32(0x24, 0x10000 + info->memory_reserved_for_heci_mb);
1954
1955 send_heci_uma_message(info);
1956
1957 pcie_write_config32(HECIDEV, 0x10, 0x0);
1958 pcie_write_config8(HECIDEV, 0x4, 0x0);
1959
1960}
1961
1962static int have_match_ranks(struct raminfo *info, int channel, int ranks)
1963{
1964 int ranks_in_channel;
1965 ranks_in_channel = info->populated_ranks[channel][0][0]
1966 + info->populated_ranks[channel][0][1]
1967 + info->populated_ranks[channel][1][0]
1968 + info->populated_ranks[channel][1][1];
1969
1970 /* empty channel */
1971 if (ranks_in_channel == 0)
1972 return 1;
1973
1974 if (ranks_in_channel != ranks)
1975 return 0;
1976 /* single slot */
1977 if (info->populated_ranks[channel][0][0] !=
1978 info->populated_ranks[channel][1][0])
1979 return 1;
1980 if (info->populated_ranks[channel][0][1] !=
1981 info->populated_ranks[channel][1][1])
1982 return 1;
1983 if (info->is_x16_module[channel][0] != info->is_x16_module[channel][1])
1984 return 0;
1985 if (info->density[channel][0] != info->density[channel][1])
1986 return 0;
1987 return 1;
1988}
1989
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01001990static void read_4090(struct raminfo *info)
1991{
1992 int i, channel, slot, rank, lane;
1993 for (i = 0; i < 2; i++)
1994 for (slot = 0; slot < NUM_SLOTS; slot++)
1995 for (rank = 0; rank < NUM_RANKS; rank++)
1996 for (lane = 0; lane < 9; lane++)
1997 info->training.
1998 lane_timings[0][i][slot][rank][lane]
1999 = 32;
2000
2001 for (i = 1; i < 4; i++)
2002 for (channel = 0; channel < NUM_CHANNELS; channel++)
2003 for (slot = 0; slot < NUM_SLOTS; slot++)
2004 for (rank = 0; rank < NUM_RANKS; rank++)
2005 for (lane = 0; lane < 9; lane++) {
2006 info->training.
2007 lane_timings[i][channel]
2008 [slot][rank][lane] =
2009 read_500(info, channel,
2010 get_timing_register_addr
2011 (lane, i, slot,
2012 rank), 9)
2013 + (i == 1) * 11; // !!!!
2014 }
2015
2016}
2017
2018static u32 get_etalon2(int flip, u32 addr)
2019{
2020 const u16 invmask[] = {
2021 0xaaaa, 0x6db6, 0x4924, 0xeeee, 0xcccc, 0x8888, 0x7bde, 0x739c,
2022 0x6318, 0x4210, 0xefbe, 0xcf3c, 0x8e38, 0x0c30, 0x0820
2023 };
2024 u32 ret;
2025 u32 comp4 = addr / 480;
2026 addr %= 480;
2027 u32 comp1 = addr & 0xf;
2028 u32 comp2 = (addr >> 4) & 1;
2029 u32 comp3 = addr >> 5;
2030
2031 if (comp4)
2032 ret = 0x1010101 << (comp4 - 1);
2033 else
2034 ret = 0;
2035 if (flip ^ (((invmask[comp3] >> comp1) ^ comp2) & 1))
2036 ret = ~ret;
2037
2038 return ret;
2039}
2040
2041static void disable_cache(void)
2042{
2043 msr_t msr = {.lo = 0, .hi = 0 };
2044
Alexandru Gagniuc86091f92015-09-30 20:23:09 -07002045 wrmsr(MTRR_PHYS_BASE(3), msr);
2046 wrmsr(MTRR_PHYS_MASK(3), msr);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002047}
2048
2049static void enable_cache(unsigned int base, unsigned int size)
2050{
2051 msr_t msr;
2052 msr.lo = base | MTRR_TYPE_WRPROT;
2053 msr.hi = 0;
Alexandru Gagniuc86091f92015-09-30 20:23:09 -07002054 wrmsr(MTRR_PHYS_BASE(3), msr);
2055 msr.lo = ((~(ALIGN_DOWN(size + 4096, 4096) - 1) | MTRR_DEF_TYPE_EN)
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002056 & 0xffffffff);
2057 msr.hi = 0x0000000f;
Alexandru Gagniuc86091f92015-09-30 20:23:09 -07002058 wrmsr(MTRR_PHYS_MASK(3), msr);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002059}
2060
2061static void flush_cache(u32 start, u32 size)
2062{
2063 u32 end;
2064 u32 addr;
2065
2066 end = start + (ALIGN_DOWN(size + 4096, 4096));
2067 for (addr = start; addr < end; addr += 64)
2068 clflush(addr);
2069}
2070
2071static void clear_errors(void)
2072{
2073 pcie_write_config8(NORTHBRIDGE, 0xc0, 0x01);
2074}
2075
2076static void write_testing(struct raminfo *info, int totalrank, int flip)
2077{
2078 int nwrites = 0;
2079 /* in 8-byte units. */
2080 u32 offset;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08002081 u8 *base;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002082
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08002083 base = (u8 *)(totalrank << 28);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002084 for (offset = 0; offset < 9 * 480; offset += 2) {
2085 write32(base + offset * 8, get_etalon2(flip, offset));
2086 write32(base + offset * 8 + 4, get_etalon2(flip, offset));
2087 write32(base + offset * 8 + 8, get_etalon2(flip, offset + 1));
2088 write32(base + offset * 8 + 12, get_etalon2(flip, offset + 1));
2089 nwrites += 4;
2090 if (nwrites >= 320) {
2091 clear_errors();
2092 nwrites = 0;
2093 }
2094 }
2095}
2096
2097static u8 check_testing(struct raminfo *info, u8 total_rank, int flip)
2098{
2099 u8 failmask = 0;
2100 int i;
2101 int comp1, comp2, comp3;
2102 u32 failxor[2] = { 0, 0 };
2103
2104 enable_cache((total_rank << 28), 1728 * 5 * 4);
2105
2106 for (comp3 = 0; comp3 < 9 && failmask != 0xff; comp3++) {
2107 for (comp1 = 0; comp1 < 4; comp1++)
2108 for (comp2 = 0; comp2 < 60; comp2++) {
2109 u32 re[4];
2110 u32 curroffset =
2111 comp3 * 8 * 60 + 2 * comp1 + 8 * comp2;
2112 read128((total_rank << 28) | (curroffset << 3),
2113 (u64 *) re);
2114 failxor[0] |=
2115 get_etalon2(flip, curroffset) ^ re[0];
2116 failxor[1] |=
2117 get_etalon2(flip, curroffset) ^ re[1];
2118 failxor[0] |=
2119 get_etalon2(flip, curroffset | 1) ^ re[2];
2120 failxor[1] |=
2121 get_etalon2(flip, curroffset | 1) ^ re[3];
2122 }
2123 for (i = 0; i < 8; i++)
2124 if ((0xff << (8 * (i % 4))) & failxor[i / 4])
2125 failmask |= 1 << i;
2126 }
2127 disable_cache();
2128 flush_cache((total_rank << 28), 1728 * 5 * 4);
2129 return failmask;
2130}
2131
2132const u32 seed1[0x18] = {
2133 0x3a9d5ab5, 0x576cb65b, 0x555773b6, 0x2ab772ee,
2134 0x555556ee, 0x3a9d5ab5, 0x576cb65b, 0x555773b6,
2135 0x2ab772ee, 0x555556ee, 0x5155a555, 0x5155a555,
2136 0x5155a555, 0x5155a555, 0x3a9d5ab5, 0x576cb65b,
2137 0x555773b6, 0x2ab772ee, 0x555556ee, 0x55d6b4a5,
2138 0x366d6b3a, 0x2ae5ddbb, 0x3b9ddbb7, 0x55d6b4a5,
2139};
2140
2141static u32 get_seed2(int a, int b)
2142{
2143 const u32 seed2[5] = {
2144 0x55555555, 0x33333333, 0x2e555a55, 0x55555555,
2145 0x5b6db6db,
2146 };
2147 u32 r;
2148 r = seed2[(a + (a >= 10)) / 5];
2149 return b ? ~r : r;
2150}
2151
2152static int make_shift(int comp2, int comp5, int x)
2153{
2154 const u8 seed3[32] = {
2155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2156 0x00, 0x00, 0x38, 0x1c, 0x3c, 0x18, 0x38, 0x38,
2157 0x38, 0x38, 0x38, 0x38, 0x0f, 0x0f, 0x0f, 0x0f,
2158 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
2159 };
2160
2161 return (comp2 - ((seed3[comp5] >> (x & 7)) & 1)) & 0x1f;
2162}
2163
2164static u32 get_etalon(int flip, u32 addr)
2165{
2166 u32 mask_byte = 0;
2167 int comp1 = (addr >> 1) & 1;
2168 int comp2 = (addr >> 3) & 0x1f;
2169 int comp3 = (addr >> 8) & 0xf;
2170 int comp4 = (addr >> 12) & 0xf;
2171 int comp5 = (addr >> 16) & 0x1f;
2172 u32 mask_bit = ~(0x10001 << comp3);
2173 u32 part1;
2174 u32 part2;
2175 int byte;
2176
2177 part2 =
2178 ((seed1[comp5] >>
2179 make_shift(comp2, comp5,
2180 (comp3 >> 3) | (comp1 << 2) | 2)) & 1) ^ flip;
2181 part1 =
2182 ((seed1[comp5] >>
2183 make_shift(comp2, comp5,
2184 (comp3 >> 3) | (comp1 << 2) | 0)) & 1) ^ flip;
2185
2186 for (byte = 0; byte < 4; byte++)
2187 if ((get_seed2(comp5, comp4) >>
2188 make_shift(comp2, comp5, (byte | (comp1 << 2)))) & 1)
2189 mask_byte |= 0xff << (8 * byte);
2190
2191 return (mask_bit & mask_byte) | (part1 << comp3) | (part2 <<
2192 (comp3 + 16));
2193}
2194
2195static void
2196write_testing_type2(struct raminfo *info, u8 totalrank, u8 region, u8 block,
2197 char flip)
2198{
2199 int i;
2200 for (i = 0; i < 2048; i++)
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08002201 write32p((totalrank << 28) | (region << 25) | (block << 16) |
2202 (i << 2), get_etalon(flip, (block << 16) | (i << 2)));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002203}
2204
2205static u8
2206check_testing_type2(struct raminfo *info, u8 totalrank, u8 region, u8 block,
2207 char flip)
2208{
2209 u8 failmask = 0;
2210 u32 failxor[2];
2211 int i;
2212 int comp1, comp2, comp3;
2213
2214 failxor[0] = 0;
2215 failxor[1] = 0;
2216
2217 enable_cache(totalrank << 28, 134217728);
2218 for (comp3 = 0; comp3 < 2 && failmask != 0xff; comp3++) {
2219 for (comp1 = 0; comp1 < 16; comp1++)
2220 for (comp2 = 0; comp2 < 64; comp2++) {
2221 u32 addr =
2222 (totalrank << 28) | (region << 25) | (block
2223 << 16)
2224 | (comp3 << 12) | (comp2 << 6) | (comp1 <<
2225 2);
2226 failxor[comp1 & 1] |=
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08002227 read32p(addr) ^ get_etalon(flip, addr);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01002228 }
2229 for (i = 0; i < 8; i++)
2230 if ((0xff << (8 * (i % 4))) & failxor[i / 4])
2231 failmask |= 1 << i;
2232 }
2233 disable_cache();
2234 flush_cache((totalrank << 28) | (region << 25) | (block << 16), 16384);
2235 return failmask;
2236}
2237
2238static int check_bounded(unsigned short *vals, u16 bound)
2239{
2240 int i;
2241
2242 for (i = 0; i < 8; i++)
2243 if (vals[i] < bound)
2244 return 0;
2245 return 1;
2246}
2247
2248enum state {
2249 BEFORE_USABLE = 0, AT_USABLE = 1, AT_MARGIN = 2, COMPLETE = 3
2250};
2251
2252static int validate_state(enum state *in)
2253{
2254 int i;
2255 for (i = 0; i < 8; i++)
2256 if (in[i] != COMPLETE)
2257 return 0;
2258 return 1;
2259}
2260
2261static void
2262do_fsm(enum state *state, u16 * counter,
2263 u8 fail_mask, int margin, int uplimit,
2264 u8 * res_low, u8 * res_high, u8 val)
2265{
2266 int lane;
2267
2268 for (lane = 0; lane < 8; lane++) {
2269 int is_fail = (fail_mask >> lane) & 1;
2270 switch (state[lane]) {
2271 case BEFORE_USABLE:
2272 if (!is_fail) {
2273 counter[lane] = 1;
2274 state[lane] = AT_USABLE;
2275 break;
2276 }
2277 counter[lane] = 0;
2278 state[lane] = BEFORE_USABLE;
2279 break;
2280 case AT_USABLE:
2281 if (!is_fail) {
2282 ++counter[lane];
2283 if (counter[lane] >= margin) {
2284 state[lane] = AT_MARGIN;
2285 res_low[lane] = val - margin + 1;
2286 break;
2287 }
2288 state[lane] = 1;
2289 break;
2290 }
2291 counter[lane] = 0;
2292 state[lane] = BEFORE_USABLE;
2293 break;
2294 case AT_MARGIN:
2295 if (is_fail) {
2296 state[lane] = COMPLETE;
2297 res_high[lane] = val - 1;
2298 } else {
2299 counter[lane]++;
2300 state[lane] = AT_MARGIN;
2301 if (val == uplimit) {
2302 state[lane] = COMPLETE;
2303 res_high[lane] = uplimit;
2304 }
2305 }
2306 break;
2307 case COMPLETE:
2308 break;
2309 }
2310 }
2311}
2312
2313static void
2314train_ram_at_178(struct raminfo *info, u8 channel, int slot, int rank,
2315 u8 total_rank, u8 reg_178, int first_run, int niter,
2316 timing_bounds_t * timings)
2317{
2318 int lane;
2319 enum state state[8];
2320 u16 count[8];
2321 u8 lower_usable[8];
2322 u8 upper_usable[8];
2323 unsigned short num_sucessfully_checked[8];
2324 u8 secondary_total_rank;
2325 u8 reg1b3;
2326
2327 if (info->populated_ranks_mask[1]) {
2328 if (channel == 1)
2329 secondary_total_rank =
2330 info->populated_ranks[1][0][0] +
2331 info->populated_ranks[1][0][1]
2332 + info->populated_ranks[1][1][0] +
2333 info->populated_ranks[1][1][1];
2334 else
2335 secondary_total_rank = 0;
2336 } else
2337 secondary_total_rank = total_rank;
2338
2339 {
2340 int i;
2341 for (i = 0; i < 8; i++)
2342 state[i] = BEFORE_USABLE;
2343 }
2344
2345 if (!first_run) {
2346 int is_all_ok = 1;
2347 for (lane = 0; lane < 8; lane++)
2348 if (timings[reg_178][channel][slot][rank][lane].
2349 smallest ==
2350 timings[reg_178][channel][slot][rank][lane].
2351 largest) {
2352 timings[reg_178][channel][slot][rank][lane].
2353 smallest = 0;
2354 timings[reg_178][channel][slot][rank][lane].
2355 largest = 0;
2356 is_all_ok = 0;
2357 }
2358 if (is_all_ok) {
2359 int i;
2360 for (i = 0; i < 8; i++)
2361 state[i] = COMPLETE;
2362 }
2363 }
2364
2365 for (reg1b3 = 0; reg1b3 < 0x30 && !validate_state(state); reg1b3++) {
2366 u8 failmask = 0;
2367 write_1d0(reg1b3 ^ 32, 0x1b3, 6, 1);
2368 write_1d0(reg1b3 ^ 32, 0x1a3, 6, 1);
2369 failmask = check_testing(info, total_rank, 0);
2370 write_mchbar32(0xfb0, read_mchbar32(0xfb0) | 0x00030000);
2371 do_fsm(state, count, failmask, 5, 47, lower_usable,
2372 upper_usable, reg1b3);
2373 }
2374
2375 if (reg1b3) {
2376 write_1d0(0, 0x1b3, 6, 1);
2377 write_1d0(0, 0x1a3, 6, 1);
2378 for (lane = 0; lane < 8; lane++) {
2379 if (state[lane] == COMPLETE) {
2380 timings[reg_178][channel][slot][rank][lane].
2381 smallest =
2382 lower_usable[lane] +
2383 (info->training.
2384 lane_timings[0][channel][slot][rank][lane]
2385 & 0x3F) - 32;
2386 timings[reg_178][channel][slot][rank][lane].
2387 largest =
2388 upper_usable[lane] +
2389 (info->training.
2390 lane_timings[0][channel][slot][rank][lane]
2391 & 0x3F) - 32;
2392 }
2393 }
2394 }
2395
2396 if (!first_run) {
2397 for (lane = 0; lane < 8; lane++)
2398 if (state[lane] == COMPLETE) {
2399 write_500(info, channel,
2400 timings[reg_178][channel][slot][rank]
2401 [lane].smallest,
2402 get_timing_register_addr(lane, 0,
2403 slot, rank),
2404 9, 1);
2405 write_500(info, channel,
2406 timings[reg_178][channel][slot][rank]
2407 [lane].smallest +
2408 info->training.
2409 lane_timings[1][channel][slot][rank]
2410 [lane]
2411 -
2412 info->training.
2413 lane_timings[0][channel][slot][rank]
2414 [lane], get_timing_register_addr(lane,
2415 1,
2416 slot,
2417 rank),
2418 9, 1);
2419 num_sucessfully_checked[lane] = 0;
2420 } else
2421 num_sucessfully_checked[lane] = -1;
2422
2423 do {
2424 u8 failmask = 0;
2425 int i;
2426 for (i = 0; i < niter; i++) {
2427 if (failmask == 0xFF)
2428 break;
2429 failmask |=
2430 check_testing_type2(info, total_rank, 2, i,
2431 0);
2432 failmask |=
2433 check_testing_type2(info, total_rank, 3, i,
2434 1);
2435 }
2436 write_mchbar32(0xfb0,
2437 read_mchbar32(0xfb0) | 0x00030000);
2438 for (lane = 0; lane < 8; lane++)
2439 if (num_sucessfully_checked[lane] != 0xffff) {
2440 if ((1 << lane) & failmask) {
2441 if (timings[reg_178][channel]
2442 [slot][rank][lane].
2443 largest <=
2444 timings[reg_178][channel]
2445 [slot][rank][lane].smallest)
2446 num_sucessfully_checked
2447 [lane] = -1;
2448 else {
2449 num_sucessfully_checked
2450 [lane] = 0;
2451 timings[reg_178]
2452 [channel][slot]
2453 [rank][lane].
2454 smallest++;
2455 write_500(info, channel,
2456 timings
2457 [reg_178]
2458 [channel]
2459 [slot][rank]
2460 [lane].
2461 smallest,
2462 get_timing_register_addr
2463 (lane, 0,
2464 slot, rank),
2465 9, 1);
2466 write_500(info, channel,
2467 timings
2468 [reg_178]
2469 [channel]
2470 [slot][rank]
2471 [lane].
2472 smallest +
2473 info->
2474 training.
2475 lane_timings
2476 [1][channel]
2477 [slot][rank]
2478 [lane]
2479 -
2480 info->
2481 training.
2482 lane_timings
2483 [0][channel]
2484 [slot][rank]
2485 [lane],
2486 get_timing_register_addr
2487 (lane, 1,
2488 slot, rank),
2489 9, 1);
2490 }
2491 } else
2492 num_sucessfully_checked[lane]++;
2493 }
2494 }
2495 while (!check_bounded(num_sucessfully_checked, 2));
2496
2497 for (lane = 0; lane < 8; lane++)
2498 if (state[lane] == COMPLETE) {
2499 write_500(info, channel,
2500 timings[reg_178][channel][slot][rank]
2501 [lane].largest,
2502 get_timing_register_addr(lane, 0,
2503 slot, rank),
2504 9, 1);
2505 write_500(info, channel,
2506 timings[reg_178][channel][slot][rank]
2507 [lane].largest +
2508 info->training.
2509 lane_timings[1][channel][slot][rank]
2510 [lane]
2511 -
2512 info->training.
2513 lane_timings[0][channel][slot][rank]
2514 [lane], get_timing_register_addr(lane,
2515 1,
2516 slot,
2517 rank),
2518 9, 1);
2519 num_sucessfully_checked[lane] = 0;
2520 } else
2521 num_sucessfully_checked[lane] = -1;
2522
2523 do {
2524 int failmask = 0;
2525 int i;
2526 for (i = 0; i < niter; i++) {
2527 if (failmask == 0xFF)
2528 break;
2529 failmask |=
2530 check_testing_type2(info, total_rank, 2, i,
2531 0);
2532 failmask |=
2533 check_testing_type2(info, total_rank, 3, i,
2534 1);
2535 }
2536
2537 write_mchbar32(0xfb0,
2538 read_mchbar32(0xfb0) | 0x00030000);
2539 for (lane = 0; lane < 8; lane++) {
2540 if (num_sucessfully_checked[lane] != 0xffff) {
2541 if ((1 << lane) & failmask) {
2542 if (timings[reg_178][channel]
2543 [slot][rank][lane].
2544 largest <=
2545 timings[reg_178][channel]
2546 [slot][rank][lane].
2547 smallest) {
2548 num_sucessfully_checked
2549 [lane] = -1;
2550 } else {
2551 num_sucessfully_checked
2552 [lane] = 0;
2553 timings[reg_178]
2554 [channel][slot]
2555 [rank][lane].
2556 largest--;
2557 write_500(info, channel,
2558 timings
2559 [reg_178]
2560 [channel]
2561 [slot][rank]
2562 [lane].
2563 largest,
2564 get_timing_register_addr
2565 (lane, 0,
2566 slot, rank),
2567 9, 1);
2568 write_500(info, channel,
2569 timings
2570 [reg_178]
2571 [channel]
2572 [slot][rank]
2573 [lane].
2574 largest +
2575 info->
2576 training.
2577 lane_timings
2578 [1][channel]
2579 [slot][rank]
2580 [lane]
2581 -
2582 info->
2583 training.
2584 lane_timings
2585 [0][channel]
2586 [slot][rank]
2587 [lane],
2588 get_timing_register_addr
2589 (lane, 1,
2590 slot, rank),
2591 9, 1);
2592 }
2593 } else
2594 num_sucessfully_checked[lane]++;
2595 }
2596 }
2597 }
2598 while (!check_bounded(num_sucessfully_checked, 3));
2599
2600 for (lane = 0; lane < 8; lane++) {
2601 write_500(info, channel,
2602 info->training.
2603 lane_timings[0][channel][slot][rank][lane],
2604 get_timing_register_addr(lane, 0, slot, rank),
2605 9, 1);
2606 write_500(info, channel,
2607 info->training.
2608 lane_timings[1][channel][slot][rank][lane],
2609 get_timing_register_addr(lane, 1, slot, rank),
2610 9, 1);
2611 if (timings[reg_178][channel][slot][rank][lane].
2612 largest <=
2613 timings[reg_178][channel][slot][rank][lane].
2614 smallest) {
2615 timings[reg_178][channel][slot][rank][lane].
2616 largest = 0;
2617 timings[reg_178][channel][slot][rank][lane].
2618 smallest = 0;
2619 }
2620 }
2621 }
2622}
2623
2624static void set_10b(struct raminfo *info, u8 val)
2625{
2626 int channel;
2627 int slot, rank;
2628 int lane;
2629
2630 if (read_1d0(0x10b, 6) == val)
2631 return;
2632
2633 write_1d0(val, 0x10b, 6, 1);
2634
2635 FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 9; lane++) {
2636 u16 reg_500;
2637 reg_500 = read_500(info, channel,
2638 get_timing_register_addr(lane, 0, slot,
2639 rank), 9);
2640 if (val == 1) {
2641 if (lut16[info->clock_speed_index] <= reg_500)
2642 reg_500 -= lut16[info->clock_speed_index];
2643 else
2644 reg_500 = 0;
2645 } else {
2646 reg_500 += lut16[info->clock_speed_index];
2647 }
2648 write_500(info, channel, reg_500,
2649 get_timing_register_addr(lane, 0, slot, rank), 9, 1);
2650 }
2651}
2652
2653static void set_ecc(int onoff)
2654{
2655 int channel;
2656 for (channel = 0; channel < NUM_CHANNELS; channel++) {
2657 u8 t;
2658 t = read_mchbar8((channel << 10) + 0x5f8);
2659 if (onoff)
2660 t |= 1;
2661 else
2662 t &= ~1;
2663 write_mchbar8((channel << 10) + 0x5f8, t);
2664 }
2665}
2666
2667static void set_178(u8 val)
2668{
2669 if (val >= 31)
2670 val = val - 31;
2671 else
2672 val = 63 - val;
2673
2674 write_1d0(2 * val, 0x178, 7, 1);
2675}
2676
2677static void
2678write_500_timings_type(struct raminfo *info, int channel, int slot, int rank,
2679 int type)
2680{
2681 int lane;
2682
2683 for (lane = 0; lane < 8; lane++)
2684 write_500(info, channel,
2685 info->training.
2686 lane_timings[type][channel][slot][rank][lane],
2687 get_timing_register_addr(lane, type, slot, rank), 9,
2688 0);
2689}
2690
2691static void
2692try_timing_offsets(struct raminfo *info, int channel,
2693 int slot, int rank, int totalrank)
2694{
2695 u16 count[8];
2696 enum state state[8];
2697 u8 lower_usable[8], upper_usable[8];
2698 int lane;
2699 int i;
2700 int flip = 1;
2701 int timing_offset;
2702
2703 for (i = 0; i < 8; i++)
2704 state[i] = BEFORE_USABLE;
2705
2706 memset(count, 0, sizeof(count));
2707
2708 for (lane = 0; lane < 8; lane++)
2709 write_500(info, channel,
2710 info->training.
2711 lane_timings[2][channel][slot][rank][lane] + 32,
2712 get_timing_register_addr(lane, 3, slot, rank), 9, 1);
2713
2714 for (timing_offset = 0; !validate_state(state) && timing_offset < 64;
2715 timing_offset++) {
2716 u8 failmask;
2717 write_1d0(timing_offset ^ 32, 0x1bb, 6, 1);
2718 failmask = 0;
2719 for (i = 0; i < 2 && failmask != 0xff; i++) {
2720 flip = !flip;
2721 write_testing(info, totalrank, flip);
2722 failmask |= check_testing(info, totalrank, flip);
2723 }
2724 do_fsm(state, count, failmask, 10, 63, lower_usable,
2725 upper_usable, timing_offset);
2726 }
2727 write_1d0(0, 0x1bb, 6, 1);
2728 dump_timings(info);
2729 if (!validate_state(state))
2730 die("Couldn't discover DRAM timings (1)\n");
2731
2732 for (lane = 0; lane < 8; lane++) {
2733 u8 bias = 0;
2734
2735 if (info->silicon_revision) {
2736 int usable_length;
2737
2738 usable_length = upper_usable[lane] - lower_usable[lane];
2739 if (usable_length >= 20) {
2740 bias = usable_length / 2 - 10;
2741 if (bias >= 2)
2742 bias = 2;
2743 }
2744 }
2745 write_500(info, channel,
2746 info->training.
2747 lane_timings[2][channel][slot][rank][lane] +
2748 (upper_usable[lane] + lower_usable[lane]) / 2 - bias,
2749 get_timing_register_addr(lane, 3, slot, rank), 9, 1);
2750 info->training.timing2_bounds[channel][slot][rank][lane][0] =
2751 info->training.lane_timings[2][channel][slot][rank][lane] +
2752 lower_usable[lane];
2753 info->training.timing2_bounds[channel][slot][rank][lane][1] =
2754 info->training.lane_timings[2][channel][slot][rank][lane] +
2755 upper_usable[lane];
2756 info->training.timing2_offset[channel][slot][rank][lane] =
2757 info->training.lane_timings[2][channel][slot][rank][lane];
2758 }
2759}
2760
2761static u8
2762choose_training(struct raminfo *info, int channel, int slot, int rank,
2763 int lane, timing_bounds_t * timings, u8 center_178)
2764{
2765 u16 central_weight;
2766 u16 side_weight;
2767 unsigned int sum = 0, count = 0;
2768 u8 span;
2769 u8 lower_margin, upper_margin;
2770 u8 reg_178;
2771 u8 result;
2772
2773 span = 12;
2774 central_weight = 20;
2775 side_weight = 20;
2776 if (info->silicon_revision == 1 && channel == 1) {
2777 central_weight = 5;
2778 side_weight = 20;
2779 if ((info->
2780 populated_ranks_mask[1] ^ (info->
2781 populated_ranks_mask[1] >> 2)) &
2782 1)
2783 span = 18;
2784 }
2785 if ((info->populated_ranks_mask[0] & 5) == 5) {
2786 central_weight = 20;
2787 side_weight = 20;
2788 }
2789 if (info->clock_speed_index >= 2
2790 && (info->populated_ranks_mask[0] & 5) == 5 && slot == 1) {
2791 if (info->silicon_revision == 1) {
2792 switch (channel) {
2793 case 0:
2794 if (lane == 1) {
2795 central_weight = 10;
2796 side_weight = 20;
2797 }
2798 break;
2799 case 1:
2800 if (lane == 6) {
2801 side_weight = 5;
2802 central_weight = 20;
2803 }
2804 break;
2805 }
2806 }
2807 if (info->silicon_revision == 0 && channel == 0 && lane == 0) {
2808 side_weight = 5;
2809 central_weight = 20;
2810 }
2811 }
2812 for (reg_178 = center_178 - span; reg_178 <= center_178 + span;
2813 reg_178 += span) {
2814 u8 smallest;
2815 u8 largest;
2816 largest = timings[reg_178][channel][slot][rank][lane].largest;
2817 smallest = timings[reg_178][channel][slot][rank][lane].smallest;
2818 if (largest - smallest + 1 >= 5) {
2819 unsigned int weight;
2820 if (reg_178 == center_178)
2821 weight = central_weight;
2822 else
2823 weight = side_weight;
2824 sum += weight * (largest + smallest);
2825 count += weight;
2826 }
2827 }
2828 dump_timings(info);
2829 if (count == 0)
2830 die("Couldn't discover DRAM timings (2)\n");
2831 result = sum / (2 * count);
2832 lower_margin =
2833 result - timings[center_178][channel][slot][rank][lane].smallest;
2834 upper_margin =
2835 timings[center_178][channel][slot][rank][lane].largest - result;
2836 if (upper_margin < 10 && lower_margin > 10)
2837 result -= min(lower_margin - 10, 10 - upper_margin);
2838 if (upper_margin > 10 && lower_margin < 10)
2839 result += min(upper_margin - 10, 10 - lower_margin);
2840 return result;
2841}
2842
2843#define STANDARD_MIN_MARGIN 5
2844
2845static u8 choose_reg178(struct raminfo *info, timing_bounds_t * timings)
2846{
2847 u16 margin[64];
2848 int lane, rank, slot, channel;
2849 u8 reg178;
2850 int count = 0, sum = 0;
2851
2852 for (reg178 = reg178_min[info->clock_speed_index];
2853 reg178 < reg178_max[info->clock_speed_index];
2854 reg178 += reg178_step[info->clock_speed_index]) {
2855 margin[reg178] = -1;
2856 FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 8; lane++) {
2857 int curmargin =
2858 timings[reg178][channel][slot][rank][lane].largest -
2859 timings[reg178][channel][slot][rank][lane].
2860 smallest + 1;
2861 if (curmargin < margin[reg178])
2862 margin[reg178] = curmargin;
2863 }
2864 if (margin[reg178] >= STANDARD_MIN_MARGIN) {
2865 u16 weight;
2866 weight = margin[reg178] - STANDARD_MIN_MARGIN;
2867 sum += weight * reg178;
2868 count += weight;
2869 }
2870 }
2871 dump_timings(info);
2872 if (count == 0)
2873 die("Couldn't discover DRAM timings (3)\n");
2874
2875 u8 threshold;
2876
2877 for (threshold = 30; threshold >= 5; threshold--) {
2878 int usable_length = 0;
2879 int smallest_fount = 0;
2880 for (reg178 = reg178_min[info->clock_speed_index];
2881 reg178 < reg178_max[info->clock_speed_index];
2882 reg178 += reg178_step[info->clock_speed_index])
2883 if (margin[reg178] >= threshold) {
2884 usable_length +=
2885 reg178_step[info->clock_speed_index];
2886 info->training.reg178_largest =
2887 reg178 -
2888 2 * reg178_step[info->clock_speed_index];
2889
2890 if (!smallest_fount) {
2891 smallest_fount = 1;
2892 info->training.reg178_smallest =
2893 reg178 +
2894 reg178_step[info->
2895 clock_speed_index];
2896 }
2897 }
2898 if (usable_length >= 0x21)
2899 break;
2900 }
2901
2902 return sum / count;
2903}
2904
2905static int check_cached_sanity(struct raminfo *info)
2906{
2907 int lane;
2908 int slot, rank;
2909 int channel;
2910
2911 if (!info->cached_training)
2912 return 0;
2913
2914 for (channel = 0; channel < NUM_CHANNELS; channel++)
2915 for (slot = 0; slot < NUM_SLOTS; slot++)
2916 for (rank = 0; rank < NUM_RANKS; rank++)
2917 for (lane = 0; lane < 8 + info->use_ecc; lane++) {
2918 u16 cached_value, estimation_value;
2919 cached_value =
2920 info->cached_training->
2921 lane_timings[1][channel][slot][rank]
2922 [lane];
2923 if (cached_value >= 0x18
2924 && cached_value <= 0x1E7) {
2925 estimation_value =
2926 info->training.
2927 lane_timings[1][channel]
2928 [slot][rank][lane];
2929 if (estimation_value <
2930 cached_value - 24)
2931 return 0;
2932 if (estimation_value >
2933 cached_value + 24)
2934 return 0;
2935 }
2936 }
2937 return 1;
2938}
2939
2940static int try_cached_training(struct raminfo *info)
2941{
2942 u8 saved_243[2];
2943 u8 tm;
2944
2945 int channel, slot, rank, lane;
2946 int flip = 1;
2947 int i, j;
2948
2949 if (!check_cached_sanity(info))
2950 return 0;
2951
2952 info->training.reg178_center = info->cached_training->reg178_center;
2953 info->training.reg178_smallest = info->cached_training->reg178_smallest;
2954 info->training.reg178_largest = info->cached_training->reg178_largest;
2955 memcpy(&info->training.timing_bounds,
2956 &info->cached_training->timing_bounds,
2957 sizeof(info->training.timing_bounds));
2958 memcpy(&info->training.timing_offset,
2959 &info->cached_training->timing_offset,
2960 sizeof(info->training.timing_offset));
2961
2962 write_1d0(2, 0x142, 3, 1);
2963 saved_243[0] = read_mchbar8(0x243);
2964 saved_243[1] = read_mchbar8(0x643);
2965 write_mchbar8(0x243, saved_243[0] | 2);
2966 write_mchbar8(0x643, saved_243[1] | 2);
2967 set_ecc(0);
2968 pcie_write_config16(NORTHBRIDGE, 0xc8, 3);
2969 if (read_1d0(0x10b, 6) & 1)
2970 set_10b(info, 0);
2971 for (tm = 0; tm < 2; tm++) {
2972 int totalrank;
2973
2974 set_178(tm ? info->cached_training->reg178_largest : info->
2975 cached_training->reg178_smallest);
2976
2977 totalrank = 0;
2978 /* Check timing ranges. With i == 0 we check smallest one and with
2979 i == 1 the largest bound. With j == 0 we check that on the bound
2980 it still works whereas with j == 1 we check that just outside of
2981 bound we fail.
2982 */
2983 FOR_POPULATED_RANKS_BACKWARDS {
2984 for (i = 0; i < 2; i++) {
2985 for (lane = 0; lane < 8; lane++) {
2986 write_500(info, channel,
2987 info->cached_training->
2988 timing2_bounds[channel][slot]
2989 [rank][lane][i],
2990 get_timing_register_addr(lane,
2991 3,
2992 slot,
2993 rank),
2994 9, 1);
2995
2996 if (!i)
2997 write_500(info, channel,
2998 info->
2999 cached_training->
3000 timing2_offset
3001 [channel][slot][rank]
3002 [lane],
3003 get_timing_register_addr
3004 (lane, 2, slot, rank),
3005 9, 1);
3006 write_500(info, channel,
3007 i ? info->cached_training->
3008 timing_bounds[tm][channel]
3009 [slot][rank][lane].
3010 largest : info->
3011 cached_training->
3012 timing_bounds[tm][channel]
3013 [slot][rank][lane].smallest,
3014 get_timing_register_addr(lane,
3015 0,
3016 slot,
3017 rank),
3018 9, 1);
3019 write_500(info, channel,
3020 info->cached_training->
3021 timing_offset[channel][slot]
3022 [rank][lane] +
3023 (i ? info->cached_training->
3024 timing_bounds[tm][channel]
3025 [slot][rank][lane].
3026 largest : info->
3027 cached_training->
3028 timing_bounds[tm][channel]
3029 [slot][rank][lane].
3030 smallest) - 64,
3031 get_timing_register_addr(lane,
3032 1,
3033 slot,
3034 rank),
3035 9, 1);
3036 }
3037 for (j = 0; j < 2; j++) {
3038 u8 failmask;
3039 u8 expected_failmask;
3040 char reg1b3;
3041
3042 reg1b3 = (j == 1) + 4;
3043 reg1b3 =
3044 j == i ? reg1b3 : (-reg1b3) & 0x3f;
3045 write_1d0(reg1b3, 0x1bb, 6, 1);
3046 write_1d0(reg1b3, 0x1b3, 6, 1);
3047 write_1d0(reg1b3, 0x1a3, 6, 1);
3048
3049 flip = !flip;
3050 write_testing(info, totalrank, flip);
3051 failmask =
3052 check_testing(info, totalrank,
3053 flip);
3054 expected_failmask =
3055 j == 0 ? 0x00 : 0xff;
3056 if (failmask != expected_failmask)
3057 goto fail;
3058 }
3059 }
3060 totalrank++;
3061 }
3062 }
3063
3064 set_178(info->cached_training->reg178_center);
3065 if (info->use_ecc)
3066 set_ecc(1);
3067 write_training_data(info);
3068 write_1d0(0, 322, 3, 1);
3069 info->training = *info->cached_training;
3070
3071 write_1d0(0, 0x1bb, 6, 1);
3072 write_1d0(0, 0x1b3, 6, 1);
3073 write_1d0(0, 0x1a3, 6, 1);
3074 write_mchbar8(0x243, saved_243[0]);
3075 write_mchbar8(0x643, saved_243[1]);
3076
3077 return 1;
3078
3079fail:
3080 FOR_POPULATED_RANKS {
3081 write_500_timings_type(info, channel, slot, rank, 1);
3082 write_500_timings_type(info, channel, slot, rank, 2);
3083 write_500_timings_type(info, channel, slot, rank, 3);
3084 }
3085
3086 write_1d0(0, 0x1bb, 6, 1);
3087 write_1d0(0, 0x1b3, 6, 1);
3088 write_1d0(0, 0x1a3, 6, 1);
3089 write_mchbar8(0x243, saved_243[0]);
3090 write_mchbar8(0x643, saved_243[1]);
3091
3092 return 0;
3093}
3094
3095static void do_ram_training(struct raminfo *info)
3096{
3097 u8 saved_243[2];
3098 int totalrank = 0;
3099 u8 reg_178;
3100 int niter;
3101
3102 timing_bounds_t timings[64];
3103 int lane, rank, slot, channel;
3104 u8 reg178_center;
3105
3106 write_1d0(2, 0x142, 3, 1);
3107 saved_243[0] = read_mchbar8(0x243);
3108 saved_243[1] = read_mchbar8(0x643);
3109 write_mchbar8(0x243, saved_243[0] | 2);
3110 write_mchbar8(0x643, saved_243[1] | 2);
3111 switch (info->clock_speed_index) {
3112 case 0:
3113 niter = 5;
3114 break;
3115 case 1:
3116 niter = 10;
3117 break;
3118 default:
3119 niter = 19;
3120 break;
3121 }
3122 set_ecc(0);
3123
3124 FOR_POPULATED_RANKS_BACKWARDS {
3125 int i;
3126
3127 write_500_timings_type(info, channel, slot, rank, 0);
3128
3129 write_testing(info, totalrank, 0);
3130 for (i = 0; i < niter; i++) {
3131 write_testing_type2(info, totalrank, 2, i, 0);
3132 write_testing_type2(info, totalrank, 3, i, 1);
3133 }
3134 pcie_write_config8(NORTHBRIDGE, 0xc0, 0x01);
3135 totalrank++;
3136 }
3137
3138 if (reg178_min[info->clock_speed_index] <
3139 reg178_max[info->clock_speed_index])
3140 memset(timings[reg178_min[info->clock_speed_index]], 0,
3141 sizeof(timings[0]) *
3142 (reg178_max[info->clock_speed_index] -
3143 reg178_min[info->clock_speed_index]));
3144 for (reg_178 = reg178_min[info->clock_speed_index];
3145 reg_178 < reg178_max[info->clock_speed_index];
3146 reg_178 += reg178_step[info->clock_speed_index]) {
3147 totalrank = 0;
3148 set_178(reg_178);
3149 for (channel = NUM_CHANNELS - 1; channel >= 0; channel--)
3150 for (slot = 0; slot < NUM_SLOTS; slot++)
3151 for (rank = 0; rank < NUM_RANKS; rank++) {
3152 memset(&timings[reg_178][channel][slot]
3153 [rank][0].smallest, 0, 16);
3154 if (info->
3155 populated_ranks[channel][slot]
3156 [rank]) {
3157 train_ram_at_178(info, channel,
3158 slot, rank,
3159 totalrank,
3160 reg_178, 1,
3161 niter,
3162 timings);
3163 totalrank++;
3164 }
3165 }
3166 }
3167
3168 reg178_center = choose_reg178(info, timings);
3169
3170 FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 8; lane++) {
3171 info->training.timing_bounds[0][channel][slot][rank][lane].
3172 smallest =
3173 timings[info->training.
3174 reg178_smallest][channel][slot][rank][lane].
3175 smallest;
3176 info->training.timing_bounds[0][channel][slot][rank][lane].
3177 largest =
3178 timings[info->training.
3179 reg178_smallest][channel][slot][rank][lane].largest;
3180 info->training.timing_bounds[1][channel][slot][rank][lane].
3181 smallest =
3182 timings[info->training.
3183 reg178_largest][channel][slot][rank][lane].smallest;
3184 info->training.timing_bounds[1][channel][slot][rank][lane].
3185 largest =
3186 timings[info->training.
3187 reg178_largest][channel][slot][rank][lane].largest;
3188 info->training.timing_offset[channel][slot][rank][lane] =
3189 info->training.lane_timings[1][channel][slot][rank][lane]
3190 -
3191 info->training.lane_timings[0][channel][slot][rank][lane] +
3192 64;
3193 }
3194
3195 if (info->silicon_revision == 1
3196 && (info->
3197 populated_ranks_mask[1] ^ (info->
3198 populated_ranks_mask[1] >> 2)) & 1) {
3199 int ranks_after_channel1;
3200
3201 totalrank = 0;
3202 for (reg_178 = reg178_center - 18;
3203 reg_178 <= reg178_center + 18; reg_178 += 18) {
3204 totalrank = 0;
3205 set_178(reg_178);
3206 for (slot = 0; slot < NUM_SLOTS; slot++)
3207 for (rank = 0; rank < NUM_RANKS; rank++) {
3208 if (info->
3209 populated_ranks[1][slot][rank]) {
3210 train_ram_at_178(info, 1, slot,
3211 rank,
3212 totalrank,
3213 reg_178, 0,
3214 niter,
3215 timings);
3216 totalrank++;
3217 }
3218 }
3219 }
3220 ranks_after_channel1 = totalrank;
3221
3222 for (reg_178 = reg178_center - 12;
3223 reg_178 <= reg178_center + 12; reg_178 += 12) {
3224 totalrank = ranks_after_channel1;
3225 set_178(reg_178);
3226 for (slot = 0; slot < NUM_SLOTS; slot++)
3227 for (rank = 0; rank < NUM_RANKS; rank++)
3228 if (info->
3229 populated_ranks[0][slot][rank]) {
3230 train_ram_at_178(info, 0, slot,
3231 rank,
3232 totalrank,
3233 reg_178, 0,
3234 niter,
3235 timings);
3236 totalrank++;
3237 }
3238
3239 }
3240 } else {
3241 for (reg_178 = reg178_center - 12;
3242 reg_178 <= reg178_center + 12; reg_178 += 12) {
3243 totalrank = 0;
3244 set_178(reg_178);
3245 FOR_POPULATED_RANKS_BACKWARDS {
3246 train_ram_at_178(info, channel, slot, rank,
3247 totalrank, reg_178, 0, niter,
3248 timings);
3249 totalrank++;
3250 }
3251 }
3252 }
3253
3254 set_178(reg178_center);
3255 FOR_POPULATED_RANKS_BACKWARDS for (lane = 0; lane < 8; lane++) {
3256 u16 tm0;
3257
3258 tm0 =
3259 choose_training(info, channel, slot, rank, lane, timings,
3260 reg178_center);
3261 write_500(info, channel, tm0,
3262 get_timing_register_addr(lane, 0, slot, rank), 9, 1);
3263 write_500(info, channel,
3264 tm0 +
3265 info->training.
3266 lane_timings[1][channel][slot][rank][lane] -
3267 info->training.
3268 lane_timings[0][channel][slot][rank][lane],
3269 get_timing_register_addr(lane, 1, slot, rank), 9, 1);
3270 }
3271
3272 totalrank = 0;
3273 FOR_POPULATED_RANKS_BACKWARDS {
3274 try_timing_offsets(info, channel, slot, rank, totalrank);
3275 totalrank++;
3276 }
3277 write_mchbar8(0x243, saved_243[0]);
3278 write_mchbar8(0x643, saved_243[1]);
3279 write_1d0(0, 0x142, 3, 1);
3280 info->training.reg178_center = reg178_center;
3281}
3282
3283static void ram_training(struct raminfo *info)
3284{
3285 u16 saved_fc4;
3286
3287 saved_fc4 = read_mchbar16(0xfc4);
3288 write_mchbar16(0xfc4, 0xffff);
3289
3290 if (info->revision >= 8)
3291 read_4090(info);
3292
3293 if (!try_cached_training(info))
3294 do_ram_training(info);
3295 if ((info->silicon_revision == 2 || info->silicon_revision == 3)
3296 && info->clock_speed_index < 2)
3297 set_10b(info, 1);
3298 write_mchbar16(0xfc4, saved_fc4);
3299}
3300
3301static unsigned gcd(unsigned a, unsigned b)
3302{
3303 unsigned t;
3304 if (a > b) {
3305 t = a;
3306 a = b;
3307 b = t;
3308 }
3309 /* invariant a < b. */
3310 while (a) {
3311 t = b % a;
3312 b = a;
3313 a = t;
3314 }
3315 return b;
3316}
3317
3318static inline int div_roundup(int a, int b)
3319{
Edward O'Callaghan7116ac82014-07-08 01:53:24 +10003320 return CEIL_DIV(a, b);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003321}
3322
3323static unsigned lcm(unsigned a, unsigned b)
3324{
3325 return (a * b) / gcd(a, b);
3326}
3327
3328struct stru1 {
3329 u8 freqs_reversed;
3330 u8 freq_diff_reduced;
3331 u8 freq_min_reduced;
3332 u8 divisor_f4_to_fmax;
3333 u8 divisor_f3_to_fmax;
3334 u8 freq4_to_max_remainder;
3335 u8 freq3_to_2_remainder;
3336 u8 freq3_to_2_remaindera;
3337 u8 freq4_to_2_remainder;
3338 int divisor_f3_to_f1, divisor_f4_to_f2;
3339 int common_time_unit_ps;
3340 int freq_max_reduced;
3341};
3342
3343static void
3344compute_frequence_ratios(struct raminfo *info, u16 freq1, u16 freq2,
3345 int num_cycles_2, int num_cycles_1, int round_it,
3346 int add_freqs, struct stru1 *result)
3347{
3348 int g;
3349 int common_time_unit_ps;
3350 int freq1_reduced, freq2_reduced;
3351 int freq_min_reduced;
3352 int freq_max_reduced;
3353 int freq3, freq4;
3354
3355 g = gcd(freq1, freq2);
3356 freq1_reduced = freq1 / g;
3357 freq2_reduced = freq2 / g;
3358 freq_min_reduced = min(freq1_reduced, freq2_reduced);
3359 freq_max_reduced = max(freq1_reduced, freq2_reduced);
3360
3361 common_time_unit_ps = div_roundup(900000, lcm(freq1, freq2));
3362 freq3 = div_roundup(num_cycles_2, common_time_unit_ps) - 1;
3363 freq4 = div_roundup(num_cycles_1, common_time_unit_ps) - 1;
3364 if (add_freqs) {
3365 freq3 += freq2_reduced;
3366 freq4 += freq1_reduced;
3367 }
3368
3369 if (round_it) {
3370 result->freq3_to_2_remainder = 0;
3371 result->freq3_to_2_remaindera = 0;
3372 result->freq4_to_max_remainder = 0;
3373 result->divisor_f4_to_f2 = 0;
3374 result->divisor_f3_to_f1 = 0;
3375 } else {
3376 if (freq2_reduced < freq1_reduced) {
3377 result->freq3_to_2_remainder =
3378 result->freq3_to_2_remaindera =
3379 freq3 % freq1_reduced - freq1_reduced + 1;
3380 result->freq4_to_max_remainder =
3381 -(freq4 % freq1_reduced);
3382 result->divisor_f3_to_f1 = freq3 / freq1_reduced;
3383 result->divisor_f4_to_f2 =
3384 (freq4 -
3385 (freq1_reduced - freq2_reduced)) / freq2_reduced;
3386 result->freq4_to_2_remainder =
3387 -(char)((freq1_reduced - freq2_reduced) +
3388 ((u8) freq4 -
3389 (freq1_reduced -
3390 freq2_reduced)) % (u8) freq2_reduced);
3391 } else {
3392 if (freq2_reduced > freq1_reduced) {
3393 result->freq4_to_max_remainder =
3394 (freq4 % freq2_reduced) - freq2_reduced + 1;
3395 result->freq4_to_2_remainder =
3396 freq4 % freq_max_reduced -
3397 freq_max_reduced + 1;
3398 } else {
3399 result->freq4_to_max_remainder =
3400 -(freq4 % freq2_reduced);
3401 result->freq4_to_2_remainder =
3402 -(char)(freq4 % freq_max_reduced);
3403 }
3404 result->divisor_f4_to_f2 = freq4 / freq2_reduced;
3405 result->divisor_f3_to_f1 =
3406 (freq3 -
3407 (freq2_reduced - freq1_reduced)) / freq1_reduced;
3408 result->freq3_to_2_remainder = -(freq3 % freq2_reduced);
3409 result->freq3_to_2_remaindera =
3410 -(char)((freq_max_reduced - freq_min_reduced) +
3411 (freq3 -
3412 (freq_max_reduced -
3413 freq_min_reduced)) % freq1_reduced);
3414 }
3415 }
3416 result->divisor_f3_to_fmax = freq3 / freq_max_reduced;
3417 result->divisor_f4_to_fmax = freq4 / freq_max_reduced;
3418 if (round_it) {
3419 if (freq2_reduced > freq1_reduced) {
3420 if (freq3 % freq_max_reduced)
3421 result->divisor_f3_to_fmax++;
3422 }
3423 if (freq2_reduced < freq1_reduced) {
3424 if (freq4 % freq_max_reduced)
3425 result->divisor_f4_to_fmax++;
3426 }
3427 }
3428 result->freqs_reversed = (freq2_reduced < freq1_reduced);
3429 result->freq_diff_reduced = freq_max_reduced - freq_min_reduced;
3430 result->freq_min_reduced = freq_min_reduced;
3431 result->common_time_unit_ps = common_time_unit_ps;
3432 result->freq_max_reduced = freq_max_reduced;
3433}
3434
3435static void
3436set_2d5x_reg(struct raminfo *info, u16 reg, u16 freq1, u16 freq2,
3437 int num_cycles_2, int num_cycles_1, int num_cycles_3,
3438 int num_cycles_4, int reverse)
3439{
3440 struct stru1 vv;
3441 char multiplier;
3442
3443 compute_frequence_ratios(info, freq1, freq2, num_cycles_2, num_cycles_1,
3444 0, 1, &vv);
3445
3446 multiplier =
3447 div_roundup(max
3448 (div_roundup(num_cycles_2, vv.common_time_unit_ps) +
3449 div_roundup(num_cycles_3, vv.common_time_unit_ps),
3450 div_roundup(num_cycles_1,
3451 vv.common_time_unit_ps) +
3452 div_roundup(num_cycles_4, vv.common_time_unit_ps))
3453 + vv.freq_min_reduced - 1, vv.freq_max_reduced) - 1;
3454
3455 u32 y =
3456 (u8) ((vv.freq_max_reduced - vv.freq_min_reduced) +
3457 vv.freq_max_reduced * multiplier)
3458 | (vv.
3459 freqs_reversed << 8) | ((u8) (vv.freq_min_reduced *
3460 multiplier) << 16) | ((u8) (vv.
3461 freq_min_reduced
3462 *
3463 multiplier)
3464 << 24);
3465 u32 x =
3466 vv.freq3_to_2_remaindera | (vv.freq4_to_2_remainder << 8) | (vv.
3467 divisor_f3_to_f1
3468 << 16)
3469 | (vv.divisor_f4_to_f2 << 20) | (vv.freq_min_reduced << 24);
3470 if (reverse) {
3471 write_mchbar32(reg, y);
3472 write_mchbar32(reg + 4, x);
3473 } else {
3474 write_mchbar32(reg + 4, y);
3475 write_mchbar32(reg, x);
3476 }
3477}
3478
3479static void
3480set_6d_reg(struct raminfo *info, u16 reg, u16 freq1, u16 freq2,
3481 int num_cycles_1, int num_cycles_2, int num_cycles_3,
3482 int num_cycles_4)
3483{
3484 struct stru1 ratios1;
3485 struct stru1 ratios2;
3486
3487 compute_frequence_ratios(info, freq1, freq2, num_cycles_1, num_cycles_2,
3488 0, 1, &ratios2);
3489 compute_frequence_ratios(info, freq1, freq2, num_cycles_3, num_cycles_4,
3490 0, 1, &ratios1);
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003491 printk (BIOS_SPEW, "[%x] <= %x\n", reg,
3492 ratios1.freq4_to_max_remainder | (ratios2.
3493 freq4_to_max_remainder
3494 << 8)
3495 | (ratios1.divisor_f4_to_fmax << 16) | (ratios2.
3496 divisor_f4_to_fmax
3497 << 20));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003498 write_mchbar32(reg,
3499 ratios1.freq4_to_max_remainder | (ratios2.
3500 freq4_to_max_remainder
3501 << 8)
3502 | (ratios1.divisor_f4_to_fmax << 16) | (ratios2.
3503 divisor_f4_to_fmax
3504 << 20));
3505}
3506
3507static void
3508set_2dx8_reg(struct raminfo *info, u16 reg, u8 mode, u16 freq1, u16 freq2,
3509 int num_cycles_2, int num_cycles_1, int round_it, int add_freqs)
3510{
3511 struct stru1 ratios;
3512
3513 compute_frequence_ratios(info, freq1, freq2, num_cycles_2, num_cycles_1,
3514 round_it, add_freqs, &ratios);
3515 switch (mode) {
3516 case 0:
3517 write_mchbar32(reg + 4,
3518 ratios.freq_diff_reduced | (ratios.
3519 freqs_reversed <<
3520 8));
3521 write_mchbar32(reg,
3522 ratios.freq3_to_2_remainder | (ratios.
3523 freq4_to_max_remainder
3524 << 8)
3525 | (ratios.divisor_f3_to_fmax << 16) | (ratios.
3526 divisor_f4_to_fmax
3527 << 20) |
3528 (ratios.freq_min_reduced << 24));
3529 break;
3530
3531 case 1:
3532 write_mchbar32(reg,
3533 ratios.freq3_to_2_remainder | (ratios.
3534 divisor_f3_to_fmax
3535 << 16));
3536 break;
3537
3538 case 2:
3539 write_mchbar32(reg,
3540 ratios.freq3_to_2_remainder | (ratios.
3541 freq4_to_max_remainder
3542 << 8) | (ratios.
3543 divisor_f3_to_fmax
3544 << 16) |
3545 (ratios.divisor_f4_to_fmax << 20));
3546 break;
3547
3548 case 4:
3549 write_mchbar32(reg, (ratios.divisor_f3_to_fmax << 4)
3550 | (ratios.divisor_f4_to_fmax << 8) | (ratios.
3551 freqs_reversed
3552 << 12) |
3553 (ratios.freq_min_reduced << 16) | (ratios.
3554 freq_diff_reduced
3555 << 24));
3556 break;
3557 }
3558}
3559
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003560static void set_2dxx_series(struct raminfo *info, int s3resume)
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003561{
3562 set_2dx8_reg(info, 0x2d00, 0, 0x78, frequency_11(info) / 2, 1359, 1005,
3563 0, 1);
3564 set_2dx8_reg(info, 0x2d08, 0, 0x78, 0x78, 3273, 5033, 1, 1);
3565 set_2dx8_reg(info, 0x2d10, 0, 0x78, info->fsb_frequency, 1475, 1131, 0,
3566 1);
3567 set_2dx8_reg(info, 0x2d18, 0, 2 * info->fsb_frequency,
3568 frequency_11(info), 1231, 1524, 0, 1);
3569 set_2dx8_reg(info, 0x2d20, 0, 2 * info->fsb_frequency,
3570 frequency_11(info) / 2, 1278, 2008, 0, 1);
3571 set_2dx8_reg(info, 0x2d28, 0, info->fsb_frequency, frequency_11(info),
3572 1167, 1539, 0, 1);
3573 set_2dx8_reg(info, 0x2d30, 0, info->fsb_frequency,
3574 frequency_11(info) / 2, 1403, 1318, 0, 1);
3575 set_2dx8_reg(info, 0x2d38, 0, info->fsb_frequency, 0x78, 3460, 5363, 1,
3576 1);
3577 set_2dx8_reg(info, 0x2d40, 0, info->fsb_frequency, 0x3c, 2792, 5178, 1,
3578 1);
3579 set_2dx8_reg(info, 0x2d48, 0, 2 * info->fsb_frequency, 0x78, 2738, 4610,
3580 1, 1);
3581 set_2dx8_reg(info, 0x2d50, 0, info->fsb_frequency, 0x78, 2819, 5932, 1,
3582 1);
3583 set_2dx8_reg(info, 0x6d4, 1, info->fsb_frequency,
3584 frequency_11(info) / 2, 4000, 0, 0, 0);
3585 set_2dx8_reg(info, 0x6d8, 2, info->fsb_frequency,
3586 frequency_11(info) / 2, 4000, 4000, 0, 0);
3587
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003588 if (s3resume) {
3589 printk (BIOS_SPEW, "[6dc] <= %x\n", info->cached_training->reg_6dc);
3590 write_mchbar32(0x6dc, info->cached_training->reg_6dc);
3591 } else
3592 set_6d_reg(info, 0x6dc, 2 * info->fsb_frequency, frequency_11(info), 0,
3593 info->delay46_ps[0], 0,
3594 info->delay54_ps[0]);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003595 set_2dx8_reg(info, 0x6e0, 1, 2 * info->fsb_frequency,
3596 frequency_11(info), 2500, 0, 0, 0);
3597 set_2dx8_reg(info, 0x6e4, 1, 2 * info->fsb_frequency,
3598 frequency_11(info) / 2, 3500, 0, 0, 0);
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003599 if (s3resume) {
3600 printk (BIOS_SPEW, "[6e8] <= %x\n", info->cached_training->reg_6e8);
3601 write_mchbar32(0x6e8, info->cached_training->reg_6e8);
3602 } else
3603 set_6d_reg(info, 0x6e8, 2 * info->fsb_frequency, frequency_11(info), 0,
3604 info->delay46_ps[1], 0,
3605 info->delay54_ps[1]);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003606 set_2d5x_reg(info, 0x2d58, 0x78, 0x78, 864, 1195, 762, 786, 0);
3607 set_2d5x_reg(info, 0x2d60, 0x195, info->fsb_frequency, 1352, 725, 455,
3608 470, 0);
3609 set_2d5x_reg(info, 0x2d68, 0x195, 0x3c, 2707, 5632, 3277, 2207, 0);
3610 set_2d5x_reg(info, 0x2d70, 0x195, frequency_11(info) / 2, 1276, 758,
3611 454, 459, 0);
3612 set_2d5x_reg(info, 0x2d78, 0x195, 0x78, 1021, 799, 510, 513, 0);
3613 set_2d5x_reg(info, 0x2d80, info->fsb_frequency, 0xe1, 0, 2862, 2579,
3614 2588, 0);
3615 set_2d5x_reg(info, 0x2d88, info->fsb_frequency, 0xe1, 0, 2690, 2405,
3616 2405, 0);
3617 set_2d5x_reg(info, 0x2da0, 0x78, 0xe1, 0, 2560, 2264, 2251, 0);
3618 set_2d5x_reg(info, 0x2da8, 0x195, frequency_11(info), 1060, 775, 484,
3619 480, 0);
3620 set_2d5x_reg(info, 0x2db0, 0x195, 0x78, 4183, 6023, 2217, 2048, 0);
3621 write_mchbar32(0x2dbc, ((frequency_11(info) / 2) - 1) | 0xe00000);
3622 write_mchbar32(0x2db8, ((info->fsb_frequency - 1) << 16) | 0x77);
3623}
3624
3625static u16 get_max_timing(struct raminfo *info, int channel)
3626{
3627 int slot, rank, lane;
3628 u16 ret = 0;
3629
3630 if ((read_mchbar8(0x2ca8) >> 2) < 1)
3631 return 384;
3632
3633 if (info->revision < 8)
3634 return 256;
3635
3636 for (slot = 0; slot < NUM_SLOTS; slot++)
3637 for (rank = 0; rank < NUM_RANKS; rank++)
3638 if (info->populated_ranks[channel][slot][rank])
3639 for (lane = 0; lane < 8 + info->use_ecc; lane++)
3640 ret = max(ret, read_500(info, channel,
3641 get_timing_register_addr
3642 (lane, 0, slot,
3643 rank), 9));
3644 return ret;
3645}
3646
3647static void set_274265(struct raminfo *info)
3648{
3649 int delay_a_ps, delay_b_ps, delay_c_ps, delay_d_ps;
3650 int delay_e_ps, delay_e_cycles, delay_f_cycles;
3651 int delay_e_over_cycle_ps;
3652 int cycletime_ps;
3653 int channel;
3654
3655 delay_a_ps = 4 * halfcycle_ps(info) + 6 * fsbcycle_ps(info);
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003656 info->training.reg2ca9_bit0 = 0;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003657 for (channel = 0; channel < NUM_CHANNELS; channel++) {
3658 cycletime_ps =
3659 900000 / lcm(2 * info->fsb_frequency, frequency_11(info));
3660 delay_d_ps =
3661 (halfcycle_ps(info) * get_max_timing(info, channel) >> 6)
3662 - info->some_delay_3_ps_rounded + 200;
3663 if (!
3664 ((info->silicon_revision == 0
3665 || info->silicon_revision == 1)
3666 && (info->revision >= 8)))
3667 delay_d_ps += halfcycle_ps(info) * 2;
3668 delay_d_ps +=
3669 halfcycle_ps(info) * (!info->revision_flag_1 +
3670 info->some_delay_2_halfcycles_ceil +
3671 2 * info->some_delay_1_cycle_floor +
3672 info->clock_speed_index +
3673 2 * info->cas_latency - 7 + 11);
3674 delay_d_ps += info->revision >= 8 ? 2758 : 4428;
3675
3676 write_mchbar32(0x140,
3677 (read_mchbar32(0x140) & 0xfaffffff) | 0x2000000);
3678 write_mchbar32(0x138,
3679 (read_mchbar32(0x138) & 0xfaffffff) | 0x2000000);
3680 if ((read_mchbar8(0x144) & 0x1f) > 0x13)
3681 delay_d_ps += 650;
3682 delay_c_ps = delay_d_ps + 1800;
3683 if (delay_c_ps <= delay_a_ps)
3684 delay_e_ps = 0;
3685 else
3686 delay_e_ps =
3687 cycletime_ps * div_roundup(delay_c_ps - delay_a_ps,
3688 cycletime_ps);
3689
3690 delay_e_over_cycle_ps = delay_e_ps % (2 * halfcycle_ps(info));
3691 delay_e_cycles = delay_e_ps / (2 * halfcycle_ps(info));
3692 delay_f_cycles =
3693 div_roundup(2500 - delay_e_over_cycle_ps,
3694 2 * halfcycle_ps(info));
3695 if (delay_f_cycles > delay_e_cycles) {
3696 info->delay46_ps[channel] = delay_e_ps;
3697 delay_e_cycles = 0;
3698 } else {
3699 info->delay46_ps[channel] =
3700 delay_e_over_cycle_ps +
3701 2 * halfcycle_ps(info) * delay_f_cycles;
3702 delay_e_cycles -= delay_f_cycles;
3703 }
3704
3705 if (info->delay46_ps[channel] < 2500) {
3706 info->delay46_ps[channel] = 2500;
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003707 info->training.reg2ca9_bit0 = 1;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003708 }
3709 delay_b_ps = halfcycle_ps(info) + delay_c_ps;
3710 if (delay_b_ps <= delay_a_ps)
3711 delay_b_ps = 0;
3712 else
3713 delay_b_ps -= delay_a_ps;
3714 info->delay54_ps[channel] =
3715 cycletime_ps * div_roundup(delay_b_ps,
3716 cycletime_ps) -
3717 2 * halfcycle_ps(info) * delay_e_cycles;
3718 if (info->delay54_ps[channel] < 2500)
3719 info->delay54_ps[channel] = 2500;
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003720 info->training.reg274265[channel][0] = delay_e_cycles;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003721 if (delay_d_ps + 7 * halfcycle_ps(info) <=
3722 24 * halfcycle_ps(info))
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003723 info->training.reg274265[channel][1] = 0;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003724 else
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003725 info->training.reg274265[channel][1] =
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003726 div_roundup(delay_d_ps + 7 * halfcycle_ps(info),
3727 4 * halfcycle_ps(info)) - 6;
3728 write_mchbar32((channel << 10) + 0x274,
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003729 info->training.reg274265[channel][1]
3730 | (info->training.reg274265[channel][0] << 16));
3731 info->training.reg274265[channel][2] =
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003732 div_roundup(delay_c_ps + 3 * fsbcycle_ps(info),
3733 4 * halfcycle_ps(info)) + 1;
3734 write_mchbar16((channel << 10) + 0x265,
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003735 info->training.reg274265[channel][2] << 8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003736 }
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003737 if (info->training.reg2ca9_bit0)
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003738 write_mchbar8(0x2ca9, read_mchbar8(0x2ca9) | 1);
3739 else
3740 write_mchbar8(0x2ca9, read_mchbar8(0x2ca9) & ~1);
3741}
3742
3743static void restore_274265(struct raminfo *info)
3744{
3745 int channel;
3746
3747 for (channel = 0; channel < NUM_CHANNELS; channel++) {
3748 write_mchbar32((channel << 10) + 0x274,
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003749 (info->cached_training->reg274265[channel][0] << 16)
3750 | info->cached_training->reg274265[channel][1]);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003751 write_mchbar16((channel << 10) + 0x265,
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003752 info->cached_training->reg274265[channel][2] << 8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003753 }
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01003754 if (info->cached_training->reg2ca9_bit0)
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003755 write_mchbar8(0x2ca9, read_mchbar8(0x2ca9) | 1);
3756 else
3757 write_mchbar8(0x2ca9, read_mchbar8(0x2ca9) & ~1);
3758}
3759
3760#if REAL
3761static void dmi_setup(void)
3762{
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08003763 gav(read8(DEFAULT_DMIBAR + 0x254));
3764 write8(DEFAULT_DMIBAR + 0x254, 0x1);
3765 write16(DEFAULT_DMIBAR + 0x1b8, 0x18f2);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003766 read_mchbar16(0x48);
3767 write_mchbar16(0x48, 0x2);
3768
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08003769 write32(DEFAULT_DMIBAR + 0xd68, read32(DEFAULT_DMIBAR + 0xd68) | 0x08000000);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003770
3771 outl((gav(inl(DEFAULT_GPIOBASE | 0x38)) & ~0x140000) | 0x400000,
3772 DEFAULT_GPIOBASE | 0x38);
3773 gav(inb(DEFAULT_GPIOBASE | 0xe)); // = 0xfdcaff6e
3774}
3775#endif
3776
Vladimir Serbinenko9817a372014-02-19 22:07:12 +01003777void chipset_init(const int s3resume)
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003778{
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003779 u8 x2ca8;
Vladimir Serbinenko55391c42014-08-03 14:51:00 +02003780 u16 ggc;
3781 u8 gfxsize;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003782
Vladimir Serbinenko9817a372014-02-19 22:07:12 +01003783 x2ca8 = read_mchbar8(0x2ca8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003784 if ((x2ca8 & 1) || (x2ca8 == 8 && !s3resume)) {
3785 printk(BIOS_DEBUG, "soft reset detected, rebooting properly\n");
3786 write_mchbar8(0x2ca8, 0);
Vladimir Serbinenkoe1eef692014-02-19 22:08:51 +01003787 outb(0x6, 0xcf9);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003788#if REAL
Patrick Georgi546953c2014-11-29 10:38:17 +01003789 halt();
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003790#else
3791 printf("CP5\n");
3792 exit(0);
3793#endif
3794 }
3795#if !REAL
3796 if (!s3resume) {
3797 pre_raminit_3(x2ca8);
3798 }
Vladimir Serbinenkof62669c2014-01-09 10:59:38 +01003799 pre_raminit_4a(x2ca8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003800#endif
3801
3802 dmi_setup();
3803
3804 write_mchbar16(0x1170, 0xa880);
3805 write_mchbar8(0x11c1, 0x1);
3806 write_mchbar16(0x1170, 0xb880);
3807 read_mchbar8(0x1210);
3808 write_mchbar8(0x1210, 0x84);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003809
Vladimir Serbinenko55391c42014-08-03 14:51:00 +02003810 if (get_option(&gfxsize, "gfx_uma_size") != CB_SUCCESS) {
3811 /* 0 for 32MB */
3812 gfxsize = 0;
3813 }
3814
3815 ggc = 0xb00 | ((gfxsize + 5) << 4);
3816
3817 pcie_write_config16(NORTHBRIDGE, D0F0_GGC, ggc | 2);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003818
3819 u16 deven;
3820 deven = pcie_read_config16(NORTHBRIDGE, D0F0_DEVEN); // = 0x3
3821
3822 if (deven & 8) {
3823 write_mchbar8(0x2c30, 0x20);
3824 pcie_read_config8(NORTHBRIDGE, 0x8); // = 0x18
3825 write_mchbar16(0x2c30, read_mchbar16(0x2c30) | 0x200);
3826 write_mchbar16(0x2c32, 0x434);
3827 read_mchbar32(0x2c44);
3828 write_mchbar32(0x2c44, 0x1053687);
3829 pcie_read_config8(GMA, 0x62); // = 0x2
3830 pcie_write_config8(GMA, 0x62, 0x2);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08003831 read8(DEFAULT_RCBA + 0x2318);
3832 write8(DEFAULT_RCBA + 0x2318, 0x47);
3833 read8(DEFAULT_RCBA + 0x2320);
3834 write8(DEFAULT_RCBA + 0x2320, 0xfc);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003835 }
3836
3837 read_mchbar32(0x30);
3838 write_mchbar32(0x30, 0x40);
3839
Vladimir Serbinenko55391c42014-08-03 14:51:00 +02003840 pcie_write_config16(NORTHBRIDGE, D0F0_GGC, ggc);
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08003841 gav(read32(DEFAULT_RCBA + 0x3428));
3842 write32(DEFAULT_RCBA + 0x3428, 0x1d);
Vladimir Serbinenko9817a372014-02-19 22:07:12 +01003843}
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003844
Vladimir Serbinenko9817a372014-02-19 22:07:12 +01003845void raminit(const int s3resume, const u8 *spd_addrmap)
3846{
3847 unsigned channel, slot, lane, rank;
3848 int i;
3849 struct raminfo info;
3850 u8 x2ca8;
3851 u16 deven;
Vladimir Serbinenkob16f0922014-06-07 16:27:27 +02003852 int cbmem_wasnot_inited;
Vladimir Serbinenko9817a372014-02-19 22:07:12 +01003853
3854 x2ca8 = read_mchbar8(0x2ca8);
3855 deven = pcie_read_config16(NORTHBRIDGE, D0F0_DEVEN);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003856
3857 memset(&info, 0x5a, sizeof(info));
3858
3859 info.last_500_command[0] = 0;
3860 info.last_500_command[1] = 0;
3861
3862 info.fsb_frequency = 135 * 2;
3863 info.board_lane_delay[0] = 0x14;
3864 info.board_lane_delay[1] = 0x07;
3865 info.board_lane_delay[2] = 0x07;
3866 info.board_lane_delay[3] = 0x08;
3867 info.board_lane_delay[4] = 0x56;
3868 info.board_lane_delay[5] = 0x04;
3869 info.board_lane_delay[6] = 0x04;
3870 info.board_lane_delay[7] = 0x05;
3871 info.board_lane_delay[8] = 0x10;
3872
3873 info.training.reg_178 = 0;
3874 info.training.reg_10b = 0;
3875
3876 info.heci_bar = 0;
3877 info.memory_reserved_for_heci_mb = 0;
3878
3879 /* before SPD */
3880 timestamp_add_now(101);
3881
3882 if (!s3resume || REAL) {
3883 pcie_read_config8(SOUTHBRIDGE, GEN_PMCON_2); // = 0x80
3884
3885 collect_system_info(&info);
3886
3887#if REAL
3888 /* Enable SMBUS. */
3889 enable_smbus();
3890#endif
3891
3892 memset(&info.populated_ranks, 0, sizeof(info.populated_ranks));
3893
3894 info.use_ecc = 1;
3895 for (channel = 0; channel < NUM_CHANNELS; channel++)
Vladimir Serbinenko2ab8ec72014-02-20 14:34:56 +01003896 for (slot = 0; slot < NUM_SLOTS; slot++) {
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003897 int v;
3898 int try;
3899 int addr;
3900 const u8 useful_addresses[] = {
3901 DEVICE_TYPE,
3902 MODULE_TYPE,
3903 DENSITY,
3904 RANKS_AND_DQ,
3905 MEMORY_BUS_WIDTH,
3906 TIMEBASE_DIVIDEND,
3907 TIMEBASE_DIVISOR,
3908 CYCLETIME,
3909 CAS_LATENCIES_LSB,
3910 CAS_LATENCIES_MSB,
3911 CAS_LATENCY_TIME,
3912 0x11, 0x12, 0x13, 0x14, 0x15,
3913 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
3914 0x1c, 0x1d,
3915 THERMAL_AND_REFRESH,
3916 0x20,
3917 REFERENCE_RAW_CARD_USED,
3918 RANK1_ADDRESS_MAPPING,
3919 0x75, 0x76, 0x77, 0x78,
3920 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e,
3921 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84,
3922 0x85, 0x86, 0x87, 0x88,
3923 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
3924 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94,
3925 0x95
3926 };
Vladimir Serbinenko902626c2014-02-16 17:22:26 +01003927 if (!spd_addrmap[2 * channel + slot])
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003928 continue;
3929 for (try = 0; try < 5; try++) {
Vladimir Serbinenko902626c2014-02-16 17:22:26 +01003930 v = smbus_read_byte(spd_addrmap[2 * channel + slot],
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003931 DEVICE_TYPE);
3932 if (v >= 0)
3933 break;
3934 }
3935 if (v < 0)
3936 continue;
3937 for (addr = 0;
3938 addr <
3939 sizeof(useful_addresses) /
3940 sizeof(useful_addresses[0]); addr++)
3941 gav(info.
3942 spd[channel][0][useful_addresses
3943 [addr]] =
Vladimir Serbinenko902626c2014-02-16 17:22:26 +01003944 smbus_read_byte(spd_addrmap[2 * channel + slot],
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003945 useful_addresses
3946 [addr]));
3947 if (info.spd[channel][0][DEVICE_TYPE] != 11)
3948 die("Only DDR3 is supported");
3949
3950 v = info.spd[channel][0][RANKS_AND_DQ];
3951 info.populated_ranks[channel][0][0] = 1;
3952 info.populated_ranks[channel][0][1] =
3953 ((v >> 3) & 7);
3954 if (((v >> 3) & 7) > 1)
3955 die("At most 2 ranks are supported");
3956 if ((v & 7) == 0 || (v & 7) > 2)
3957 die("Only x8 and x16 modules are supported");
3958 if ((info.
3959 spd[channel][slot][MODULE_TYPE] & 0xF) != 2
3960 && (info.
3961 spd[channel][slot][MODULE_TYPE] & 0xF)
3962 != 3)
3963 die("Registered memory is not supported");
3964 info.is_x16_module[channel][0] = (v & 7) - 1;
3965 info.density[channel][slot] =
3966 info.spd[channel][slot][DENSITY] & 0xF;
3967 if (!
3968 (info.
3969 spd[channel][slot][MEMORY_BUS_WIDTH] &
3970 0x18))
3971 info.use_ecc = 0;
3972 }
3973
3974 gav(0x55);
3975
3976 for (channel = 0; channel < NUM_CHANNELS; channel++) {
3977 int v = 0;
3978 for (slot = 0; slot < NUM_SLOTS; slot++)
3979 for (rank = 0; rank < NUM_RANKS; rank++)
3980 v |= info.
3981 populated_ranks[channel][slot][rank]
3982 << (2 * slot + rank);
3983 info.populated_ranks_mask[channel] = v;
3984 }
3985
3986 gav(0x55);
3987
3988 gav(pcie_read_config32(NORTHBRIDGE, D0F0_CAPID0 + 4));
3989 }
3990
3991 /* after SPD */
3992 timestamp_add_now(102);
3993
3994 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) & 0xfc);
3995#if !REAL
Alexandru Gagniuc86091f92015-09-30 20:23:09 -07003996 rdmsr (MTRR_PHYS_MASK (3));
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01003997#endif
3998
3999 collect_system_info(&info);
4000 calculate_timings(&info);
4001
4002#if !REAL
4003 pcie_write_config8(NORTHBRIDGE, 0xdf, 0x82);
4004#endif
4005
4006 if (!s3resume) {
4007 u8 reg8 = pcie_read_config8(SOUTHBRIDGE, GEN_PMCON_2);
4008 if (x2ca8 == 0 && (reg8 & 0x80)) {
4009 /* Don't enable S4-assertion stretch. Makes trouble on roda/rk9.
4010 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
4011 pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8 | 0x08);
4012 */
4013
4014 /* Clear bit7. */
4015
4016 pci_write_config8(SOUTHBRIDGE, GEN_PMCON_2,
4017 (reg8 & ~(1 << 7)));
4018
4019 printk(BIOS_INFO,
4020 "Interrupted RAM init, reset required.\n");
4021 outb(0x6, 0xcf9);
4022#if REAL
Patrick Georgi546953c2014-11-29 10:38:17 +01004023 halt();
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004024#endif
4025 }
4026 }
4027#if !REAL
4028 gav(read_mchbar8(0x2ca8)); ///!!!!
4029#endif
4030
4031 if (!s3resume && x2ca8 == 0)
4032 pcie_write_config8(SOUTHBRIDGE, GEN_PMCON_2,
4033 pcie_read_config8(SOUTHBRIDGE, GEN_PMCON_2) | 0x80);
4034
4035 compute_derived_timings(&info);
4036
4037 if (x2ca8 == 0) {
4038 gav(read_mchbar8(0x164));
4039 write_mchbar8(0x164, 0x26);
4040 write_mchbar16(0x2c20, 0x10);
4041 }
4042
4043 write_mchbar32(0x18b4, read_mchbar32(0x18b4) | 0x210000); /* OK */
4044 write_mchbar32(0x1890, read_mchbar32(0x1890) | 0x2000000); /* OK */
4045 write_mchbar32(0x18b4, read_mchbar32(0x18b4) | 0x8000);
4046
4047 gav(pcie_read_config32(PCI_DEV(0xff, 2, 1), 0x50)); // !!!!
4048 pcie_write_config8(PCI_DEV(0xff, 2, 1), 0x54, 0x12);
4049
4050 gav(read_mchbar16(0x2c10)); // !!!!
4051 write_mchbar16(0x2c10, 0x412);
4052 gav(read_mchbar16(0x2c10)); // !!!!
4053 write_mchbar16(0x2c12, read_mchbar16(0x2c12) | 0x100); /* OK */
4054
4055 gav(read_mchbar8(0x2ca8)); // !!!!
4056 write_mchbar32(0x1804,
4057 (read_mchbar32(0x1804) & 0xfffffffc) | 0x8400080);
4058
4059 pcie_read_config32(PCI_DEV(0xff, 2, 1), 0x6c); // !!!!
4060 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0x6c, 0x40a0a0);
4061 gav(read_mchbar32(0x1c04)); // !!!!
4062 gav(read_mchbar32(0x1804)); // !!!!
4063
4064 if (x2ca8 == 0) {
4065 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) | 1);
4066 }
4067
4068 write_mchbar32(0x18d8, 0x120000);
4069 write_mchbar32(0x18dc, 0x30a484a);
4070 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xe0, 0x0);
4071 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xf4, 0x9444a);
4072 write_mchbar32(0x18d8, 0x40000);
4073 write_mchbar32(0x18dc, 0xb000000);
4074 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xe0, 0x60000);
4075 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xf4, 0x0);
4076 write_mchbar32(0x18d8, 0x180000);
4077 write_mchbar32(0x18dc, 0xc0000142);
4078 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xe0, 0x20000);
4079 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xf4, 0x142);
4080 write_mchbar32(0x18d8, 0x1e0000);
4081
4082 gav(read_mchbar32(0x18dc)); // !!!!
4083 write_mchbar32(0x18dc, 0x3);
4084 gav(read_mchbar32(0x18dc)); // !!!!
4085
4086 if (x2ca8 == 0) {
4087 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) | 1); // guess
4088 }
4089
4090 write_mchbar32(0x188c, 0x20bc09);
4091 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0xd0, 0x40b0c09);
4092 write_mchbar32(0x1a10, 0x4200010e);
4093 write_mchbar32(0x18b8, read_mchbar32(0x18b8) | 0x200);
4094 gav(read_mchbar32(0x1918)); // !!!!
4095 write_mchbar32(0x1918, 0x332);
4096
4097 gav(read_mchbar32(0x18b8)); // !!!!
4098 write_mchbar32(0x18b8, 0xe00);
4099 gav(read_mchbar32(0x182c)); // !!!!
4100 write_mchbar32(0x182c, 0x10202);
4101 gav(pcie_read_config32(PCI_DEV(0xff, 2, 1), 0x94)); // !!!!
4102 pcie_write_config32(PCI_DEV(0xff, 2, 1), 0x94, 0x10202);
4103 write_mchbar32(0x1a1c, read_mchbar32(0x1a1c) & 0x8fffffff);
4104 write_mchbar32(0x1a70, read_mchbar32(0x1a70) | 0x100000);
4105
4106 write_mchbar32(0x18b4, read_mchbar32(0x18b4) & 0xffff7fff);
4107 gav(read_mchbar32(0x1a68)); // !!!!
4108 write_mchbar32(0x1a68, 0x343800);
4109 gav(read_mchbar32(0x1e68)); // !!!!
4110 gav(read_mchbar32(0x1a68)); // !!!!
4111
4112 if (x2ca8 == 0) {
4113 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) | 1); // guess
4114 }
4115
4116 pcie_read_config32(PCI_DEV(0xff, 2, 0), 0x048); // !!!!
4117 pcie_write_config32(PCI_DEV(0xff, 2, 0), 0x048, 0x140000);
4118 pcie_read_config32(PCI_DEV(0xff, 2, 0), 0x058); // !!!!
4119 pcie_write_config32(PCI_DEV(0xff, 2, 0), 0x058, 0x64555);
4120 pcie_read_config32(PCI_DEV(0xff, 2, 0), 0x058); // !!!!
4121 pcie_read_config32(PCI_DEV (0xff, 0, 0), 0xd0); // !!!!
4122 pcie_write_config32(PCI_DEV (0xff, 0, 0), 0xd0, 0x180);
4123 gav(read_mchbar32(0x1af0)); // !!!!
4124 gav(read_mchbar32(0x1af0)); // !!!!
4125 write_mchbar32(0x1af0, 0x1f020003);
4126 gav(read_mchbar32(0x1af0)); // !!!!
4127
Edward O'Callaghan42b716f2014-06-26 21:38:52 +10004128 if (x2ca8 == 0) {
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004129 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) | 1); // guess
4130 }
4131
4132 gav(read_mchbar32(0x1890)); // !!!!
4133 write_mchbar32(0x1890, 0x80102);
4134 gav(read_mchbar32(0x18b4)); // !!!!
4135 write_mchbar32(0x18b4, 0x216000);
4136 write_mchbar32(0x18a4, 0x22222222);
4137 write_mchbar32(0x18a8, 0x22222222);
4138 write_mchbar32(0x18ac, 0x22222);
4139
4140 udelay(1000);
4141
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01004142 info.cached_training = get_cached_training();
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004143
Vladimir Serbinenkof7a42de2014-01-09 11:10:04 +01004144 if (x2ca8 == 0) {
4145 int j;
4146 if (s3resume && info.cached_training) {
4147 restore_274265(&info);
4148 printk(BIOS_DEBUG, "reg2ca9_bit0 = %x\n",
4149 info.cached_training->reg2ca9_bit0);
4150 for (i = 0; i < 2; i++)
4151 for (j = 0; j < 3; j++)
4152 printk(BIOS_DEBUG, "reg274265[%d][%d] = %x\n",
4153 i, j, info.cached_training->reg274265[i][j]);
4154 } else {
4155 set_274265(&info);
4156 printk(BIOS_DEBUG, "reg2ca9_bit0 = %x\n",
4157 info.training.reg2ca9_bit0);
4158 for (i = 0; i < 2; i++)
4159 for (j = 0; j < 3; j++)
4160 printk(BIOS_DEBUG, "reg274265[%d][%d] = %x\n",
4161 i, j, info.training.reg274265[i][j]);
4162 }
4163
4164 set_2dxx_series(&info, s3resume);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004165
4166 if (!(deven & 8)) {
4167 read_mchbar32(0x2cb0);
4168 write_mchbar32(0x2cb0, 0x40);
4169 }
4170
4171 udelay(1000);
4172
4173 if (deven & 8) {
4174 write_mchbar32(0xff8, 0x1800 | read_mchbar32(0xff8));
4175 read_mchbar32(0x2cb0);
4176 write_mchbar32(0x2cb0, 0x00);
4177 pcie_read_config8(PCI_DEV (0, 0x2, 0x0), 0x4c);
4178 pcie_read_config8(PCI_DEV (0, 0x2, 0x0), 0x4c);
4179 pcie_read_config8(PCI_DEV (0, 0x2, 0x0), 0x4e);
4180
4181 read_mchbar8(0x1150);
4182 read_mchbar8(0x1151);
4183 read_mchbar8(0x1022);
4184 read_mchbar8(0x16d0);
4185 write_mchbar32(0x1300, 0x60606060);
4186 write_mchbar32(0x1304, 0x60606060);
4187 write_mchbar32(0x1308, 0x78797a7b);
4188 write_mchbar32(0x130c, 0x7c7d7e7f);
4189 write_mchbar32(0x1310, 0x60606060);
4190 write_mchbar32(0x1314, 0x60606060);
4191 write_mchbar32(0x1318, 0x60606060);
4192 write_mchbar32(0x131c, 0x60606060);
4193 write_mchbar32(0x1320, 0x50515253);
4194 write_mchbar32(0x1324, 0x54555657);
4195 write_mchbar32(0x1328, 0x58595a5b);
4196 write_mchbar32(0x132c, 0x5c5d5e5f);
4197 write_mchbar32(0x1330, 0x40414243);
4198 write_mchbar32(0x1334, 0x44454647);
4199 write_mchbar32(0x1338, 0x48494a4b);
4200 write_mchbar32(0x133c, 0x4c4d4e4f);
4201 write_mchbar32(0x1340, 0x30313233);
4202 write_mchbar32(0x1344, 0x34353637);
4203 write_mchbar32(0x1348, 0x38393a3b);
4204 write_mchbar32(0x134c, 0x3c3d3e3f);
4205 write_mchbar32(0x1350, 0x20212223);
4206 write_mchbar32(0x1354, 0x24252627);
4207 write_mchbar32(0x1358, 0x28292a2b);
4208 write_mchbar32(0x135c, 0x2c2d2e2f);
4209 write_mchbar32(0x1360, 0x10111213);
4210 write_mchbar32(0x1364, 0x14151617);
4211 write_mchbar32(0x1368, 0x18191a1b);
4212 write_mchbar32(0x136c, 0x1c1d1e1f);
4213 write_mchbar32(0x1370, 0x10203);
4214 write_mchbar32(0x1374, 0x4050607);
4215 write_mchbar32(0x1378, 0x8090a0b);
4216 write_mchbar32(0x137c, 0xc0d0e0f);
4217 write_mchbar8(0x11cc, 0x4e);
4218 write_mchbar32(0x1110, 0x73970404);
4219 write_mchbar32(0x1114, 0x72960404);
4220 write_mchbar32(0x1118, 0x6f950404);
4221 write_mchbar32(0x111c, 0x6d940404);
4222 write_mchbar32(0x1120, 0x6a930404);
4223 write_mchbar32(0x1124, 0x68a41404);
4224 write_mchbar32(0x1128, 0x66a21404);
4225 write_mchbar32(0x112c, 0x63a01404);
4226 write_mchbar32(0x1130, 0x609e1404);
4227 write_mchbar32(0x1134, 0x5f9c1404);
4228 write_mchbar32(0x1138, 0x5c961404);
4229 write_mchbar32(0x113c, 0x58a02404);
4230 write_mchbar32(0x1140, 0x54942404);
4231 write_mchbar32(0x1190, 0x900080a);
4232 write_mchbar16(0x11c0, 0xc40b);
4233 write_mchbar16(0x11c2, 0x303);
4234 write_mchbar16(0x11c4, 0x301);
4235 read_mchbar32(0x1190);
4236 write_mchbar32(0x1190, 0x8900080a);
4237 write_mchbar32(0x11b8, 0x70c3000);
4238 write_mchbar8(0x11ec, 0xa);
4239 write_mchbar16(0x1100, 0x800);
4240 read_mchbar32(0x11bc);
4241 write_mchbar32(0x11bc, 0x1e84800);
4242 write_mchbar16(0x11ca, 0xfa);
4243 write_mchbar32(0x11e4, 0x4e20);
4244 write_mchbar8(0x11bc, 0xf);
4245 write_mchbar16(0x11da, 0x19);
4246 write_mchbar16(0x11ba, 0x470c);
4247 write_mchbar32(0x1680, 0xe6ffe4ff);
4248 write_mchbar32(0x1684, 0xdeffdaff);
4249 write_mchbar32(0x1688, 0xd4ffd0ff);
4250 write_mchbar32(0x168c, 0xccffc6ff);
4251 write_mchbar32(0x1690, 0xc0ffbeff);
4252 write_mchbar32(0x1694, 0xb8ffb0ff);
4253 write_mchbar32(0x1698, 0xa8ff0000);
4254 write_mchbar32(0x169c, 0xc00);
4255 write_mchbar32(0x1290, 0x5000000);
4256 }
4257
4258 write_mchbar32(0x124c, 0x15040d00);
4259 write_mchbar32(0x1250, 0x7f0000);
4260 write_mchbar32(0x1254, 0x1e220004);
4261 write_mchbar32(0x1258, 0x4000004);
4262 write_mchbar32(0x1278, 0x0);
4263 write_mchbar32(0x125c, 0x0);
4264 write_mchbar32(0x1260, 0x0);
4265 write_mchbar32(0x1264, 0x0);
4266 write_mchbar32(0x1268, 0x0);
4267 write_mchbar32(0x126c, 0x0);
4268 write_mchbar32(0x1270, 0x0);
4269 write_mchbar32(0x1274, 0x0);
4270 }
4271
4272 if ((deven & 8) && x2ca8 == 0) {
4273 write_mchbar16(0x1214, 0x320);
4274 write_mchbar32(0x1600, 0x40000000);
4275 read_mchbar32(0x11f4);
4276 write_mchbar32(0x11f4, 0x10000000);
4277 read_mchbar16(0x1230);
4278 write_mchbar16(0x1230, 0x8000);
4279 write_mchbar32(0x1400, 0x13040020);
4280 write_mchbar32(0x1404, 0xe090120);
4281 write_mchbar32(0x1408, 0x5120220);
4282 write_mchbar32(0x140c, 0x5120330);
4283 write_mchbar32(0x1410, 0xe090220);
4284 write_mchbar32(0x1414, 0x1010001);
4285 write_mchbar32(0x1418, 0x1110000);
4286 write_mchbar32(0x141c, 0x9020020);
4287 write_mchbar32(0x1420, 0xd090220);
4288 write_mchbar32(0x1424, 0x2090220);
4289 write_mchbar32(0x1428, 0x2090330);
4290 write_mchbar32(0x142c, 0xd090220);
4291 write_mchbar32(0x1430, 0x1010001);
4292 write_mchbar32(0x1434, 0x1110000);
4293 write_mchbar32(0x1438, 0x11040020);
4294 write_mchbar32(0x143c, 0x4030220);
4295 write_mchbar32(0x1440, 0x1060220);
4296 write_mchbar32(0x1444, 0x1060330);
4297 write_mchbar32(0x1448, 0x4030220);
4298 write_mchbar32(0x144c, 0x1010001);
4299 write_mchbar32(0x1450, 0x1110000);
4300 write_mchbar32(0x1454, 0x4010020);
4301 write_mchbar32(0x1458, 0xb090220);
4302 write_mchbar32(0x145c, 0x1090220);
4303 write_mchbar32(0x1460, 0x1090330);
4304 write_mchbar32(0x1464, 0xb090220);
4305 write_mchbar32(0x1468, 0x1010001);
4306 write_mchbar32(0x146c, 0x1110000);
4307 write_mchbar32(0x1470, 0xf040020);
4308 write_mchbar32(0x1474, 0xa090220);
4309 write_mchbar32(0x1478, 0x1120220);
4310 write_mchbar32(0x147c, 0x1120330);
4311 write_mchbar32(0x1480, 0xa090220);
4312 write_mchbar32(0x1484, 0x1010001);
4313 write_mchbar32(0x1488, 0x1110000);
4314 write_mchbar32(0x148c, 0x7020020);
4315 write_mchbar32(0x1490, 0x1010220);
4316 write_mchbar32(0x1494, 0x10210);
4317 write_mchbar32(0x1498, 0x10320);
4318 write_mchbar32(0x149c, 0x1010220);
4319 write_mchbar32(0x14a0, 0x1010001);
4320 write_mchbar32(0x14a4, 0x1110000);
4321 write_mchbar32(0x14a8, 0xd040020);
4322 write_mchbar32(0x14ac, 0x8090220);
4323 write_mchbar32(0x14b0, 0x1111310);
4324 write_mchbar32(0x14b4, 0x1111420);
4325 write_mchbar32(0x14b8, 0x8090220);
4326 write_mchbar32(0x14bc, 0x1010001);
4327 write_mchbar32(0x14c0, 0x1110000);
4328 write_mchbar32(0x14c4, 0x3010020);
4329 write_mchbar32(0x14c8, 0x7090220);
4330 write_mchbar32(0x14cc, 0x1081310);
4331 write_mchbar32(0x14d0, 0x1081420);
4332 write_mchbar32(0x14d4, 0x7090220);
4333 write_mchbar32(0x14d8, 0x1010001);
4334 write_mchbar32(0x14dc, 0x1110000);
4335 write_mchbar32(0x14e0, 0xb040020);
4336 write_mchbar32(0x14e4, 0x2030220);
4337 write_mchbar32(0x14e8, 0x1051310);
4338 write_mchbar32(0x14ec, 0x1051420);
4339 write_mchbar32(0x14f0, 0x2030220);
4340 write_mchbar32(0x14f4, 0x1010001);
4341 write_mchbar32(0x14f8, 0x1110000);
4342 write_mchbar32(0x14fc, 0x5020020);
4343 write_mchbar32(0x1500, 0x5090220);
4344 write_mchbar32(0x1504, 0x2071310);
4345 write_mchbar32(0x1508, 0x2071420);
4346 write_mchbar32(0x150c, 0x5090220);
4347 write_mchbar32(0x1510, 0x1010001);
4348 write_mchbar32(0x1514, 0x1110000);
4349 write_mchbar32(0x1518, 0x7040120);
4350 write_mchbar32(0x151c, 0x2090220);
4351 write_mchbar32(0x1520, 0x70b1210);
4352 write_mchbar32(0x1524, 0x70b1310);
4353 write_mchbar32(0x1528, 0x2090220);
4354 write_mchbar32(0x152c, 0x1010001);
4355 write_mchbar32(0x1530, 0x1110000);
4356 write_mchbar32(0x1534, 0x1010110);
4357 write_mchbar32(0x1538, 0x1081310);
4358 write_mchbar32(0x153c, 0x5041200);
4359 write_mchbar32(0x1540, 0x5041310);
4360 write_mchbar32(0x1544, 0x1081310);
4361 write_mchbar32(0x1548, 0x1010001);
4362 write_mchbar32(0x154c, 0x1110000);
4363 write_mchbar32(0x1550, 0x1040120);
4364 write_mchbar32(0x1554, 0x4051210);
4365 write_mchbar32(0x1558, 0xd051200);
4366 write_mchbar32(0x155c, 0xd051200);
4367 write_mchbar32(0x1560, 0x4051210);
4368 write_mchbar32(0x1564, 0x1010001);
4369 write_mchbar32(0x1568, 0x1110000);
4370 write_mchbar16(0x1222, 0x220a);
4371 write_mchbar16(0x123c, 0x1fc0);
4372 write_mchbar16(0x1220, 0x1388);
4373 }
4374
4375 read_mchbar32(0x2c80); // !!!!
4376 write_mchbar32(0x2c80, 0x1053688);
4377 read_mchbar32(0x1c04); // !!!!
4378 write_mchbar32(0x1804, 0x406080);
4379
4380 read_mchbar8(0x2ca8);
4381
4382 if (x2ca8 == 0) {
4383 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) & ~3);
4384 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8) + 4);
4385 write_mchbar32(0x1af0, read_mchbar32(0x1af0) | 0x10);
4386#if REAL
Patrick Georgi546953c2014-11-29 10:38:17 +01004387 halt();
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004388#else
4389 printf("CP5\n");
4390 exit(0);
4391#endif
4392 }
4393
4394 write_mchbar8(0x2ca8, read_mchbar8(0x2ca8));
4395 read_mchbar32(0x2c80); // !!!!
4396 write_mchbar32(0x2c80, 0x53688);
4397 pcie_write_config32(PCI_DEV (0xff, 0, 0), 0x60, 0x20220);
4398 read_mchbar16(0x2c20); // !!!!
4399 read_mchbar16(0x2c10); // !!!!
4400 read_mchbar16(0x2c00); // !!!!
4401 write_mchbar16(0x2c00, 0x8c0);
4402 udelay(1000);
4403 write_1d0(0, 0x33d, 0, 0);
4404 write_500(&info, 0, 0, 0xb61, 0, 0);
4405 write_500(&info, 1, 0, 0xb61, 0, 0);
4406 write_mchbar32(0x1a30, 0x0);
4407 write_mchbar32(0x1a34, 0x0);
4408 write_mchbar16(0x614,
4409 0xb5b | (info.populated_ranks[1][0][0] *
4410 0x404) | (info.populated_ranks[0][0][0] *
4411 0xa0));
4412 write_mchbar16(0x616, 0x26a);
4413 write_mchbar32(0x134, 0x856000);
4414 write_mchbar32(0x160, 0x5ffffff);
4415 read_mchbar32(0x114); // !!!!
4416 write_mchbar32(0x114, 0xc2024440);
4417 read_mchbar32(0x118); // !!!!
4418 write_mchbar32(0x118, 0x4);
4419 for (channel = 0; channel < NUM_CHANNELS; channel++)
4420 write_mchbar32(0x260 + (channel << 10),
4421 0x30809ff |
4422 ((info.
4423 populated_ranks_mask[channel] & 3) << 20));
4424 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4425 write_mchbar16(0x31c + (channel << 10), 0x101);
4426 write_mchbar16(0x360 + (channel << 10), 0x909);
4427 write_mchbar16(0x3a4 + (channel << 10), 0x101);
4428 write_mchbar16(0x3e8 + (channel << 10), 0x101);
4429 write_mchbar32(0x320 + (channel << 10), 0x29002900);
4430 write_mchbar32(0x324 + (channel << 10), 0x0);
4431 write_mchbar32(0x368 + (channel << 10), 0x32003200);
4432 write_mchbar16(0x352 + (channel << 10), 0x505);
4433 write_mchbar16(0x354 + (channel << 10), 0x3c3c);
4434 write_mchbar16(0x356 + (channel << 10), 0x1040);
4435 write_mchbar16(0x39a + (channel << 10), 0x73e4);
4436 write_mchbar16(0x3de + (channel << 10), 0x77ed);
4437 write_mchbar16(0x422 + (channel << 10), 0x1040);
4438 }
4439
4440 write_1d0(0x4, 0x151, 4, 1);
4441 write_1d0(0, 0x142, 3, 1);
4442 rdmsr(0x1ac); // !!!!
4443 write_500(&info, 1, 1, 0x6b3, 4, 1);
4444 write_500(&info, 1, 1, 0x6cf, 4, 1);
4445
4446 rmw_1d0(0x21c, 0x38, 0, 6, 1);
4447
4448 write_1d0(((!info.populated_ranks[1][0][0]) << 1) | ((!info.
4449 populated_ranks[0]
4450 [0][0]) << 0),
4451 0x1d1, 3, 1);
4452 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4453 write_mchbar16(0x38e + (channel << 10), 0x5f5f);
4454 write_mchbar16(0x3d2 + (channel << 10), 0x5f5f);
4455 }
4456
4457 set_334(0);
4458
4459 program_base_timings(&info);
4460
4461 write_mchbar8(0x5ff, read_mchbar8(0x5ff) | 0x80); /* OK */
4462
4463 write_1d0(0x2, 0x1d5, 2, 1);
4464 write_1d0(0x20, 0x166, 7, 1);
4465 write_1d0(0x0, 0xeb, 3, 1);
4466 write_1d0(0x0, 0xf3, 6, 1);
4467
4468 for (channel = 0; channel < NUM_CHANNELS; channel++)
4469 for (lane = 0; lane < 9; lane++) {
4470 u16 addr = 0x125 + get_lane_offset(0, 0, lane);
4471 u8 a;
4472 a = read_500(&info, channel, addr, 6); // = 0x20040080 //!!!!
4473 write_500(&info, channel, a, addr, 6, 1);
4474 }
4475
4476 udelay(1000);
4477
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004478 if (s3resume) {
4479 if (info.cached_training == NULL) {
4480 u32 reg32;
4481 printk(BIOS_ERR,
4482 "Couldn't find training data. Rebooting\n");
4483 reg32 = inl(DEFAULT_PMBASE + 0x04);
4484 outl(reg32 & ~(7 << 10), DEFAULT_PMBASE + 0x04);
4485 outb(0xe, 0xcf9);
4486
4487#if REAL
Patrick Georgi546953c2014-11-29 10:38:17 +01004488 halt();
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004489#else
4490 printf("CP5\n");
4491 exit(0);
4492#endif
4493 }
4494 int tm;
4495 info.training = *info.cached_training;
4496 for (tm = 0; tm < 4; tm++)
4497 for (channel = 0; channel < NUM_CHANNELS; channel++)
4498 for (slot = 0; slot < NUM_SLOTS; slot++)
4499 for (rank = 0; rank < NUM_RANKS; rank++)
4500 for (lane = 0; lane < 9; lane++)
4501 write_500(&info,
4502 channel,
4503 info.training.
4504 lane_timings
4505 [tm][channel]
4506 [slot][rank]
4507 [lane],
4508 get_timing_register_addr
4509 (lane, tm,
4510 slot, rank),
4511 9, 0);
4512 write_1d0(info.cached_training->reg_178, 0x178, 7, 1);
4513 write_1d0(info.cached_training->reg_10b, 0x10b, 6, 1);
4514 }
4515
4516 read_mchbar32(0x1f4); // !!!!
4517 write_mchbar32(0x1f4, 0x20000);
4518 write_mchbar32(0x1f0, 0x1d000200);
4519 read_mchbar8(0x1f0); // !!!!
4520 write_mchbar8(0x1f0, 0x1);
4521 read_mchbar8(0x1f0); // !!!!
4522
4523 program_board_delay(&info);
4524
4525 write_mchbar8(0x5ff, 0x0); /* OK */
4526 write_mchbar8(0x5ff, 0x80); /* OK */
4527 write_mchbar8(0x5f4, 0x1); /* OK */
4528
4529 write_mchbar32(0x130, read_mchbar32(0x130) & 0xfffffffd); // | 2 when ?
4530 while (read_mchbar32(0x130) & 1) ;
4531 gav(read_1d0(0x14b, 7)); // = 0x81023100
4532 write_1d0(0x30, 0x14b, 7, 1);
4533 read_1d0(0xd6, 6); // = 0xfa008080 // !!!!
4534 write_1d0(7, 0xd6, 6, 1);
4535 read_1d0(0x328, 6); // = 0xfa018080 // !!!!
4536 write_1d0(7, 0x328, 6, 1);
4537
4538 for (channel = 0; channel < NUM_CHANNELS; channel++)
4539 set_4cf(&info, channel,
4540 info.populated_ranks[channel][0][0] ? 8 : 0);
4541
4542 read_1d0(0x116, 4); // = 0x4040432 // !!!!
4543 write_1d0(2, 0x116, 4, 1);
4544 read_1d0(0xae, 6); // = 0xe8088080 // !!!!
4545 write_1d0(0, 0xae, 6, 1);
4546 read_1d0(0x300, 4); // = 0x48088080 // !!!!
4547 write_1d0(0, 0x300, 6, 1);
4548 read_mchbar16(0x356); // !!!!
4549 write_mchbar16(0x356, 0x1040);
4550 read_mchbar16(0x756); // !!!!
4551 write_mchbar16(0x756, 0x1040);
4552 write_mchbar32(0x140, read_mchbar32(0x140) & ~0x07000000);
4553 write_mchbar32(0x138, read_mchbar32(0x138) & ~0x07000000);
4554 write_mchbar32(0x130, 0x31111301);
Vladimir Serbinenko25fc5322014-12-07 13:05:44 +01004555 /* Wait until REG130b0 is 1. */
4556 while (read_mchbar32(0x130) & 1)
4557 ;
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004558
4559 {
4560 u32 t;
4561 u8 val_a1;
4562 val_a1 = read_1d0(0xa1, 6); // = 0x1cf4040 // !!!!
4563 t = read_1d0(0x2f3, 6); // = 0x10a4040 // !!!!
4564 rmw_1d0(0x320, 0x07,
4565 (t & 4) | ((t & 8) >> 2) | ((t & 0x10) >> 4), 6, 1);
4566 rmw_1d0(0x14b, 0x78,
4567 ((((val_a1 >> 2) & 4) | (val_a1 & 8)) >> 2) | (val_a1 &
4568 4), 7,
4569 1);
4570 rmw_1d0(0xce, 0x38,
4571 ((((val_a1 >> 2) & 4) | (val_a1 & 8)) >> 2) | (val_a1 &
4572 4), 6,
4573 1);
4574 }
4575
4576 for (channel = 0; channel < NUM_CHANNELS; channel++)
4577 set_4cf(&info, channel,
4578 info.populated_ranks[channel][0][0] ? 9 : 1);
4579
4580 rmw_1d0(0x116, 0xe, 1, 4, 1); // = 0x4040432 // !!!!
4581 read_mchbar32(0x144); // !!!!
4582 write_1d0(2, 0xae, 6, 1);
4583 write_1d0(2, 0x300, 6, 1);
4584 write_1d0(2, 0x121, 3, 1);
4585 read_1d0(0xd6, 6); // = 0xfa00c0c7 // !!!!
4586 write_1d0(4, 0xd6, 6, 1);
4587 read_1d0(0x328, 6); // = 0xfa00c0c7 // !!!!
4588 write_1d0(4, 0x328, 6, 1);
4589
4590 for (channel = 0; channel < NUM_CHANNELS; channel++)
4591 set_4cf(&info, channel,
4592 info.populated_ranks[channel][0][0] ? 9 : 0);
4593
4594 write_mchbar32(0x130,
4595 0x11111301 | (info.
4596 populated_ranks[1][0][0] << 30) | (info.
4597 populated_ranks
4598 [0][0]
4599 [0] <<
4600 29));
4601 while (read_mchbar8(0x130) & 1) ; // !!!!
4602 read_1d0(0xa1, 6); // = 0x1cf4054 // !!!!
4603 read_1d0(0x2f3, 6); // = 0x10a4054 // !!!!
4604 read_1d0(0x21c, 6); // = 0xafa00c0 // !!!!
4605 write_1d0(0, 0x21c, 6, 1);
4606 read_1d0(0x14b, 7); // = 0x810231b0 // !!!!
4607 write_1d0(0x35, 0x14b, 7, 1);
4608
4609 for (channel = 0; channel < NUM_CHANNELS; channel++)
4610 set_4cf(&info, channel,
4611 info.populated_ranks[channel][0][0] ? 0xb : 0x2);
4612
4613 set_334(1);
4614
4615 write_mchbar8(0x1e8, 0x4); /* OK */
4616
4617 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4618 write_500(&info, channel,
4619 0x3 & ~(info.populated_ranks_mask[channel]), 0x6b7, 2,
4620 1);
4621 write_500(&info, channel, 0x3, 0x69b, 2, 1);
4622 }
4623 write_mchbar32(0x2d0, (read_mchbar32(0x2d0) & 0xff2c01ff) | 0x200000); /* OK */
4624 write_mchbar16(0x6c0, 0x14a0); /* OK */
4625 write_mchbar32(0x6d0, (read_mchbar32(0x6d0) & 0xff0080ff) | 0x8000); /* OK */
4626 write_mchbar16(0x232, 0x8);
4627 write_mchbar32(0x234, (read_mchbar32(0x234) & 0xfffbfffb) | 0x40004); /* 0x40004 or 0 depending on ? */
4628 write_mchbar32(0x34, (read_mchbar32(0x34) & 0xfffffffd) | 5); /* OK */
4629 write_mchbar32(0x128, 0x2150d05);
4630 write_mchbar8(0x12c, 0x1f); /* OK */
4631 write_mchbar8(0x12d, 0x56); /* OK */
4632 write_mchbar8(0x12e, 0x31);
4633 write_mchbar8(0x12f, 0x0); /* OK */
4634 write_mchbar8(0x271, 0x2); /* OK */
4635 write_mchbar8(0x671, 0x2); /* OK */
4636 write_mchbar8(0x1e8, 0x4); /* OK */
4637 for (channel = 0; channel < NUM_CHANNELS; channel++)
4638 write_mchbar32(0x294 + (channel << 10),
4639 (info.populated_ranks_mask[channel] & 3) << 16);
4640 write_mchbar32(0x134, (read_mchbar32(0x134) & 0xfc01ffff) | 0x10000); /* OK */
4641 write_mchbar32(0x134, (read_mchbar32(0x134) & 0xfc85ffff) | 0x850000); /* OK */
4642 for (channel = 0; channel < NUM_CHANNELS; channel++)
4643 write_mchbar32(0x260 + (channel << 10),
4644 (read_mchbar32(0x260 + (channel << 10)) &
4645 ~0xf00000) | 0x8000000 | ((info.
4646 populated_ranks_mask
4647 [channel] & 3) <<
4648 20));
4649
4650 if (!s3resume)
4651 jedec_init(&info);
4652
4653 int totalrank = 0;
4654 for (channel = 0; channel < NUM_CHANNELS; channel++)
4655 for (slot = 0; slot < NUM_SLOTS; slot++)
4656 for (rank = 0; rank < NUM_RANKS; rank++)
4657 if (info.populated_ranks[channel][slot][rank]) {
4658 jedec_read(&info, channel, slot, rank,
4659 totalrank, 0xa, 0x400);
4660 totalrank++;
4661 }
4662
4663 write_mchbar8(0x12c, 0x9f);
4664
4665 read_mchbar8(0x271); // 2 // !!!!
4666 write_mchbar8(0x271, 0xe);
4667 read_mchbar8(0x671); // !!!!
4668 write_mchbar8(0x671, 0xe);
4669
4670 if (!s3resume) {
4671 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4672 write_mchbar32(0x294 + (channel << 10),
4673 (info.
4674 populated_ranks_mask[channel] & 3) <<
4675 16);
4676 write_mchbar16(0x298 + (channel << 10),
4677 (info.
4678 populated_ranks[channel][0][0]) | (info.
4679 populated_ranks
4680 [channel]
4681 [0]
4682 [1]
4683 <<
4684 5));
4685 write_mchbar32(0x29c + (channel << 10), 0x77a);
4686 }
4687 read_mchbar32(0x2c0); /// !!!
4688 write_mchbar32(0x2c0, 0x6009cc00);
4689
4690 {
4691 u8 a, b;
4692 a = read_mchbar8(0x243); // !!!!
4693 b = read_mchbar8(0x643); // !!!!
4694 write_mchbar8(0x243, a | 2);
4695 write_mchbar8(0x643, b | 2);
4696 }
4697
4698 write_1d0(7, 0x19b, 3, 1);
4699 write_1d0(7, 0x1c0, 3, 1);
4700 write_1d0(4, 0x1c6, 4, 1);
4701 write_1d0(4, 0x1cc, 4, 1);
4702 read_1d0(0x151, 4); // = 0x408c6d74 // !!!!
4703 write_1d0(4, 0x151, 4, 1);
4704 write_mchbar32(0x584, 0xfffff);
4705 write_mchbar32(0x984, 0xfffff);
4706
4707 for (channel = 0; channel < NUM_CHANNELS; channel++)
4708 for (slot = 0; slot < NUM_SLOTS; slot++)
4709 for (rank = 0; rank < NUM_RANKS; rank++)
4710 if (info.
4711 populated_ranks[channel][slot]
4712 [rank])
4713 config_rank(&info, s3resume,
4714 channel, slot,
4715 rank);
4716
4717 write_mchbar8(0x243, 0x1);
4718 write_mchbar8(0x643, 0x1);
4719 }
4720
4721 /* was == 1 but is common */
4722 pcie_write_config16(NORTHBRIDGE, 0xc8, 3);
4723 write_26c(0, 0x820);
4724 write_26c(1, 0x820);
4725 write_mchbar32(0x130, read_mchbar32(0x130) | 2);
4726 /* end */
4727
4728 if (s3resume) {
4729 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4730 write_mchbar32(0x294 + (channel << 10),
4731 (info.
4732 populated_ranks_mask[channel] & 3) <<
4733 16);
4734 write_mchbar16(0x298 + (channel << 10),
4735 (info.
4736 populated_ranks[channel][0][0]) | (info.
4737 populated_ranks
4738 [channel]
4739 [0]
4740 [1]
4741 <<
4742 5));
4743 write_mchbar32(0x29c + (channel << 10), 0x77a);
4744 }
4745 read_mchbar32(0x2c0); /// !!!
4746 write_mchbar32(0x2c0, 0x6009cc00);
4747 }
4748
4749 write_mchbar32(0xfa4, read_mchbar32(0xfa4) & ~0x01000002);
4750 write_mchbar32(0xfb0, 0x2000e019);
4751
4752#if !REAL
4753 printf("CP16\n");
4754#endif
4755
4756 /* Before training. */
4757 timestamp_add_now(103);
4758
4759 if (!s3resume)
4760 ram_training(&info);
4761
4762 /* After training. */
Paul Menzel9e817bf2015-05-28 07:32:48 +02004763 timestamp_add_now(104);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004764
4765 dump_timings(&info);
4766
4767#if 0
4768 ram_check(0x100000, 0x200000);
4769#endif
4770 program_modules_memory_map(&info, 0);
4771 program_total_memory_map(&info);
4772
4773 if (info.non_interleaved_part_mb != 0 && info.interleaved_part_mb != 0)
4774 write_mchbar8(0x111, 0x20 | (0 << 2) | (1 << 6) | (0 << 7));
4775 else if (have_match_ranks(&info, 0, 4) && have_match_ranks(&info, 1, 4))
4776 write_mchbar8(0x111, 0x20 | (3 << 2) | (0 << 6) | (1 << 7));
4777 else if (have_match_ranks(&info, 0, 2) && have_match_ranks(&info, 1, 2))
4778 write_mchbar8(0x111, 0x20 | (3 << 2) | (0 << 6) | (0 << 7));
4779 else
4780 write_mchbar8(0x111, 0x20 | (3 << 2) | (1 << 6) | (0 << 7));
4781
4782 write_mchbar32(0xfac, read_mchbar32(0xfac) & ~0x80000000); // OK
4783 write_mchbar32(0xfb4, 0x4800); // OK
4784 write_mchbar32(0xfb8, (info.revision < 8) ? 0x20 : 0x0); // OK
4785 write_mchbar32(0xe94, 0x7ffff); // OK
4786 write_mchbar32(0xfc0, 0x80002040); // OK
4787 write_mchbar32(0xfc4, 0x701246); // OK
4788 write_mchbar8(0xfc8, read_mchbar8(0xfc8) & ~0x70); // OK
4789 write_mchbar32(0xe5c, 0x1000000 | read_mchbar32(0xe5c)); // OK
4790 write_mchbar32(0x1a70, (read_mchbar32(0x1a70) | 0x00200000) & ~0x00100000); // OK
4791 write_mchbar32(0x50, 0x700b0); // OK
4792 write_mchbar32(0x3c, 0x10); // OK
4793 write_mchbar8(0x1aa8, (read_mchbar8(0x1aa8) & ~0x35) | 0xa); // OK
4794 write_mchbar8(0xff4, read_mchbar8(0xff4) | 0x2); // OK
4795 write_mchbar32(0xff8, (read_mchbar32(0xff8) & ~0xe008) | 0x1020); // OK
4796
4797#if REAL
4798 write_mchbar32(0xd00, IOMMU_BASE2 | 1);
4799 write_mchbar32(0xd40, IOMMU_BASE1 | 1);
4800 write_mchbar32(0xdc0, IOMMU_BASE4 | 1);
4801
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08004802 write32p(IOMMU_BASE1 | 0xffc, 0x80000000);
4803 write32p(IOMMU_BASE2 | 0xffc, 0xc0000000);
4804 write32p(IOMMU_BASE4 | 0xffc, 0x80000000);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004805
4806#else
4807 {
4808 u32 eax;
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08004809 eax = read32p(0xffc + (read_mchbar32(0xd00) & ~1)) | 0x08000000; // = 0xe911714b// OK
4810 write32p(0xffc + (read_mchbar32(0xd00) & ~1), eax); // OK
4811 eax = read32p(0xffc + (read_mchbar32(0xdc0) & ~1)) | 0x40000000; // = 0xe911714b// OK
4812 write32p(0xffc + (read_mchbar32(0xdc0) & ~1), eax); // OK
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004813 }
4814#endif
4815
4816 {
4817 u32 eax;
4818
4819 eax = info.fsb_frequency / 9;
4820 write_mchbar32(0xfcc, (read_mchbar32(0xfcc) & 0xfffc0000) | (eax * 0x280) | (eax * 0x5000) | eax | 0x40000); // OK
4821 write_mchbar32(0x20, 0x33001); //OK
4822 }
4823
4824 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4825 write_mchbar32(0x220 + (channel << 10), read_mchbar32(0x220 + (channel << 10)) & ~0x7770); //OK
4826 if (info.max_slots_used_in_channel == 1)
4827 write_mchbar16(0x237 + (channel << 10), (read_mchbar16(0x237 + (channel << 10)) | 0x0201)); //OK
4828 else
4829 write_mchbar16(0x237 + (channel << 10), (read_mchbar16(0x237 + (channel << 10)) & ~0x0201)); //OK
4830
4831 write_mchbar8(0x241 + (channel << 10), read_mchbar8(0x241 + (channel << 10)) | 1); // OK
4832
4833 if (info.clock_speed_index <= 1
4834 && (info.silicon_revision == 2
4835 || info.silicon_revision == 3))
4836 write_mchbar32(0x248 + (channel << 10), (read_mchbar32(0x248 + (channel << 10)) | 0x00102000)); // OK
4837 else
4838 write_mchbar32(0x248 + (channel << 10), (read_mchbar32(0x248 + (channel << 10)) & ~0x00102000)); // OK
4839 }
4840
4841 write_mchbar32(0x115, read_mchbar32(0x115) | 0x1000000); // OK
4842
4843 {
4844 u8 al;
4845 al = 0xd;
4846 if (!(info.silicon_revision == 0 || info.silicon_revision == 1))
4847 al += 2;
4848 al |= ((1 << (info.max_slots_used_in_channel - 1)) - 1) << 4;
4849 write_mchbar32(0x210, (al << 16) | 0x20); // OK
4850 }
4851
4852 for (channel = 0; channel < NUM_CHANNELS; channel++) {
4853 write_mchbar32(0x288 + (channel << 10), 0x70605040); // OK
4854 write_mchbar32(0x28c + (channel << 10), 0xfffec080); // OK
4855 write_mchbar32(0x290 + (channel << 10), 0x282091c | ((info.max_slots_used_in_channel - 1) << 0x16)); // OK
4856 }
4857 u32 reg1c;
4858 pcie_read_config32(NORTHBRIDGE, 0x40); // = DEFAULT_EPBAR | 0x001 // OK
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08004859 reg1c = read32p(DEFAULT_EPBAR | 0x01c); // = 0x8001 // OK
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004860 pcie_read_config32(NORTHBRIDGE, 0x40); // = DEFAULT_EPBAR | 0x001 // OK
Kevin Paul Herbertbde6d302014-12-24 18:43:20 -08004861 write32p(DEFAULT_EPBAR | 0x01c, reg1c); // OK
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004862 read_mchbar8(0xe08); // = 0x0
4863 pcie_read_config32(NORTHBRIDGE, 0xe4); // = 0x316126
4864 write_mchbar8(0x1210, read_mchbar8(0x1210) | 2); // OK
4865 write_mchbar32(0x1200, 0x8800440); // OK
4866 write_mchbar32(0x1204, 0x53ff0453); // OK
4867 write_mchbar32(0x1208, 0x19002043); // OK
4868 write_mchbar16(0x1214, 0x320); // OK
4869
4870 if (info.revision == 0x10 || info.revision == 0x11) {
4871 write_mchbar16(0x1214, 0x220); // OK
4872 write_mchbar8(0x1210, read_mchbar8(0x1210) | 0x40); // OK
4873 }
4874
4875 write_mchbar8(0x1214, read_mchbar8(0x1214) | 0x4); // OK
4876 write_mchbar8(0x120c, 0x1); // OK
4877 write_mchbar8(0x1218, 0x3); // OK
4878 write_mchbar8(0x121a, 0x3); // OK
4879 write_mchbar8(0x121c, 0x3); // OK
4880 write_mchbar16(0xc14, 0x0); // OK
4881 write_mchbar16(0xc20, 0x0); // OK
4882 write_mchbar32(0x1c, 0x0); // OK
4883
4884 /* revision dependent here. */
4885
4886 write_mchbar16(0x1230, read_mchbar16(0x1230) | 0x1f07); // OK
4887
4888 if (info.uma_enabled)
4889 write_mchbar32(0x11f4, read_mchbar32(0x11f4) | 0x10000000); // OK
4890
4891 write_mchbar16(0x1230, read_mchbar16(0x1230) | 0x8000); // OK
4892 write_mchbar8(0x1214, read_mchbar8(0x1214) | 1); // OK
4893
4894 u8 bl, ebpb;
4895 u16 reg_1020;
4896
4897 reg_1020 = read_mchbar32(0x1020); // = 0x6c733c // OK
4898 write_mchbar8(0x1070, 0x1); // OK
4899
4900 write_mchbar32(0x1000, 0x100); // OK
4901 write_mchbar8(0x1007, 0x0); // OK
4902
4903 if (reg_1020 != 0) {
4904 write_mchbar16(0x1018, 0x0); // OK
4905 bl = reg_1020 >> 8;
4906 ebpb = reg_1020 & 0xff;
4907 } else {
4908 ebpb = 0;
4909 bl = 8;
4910 }
4911
4912 rdmsr(0x1a2);
4913
4914 write_mchbar32(0x1014, 0xffffffff); // OK
4915
4916 write_mchbar32(0x1010, ((((ebpb + 0x7d) << 7) / bl) & 0xff) * (! !reg_1020)); // OK
4917
4918 write_mchbar8(0x101c, 0xb8); // OK
4919
4920 write_mchbar8(0x123e, (read_mchbar8(0x123e) & 0xf) | 0x60); // OK
4921 if (reg_1020 != 0) {
4922 write_mchbar32(0x123c, (read_mchbar32(0x123c) & ~0x00900000) | 0x600000); // OK
4923 write_mchbar8(0x101c, 0xb8); // OK
4924 }
4925
4926 setup_heci_uma(&info);
4927
4928 if (info.uma_enabled) {
4929 u16 ax;
4930 write_mchbar32(0x11b0, read_mchbar32(0x11b0) | 0x4000); // OK
4931 write_mchbar32(0x11b4, read_mchbar32(0x11b4) | 0x4000); // OK
4932 write_mchbar16(0x1190, read_mchbar16(0x1190) | 0x4000); // OK
4933
4934 ax = read_mchbar16(0x1190) & 0xf00; // = 0x480a // OK
4935 write_mchbar16(0x1170, ax | (read_mchbar16(0x1170) & 0x107f) | 0x4080); // OK
4936 write_mchbar16(0x1170, read_mchbar16(0x1170) | 0x1000); // OK
4937#if REAL
4938 udelay(1000);
4939#endif
4940 u16 ecx;
4941 for (ecx = 0xffff; ecx && (read_mchbar16(0x1170) & 0x1000); ecx--) ; // OK
4942 write_mchbar16(0x1190, read_mchbar16(0x1190) & ~0x4000); // OK
4943 }
4944
4945 pcie_write_config8(SOUTHBRIDGE, GEN_PMCON_2,
4946 pcie_read_config8(SOUTHBRIDGE, GEN_PMCON_2) & ~0x80);
4947 udelay(10000);
Vladimir Serbinenkoc7db28c2014-02-19 22:09:33 +01004948 write_mchbar16(0x2ca8, 0x8);
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004949
4950#if REAL
4951 udelay(1000);
4952 dump_timings(&info);
Vladimir Serbinenkob16f0922014-06-07 16:27:27 +02004953 cbmem_wasnot_inited = cbmem_recovery(s3resume);
4954
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004955 if (!s3resume)
4956 save_timings(&info);
Vladimir Serbinenkob16f0922014-06-07 16:27:27 +02004957 if (s3resume && cbmem_wasnot_inited) {
4958 u32 reg32;
4959 printk(BIOS_ERR, "Failed S3 resume.\n");
4960 ram_check(0x100000, 0x200000);
4961
4962 /* Clear SLP_TYPE. */
4963 reg32 = inl(DEFAULT_PMBASE + 0x04);
4964 outl(reg32 & ~(7 << 10), DEFAULT_PMBASE + 0x04);
4965
4966 /* Failed S3 resume, reset to come up cleanly */
4967 outb(0xe, 0xcf9);
Patrick Georgi546953c2014-11-29 10:38:17 +01004968 halt();
Vladimir Serbinenkob16f0922014-06-07 16:27:27 +02004969 }
Vladimir Serbinenkoc6f6be02013-11-12 22:32:08 +01004970#endif
4971}