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