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