blob: 0b27fe5524ebfa3fe2e086ed270d5bacad904ab5 [file] [log] [blame]
Stefan Reinauer00636b02012-04-04 00:08:51 +02001/*
2 * This file is part of the coreboot project.
3 *
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004 * Copyright (C) 2014 Damien Zammit <damien@zamaudio.com>
5 * Copyright (C) 2014 Vladimir Serbinenko <phcoder@gmail.com>
Stefan Reinauer00636b02012-04-04 00:08:51 +02006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
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.
Stefan Reinauer00636b02012-04-04 00:08:51 +020015 */
16
17#include <console/console.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +020018#include <console/usb.h>
Kyösti Mälkki5687fc92013-11-28 18:11:49 +020019#include <bootmode.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020020#include <string.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020021#include <arch/io.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020022#include <cbmem.h>
23#include <arch/cbfs.h>
24#include <cbfs.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070025#include <halt.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020026#include <ip_checksum.h>
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010027#include <timestamp.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020028#include <pc80/mc146818rtc.h>
Alexander Couzens81c5c762016-03-09 03:13:45 +010029#include <northbridge/intel/common/mrc_cache.h>
Duncan Laurie7b508dd2012-04-09 12:30:43 -070030#include <device/pci_def.h>
Patrick Rudolphb97009e2016-02-28 15:24:04 +010031#include <memory_info.h>
32#include <smbios.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070033#include "raminit_native.h"
Stefan Reinauer00636b02012-04-04 00:08:51 +020034#include "sandybridge.h"
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070035#include <delay.h>
36#include <lib.h>
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010037#include <device/device.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020038
39/* Management Engine is in the southbridge */
40#include "southbridge/intel/bd82x6x/me.h"
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070041/* For SPD. */
42#include "southbridge/intel/bd82x6x/smbus.h"
43#include "arch/cpu.h"
44#include "cpu/x86/msr.h"
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010045#include <northbridge/intel/sandybridge/chip.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020046
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070047/* FIXME: no ECC support. */
48/* FIXME: no support for 3-channel chipsets. */
Stefan Reinauer00636b02012-04-04 00:08:51 +020049
Patrick Rudolph371d2912015-10-09 13:33:25 +020050/*
51 * Register description:
52 * Intel provides a command queue of depth four.
53 * Every command is configured by using multiple registers.
54 * On executing the command queue you have to provide the depth used.
55 *
56 * Known registers:
57 * Channel X = [0, 1]
58 * Command queue index Y = [0, 1, 2, 3]
59 *
60 * DEFAULT_MCHBAR + 0x4220 + 0x400 * X + 4 * Y: command io register
61 * Controls the DRAM command signals
62 * Bit 0: !RAS
63 * Bit 1: !CAS
64 * Bit 2: !WE
65 *
66 * DEFAULT_MCHBAR + 0x4200 + 0x400 * X + 4 * Y: addr bankslot io register
67 * Controls the address, bank address and slotrank signals
68 * Bit 0-15 : Address
69 * Bit 20-22: Bank Address
70 * Bit 24-25: slotrank
71 *
72 * DEFAULT_MCHBAR + 0x4230 + 0x400 * X + 4 * Y: idle register
73 * Controls the idle time after issuing this DRAM command
74 * Bit 16-32: number of clock-cylces to idle
75 *
76 * DEFAULT_MCHBAR + 0x4284 + 0x400 * channel: execute command queue
77 * Starts to execute all queued commands
78 * Bit 0 : start DRAM command execution
79 * Bit 16-20: (number of queued commands - 1) * 4
80 */
81
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070082#define BASEFREQ 133
83#define tDLLK 512
Stefan Reinauer00636b02012-04-04 00:08:51 +020084
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070085#define IS_SANDY_CPU(x) ((x & 0xffff0) == 0x206a0)
86#define IS_SANDY_CPU_C(x) ((x & 0xf) == 4)
87#define IS_SANDY_CPU_D0(x) ((x & 0xf) == 5)
88#define IS_SANDY_CPU_D1(x) ((x & 0xf) == 6)
89#define IS_SANDY_CPU_D2(x) ((x & 0xf) == 7)
Stefan Reinauer00636b02012-04-04 00:08:51 +020090
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070091#define IS_IVY_CPU(x) ((x & 0xffff0) == 0x306a0)
92#define IS_IVY_CPU_C(x) ((x & 0xf) == 4)
93#define IS_IVY_CPU_K(x) ((x & 0xf) == 5)
94#define IS_IVY_CPU_D(x) ((x & 0xf) == 6)
95#define IS_IVY_CPU_E(x) ((x & 0xf) >= 8)
Stefan Reinauer00636b02012-04-04 00:08:51 +020096
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070097#define NUM_CHANNELS 2
98#define NUM_SLOTRANKS 4
99#define NUM_SLOTS 2
100#define NUM_LANES 8
Stefan Reinauer00636b02012-04-04 00:08:51 +0200101
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700102/* FIXME: Vendor BIOS uses 64 but our algorithms are less
103 performant and even 1 seems to be enough in practice. */
104#define NUM_PATTERNS 4
Stefan Reinauer00636b02012-04-04 00:08:51 +0200105
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700106typedef struct odtmap_st {
107 u16 rttwr;
108 u16 rttnom;
109} odtmap;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200110
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700111typedef struct dimm_info_st {
112 dimm_attr dimm[NUM_CHANNELS][NUM_SLOTS];
113} dimm_info;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200114
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700115struct ram_rank_timings {
116 /* Register 4024. One byte per slotrank. */
117 u8 val_4024;
118 /* Register 4028. One nibble per slotrank. */
119 u8 val_4028;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200120
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700121 int val_320c;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200122
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700123 struct ram_lane_timings {
124 /* lane register offset 0x10. */
125 u16 timA; /* bits 0 - 5, bits 16 - 18 */
126 u8 rising; /* bits 8 - 14 */
127 u8 falling; /* bits 20 - 26. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200128
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700129 /* lane register offset 0x20. */
130 int timC; /* bit 0 - 5, 19. */
131 u16 timB; /* bits 8 - 13, 15 - 17. */
132 } lanes[NUM_LANES];
133};
Stefan Reinauer00636b02012-04-04 00:08:51 +0200134
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700135struct ramctr_timing_st;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200136
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700137typedef struct ramctr_timing_st {
138 int mobile;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200139
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700140 u16 cas_supported;
141 /* tLatencies are in units of ns, scaled by x256 */
142 u32 tCK;
143 u32 tAA;
144 u32 tWR;
145 u32 tRCD;
146 u32 tRRD;
147 u32 tRP;
148 u32 tRAS;
149 u32 tRFC;
150 u32 tWTR;
151 u32 tRTP;
152 u32 tFAW;
153 /* Latencies in terms of clock cycles
154 * They are saved separately as they are needed for DRAM MRS commands*/
155 u8 CAS; /* CAS read latency */
156 u8 CWL; /* CAS write latency */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200157
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700158 u32 tREFI;
159 u32 tMOD;
160 u32 tXSOffset;
161 u32 tWLO;
162 u32 tCKE;
163 u32 tXPDLL;
164 u32 tXP;
165 u32 tAONPD;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200166
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700167 u16 reg_5064b0; /* bits 0-11. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200168
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700169 u8 rankmap[NUM_CHANNELS];
170 int ref_card_offset[NUM_CHANNELS];
171 u32 mad_dimm[NUM_CHANNELS];
172 int channel_size_mb[NUM_CHANNELS];
173 u32 cmd_stretch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200174
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700175 int reg_c14_offset;
176 int reg_320c_range_threshold;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200177
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700178 int edge_offset[3];
179 int timC_offset[3];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200180
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700181 int extended_temperature_range;
182 int auto_self_refresh;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200183
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700184 int rank_mirror[NUM_CHANNELS][NUM_SLOTRANKS];
185
186 struct ram_rank_timings timings[NUM_CHANNELS][NUM_SLOTRANKS];
187} ramctr_timing;
188
189#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
190#define NORTHBRIDGE PCI_DEV(0, 0x0, 0)
191#define FOR_ALL_LANES for (lane = 0; lane < NUM_LANES; lane++)
192#define FOR_ALL_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++)
193#define FOR_ALL_POPULATED_RANKS for (slotrank = 0; slotrank < NUM_SLOTRANKS; slotrank++) if (ctrl->rankmap[channel] & (1 << slotrank))
194#define FOR_ALL_POPULATED_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) if (ctrl->rankmap[channel])
195#define MAX_EDGE_TIMING 71
196#define MAX_TIMC 127
197#define MAX_TIMB 511
198#define MAX_TIMA 127
199
200static void program_timings(ramctr_timing * ctrl, int channel);
201
202static const char *ecc_decoder[] = {
Stefan Reinauer00636b02012-04-04 00:08:51 +0200203 "inactive",
204 "active on IO",
205 "disabled on IO",
206 "active"
207};
208
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700209static void wait_txt_clear(void)
210{
211 struct cpuid_result cp;
212
213 cp = cpuid_ext(0x1, 0x0);
214 /* Check if TXT is supported? */
215 if (!(cp.ecx & 0x40))
216 return;
217 /* Some TXT public bit. */
218 if (!(read32((void *)0xfed30010) & 1))
219 return;
220 /* Wait for TXT clear. */
221 while (!(read8((void *)0xfed40000) & (1 << 7))) ;
222}
223
224static void sfence(void)
225{
226 asm volatile ("sfence");
227}
228
Patrick Rudolph9b515682015-10-09 13:43:51 +0200229static void toggle_io_reset(void) {
230 /* toggle IO reset bit */
231 u32 r32 = read32(DEFAULT_MCHBAR + 0x5030);
232 write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20);
233 udelay(1);
234 write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20);
235 udelay(1);
236}
237
Stefan Reinauer00636b02012-04-04 00:08:51 +0200238/*
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100239 * Fill cbmem with information for SMBIOS type 17.
240 */
241static void fill_smbios17(dimm_info *info, uint16_t ddr_freq)
242{
243 struct memory_info *mem_info;
244 int channel, slot;
245 struct dimm_info *dimm;
246
247 /*
248 * Allocate CBMEM area for DIMM information used to populate SMBIOS
249 * table 17
250 */
251 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
252 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
253 if (!mem_info)
254 return;
255
256 memset(mem_info, 0, sizeof(*mem_info));
257
258 FOR_ALL_CHANNELS for(slot = 0; slot < NUM_SLOTS; slot++) {
259 dimm = &mem_info->dimm[mem_info->dimm_cnt];
260 if (info->dimm[channel][slot].size_mb) {
261 dimm->ddr_type = MEMORY_TYPE_DDR3;
262 dimm->ddr_frequency = ddr_freq;
263 dimm->dimm_size = info->dimm[channel][slot].size_mb;
264 dimm->channel_num = channel;
265 dimm->rank_per_dimm = info->dimm[channel][slot].ranks;
266 dimm->dimm_num = slot;
267 memcpy(dimm->module_part_number,
268 info->dimm[channel][slot].part_number, 16);
269 dimm->mod_id = info->dimm[channel][slot].manufacturer_id;
270 dimm->mod_type = info->dimm[channel][slot].dimm_type;
271 dimm->bus_width = info->dimm[channel][slot].width;
272 mem_info->dimm_cnt++;
273 }
274 }
275}
276
277/*
Stefan Reinauer00636b02012-04-04 00:08:51 +0200278 * Dump in the log memory controller configuration as read from the memory
279 * controller registers.
280 */
281static void report_memory_config(void)
282{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700283 u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200284 int i;
285
286 addr_decoder_common = MCHBAR32(0x5000);
287 addr_decode_ch[0] = MCHBAR32(0x5004);
288 addr_decode_ch[1] = MCHBAR32(0x5008);
289
290 printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700291 (MCHBAR32(0x5e04) * 13333 * 2 + 50) / 100);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200292 printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700293 addr_decoder_common & 3, (addr_decoder_common >> 2) & 3,
Stefan Reinauer00636b02012-04-04 00:08:51 +0200294 (addr_decoder_common >> 4) & 3);
295
296 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
297 u32 ch_conf = addr_decode_ch[i];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700298 printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i,
299 ch_conf);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200300 printk(BIOS_DEBUG, " ECC %s\n",
301 ecc_decoder[(ch_conf >> 24) & 3]);
302 printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
303 ((ch_conf >> 22) & 1) ? "on" : "off");
304 printk(BIOS_DEBUG, " rank interleave %s\n",
305 ((ch_conf >> 21) & 1) ? "on" : "off");
306 printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n",
307 ((ch_conf >> 0) & 0xff) * 256,
308 ((ch_conf >> 19) & 1) ? 16 : 8,
309 ((ch_conf >> 17) & 1) ? "dual" : "single",
310 ((ch_conf >> 16) & 1) ? "" : ", selected");
311 printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n",
312 ((ch_conf >> 8) & 0xff) * 256,
313 ((ch_conf >> 20) & 1) ? 16 : 8,
314 ((ch_conf >> 18) & 1) ? "dual" : "single",
315 ((ch_conf >> 16) & 1) ? ", selected" : "");
316 }
317}
318
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700319void read_spd(spd_raw_data * spd, u8 addr)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200320{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700321 int j;
322 for (j = 0; j < 256; j++)
323 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
324}
325
326static void dram_find_spds_ddr3(spd_raw_data * spd, dimm_info * dimm,
327 ramctr_timing * ctrl)
328{
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100329 int dimms = 0, dimms_on_channel;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700330 int channel, slot, spd_slot;
331
332 memset (ctrl->rankmap, 0, sizeof (ctrl->rankmap));
333
334 ctrl->extended_temperature_range = 1;
335 ctrl->auto_self_refresh = 1;
336
337 FOR_ALL_CHANNELS {
338 ctrl->channel_size_mb[channel] = 0;
339
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100340 dimms_on_channel = 0;
341 /* count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700342 for (slot = 0; slot < NUM_SLOTS; slot++) {
343 spd_slot = 2 * channel + slot;
344 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100345 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
346 dimms_on_channel++;
347 }
348
349 for (slot = 0; slot < NUM_SLOTS; slot++) {
350 spd_slot = 2 * channel + slot;
351 /* search for XMP profile */
352 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
353 spd[spd_slot],
354 DDR3_XMP_PROFILE_1);
355
356 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
357 printram("No valid XMP profile found.\n");
358 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
359 } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
360 printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
361 dimm->dimm[channel][slot].dimms_per_channel,
362 dimms_on_channel);
363 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
364 } else if (dimm->dimm[channel][slot].voltage != 1500) {
365 /* TODO: support other DDR3 voltage than 1500mV */
366 printram("XMP profile's requested %u mV is unsupported.\n",
367 dimm->dimm[channel][slot].voltage);
368 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
369 }
370
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700371 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
372 // set dimm invalid
373 dimm->dimm[channel][slot].ranks = 0;
374 dimm->dimm[channel][slot].size_mb = 0;
375 continue;
376 }
377
378 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
379 dimms++;
380 ctrl->rank_mirror[channel][slot * 2] = 0;
381 ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
382 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
383
384 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
385 ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
386
387 ctrl->rankmap[channel] |= ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100388 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n",
389 channel, ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700390 }
391 if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc)
392 && dimm->dimm[channel][0].reference_card <= 5 && dimm->dimm[channel][1].reference_card <= 5) {
393 const int ref_card_offset_table[6][6] = {
394 { 0, 0, 0, 0, 2, 2, },
395 { 0, 0, 0, 0, 2, 2, },
396 { 0, 0, 0, 0, 2, 2, },
397 { 0, 0, 0, 0, 1, 1, },
398 { 2, 2, 2, 1, 0, 0, },
399 { 2, 2, 2, 1, 0, 0, },
400 };
401 ctrl->ref_card_offset[channel] = ref_card_offset_table[dimm->dimm[channel][0].reference_card]
402 [dimm->dimm[channel][1].reference_card];
403 } else
404 ctrl->ref_card_offset[channel] = 0;
405 }
406
407 if (!dimms)
408 die("No DIMMs were found");
409}
410
411static void dram_find_common_params(const dimm_info * dimms,
412 ramctr_timing * ctrl)
413{
414 size_t valid_dimms;
415 int channel, slot;
416 ctrl->cas_supported = 0xff;
417 valid_dimms = 0;
418 FOR_ALL_CHANNELS for (slot = 0; slot < 2; slot++) {
419 const dimm_attr *dimm = &dimms->dimm[channel][slot];
420 if (dimm->dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3)
421 continue;
422 valid_dimms++;
423
424 /* Find all possible CAS combinations */
425 ctrl->cas_supported &= dimm->cas_supported;
426
427 /* Find the smallest common latencies supported by all DIMMs */
428 ctrl->tCK = MAX(ctrl->tCK, dimm->tCK);
429 ctrl->tAA = MAX(ctrl->tAA, dimm->tAA);
430 ctrl->tWR = MAX(ctrl->tWR, dimm->tWR);
431 ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD);
432 ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD);
433 ctrl->tRP = MAX(ctrl->tRP, dimm->tRP);
434 ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS);
435 ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC);
436 ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR);
437 ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP);
438 ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW);
439 }
440
441 if (!ctrl->cas_supported)
442 die("Unsupported DIMM combination. "
443 "DIMMS do not support common CAS latency");
444 if (!valid_dimms)
445 die("No valid DIMMs found");
446}
447
448static u8 get_CWL(u8 CAS)
449{
450 /* Get CWL based on CAS using the following rule:
451 * _________________________________________
452 * CAS: | 4T | 5T | 6T | 7T | 8T | 9T | 10T | 11T |
453 * CWL: | 5T | 5T | 5T | 6T | 6T | 7T | 7T | 8T |
454 */
455 static const u8 cas_cwl_map[] = { 5, 5, 5, 6, 6, 7, 7, 8 };
456 if (CAS > 11)
457 return 8;
458 return cas_cwl_map[CAS - 4];
459}
460
461/* Frequency multiplier. */
462static u32 get_FRQ(u32 tCK)
463{
464 u32 FRQ;
465 FRQ = 256000 / (tCK * BASEFREQ);
466 if (FRQ > 8)
467 return 8;
468 if (FRQ < 3)
469 return 3;
470 return FRQ;
471}
472
473static u32 get_REFI(u32 tCK)
474{
475 /* Get REFI based on MCU frequency using the following rule:
476 * _________________________________________
477 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
478 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 |
479 */
480 static const u32 frq_refi_map[] =
481 { 3120, 4160, 5200, 6240, 7280, 8320 };
482 return frq_refi_map[get_FRQ(tCK) - 3];
483}
484
485static u8 get_XSOffset(u32 tCK)
486{
487 /* Get XSOffset based on MCU frequency using the following rule:
488 * _________________________
489 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
490 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 |
491 */
492 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 };
493 return frq_xs_map[get_FRQ(tCK) - 3];
494}
495
496static u8 get_MOD(u32 tCK)
497{
498 /* Get MOD based on MCU frequency using the following rule:
499 * _____________________________
500 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
501 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 |
502 */
503 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 };
504 return frq_mod_map[get_FRQ(tCK) - 3];
505}
506
507static u8 get_WLO(u32 tCK)
508{
509 /* Get WLO based on MCU frequency using the following rule:
510 * _______________________
511 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
512 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 |
513 */
514 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 };
515 return frq_wlo_map[get_FRQ(tCK) - 3];
516}
517
518static u8 get_CKE(u32 tCK)
519{
520 /* Get CKE based on MCU frequency using the following rule:
521 * _______________________
522 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
523 * CKE : | 3 | 3 | 4 | 4 | 5 | 6 |
524 */
525 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 };
526 return frq_cke_map[get_FRQ(tCK) - 3];
527}
528
529static u8 get_XPDLL(u32 tCK)
530{
531 /* Get XPDLL based on MCU frequency using the following rule:
532 * _____________________________
533 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
534 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 |
535 */
536 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 };
537 return frq_xpdll_map[get_FRQ(tCK) - 3];
538}
539
540static u8 get_XP(u32 tCK)
541{
542 /* Get XP based on MCU frequency using the following rule:
543 * _______________________
544 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
545 * XP : | 3 | 4 | 4 | 5 | 6 | 7 |
546 */
547 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 };
548 return frq_xp_map[get_FRQ(tCK) - 3];
549}
550
551static u8 get_AONPD(u32 tCK)
552{
553 /* Get AONPD based on MCU frequency using the following rule:
554 * ________________________
555 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
556 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 |
557 */
558 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 };
559 return frq_aonpd_map[get_FRQ(tCK) - 3];
560}
561
562static u32 get_COMP2(u32 tCK)
563{
564 /* Get COMP2 based on MCU frequency using the following rule:
565 * ___________________________________________________________
566 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
567 * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C |
568 */
569 static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C,
570 0xC6369CC, 0xC42514C, 0xC21410C
571 };
572 return frq_comp2_map[get_FRQ(tCK) - 3];
573}
574
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100575static u32 get_XOVER_CLK(u8 rankmap)
576{
577 return rankmap << 24;
578}
579
580static u32 get_XOVER_CMD(u8 rankmap)
581{
582 u32 reg;
583
584 // enable xover cmd
585 reg = 0x4000;
586
587 // enable xover ctl
588 if (rankmap & 0x3)
589 reg |= 0x20000;
590
591 if (rankmap & 0xc)
592 reg |= 0x4000000;
593
594 return reg;
595}
596
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700597static void dram_timing(ramctr_timing * ctrl)
598{
599 u8 val;
600 u32 val32;
601
602 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
603 * we cap it if we have faster DIMMs.
604 * Then, align it to the closest JEDEC standard frequency */
605 if (ctrl->tCK <= TCK_1066MHZ) {
606 ctrl->tCK = TCK_1066MHZ;
607 ctrl->edge_offset[0] = 16;
608 ctrl->edge_offset[1] = 7;
609 ctrl->edge_offset[2] = 7;
610 ctrl->timC_offset[0] = 18;
611 ctrl->timC_offset[1] = 7;
612 ctrl->timC_offset[2] = 7;
613 ctrl->reg_c14_offset = 16;
614 ctrl->reg_5064b0 = 0x218;
615 ctrl->reg_320c_range_threshold = 13;
616 } else if (ctrl->tCK <= TCK_933MHZ) {
617 ctrl->tCK = TCK_933MHZ;
618 ctrl->edge_offset[0] = 14;
619 ctrl->edge_offset[1] = 6;
620 ctrl->edge_offset[2] = 6;
621 ctrl->timC_offset[0] = 15;
622 ctrl->timC_offset[1] = 6;
623 ctrl->timC_offset[2] = 6;
624 ctrl->reg_c14_offset = 14;
625 ctrl->reg_5064b0 = 0x1d5;
626 ctrl->reg_320c_range_threshold = 15;
627 } else if (ctrl->tCK <= TCK_800MHZ) {
628 ctrl->tCK = TCK_800MHZ;
629 ctrl->edge_offset[0] = 13;
630 ctrl->edge_offset[1] = 5;
631 ctrl->edge_offset[2] = 5;
632 ctrl->timC_offset[0] = 14;
633 ctrl->timC_offset[1] = 5;
634 ctrl->timC_offset[2] = 5;
635 ctrl->reg_c14_offset = 12;
636 ctrl->reg_5064b0 = 0x193;
637 ctrl->reg_320c_range_threshold = 15;
638 } else if (ctrl->tCK <= TCK_666MHZ) {
639 ctrl->tCK = TCK_666MHZ;
640 ctrl->edge_offset[0] = 10;
641 ctrl->edge_offset[1] = 4;
642 ctrl->edge_offset[2] = 4;
643 ctrl->timC_offset[0] = 11;
644 ctrl->timC_offset[1] = 4;
645 ctrl->timC_offset[2] = 4;
646 ctrl->reg_c14_offset = 10;
647 ctrl->reg_5064b0 = 0x150;
648 ctrl->reg_320c_range_threshold = 16;
649 } else if (ctrl->tCK <= TCK_533MHZ) {
650 ctrl->tCK = TCK_533MHZ;
651 ctrl->edge_offset[0] = 8;
652 ctrl->edge_offset[1] = 3;
653 ctrl->edge_offset[2] = 3;
654 ctrl->timC_offset[0] = 9;
655 ctrl->timC_offset[1] = 3;
656 ctrl->timC_offset[2] = 3;
657 ctrl->reg_c14_offset = 8;
658 ctrl->reg_5064b0 = 0x10d;
659 ctrl->reg_320c_range_threshold = 17;
660 } else {
661 ctrl->tCK = TCK_400MHZ;
662 ctrl->edge_offset[0] = 6;
663 ctrl->edge_offset[1] = 2;
664 ctrl->edge_offset[2] = 2;
665 ctrl->timC_offset[0] = 6;
666 ctrl->timC_offset[1] = 2;
667 ctrl->timC_offset[2] = 2;
668 ctrl->reg_c14_offset = 8;
669 ctrl->reg_5064b0 = 0xcd;
670 ctrl->reg_320c_range_threshold = 17;
671 }
672
673 val32 = (1000 << 8) / ctrl->tCK;
674 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
675
676 /* Find CAS and CWL latencies */
677 val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK;
678 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
679 /* Find lowest supported CAS latency that satisfies the minimum value */
680 while (!((ctrl->cas_supported >> (val - 4)) & 1)
681 && (ctrl->cas_supported >> (val - 4))) {
682 val++;
683 }
684 /* Is CAS supported */
685 if (!(ctrl->cas_supported & (1 << (val - 4))))
686 printk(BIOS_DEBUG, "CAS not supported\n");
687 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
688 ctrl->CAS = val;
689 ctrl->CWL = get_CWL(ctrl->CAS);
690 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
691
692 /* Find tRCD */
693 ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK;
694 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
695
696 ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK;
697 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
698
699 /* Find tRAS */
700 ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK;
701 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
702
703 /* Find tWR */
704 ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK;
705 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
706
707 /* Find tFAW */
708 ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK;
709 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
710
711 /* Find tRRD */
712 ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK;
713 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
714
715 /* Find tRTP */
716 ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK;
717 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
718
719 /* Find tWTR */
720 ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK;
721 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
722
723 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
724 ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK;
725 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
726
727 ctrl->tREFI = get_REFI(ctrl->tCK);
728 ctrl->tMOD = get_MOD(ctrl->tCK);
729 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
730 ctrl->tWLO = get_WLO(ctrl->tCK);
731 ctrl->tCKE = get_CKE(ctrl->tCK);
732 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
733 ctrl->tXP = get_XP(ctrl->tCK);
734 ctrl->tAONPD = get_AONPD(ctrl->tCK);
735}
736
737static void dram_freq(ramctr_timing * ctrl)
738{
739 if (ctrl->tCK > TCK_400MHZ) {
740 printk (BIOS_ERR, "DRAM frequency is under lowest supported frequency (400 MHz). Increasing to 400 MHz as last resort");
741 ctrl->tCK = TCK_400MHZ;
742 }
743 while (1) {
744 u8 val2;
745 u32 reg1 = 0;
746
747 /* Step 1 - Set target PCU frequency */
748
749 if (ctrl->tCK <= TCK_1066MHZ) {
750 ctrl->tCK = TCK_1066MHZ;
751 } else if (ctrl->tCK <= TCK_933MHZ) {
752 ctrl->tCK = TCK_933MHZ;
753 } else if (ctrl->tCK <= TCK_800MHZ) {
754 ctrl->tCK = TCK_800MHZ;
755 } else if (ctrl->tCK <= TCK_666MHZ) {
756 ctrl->tCK = TCK_666MHZ;
757 } else if (ctrl->tCK <= TCK_533MHZ) {
758 ctrl->tCK = TCK_533MHZ;
759 } else if (ctrl->tCK <= TCK_400MHZ) {
760 ctrl->tCK = TCK_400MHZ;
761 } else {
762 die ("No lock frequency found");
763 }
764
765 /* Frequency mulitplier. */
766 u32 FRQ = get_FRQ(ctrl->tCK);
767
768 /* Step 2 - Select frequency in the MCU */
769 reg1 = FRQ;
770 reg1 |= 0x80000000; // set running bit
771 MCHBAR32(0x5e00) = reg1;
772 while (reg1 & 0x80000000) {
773 printk(BIOS_DEBUG, " PLL busy...");
774 reg1 = MCHBAR32(0x5e00);
775 }
776 printk(BIOS_DEBUG, "done\n");
777
778 /* Step 3 - Verify lock frequency */
779 reg1 = MCHBAR32(0x5e04);
780 val2 = (u8) reg1;
781 if (val2 >= FRQ) {
782 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
783 (1000 << 8) / ctrl->tCK);
784 return;
785 }
786 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
787 ctrl->tCK++;
788 }
789}
790
791static void dram_xover(ramctr_timing * ctrl)
792{
793 u32 reg;
794 int channel;
795
796 FOR_ALL_CHANNELS {
797 // enable xover clk
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100798 reg = get_XOVER_CLK(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100799 printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
800 reg);
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100801 MCHBAR32(channel * 0x100 + 0xc14) = reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700802
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100803 // enable xover ctl & xover cmd
804 reg = get_XOVER_CMD(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100805 printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
806 reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700807 MCHBAR32(0x100 * channel + 0x320c) = reg;
808 }
809}
810
811static void dram_timing_regs(ramctr_timing * ctrl)
812{
813 u32 reg, addr, val32, cpu, stretch;
814 struct cpuid_result cpures;
815 int channel;
816
817 FOR_ALL_CHANNELS {
818 // DBP
819 reg = 0;
820 reg |= ctrl->tRCD;
821 reg |= (ctrl->tRP << 4);
822 reg |= (ctrl->CAS << 8);
823 reg |= (ctrl->CWL << 12);
824 reg |= (ctrl->tRAS << 16);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100825 printram("DBP [%x] = %x\n", 0x400 * channel + 0x4000, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700826 MCHBAR32(0x400 * channel + 0x4000) = reg;
827
828 // RAP
829 reg = 0;
830 reg |= ctrl->tRRD;
831 reg |= (ctrl->tRTP << 4);
832 reg |= (ctrl->tCKE << 8);
833 reg |= (ctrl->tWTR << 12);
834 reg |= (ctrl->tFAW << 16);
835 reg |= (ctrl->tWR << 24);
836 reg |= (3 << 30);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100837 printram("RAP [%x] = %x\n", 0x400 * channel + 0x4004, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700838 MCHBAR32(0x400 * channel + 0x4004) = reg;
839
840 // OTHP
841 addr = 0x400 * channel + 0x400c;
842 reg = 0;
843 reg |= ctrl->tXPDLL;
844 reg |= (ctrl->tXP << 5);
845 reg |= (ctrl->tAONPD << 8);
846 reg |= 0xa0000;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100847 printram("OTHP [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700848 MCHBAR32(addr) = reg;
849
850 MCHBAR32(0x400 * channel + 0x4014) = 0;
851
852 MCHBAR32(addr) |= 0x00020000;
853
854 // ODT stretch
855 reg = 0;
856
857 cpures = cpuid(0);
858 cpu = cpures.eax;
859 if (IS_IVY_CPU(cpu)
860 || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) {
861 stretch = 2;
862 addr = 0x400 * channel + 0x400c;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100863 printram("ODT stretch [%x] = %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700864 0x400 * channel + 0x400c, reg);
865 reg = MCHBAR32(addr);
866
867 if (((ctrl->rankmap[channel] & 3) == 0)
868 || (ctrl->rankmap[channel] & 0xc) == 0) {
869
870 // Rank 0 - operate on rank 2
871 reg = (reg & ~0xc0000) | (stretch << 18);
872
873 // Rank 2 - operate on rank 0
874 reg = (reg & ~0x30000) | (stretch << 16);
875
Patrick Rudolpha649a542016-01-17 18:32:06 +0100876 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700877 MCHBAR32(addr) = reg;
878 }
879
880 } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) {
881 stretch = 3;
882 addr = 0x400 * channel + 0x401c;
883 reg = MCHBAR32(addr);
884
885 if (((ctrl->rankmap[channel] & 3) == 0)
886 || (ctrl->rankmap[channel] & 0xc) == 0) {
887
888 // Rank 0 - operate on rank 2
889 reg = (reg & ~0x3000) | (stretch << 12);
890
891 // Rank 2 - operate on rank 0
892 reg = (reg & ~0xc00) | (stretch << 10);
893
Patrick Rudolpha649a542016-01-17 18:32:06 +0100894 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700895 MCHBAR32(addr) = reg;
896 }
897 } else {
898 stretch = 0;
899 }
900
901 // REFI
902 reg = 0;
903 val32 = ctrl->tREFI;
904 reg = (reg & ~0xffff) | val32;
905 val32 = ctrl->tRFC;
906 reg = (reg & ~0x1ff0000) | (val32 << 16);
907 val32 = (u32) (ctrl->tREFI * 9) / 1024;
908 reg = (reg & ~0xfe000000) | (val32 << 25);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100909 printram("REFI [%x] = %x\n", 0x400 * channel + 0x4298,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700910 reg);
911 MCHBAR32(0x400 * channel + 0x4298) = reg;
912
913 MCHBAR32(0x400 * channel + 0x4294) |= 0xff;
914
915 // SRFTP
916 reg = 0;
917 val32 = tDLLK;
918 reg = (reg & ~0xfff) | val32;
919 val32 = ctrl->tXSOffset;
920 reg = (reg & ~0xf000) | (val32 << 12);
921 val32 = tDLLK - ctrl->tXSOffset;
922 reg = (reg & ~0x3ff0000) | (val32 << 16);
923 val32 = ctrl->tMOD - 8;
924 reg = (reg & ~0xf0000000) | (val32 << 28);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100925 printram("SRFTP [%x] = %x\n", 0x400 * channel + 0x42a4,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700926 reg);
927 MCHBAR32(0x400 * channel + 0x42a4) = reg;
928 }
929}
930
931static void dram_dimm_mapping(dimm_info * info, ramctr_timing * ctrl)
932{
933 u32 reg, val32;
934 int channel;
935
936 FOR_ALL_CHANNELS {
937 dimm_attr *dimmA = 0;
938 dimm_attr *dimmB = 0;
939 reg = 0;
940 val32 = 0;
941 if (info->dimm[channel][0].size_mb >=
942 info->dimm[channel][1].size_mb) {
943 // dimm 0 is bigger, set it to dimmA
944 dimmA = &info->dimm[channel][0];
945 dimmB = &info->dimm[channel][1];
946 reg |= (0 << 16);
947 } else {
948 // dimm 1 is bigger, set it to dimmA
949 dimmA = &info->dimm[channel][1];
950 dimmB = &info->dimm[channel][0];
951 reg |= (1 << 16);
952 }
953 // dimmA
954 if (dimmA && (dimmA->ranks > 0)) {
955 val32 = dimmA->size_mb / 256;
956 reg = (reg & ~0xff) | val32;
957 val32 = dimmA->ranks - 1;
958 reg = (reg & ~0x20000) | (val32 << 17);
959 val32 = (dimmA->width / 8) - 1;
960 reg = (reg & ~0x80000) | (val32 << 19);
961 }
962 // dimmB
963 if (dimmB && (dimmB->ranks > 0)) {
964 val32 = dimmB->size_mb / 256;
965 reg = (reg & ~0xff00) | (val32 << 8);
966 val32 = dimmB->ranks - 1;
967 reg = (reg & ~0x40000) | (val32 << 18);
968 val32 = (dimmB->width / 8) - 1;
969 reg = (reg & ~0x100000) | (val32 << 20);
970 }
971 reg = (reg & ~0x200000) | (1 << 21); // rank interleave
972 reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave
973
974 // Save MAD-DIMM register
975 if ((dimmA && (dimmA->ranks > 0))
976 || (dimmB && (dimmB->ranks > 0))) {
977 ctrl->mad_dimm[channel] = reg;
978 } else {
979 ctrl->mad_dimm[channel] = 0;
980 }
981 }
982}
983
984static void dram_dimm_set_mapping(ramctr_timing * ctrl)
985{
986 int channel;
987 FOR_ALL_CHANNELS {
988 MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
989 }
990}
991
992static void dram_zones(ramctr_timing * ctrl, int training)
993{
994 u32 reg, ch0size, ch1size;
995 u8 val;
996 reg = 0;
997 val = 0;
998 if (training) {
999 ch0size = ctrl->channel_size_mb[0] ? 256 : 0;
1000 ch1size = ctrl->channel_size_mb[1] ? 256 : 0;
1001 } else {
1002 ch0size = ctrl->channel_size_mb[0];
1003 ch1size = ctrl->channel_size_mb[1];
1004 }
1005
1006 if (ch0size >= ch1size) {
1007 reg = MCHBAR32(0x5014);
1008 val = ch1size / 256;
1009 reg = (reg & ~0xff000000) | val << 24;
1010 reg = (reg & ~0xff0000) | (2 * val) << 16;
1011 MCHBAR32(0x5014) = reg;
1012 MCHBAR32(0x5000) = 0x24;
1013 } else {
1014 reg = MCHBAR32(0x5014);
1015 val = ch0size / 256;
1016 reg = (reg & ~0xff000000) | val << 24;
1017 reg = (reg & ~0xff0000) | (2 * val) << 16;
1018 MCHBAR32(0x5014) = reg;
1019 MCHBAR32(0x5000) = 0x21;
1020 }
1021}
1022
1023static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
1024{
1025 u32 reg, val, reclaim;
1026 u32 tom, gfxstolen, gttsize;
1027 size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase,
1028 tsegbase, mestolenbase;
1029 size_t tsegbasedelta, remapbase, remaplimit;
1030 uint16_t ggc;
1031
1032 mmiosize = 0x400;
1033
1034 ggc = pci_read_config16(NORTHBRIDGE, GGC);
1035 if (!(ggc & 2)) {
1036 gfxstolen = ((ggc >> 3) & 0x1f) * 32;
1037 gttsize = ((ggc >> 8) & 0x3);
1038 } else {
1039 gfxstolen = 0;
1040 gttsize = 0;
1041 }
1042
1043 tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
1044
1045 tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
1046
1047 mestolenbase = tom - me_uma_size;
1048
1049 toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
1050 tom - me_uma_size);
1051 gfxstolenbase = toludbase - gfxstolen;
1052 gttbase = gfxstolenbase - gttsize;
1053
1054 tsegbase = gttbase - tsegsize;
1055
1056 // Round tsegbase down to nearest address aligned to tsegsize
1057 tsegbasedelta = tsegbase & (tsegsize - 1);
1058 tsegbase &= ~(tsegsize - 1);
1059
1060 gttbase -= tsegbasedelta;
1061 gfxstolenbase -= tsegbasedelta;
1062 toludbase -= tsegbasedelta;
1063
1064 // Test if it is possible to reclaim a hole in the ram addressing
1065 if (tom - me_uma_size > toludbase) {
1066 // Reclaim is possible
1067 reclaim = 1;
1068 remapbase = MAX(4096, tom - me_uma_size);
1069 remaplimit =
1070 remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1;
1071 touudbase = remaplimit + 1;
1072 } else {
1073 // Reclaim not possible
1074 reclaim = 0;
1075 touudbase = tom - me_uma_size;
1076 }
1077
1078 // Update memory map in pci-e configuration space
Patrick Rudolpha649a542016-01-17 18:32:06 +01001079 printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001080
1081 // TOM (top of memory)
1082 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0);
1083 val = tom & 0xfff;
1084 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001085 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001086 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg);
1087
1088 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4);
1089 val = tom & 0xfffff000;
1090 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001091 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001092 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg);
1093
1094 // TOLUD (top of low used dram)
1095 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
1096 val = toludbase & 0xfff;
1097 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001098 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xbc, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001099 pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg);
1100
1101 // TOUUD LSB (top of upper usable dram)
1102 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
1103 val = touudbase & 0xfff;
1104 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001105 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001106 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg);
1107
1108 // TOUUD MSB
1109 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
1110 val = touudbase & 0xfffff000;
1111 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001112 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xac, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001113 pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg);
1114
1115 if (reclaim) {
1116 // REMAP BASE
1117 pcie_write_config32(PCI_DEV(0, 0, 0), 0x90, remapbase << 20);
1118 pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, remapbase >> 12);
1119
1120 // REMAP LIMIT
1121 pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
1122 pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
1123 }
1124 // TSEG
1125 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
1126 val = tsegbase & 0xfff;
1127 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001128 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001129 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg);
1130
1131 // GFX stolen memory
1132 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0);
1133 val = gfxstolenbase & 0xfff;
1134 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001135 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001136 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg);
1137
1138 // GTT stolen memory
1139 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4);
1140 val = gttbase & 0xfff;
1141 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001142 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001143 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
1144
1145 if (me_uma_size) {
1146 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
1147 val = (0x80000 - me_uma_size) & 0xfffff000;
1148 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001149 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x7c, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001150 pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg);
1151
1152 // ME base
1153 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70);
1154 val = mestolenbase & 0xfff;
1155 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001156 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x70, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001157 pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg);
1158
1159 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74);
1160 val = mestolenbase & 0xfffff000;
1161 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001162 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x74, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001163 pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg);
1164
1165 // ME mask
1166 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78);
1167 val = (0x80000 - me_uma_size) & 0xfff;
1168 reg = (reg & ~0xfff00000) | (val << 20);
1169 reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem
1170
1171 reg = (reg & ~0x800) | (1 << 11); // set ME memory enable
Patrick Rudolpha649a542016-01-17 18:32:06 +01001172 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x78, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001173 pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg);
1174 }
1175}
1176
1177static void dram_ioregs(ramctr_timing * ctrl)
1178{
1179 u32 reg, comp2;
1180
1181 int channel;
1182
1183 // IO clock
1184 FOR_ALL_CHANNELS {
1185 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
1186 }
1187
1188 // IO command
1189 FOR_ALL_CHANNELS {
1190 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
1191 }
1192
1193 // IO control
1194 FOR_ALL_POPULATED_CHANNELS {
1195 program_timings(ctrl, channel);
1196 }
1197
1198 // Rcomp
Patrick Rudolpha649a542016-01-17 18:32:06 +01001199 printram("RCOMP...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001200 reg = 0;
1201 while (reg == 0) {
1202 reg = MCHBAR32(0x5084) & 0x10000;
1203 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001204 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001205
1206 // Set comp2
1207 comp2 = get_COMP2(ctrl->tCK);
1208 MCHBAR32(0x3714) = comp2;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001209 printram("COMP2 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001210
1211 // Set comp1
1212 FOR_ALL_POPULATED_CHANNELS {
1213 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
1214 reg = (reg & ~0xe00) | (1 << 9); //odt
1215 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
1216 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
1217 MCHBAR32(0x1810 + channel * 0x100) = reg;
1218 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001219 printram("COMP1 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001220
Patrick Rudolpha649a542016-01-17 18:32:06 +01001221 printram("FORCE RCOMP and wait 20us...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001222 MCHBAR32(0x5f08) |= 0x100;
1223 udelay(20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001224 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001225}
1226
1227static void wait_428c(int channel)
1228{
1229 while (1) {
1230 if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
1231 return;
1232 }
1233}
1234
1235static void write_reset(ramctr_timing * ctrl)
1236{
1237 int channel, slotrank;
1238
1239 /* choose a populated channel. */
1240 channel = (ctrl->rankmap[0]) ? 0 : 1;
1241
1242 wait_428c(channel);
1243
1244 /* choose a populated rank. */
1245 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
1246
Patrick Rudolph371d2912015-10-09 13:33:25 +02001247 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001248 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1249 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01);
1250
1251 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1252 (slotrank << 24) | 0x60000);
1253
1254 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1255
1256 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001);
1257 wait_428c(channel);
1258}
1259
1260static void dram_jedecreset(ramctr_timing * ctrl)
1261{
1262 u32 reg, addr;
1263 int channel;
1264
1265 while (!(MCHBAR32(0x5084) & 0x10000)) ;
1266 do {
1267 reg = MCHBAR32(0x428c);
1268 } while ((reg & 0x14) == 0);
1269
1270 // Set state of memory controller
1271 reg = 0x112;
1272 MCHBAR32(0x5030) = reg;
1273 MCHBAR32(0x4ea0) = 0;
1274 reg |= 2; //ddr reset
1275 MCHBAR32(0x5030) = reg;
1276
1277 // Assert dimm reset signal
1278 reg = MCHBAR32(0x5030);
1279 reg &= ~0x2;
1280 MCHBAR32(0x5030) = reg;
1281
1282 // Wait 200us
1283 udelay(200);
1284
1285 // Deassert dimm reset signal
1286 MCHBAR32(0x5030) |= 2;
1287
1288 // Wait 500us
1289 udelay(500);
1290
1291 // Enable DCLK
1292 MCHBAR32(0x5030) |= 4;
1293
1294 // XXX Wait 20ns
1295 udelay(1);
1296
1297 FOR_ALL_CHANNELS {
1298 // Set valid rank CKE
1299 reg = 0;
1300 reg = (reg & ~0xf) | ctrl->rankmap[channel];
1301 addr = 0x400 * channel + 0x42a0;
1302 MCHBAR32(addr) = reg;
1303
1304 // Wait 10ns for ranks to settle
1305 //udelay(0.01);
1306
1307 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
1308 MCHBAR32(addr) = reg;
1309
1310 // Write reset using a NOP
1311 write_reset(ctrl);
1312 }
1313}
1314
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001315static odtmap get_ODT(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001316{
1317 /* Get ODT based on rankmap: */
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001318 int dimms_per_ch = (ctrl->rankmap[channel] & 1)
1319 + ((ctrl->rankmap[channel] >> 2) & 1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001320
1321 if (dimms_per_ch == 1) {
1322 return (const odtmap){60, 60};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001323 } else {
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001324 return (const odtmap){120, 30};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001325 }
1326}
1327
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001328static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001329 int reg, u32 val)
1330{
1331 wait_428c(channel);
1332
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001333 if (ctrl->rank_mirror[channel][slotrank]) {
1334 /* DDR3 Rank1 Address mirror
1335 * swap the following pins:
1336 * A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 */
1337 reg = ((reg >> 1) & 1) | ((reg << 1) & 2);
1338 val = (val & ~0x1f8) | ((val >> 1) & 0xa8)
1339 | ((val & 0xa8) << 1);
1340 }
1341
Patrick Rudolph371d2912015-10-09 13:33:25 +02001342 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001343 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000);
1344 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
1345 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1346 (slotrank << 24) | (reg << 20) | val | 0x60000);
1347 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1348
Patrick Rudolph371d2912015-10-09 13:33:25 +02001349 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001350 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000);
1351 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001);
1352 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
1353 (slotrank << 24) | (reg << 20) | val | 0x60000);
1354 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1355
Patrick Rudolph371d2912015-10-09 13:33:25 +02001356 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001357 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000);
1358 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1359 0x1001 | (ctrl->tMOD << 16));
1360 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1361 (slotrank << 24) | (reg << 20) | val | 0x60000);
1362 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1363 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
1364}
1365
1366static u32 make_mr0(ramctr_timing * ctrl, u8 rank)
1367{
1368 u16 mr0reg, mch_cas, mch_wr;
1369 static const u8 mch_wr_t[12] = { 1, 2, 3, 4, 0, 5, 0, 6, 0, 7, 0, 0 };
Patrick Rudolph371d2912015-10-09 13:33:25 +02001370
1371 /* DLL Reset - self clearing - set after CLK frequency has been changed */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001372 mr0reg = 0x100;
1373
1374 // Convert CAS to MCH register friendly
1375 if (ctrl->CAS < 12) {
1376 mch_cas = (u16) ((ctrl->CAS - 4) << 1);
1377 } else {
1378 mch_cas = (u16) (ctrl->CAS - 12);
1379 mch_cas = ((mch_cas << 1) | 0x1);
1380 }
1381
1382 // Convert tWR to MCH register friendly
1383 mch_wr = mch_wr_t[ctrl->tWR - 5];
1384
1385 mr0reg = (mr0reg & ~0x4) | (mch_cas & 0x1);
1386 mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3);
1387 mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001388
1389 // Precharge PD - Fast (desktop) 0x1 or slow (mobile) 0x0 - mostly power-saving feature
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001390 mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12);
1391 return mr0reg;
1392}
1393
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001394static void dram_mr0(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001395{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001396 write_mrreg(ctrl, channel, rank, 0,
1397 make_mr0(ctrl, rank));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001398}
1399
1400static u32 encode_odt(u32 odt)
1401{
1402 switch (odt) {
1403 case 30:
1404 return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4
1405 case 60:
1406 return (1 << 2); // RZQ/4
1407 case 120:
1408 return (1 << 6); // RZQ/2
1409 default:
1410 case 0:
1411 return 0;
1412 }
1413}
1414
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001415static u32 make_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001416{
1417 odtmap odt;
1418 u32 mr1reg;
1419
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001420 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001421 mr1reg = 0x2;
1422
1423 mr1reg |= encode_odt(odt.rttnom);
1424
1425 return mr1reg;
1426}
1427
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001428static void dram_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001429{
1430 u16 mr1reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001431
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001432 mr1reg = make_mr1(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001433
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001434 write_mrreg(ctrl, channel, rank, 1, mr1reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001435}
1436
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001437static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001438{
1439 u16 pasr, cwl, mr2reg;
1440 odtmap odt;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001441 int srt;
1442
1443 pasr = 0;
1444 cwl = ctrl->CWL - 5;
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001445 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001446
1447 srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh;
1448
1449 mr2reg = 0;
1450 mr2reg = (mr2reg & ~0x7) | pasr;
1451 mr2reg = (mr2reg & ~0x38) | (cwl << 3);
1452 mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6);
1453 mr2reg = (mr2reg & ~0x80) | (srt << 7);
1454 mr2reg |= (odt.rttwr / 60) << 9;
1455
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001456 write_mrreg(ctrl, channel, rank, 2, mr2reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001457}
1458
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001459static void dram_mr3(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001460{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001461 write_mrreg(ctrl, channel, rank, 3, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001462}
1463
1464static void dram_mrscommands(ramctr_timing * ctrl)
1465{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001466 u8 slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001467 u32 reg, addr;
1468 int channel;
1469
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001470 FOR_ALL_POPULATED_CHANNELS {
1471 FOR_ALL_POPULATED_RANKS {
1472 // MR2
1473 dram_mr2(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001474
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001475 // MR3
1476 dram_mr3(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001477
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001478 // MR1
1479 dram_mr1(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001480
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001481 // MR0
1482 dram_mr0(ctrl, slotrank, channel);
1483 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001484 }
1485
Patrick Rudolph371d2912015-10-09 13:33:25 +02001486 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001487 write32(DEFAULT_MCHBAR + 0x4e20, 0x7);
1488 write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001);
1489 write32(DEFAULT_MCHBAR + 0x4e00, 0x60002);
1490 write32(DEFAULT_MCHBAR + 0x4e10, 0);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001491
1492 /* DRAM command ZQCL */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001493 write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003);
1494 write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001);
1495 write32(DEFAULT_MCHBAR + 0x4e04, 0x60400);
1496 write32(DEFAULT_MCHBAR + 0x4e14, 0x288);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001497
1498 /* execute command queue on all channels ? */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001499 write32(DEFAULT_MCHBAR + 0x4e84, 0x40004);
1500
1501 // Drain
1502 FOR_ALL_CHANNELS {
1503 // Wait for ref drained
1504 wait_428c(channel);
1505 }
1506
1507 // Refresh enable
1508 MCHBAR32(0x5030) |= 8;
1509
1510 FOR_ALL_POPULATED_CHANNELS {
1511 addr = 0x400 * channel + 0x4020;
1512 reg = MCHBAR32(addr);
1513 reg &= ~0x200000;
1514 MCHBAR32(addr) = reg;
1515
1516 wait_428c(channel);
1517
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001518 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001519
1520 // Drain
1521 wait_428c(channel);
1522
Patrick Rudolph371d2912015-10-09 13:33:25 +02001523 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001524 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1525 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
1526 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001527 (slotrank << 24) | 0x60000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001528 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
1529 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1);
1530
1531 // Drain
1532 wait_428c(channel);
1533 }
1534}
1535
1536const u32 lane_registers[] = {
1537 0x0000, 0x0200, 0x0400, 0x0600,
1538 0x1000, 0x1200, 0x1400, 0x1600,
1539 0x0800
1540};
1541
1542static void program_timings(ramctr_timing * ctrl, int channel)
1543{
1544 u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028;
1545 int lane;
1546 int slotrank, slot;
1547 int full_shift = 0;
1548 u16 slot320c[NUM_SLOTS];
1549
1550 FOR_ALL_POPULATED_RANKS {
1551 if (full_shift < -ctrl->timings[channel][slotrank].val_320c)
1552 full_shift = -ctrl->timings[channel][slotrank].val_320c;
1553 }
1554
1555 for (slot = 0; slot < NUM_SLOTS; slot++)
1556 switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) {
1557 case 0:
1558 default:
1559 slot320c[slot] = 0x7f;
1560 break;
1561 case 1:
1562 slot320c[slot] =
1563 ctrl->timings[channel][2 * slot + 0].val_320c +
1564 full_shift;
1565 break;
1566 case 2:
1567 slot320c[slot] =
1568 ctrl->timings[channel][2 * slot + 1].val_320c +
1569 full_shift;
1570 break;
1571 case 3:
1572 slot320c[slot] =
1573 (ctrl->timings[channel][2 * slot].val_320c +
1574 ctrl->timings[channel][2 * slot +
1575 1].val_320c) / 2 +
1576 full_shift;
1577 break;
1578 }
1579
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001580 /* enable CMD XOVER */
1581 reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001582 reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
1583 reg32 |= (slot320c[1] & 0x7f) << 18;
1584 reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
1585
1586 MCHBAR32(0x320c + 0x100 * channel) = reg32;
1587
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001588 /* enable CLK XOVER */
1589 reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001590 reg_c18 = 0;
1591
1592 FOR_ALL_POPULATED_RANKS {
1593 int shift =
1594 ctrl->timings[channel][slotrank].val_320c + full_shift;
1595 int offset_val_c14;
1596 if (shift < 0)
1597 shift = 0;
1598 offset_val_c14 = ctrl->reg_c14_offset + shift;
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001599 /* set CLK phase shift */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001600 reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
1601 reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
1602 }
1603
1604 MCHBAR32(0xc14 + channel * 0x100) = reg_c14;
1605 MCHBAR32(0xc18 + channel * 0x100) = reg_c18;
1606
1607 reg_4028 = MCHBAR32(0x4028 + 0x400 * channel);
1608 reg_4028 &= 0xffff0000;
1609
1610 reg_4024 = 0;
1611
1612 FOR_ALL_POPULATED_RANKS {
1613 int post_timA_min_high = 7, post_timA_max_high = 0;
1614 int pre_timA_min_high = 7, pre_timA_max_high = 0;
1615 int shift_402x = 0;
1616 int shift =
1617 ctrl->timings[channel][slotrank].val_320c + full_shift;
1618
1619 if (shift < 0)
1620 shift = 0;
1621
1622 FOR_ALL_LANES {
1623 if (post_timA_min_high >
1624 ((ctrl->timings[channel][slotrank].lanes[lane].
1625 timA + shift) >> 6))
1626 post_timA_min_high =
1627 ((ctrl->timings[channel][slotrank].
1628 lanes[lane].timA + shift) >> 6);
1629 if (pre_timA_min_high >
1630 (ctrl->timings[channel][slotrank].lanes[lane].
1631 timA >> 6))
1632 pre_timA_min_high =
1633 (ctrl->timings[channel][slotrank].
1634 lanes[lane].timA >> 6);
1635 if (post_timA_max_high <
1636 ((ctrl->timings[channel][slotrank].lanes[lane].
1637 timA + shift) >> 6))
1638 post_timA_max_high =
1639 ((ctrl->timings[channel][slotrank].
1640 lanes[lane].timA + shift) >> 6);
1641 if (pre_timA_max_high <
1642 (ctrl->timings[channel][slotrank].lanes[lane].
1643 timA >> 6))
1644 pre_timA_max_high =
1645 (ctrl->timings[channel][slotrank].
1646 lanes[lane].timA >> 6);
1647 }
1648
1649 if (pre_timA_max_high - pre_timA_min_high <
1650 post_timA_max_high - post_timA_min_high)
1651 shift_402x = +1;
1652 else if (pre_timA_max_high - pre_timA_min_high >
1653 post_timA_max_high - post_timA_min_high)
1654 shift_402x = -1;
1655
1656 reg_4028 |=
1657 (ctrl->timings[channel][slotrank].val_4028 + shift_402x -
1658 post_timA_min_high) << (4 * slotrank);
1659 reg_4024 |=
1660 (ctrl->timings[channel][slotrank].val_4024 +
1661 shift_402x) << (8 * slotrank);
1662
1663 FOR_ALL_LANES {
1664 MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel +
1665 4 * slotrank)
1666 =
1667 (((ctrl->timings[channel][slotrank].lanes[lane].
1668 timA + shift) & 0x3f)
1669 |
1670 ((ctrl->timings[channel][slotrank].lanes[lane].
1671 rising + shift) << 8)
1672 |
1673 (((ctrl->timings[channel][slotrank].lanes[lane].
1674 timA + shift -
1675 (post_timA_min_high << 6)) & 0x1c0) << 10)
Patrick Rudolph0188b132016-02-10 19:16:34 +01001676 | ((ctrl->timings[channel][slotrank].lanes[lane].
1677 falling + shift) << 20));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001678
1679 MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel +
1680 4 * slotrank)
1681 =
1682 (((ctrl->timings[channel][slotrank].lanes[lane].
1683 timC + shift) & 0x3f)
1684 |
1685 (((ctrl->timings[channel][slotrank].lanes[lane].
1686 timB + shift) & 0x3f) << 8)
1687 |
1688 (((ctrl->timings[channel][slotrank].lanes[lane].
1689 timB + shift) & 0x1c0) << 9)
1690 |
1691 (((ctrl->timings[channel][slotrank].lanes[lane].
1692 timC + shift) & 0x40) << 13));
1693 }
1694 }
1695 MCHBAR32(0x4024 + 0x400 * channel) = reg_4024;
1696 MCHBAR32(0x4028 + 0x400 * channel) = reg_4028;
1697}
1698
1699static void test_timA(ramctr_timing * ctrl, int channel, int slotrank)
1700{
1701 wait_428c(channel);
1702
Patrick Rudolph371d2912015-10-09 13:33:25 +02001703 /* DRAM command MRS
1704 * write MR3 MPR enable
1705 * in this mode only RD and RDA are allowed
1706 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001707 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
1708 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1709 (0xc01 | (ctrl->tMOD << 16)));
1710 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1711 (slotrank << 24) | 0x360004);
1712 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1713
Patrick Rudolph371d2912015-10-09 13:33:25 +02001714 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001715 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
1716 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01);
1717 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24));
1718 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1719
Patrick Rudolph371d2912015-10-09 13:33:25 +02001720 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001721 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
1722 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1723 0x100f | ((ctrl->CAS + 36) << 16));
1724 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1725 (slotrank << 24) | 0x60000);
1726 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1727
Patrick Rudolph371d2912015-10-09 13:33:25 +02001728 /* DRAM command MRS
1729 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001730 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
1731 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
1732 (0xc01 | (ctrl->tMOD << 16)));
1733 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
1734 (slotrank << 24) | 0x360000);
1735 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
1736
1737 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
1738
1739 wait_428c(channel);
1740}
1741
1742static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank,
1743 int lane)
1744{
1745 u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA;
1746 return ((read32
1747 (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 +
1748 ((timA / 32) & 1) * 4)
1749 >> (timA % 32)) & 1);
1750}
1751
1752struct run {
1753 int middle;
1754 int end;
1755 int start;
1756 int all;
1757 int length;
1758};
1759
1760static struct run get_longest_zero_run(int *seq, int sz)
1761{
1762 int i, ls;
1763 int bl = 0, bs = 0;
1764 struct run ret;
1765
1766 ls = 0;
1767 for (i = 0; i < 2 * sz; i++)
1768 if (seq[i % sz]) {
1769 if (i - ls > bl) {
1770 bl = i - ls;
1771 bs = ls;
1772 }
1773 ls = i + 1;
1774 }
1775 if (bl == 0) {
1776 ret.middle = sz / 2;
1777 ret.start = 0;
1778 ret.end = sz;
1779 ret.all = 1;
1780 return ret;
1781 }
1782
1783 ret.start = bs % sz;
1784 ret.end = (bs + bl - 1) % sz;
1785 ret.middle = (bs + (bl - 1) / 2) % sz;
1786 ret.length = bl;
1787 ret.all = 0;
1788
1789 return ret;
1790}
1791
1792static void discover_timA_coarse(ramctr_timing * ctrl, int channel,
1793 int slotrank, int *upperA)
1794{
1795 int timA;
1796 int statistics[NUM_LANES][128];
1797 int lane;
1798
1799 for (timA = 0; timA < 128; timA++) {
1800 FOR_ALL_LANES {
1801 ctrl->timings[channel][slotrank].lanes[lane].timA = timA;
1802 }
1803 program_timings(ctrl, channel);
1804
1805 test_timA(ctrl, channel, slotrank);
1806
1807 FOR_ALL_LANES {
1808 statistics[lane][timA] =
1809 !does_lane_work(ctrl, channel, slotrank, lane);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001810 printram("Astat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001811 channel, slotrank, lane, timA,
1812 statistics[lane][timA]);
1813 }
1814 }
1815 FOR_ALL_LANES {
1816 struct run rn = get_longest_zero_run(statistics[lane], 128);
1817 ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle;
1818 upperA[lane] = rn.end;
1819 if (upperA[lane] < rn.middle)
1820 upperA[lane] += 128;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001821 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001822 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001823 printram("Aend: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001824 lane, upperA[lane]);
1825 }
1826}
1827
1828static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
1829 int *upperA)
1830{
1831 int timA_delta;
1832 int statistics[NUM_LANES][51];
1833 int lane, i;
1834
1835 memset(statistics, 0, sizeof(statistics));
1836
1837 for (timA_delta = -25; timA_delta <= 25; timA_delta++) {
1838 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
1839 timA = upperA[lane] + timA_delta + 0x40;
1840 program_timings(ctrl, channel);
1841
1842 for (i = 0; i < 100; i++) {
1843 test_timA(ctrl, channel, slotrank);
1844 FOR_ALL_LANES {
1845 statistics[lane][timA_delta + 25] +=
1846 does_lane_work(ctrl, channel, slotrank,
1847 lane);
1848 }
1849 }
1850 }
1851 FOR_ALL_LANES {
1852 int last_zero, first_all;
1853
1854 for (last_zero = -25; last_zero <= 25; last_zero++)
1855 if (statistics[lane][last_zero + 25])
1856 break;
1857 last_zero--;
1858 for (first_all = -25; first_all <= 25; first_all++)
1859 if (statistics[lane][first_all + 25] == 100)
1860 break;
1861
1862 printram("lane %d: %d, %d\n", lane, last_zero,
1863 first_all);
1864
1865 ctrl->timings[channel][slotrank].lanes[lane].timA =
1866 (last_zero + first_all) / 2 + upperA[lane];
Patrick Rudolpha649a542016-01-17 18:32:06 +01001867 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001868 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
1869 }
1870}
1871
1872static void discover_402x(ramctr_timing * ctrl, int channel, int slotrank,
1873 int *upperA)
1874{
1875 int works[NUM_LANES];
1876 int lane;
1877 while (1) {
1878 int all_works = 1, some_works = 0;
1879 program_timings(ctrl, channel);
1880 test_timA(ctrl, channel, slotrank);
1881 FOR_ALL_LANES {
1882 works[lane] =
1883 !does_lane_work(ctrl, channel, slotrank, lane);
1884 if (works[lane])
1885 some_works = 1;
1886 else
1887 all_works = 0;
1888 }
1889 if (all_works)
1890 return;
1891 if (!some_works) {
1892 if (ctrl->timings[channel][slotrank].val_4024 < 2)
1893 die("402x discovery failed");
1894 ctrl->timings[channel][slotrank].val_4024 -= 2;
1895 printram("4024 -= 2;\n");
1896 continue;
1897 }
1898 ctrl->timings[channel][slotrank].val_4028 += 2;
1899 printram("4028 += 2;\n");
1900 if (ctrl->timings[channel][slotrank].val_4028 >= 0x10)
1901 die("402x discovery failed");
1902 FOR_ALL_LANES if (works[lane]) {
1903 ctrl->timings[channel][slotrank].lanes[lane].timA +=
1904 128;
1905 upperA[lane] += 128;
1906 printram("increment %d, %d, %d\n", channel,
1907 slotrank, lane);
1908 }
1909 }
1910}
1911
1912struct timA_minmax {
1913 int timA_min_high, timA_max_high;
1914};
1915
1916static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1917 struct timA_minmax *mnmx)
1918{
1919 int lane;
1920 mnmx->timA_min_high = 7;
1921 mnmx->timA_max_high = 0;
1922
1923 FOR_ALL_LANES {
1924 if (mnmx->timA_min_high >
1925 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1926 mnmx->timA_min_high =
1927 (ctrl->timings[channel][slotrank].lanes[lane].
1928 timA >> 6);
1929 if (mnmx->timA_max_high <
1930 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1931 mnmx->timA_max_high =
1932 (ctrl->timings[channel][slotrank].lanes[lane].
1933 timA >> 6);
1934 }
1935}
1936
1937static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1938 struct timA_minmax *mnmx)
1939{
1940 struct timA_minmax post;
1941 int shift_402x = 0;
1942
1943 /* Get changed maxima. */
1944 pre_timA_change(ctrl, channel, slotrank, &post);
1945
1946 if (mnmx->timA_max_high - mnmx->timA_min_high <
1947 post.timA_max_high - post.timA_min_high)
1948 shift_402x = +1;
1949 else if (mnmx->timA_max_high - mnmx->timA_min_high >
1950 post.timA_max_high - post.timA_min_high)
1951 shift_402x = -1;
1952 else
1953 shift_402x = 0;
1954
1955 ctrl->timings[channel][slotrank].val_4028 += shift_402x;
1956 ctrl->timings[channel][slotrank].val_4024 += shift_402x;
1957 printram("4024 += %d;\n", shift_402x);
1958 printram("4028 += %d;\n", shift_402x);
1959}
1960
Patrick Rudolph371d2912015-10-09 13:33:25 +02001961/* Compensate the skew between DQS and DQs.
1962 * To ease PCB design a small skew between Data Strobe signals and
1963 * Data Signals is allowed.
1964 * The controller has to measure and compensate this skew for every byte-lane.
1965 * By delaying either all DQs signals or DQS signal, a full phase
1966 * shift can be introduced.
1967 * It is assumed that one byte-lane's DQs signals have the same routing delay.
1968 *
1969 * To measure the actual skew, the DRAM is placed in "read leveling" mode.
1970 * In read leveling mode the DRAM-chip outputs an alternating periodic pattern.
1971 * The memory controller iterates over all possible values to do a full phase shift
1972 * and issues read commands.
1973 * With DQS and DQs in phase the data read is expected to alternate on every byte:
1974 * 0xFF 0x00 0xFF ...
1975 * Once the controller has detected this pattern a bit in the result register is
1976 * set for the current phase shift.
1977 */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001978static void read_training(ramctr_timing * ctrl)
1979{
1980 int channel, slotrank, lane;
1981
1982 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001983 int all_high, some_high;
1984 int upperA[NUM_LANES];
1985 struct timA_minmax mnmx;
1986
1987 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001988
1989 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001990 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
1991 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1992 0xc01 | (ctrl->tRP << 16));
1993 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1994 (slotrank << 24) | 0x60400);
1995 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1996 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
1997
1998 write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001);
1999
2000 ctrl->timings[channel][slotrank].val_4028 = 4;
2001 ctrl->timings[channel][slotrank].val_4024 = 55;
2002 program_timings(ctrl, channel);
2003
2004 discover_timA_coarse(ctrl, channel, slotrank, upperA);
2005
2006 all_high = 1;
2007 some_high = 0;
2008 FOR_ALL_LANES {
2009 if (ctrl->timings[channel][slotrank].lanes[lane].
2010 timA >= 0x40)
2011 some_high = 1;
2012 else
2013 all_high = 0;
2014 }
2015
2016 if (all_high) {
2017 ctrl->timings[channel][slotrank].val_4028--;
2018 printram("4028--;\n");
2019 FOR_ALL_LANES {
2020 ctrl->timings[channel][slotrank].lanes[lane].
2021 timA -= 0x40;
2022 upperA[lane] -= 0x40;
2023
2024 }
2025 } else if (some_high) {
2026 ctrl->timings[channel][slotrank].val_4024++;
2027 ctrl->timings[channel][slotrank].val_4028++;
2028 printram("4024++;\n");
2029 printram("4028++;\n");
2030 }
2031
2032 program_timings(ctrl, channel);
2033
2034 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2035
2036 discover_402x(ctrl, channel, slotrank, upperA);
2037
2038 post_timA_change(ctrl, channel, slotrank, &mnmx);
2039 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2040
2041 discover_timA_fine(ctrl, channel, slotrank, upperA);
2042
2043 post_timA_change(ctrl, channel, slotrank, &mnmx);
2044 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2045
2046 FOR_ALL_LANES {
2047 ctrl->timings[channel][slotrank].lanes[lane].timA -= mnmx.timA_min_high * 0x40;
2048 }
2049 ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high;
2050 printram("4028 -= %d;\n", mnmx.timA_min_high);
2051
2052 post_timA_change(ctrl, channel, slotrank, &mnmx);
2053
2054 printram("4/8: %d, %d, %x, %x\n", channel, slotrank,
2055 ctrl->timings[channel][slotrank].val_4024,
2056 ctrl->timings[channel][slotrank].val_4028);
2057
Patrick Rudolpha649a542016-01-17 18:32:06 +01002058 printram("final results:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002059 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01002060 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002061 lane,
2062 ctrl->timings[channel][slotrank].lanes[lane].timA);
2063
2064 write32(DEFAULT_MCHBAR + 0x3400, 0);
2065
Patrick Rudolph9b515682015-10-09 13:43:51 +02002066 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002067 }
2068
2069 FOR_ALL_POPULATED_CHANNELS {
2070 program_timings(ctrl, channel);
2071 }
2072 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2073 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
2074 + 4 * lane, 0);
2075 }
2076}
2077
2078static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
2079{
2080 int lane;
2081
2082 FOR_ALL_LANES {
2083 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0);
2084 read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane);
2085 }
2086
2087 wait_428c(channel);
2088
Patrick Rudolph371d2912015-10-09 13:33:25 +02002089 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002090 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2091 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2092 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
2093 | 4 | (ctrl->tRCD << 16));
2094
2095 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2096 (slotrank << 24) | (6 << 16));
2097
2098 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
2099
Patrick Rudolph371d2912015-10-09 13:33:25 +02002100 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002101 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2102 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001);
2103 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2104 (slotrank << 24) | 8);
2105 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2106
Patrick Rudolph371d2912015-10-09 13:33:25 +02002107 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002108 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2109 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4);
2110 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2111 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2112
Patrick Rudolph371d2912015-10-09 13:33:25 +02002113 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002114 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2115 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2116 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2117 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2118 (slotrank << 24) | 8);
2119 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2120
2121 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2122
2123 wait_428c(channel);
2124
Patrick Rudolph371d2912015-10-09 13:33:25 +02002125 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002126 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2127 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2128 0xc01 | (ctrl->tRP << 16));
2129 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2130 (slotrank << 24) | 0x60400);
2131 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2132
Patrick Rudolph371d2912015-10-09 13:33:25 +02002133 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002134 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2135 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2136 (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10)
2137 | 8 | (ctrl->CAS << 16));
2138
2139 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2140 (slotrank << 24) | 0x60000);
2141
2142 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244);
2143
Patrick Rudolph371d2912015-10-09 13:33:25 +02002144 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002145 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2146 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2147 0x40011f4 | (max(ctrl->tRTP, 8) << 16));
2148 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2149 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2150
Patrick Rudolph371d2912015-10-09 13:33:25 +02002151 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002152 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2153 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2154 0xc01 | (ctrl->tRP << 16));
2155 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2156 (slotrank << 24) | 0x60400);
2157 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2158 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2159 wait_428c(channel);
2160}
2161
2162static void discover_timC(ramctr_timing * ctrl, int channel, int slotrank)
2163{
2164 int timC;
2165 int statistics[NUM_LANES][MAX_TIMC + 1];
2166 int lane;
2167
2168 wait_428c(channel);
2169
Patrick Rudolph371d2912015-10-09 13:33:25 +02002170 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002171 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2172 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2173 0xc01 | (ctrl->tRP << 16));
2174 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2175 (slotrank << 24) | 0x60400);
2176 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2177 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2178
2179 for (timC = 0; timC <= MAX_TIMC; timC++) {
2180 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
2181 timC = timC;
2182 program_timings(ctrl, channel);
2183
2184 test_timC(ctrl, channel, slotrank);
2185
2186 FOR_ALL_LANES {
2187 statistics[lane][timC] =
2188 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2189 0x400 * channel);
2190 printram("Cstat: %d, %d, %d, %x, %x\n",
2191 channel, slotrank, lane, timC,
2192 statistics[lane][timC]);
2193 }
2194 }
2195 FOR_ALL_LANES {
2196 struct run rn =
2197 get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
2198 ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
2199 if (rn.all)
Patrick Rudolpha649a542016-01-17 18:32:06 +01002200 die("timC discovery failed");
2201 printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002202 lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
2203 }
2204}
2205
2206static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
2207{
2208 int channel, ret = 0;
2209 FOR_ALL_POPULATED_CHANNELS if (channel < target_channel)
2210 ret++;
2211 return ret;
2212}
2213
2214static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b)
2215{
2216 unsigned j;
2217 unsigned channel_offset =
2218 get_precedening_channels(ctrl, channel) * 0x40;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002219 for (j = 0; j < 16; j++)
2220 write32((void *)(0x04000000 + channel_offset + 4 * j), j & 2 ? b : a);
2221 sfence();
2222}
2223
2224static int num_of_channels(const ramctr_timing * ctrl)
2225{
2226 int ret = 0;
2227 int channel;
2228 FOR_ALL_POPULATED_CHANNELS ret++;
2229 return ret;
2230}
2231
2232static void fill_pattern1(ramctr_timing * ctrl, int channel)
2233{
2234 unsigned j;
2235 unsigned channel_offset =
2236 get_precedening_channels(ctrl, channel) * 0x40;
2237 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2238 for (j = 0; j < 16; j++)
2239 write32((void *)(0x04000000 + channel_offset + j * 4), 0xffffffff);
2240 for (j = 0; j < 16; j++)
2241 write32((void *)(0x04000000 + channel_offset + channel_step + j * 4), 0);
2242 sfence();
2243}
2244
2245static void precharge(ramctr_timing * ctrl)
2246{
2247 int channel, slotrank, lane;
2248
2249 FOR_ALL_POPULATED_CHANNELS {
2250 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2251 ctrl->timings[channel][slotrank].lanes[lane].falling =
2252 16;
2253 ctrl->timings[channel][slotrank].lanes[lane].rising =
2254 16;
Patrick Rudolpha649a542016-01-17 18:32:06 +01002255 }
2256
2257 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002258
2259 FOR_ALL_POPULATED_RANKS {
2260 wait_428c(channel);
2261
Patrick Rudolph371d2912015-10-09 13:33:25 +02002262 /* DRAM command MRS
2263 * write MR3 MPR enable
2264 * in this mode only RD and RDA are allowed
2265 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002266 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2267 0x1f000);
2268 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2269 0xc01 | (ctrl->tMOD << 16));
2270 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2271 (slotrank << 24) | 0x360004);
2272 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2273
Patrick Rudolph371d2912015-10-09 13:33:25 +02002274 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002275 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2276 0x1f105);
2277 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2278 0x4041003);
2279 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2280 (slotrank << 24) | 0);
2281 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2282
Patrick Rudolph371d2912015-10-09 13:33:25 +02002283 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002284 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2285 0x1f105);
2286 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2287 0x1001 | ((ctrl->CAS + 8) << 16));
2288 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2289 (slotrank << 24) | 0x60000);
2290 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2291
Patrick Rudolph371d2912015-10-09 13:33:25 +02002292 /* DRAM command MRS
2293 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002294 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2295 0x1f000);
2296 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2297 0xc01 | (ctrl->tMOD << 16));
2298 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2299 (slotrank << 24) | 0x360000);
2300 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2301 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2302 0xc0001);
2303
2304 wait_428c(channel);
2305 }
2306
2307 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2308 ctrl->timings[channel][slotrank].lanes[lane].falling =
2309 48;
2310 ctrl->timings[channel][slotrank].lanes[lane].rising =
2311 48;
2312 }
2313
2314 program_timings(ctrl, channel);
2315
2316 FOR_ALL_POPULATED_RANKS {
2317 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002318 /* DRAM command MRS
2319 * write MR3 MPR enable
2320 * in this mode only RD and RDA are allowed
2321 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002322 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2323 0x1f000);
2324 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2325 0xc01 | (ctrl->tMOD << 16));
2326 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2327 (slotrank << 24) | 0x360004);
2328 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2329
Patrick Rudolph371d2912015-10-09 13:33:25 +02002330 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002331 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2332 0x1f105);
2333 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2334 0x4041003);
2335 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2336 (slotrank << 24) | 0);
2337 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2338
Patrick Rudolph371d2912015-10-09 13:33:25 +02002339 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002340 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2341 0x1f105);
2342 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2343 0x1001 | ((ctrl->CAS + 8) << 16));
2344 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2345 (slotrank << 24) | 0x60000);
2346 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2347
Patrick Rudolph371d2912015-10-09 13:33:25 +02002348 /* DRAM command MRS
2349 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002350 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2351 0x1f000);
2352 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2353 0xc01 | (ctrl->tMOD << 16));
2354
2355 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2356 (slotrank << 24) | 0x360000);
2357 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2358
2359 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2360 0xc0001);
2361 wait_428c(channel);
2362 }
2363 }
2364}
2365
2366static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
2367{
Patrick Rudolph371d2912015-10-09 13:33:25 +02002368 /* enable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002369 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002370 0x80 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002371
2372 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002373 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002374 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207);
2375 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2376 0x8000c01 | ((ctrl->CWL + ctrl->tWLO) << 16));
2377 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2378 8 | (slotrank << 24));
2379 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2380
Patrick Rudolph371d2912015-10-09 13:33:25 +02002381 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002382 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107);
2383 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2384 0x4000c01 | ((ctrl->CAS + 38) << 16));
2385 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2386 (slotrank << 24) | 4);
2387 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2388
2389 write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001);
2390 wait_428c(channel);
2391
Patrick Rudolph371d2912015-10-09 13:33:25 +02002392 /* disable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002393 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002394 0x1080 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002395}
2396
2397static void discover_timB(ramctr_timing * ctrl, int channel, int slotrank)
2398{
2399 int timB;
2400 int statistics[NUM_LANES][128];
2401 int lane;
2402
2403 write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2));
2404
2405 for (timB = 0; timB < 128; timB++) {
2406 FOR_ALL_LANES {
2407 ctrl->timings[channel][slotrank].lanes[lane].timB = timB;
2408 }
2409 program_timings(ctrl, channel);
2410
2411 test_timB(ctrl, channel, slotrank);
2412
2413 FOR_ALL_LANES {
2414 statistics[lane][timB] =
2415 !((read32
2416 (DEFAULT_MCHBAR + lane_registers[lane] +
2417 channel * 0x100 + 4 + ((timB / 32) & 1) * 4)
2418 >> (timB % 32)) & 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002419 printram("Bstat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002420 channel, slotrank, lane, timB,
2421 statistics[lane][timB]);
2422 }
2423 }
2424 FOR_ALL_LANES {
2425 struct run rn = get_longest_zero_run(statistics[lane], 128);
Patrick Rudolphd912f1d2016-02-15 20:07:42 +01002426 /* timC is a direct function of timB's 6 LSBs.
2427 * Some tests increments the value of timB by a small value,
2428 * which might cause the 6bit value to overflow, if it's close
2429 * to 0x3F. Increment the value by a small offset if it's likely
2430 * to overflow, to make sure it won't overflow while running
2431 * tests and bricks the system due to a non matching timC.
2432 *
2433 * TODO: find out why some tests (edge write discovery)
2434 * increment timB. */
2435 if ((rn.start & 0x3F) == 0x3E)
2436 rn.start += 2;
2437 else if ((rn.start & 0x3F) == 0x3F)
2438 rn.start += 1;
Vladimir Serbinenko3141eac2016-01-29 19:42:02 +01002439 ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002440 if (rn.all)
2441 die("timB discovery failed");
Patrick Rudolpha649a542016-01-17 18:32:06 +01002442 printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002443 lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
2444 }
2445}
2446
2447static int get_timB_high_adjust(u64 val)
2448{
2449 int i;
2450
2451 /* good */
2452 if (val == 0xffffffffffffffffLL)
2453 return 0;
2454
2455 if (val >= 0xf000000000000000LL) {
2456 /* needs negative adjustment */
2457 for (i = 0; i < 8; i++)
2458 if (val << (8 * (7 - i) + 4))
2459 return -i;
2460 } else {
2461 /* needs positive adjustment */
2462 for (i = 0; i < 8; i++)
2463 if (val >> (8 * (7 - i) + 4))
2464 return i;
2465 }
2466 return 8;
2467}
2468
2469static void adjust_high_timB(ramctr_timing * ctrl)
2470{
2471 int channel, slotrank, lane, old;
2472 write32(DEFAULT_MCHBAR + 0x3400, 0x200);
2473 FOR_ALL_POPULATED_CHANNELS {
2474 fill_pattern1(ctrl, channel);
2475 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 1);
2476 }
2477 FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
2478
2479 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001);
2480
2481 wait_428c(channel);
2482
Patrick Rudolph371d2912015-10-09 13:33:25 +02002483 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002484 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2485 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2486 0xc01 | (ctrl->tRCD << 16));
2487 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2488 (slotrank << 24) | 0x60000);
2489 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2490
Patrick Rudolph371d2912015-10-09 13:33:25 +02002491 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002492 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2493 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01);
2494 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2495 (slotrank << 24) | 0x8);
2496 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2497
Patrick Rudolph371d2912015-10-09 13:33:25 +02002498 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002499 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2500 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003);
2501 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2502 (slotrank << 24));
2503 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2);
2504
Patrick Rudolph371d2912015-10-09 13:33:25 +02002505 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002506 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2507 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2508 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2509 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2510 (slotrank << 24) | 0x8);
2511 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2512
2513 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2514
2515 wait_428c(channel);
2516
Patrick Rudolph371d2912015-10-09 13:33:25 +02002517 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002518 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2519 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2520 0xc01 | ((ctrl->tRP) << 16));
2521 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2522 (slotrank << 24) | 0x60400);
2523 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2524
Patrick Rudolph371d2912015-10-09 13:33:25 +02002525 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002526 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2527 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2528 0xc01 | ((ctrl->tRCD) << 16));
2529 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2530 (slotrank << 24) | 0x60000);
2531 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2532
Patrick Rudolph371d2912015-10-09 13:33:25 +02002533 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002534 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105);
2535 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2536 0x4000c01 |
2537 ((ctrl->tRP +
2538 ctrl->timings[channel][slotrank].val_4024 +
2539 ctrl->timings[channel][slotrank].val_4028) << 16));
2540 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2541 (slotrank << 24) | 0x60008);
2542 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2543
2544 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
2545 wait_428c(channel);
2546 FOR_ALL_LANES {
2547 u64 res =
2548 read32(DEFAULT_MCHBAR + lane_registers[lane] +
2549 0x100 * channel + 4);
2550 res |=
2551 ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] +
2552 0x100 * channel + 8)) << 32;
2553 old = ctrl->timings[channel][slotrank].lanes[lane].timB;
2554 ctrl->timings[channel][slotrank].lanes[lane].timB +=
2555 get_timB_high_adjust(res) * 64;
2556
Patrick Rudolpha649a542016-01-17 18:32:06 +01002557 printram("High adjust %d:%016llx\n", lane, res);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002558 printram("Bval+: %d, %d, %d, %x -> %x\n", channel,
2559 slotrank, lane, old,
2560 ctrl->timings[channel][slotrank].lanes[lane].
2561 timB);
2562 }
2563 }
2564 write32(DEFAULT_MCHBAR + 0x3400, 0);
2565}
2566
2567static void write_op(ramctr_timing * ctrl, int channel)
2568{
2569 int slotrank;
2570
2571 wait_428c(channel);
2572
2573 /* choose an existing rank. */
2574 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2575
Patrick Rudolph371d2912015-10-09 13:33:25 +02002576 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002577 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2578 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2579
2580 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2581 (slotrank << 24) | 0x60000);
2582
2583 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2584
2585 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2586 wait_428c(channel);
2587}
2588
Patrick Rudolph371d2912015-10-09 13:33:25 +02002589/* Compensate the skew between CMD/ADDR/CLK and DQ/DQS lanes.
2590 * DDR3 adopted the fly-by topology. The data and strobes signals reach
2591 * the chips at different times with respect to command, address and
2592 * clock signals.
2593 * By delaying either all DQ/DQs or all CMD/ADDR/CLK signals, a full phase
2594 * shift can be introduced.
2595 * It is assumed that the CLK/ADDR/CMD signals have the same routing delay.
2596 *
2597 * To find the required phase shift the DRAM is placed in "write leveling" mode.
2598 * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
2599 * sampled value on the data lanes (DQs).
2600 */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002601static void write_training(ramctr_timing * ctrl)
2602{
2603 int channel, slotrank, lane;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002604
2605 FOR_ALL_POPULATED_CHANNELS
2606 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
2607 read32(DEFAULT_MCHBAR + 0x4008 +
2608 0x400 * channel) | 0x8000000);
2609
2610 FOR_ALL_POPULATED_CHANNELS {
2611 write_op(ctrl, channel);
2612 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2613 read32(DEFAULT_MCHBAR + 0x4020 +
2614 0x400 * channel) | 0x200000);
2615 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002616
2617 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002618 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2619 FOR_ALL_POPULATED_CHANNELS {
2620 write_op(ctrl, channel);
2621 }
2622
Patrick Rudolph371d2912015-10-09 13:33:25 +02002623 /* enable write leveling on all ranks
2624 * disable all DQ outputs
2625 * only NOP is allowed in this mode */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002626 FOR_ALL_CHANNELS
2627 FOR_ALL_POPULATED_RANKS
2628 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002629 make_mr1(ctrl, slotrank, channel) | 0x1080);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002630
2631 write32(DEFAULT_MCHBAR + 0x3400, 0x108052);
2632
Patrick Rudolph9b515682015-10-09 13:43:51 +02002633 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002634
Patrick Rudolph371d2912015-10-09 13:33:25 +02002635 /* set any valid value for timB, it gets corrected later */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002636 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2637 discover_timB(ctrl, channel, slotrank);
2638
Patrick Rudolph371d2912015-10-09 13:33:25 +02002639 /* disable write leveling on all ranks */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002640 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2641 write_mrreg(ctrl, channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002642 slotrank, 1, make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002643
2644 write32(DEFAULT_MCHBAR + 0x3400, 0);
2645
2646 FOR_ALL_POPULATED_CHANNELS
2647 wait_428c(channel);
2648
Patrick Rudolph371d2912015-10-09 13:33:25 +02002649 /* refresh enable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002650 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8);
2651
2652 FOR_ALL_POPULATED_CHANNELS {
2653 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2654 ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 +
2655 0x400 * channel));
2656 read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel);
2657 wait_428c(channel);
2658
Patrick Rudolph371d2912015-10-09 13:33:25 +02002659 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002660 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2661 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
2662 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000);
2663 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2664
2665 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2666 wait_428c(channel);
2667 }
2668
Patrick Rudolph9b515682015-10-09 13:43:51 +02002669 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002670
2671 printram("CPE\n");
2672 precharge(ctrl);
2673 printram("CPF\n");
2674
2675 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2676 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2677 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2678 0);
2679 }
2680
2681 FOR_ALL_POPULATED_CHANNELS {
2682 fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555);
2683 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
2684 }
2685
2686 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2687 discover_timC(ctrl, channel, slotrank);
2688
2689 FOR_ALL_POPULATED_CHANNELS
2690 program_timings(ctrl, channel);
2691
Patrick Rudolph371d2912015-10-09 13:33:25 +02002692 /* measure and adjust timB timings */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002693 adjust_high_timB(ctrl);
2694
2695 FOR_ALL_POPULATED_CHANNELS
2696 program_timings(ctrl, channel);
2697
2698 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2699 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2700 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2701 0);
2702 }
2703}
2704
2705static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
2706{
2707 struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank];
2708 int timC_delta;
2709 int lanes_ok = 0;
2710 int ctr = 0;
2711 int lane;
2712
2713 for (timC_delta = -5; timC_delta <= 5; timC_delta++) {
2714 FOR_ALL_LANES {
2715 ctrl->timings[channel][slotrank].lanes[lane].timC =
2716 saved_rt.lanes[lane].timC + timC_delta;
2717 }
2718 program_timings(ctrl, channel);
2719 FOR_ALL_LANES {
2720 write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0);
2721 }
2722
2723 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2724
2725 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002726 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002727 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2728 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2729 ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10)
2730 | 8 | (ctrl->tRCD << 16));
2731
2732 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2733 (slotrank << 24) | ctr | 0x60000);
2734
2735 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002736 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002737 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
2738 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2739 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16));
2740 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2741 (slotrank << 24));
2742 write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd);
2743 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42);
2744
Patrick Rudolph371d2912015-10-09 13:33:25 +02002745 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002746 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2747 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2748 0x4001020 | (max(ctrl->tRTP, 8) << 16));
2749 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2750 (slotrank << 24));
2751 write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd);
2752 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42);
2753
Patrick Rudolph371d2912015-10-09 13:33:25 +02002754 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002755 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2756 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001);
2757 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2758 (slotrank << 24) | 0x60400);
2759 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2760
2761 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2762 wait_428c(channel);
2763 FOR_ALL_LANES {
2764 u32 r32 =
2765 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2766 0x400 * channel);
2767
2768 if (r32 == 0)
2769 lanes_ok |= 1 << lane;
2770 }
2771 ctr++;
2772 if (lanes_ok == ((1 << NUM_LANES) - 1))
2773 break;
2774 }
2775
2776 ctrl->timings[channel][slotrank] = saved_rt;
2777
2778 printram("3lanes: %x\n", lanes_ok);
2779 return lanes_ok != ((1 << NUM_LANES) - 1);
2780}
2781
2782#include "raminit_patterns.h"
2783
2784static void fill_pattern5(ramctr_timing * ctrl, int channel, int patno)
2785{
2786 unsigned i, j;
2787 unsigned channel_offset =
2788 get_precedening_channels(ctrl, channel) * 0x40;
2789 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2790
2791 if (patno) {
2792 u8 base8 = 0x80 >> ((patno - 1) % 8);
2793 u32 base = base8 | (base8 << 8) | (base8 << 16) | (base8 << 24);
2794 for (i = 0; i < 32; i++) {
2795 for (j = 0; j < 16; j++) {
2796 u32 val = use_base[patno - 1][i] & (1 << (j / 2)) ? base : 0;
2797 if (invert[patno - 1][i] & (1 << (j / 2)))
2798 val = ~val;
2799 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2800 j * 4), val);
2801 }
2802 }
2803
2804 } else {
2805 for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) {
2806 for (j = 0; j < 16; j++)
2807 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2808 j * 4), pattern[i][j]);
2809 }
2810 sfence();
2811 }
2812}
2813
2814static void reprogram_320c(ramctr_timing * ctrl)
2815{
2816 int channel, slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002817
2818 FOR_ALL_POPULATED_CHANNELS {
2819 wait_428c(channel);
2820
2821 /* choose an existing rank. */
2822 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2823
Patrick Rudolph371d2912015-10-09 13:33:25 +02002824 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002825 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2826 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2827
2828 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2829 (slotrank << 24) | 0x60000);
2830
2831 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2832
2833 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2834 wait_428c(channel);
2835 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2836 read32(DEFAULT_MCHBAR + 0x4020 +
2837 0x400 * channel) | 0x200000);
2838 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002839
2840 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002841 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2842 FOR_ALL_POPULATED_CHANNELS {
2843 wait_428c(channel);
2844
2845 /* choose an existing rank. */
2846 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2847
Patrick Rudolph371d2912015-10-09 13:33:25 +02002848 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002849 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2850 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2851
2852 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2853 (slotrank << 24) | 0x60000);
2854
2855 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2856
2857 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2858 wait_428c(channel);
2859 }
2860
2861 /* jedec reset */
2862 dram_jedecreset(ctrl);
2863 /* mrs commands. */
2864 dram_mrscommands(ctrl);
2865
Patrick Rudolph9b515682015-10-09 13:43:51 +02002866 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002867}
2868
2869#define MIN_C320C_LEN 13
2870
2871static int try_cmd_stretch(ramctr_timing * ctrl, int cmd_stretch)
2872{
2873 struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
2874 int channel, slotrank;
2875 int c320c;
2876 int stat[NUM_SLOTRANKS][256];
2877
2878 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2879 saved_timings[channel][slotrank] = ctrl->timings[channel][slotrank];
2880 }
2881
2882 FOR_ALL_POPULATED_CHANNELS {
2883 ctrl->cmd_stretch[channel] = cmd_stretch;
2884 }
2885
2886 FOR_ALL_POPULATED_CHANNELS
2887 MCHBAR32(0x4004 + 0x400 * channel) =
2888 ctrl->tRRD
2889 | (ctrl->tRTP << 4)
2890 | (ctrl->tCKE << 8)
2891 | (ctrl->tWTR << 12)
2892 | (ctrl->tFAW << 16)
2893 | (ctrl->tWR << 24)
2894 | (ctrl->cmd_stretch[channel] << 30);
2895
2896
2897 FOR_ALL_CHANNELS {
2898 int delta = 0;
2899 if (ctrl->cmd_stretch[channel] == 2)
2900 delta = 2;
2901 else if (ctrl->cmd_stretch[channel] == 0)
2902 delta = 4;
2903
2904 FOR_ALL_POPULATED_RANKS {
2905 ctrl->timings[channel][slotrank].val_4024 -= delta;
2906 }
2907 }
2908
2909 FOR_ALL_POPULATED_CHANNELS {
2910 for (c320c = -127; c320c <= 127; c320c++) {
2911 FOR_ALL_POPULATED_RANKS {
2912 ctrl->timings[channel][slotrank].val_320c = c320c;
2913 }
2914 program_timings(ctrl, channel);
2915 reprogram_320c(ctrl);
2916 FOR_ALL_POPULATED_RANKS {
2917 stat[slotrank][c320c + 127] =
2918 test_320c(ctrl, channel, slotrank);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002919 printram("3stat: %d, %d, %d: %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002920 channel, slotrank, c320c,
2921 stat[slotrank][c320c + 127]);
2922 }
2923 }
2924 FOR_ALL_POPULATED_RANKS {
2925 struct run rn =
2926 get_longest_zero_run(stat[slotrank], 255);
2927 ctrl->timings[channel][slotrank].val_320c =
2928 rn.middle - 127;
2929 printram("3val: %d, %d: %d\n", channel,
2930 slotrank,
2931 ctrl->timings[channel][slotrank].val_320c);
2932 if (rn.all || rn.length < MIN_C320C_LEN) {
2933 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2934 ctrl->timings[channel][slotrank] = saved_timings[channel][slotrank];
2935 }
2936 return 0;
2937 }
2938 }
2939 }
2940 return 1;
2941}
2942
Patrick Rudolph371d2912015-10-09 13:33:25 +02002943/* Adjust CMD phase shift and try multiple command rates.
2944 * A command rate of 2T doubles the time needed for address and
2945 * command decode. */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002946static void command_training(ramctr_timing * ctrl)
2947{
2948 int channel;
2949
2950 FOR_ALL_POPULATED_CHANNELS {
2951 fill_pattern5(ctrl, channel, 0);
2952 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2953 }
2954
2955 /* try command rate 1T and 2T */
2956 if (!try_cmd_stretch(ctrl, 0) && !try_cmd_stretch(ctrl, 2))
2957 die("c320c discovery failed");
2958
2959 FOR_ALL_POPULATED_CHANNELS {
2960 program_timings(ctrl, channel);
2961 }
2962
2963 reprogram_320c(ctrl);
2964}
2965
2966static void discover_edges_real(ramctr_timing * ctrl, int channel, int slotrank,
2967 int *edges)
2968{
2969 int edge;
2970 int statistics[NUM_LANES][MAX_EDGE_TIMING + 1];
2971 int lane;
2972
2973 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
2974 FOR_ALL_LANES {
2975 ctrl->timings[channel][slotrank].lanes[lane].rising =
2976 edge;
2977 ctrl->timings[channel][slotrank].lanes[lane].falling =
2978 edge;
2979 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002980 program_timings(ctrl, channel);
2981
2982 FOR_ALL_LANES {
2983 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
2984 4 * lane, 0);
2985 read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane +
2986 0x4140);
2987 }
2988
2989 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002990 /* DRAM command MRS
2991 * write MR3 MPR enable
2992 * in this mode only RD and RDA are allowed
2993 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002994 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
2995 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2996 (0xc01 | (ctrl->tMOD << 16)));
2997 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2998 (slotrank << 24) | 0x360004);
2999 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3000
Patrick Rudolph371d2912015-10-09 13:33:25 +02003001 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003002 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
3003 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4);
3004 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3005 (slotrank << 24));
3006 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3007
Patrick Rudolph371d2912015-10-09 13:33:25 +02003008 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003009 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
3010 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3011 0x1001 | ((ctrl->CAS + 8) << 16));
3012 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3013 (slotrank << 24) | 0x60000);
3014 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3015
Patrick Rudolph371d2912015-10-09 13:33:25 +02003016 /* DRAM command MRS
3017 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003018 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
3019 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3020 (0xc01 | (ctrl->tMOD << 16)));
3021 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3022 (slotrank << 24) | 0x360000);
3023 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3024
3025 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
3026
3027 wait_428c(channel);
3028
3029 FOR_ALL_LANES {
3030 statistics[lane][edge] =
3031 read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3032 lane * 4);
3033 }
3034 }
3035 FOR_ALL_LANES {
3036 struct run rn =
3037 get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
3038 edges[lane] = rn.middle;
3039 if (rn.all)
3040 die("edge discovery failed");
Patrick Rudolpha649a542016-01-17 18:32:06 +01003041 printram("eval %d, %d, %d: %02x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003042 lane, edges[lane]);
3043 }
3044}
3045
3046static void discover_edges(ramctr_timing * ctrl)
3047{
3048 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3049 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3050 int channel, slotrank, lane;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003051
3052 write32(DEFAULT_MCHBAR + 0x3400, 0);
3053
Patrick Rudolph9b515682015-10-09 13:43:51 +02003054 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003055
3056 FOR_ALL_POPULATED_CHANNELS FOR_ALL_LANES {
3057 write32(DEFAULT_MCHBAR + 4 * lane +
3058 0x400 * channel + 0x4080, 0);
3059 }
3060
3061 FOR_ALL_POPULATED_CHANNELS {
3062 fill_pattern0(ctrl, channel, 0, 0);
3063 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3064 FOR_ALL_LANES {
3065 read32(DEFAULT_MCHBAR + 0x400 * channel +
3066 lane * 4 + 0x4140);
3067 }
3068
3069 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3070 ctrl->timings[channel][slotrank].lanes[lane].falling =
3071 16;
3072 ctrl->timings[channel][slotrank].lanes[lane].rising =
3073 16;
3074 }
3075
3076 program_timings(ctrl, channel);
3077
3078 FOR_ALL_POPULATED_RANKS {
3079 wait_428c(channel);
3080
Patrick Rudolph371d2912015-10-09 13:33:25 +02003081 /* DRAM command MRS
3082 * MR3 enable MPR
3083 * write MR3 MPR enable
3084 * in this mode only RD and RDA are allowed
3085 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003086 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3087 0x1f000);
3088 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3089 0xc01 | (ctrl->tMOD << 16));
3090 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3091 (slotrank << 24) | 0x360004);
3092 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3093
Patrick Rudolph371d2912015-10-09 13:33:25 +02003094 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003095 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3096 0x1f105);
3097 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3098 0x4041003);
3099 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3100 (slotrank << 24) | 0);
3101 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3102
Patrick Rudolph371d2912015-10-09 13:33:25 +02003103 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003104 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3105 0x1f105);
3106 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3107 0x1001 | ((ctrl->CAS + 8) << 16));
3108 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3109 (slotrank << 24) | 0x60000);
3110 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3111
Patrick Rudolph371d2912015-10-09 13:33:25 +02003112 /* DRAM command MRS
3113 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003114 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3115 0x1f000);
3116 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3117 0xc01 | (ctrl->tMOD << 16));
3118 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3119 (slotrank << 24) | 0x360000);
3120 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3121 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3122 0xc0001);
3123
3124 wait_428c(channel);
3125 }
3126
Patrick Rudolph371d2912015-10-09 13:33:25 +02003127 /* XXX: check any measured value ? */
3128
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003129 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3130 ctrl->timings[channel][slotrank].lanes[lane].falling =
3131 48;
3132 ctrl->timings[channel][slotrank].lanes[lane].rising =
3133 48;
3134 }
3135
3136 program_timings(ctrl, channel);
3137
3138 FOR_ALL_POPULATED_RANKS {
3139 wait_428c(channel);
3140
Patrick Rudolph371d2912015-10-09 13:33:25 +02003141 /* DRAM command MRS
3142 * MR3 enable MPR
3143 * write MR3 MPR enable
3144 * in this mode only RD and RDA are allowed
3145 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003146 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3147 0x1f000);
3148 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3149 0xc01 | (ctrl->tMOD << 16));
3150 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3151 (slotrank << 24) | 0x360004);
3152 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3153
Patrick Rudolph371d2912015-10-09 13:33:25 +02003154 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003155 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3156 0x1f105);
3157 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3158 0x4041003);
3159 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3160 (slotrank << 24) | 0);
3161 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3162
Patrick Rudolph371d2912015-10-09 13:33:25 +02003163 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003164 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3165 0x1f105);
3166 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3167 0x1001 | ((ctrl->CAS + 8) << 16));
3168 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3169 (slotrank << 24) | 0x60000);
3170 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3171
Patrick Rudolph371d2912015-10-09 13:33:25 +02003172 /* DRAM command MRS
3173 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003174 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3175 0x1f000);
3176 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3177 0xc01 | (ctrl->tMOD << 16));
3178 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3179 (slotrank << 24) | 0x360000);
3180 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3181
3182 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3183 0xc0001);
3184 wait_428c(channel);
3185 }
3186
Patrick Rudolph371d2912015-10-09 13:33:25 +02003187 /* XXX: check any measured value ? */
3188
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003189 FOR_ALL_LANES {
3190 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel +
3191 lane * 4,
3192 ~read32(DEFAULT_MCHBAR + 0x4040 +
3193 0x400 * channel + lane * 4) & 0xff);
3194 }
3195
3196 fill_pattern0(ctrl, channel, 0, 0xffffffff);
3197 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3198 }
3199
3200 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3201 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003202 printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003203
3204 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3205 discover_edges_real(ctrl, channel, slotrank,
3206 falling_edges[channel][slotrank]);
3207 }
3208
3209 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003210 printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003211
3212 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3213 discover_edges_real(ctrl, channel, slotrank,
3214 rising_edges[channel][slotrank]);
3215 }
3216
3217 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3218
3219 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3220 ctrl->timings[channel][slotrank].lanes[lane].falling =
3221 falling_edges[channel][slotrank][lane];
3222 ctrl->timings[channel][slotrank].lanes[lane].rising =
3223 rising_edges[channel][slotrank][lane];
3224 }
3225
3226 FOR_ALL_POPULATED_CHANNELS {
3227 program_timings(ctrl, channel);
3228 }
3229
3230 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3231 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3232 0);
3233 }
3234}
3235
3236static void discover_edges_write_real(ramctr_timing * ctrl, int channel,
3237 int slotrank, int *edges)
3238{
3239 int edge;
3240 u32 raw_statistics[MAX_EDGE_TIMING + 1];
3241 int statistics[MAX_EDGE_TIMING + 1];
3242 const int reg3000b24[] = { 0, 0xc, 0x2c };
3243 int lane, i;
3244 int lower[NUM_LANES];
3245 int upper[NUM_LANES];
3246 int pat;
3247
3248 FOR_ALL_LANES {
3249 lower[lane] = 0;
3250 upper[lane] = MAX_EDGE_TIMING;
3251 }
3252
3253 for (i = 0; i < 3; i++) {
3254 write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel,
3255 reg3000b24[i] << 24);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003256 printram("[%x] = 0x%08x\n",
3257 0x3000 + 0x100 * channel, reg3000b24[i] << 24);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003258 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3259 fill_pattern5(ctrl, channel, pat);
3260 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003261 printram("using pattern %d\n", pat);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003262 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3263 FOR_ALL_LANES {
3264 ctrl->timings[channel][slotrank].lanes[lane].
3265 rising = edge;
3266 ctrl->timings[channel][slotrank].lanes[lane].
3267 falling = edge;
3268 }
3269 program_timings(ctrl, channel);
3270
3271 FOR_ALL_LANES {
3272 write32(DEFAULT_MCHBAR + 0x4340 +
3273 0x400 * channel + 4 * lane, 0);
3274 read32(DEFAULT_MCHBAR + 0x400 * channel +
3275 4 * lane + 0x4140);
3276 }
3277 wait_428c(channel);
3278
Patrick Rudolph371d2912015-10-09 13:33:25 +02003279 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003280 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3281 0x1f006);
3282 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3283 0x4 | (ctrl->tRCD << 16)
3284 | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) <<
3285 10));
3286 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3287 (slotrank << 24) | 0x60000);
3288 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel,
3289 0x240);
3290
Patrick Rudolph371d2912015-10-09 13:33:25 +02003291 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003292 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3293 0x1f201);
3294 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3295 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) <<
3296 16));
3297 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3298 (slotrank << 24));
3299 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel,
3300 0x242);
3301
Patrick Rudolph371d2912015-10-09 13:33:25 +02003302 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003303 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3304 0x1f105);
3305 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3306 0x4005020 | (max(ctrl->tRTP, 8) << 16));
3307 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3308 (slotrank << 24));
3309 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel,
3310 0x242);
3311
Patrick Rudolph371d2912015-10-09 13:33:25 +02003312 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003313 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3314 0x1f002);
3315 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3316 0xc01 | (ctrl->tRP << 16));
3317 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3318 (slotrank << 24) | 0x60400);
3319 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3320
3321 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3322 0xc0001);
3323 wait_428c(channel);
3324 FOR_ALL_LANES {
3325 read32(DEFAULT_MCHBAR + 0x4340 +
3326 0x400 * channel + lane * 4);
3327 }
3328
3329 raw_statistics[edge] =
3330 MCHBAR32(0x436c + 0x400 * channel);
3331 }
3332 FOR_ALL_LANES {
3333 struct run rn;
3334 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++)
3335 statistics[edge] =
3336 ! !(raw_statistics[edge] & (1 << lane));
3337 rn = get_longest_zero_run(statistics,
3338 MAX_EDGE_TIMING + 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003339 printram("edges: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003340 channel, slotrank, i, rn.start, rn.middle,
3341 rn.end, rn.start + ctrl->edge_offset[i],
3342 rn.end - ctrl->edge_offset[i]);
3343 lower[lane] =
3344 max(rn.start + ctrl->edge_offset[i], lower[lane]);
3345 upper[lane] =
3346 min(rn.end - ctrl->edge_offset[i], upper[lane]);
3347 edges[lane] = (lower[lane] + upper[lane]) / 2;
Patrick Rudolph9733e282015-08-16 17:06:30 +02003348 if (rn.all || (lower[lane] > upper[lane]))
3349 die("edge write discovery failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003350
3351 }
3352 }
3353 }
3354
3355 write32(DEFAULT_MCHBAR + 0x3000, 0);
3356 printram("CPA\n");
3357}
3358
3359static void discover_edges_write(ramctr_timing * ctrl)
3360{
3361 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3362 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3363 int channel, slotrank, lane;
3364
3365 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3366 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003367 printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003368
3369 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3370 discover_edges_write_real(ctrl, channel, slotrank,
3371 falling_edges[channel][slotrank]);
3372 }
3373
3374 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003375 printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003376
3377 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3378 discover_edges_write_real(ctrl, channel, slotrank,
3379 rising_edges[channel][slotrank]);
3380 }
3381
3382 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3383
3384 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3385 ctrl->timings[channel][slotrank].lanes[lane].falling =
3386 falling_edges[channel][slotrank][lane];
3387 ctrl->timings[channel][slotrank].lanes[lane].rising =
3388 rising_edges[channel][slotrank][lane];
3389 }
3390
3391 FOR_ALL_POPULATED_CHANNELS
3392 program_timings(ctrl, channel);
3393
3394 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3395 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3396 0);
3397 }
3398}
3399
3400static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
3401{
3402 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003403 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003404 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
3405 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3406 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD)
3407 << 10) | (ctrl->tRCD << 16) | 4);
3408 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3409 (slotrank << 24) | 0x60000);
3410 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
3411
Patrick Rudolph371d2912015-10-09 13:33:25 +02003412 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003413 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
3414 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3415 0x80011e0 |
3416 ((ctrl->tWTR + ctrl->CWL + 8) << 16));
3417 write32(DEFAULT_MCHBAR + 0x4204 +
3418 0x400 * channel, (slotrank << 24));
3419 write32(DEFAULT_MCHBAR + 0x4214 +
3420 0x400 * channel, 0x242);
3421
Patrick Rudolph371d2912015-10-09 13:33:25 +02003422 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003423 write32(DEFAULT_MCHBAR + 0x4228 +
3424 0x400 * channel, 0x1f105);
3425 write32(DEFAULT_MCHBAR + 0x4238 +
3426 0x400 * channel,
3427 0x40011e0 | (max(ctrl->tRTP, 8) << 16));
3428 write32(DEFAULT_MCHBAR + 0x4208 +
3429 0x400 * channel, (slotrank << 24));
3430 write32(DEFAULT_MCHBAR + 0x4218 +
3431 0x400 * channel, 0x242);
3432
Patrick Rudolph371d2912015-10-09 13:33:25 +02003433 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003434 write32(DEFAULT_MCHBAR + 0x422c +
3435 0x400 * channel, 0x1f002);
3436 write32(DEFAULT_MCHBAR + 0x423c +
3437 0x400 * channel,
3438 0x1001 | (ctrl->tRP << 16));
3439 write32(DEFAULT_MCHBAR + 0x420c +
3440 0x400 * channel,
3441 (slotrank << 24) | 0x60400);
3442 write32(DEFAULT_MCHBAR + 0x421c +
3443 0x400 * channel, 0);
3444
3445 write32(DEFAULT_MCHBAR + 0x4284 +
3446 0x400 * channel, 0xc0001);
3447 wait_428c(channel);
3448}
3449
3450static void discover_timC_write(ramctr_timing * ctrl)
3451{
3452 const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
3453 int i, pat;
3454
3455 int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3456 int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3457 int channel, slotrank, lane;
3458
3459 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3460 lower[channel][slotrank][lane] = 0;
3461 upper[channel][slotrank][lane] = MAX_TIMC;
3462 }
3463
3464 write32(DEFAULT_MCHBAR + 0x4ea8, 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003465 printram("discover timC write:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003466
3467 for (i = 0; i < 3; i++)
3468 FOR_ALL_POPULATED_CHANNELS {
3469 write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100),
3470 (rege3c_b24[i] << 24)
3471 | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100))
3472 & ~0x3f000000));
3473 udelay(2);
3474 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3475 FOR_ALL_POPULATED_RANKS {
3476 int timC;
3477 u32 raw_statistics[MAX_TIMC + 1];
3478 int statistics[MAX_TIMC + 1];
3479
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003480 /* Make sure rn.start < rn.end */
3481 statistics[MAX_TIMC] = 1;
3482
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003483 fill_pattern5(ctrl, channel, pat);
3484 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003485 for (timC = 0; timC < MAX_TIMC; timC++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003486 FOR_ALL_LANES
3487 ctrl->timings[channel][slotrank].lanes[lane].timC = timC;
3488 program_timings(ctrl, channel);
3489
3490 test_timC_write (ctrl, channel, slotrank);
3491
3492 raw_statistics[timC] =
3493 MCHBAR32(0x436c + 0x400 * channel);
3494 }
3495 FOR_ALL_LANES {
3496 struct run rn;
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003497 for (timC = 0; timC < MAX_TIMC; timC++)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003498 statistics[timC] =
3499 !!(raw_statistics[timC] &
3500 (1 << lane));
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003501
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003502 rn = get_longest_zero_run(statistics,
3503 MAX_TIMC + 1);
3504 if (rn.all)
3505 die("timC write discovery failed");
Patrick Rudolpha649a542016-01-17 18:32:06 +01003506 printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003507 channel, slotrank, i, rn.start,
3508 rn.middle, rn.end,
3509 rn.start + ctrl->timC_offset[i],
3510 rn.end - ctrl->timC_offset[i]);
3511 lower[channel][slotrank][lane] =
3512 max(rn.start + ctrl->timC_offset[i],
3513 lower[channel][slotrank][lane]);
3514 upper[channel][slotrank][lane] =
3515 min(rn.end - ctrl->timC_offset[i],
3516 upper[channel][slotrank][lane]);
3517
3518 }
3519 }
3520 }
3521 }
3522
3523 FOR_ALL_CHANNELS {
3524 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3525 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3526 ~0x3f000000));
3527 udelay(2);
3528 }
3529
3530 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3531
3532 printram("CPB\n");
3533
3534 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
Patrick Rudolpha649a542016-01-17 18:32:06 +01003535 printram("timC %d, %d, %d: %x\n", channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003536 slotrank, lane,
3537 (lower[channel][slotrank][lane] +
3538 upper[channel][slotrank][lane]) / 2);
3539 ctrl->timings[channel][slotrank].lanes[lane].timC =
3540 (lower[channel][slotrank][lane] +
3541 upper[channel][slotrank][lane]) / 2;
3542 }
3543 FOR_ALL_POPULATED_CHANNELS {
3544 program_timings(ctrl, channel);
3545 }
3546}
3547
3548static void normalize_training(ramctr_timing * ctrl)
3549{
3550 int channel, slotrank, lane;
3551 int mat = 0;
3552
3553 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3554 int delta;
3555 FOR_ALL_LANES mat =
3556 max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat);
3557 delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028;
3558 ctrl->timings[channel][slotrank].val_4024 += delta;
3559 ctrl->timings[channel][slotrank].val_4028 += delta;
3560 }
3561
3562 FOR_ALL_POPULATED_CHANNELS {
3563 program_timings(ctrl, channel);
3564 }
3565}
3566
3567static void write_controller_mr(ramctr_timing * ctrl)
3568{
3569 int channel, slotrank;
3570
3571 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3572 write32(DEFAULT_MCHBAR + 0x0004 + (channel << 8) +
3573 lane_registers[slotrank], make_mr0(ctrl, slotrank));
3574 write32(DEFAULT_MCHBAR + 0x0008 + (channel << 8) +
Patrick Rudolph7e513d12016-01-10 14:22:34 +01003575 lane_registers[slotrank],
3576 make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003577 }
3578}
3579
3580static void channel_test(ramctr_timing * ctrl)
3581{
3582 int channel, slotrank, lane;
3583
3584 FOR_ALL_POPULATED_CHANNELS
Patrick Rudolpha649a542016-01-17 18:32:06 +01003585 if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000)
3586 die("Mini channel test failed (1)\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003587 FOR_ALL_POPULATED_CHANNELS {
3588 fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
3589
3590 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3591 }
3592
3593 for (slotrank = 0; slotrank < 4; slotrank++)
3594 FOR_ALL_CHANNELS
3595 if (ctrl->rankmap[channel] & (1 << slotrank)) {
3596 FOR_ALL_LANES {
3597 write32(DEFAULT_MCHBAR + (0x4f40 + 4 * lane), 0);
3598 write32(DEFAULT_MCHBAR + (0x4d40 + 4 * lane), 0);
3599 }
3600 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003601 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003602 write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
3603 write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10), 0x0028a004);
3604 write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
3605 0x00060000 | (slotrank << 24));
3606 write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003607 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003608 write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
3609 write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281064);
3610 write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
3611 0x00000000 | (slotrank << 24));
3612 write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003613 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003614 write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f105);
3615 write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x04281064);
3616 write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
3617 0x00000000 | (slotrank << 24));
3618 write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003619 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003620 write32(DEFAULT_MCHBAR + 0x422c + (channel << 10), 0x0001f002);
3621 write32(DEFAULT_MCHBAR + 0x423c + (channel << 10), 0x00280c01);
3622 write32(DEFAULT_MCHBAR + 0x420c + (channel << 10),
3623 0x00060400 | (slotrank << 24));
3624 write32(DEFAULT_MCHBAR + 0x421c + (channel << 10), 0x00000240);
3625 write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
3626 wait_428c(channel);
3627 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01003628 if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane))
3629 die("Mini channel test failed (2)\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003630 }
3631}
3632
3633static void set_scrambling_seed(ramctr_timing * ctrl)
3634{
3635 int channel;
3636
3637 /* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
3638 I don't think so. */
3639 static u32 seeds[NUM_CHANNELS][3] = {
3640 {0x00009a36, 0xbafcfdcf, 0x46d1ab68},
3641 {0x00028bfa, 0x53fe4b49, 0x19ed5483}
3642 };
3643 FOR_ALL_POPULATED_CHANNELS {
3644 MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
3645 write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
3646 write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
3647 write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
3648 }
3649}
3650
3651static void set_4f8c(void)
3652{
3653 struct cpuid_result cpures;
3654 u32 cpu;
3655
3656 cpures = cpuid(0);
3657 cpu = (cpures.eax);
3658 if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) {
3659 MCHBAR32(0x4f8c) = 0x141D1519;
3660 } else {
3661 MCHBAR32(0x4f8c) = 0x551D1519;
3662 }
3663}
3664
3665static void prepare_training(ramctr_timing * ctrl)
3666{
3667 int channel;
3668
3669 FOR_ALL_POPULATED_CHANNELS {
3670 // Always drive command bus
3671 MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000;
3672 }
3673
3674 udelay(1);
3675
3676 FOR_ALL_POPULATED_CHANNELS {
3677 wait_428c(channel);
3678 }
3679}
3680
3681static void set_4008c(ramctr_timing * ctrl)
3682{
3683 int channel, slotrank;
3684 u32 reg;
3685 FOR_ALL_POPULATED_CHANNELS {
3686 u32 b20, b4_8_12;
3687 int min_320c = 10000;
3688 int max_320c = -10000;
3689
3690 FOR_ALL_POPULATED_RANKS {
3691 max_320c = max(ctrl->timings[channel][slotrank].val_320c, max_320c);
3692 min_320c = min(ctrl->timings[channel][slotrank].val_320c, min_320c);
3693 }
3694
3695 if (max_320c - min_320c > 51)
3696 b20 = 0;
3697 else
3698 b20 = ctrl->ref_card_offset[channel];
3699
3700 if (ctrl->reg_320c_range_threshold < max_320c - min_320c)
3701 b4_8_12 = 0x3330;
3702 else
3703 b4_8_12 = 0x2220;
3704
3705 reg = read32(DEFAULT_MCHBAR + 0x400c + (channel << 10));
3706 write32(DEFAULT_MCHBAR + 0x400c + (channel << 10),
3707 (reg & 0xFFF0FFFF)
3708 | (ctrl->ref_card_offset[channel] << 16)
3709 | (ctrl->ref_card_offset[channel] << 18));
3710 write32(DEFAULT_MCHBAR + 0x4008 + (channel << 10),
3711 0x0a000000
3712 | (b20 << 20)
3713 | ((ctrl->ref_card_offset[channel] + 2) << 16)
3714 | b4_8_12);
3715 }
3716}
3717
3718static void set_42a0(ramctr_timing * ctrl)
3719{
3720 int channel;
3721 FOR_ALL_POPULATED_CHANNELS {
3722 write32(DEFAULT_MCHBAR + (0x42a0 + 0x400 * channel),
3723 0x00001000 | ctrl->rankmap[channel]);
3724 MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK
3725 }
3726}
3727
3728static int encode_5d10(int ns)
3729{
3730 return (ns + 499) / 500;
3731}
3732
3733/* FIXME: values in this function should be hardware revision-dependent. */
3734static void final_registers(ramctr_timing * ctrl)
3735{
3736 int channel;
3737 int t1_cycles = 0, t1_ns = 0, t2_ns;
3738 int t3_ns;
3739 u32 r32;
3740
3741 write32(DEFAULT_MCHBAR + 0x4cd4, 0x00000046);
3742
3743 write32(DEFAULT_MCHBAR + 0x400c, (read32(DEFAULT_MCHBAR + 0x400c) & 0xFFFFCFFF) | 0x1000); // OK
3744 write32(DEFAULT_MCHBAR + 0x440c, (read32(DEFAULT_MCHBAR + 0x440c) & 0xFFFFCFFF) | 0x1000); // OK
3745 write32(DEFAULT_MCHBAR + 0x4cb0, 0x00000740);
3746 write32(DEFAULT_MCHBAR + 0x4380, 0x00000aaa); // OK
3747 write32(DEFAULT_MCHBAR + 0x4780, 0x00000aaa); // OK
3748 write32(DEFAULT_MCHBAR + 0x4f88, 0x5f7003ff); // OK
3749 write32(DEFAULT_MCHBAR + 0x5064, 0x00073000 | ctrl->reg_5064b0); // OK
3750
3751 FOR_ALL_CHANNELS {
3752 switch (ctrl->rankmap[channel]) {
3753 /* Unpopulated channel. */
3754 case 0:
3755 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0);
3756 break;
3757 /* Only single-ranked dimms. */
3758 case 1:
3759 case 4:
3760 case 5:
3761 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x373131);
3762 break;
3763 /* Dual-ranked dimms present. */
3764 default:
3765 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x9b6ea1);
3766 break;
3767 }
3768 }
3769
3770 write32 (DEFAULT_MCHBAR + 0x5880, 0xca9171e5);
3771 write32 (DEFAULT_MCHBAR + 0x5888,
3772 (read32 (DEFAULT_MCHBAR + 0x5888) & ~0xffffff) | 0xe4d5d0);
3773 write32 (DEFAULT_MCHBAR + 0x58a8, read32 (DEFAULT_MCHBAR + 0x58a8) & ~0x1f);
3774 write32 (DEFAULT_MCHBAR + 0x4294,
3775 (read32 (DEFAULT_MCHBAR + 0x4294) & ~0x30000)
3776 | (1 << 16));
3777 write32 (DEFAULT_MCHBAR + 0x4694,
3778 (read32 (DEFAULT_MCHBAR + 0x4694) & ~0x30000)
3779 | (1 << 16));
3780
3781 MCHBAR32(0x5030) |= 1; // OK
3782 MCHBAR32(0x5030) |= 0x80; // OK
3783 MCHBAR32(0x5f18) = 0xfa; // OK
3784
3785 /* Find a populated channel. */
3786 FOR_ALL_POPULATED_CHANNELS
3787 break;
3788
3789 t1_cycles = ((read32(DEFAULT_MCHBAR + 0x4290 + channel * 0x400) >> 8) & 0xff);
3790 r32 = read32(DEFAULT_MCHBAR + 0x5064);
3791 if (r32 & 0x20000)
3792 t1_cycles += (r32 & 0xfff);
3793 t1_cycles += (read32(DEFAULT_MCHBAR + channel * 0x400 + 0x42a4) & 0xfff);
3794 t1_ns = t1_cycles * ctrl->tCK / 256 + 544;
3795 if (!(r32 & 0x20000))
3796 t1_ns += 500;
3797
3798 t2_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f10) >> 8) & 0xfff);
3799 if ( read32(DEFAULT_MCHBAR + 0x5f00) & 8 )
3800 {
3801 t3_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f20) >> 8) & 0xfff);
3802 t3_ns += 10 * (read32(DEFAULT_MCHBAR + 0x5f18) & 0xff);
3803 }
3804 else
3805 {
3806 t3_ns = 500;
3807 }
3808 printk(BIOS_DEBUG, "t123: %d, %d, %d\n",
3809 t1_ns, t2_ns, t3_ns);
3810 write32 (DEFAULT_MCHBAR + 0x5d10,
3811 ((encode_5d10(t1_ns) + encode_5d10(t2_ns)) << 16)
3812 | (encode_5d10(t1_ns) << 8)
3813 | ((encode_5d10(t3_ns) + encode_5d10(t2_ns) + encode_5d10(t1_ns)) << 24)
3814 | (read32(DEFAULT_MCHBAR + 0x5d10) & 0xC0C0C0C0)
3815 | 0xc);
3816}
3817
3818static void save_timings(ramctr_timing * ctrl)
3819{
3820 struct mrc_data_container *mrcdata;
3821 int output_len = ALIGN(sizeof (*ctrl), 16);
3822
3823 /* Save the MRC S3 restore data to cbmem */
3824 mrcdata = cbmem_add
3825 (CBMEM_ID_MRCDATA,
3826 output_len + sizeof(struct mrc_data_container));
3827
3828 printk(BIOS_DEBUG, "Relocate MRC DATA from %p to %p (%u bytes)\n",
3829 ctrl, mrcdata, output_len);
3830
3831 mrcdata->mrc_signature = MRC_DATA_SIGNATURE;
3832 mrcdata->mrc_data_size = output_len;
3833 mrcdata->reserved = 0;
3834 memcpy(mrcdata->mrc_data, ctrl, sizeof (*ctrl));
3835
3836 /* Zero the unused space in aligned buffer. */
3837 if (output_len > sizeof (*ctrl))
3838 memset(mrcdata->mrc_data+sizeof (*ctrl), 0,
3839 output_len - sizeof (*ctrl));
3840
3841 mrcdata->mrc_checksum = compute_ip_checksum(mrcdata->mrc_data,
3842 mrcdata->mrc_data_size);
3843}
3844
3845static void restore_timings(ramctr_timing * ctrl)
3846{
3847 int channel, slotrank, lane;
3848
3849 FOR_ALL_POPULATED_CHANNELS
3850 MCHBAR32(0x4004 + 0x400 * channel) =
3851 ctrl->tRRD
3852 | (ctrl->tRTP << 4)
3853 | (ctrl->tCKE << 8)
3854 | (ctrl->tWTR << 12)
3855 | (ctrl->tFAW << 16)
3856 | (ctrl->tWR << 24)
3857 | (ctrl->cmd_stretch[channel] << 30);
3858
3859 udelay(1);
3860
3861 FOR_ALL_POPULATED_CHANNELS {
3862 wait_428c(channel);
3863 }
3864
3865 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3866 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
3867 + 4 * lane, 0);
3868 }
3869
3870 FOR_ALL_POPULATED_CHANNELS
3871 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
3872 read32(DEFAULT_MCHBAR + 0x4008 +
3873 0x400 * channel) | 0x8000000);
3874
3875 FOR_ALL_POPULATED_CHANNELS {
3876 udelay (1);
3877 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
3878 read32(DEFAULT_MCHBAR + 0x4020 +
3879 0x400 * channel) | 0x200000);
3880 }
3881
3882 printram("CPE\n");
3883
3884 write32(DEFAULT_MCHBAR + 0x3400, 0);
3885 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3886
3887 printram("CP5b\n");
3888
3889 FOR_ALL_POPULATED_CHANNELS {
3890 program_timings(ctrl, channel);
3891 }
3892
3893 u32 reg, addr;
3894
3895 while (!(MCHBAR32(0x5084) & 0x10000)) ;
3896 do {
3897 reg = MCHBAR32(0x428c);
3898 } while ((reg & 0x14) == 0);
3899
3900 // Set state of memory controller
3901 MCHBAR32(0x5030) = 0x116;
3902 MCHBAR32(0x4ea0) = 0;
3903
3904 // Wait 500us
3905 udelay(500);
3906
3907 FOR_ALL_CHANNELS {
3908 // Set valid rank CKE
3909 reg = 0;
3910 reg = (reg & ~0xf) | ctrl->rankmap[channel];
3911 addr = 0x400 * channel + 0x42a0;
3912 MCHBAR32(addr) = reg;
3913
3914 // Wait 10ns for ranks to settle
3915 //udelay(0.01);
3916
3917 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
3918 MCHBAR32(addr) = reg;
3919
3920 // Write reset using a NOP
3921 write_reset(ctrl);
3922 }
3923
3924 /* mrs commands. */
3925 dram_mrscommands(ctrl);
3926
3927 printram("CP5c\n");
3928
3929 write32(DEFAULT_MCHBAR + 0x3000, 0);
3930
3931 FOR_ALL_CHANNELS {
3932 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3933 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3934 ~0x3f000000));
3935 udelay(2);
3936 }
3937
3938 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3939}
3940
3941void init_dram_ddr3(spd_raw_data * spds, int mobile, int min_tck,
3942 int s3resume)
3943{
3944 int me_uma_size;
3945 int cbmem_was_inited;
Patrick Rudolphb97009e2016-02-28 15:24:04 +01003946 dimm_info info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003947
3948 MCHBAR32(0x5f00) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +02003949
Vadim Bendebury7a3f36a2012-04-18 15:47:32 -07003950 report_platform_info();
3951
Stefan Reinauer00636b02012-04-04 00:08:51 +02003952 /* Wait for ME to be ready */
3953 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003954 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +02003955
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003956 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +02003957
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003958 u32 reg_5d10;
Stefan Reinauer00636b02012-04-04 00:08:51 +02003959
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003960 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +02003961
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003962 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +02003963
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003964 reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10); // !!! = 0x00000000
3965 if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */
3966 && reg_5d10 && !s3resume) {
3967 write32(DEFAULT_MCHBAR + 0x5d10, 0);
3968 /* Need reset. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02003969 outb(0x6, 0xcf9);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003970
Patrick Georgi546953c2014-11-29 10:38:17 +01003971 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02003972 }
Stefan Reinauer00636b02012-04-04 00:08:51 +02003973
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003974 ramctr_timing ctrl;
Vadim Bendebury48a4a7f2012-06-07 18:47:13 -07003975
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003976 memset(&ctrl, 0, sizeof (ctrl));
3977
3978 early_pch_init_native();
3979 early_thermal_init();
3980
3981 ctrl.mobile = mobile;
3982 ctrl.tCK = min_tck;
3983
3984 /* FIXME: for non-S3 we should be able to use timing caching with
3985 proper verification. Right now we use timings only for S3 case.
3986 */
3987 if (s3resume) {
3988 struct mrc_data_container *mrc_cache;
3989
3990 mrc_cache = find_current_mrc_cache();
3991 if (!mrc_cache || mrc_cache->mrc_data_size < sizeof (ctrl)) {
3992 /* Failed S3 resume, reset to come up cleanly */
3993 outb(0x6, 0xcf9);
3994 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02003995 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003996 memcpy(&ctrl, mrc_cache->mrc_data, sizeof (ctrl));
Stefan Reinauer00636b02012-04-04 00:08:51 +02003997 }
3998
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003999 if (!s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004000 /* Get DDR3 SPD data */
4001 dram_find_spds_ddr3(spds, &info, &ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004002
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004003 /* Find fastest common supported parameters */
4004 dram_find_common_params(&info, &ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004005
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004006 dram_dimm_mapping(&info, &ctrl);
4007 }
4008
4009 /* Set MCU frequency */
4010 dram_freq(&ctrl);
4011
4012 if (!s3resume) {
4013 /* Calculate timings */
4014 dram_timing(&ctrl);
4015 }
4016
4017 /* Set version register */
4018 MCHBAR32(0x5034) = 0xC04EB002;
4019
4020 /* Enable crossover */
4021 dram_xover(&ctrl);
4022
4023 /* Set timing and refresh registers */
4024 dram_timing_regs(&ctrl);
4025
4026 /* Power mode preset */
4027 MCHBAR32(0x4e80) = 0x5500;
4028
4029 /* Set scheduler parameters */
4030 MCHBAR32(0x4c20) = 0x10100005;
4031
4032 /* Set cpu specific register */
4033 set_4f8c();
4034
4035 /* Clear IO reset bit */
4036 MCHBAR32(0x5030) &= ~0x20;
4037
4038 /* Set MAD-DIMM registers */
4039 dram_dimm_set_mapping(&ctrl);
4040 printk(BIOS_DEBUG, "Done dimm mapping\n");
4041
4042 /* Zone config */
4043 dram_zones(&ctrl, 1);
4044
4045 /* Set memory map */
4046 dram_memorymap(&ctrl, me_uma_size);
4047 printk(BIOS_DEBUG, "Done memory map\n");
4048
4049 /* Set IO registers */
4050 dram_ioregs(&ctrl);
4051 printk(BIOS_DEBUG, "Done io registers\n");
4052
4053 udelay(1);
4054
4055 if (s3resume) {
4056 restore_timings(&ctrl);
4057 } else {
4058 /* Do jedec ddr3 reset sequence */
4059 dram_jedecreset(&ctrl);
4060 printk(BIOS_DEBUG, "Done jedec reset\n");
4061
4062 /* MRS commands */
4063 dram_mrscommands(&ctrl);
4064 printk(BIOS_DEBUG, "Done MRS commands\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004065
4066 /* Prepare for memory training */
4067 prepare_training(&ctrl);
4068
4069 read_training(&ctrl);
4070 write_training(&ctrl);
4071
4072 printram("CP5a\n");
4073
4074 discover_edges(&ctrl);
4075
4076 printram("CP5b\n");
4077
4078 command_training(&ctrl);
4079
4080 printram("CP5c\n");
4081
4082 discover_edges_write(&ctrl);
4083
4084 discover_timC_write(&ctrl);
4085
4086 normalize_training(&ctrl);
4087 }
4088
4089 set_4008c(&ctrl);
4090
4091 write_controller_mr(&ctrl);
4092
4093 if (!s3resume) {
4094 channel_test(&ctrl);
4095 }
4096
4097 /* FIXME: should be hardware revision-dependent. */
4098 write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
4099
4100 set_scrambling_seed(&ctrl);
4101
4102 set_42a0(&ctrl);
4103
4104 final_registers(&ctrl);
4105
4106 /* Zone config */
4107 dram_zones(&ctrl, 0);
4108
4109 if (!s3resume)
4110 quick_ram_check();
4111
4112 intel_early_me_status();
4113 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
4114 intel_early_me_status();
4115
Stefan Reinauer00636b02012-04-04 00:08:51 +02004116 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004117
4118 cbmem_was_inited = !cbmem_recovery(s3resume);
4119 if (!s3resume)
4120 save_timings(&ctrl);
4121 if (s3resume && !cbmem_was_inited) {
4122 /* Failed S3 resume, reset to come up cleanly */
4123 outb(0x6, 0xcf9);
4124 halt();
4125 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +01004126
4127 fill_smbios17(&info, (1000 << 8) / ctrl.tCK);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004128}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004129
4130#define HOST_BRIDGE PCI_DEVFN(0, 0)
4131#define DEFAULT_TCK TCK_800MHZ
4132
4133static unsigned int get_mem_min_tck(void)
4134{
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004135 u32 reg32;
4136 u8 rev;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004137 const struct device *dev;
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004138 const struct northbridge_intel_sandybridge_config *cfg = NULL;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004139
4140 dev = dev_find_slot(0, HOST_BRIDGE);
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004141 if (dev)
4142 cfg = dev->chip_info;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004143
4144 /* If this is zero, it just means devicetree.cb didn't set it */
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004145 if (!cfg || cfg->max_mem_clock_mhz == 0) {
4146 rev = pci_read_config8(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004147
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004148 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
4149 /* read Capabilities A Register DMFC bits */
4150 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A);
4151 reg32 &= 0x7;
4152
4153 switch (reg32) {
4154 case 7: return TCK_533MHZ;
4155 case 6: return TCK_666MHZ;
4156 case 5: return TCK_800MHZ;
4157 /* reserved: */
4158 default:
4159 break;
4160 }
4161 } else {
4162 /* read Capabilities B Register DMFC bits */
4163 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
4164 reg32 = (reg32 >> 4) & 0x7;
4165
4166 switch (reg32) {
4167 case 7: return TCK_533MHZ;
4168 case 6: return TCK_666MHZ;
4169 case 5: return TCK_800MHZ;
4170 case 4: return TCK_933MHZ;
4171 case 3: return TCK_1066MHZ;
4172 case 2: return TCK_1200MHZ;
4173 case 1: return TCK_1333MHZ;
4174 /* reserved: */
4175 default:
4176 break;
4177 }
4178 }
4179 return DEFAULT_TCK;
4180 } else {
4181 if (cfg->max_mem_clock_mhz >= 800)
4182 return TCK_800MHZ;
4183 else if (cfg->max_mem_clock_mhz >= 666)
4184 return TCK_666MHZ;
4185 else if (cfg->max_mem_clock_mhz >= 533)
4186 return TCK_533MHZ;
4187 else
4188 return TCK_400MHZ;
4189 }
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004190}
4191
4192void perform_raminit(int s3resume)
4193{
4194 spd_raw_data spd[4];
4195
4196 post_code(0x3a);
4197
4198 memset (spd, 0, sizeof (spd));
4199 mainboard_get_spd(spd);
4200
4201 timestamp_add_now(TS_BEFORE_INITRAM);
4202
4203 init_dram_ddr3(spd, 1, get_mem_min_tck(), s3resume);
4204}