blob: 1527ec34cccb4f41492cf6d31f2611e9cdab8f04 [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>
Duncan Laurie7b508dd2012-04-09 12:30:43 -070029#include <device/pci_def.h>
Patrick Rudolphb97009e2016-02-28 15:24:04 +010030#include <memory_info.h>
31#include <smbios.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070032#include "raminit_native.h"
Stefan Reinauer00636b02012-04-04 00:08:51 +020033#include "sandybridge.h"
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070034#include <delay.h>
35#include <lib.h>
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010036#include <device/device.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020037
38/* Management Engine is in the southbridge */
39#include "southbridge/intel/bd82x6x/me.h"
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070040/* For SPD. */
41#include "southbridge/intel/bd82x6x/smbus.h"
42#include "arch/cpu.h"
43#include "cpu/x86/msr.h"
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010044#include <northbridge/intel/sandybridge/chip.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020045
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070046/* FIXME: no ECC support. */
47/* FIXME: no support for 3-channel chipsets. */
Stefan Reinauer00636b02012-04-04 00:08:51 +020048
Patrick Rudolph371d2912015-10-09 13:33:25 +020049/*
50 * Register description:
51 * Intel provides a command queue of depth four.
52 * Every command is configured by using multiple registers.
53 * On executing the command queue you have to provide the depth used.
54 *
55 * Known registers:
56 * Channel X = [0, 1]
57 * Command queue index Y = [0, 1, 2, 3]
58 *
59 * DEFAULT_MCHBAR + 0x4220 + 0x400 * X + 4 * Y: command io register
60 * Controls the DRAM command signals
61 * Bit 0: !RAS
62 * Bit 1: !CAS
63 * Bit 2: !WE
64 *
65 * DEFAULT_MCHBAR + 0x4200 + 0x400 * X + 4 * Y: addr bankslot io register
66 * Controls the address, bank address and slotrank signals
67 * Bit 0-15 : Address
68 * Bit 20-22: Bank Address
69 * Bit 24-25: slotrank
70 *
71 * DEFAULT_MCHBAR + 0x4230 + 0x400 * X + 4 * Y: idle register
72 * Controls the idle time after issuing this DRAM command
73 * Bit 16-32: number of clock-cylces to idle
74 *
75 * DEFAULT_MCHBAR + 0x4284 + 0x400 * channel: execute command queue
76 * Starts to execute all queued commands
77 * Bit 0 : start DRAM command execution
78 * Bit 16-20: (number of queued commands - 1) * 4
79 */
80
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070081#define BASEFREQ 133
82#define tDLLK 512
Stefan Reinauer00636b02012-04-04 00:08:51 +020083
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070084#define IS_SANDY_CPU(x) ((x & 0xffff0) == 0x206a0)
85#define IS_SANDY_CPU_C(x) ((x & 0xf) == 4)
86#define IS_SANDY_CPU_D0(x) ((x & 0xf) == 5)
87#define IS_SANDY_CPU_D1(x) ((x & 0xf) == 6)
88#define IS_SANDY_CPU_D2(x) ((x & 0xf) == 7)
Stefan Reinauer00636b02012-04-04 00:08:51 +020089
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070090#define IS_IVY_CPU(x) ((x & 0xffff0) == 0x306a0)
91#define IS_IVY_CPU_C(x) ((x & 0xf) == 4)
92#define IS_IVY_CPU_K(x) ((x & 0xf) == 5)
93#define IS_IVY_CPU_D(x) ((x & 0xf) == 6)
94#define IS_IVY_CPU_E(x) ((x & 0xf) >= 8)
Stefan Reinauer00636b02012-04-04 00:08:51 +020095
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070096#define NUM_CHANNELS 2
97#define NUM_SLOTRANKS 4
98#define NUM_SLOTS 2
99#define NUM_LANES 8
Stefan Reinauer00636b02012-04-04 00:08:51 +0200100
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700101/* FIXME: Vendor BIOS uses 64 but our algorithms are less
102 performant and even 1 seems to be enough in practice. */
103#define NUM_PATTERNS 4
Stefan Reinauer00636b02012-04-04 00:08:51 +0200104
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700105typedef struct odtmap_st {
106 u16 rttwr;
107 u16 rttnom;
108} odtmap;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200109
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700110typedef struct dimm_info_st {
111 dimm_attr dimm[NUM_CHANNELS][NUM_SLOTS];
112} dimm_info;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200113
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700114struct ram_rank_timings {
115 /* Register 4024. One byte per slotrank. */
116 u8 val_4024;
117 /* Register 4028. One nibble per slotrank. */
118 u8 val_4028;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200119
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700120 int val_320c;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200121
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700122 struct ram_lane_timings {
123 /* lane register offset 0x10. */
124 u16 timA; /* bits 0 - 5, bits 16 - 18 */
125 u8 rising; /* bits 8 - 14 */
126 u8 falling; /* bits 20 - 26. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200127
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700128 /* lane register offset 0x20. */
129 int timC; /* bit 0 - 5, 19. */
130 u16 timB; /* bits 8 - 13, 15 - 17. */
131 } lanes[NUM_LANES];
132};
Stefan Reinauer00636b02012-04-04 00:08:51 +0200133
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700134struct ramctr_timing_st;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200135
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700136typedef struct ramctr_timing_st {
137 int mobile;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200138
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700139 u16 cas_supported;
140 /* tLatencies are in units of ns, scaled by x256 */
141 u32 tCK;
142 u32 tAA;
143 u32 tWR;
144 u32 tRCD;
145 u32 tRRD;
146 u32 tRP;
147 u32 tRAS;
148 u32 tRFC;
149 u32 tWTR;
150 u32 tRTP;
151 u32 tFAW;
152 /* Latencies in terms of clock cycles
153 * They are saved separately as they are needed for DRAM MRS commands*/
154 u8 CAS; /* CAS read latency */
155 u8 CWL; /* CAS write latency */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200156
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700157 u32 tREFI;
158 u32 tMOD;
159 u32 tXSOffset;
160 u32 tWLO;
161 u32 tCKE;
162 u32 tXPDLL;
163 u32 tXP;
164 u32 tAONPD;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200165
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700166 u16 reg_5064b0; /* bits 0-11. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200167
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700168 u8 rankmap[NUM_CHANNELS];
169 int ref_card_offset[NUM_CHANNELS];
170 u32 mad_dimm[NUM_CHANNELS];
171 int channel_size_mb[NUM_CHANNELS];
172 u32 cmd_stretch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200173
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700174 int reg_c14_offset;
175 int reg_320c_range_threshold;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200176
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700177 int edge_offset[3];
178 int timC_offset[3];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200179
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700180 int extended_temperature_range;
181 int auto_self_refresh;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200182
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700183 int rank_mirror[NUM_CHANNELS][NUM_SLOTRANKS];
184
185 struct ram_rank_timings timings[NUM_CHANNELS][NUM_SLOTRANKS];
186} ramctr_timing;
187
188#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
189#define NORTHBRIDGE PCI_DEV(0, 0x0, 0)
190#define FOR_ALL_LANES for (lane = 0; lane < NUM_LANES; lane++)
191#define FOR_ALL_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++)
192#define FOR_ALL_POPULATED_RANKS for (slotrank = 0; slotrank < NUM_SLOTRANKS; slotrank++) if (ctrl->rankmap[channel] & (1 << slotrank))
193#define FOR_ALL_POPULATED_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) if (ctrl->rankmap[channel])
194#define MAX_EDGE_TIMING 71
195#define MAX_TIMC 127
196#define MAX_TIMB 511
197#define MAX_TIMA 127
198
199static void program_timings(ramctr_timing * ctrl, int channel);
200
201static const char *ecc_decoder[] = {
Stefan Reinauer00636b02012-04-04 00:08:51 +0200202 "inactive",
203 "active on IO",
204 "disabled on IO",
205 "active"
206};
207
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700208static void wait_txt_clear(void)
209{
210 struct cpuid_result cp;
211
212 cp = cpuid_ext(0x1, 0x0);
213 /* Check if TXT is supported? */
214 if (!(cp.ecx & 0x40))
215 return;
216 /* Some TXT public bit. */
217 if (!(read32((void *)0xfed30010) & 1))
218 return;
219 /* Wait for TXT clear. */
220 while (!(read8((void *)0xfed40000) & (1 << 7))) ;
221}
222
223static void sfence(void)
224{
225 asm volatile ("sfence");
226}
227
Patrick Rudolph9b515682015-10-09 13:43:51 +0200228static void toggle_io_reset(void) {
229 /* toggle IO reset bit */
230 u32 r32 = read32(DEFAULT_MCHBAR + 0x5030);
231 write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20);
232 udelay(1);
233 write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20);
234 udelay(1);
235}
236
Stefan Reinauer00636b02012-04-04 00:08:51 +0200237/*
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100238 * Fill cbmem with information for SMBIOS type 17.
239 */
240static void fill_smbios17(dimm_info *info, uint16_t ddr_freq)
241{
242 struct memory_info *mem_info;
243 int channel, slot;
244 struct dimm_info *dimm;
245
246 /*
247 * Allocate CBMEM area for DIMM information used to populate SMBIOS
248 * table 17
249 */
250 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
251 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
252 if (!mem_info)
253 return;
254
255 memset(mem_info, 0, sizeof(*mem_info));
256
257 FOR_ALL_CHANNELS for(slot = 0; slot < NUM_SLOTS; slot++) {
258 dimm = &mem_info->dimm[mem_info->dimm_cnt];
259 if (info->dimm[channel][slot].size_mb) {
260 dimm->ddr_type = MEMORY_TYPE_DDR3;
261 dimm->ddr_frequency = ddr_freq;
262 dimm->dimm_size = info->dimm[channel][slot].size_mb;
263 dimm->channel_num = channel;
264 dimm->rank_per_dimm = info->dimm[channel][slot].ranks;
265 dimm->dimm_num = slot;
266 memcpy(dimm->module_part_number,
267 info->dimm[channel][slot].part_number, 16);
268 dimm->mod_id = info->dimm[channel][slot].manufacturer_id;
269 dimm->mod_type = info->dimm[channel][slot].dimm_type;
270 dimm->bus_width = info->dimm[channel][slot].width;
271 mem_info->dimm_cnt++;
272 }
273 }
274}
275
276/*
Stefan Reinauer00636b02012-04-04 00:08:51 +0200277 * Dump in the log memory controller configuration as read from the memory
278 * controller registers.
279 */
280static void report_memory_config(void)
281{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700282 u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200283 int i;
284
285 addr_decoder_common = MCHBAR32(0x5000);
286 addr_decode_ch[0] = MCHBAR32(0x5004);
287 addr_decode_ch[1] = MCHBAR32(0x5008);
288
289 printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700290 (MCHBAR32(0x5e04) * 13333 * 2 + 50) / 100);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200291 printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700292 addr_decoder_common & 3, (addr_decoder_common >> 2) & 3,
Stefan Reinauer00636b02012-04-04 00:08:51 +0200293 (addr_decoder_common >> 4) & 3);
294
295 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
296 u32 ch_conf = addr_decode_ch[i];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700297 printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i,
298 ch_conf);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200299 printk(BIOS_DEBUG, " ECC %s\n",
300 ecc_decoder[(ch_conf >> 24) & 3]);
301 printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
302 ((ch_conf >> 22) & 1) ? "on" : "off");
303 printk(BIOS_DEBUG, " rank interleave %s\n",
304 ((ch_conf >> 21) & 1) ? "on" : "off");
305 printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n",
306 ((ch_conf >> 0) & 0xff) * 256,
307 ((ch_conf >> 19) & 1) ? 16 : 8,
308 ((ch_conf >> 17) & 1) ? "dual" : "single",
309 ((ch_conf >> 16) & 1) ? "" : ", selected");
310 printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n",
311 ((ch_conf >> 8) & 0xff) * 256,
312 ((ch_conf >> 20) & 1) ? 16 : 8,
313 ((ch_conf >> 18) & 1) ? "dual" : "single",
314 ((ch_conf >> 16) & 1) ? ", selected" : "");
315 }
316}
317
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700318void read_spd(spd_raw_data * spd, u8 addr)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200319{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700320 int j;
321 for (j = 0; j < 256; j++)
322 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
323}
324
325static void dram_find_spds_ddr3(spd_raw_data * spd, dimm_info * dimm,
326 ramctr_timing * ctrl)
327{
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100328 int dimms = 0, dimms_on_channel;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700329 int channel, slot, spd_slot;
330
331 memset (ctrl->rankmap, 0, sizeof (ctrl->rankmap));
332
333 ctrl->extended_temperature_range = 1;
334 ctrl->auto_self_refresh = 1;
335
336 FOR_ALL_CHANNELS {
337 ctrl->channel_size_mb[channel] = 0;
338
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100339 dimms_on_channel = 0;
340 /* count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700341 for (slot = 0; slot < NUM_SLOTS; slot++) {
342 spd_slot = 2 * channel + slot;
343 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100344 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
345 dimms_on_channel++;
346 }
347
348 for (slot = 0; slot < NUM_SLOTS; slot++) {
349 spd_slot = 2 * channel + slot;
350 /* search for XMP profile */
351 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
352 spd[spd_slot],
353 DDR3_XMP_PROFILE_1);
354
355 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
356 printram("No valid XMP profile found.\n");
357 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
358 } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
359 printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
360 dimm->dimm[channel][slot].dimms_per_channel,
361 dimms_on_channel);
362 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
363 } else if (dimm->dimm[channel][slot].voltage != 1500) {
364 /* TODO: support other DDR3 voltage than 1500mV */
365 printram("XMP profile's requested %u mV is unsupported.\n",
366 dimm->dimm[channel][slot].voltage);
367 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
368 }
369
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700370 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
371 // set dimm invalid
372 dimm->dimm[channel][slot].ranks = 0;
373 dimm->dimm[channel][slot].size_mb = 0;
374 continue;
375 }
376
377 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
378 dimms++;
379 ctrl->rank_mirror[channel][slot * 2] = 0;
380 ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
381 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
382
383 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
384 ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
385
386 ctrl->rankmap[channel] |= ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100387 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n",
388 channel, ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700389 }
390 if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc)
391 && dimm->dimm[channel][0].reference_card <= 5 && dimm->dimm[channel][1].reference_card <= 5) {
392 const int ref_card_offset_table[6][6] = {
393 { 0, 0, 0, 0, 2, 2, },
394 { 0, 0, 0, 0, 2, 2, },
395 { 0, 0, 0, 0, 2, 2, },
396 { 0, 0, 0, 0, 1, 1, },
397 { 2, 2, 2, 1, 0, 0, },
398 { 2, 2, 2, 1, 0, 0, },
399 };
400 ctrl->ref_card_offset[channel] = ref_card_offset_table[dimm->dimm[channel][0].reference_card]
401 [dimm->dimm[channel][1].reference_card];
402 } else
403 ctrl->ref_card_offset[channel] = 0;
404 }
405
406 if (!dimms)
407 die("No DIMMs were found");
408}
409
410static void dram_find_common_params(const dimm_info * dimms,
411 ramctr_timing * ctrl)
412{
413 size_t valid_dimms;
414 int channel, slot;
415 ctrl->cas_supported = 0xff;
416 valid_dimms = 0;
417 FOR_ALL_CHANNELS for (slot = 0; slot < 2; slot++) {
418 const dimm_attr *dimm = &dimms->dimm[channel][slot];
419 if (dimm->dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3)
420 continue;
421 valid_dimms++;
422
423 /* Find all possible CAS combinations */
424 ctrl->cas_supported &= dimm->cas_supported;
425
426 /* Find the smallest common latencies supported by all DIMMs */
427 ctrl->tCK = MAX(ctrl->tCK, dimm->tCK);
428 ctrl->tAA = MAX(ctrl->tAA, dimm->tAA);
429 ctrl->tWR = MAX(ctrl->tWR, dimm->tWR);
430 ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD);
431 ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD);
432 ctrl->tRP = MAX(ctrl->tRP, dimm->tRP);
433 ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS);
434 ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC);
435 ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR);
436 ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP);
437 ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW);
438 }
439
440 if (!ctrl->cas_supported)
441 die("Unsupported DIMM combination. "
442 "DIMMS do not support common CAS latency");
443 if (!valid_dimms)
444 die("No valid DIMMs found");
445}
446
447static u8 get_CWL(u8 CAS)
448{
449 /* Get CWL based on CAS using the following rule:
450 * _________________________________________
451 * CAS: | 4T | 5T | 6T | 7T | 8T | 9T | 10T | 11T |
452 * CWL: | 5T | 5T | 5T | 6T | 6T | 7T | 7T | 8T |
453 */
454 static const u8 cas_cwl_map[] = { 5, 5, 5, 6, 6, 7, 7, 8 };
455 if (CAS > 11)
456 return 8;
457 return cas_cwl_map[CAS - 4];
458}
459
460/* Frequency multiplier. */
461static u32 get_FRQ(u32 tCK)
462{
463 u32 FRQ;
464 FRQ = 256000 / (tCK * BASEFREQ);
465 if (FRQ > 8)
466 return 8;
467 if (FRQ < 3)
468 return 3;
469 return FRQ;
470}
471
472static u32 get_REFI(u32 tCK)
473{
474 /* Get REFI based on MCU frequency using the following rule:
475 * _________________________________________
476 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
477 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 |
478 */
479 static const u32 frq_refi_map[] =
480 { 3120, 4160, 5200, 6240, 7280, 8320 };
481 return frq_refi_map[get_FRQ(tCK) - 3];
482}
483
484static u8 get_XSOffset(u32 tCK)
485{
486 /* Get XSOffset based on MCU frequency using the following rule:
487 * _________________________
488 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
489 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 |
490 */
491 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 };
492 return frq_xs_map[get_FRQ(tCK) - 3];
493}
494
495static u8 get_MOD(u32 tCK)
496{
497 /* Get MOD based on MCU frequency using the following rule:
498 * _____________________________
499 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
500 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 |
501 */
502 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 };
503 return frq_mod_map[get_FRQ(tCK) - 3];
504}
505
506static u8 get_WLO(u32 tCK)
507{
508 /* Get WLO based on MCU frequency using the following rule:
509 * _______________________
510 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
511 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 |
512 */
513 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 };
514 return frq_wlo_map[get_FRQ(tCK) - 3];
515}
516
517static u8 get_CKE(u32 tCK)
518{
519 /* Get CKE based on MCU frequency using the following rule:
520 * _______________________
521 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
522 * CKE : | 3 | 3 | 4 | 4 | 5 | 6 |
523 */
524 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 };
525 return frq_cke_map[get_FRQ(tCK) - 3];
526}
527
528static u8 get_XPDLL(u32 tCK)
529{
530 /* Get XPDLL based on MCU frequency using the following rule:
531 * _____________________________
532 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
533 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 |
534 */
535 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 };
536 return frq_xpdll_map[get_FRQ(tCK) - 3];
537}
538
539static u8 get_XP(u32 tCK)
540{
541 /* Get XP based on MCU frequency using the following rule:
542 * _______________________
543 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
544 * XP : | 3 | 4 | 4 | 5 | 6 | 7 |
545 */
546 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 };
547 return frq_xp_map[get_FRQ(tCK) - 3];
548}
549
550static u8 get_AONPD(u32 tCK)
551{
552 /* Get AONPD based on MCU frequency using the following rule:
553 * ________________________
554 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
555 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 |
556 */
557 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 };
558 return frq_aonpd_map[get_FRQ(tCK) - 3];
559}
560
561static u32 get_COMP2(u32 tCK)
562{
563 /* Get COMP2 based on MCU frequency using the following rule:
564 * ___________________________________________________________
565 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
566 * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C |
567 */
568 static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C,
569 0xC6369CC, 0xC42514C, 0xC21410C
570 };
571 return frq_comp2_map[get_FRQ(tCK) - 3];
572}
573
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100574static u32 get_XOVER_CLK(u8 rankmap)
575{
576 return rankmap << 24;
577}
578
579static u32 get_XOVER_CMD(u8 rankmap)
580{
581 u32 reg;
582
583 // enable xover cmd
584 reg = 0x4000;
585
586 // enable xover ctl
587 if (rankmap & 0x3)
588 reg |= 0x20000;
589
590 if (rankmap & 0xc)
591 reg |= 0x4000000;
592
593 return reg;
594}
595
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700596static void dram_timing(ramctr_timing * ctrl)
597{
598 u8 val;
599 u32 val32;
600
601 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
602 * we cap it if we have faster DIMMs.
603 * Then, align it to the closest JEDEC standard frequency */
604 if (ctrl->tCK <= TCK_1066MHZ) {
605 ctrl->tCK = TCK_1066MHZ;
606 ctrl->edge_offset[0] = 16;
607 ctrl->edge_offset[1] = 7;
608 ctrl->edge_offset[2] = 7;
609 ctrl->timC_offset[0] = 18;
610 ctrl->timC_offset[1] = 7;
611 ctrl->timC_offset[2] = 7;
612 ctrl->reg_c14_offset = 16;
613 ctrl->reg_5064b0 = 0x218;
614 ctrl->reg_320c_range_threshold = 13;
615 } else if (ctrl->tCK <= TCK_933MHZ) {
616 ctrl->tCK = TCK_933MHZ;
617 ctrl->edge_offset[0] = 14;
618 ctrl->edge_offset[1] = 6;
619 ctrl->edge_offset[2] = 6;
620 ctrl->timC_offset[0] = 15;
621 ctrl->timC_offset[1] = 6;
622 ctrl->timC_offset[2] = 6;
623 ctrl->reg_c14_offset = 14;
624 ctrl->reg_5064b0 = 0x1d5;
625 ctrl->reg_320c_range_threshold = 15;
626 } else if (ctrl->tCK <= TCK_800MHZ) {
627 ctrl->tCK = TCK_800MHZ;
628 ctrl->edge_offset[0] = 13;
629 ctrl->edge_offset[1] = 5;
630 ctrl->edge_offset[2] = 5;
631 ctrl->timC_offset[0] = 14;
632 ctrl->timC_offset[1] = 5;
633 ctrl->timC_offset[2] = 5;
634 ctrl->reg_c14_offset = 12;
635 ctrl->reg_5064b0 = 0x193;
636 ctrl->reg_320c_range_threshold = 15;
637 } else if (ctrl->tCK <= TCK_666MHZ) {
638 ctrl->tCK = TCK_666MHZ;
639 ctrl->edge_offset[0] = 10;
640 ctrl->edge_offset[1] = 4;
641 ctrl->edge_offset[2] = 4;
642 ctrl->timC_offset[0] = 11;
643 ctrl->timC_offset[1] = 4;
644 ctrl->timC_offset[2] = 4;
645 ctrl->reg_c14_offset = 10;
646 ctrl->reg_5064b0 = 0x150;
647 ctrl->reg_320c_range_threshold = 16;
648 } else if (ctrl->tCK <= TCK_533MHZ) {
649 ctrl->tCK = TCK_533MHZ;
650 ctrl->edge_offset[0] = 8;
651 ctrl->edge_offset[1] = 3;
652 ctrl->edge_offset[2] = 3;
653 ctrl->timC_offset[0] = 9;
654 ctrl->timC_offset[1] = 3;
655 ctrl->timC_offset[2] = 3;
656 ctrl->reg_c14_offset = 8;
657 ctrl->reg_5064b0 = 0x10d;
658 ctrl->reg_320c_range_threshold = 17;
659 } else {
660 ctrl->tCK = TCK_400MHZ;
661 ctrl->edge_offset[0] = 6;
662 ctrl->edge_offset[1] = 2;
663 ctrl->edge_offset[2] = 2;
664 ctrl->timC_offset[0] = 6;
665 ctrl->timC_offset[1] = 2;
666 ctrl->timC_offset[2] = 2;
667 ctrl->reg_c14_offset = 8;
668 ctrl->reg_5064b0 = 0xcd;
669 ctrl->reg_320c_range_threshold = 17;
670 }
671
672 val32 = (1000 << 8) / ctrl->tCK;
673 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
674
675 /* Find CAS and CWL latencies */
676 val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK;
677 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
678 /* Find lowest supported CAS latency that satisfies the minimum value */
679 while (!((ctrl->cas_supported >> (val - 4)) & 1)
680 && (ctrl->cas_supported >> (val - 4))) {
681 val++;
682 }
683 /* Is CAS supported */
684 if (!(ctrl->cas_supported & (1 << (val - 4))))
685 printk(BIOS_DEBUG, "CAS not supported\n");
686 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
687 ctrl->CAS = val;
688 ctrl->CWL = get_CWL(ctrl->CAS);
689 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
690
691 /* Find tRCD */
692 ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK;
693 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
694
695 ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK;
696 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
697
698 /* Find tRAS */
699 ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK;
700 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
701
702 /* Find tWR */
703 ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK;
704 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
705
706 /* Find tFAW */
707 ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK;
708 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
709
710 /* Find tRRD */
711 ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK;
712 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
713
714 /* Find tRTP */
715 ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK;
716 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
717
718 /* Find tWTR */
719 ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK;
720 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
721
722 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
723 ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK;
724 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
725
726 ctrl->tREFI = get_REFI(ctrl->tCK);
727 ctrl->tMOD = get_MOD(ctrl->tCK);
728 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
729 ctrl->tWLO = get_WLO(ctrl->tCK);
730 ctrl->tCKE = get_CKE(ctrl->tCK);
731 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
732 ctrl->tXP = get_XP(ctrl->tCK);
733 ctrl->tAONPD = get_AONPD(ctrl->tCK);
734}
735
736static void dram_freq(ramctr_timing * ctrl)
737{
738 if (ctrl->tCK > TCK_400MHZ) {
739 printk (BIOS_ERR, "DRAM frequency is under lowest supported frequency (400 MHz). Increasing to 400 MHz as last resort");
740 ctrl->tCK = TCK_400MHZ;
741 }
742 while (1) {
743 u8 val2;
744 u32 reg1 = 0;
745
746 /* Step 1 - Set target PCU frequency */
747
748 if (ctrl->tCK <= TCK_1066MHZ) {
749 ctrl->tCK = TCK_1066MHZ;
750 } else if (ctrl->tCK <= TCK_933MHZ) {
751 ctrl->tCK = TCK_933MHZ;
752 } else if (ctrl->tCK <= TCK_800MHZ) {
753 ctrl->tCK = TCK_800MHZ;
754 } else if (ctrl->tCK <= TCK_666MHZ) {
755 ctrl->tCK = TCK_666MHZ;
756 } else if (ctrl->tCK <= TCK_533MHZ) {
757 ctrl->tCK = TCK_533MHZ;
758 } else if (ctrl->tCK <= TCK_400MHZ) {
759 ctrl->tCK = TCK_400MHZ;
760 } else {
761 die ("No lock frequency found");
762 }
763
764 /* Frequency mulitplier. */
765 u32 FRQ = get_FRQ(ctrl->tCK);
766
767 /* Step 2 - Select frequency in the MCU */
768 reg1 = FRQ;
769 reg1 |= 0x80000000; // set running bit
770 MCHBAR32(0x5e00) = reg1;
771 while (reg1 & 0x80000000) {
772 printk(BIOS_DEBUG, " PLL busy...");
773 reg1 = MCHBAR32(0x5e00);
774 }
775 printk(BIOS_DEBUG, "done\n");
776
777 /* Step 3 - Verify lock frequency */
778 reg1 = MCHBAR32(0x5e04);
779 val2 = (u8) reg1;
780 if (val2 >= FRQ) {
781 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
782 (1000 << 8) / ctrl->tCK);
783 return;
784 }
785 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
786 ctrl->tCK++;
787 }
788}
789
790static void dram_xover(ramctr_timing * ctrl)
791{
792 u32 reg;
793 int channel;
794
795 FOR_ALL_CHANNELS {
796 // enable xover clk
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100797 reg = get_XOVER_CLK(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100798 printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
799 reg);
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100800 MCHBAR32(channel * 0x100 + 0xc14) = reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700801
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100802 // enable xover ctl & xover cmd
803 reg = get_XOVER_CMD(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100804 printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
805 reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700806 MCHBAR32(0x100 * channel + 0x320c) = reg;
807 }
808}
809
810static void dram_timing_regs(ramctr_timing * ctrl)
811{
812 u32 reg, addr, val32, cpu, stretch;
813 struct cpuid_result cpures;
814 int channel;
815
816 FOR_ALL_CHANNELS {
817 // DBP
818 reg = 0;
819 reg |= ctrl->tRCD;
820 reg |= (ctrl->tRP << 4);
821 reg |= (ctrl->CAS << 8);
822 reg |= (ctrl->CWL << 12);
823 reg |= (ctrl->tRAS << 16);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100824 printram("DBP [%x] = %x\n", 0x400 * channel + 0x4000, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700825 MCHBAR32(0x400 * channel + 0x4000) = reg;
826
827 // RAP
828 reg = 0;
829 reg |= ctrl->tRRD;
830 reg |= (ctrl->tRTP << 4);
831 reg |= (ctrl->tCKE << 8);
832 reg |= (ctrl->tWTR << 12);
833 reg |= (ctrl->tFAW << 16);
834 reg |= (ctrl->tWR << 24);
835 reg |= (3 << 30);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100836 printram("RAP [%x] = %x\n", 0x400 * channel + 0x4004, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700837 MCHBAR32(0x400 * channel + 0x4004) = reg;
838
839 // OTHP
840 addr = 0x400 * channel + 0x400c;
841 reg = 0;
842 reg |= ctrl->tXPDLL;
843 reg |= (ctrl->tXP << 5);
844 reg |= (ctrl->tAONPD << 8);
845 reg |= 0xa0000;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100846 printram("OTHP [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700847 MCHBAR32(addr) = reg;
848
849 MCHBAR32(0x400 * channel + 0x4014) = 0;
850
851 MCHBAR32(addr) |= 0x00020000;
852
853 // ODT stretch
854 reg = 0;
855
856 cpures = cpuid(0);
857 cpu = cpures.eax;
858 if (IS_IVY_CPU(cpu)
859 || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) {
860 stretch = 2;
861 addr = 0x400 * channel + 0x400c;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100862 printram("ODT stretch [%x] = %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700863 0x400 * channel + 0x400c, reg);
864 reg = MCHBAR32(addr);
865
866 if (((ctrl->rankmap[channel] & 3) == 0)
867 || (ctrl->rankmap[channel] & 0xc) == 0) {
868
869 // Rank 0 - operate on rank 2
870 reg = (reg & ~0xc0000) | (stretch << 18);
871
872 // Rank 2 - operate on rank 0
873 reg = (reg & ~0x30000) | (stretch << 16);
874
Patrick Rudolpha649a542016-01-17 18:32:06 +0100875 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700876 MCHBAR32(addr) = reg;
877 }
878
879 } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) {
880 stretch = 3;
881 addr = 0x400 * channel + 0x401c;
882 reg = MCHBAR32(addr);
883
884 if (((ctrl->rankmap[channel] & 3) == 0)
885 || (ctrl->rankmap[channel] & 0xc) == 0) {
886
887 // Rank 0 - operate on rank 2
888 reg = (reg & ~0x3000) | (stretch << 12);
889
890 // Rank 2 - operate on rank 0
891 reg = (reg & ~0xc00) | (stretch << 10);
892
Patrick Rudolpha649a542016-01-17 18:32:06 +0100893 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700894 MCHBAR32(addr) = reg;
895 }
896 } else {
897 stretch = 0;
898 }
899
900 // REFI
901 reg = 0;
902 val32 = ctrl->tREFI;
903 reg = (reg & ~0xffff) | val32;
904 val32 = ctrl->tRFC;
905 reg = (reg & ~0x1ff0000) | (val32 << 16);
906 val32 = (u32) (ctrl->tREFI * 9) / 1024;
907 reg = (reg & ~0xfe000000) | (val32 << 25);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100908 printram("REFI [%x] = %x\n", 0x400 * channel + 0x4298,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700909 reg);
910 MCHBAR32(0x400 * channel + 0x4298) = reg;
911
912 MCHBAR32(0x400 * channel + 0x4294) |= 0xff;
913
914 // SRFTP
915 reg = 0;
916 val32 = tDLLK;
917 reg = (reg & ~0xfff) | val32;
918 val32 = ctrl->tXSOffset;
919 reg = (reg & ~0xf000) | (val32 << 12);
920 val32 = tDLLK - ctrl->tXSOffset;
921 reg = (reg & ~0x3ff0000) | (val32 << 16);
922 val32 = ctrl->tMOD - 8;
923 reg = (reg & ~0xf0000000) | (val32 << 28);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100924 printram("SRFTP [%x] = %x\n", 0x400 * channel + 0x42a4,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700925 reg);
926 MCHBAR32(0x400 * channel + 0x42a4) = reg;
927 }
928}
929
930static void dram_dimm_mapping(dimm_info * info, ramctr_timing * ctrl)
931{
932 u32 reg, val32;
933 int channel;
934
935 FOR_ALL_CHANNELS {
936 dimm_attr *dimmA = 0;
937 dimm_attr *dimmB = 0;
938 reg = 0;
939 val32 = 0;
940 if (info->dimm[channel][0].size_mb >=
941 info->dimm[channel][1].size_mb) {
942 // dimm 0 is bigger, set it to dimmA
943 dimmA = &info->dimm[channel][0];
944 dimmB = &info->dimm[channel][1];
945 reg |= (0 << 16);
946 } else {
947 // dimm 1 is bigger, set it to dimmA
948 dimmA = &info->dimm[channel][1];
949 dimmB = &info->dimm[channel][0];
950 reg |= (1 << 16);
951 }
952 // dimmA
953 if (dimmA && (dimmA->ranks > 0)) {
954 val32 = dimmA->size_mb / 256;
955 reg = (reg & ~0xff) | val32;
956 val32 = dimmA->ranks - 1;
957 reg = (reg & ~0x20000) | (val32 << 17);
958 val32 = (dimmA->width / 8) - 1;
959 reg = (reg & ~0x80000) | (val32 << 19);
960 }
961 // dimmB
962 if (dimmB && (dimmB->ranks > 0)) {
963 val32 = dimmB->size_mb / 256;
964 reg = (reg & ~0xff00) | (val32 << 8);
965 val32 = dimmB->ranks - 1;
966 reg = (reg & ~0x40000) | (val32 << 18);
967 val32 = (dimmB->width / 8) - 1;
968 reg = (reg & ~0x100000) | (val32 << 20);
969 }
970 reg = (reg & ~0x200000) | (1 << 21); // rank interleave
971 reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave
972
973 // Save MAD-DIMM register
974 if ((dimmA && (dimmA->ranks > 0))
975 || (dimmB && (dimmB->ranks > 0))) {
976 ctrl->mad_dimm[channel] = reg;
977 } else {
978 ctrl->mad_dimm[channel] = 0;
979 }
980 }
981}
982
983static void dram_dimm_set_mapping(ramctr_timing * ctrl)
984{
985 int channel;
986 FOR_ALL_CHANNELS {
987 MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
988 }
989}
990
991static void dram_zones(ramctr_timing * ctrl, int training)
992{
993 u32 reg, ch0size, ch1size;
994 u8 val;
995 reg = 0;
996 val = 0;
997 if (training) {
998 ch0size = ctrl->channel_size_mb[0] ? 256 : 0;
999 ch1size = ctrl->channel_size_mb[1] ? 256 : 0;
1000 } else {
1001 ch0size = ctrl->channel_size_mb[0];
1002 ch1size = ctrl->channel_size_mb[1];
1003 }
1004
1005 if (ch0size >= ch1size) {
1006 reg = MCHBAR32(0x5014);
1007 val = ch1size / 256;
1008 reg = (reg & ~0xff000000) | val << 24;
1009 reg = (reg & ~0xff0000) | (2 * val) << 16;
1010 MCHBAR32(0x5014) = reg;
1011 MCHBAR32(0x5000) = 0x24;
1012 } else {
1013 reg = MCHBAR32(0x5014);
1014 val = ch0size / 256;
1015 reg = (reg & ~0xff000000) | val << 24;
1016 reg = (reg & ~0xff0000) | (2 * val) << 16;
1017 MCHBAR32(0x5014) = reg;
1018 MCHBAR32(0x5000) = 0x21;
1019 }
1020}
1021
1022static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
1023{
1024 u32 reg, val, reclaim;
1025 u32 tom, gfxstolen, gttsize;
1026 size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase,
1027 tsegbase, mestolenbase;
1028 size_t tsegbasedelta, remapbase, remaplimit;
1029 uint16_t ggc;
1030
1031 mmiosize = 0x400;
1032
1033 ggc = pci_read_config16(NORTHBRIDGE, GGC);
1034 if (!(ggc & 2)) {
1035 gfxstolen = ((ggc >> 3) & 0x1f) * 32;
1036 gttsize = ((ggc >> 8) & 0x3);
1037 } else {
1038 gfxstolen = 0;
1039 gttsize = 0;
1040 }
1041
1042 tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
1043
1044 tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
1045
1046 mestolenbase = tom - me_uma_size;
1047
1048 toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
1049 tom - me_uma_size);
1050 gfxstolenbase = toludbase - gfxstolen;
1051 gttbase = gfxstolenbase - gttsize;
1052
1053 tsegbase = gttbase - tsegsize;
1054
1055 // Round tsegbase down to nearest address aligned to tsegsize
1056 tsegbasedelta = tsegbase & (tsegsize - 1);
1057 tsegbase &= ~(tsegsize - 1);
1058
1059 gttbase -= tsegbasedelta;
1060 gfxstolenbase -= tsegbasedelta;
1061 toludbase -= tsegbasedelta;
1062
1063 // Test if it is possible to reclaim a hole in the ram addressing
1064 if (tom - me_uma_size > toludbase) {
1065 // Reclaim is possible
1066 reclaim = 1;
1067 remapbase = MAX(4096, tom - me_uma_size);
1068 remaplimit =
1069 remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1;
1070 touudbase = remaplimit + 1;
1071 } else {
1072 // Reclaim not possible
1073 reclaim = 0;
1074 touudbase = tom - me_uma_size;
1075 }
1076
1077 // Update memory map in pci-e configuration space
Patrick Rudolpha649a542016-01-17 18:32:06 +01001078 printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001079
1080 // TOM (top of memory)
1081 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0);
1082 val = tom & 0xfff;
1083 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001084 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001085 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg);
1086
1087 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4);
1088 val = tom & 0xfffff000;
1089 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001090 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001091 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg);
1092
1093 // TOLUD (top of low used dram)
1094 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
1095 val = toludbase & 0xfff;
1096 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001097 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xbc, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001098 pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg);
1099
1100 // TOUUD LSB (top of upper usable dram)
1101 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
1102 val = touudbase & 0xfff;
1103 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001104 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001105 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg);
1106
1107 // TOUUD MSB
1108 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
1109 val = touudbase & 0xfffff000;
1110 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001111 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xac, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001112 pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg);
1113
1114 if (reclaim) {
1115 // REMAP BASE
1116 pcie_write_config32(PCI_DEV(0, 0, 0), 0x90, remapbase << 20);
1117 pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, remapbase >> 12);
1118
1119 // REMAP LIMIT
1120 pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
1121 pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
1122 }
1123 // TSEG
1124 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
1125 val = tsegbase & 0xfff;
1126 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001127 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001128 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg);
1129
1130 // GFX stolen memory
1131 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0);
1132 val = gfxstolenbase & 0xfff;
1133 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001134 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001135 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg);
1136
1137 // GTT stolen memory
1138 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4);
1139 val = gttbase & 0xfff;
1140 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001141 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001142 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
1143
1144 if (me_uma_size) {
1145 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
1146 val = (0x80000 - me_uma_size) & 0xfffff000;
1147 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001148 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x7c, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001149 pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg);
1150
1151 // ME base
1152 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70);
1153 val = mestolenbase & 0xfff;
1154 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001155 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x70, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001156 pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg);
1157
1158 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74);
1159 val = mestolenbase & 0xfffff000;
1160 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001161 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x74, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001162 pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg);
1163
1164 // ME mask
1165 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78);
1166 val = (0x80000 - me_uma_size) & 0xfff;
1167 reg = (reg & ~0xfff00000) | (val << 20);
1168 reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem
1169
1170 reg = (reg & ~0x800) | (1 << 11); // set ME memory enable
Patrick Rudolpha649a542016-01-17 18:32:06 +01001171 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x78, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001172 pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg);
1173 }
1174}
1175
1176static void dram_ioregs(ramctr_timing * ctrl)
1177{
1178 u32 reg, comp2;
1179
1180 int channel;
1181
1182 // IO clock
1183 FOR_ALL_CHANNELS {
1184 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
1185 }
1186
1187 // IO command
1188 FOR_ALL_CHANNELS {
1189 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
1190 }
1191
1192 // IO control
1193 FOR_ALL_POPULATED_CHANNELS {
1194 program_timings(ctrl, channel);
1195 }
1196
1197 // Rcomp
Patrick Rudolpha649a542016-01-17 18:32:06 +01001198 printram("RCOMP...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001199 reg = 0;
1200 while (reg == 0) {
1201 reg = MCHBAR32(0x5084) & 0x10000;
1202 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001203 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001204
1205 // Set comp2
1206 comp2 = get_COMP2(ctrl->tCK);
1207 MCHBAR32(0x3714) = comp2;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001208 printram("COMP2 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001209
1210 // Set comp1
1211 FOR_ALL_POPULATED_CHANNELS {
1212 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
1213 reg = (reg & ~0xe00) | (1 << 9); //odt
1214 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
1215 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
1216 MCHBAR32(0x1810 + channel * 0x100) = reg;
1217 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001218 printram("COMP1 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001219
Patrick Rudolpha649a542016-01-17 18:32:06 +01001220 printram("FORCE RCOMP and wait 20us...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001221 MCHBAR32(0x5f08) |= 0x100;
1222 udelay(20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001223 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001224}
1225
1226static void wait_428c(int channel)
1227{
1228 while (1) {
1229 if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
1230 return;
1231 }
1232}
1233
1234static void write_reset(ramctr_timing * ctrl)
1235{
1236 int channel, slotrank;
1237
1238 /* choose a populated channel. */
1239 channel = (ctrl->rankmap[0]) ? 0 : 1;
1240
1241 wait_428c(channel);
1242
1243 /* choose a populated rank. */
1244 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
1245
Patrick Rudolph371d2912015-10-09 13:33:25 +02001246 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001247 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1248 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01);
1249
1250 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1251 (slotrank << 24) | 0x60000);
1252
1253 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1254
1255 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001);
1256 wait_428c(channel);
1257}
1258
1259static void dram_jedecreset(ramctr_timing * ctrl)
1260{
1261 u32 reg, addr;
1262 int channel;
1263
1264 while (!(MCHBAR32(0x5084) & 0x10000)) ;
1265 do {
1266 reg = MCHBAR32(0x428c);
1267 } while ((reg & 0x14) == 0);
1268
1269 // Set state of memory controller
1270 reg = 0x112;
1271 MCHBAR32(0x5030) = reg;
1272 MCHBAR32(0x4ea0) = 0;
1273 reg |= 2; //ddr reset
1274 MCHBAR32(0x5030) = reg;
1275
1276 // Assert dimm reset signal
1277 reg = MCHBAR32(0x5030);
1278 reg &= ~0x2;
1279 MCHBAR32(0x5030) = reg;
1280
1281 // Wait 200us
1282 udelay(200);
1283
1284 // Deassert dimm reset signal
1285 MCHBAR32(0x5030) |= 2;
1286
1287 // Wait 500us
1288 udelay(500);
1289
1290 // Enable DCLK
1291 MCHBAR32(0x5030) |= 4;
1292
1293 // XXX Wait 20ns
1294 udelay(1);
1295
1296 FOR_ALL_CHANNELS {
1297 // Set valid rank CKE
1298 reg = 0;
1299 reg = (reg & ~0xf) | ctrl->rankmap[channel];
1300 addr = 0x400 * channel + 0x42a0;
1301 MCHBAR32(addr) = reg;
1302
1303 // Wait 10ns for ranks to settle
1304 //udelay(0.01);
1305
1306 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
1307 MCHBAR32(addr) = reg;
1308
1309 // Write reset using a NOP
1310 write_reset(ctrl);
1311 }
1312}
1313
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001314static odtmap get_ODT(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001315{
1316 /* Get ODT based on rankmap: */
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001317 int dimms_per_ch = (ctrl->rankmap[channel] & 1)
1318 + ((ctrl->rankmap[channel] >> 2) & 1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001319
1320 if (dimms_per_ch == 1) {
1321 return (const odtmap){60, 60};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001322 } else {
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001323 return (const odtmap){120, 30};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001324 }
1325}
1326
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001327static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001328 int reg, u32 val)
1329{
1330 wait_428c(channel);
1331
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001332 if (ctrl->rank_mirror[channel][slotrank]) {
1333 /* DDR3 Rank1 Address mirror
1334 * swap the following pins:
1335 * A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 */
1336 reg = ((reg >> 1) & 1) | ((reg << 1) & 2);
1337 val = (val & ~0x1f8) | ((val >> 1) & 0xa8)
1338 | ((val & 0xa8) << 1);
1339 }
1340
Patrick Rudolph371d2912015-10-09 13:33:25 +02001341 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001342 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000);
1343 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
1344 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1345 (slotrank << 24) | (reg << 20) | val | 0x60000);
1346 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1347
Patrick Rudolph371d2912015-10-09 13:33:25 +02001348 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001349 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000);
1350 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001);
1351 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
1352 (slotrank << 24) | (reg << 20) | val | 0x60000);
1353 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1354
Patrick Rudolph371d2912015-10-09 13:33:25 +02001355 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001356 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000);
1357 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1358 0x1001 | (ctrl->tMOD << 16));
1359 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1360 (slotrank << 24) | (reg << 20) | val | 0x60000);
1361 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1362 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
1363}
1364
1365static u32 make_mr0(ramctr_timing * ctrl, u8 rank)
1366{
1367 u16 mr0reg, mch_cas, mch_wr;
1368 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 +02001369
1370 /* DLL Reset - self clearing - set after CLK frequency has been changed */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001371 mr0reg = 0x100;
1372
1373 // Convert CAS to MCH register friendly
1374 if (ctrl->CAS < 12) {
1375 mch_cas = (u16) ((ctrl->CAS - 4) << 1);
1376 } else {
1377 mch_cas = (u16) (ctrl->CAS - 12);
1378 mch_cas = ((mch_cas << 1) | 0x1);
1379 }
1380
1381 // Convert tWR to MCH register friendly
1382 mch_wr = mch_wr_t[ctrl->tWR - 5];
1383
1384 mr0reg = (mr0reg & ~0x4) | (mch_cas & 0x1);
1385 mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3);
1386 mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001387
1388 // Precharge PD - Fast (desktop) 0x1 or slow (mobile) 0x0 - mostly power-saving feature
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001389 mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12);
1390 return mr0reg;
1391}
1392
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001393static void dram_mr0(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001394{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001395 write_mrreg(ctrl, channel, rank, 0,
1396 make_mr0(ctrl, rank));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001397}
1398
1399static u32 encode_odt(u32 odt)
1400{
1401 switch (odt) {
1402 case 30:
1403 return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4
1404 case 60:
1405 return (1 << 2); // RZQ/4
1406 case 120:
1407 return (1 << 6); // RZQ/2
1408 default:
1409 case 0:
1410 return 0;
1411 }
1412}
1413
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001414static u32 make_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001415{
1416 odtmap odt;
1417 u32 mr1reg;
1418
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001419 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001420 mr1reg = 0x2;
1421
1422 mr1reg |= encode_odt(odt.rttnom);
1423
1424 return mr1reg;
1425}
1426
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001427static void dram_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001428{
1429 u16 mr1reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001430
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001431 mr1reg = make_mr1(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001432
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001433 write_mrreg(ctrl, channel, rank, 1, mr1reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001434}
1435
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001436static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001437{
1438 u16 pasr, cwl, mr2reg;
1439 odtmap odt;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001440 int srt;
1441
1442 pasr = 0;
1443 cwl = ctrl->CWL - 5;
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001444 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001445
1446 srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh;
1447
1448 mr2reg = 0;
1449 mr2reg = (mr2reg & ~0x7) | pasr;
1450 mr2reg = (mr2reg & ~0x38) | (cwl << 3);
1451 mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6);
1452 mr2reg = (mr2reg & ~0x80) | (srt << 7);
1453 mr2reg |= (odt.rttwr / 60) << 9;
1454
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001455 write_mrreg(ctrl, channel, rank, 2, mr2reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001456}
1457
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001458static void dram_mr3(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001459{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001460 write_mrreg(ctrl, channel, rank, 3, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001461}
1462
1463static void dram_mrscommands(ramctr_timing * ctrl)
1464{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001465 u8 slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001466 u32 reg, addr;
1467 int channel;
1468
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001469 FOR_ALL_POPULATED_CHANNELS {
1470 FOR_ALL_POPULATED_RANKS {
1471 // MR2
1472 dram_mr2(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001473
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001474 // MR3
1475 dram_mr3(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001476
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001477 // MR1
1478 dram_mr1(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001479
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001480 // MR0
1481 dram_mr0(ctrl, slotrank, channel);
1482 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001483 }
1484
Patrick Rudolph371d2912015-10-09 13:33:25 +02001485 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001486 write32(DEFAULT_MCHBAR + 0x4e20, 0x7);
1487 write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001);
1488 write32(DEFAULT_MCHBAR + 0x4e00, 0x60002);
1489 write32(DEFAULT_MCHBAR + 0x4e10, 0);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001490
1491 /* DRAM command ZQCL */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001492 write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003);
1493 write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001);
1494 write32(DEFAULT_MCHBAR + 0x4e04, 0x60400);
1495 write32(DEFAULT_MCHBAR + 0x4e14, 0x288);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001496
1497 /* execute command queue on all channels ? */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001498 write32(DEFAULT_MCHBAR + 0x4e84, 0x40004);
1499
1500 // Drain
1501 FOR_ALL_CHANNELS {
1502 // Wait for ref drained
1503 wait_428c(channel);
1504 }
1505
1506 // Refresh enable
1507 MCHBAR32(0x5030) |= 8;
1508
1509 FOR_ALL_POPULATED_CHANNELS {
1510 addr = 0x400 * channel + 0x4020;
1511 reg = MCHBAR32(addr);
1512 reg &= ~0x200000;
1513 MCHBAR32(addr) = reg;
1514
1515 wait_428c(channel);
1516
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001517 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001518
1519 // Drain
1520 wait_428c(channel);
1521
Patrick Rudolph371d2912015-10-09 13:33:25 +02001522 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001523 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1524 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
1525 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001526 (slotrank << 24) | 0x60000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001527 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
1528 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1);
1529
1530 // Drain
1531 wait_428c(channel);
1532 }
1533}
1534
1535const u32 lane_registers[] = {
1536 0x0000, 0x0200, 0x0400, 0x0600,
1537 0x1000, 0x1200, 0x1400, 0x1600,
1538 0x0800
1539};
1540
1541static void program_timings(ramctr_timing * ctrl, int channel)
1542{
1543 u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028;
1544 int lane;
1545 int slotrank, slot;
1546 int full_shift = 0;
1547 u16 slot320c[NUM_SLOTS];
1548
1549 FOR_ALL_POPULATED_RANKS {
1550 if (full_shift < -ctrl->timings[channel][slotrank].val_320c)
1551 full_shift = -ctrl->timings[channel][slotrank].val_320c;
1552 }
1553
1554 for (slot = 0; slot < NUM_SLOTS; slot++)
1555 switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) {
1556 case 0:
1557 default:
1558 slot320c[slot] = 0x7f;
1559 break;
1560 case 1:
1561 slot320c[slot] =
1562 ctrl->timings[channel][2 * slot + 0].val_320c +
1563 full_shift;
1564 break;
1565 case 2:
1566 slot320c[slot] =
1567 ctrl->timings[channel][2 * slot + 1].val_320c +
1568 full_shift;
1569 break;
1570 case 3:
1571 slot320c[slot] =
1572 (ctrl->timings[channel][2 * slot].val_320c +
1573 ctrl->timings[channel][2 * slot +
1574 1].val_320c) / 2 +
1575 full_shift;
1576 break;
1577 }
1578
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001579 /* enable CMD XOVER */
1580 reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001581 reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
1582 reg32 |= (slot320c[1] & 0x7f) << 18;
1583 reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
1584
1585 MCHBAR32(0x320c + 0x100 * channel) = reg32;
1586
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001587 /* enable CLK XOVER */
1588 reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001589 reg_c18 = 0;
1590
1591 FOR_ALL_POPULATED_RANKS {
1592 int shift =
1593 ctrl->timings[channel][slotrank].val_320c + full_shift;
1594 int offset_val_c14;
1595 if (shift < 0)
1596 shift = 0;
1597 offset_val_c14 = ctrl->reg_c14_offset + shift;
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001598 /* set CLK phase shift */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001599 reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
1600 reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
1601 }
1602
1603 MCHBAR32(0xc14 + channel * 0x100) = reg_c14;
1604 MCHBAR32(0xc18 + channel * 0x100) = reg_c18;
1605
1606 reg_4028 = MCHBAR32(0x4028 + 0x400 * channel);
1607 reg_4028 &= 0xffff0000;
1608
1609 reg_4024 = 0;
1610
1611 FOR_ALL_POPULATED_RANKS {
1612 int post_timA_min_high = 7, post_timA_max_high = 0;
1613 int pre_timA_min_high = 7, pre_timA_max_high = 0;
1614 int shift_402x = 0;
1615 int shift =
1616 ctrl->timings[channel][slotrank].val_320c + full_shift;
1617
1618 if (shift < 0)
1619 shift = 0;
1620
1621 FOR_ALL_LANES {
1622 if (post_timA_min_high >
1623 ((ctrl->timings[channel][slotrank].lanes[lane].
1624 timA + shift) >> 6))
1625 post_timA_min_high =
1626 ((ctrl->timings[channel][slotrank].
1627 lanes[lane].timA + shift) >> 6);
1628 if (pre_timA_min_high >
1629 (ctrl->timings[channel][slotrank].lanes[lane].
1630 timA >> 6))
1631 pre_timA_min_high =
1632 (ctrl->timings[channel][slotrank].
1633 lanes[lane].timA >> 6);
1634 if (post_timA_max_high <
1635 ((ctrl->timings[channel][slotrank].lanes[lane].
1636 timA + shift) >> 6))
1637 post_timA_max_high =
1638 ((ctrl->timings[channel][slotrank].
1639 lanes[lane].timA + shift) >> 6);
1640 if (pre_timA_max_high <
1641 (ctrl->timings[channel][slotrank].lanes[lane].
1642 timA >> 6))
1643 pre_timA_max_high =
1644 (ctrl->timings[channel][slotrank].
1645 lanes[lane].timA >> 6);
1646 }
1647
1648 if (pre_timA_max_high - pre_timA_min_high <
1649 post_timA_max_high - post_timA_min_high)
1650 shift_402x = +1;
1651 else if (pre_timA_max_high - pre_timA_min_high >
1652 post_timA_max_high - post_timA_min_high)
1653 shift_402x = -1;
1654
1655 reg_4028 |=
1656 (ctrl->timings[channel][slotrank].val_4028 + shift_402x -
1657 post_timA_min_high) << (4 * slotrank);
1658 reg_4024 |=
1659 (ctrl->timings[channel][slotrank].val_4024 +
1660 shift_402x) << (8 * slotrank);
1661
1662 FOR_ALL_LANES {
1663 MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel +
1664 4 * slotrank)
1665 =
1666 (((ctrl->timings[channel][slotrank].lanes[lane].
1667 timA + shift) & 0x3f)
1668 |
1669 ((ctrl->timings[channel][slotrank].lanes[lane].
1670 rising + shift) << 8)
1671 |
1672 (((ctrl->timings[channel][slotrank].lanes[lane].
1673 timA + shift -
1674 (post_timA_min_high << 6)) & 0x1c0) << 10)
Patrick Rudolph0188b132016-02-10 19:16:34 +01001675 | ((ctrl->timings[channel][slotrank].lanes[lane].
1676 falling + shift) << 20));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001677
1678 MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel +
1679 4 * slotrank)
1680 =
1681 (((ctrl->timings[channel][slotrank].lanes[lane].
1682 timC + shift) & 0x3f)
1683 |
1684 (((ctrl->timings[channel][slotrank].lanes[lane].
1685 timB + shift) & 0x3f) << 8)
1686 |
1687 (((ctrl->timings[channel][slotrank].lanes[lane].
1688 timB + shift) & 0x1c0) << 9)
1689 |
1690 (((ctrl->timings[channel][slotrank].lanes[lane].
1691 timC + shift) & 0x40) << 13));
1692 }
1693 }
1694 MCHBAR32(0x4024 + 0x400 * channel) = reg_4024;
1695 MCHBAR32(0x4028 + 0x400 * channel) = reg_4028;
1696}
1697
1698static void test_timA(ramctr_timing * ctrl, int channel, int slotrank)
1699{
1700 wait_428c(channel);
1701
Patrick Rudolph371d2912015-10-09 13:33:25 +02001702 /* DRAM command MRS
1703 * write MR3 MPR enable
1704 * in this mode only RD and RDA are allowed
1705 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001706 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
1707 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1708 (0xc01 | (ctrl->tMOD << 16)));
1709 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1710 (slotrank << 24) | 0x360004);
1711 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1712
Patrick Rudolph371d2912015-10-09 13:33:25 +02001713 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001714 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
1715 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01);
1716 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24));
1717 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1718
Patrick Rudolph371d2912015-10-09 13:33:25 +02001719 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001720 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
1721 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1722 0x100f | ((ctrl->CAS + 36) << 16));
1723 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1724 (slotrank << 24) | 0x60000);
1725 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1726
Patrick Rudolph371d2912015-10-09 13:33:25 +02001727 /* DRAM command MRS
1728 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001729 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
1730 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
1731 (0xc01 | (ctrl->tMOD << 16)));
1732 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
1733 (slotrank << 24) | 0x360000);
1734 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
1735
1736 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
1737
1738 wait_428c(channel);
1739}
1740
1741static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank,
1742 int lane)
1743{
1744 u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA;
1745 return ((read32
1746 (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 +
1747 ((timA / 32) & 1) * 4)
1748 >> (timA % 32)) & 1);
1749}
1750
1751struct run {
1752 int middle;
1753 int end;
1754 int start;
1755 int all;
1756 int length;
1757};
1758
1759static struct run get_longest_zero_run(int *seq, int sz)
1760{
1761 int i, ls;
1762 int bl = 0, bs = 0;
1763 struct run ret;
1764
1765 ls = 0;
1766 for (i = 0; i < 2 * sz; i++)
1767 if (seq[i % sz]) {
1768 if (i - ls > bl) {
1769 bl = i - ls;
1770 bs = ls;
1771 }
1772 ls = i + 1;
1773 }
1774 if (bl == 0) {
1775 ret.middle = sz / 2;
1776 ret.start = 0;
1777 ret.end = sz;
1778 ret.all = 1;
1779 return ret;
1780 }
1781
1782 ret.start = bs % sz;
1783 ret.end = (bs + bl - 1) % sz;
1784 ret.middle = (bs + (bl - 1) / 2) % sz;
1785 ret.length = bl;
1786 ret.all = 0;
1787
1788 return ret;
1789}
1790
1791static void discover_timA_coarse(ramctr_timing * ctrl, int channel,
1792 int slotrank, int *upperA)
1793{
1794 int timA;
1795 int statistics[NUM_LANES][128];
1796 int lane;
1797
1798 for (timA = 0; timA < 128; timA++) {
1799 FOR_ALL_LANES {
1800 ctrl->timings[channel][slotrank].lanes[lane].timA = timA;
1801 }
1802 program_timings(ctrl, channel);
1803
1804 test_timA(ctrl, channel, slotrank);
1805
1806 FOR_ALL_LANES {
1807 statistics[lane][timA] =
1808 !does_lane_work(ctrl, channel, slotrank, lane);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001809 printram("Astat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001810 channel, slotrank, lane, timA,
1811 statistics[lane][timA]);
1812 }
1813 }
1814 FOR_ALL_LANES {
1815 struct run rn = get_longest_zero_run(statistics[lane], 128);
1816 ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle;
1817 upperA[lane] = rn.end;
1818 if (upperA[lane] < rn.middle)
1819 upperA[lane] += 128;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001820 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001821 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001822 printram("Aend: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001823 lane, upperA[lane]);
1824 }
1825}
1826
1827static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
1828 int *upperA)
1829{
1830 int timA_delta;
1831 int statistics[NUM_LANES][51];
1832 int lane, i;
1833
1834 memset(statistics, 0, sizeof(statistics));
1835
1836 for (timA_delta = -25; timA_delta <= 25; timA_delta++) {
1837 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
1838 timA = upperA[lane] + timA_delta + 0x40;
1839 program_timings(ctrl, channel);
1840
1841 for (i = 0; i < 100; i++) {
1842 test_timA(ctrl, channel, slotrank);
1843 FOR_ALL_LANES {
1844 statistics[lane][timA_delta + 25] +=
1845 does_lane_work(ctrl, channel, slotrank,
1846 lane);
1847 }
1848 }
1849 }
1850 FOR_ALL_LANES {
1851 int last_zero, first_all;
1852
1853 for (last_zero = -25; last_zero <= 25; last_zero++)
1854 if (statistics[lane][last_zero + 25])
1855 break;
1856 last_zero--;
1857 for (first_all = -25; first_all <= 25; first_all++)
1858 if (statistics[lane][first_all + 25] == 100)
1859 break;
1860
1861 printram("lane %d: %d, %d\n", lane, last_zero,
1862 first_all);
1863
1864 ctrl->timings[channel][slotrank].lanes[lane].timA =
1865 (last_zero + first_all) / 2 + upperA[lane];
Patrick Rudolpha649a542016-01-17 18:32:06 +01001866 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001867 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
1868 }
1869}
1870
1871static void discover_402x(ramctr_timing * ctrl, int channel, int slotrank,
1872 int *upperA)
1873{
1874 int works[NUM_LANES];
1875 int lane;
1876 while (1) {
1877 int all_works = 1, some_works = 0;
1878 program_timings(ctrl, channel);
1879 test_timA(ctrl, channel, slotrank);
1880 FOR_ALL_LANES {
1881 works[lane] =
1882 !does_lane_work(ctrl, channel, slotrank, lane);
1883 if (works[lane])
1884 some_works = 1;
1885 else
1886 all_works = 0;
1887 }
1888 if (all_works)
1889 return;
1890 if (!some_works) {
1891 if (ctrl->timings[channel][slotrank].val_4024 < 2)
1892 die("402x discovery failed");
1893 ctrl->timings[channel][slotrank].val_4024 -= 2;
1894 printram("4024 -= 2;\n");
1895 continue;
1896 }
1897 ctrl->timings[channel][slotrank].val_4028 += 2;
1898 printram("4028 += 2;\n");
1899 if (ctrl->timings[channel][slotrank].val_4028 >= 0x10)
1900 die("402x discovery failed");
1901 FOR_ALL_LANES if (works[lane]) {
1902 ctrl->timings[channel][slotrank].lanes[lane].timA +=
1903 128;
1904 upperA[lane] += 128;
1905 printram("increment %d, %d, %d\n", channel,
1906 slotrank, lane);
1907 }
1908 }
1909}
1910
1911struct timA_minmax {
1912 int timA_min_high, timA_max_high;
1913};
1914
1915static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1916 struct timA_minmax *mnmx)
1917{
1918 int lane;
1919 mnmx->timA_min_high = 7;
1920 mnmx->timA_max_high = 0;
1921
1922 FOR_ALL_LANES {
1923 if (mnmx->timA_min_high >
1924 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1925 mnmx->timA_min_high =
1926 (ctrl->timings[channel][slotrank].lanes[lane].
1927 timA >> 6);
1928 if (mnmx->timA_max_high <
1929 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1930 mnmx->timA_max_high =
1931 (ctrl->timings[channel][slotrank].lanes[lane].
1932 timA >> 6);
1933 }
1934}
1935
1936static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1937 struct timA_minmax *mnmx)
1938{
1939 struct timA_minmax post;
1940 int shift_402x = 0;
1941
1942 /* Get changed maxima. */
1943 pre_timA_change(ctrl, channel, slotrank, &post);
1944
1945 if (mnmx->timA_max_high - mnmx->timA_min_high <
1946 post.timA_max_high - post.timA_min_high)
1947 shift_402x = +1;
1948 else if (mnmx->timA_max_high - mnmx->timA_min_high >
1949 post.timA_max_high - post.timA_min_high)
1950 shift_402x = -1;
1951 else
1952 shift_402x = 0;
1953
1954 ctrl->timings[channel][slotrank].val_4028 += shift_402x;
1955 ctrl->timings[channel][slotrank].val_4024 += shift_402x;
1956 printram("4024 += %d;\n", shift_402x);
1957 printram("4028 += %d;\n", shift_402x);
1958}
1959
Patrick Rudolph371d2912015-10-09 13:33:25 +02001960/* Compensate the skew between DQS and DQs.
1961 * To ease PCB design a small skew between Data Strobe signals and
1962 * Data Signals is allowed.
1963 * The controller has to measure and compensate this skew for every byte-lane.
1964 * By delaying either all DQs signals or DQS signal, a full phase
1965 * shift can be introduced.
1966 * It is assumed that one byte-lane's DQs signals have the same routing delay.
1967 *
1968 * To measure the actual skew, the DRAM is placed in "read leveling" mode.
1969 * In read leveling mode the DRAM-chip outputs an alternating periodic pattern.
1970 * The memory controller iterates over all possible values to do a full phase shift
1971 * and issues read commands.
1972 * With DQS and DQs in phase the data read is expected to alternate on every byte:
1973 * 0xFF 0x00 0xFF ...
1974 * Once the controller has detected this pattern a bit in the result register is
1975 * set for the current phase shift.
1976 */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001977static void read_training(ramctr_timing * ctrl)
1978{
1979 int channel, slotrank, lane;
1980
1981 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001982 int all_high, some_high;
1983 int upperA[NUM_LANES];
1984 struct timA_minmax mnmx;
1985
1986 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001987
1988 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001989 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
1990 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1991 0xc01 | (ctrl->tRP << 16));
1992 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1993 (slotrank << 24) | 0x60400);
1994 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1995 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
1996
1997 write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001);
1998
1999 ctrl->timings[channel][slotrank].val_4028 = 4;
2000 ctrl->timings[channel][slotrank].val_4024 = 55;
2001 program_timings(ctrl, channel);
2002
2003 discover_timA_coarse(ctrl, channel, slotrank, upperA);
2004
2005 all_high = 1;
2006 some_high = 0;
2007 FOR_ALL_LANES {
2008 if (ctrl->timings[channel][slotrank].lanes[lane].
2009 timA >= 0x40)
2010 some_high = 1;
2011 else
2012 all_high = 0;
2013 }
2014
2015 if (all_high) {
2016 ctrl->timings[channel][slotrank].val_4028--;
2017 printram("4028--;\n");
2018 FOR_ALL_LANES {
2019 ctrl->timings[channel][slotrank].lanes[lane].
2020 timA -= 0x40;
2021 upperA[lane] -= 0x40;
2022
2023 }
2024 } else if (some_high) {
2025 ctrl->timings[channel][slotrank].val_4024++;
2026 ctrl->timings[channel][slotrank].val_4028++;
2027 printram("4024++;\n");
2028 printram("4028++;\n");
2029 }
2030
2031 program_timings(ctrl, channel);
2032
2033 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2034
2035 discover_402x(ctrl, channel, slotrank, upperA);
2036
2037 post_timA_change(ctrl, channel, slotrank, &mnmx);
2038 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2039
2040 discover_timA_fine(ctrl, channel, slotrank, upperA);
2041
2042 post_timA_change(ctrl, channel, slotrank, &mnmx);
2043 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2044
2045 FOR_ALL_LANES {
2046 ctrl->timings[channel][slotrank].lanes[lane].timA -= mnmx.timA_min_high * 0x40;
2047 }
2048 ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high;
2049 printram("4028 -= %d;\n", mnmx.timA_min_high);
2050
2051 post_timA_change(ctrl, channel, slotrank, &mnmx);
2052
2053 printram("4/8: %d, %d, %x, %x\n", channel, slotrank,
2054 ctrl->timings[channel][slotrank].val_4024,
2055 ctrl->timings[channel][slotrank].val_4028);
2056
Patrick Rudolpha649a542016-01-17 18:32:06 +01002057 printram("final results:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002058 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01002059 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002060 lane,
2061 ctrl->timings[channel][slotrank].lanes[lane].timA);
2062
2063 write32(DEFAULT_MCHBAR + 0x3400, 0);
2064
Patrick Rudolph9b515682015-10-09 13:43:51 +02002065 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002066 }
2067
2068 FOR_ALL_POPULATED_CHANNELS {
2069 program_timings(ctrl, channel);
2070 }
2071 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2072 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
2073 + 4 * lane, 0);
2074 }
2075}
2076
2077static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
2078{
2079 int lane;
2080
2081 FOR_ALL_LANES {
2082 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0);
2083 read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane);
2084 }
2085
2086 wait_428c(channel);
2087
Patrick Rudolph371d2912015-10-09 13:33:25 +02002088 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002089 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2090 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2091 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
2092 | 4 | (ctrl->tRCD << 16));
2093
2094 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2095 (slotrank << 24) | (6 << 16));
2096
2097 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
2098
Patrick Rudolph371d2912015-10-09 13:33:25 +02002099 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002100 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2101 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001);
2102 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2103 (slotrank << 24) | 8);
2104 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2105
Patrick Rudolph371d2912015-10-09 13:33:25 +02002106 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002107 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2108 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4);
2109 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2110 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2111
Patrick Rudolph371d2912015-10-09 13:33:25 +02002112 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002113 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2114 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2115 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2116 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2117 (slotrank << 24) | 8);
2118 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2119
2120 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2121
2122 wait_428c(channel);
2123
Patrick Rudolph371d2912015-10-09 13:33:25 +02002124 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002125 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2126 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2127 0xc01 | (ctrl->tRP << 16));
2128 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2129 (slotrank << 24) | 0x60400);
2130 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2131
Patrick Rudolph371d2912015-10-09 13:33:25 +02002132 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002133 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2134 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2135 (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10)
2136 | 8 | (ctrl->CAS << 16));
2137
2138 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2139 (slotrank << 24) | 0x60000);
2140
2141 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244);
2142
Patrick Rudolph371d2912015-10-09 13:33:25 +02002143 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002144 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2145 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2146 0x40011f4 | (max(ctrl->tRTP, 8) << 16));
2147 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2148 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2149
Patrick Rudolph371d2912015-10-09 13:33:25 +02002150 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002151 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2152 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2153 0xc01 | (ctrl->tRP << 16));
2154 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2155 (slotrank << 24) | 0x60400);
2156 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2157 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2158 wait_428c(channel);
2159}
2160
2161static void discover_timC(ramctr_timing * ctrl, int channel, int slotrank)
2162{
2163 int timC;
2164 int statistics[NUM_LANES][MAX_TIMC + 1];
2165 int lane;
2166
2167 wait_428c(channel);
2168
Patrick Rudolph371d2912015-10-09 13:33:25 +02002169 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002170 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2171 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2172 0xc01 | (ctrl->tRP << 16));
2173 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2174 (slotrank << 24) | 0x60400);
2175 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2176 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2177
2178 for (timC = 0; timC <= MAX_TIMC; timC++) {
2179 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
2180 timC = timC;
2181 program_timings(ctrl, channel);
2182
2183 test_timC(ctrl, channel, slotrank);
2184
2185 FOR_ALL_LANES {
2186 statistics[lane][timC] =
2187 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2188 0x400 * channel);
2189 printram("Cstat: %d, %d, %d, %x, %x\n",
2190 channel, slotrank, lane, timC,
2191 statistics[lane][timC]);
2192 }
2193 }
2194 FOR_ALL_LANES {
2195 struct run rn =
2196 get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
2197 ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
2198 if (rn.all)
Patrick Rudolpha649a542016-01-17 18:32:06 +01002199 die("timC discovery failed");
2200 printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002201 lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
2202 }
2203}
2204
2205static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
2206{
2207 int channel, ret = 0;
2208 FOR_ALL_POPULATED_CHANNELS if (channel < target_channel)
2209 ret++;
2210 return ret;
2211}
2212
2213static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b)
2214{
2215 unsigned j;
2216 unsigned channel_offset =
2217 get_precedening_channels(ctrl, channel) * 0x40;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002218 for (j = 0; j < 16; j++)
2219 write32((void *)(0x04000000 + channel_offset + 4 * j), j & 2 ? b : a);
2220 sfence();
2221}
2222
2223static int num_of_channels(const ramctr_timing * ctrl)
2224{
2225 int ret = 0;
2226 int channel;
2227 FOR_ALL_POPULATED_CHANNELS ret++;
2228 return ret;
2229}
2230
2231static void fill_pattern1(ramctr_timing * ctrl, int channel)
2232{
2233 unsigned j;
2234 unsigned channel_offset =
2235 get_precedening_channels(ctrl, channel) * 0x40;
2236 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2237 for (j = 0; j < 16; j++)
2238 write32((void *)(0x04000000 + channel_offset + j * 4), 0xffffffff);
2239 for (j = 0; j < 16; j++)
2240 write32((void *)(0x04000000 + channel_offset + channel_step + j * 4), 0);
2241 sfence();
2242}
2243
2244static void precharge(ramctr_timing * ctrl)
2245{
2246 int channel, slotrank, lane;
2247
2248 FOR_ALL_POPULATED_CHANNELS {
2249 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2250 ctrl->timings[channel][slotrank].lanes[lane].falling =
2251 16;
2252 ctrl->timings[channel][slotrank].lanes[lane].rising =
2253 16;
Patrick Rudolpha649a542016-01-17 18:32:06 +01002254 }
2255
2256 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002257
2258 FOR_ALL_POPULATED_RANKS {
2259 wait_428c(channel);
2260
Patrick Rudolph371d2912015-10-09 13:33:25 +02002261 /* DRAM command MRS
2262 * write MR3 MPR enable
2263 * in this mode only RD and RDA are allowed
2264 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002265 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2266 0x1f000);
2267 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2268 0xc01 | (ctrl->tMOD << 16));
2269 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2270 (slotrank << 24) | 0x360004);
2271 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2272
Patrick Rudolph371d2912015-10-09 13:33:25 +02002273 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002274 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2275 0x1f105);
2276 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2277 0x4041003);
2278 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2279 (slotrank << 24) | 0);
2280 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2281
Patrick Rudolph371d2912015-10-09 13:33:25 +02002282 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002283 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2284 0x1f105);
2285 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2286 0x1001 | ((ctrl->CAS + 8) << 16));
2287 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2288 (slotrank << 24) | 0x60000);
2289 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2290
Patrick Rudolph371d2912015-10-09 13:33:25 +02002291 /* DRAM command MRS
2292 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002293 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2294 0x1f000);
2295 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2296 0xc01 | (ctrl->tMOD << 16));
2297 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2298 (slotrank << 24) | 0x360000);
2299 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2300 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2301 0xc0001);
2302
2303 wait_428c(channel);
2304 }
2305
2306 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2307 ctrl->timings[channel][slotrank].lanes[lane].falling =
2308 48;
2309 ctrl->timings[channel][slotrank].lanes[lane].rising =
2310 48;
2311 }
2312
2313 program_timings(ctrl, channel);
2314
2315 FOR_ALL_POPULATED_RANKS {
2316 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002317 /* DRAM command MRS
2318 * write MR3 MPR enable
2319 * in this mode only RD and RDA are allowed
2320 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002321 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2322 0x1f000);
2323 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2324 0xc01 | (ctrl->tMOD << 16));
2325 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2326 (slotrank << 24) | 0x360004);
2327 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2328
Patrick Rudolph371d2912015-10-09 13:33:25 +02002329 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002330 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2331 0x1f105);
2332 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2333 0x4041003);
2334 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2335 (slotrank << 24) | 0);
2336 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2337
Patrick Rudolph371d2912015-10-09 13:33:25 +02002338 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002339 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2340 0x1f105);
2341 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2342 0x1001 | ((ctrl->CAS + 8) << 16));
2343 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2344 (slotrank << 24) | 0x60000);
2345 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2346
Patrick Rudolph371d2912015-10-09 13:33:25 +02002347 /* DRAM command MRS
2348 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002349 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2350 0x1f000);
2351 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2352 0xc01 | (ctrl->tMOD << 16));
2353
2354 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2355 (slotrank << 24) | 0x360000);
2356 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2357
2358 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2359 0xc0001);
2360 wait_428c(channel);
2361 }
2362 }
2363}
2364
2365static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
2366{
Patrick Rudolph371d2912015-10-09 13:33:25 +02002367 /* enable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002368 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002369 0x80 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002370
2371 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002372 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002373 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207);
2374 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2375 0x8000c01 | ((ctrl->CWL + ctrl->tWLO) << 16));
2376 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2377 8 | (slotrank << 24));
2378 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2379
Patrick Rudolph371d2912015-10-09 13:33:25 +02002380 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002381 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107);
2382 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2383 0x4000c01 | ((ctrl->CAS + 38) << 16));
2384 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2385 (slotrank << 24) | 4);
2386 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2387
2388 write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001);
2389 wait_428c(channel);
2390
Patrick Rudolph371d2912015-10-09 13:33:25 +02002391 /* disable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002392 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002393 0x1080 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002394}
2395
2396static void discover_timB(ramctr_timing * ctrl, int channel, int slotrank)
2397{
2398 int timB;
2399 int statistics[NUM_LANES][128];
2400 int lane;
2401
2402 write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2));
2403
2404 for (timB = 0; timB < 128; timB++) {
2405 FOR_ALL_LANES {
2406 ctrl->timings[channel][slotrank].lanes[lane].timB = timB;
2407 }
2408 program_timings(ctrl, channel);
2409
2410 test_timB(ctrl, channel, slotrank);
2411
2412 FOR_ALL_LANES {
2413 statistics[lane][timB] =
2414 !((read32
2415 (DEFAULT_MCHBAR + lane_registers[lane] +
2416 channel * 0x100 + 4 + ((timB / 32) & 1) * 4)
2417 >> (timB % 32)) & 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002418 printram("Bstat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002419 channel, slotrank, lane, timB,
2420 statistics[lane][timB]);
2421 }
2422 }
2423 FOR_ALL_LANES {
2424 struct run rn = get_longest_zero_run(statistics[lane], 128);
Patrick Rudolphd912f1d2016-02-15 20:07:42 +01002425 /* timC is a direct function of timB's 6 LSBs.
2426 * Some tests increments the value of timB by a small value,
2427 * which might cause the 6bit value to overflow, if it's close
2428 * to 0x3F. Increment the value by a small offset if it's likely
2429 * to overflow, to make sure it won't overflow while running
2430 * tests and bricks the system due to a non matching timC.
2431 *
2432 * TODO: find out why some tests (edge write discovery)
2433 * increment timB. */
2434 if ((rn.start & 0x3F) == 0x3E)
2435 rn.start += 2;
2436 else if ((rn.start & 0x3F) == 0x3F)
2437 rn.start += 1;
Vladimir Serbinenko3141eac2016-01-29 19:42:02 +01002438 ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002439 if (rn.all)
2440 die("timB discovery failed");
Patrick Rudolpha649a542016-01-17 18:32:06 +01002441 printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002442 lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
2443 }
2444}
2445
2446static int get_timB_high_adjust(u64 val)
2447{
2448 int i;
2449
2450 /* good */
2451 if (val == 0xffffffffffffffffLL)
2452 return 0;
2453
2454 if (val >= 0xf000000000000000LL) {
2455 /* needs negative adjustment */
2456 for (i = 0; i < 8; i++)
2457 if (val << (8 * (7 - i) + 4))
2458 return -i;
2459 } else {
2460 /* needs positive adjustment */
2461 for (i = 0; i < 8; i++)
2462 if (val >> (8 * (7 - i) + 4))
2463 return i;
2464 }
2465 return 8;
2466}
2467
2468static void adjust_high_timB(ramctr_timing * ctrl)
2469{
2470 int channel, slotrank, lane, old;
2471 write32(DEFAULT_MCHBAR + 0x3400, 0x200);
2472 FOR_ALL_POPULATED_CHANNELS {
2473 fill_pattern1(ctrl, channel);
2474 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 1);
2475 }
2476 FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
2477
2478 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001);
2479
2480 wait_428c(channel);
2481
Patrick Rudolph371d2912015-10-09 13:33:25 +02002482 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002483 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2484 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2485 0xc01 | (ctrl->tRCD << 16));
2486 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2487 (slotrank << 24) | 0x60000);
2488 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2489
Patrick Rudolph371d2912015-10-09 13:33:25 +02002490 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002491 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2492 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01);
2493 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2494 (slotrank << 24) | 0x8);
2495 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2496
Patrick Rudolph371d2912015-10-09 13:33:25 +02002497 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002498 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2499 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003);
2500 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2501 (slotrank << 24));
2502 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2);
2503
Patrick Rudolph371d2912015-10-09 13:33:25 +02002504 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002505 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2506 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2507 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2508 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2509 (slotrank << 24) | 0x8);
2510 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2511
2512 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2513
2514 wait_428c(channel);
2515
Patrick Rudolph371d2912015-10-09 13:33:25 +02002516 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002517 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2518 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2519 0xc01 | ((ctrl->tRP) << 16));
2520 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2521 (slotrank << 24) | 0x60400);
2522 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2523
Patrick Rudolph371d2912015-10-09 13:33:25 +02002524 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002525 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2526 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2527 0xc01 | ((ctrl->tRCD) << 16));
2528 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2529 (slotrank << 24) | 0x60000);
2530 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2531
Patrick Rudolph371d2912015-10-09 13:33:25 +02002532 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002533 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105);
2534 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2535 0x4000c01 |
2536 ((ctrl->tRP +
2537 ctrl->timings[channel][slotrank].val_4024 +
2538 ctrl->timings[channel][slotrank].val_4028) << 16));
2539 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2540 (slotrank << 24) | 0x60008);
2541 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2542
2543 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
2544 wait_428c(channel);
2545 FOR_ALL_LANES {
2546 u64 res =
2547 read32(DEFAULT_MCHBAR + lane_registers[lane] +
2548 0x100 * channel + 4);
2549 res |=
2550 ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] +
2551 0x100 * channel + 8)) << 32;
2552 old = ctrl->timings[channel][slotrank].lanes[lane].timB;
2553 ctrl->timings[channel][slotrank].lanes[lane].timB +=
2554 get_timB_high_adjust(res) * 64;
2555
Patrick Rudolpha649a542016-01-17 18:32:06 +01002556 printram("High adjust %d:%016llx\n", lane, res);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002557 printram("Bval+: %d, %d, %d, %x -> %x\n", channel,
2558 slotrank, lane, old,
2559 ctrl->timings[channel][slotrank].lanes[lane].
2560 timB);
2561 }
2562 }
2563 write32(DEFAULT_MCHBAR + 0x3400, 0);
2564}
2565
2566static void write_op(ramctr_timing * ctrl, int channel)
2567{
2568 int slotrank;
2569
2570 wait_428c(channel);
2571
2572 /* choose an existing rank. */
2573 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2574
Patrick Rudolph371d2912015-10-09 13:33:25 +02002575 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002576 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2577 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2578
2579 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2580 (slotrank << 24) | 0x60000);
2581
2582 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2583
2584 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2585 wait_428c(channel);
2586}
2587
Patrick Rudolph371d2912015-10-09 13:33:25 +02002588/* Compensate the skew between CMD/ADDR/CLK and DQ/DQS lanes.
2589 * DDR3 adopted the fly-by topology. The data and strobes signals reach
2590 * the chips at different times with respect to command, address and
2591 * clock signals.
2592 * By delaying either all DQ/DQs or all CMD/ADDR/CLK signals, a full phase
2593 * shift can be introduced.
2594 * It is assumed that the CLK/ADDR/CMD signals have the same routing delay.
2595 *
2596 * To find the required phase shift the DRAM is placed in "write leveling" mode.
2597 * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
2598 * sampled value on the data lanes (DQs).
2599 */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002600static void write_training(ramctr_timing * ctrl)
2601{
2602 int channel, slotrank, lane;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002603
2604 FOR_ALL_POPULATED_CHANNELS
2605 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
2606 read32(DEFAULT_MCHBAR + 0x4008 +
2607 0x400 * channel) | 0x8000000);
2608
2609 FOR_ALL_POPULATED_CHANNELS {
2610 write_op(ctrl, channel);
2611 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2612 read32(DEFAULT_MCHBAR + 0x4020 +
2613 0x400 * channel) | 0x200000);
2614 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002615
2616 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002617 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2618 FOR_ALL_POPULATED_CHANNELS {
2619 write_op(ctrl, channel);
2620 }
2621
Patrick Rudolph371d2912015-10-09 13:33:25 +02002622 /* enable write leveling on all ranks
2623 * disable all DQ outputs
2624 * only NOP is allowed in this mode */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002625 FOR_ALL_CHANNELS
2626 FOR_ALL_POPULATED_RANKS
2627 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002628 make_mr1(ctrl, slotrank, channel) | 0x1080);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002629
2630 write32(DEFAULT_MCHBAR + 0x3400, 0x108052);
2631
Patrick Rudolph9b515682015-10-09 13:43:51 +02002632 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002633
Patrick Rudolph371d2912015-10-09 13:33:25 +02002634 /* set any valid value for timB, it gets corrected later */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002635 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2636 discover_timB(ctrl, channel, slotrank);
2637
Patrick Rudolph371d2912015-10-09 13:33:25 +02002638 /* disable write leveling on all ranks */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002639 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2640 write_mrreg(ctrl, channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002641 slotrank, 1, make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002642
2643 write32(DEFAULT_MCHBAR + 0x3400, 0);
2644
2645 FOR_ALL_POPULATED_CHANNELS
2646 wait_428c(channel);
2647
Patrick Rudolph371d2912015-10-09 13:33:25 +02002648 /* refresh enable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002649 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8);
2650
2651 FOR_ALL_POPULATED_CHANNELS {
2652 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2653 ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 +
2654 0x400 * channel));
2655 read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel);
2656 wait_428c(channel);
2657
Patrick Rudolph371d2912015-10-09 13:33:25 +02002658 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002659 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2660 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
2661 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000);
2662 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2663
2664 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2665 wait_428c(channel);
2666 }
2667
Patrick Rudolph9b515682015-10-09 13:43:51 +02002668 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002669
2670 printram("CPE\n");
2671 precharge(ctrl);
2672 printram("CPF\n");
2673
2674 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2675 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2676 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2677 0);
2678 }
2679
2680 FOR_ALL_POPULATED_CHANNELS {
2681 fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555);
2682 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
2683 }
2684
2685 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2686 discover_timC(ctrl, channel, slotrank);
2687
2688 FOR_ALL_POPULATED_CHANNELS
2689 program_timings(ctrl, channel);
2690
Patrick Rudolph371d2912015-10-09 13:33:25 +02002691 /* measure and adjust timB timings */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002692 adjust_high_timB(ctrl);
2693
2694 FOR_ALL_POPULATED_CHANNELS
2695 program_timings(ctrl, channel);
2696
2697 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2698 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2699 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2700 0);
2701 }
2702}
2703
2704static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
2705{
2706 struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank];
2707 int timC_delta;
2708 int lanes_ok = 0;
2709 int ctr = 0;
2710 int lane;
2711
2712 for (timC_delta = -5; timC_delta <= 5; timC_delta++) {
2713 FOR_ALL_LANES {
2714 ctrl->timings[channel][slotrank].lanes[lane].timC =
2715 saved_rt.lanes[lane].timC + timC_delta;
2716 }
2717 program_timings(ctrl, channel);
2718 FOR_ALL_LANES {
2719 write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0);
2720 }
2721
2722 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2723
2724 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002725 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002726 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2727 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2728 ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10)
2729 | 8 | (ctrl->tRCD << 16));
2730
2731 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2732 (slotrank << 24) | ctr | 0x60000);
2733
2734 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002735 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002736 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
2737 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2738 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16));
2739 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2740 (slotrank << 24));
2741 write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd);
2742 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42);
2743
Patrick Rudolph371d2912015-10-09 13:33:25 +02002744 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002745 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2746 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2747 0x4001020 | (max(ctrl->tRTP, 8) << 16));
2748 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2749 (slotrank << 24));
2750 write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd);
2751 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42);
2752
Patrick Rudolph371d2912015-10-09 13:33:25 +02002753 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002754 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2755 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001);
2756 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2757 (slotrank << 24) | 0x60400);
2758 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2759
2760 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2761 wait_428c(channel);
2762 FOR_ALL_LANES {
2763 u32 r32 =
2764 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2765 0x400 * channel);
2766
2767 if (r32 == 0)
2768 lanes_ok |= 1 << lane;
2769 }
2770 ctr++;
2771 if (lanes_ok == ((1 << NUM_LANES) - 1))
2772 break;
2773 }
2774
2775 ctrl->timings[channel][slotrank] = saved_rt;
2776
2777 printram("3lanes: %x\n", lanes_ok);
2778 return lanes_ok != ((1 << NUM_LANES) - 1);
2779}
2780
2781#include "raminit_patterns.h"
2782
2783static void fill_pattern5(ramctr_timing * ctrl, int channel, int patno)
2784{
2785 unsigned i, j;
2786 unsigned channel_offset =
2787 get_precedening_channels(ctrl, channel) * 0x40;
2788 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2789
2790 if (patno) {
2791 u8 base8 = 0x80 >> ((patno - 1) % 8);
2792 u32 base = base8 | (base8 << 8) | (base8 << 16) | (base8 << 24);
2793 for (i = 0; i < 32; i++) {
2794 for (j = 0; j < 16; j++) {
2795 u32 val = use_base[patno - 1][i] & (1 << (j / 2)) ? base : 0;
2796 if (invert[patno - 1][i] & (1 << (j / 2)))
2797 val = ~val;
2798 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2799 j * 4), val);
2800 }
2801 }
2802
2803 } else {
2804 for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) {
2805 for (j = 0; j < 16; j++)
2806 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2807 j * 4), pattern[i][j]);
2808 }
2809 sfence();
2810 }
2811}
2812
2813static void reprogram_320c(ramctr_timing * ctrl)
2814{
2815 int channel, slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002816
2817 FOR_ALL_POPULATED_CHANNELS {
2818 wait_428c(channel);
2819
2820 /* choose an existing rank. */
2821 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2822
Patrick Rudolph371d2912015-10-09 13:33:25 +02002823 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002824 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2825 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2826
2827 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2828 (slotrank << 24) | 0x60000);
2829
2830 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2831
2832 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2833 wait_428c(channel);
2834 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2835 read32(DEFAULT_MCHBAR + 0x4020 +
2836 0x400 * channel) | 0x200000);
2837 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002838
2839 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002840 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2841 FOR_ALL_POPULATED_CHANNELS {
2842 wait_428c(channel);
2843
2844 /* choose an existing rank. */
2845 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2846
Patrick Rudolph371d2912015-10-09 13:33:25 +02002847 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002848 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2849 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2850
2851 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2852 (slotrank << 24) | 0x60000);
2853
2854 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2855
2856 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2857 wait_428c(channel);
2858 }
2859
2860 /* jedec reset */
2861 dram_jedecreset(ctrl);
2862 /* mrs commands. */
2863 dram_mrscommands(ctrl);
2864
Patrick Rudolph9b515682015-10-09 13:43:51 +02002865 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002866}
2867
2868#define MIN_C320C_LEN 13
2869
2870static int try_cmd_stretch(ramctr_timing * ctrl, int cmd_stretch)
2871{
2872 struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
2873 int channel, slotrank;
2874 int c320c;
2875 int stat[NUM_SLOTRANKS][256];
2876
2877 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2878 saved_timings[channel][slotrank] = ctrl->timings[channel][slotrank];
2879 }
2880
2881 FOR_ALL_POPULATED_CHANNELS {
2882 ctrl->cmd_stretch[channel] = cmd_stretch;
2883 }
2884
2885 FOR_ALL_POPULATED_CHANNELS
2886 MCHBAR32(0x4004 + 0x400 * channel) =
2887 ctrl->tRRD
2888 | (ctrl->tRTP << 4)
2889 | (ctrl->tCKE << 8)
2890 | (ctrl->tWTR << 12)
2891 | (ctrl->tFAW << 16)
2892 | (ctrl->tWR << 24)
2893 | (ctrl->cmd_stretch[channel] << 30);
2894
2895
2896 FOR_ALL_CHANNELS {
2897 int delta = 0;
2898 if (ctrl->cmd_stretch[channel] == 2)
2899 delta = 2;
2900 else if (ctrl->cmd_stretch[channel] == 0)
2901 delta = 4;
2902
2903 FOR_ALL_POPULATED_RANKS {
2904 ctrl->timings[channel][slotrank].val_4024 -= delta;
2905 }
2906 }
2907
2908 FOR_ALL_POPULATED_CHANNELS {
2909 for (c320c = -127; c320c <= 127; c320c++) {
2910 FOR_ALL_POPULATED_RANKS {
2911 ctrl->timings[channel][slotrank].val_320c = c320c;
2912 }
2913 program_timings(ctrl, channel);
2914 reprogram_320c(ctrl);
2915 FOR_ALL_POPULATED_RANKS {
2916 stat[slotrank][c320c + 127] =
2917 test_320c(ctrl, channel, slotrank);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002918 printram("3stat: %d, %d, %d: %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002919 channel, slotrank, c320c,
2920 stat[slotrank][c320c + 127]);
2921 }
2922 }
2923 FOR_ALL_POPULATED_RANKS {
2924 struct run rn =
2925 get_longest_zero_run(stat[slotrank], 255);
2926 ctrl->timings[channel][slotrank].val_320c =
2927 rn.middle - 127;
2928 printram("3val: %d, %d: %d\n", channel,
2929 slotrank,
2930 ctrl->timings[channel][slotrank].val_320c);
2931 if (rn.all || rn.length < MIN_C320C_LEN) {
2932 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2933 ctrl->timings[channel][slotrank] = saved_timings[channel][slotrank];
2934 }
2935 return 0;
2936 }
2937 }
2938 }
2939 return 1;
2940}
2941
Patrick Rudolph371d2912015-10-09 13:33:25 +02002942/* Adjust CMD phase shift and try multiple command rates.
2943 * A command rate of 2T doubles the time needed for address and
2944 * command decode. */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002945static void command_training(ramctr_timing * ctrl)
2946{
2947 int channel;
2948
2949 FOR_ALL_POPULATED_CHANNELS {
2950 fill_pattern5(ctrl, channel, 0);
2951 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2952 }
2953
2954 /* try command rate 1T and 2T */
2955 if (!try_cmd_stretch(ctrl, 0) && !try_cmd_stretch(ctrl, 2))
2956 die("c320c discovery failed");
2957
2958 FOR_ALL_POPULATED_CHANNELS {
2959 program_timings(ctrl, channel);
2960 }
2961
2962 reprogram_320c(ctrl);
2963}
2964
2965static void discover_edges_real(ramctr_timing * ctrl, int channel, int slotrank,
2966 int *edges)
2967{
2968 int edge;
2969 int statistics[NUM_LANES][MAX_EDGE_TIMING + 1];
2970 int lane;
2971
2972 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
2973 FOR_ALL_LANES {
2974 ctrl->timings[channel][slotrank].lanes[lane].rising =
2975 edge;
2976 ctrl->timings[channel][slotrank].lanes[lane].falling =
2977 edge;
2978 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002979 program_timings(ctrl, channel);
2980
2981 FOR_ALL_LANES {
2982 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
2983 4 * lane, 0);
2984 read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane +
2985 0x4140);
2986 }
2987
2988 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002989 /* DRAM command MRS
2990 * write MR3 MPR enable
2991 * in this mode only RD and RDA are allowed
2992 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002993 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
2994 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2995 (0xc01 | (ctrl->tMOD << 16)));
2996 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2997 (slotrank << 24) | 0x360004);
2998 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2999
Patrick Rudolph371d2912015-10-09 13:33:25 +02003000 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003001 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
3002 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4);
3003 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3004 (slotrank << 24));
3005 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3006
Patrick Rudolph371d2912015-10-09 13:33:25 +02003007 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003008 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
3009 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3010 0x1001 | ((ctrl->CAS + 8) << 16));
3011 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3012 (slotrank << 24) | 0x60000);
3013 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3014
Patrick Rudolph371d2912015-10-09 13:33:25 +02003015 /* DRAM command MRS
3016 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003017 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
3018 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3019 (0xc01 | (ctrl->tMOD << 16)));
3020 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3021 (slotrank << 24) | 0x360000);
3022 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3023
3024 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
3025
3026 wait_428c(channel);
3027
3028 FOR_ALL_LANES {
3029 statistics[lane][edge] =
3030 read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3031 lane * 4);
3032 }
3033 }
3034 FOR_ALL_LANES {
3035 struct run rn =
3036 get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
3037 edges[lane] = rn.middle;
3038 if (rn.all)
3039 die("edge discovery failed");
Patrick Rudolpha649a542016-01-17 18:32:06 +01003040 printram("eval %d, %d, %d: %02x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003041 lane, edges[lane]);
3042 }
3043}
3044
3045static void discover_edges(ramctr_timing * ctrl)
3046{
3047 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3048 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3049 int channel, slotrank, lane;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003050
3051 write32(DEFAULT_MCHBAR + 0x3400, 0);
3052
Patrick Rudolph9b515682015-10-09 13:43:51 +02003053 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003054
3055 FOR_ALL_POPULATED_CHANNELS FOR_ALL_LANES {
3056 write32(DEFAULT_MCHBAR + 4 * lane +
3057 0x400 * channel + 0x4080, 0);
3058 }
3059
3060 FOR_ALL_POPULATED_CHANNELS {
3061 fill_pattern0(ctrl, channel, 0, 0);
3062 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3063 FOR_ALL_LANES {
3064 read32(DEFAULT_MCHBAR + 0x400 * channel +
3065 lane * 4 + 0x4140);
3066 }
3067
3068 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3069 ctrl->timings[channel][slotrank].lanes[lane].falling =
3070 16;
3071 ctrl->timings[channel][slotrank].lanes[lane].rising =
3072 16;
3073 }
3074
3075 program_timings(ctrl, channel);
3076
3077 FOR_ALL_POPULATED_RANKS {
3078 wait_428c(channel);
3079
Patrick Rudolph371d2912015-10-09 13:33:25 +02003080 /* DRAM command MRS
3081 * MR3 enable MPR
3082 * write MR3 MPR enable
3083 * in this mode only RD and RDA are allowed
3084 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003085 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3086 0x1f000);
3087 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3088 0xc01 | (ctrl->tMOD << 16));
3089 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3090 (slotrank << 24) | 0x360004);
3091 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3092
Patrick Rudolph371d2912015-10-09 13:33:25 +02003093 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003094 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3095 0x1f105);
3096 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3097 0x4041003);
3098 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3099 (slotrank << 24) | 0);
3100 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3101
Patrick Rudolph371d2912015-10-09 13:33:25 +02003102 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003103 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3104 0x1f105);
3105 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3106 0x1001 | ((ctrl->CAS + 8) << 16));
3107 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3108 (slotrank << 24) | 0x60000);
3109 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3110
Patrick Rudolph371d2912015-10-09 13:33:25 +02003111 /* DRAM command MRS
3112 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003113 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3114 0x1f000);
3115 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3116 0xc01 | (ctrl->tMOD << 16));
3117 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3118 (slotrank << 24) | 0x360000);
3119 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3120 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3121 0xc0001);
3122
3123 wait_428c(channel);
3124 }
3125
Patrick Rudolph371d2912015-10-09 13:33:25 +02003126 /* XXX: check any measured value ? */
3127
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003128 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3129 ctrl->timings[channel][slotrank].lanes[lane].falling =
3130 48;
3131 ctrl->timings[channel][slotrank].lanes[lane].rising =
3132 48;
3133 }
3134
3135 program_timings(ctrl, channel);
3136
3137 FOR_ALL_POPULATED_RANKS {
3138 wait_428c(channel);
3139
Patrick Rudolph371d2912015-10-09 13:33:25 +02003140 /* DRAM command MRS
3141 * MR3 enable MPR
3142 * write MR3 MPR enable
3143 * in this mode only RD and RDA are allowed
3144 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003145 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3146 0x1f000);
3147 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3148 0xc01 | (ctrl->tMOD << 16));
3149 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3150 (slotrank << 24) | 0x360004);
3151 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3152
Patrick Rudolph371d2912015-10-09 13:33:25 +02003153 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003154 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3155 0x1f105);
3156 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3157 0x4041003);
3158 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3159 (slotrank << 24) | 0);
3160 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3161
Patrick Rudolph371d2912015-10-09 13:33:25 +02003162 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003163 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3164 0x1f105);
3165 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3166 0x1001 | ((ctrl->CAS + 8) << 16));
3167 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3168 (slotrank << 24) | 0x60000);
3169 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3170
Patrick Rudolph371d2912015-10-09 13:33:25 +02003171 /* DRAM command MRS
3172 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003173 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3174 0x1f000);
3175 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3176 0xc01 | (ctrl->tMOD << 16));
3177 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3178 (slotrank << 24) | 0x360000);
3179 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3180
3181 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3182 0xc0001);
3183 wait_428c(channel);
3184 }
3185
Patrick Rudolph371d2912015-10-09 13:33:25 +02003186 /* XXX: check any measured value ? */
3187
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003188 FOR_ALL_LANES {
3189 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel +
3190 lane * 4,
3191 ~read32(DEFAULT_MCHBAR + 0x4040 +
3192 0x400 * channel + lane * 4) & 0xff);
3193 }
3194
3195 fill_pattern0(ctrl, channel, 0, 0xffffffff);
3196 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3197 }
3198
3199 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3200 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003201 printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003202
3203 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3204 discover_edges_real(ctrl, channel, slotrank,
3205 falling_edges[channel][slotrank]);
3206 }
3207
3208 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003209 printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003210
3211 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3212 discover_edges_real(ctrl, channel, slotrank,
3213 rising_edges[channel][slotrank]);
3214 }
3215
3216 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3217
3218 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3219 ctrl->timings[channel][slotrank].lanes[lane].falling =
3220 falling_edges[channel][slotrank][lane];
3221 ctrl->timings[channel][slotrank].lanes[lane].rising =
3222 rising_edges[channel][slotrank][lane];
3223 }
3224
3225 FOR_ALL_POPULATED_CHANNELS {
3226 program_timings(ctrl, channel);
3227 }
3228
3229 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3230 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3231 0);
3232 }
3233}
3234
3235static void discover_edges_write_real(ramctr_timing * ctrl, int channel,
3236 int slotrank, int *edges)
3237{
3238 int edge;
3239 u32 raw_statistics[MAX_EDGE_TIMING + 1];
3240 int statistics[MAX_EDGE_TIMING + 1];
3241 const int reg3000b24[] = { 0, 0xc, 0x2c };
3242 int lane, i;
3243 int lower[NUM_LANES];
3244 int upper[NUM_LANES];
3245 int pat;
3246
3247 FOR_ALL_LANES {
3248 lower[lane] = 0;
3249 upper[lane] = MAX_EDGE_TIMING;
3250 }
3251
3252 for (i = 0; i < 3; i++) {
3253 write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel,
3254 reg3000b24[i] << 24);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003255 printram("[%x] = 0x%08x\n",
3256 0x3000 + 0x100 * channel, reg3000b24[i] << 24);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003257 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3258 fill_pattern5(ctrl, channel, pat);
3259 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003260 printram("using pattern %d\n", pat);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003261 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3262 FOR_ALL_LANES {
3263 ctrl->timings[channel][slotrank].lanes[lane].
3264 rising = edge;
3265 ctrl->timings[channel][slotrank].lanes[lane].
3266 falling = edge;
3267 }
3268 program_timings(ctrl, channel);
3269
3270 FOR_ALL_LANES {
3271 write32(DEFAULT_MCHBAR + 0x4340 +
3272 0x400 * channel + 4 * lane, 0);
3273 read32(DEFAULT_MCHBAR + 0x400 * channel +
3274 4 * lane + 0x4140);
3275 }
3276 wait_428c(channel);
3277
Patrick Rudolph371d2912015-10-09 13:33:25 +02003278 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003279 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3280 0x1f006);
3281 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3282 0x4 | (ctrl->tRCD << 16)
3283 | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) <<
3284 10));
3285 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3286 (slotrank << 24) | 0x60000);
3287 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel,
3288 0x240);
3289
Patrick Rudolph371d2912015-10-09 13:33:25 +02003290 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003291 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3292 0x1f201);
3293 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3294 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) <<
3295 16));
3296 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3297 (slotrank << 24));
3298 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel,
3299 0x242);
3300
Patrick Rudolph371d2912015-10-09 13:33:25 +02003301 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003302 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3303 0x1f105);
3304 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3305 0x4005020 | (max(ctrl->tRTP, 8) << 16));
3306 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3307 (slotrank << 24));
3308 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel,
3309 0x242);
3310
Patrick Rudolph371d2912015-10-09 13:33:25 +02003311 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003312 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3313 0x1f002);
3314 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3315 0xc01 | (ctrl->tRP << 16));
3316 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3317 (slotrank << 24) | 0x60400);
3318 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3319
3320 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3321 0xc0001);
3322 wait_428c(channel);
3323 FOR_ALL_LANES {
3324 read32(DEFAULT_MCHBAR + 0x4340 +
3325 0x400 * channel + lane * 4);
3326 }
3327
3328 raw_statistics[edge] =
3329 MCHBAR32(0x436c + 0x400 * channel);
3330 }
3331 FOR_ALL_LANES {
3332 struct run rn;
3333 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++)
3334 statistics[edge] =
3335 ! !(raw_statistics[edge] & (1 << lane));
3336 rn = get_longest_zero_run(statistics,
3337 MAX_EDGE_TIMING + 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003338 printram("edges: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003339 channel, slotrank, i, rn.start, rn.middle,
3340 rn.end, rn.start + ctrl->edge_offset[i],
3341 rn.end - ctrl->edge_offset[i]);
3342 lower[lane] =
3343 max(rn.start + ctrl->edge_offset[i], lower[lane]);
3344 upper[lane] =
3345 min(rn.end - ctrl->edge_offset[i], upper[lane]);
3346 edges[lane] = (lower[lane] + upper[lane]) / 2;
Patrick Rudolph9733e282015-08-16 17:06:30 +02003347 if (rn.all || (lower[lane] > upper[lane]))
3348 die("edge write discovery failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003349
3350 }
3351 }
3352 }
3353
3354 write32(DEFAULT_MCHBAR + 0x3000, 0);
3355 printram("CPA\n");
3356}
3357
3358static void discover_edges_write(ramctr_timing * ctrl)
3359{
3360 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3361 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3362 int channel, slotrank, lane;
3363
3364 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3365 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003366 printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003367
3368 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3369 discover_edges_write_real(ctrl, channel, slotrank,
3370 falling_edges[channel][slotrank]);
3371 }
3372
3373 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003374 printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003375
3376 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3377 discover_edges_write_real(ctrl, channel, slotrank,
3378 rising_edges[channel][slotrank]);
3379 }
3380
3381 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3382
3383 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3384 ctrl->timings[channel][slotrank].lanes[lane].falling =
3385 falling_edges[channel][slotrank][lane];
3386 ctrl->timings[channel][slotrank].lanes[lane].rising =
3387 rising_edges[channel][slotrank][lane];
3388 }
3389
3390 FOR_ALL_POPULATED_CHANNELS
3391 program_timings(ctrl, channel);
3392
3393 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3394 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3395 0);
3396 }
3397}
3398
3399static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
3400{
3401 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003402 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003403 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
3404 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3405 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD)
3406 << 10) | (ctrl->tRCD << 16) | 4);
3407 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3408 (slotrank << 24) | 0x60000);
3409 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
3410
Patrick Rudolph371d2912015-10-09 13:33:25 +02003411 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003412 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
3413 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3414 0x80011e0 |
3415 ((ctrl->tWTR + ctrl->CWL + 8) << 16));
3416 write32(DEFAULT_MCHBAR + 0x4204 +
3417 0x400 * channel, (slotrank << 24));
3418 write32(DEFAULT_MCHBAR + 0x4214 +
3419 0x400 * channel, 0x242);
3420
Patrick Rudolph371d2912015-10-09 13:33:25 +02003421 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003422 write32(DEFAULT_MCHBAR + 0x4228 +
3423 0x400 * channel, 0x1f105);
3424 write32(DEFAULT_MCHBAR + 0x4238 +
3425 0x400 * channel,
3426 0x40011e0 | (max(ctrl->tRTP, 8) << 16));
3427 write32(DEFAULT_MCHBAR + 0x4208 +
3428 0x400 * channel, (slotrank << 24));
3429 write32(DEFAULT_MCHBAR + 0x4218 +
3430 0x400 * channel, 0x242);
3431
Patrick Rudolph371d2912015-10-09 13:33:25 +02003432 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003433 write32(DEFAULT_MCHBAR + 0x422c +
3434 0x400 * channel, 0x1f002);
3435 write32(DEFAULT_MCHBAR + 0x423c +
3436 0x400 * channel,
3437 0x1001 | (ctrl->tRP << 16));
3438 write32(DEFAULT_MCHBAR + 0x420c +
3439 0x400 * channel,
3440 (slotrank << 24) | 0x60400);
3441 write32(DEFAULT_MCHBAR + 0x421c +
3442 0x400 * channel, 0);
3443
3444 write32(DEFAULT_MCHBAR + 0x4284 +
3445 0x400 * channel, 0xc0001);
3446 wait_428c(channel);
3447}
3448
3449static void discover_timC_write(ramctr_timing * ctrl)
3450{
3451 const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
3452 int i, pat;
3453
3454 int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3455 int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3456 int channel, slotrank, lane;
3457
3458 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3459 lower[channel][slotrank][lane] = 0;
3460 upper[channel][slotrank][lane] = MAX_TIMC;
3461 }
3462
3463 write32(DEFAULT_MCHBAR + 0x4ea8, 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003464 printram("discover timC write:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003465
3466 for (i = 0; i < 3; i++)
3467 FOR_ALL_POPULATED_CHANNELS {
3468 write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100),
3469 (rege3c_b24[i] << 24)
3470 | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100))
3471 & ~0x3f000000));
3472 udelay(2);
3473 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3474 FOR_ALL_POPULATED_RANKS {
3475 int timC;
3476 u32 raw_statistics[MAX_TIMC + 1];
3477 int statistics[MAX_TIMC + 1];
3478
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003479 /* Make sure rn.start < rn.end */
3480 statistics[MAX_TIMC] = 1;
3481
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003482 fill_pattern5(ctrl, channel, pat);
3483 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003484 for (timC = 0; timC < MAX_TIMC; timC++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003485 FOR_ALL_LANES
3486 ctrl->timings[channel][slotrank].lanes[lane].timC = timC;
3487 program_timings(ctrl, channel);
3488
3489 test_timC_write (ctrl, channel, slotrank);
3490
3491 raw_statistics[timC] =
3492 MCHBAR32(0x436c + 0x400 * channel);
3493 }
3494 FOR_ALL_LANES {
3495 struct run rn;
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003496 for (timC = 0; timC < MAX_TIMC; timC++)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003497 statistics[timC] =
3498 !!(raw_statistics[timC] &
3499 (1 << lane));
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003500
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003501 rn = get_longest_zero_run(statistics,
3502 MAX_TIMC + 1);
3503 if (rn.all)
3504 die("timC write discovery failed");
Patrick Rudolpha649a542016-01-17 18:32:06 +01003505 printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003506 channel, slotrank, i, rn.start,
3507 rn.middle, rn.end,
3508 rn.start + ctrl->timC_offset[i],
3509 rn.end - ctrl->timC_offset[i]);
3510 lower[channel][slotrank][lane] =
3511 max(rn.start + ctrl->timC_offset[i],
3512 lower[channel][slotrank][lane]);
3513 upper[channel][slotrank][lane] =
3514 min(rn.end - ctrl->timC_offset[i],
3515 upper[channel][slotrank][lane]);
3516
3517 }
3518 }
3519 }
3520 }
3521
3522 FOR_ALL_CHANNELS {
3523 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3524 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3525 ~0x3f000000));
3526 udelay(2);
3527 }
3528
3529 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3530
3531 printram("CPB\n");
3532
3533 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
Patrick Rudolpha649a542016-01-17 18:32:06 +01003534 printram("timC %d, %d, %d: %x\n", channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003535 slotrank, lane,
3536 (lower[channel][slotrank][lane] +
3537 upper[channel][slotrank][lane]) / 2);
3538 ctrl->timings[channel][slotrank].lanes[lane].timC =
3539 (lower[channel][slotrank][lane] +
3540 upper[channel][slotrank][lane]) / 2;
3541 }
3542 FOR_ALL_POPULATED_CHANNELS {
3543 program_timings(ctrl, channel);
3544 }
3545}
3546
3547static void normalize_training(ramctr_timing * ctrl)
3548{
3549 int channel, slotrank, lane;
3550 int mat = 0;
3551
3552 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3553 int delta;
3554 FOR_ALL_LANES mat =
3555 max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat);
3556 delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028;
3557 ctrl->timings[channel][slotrank].val_4024 += delta;
3558 ctrl->timings[channel][slotrank].val_4028 += delta;
3559 }
3560
3561 FOR_ALL_POPULATED_CHANNELS {
3562 program_timings(ctrl, channel);
3563 }
3564}
3565
3566static void write_controller_mr(ramctr_timing * ctrl)
3567{
3568 int channel, slotrank;
3569
3570 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3571 write32(DEFAULT_MCHBAR + 0x0004 + (channel << 8) +
3572 lane_registers[slotrank], make_mr0(ctrl, slotrank));
3573 write32(DEFAULT_MCHBAR + 0x0008 + (channel << 8) +
Patrick Rudolph7e513d12016-01-10 14:22:34 +01003574 lane_registers[slotrank],
3575 make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003576 }
3577}
3578
3579static void channel_test(ramctr_timing * ctrl)
3580{
3581 int channel, slotrank, lane;
3582
3583 FOR_ALL_POPULATED_CHANNELS
Patrick Rudolpha649a542016-01-17 18:32:06 +01003584 if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000)
3585 die("Mini channel test failed (1)\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003586 FOR_ALL_POPULATED_CHANNELS {
3587 fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
3588
3589 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3590 }
3591
3592 for (slotrank = 0; slotrank < 4; slotrank++)
3593 FOR_ALL_CHANNELS
3594 if (ctrl->rankmap[channel] & (1 << slotrank)) {
3595 FOR_ALL_LANES {
3596 write32(DEFAULT_MCHBAR + (0x4f40 + 4 * lane), 0);
3597 write32(DEFAULT_MCHBAR + (0x4d40 + 4 * lane), 0);
3598 }
3599 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003600 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003601 write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
3602 write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10), 0x0028a004);
3603 write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
3604 0x00060000 | (slotrank << 24));
3605 write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003606 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003607 write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
3608 write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281064);
3609 write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
3610 0x00000000 | (slotrank << 24));
3611 write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003612 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003613 write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f105);
3614 write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x04281064);
3615 write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
3616 0x00000000 | (slotrank << 24));
3617 write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003618 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003619 write32(DEFAULT_MCHBAR + 0x422c + (channel << 10), 0x0001f002);
3620 write32(DEFAULT_MCHBAR + 0x423c + (channel << 10), 0x00280c01);
3621 write32(DEFAULT_MCHBAR + 0x420c + (channel << 10),
3622 0x00060400 | (slotrank << 24));
3623 write32(DEFAULT_MCHBAR + 0x421c + (channel << 10), 0x00000240);
3624 write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
3625 wait_428c(channel);
3626 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01003627 if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane))
3628 die("Mini channel test failed (2)\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003629 }
3630}
3631
3632static void set_scrambling_seed(ramctr_timing * ctrl)
3633{
3634 int channel;
3635
3636 /* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
3637 I don't think so. */
3638 static u32 seeds[NUM_CHANNELS][3] = {
3639 {0x00009a36, 0xbafcfdcf, 0x46d1ab68},
3640 {0x00028bfa, 0x53fe4b49, 0x19ed5483}
3641 };
3642 FOR_ALL_POPULATED_CHANNELS {
3643 MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
3644 write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
3645 write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
3646 write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
3647 }
3648}
3649
3650static void set_4f8c(void)
3651{
3652 struct cpuid_result cpures;
3653 u32 cpu;
3654
3655 cpures = cpuid(0);
3656 cpu = (cpures.eax);
3657 if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) {
3658 MCHBAR32(0x4f8c) = 0x141D1519;
3659 } else {
3660 MCHBAR32(0x4f8c) = 0x551D1519;
3661 }
3662}
3663
3664static void prepare_training(ramctr_timing * ctrl)
3665{
3666 int channel;
3667
3668 FOR_ALL_POPULATED_CHANNELS {
3669 // Always drive command bus
3670 MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000;
3671 }
3672
3673 udelay(1);
3674
3675 FOR_ALL_POPULATED_CHANNELS {
3676 wait_428c(channel);
3677 }
3678}
3679
3680static void set_4008c(ramctr_timing * ctrl)
3681{
3682 int channel, slotrank;
3683 u32 reg;
3684 FOR_ALL_POPULATED_CHANNELS {
3685 u32 b20, b4_8_12;
3686 int min_320c = 10000;
3687 int max_320c = -10000;
3688
3689 FOR_ALL_POPULATED_RANKS {
3690 max_320c = max(ctrl->timings[channel][slotrank].val_320c, max_320c);
3691 min_320c = min(ctrl->timings[channel][slotrank].val_320c, min_320c);
3692 }
3693
3694 if (max_320c - min_320c > 51)
3695 b20 = 0;
3696 else
3697 b20 = ctrl->ref_card_offset[channel];
3698
3699 if (ctrl->reg_320c_range_threshold < max_320c - min_320c)
3700 b4_8_12 = 0x3330;
3701 else
3702 b4_8_12 = 0x2220;
3703
3704 reg = read32(DEFAULT_MCHBAR + 0x400c + (channel << 10));
3705 write32(DEFAULT_MCHBAR + 0x400c + (channel << 10),
3706 (reg & 0xFFF0FFFF)
3707 | (ctrl->ref_card_offset[channel] << 16)
3708 | (ctrl->ref_card_offset[channel] << 18));
3709 write32(DEFAULT_MCHBAR + 0x4008 + (channel << 10),
3710 0x0a000000
3711 | (b20 << 20)
3712 | ((ctrl->ref_card_offset[channel] + 2) << 16)
3713 | b4_8_12);
3714 }
3715}
3716
3717static void set_42a0(ramctr_timing * ctrl)
3718{
3719 int channel;
3720 FOR_ALL_POPULATED_CHANNELS {
3721 write32(DEFAULT_MCHBAR + (0x42a0 + 0x400 * channel),
3722 0x00001000 | ctrl->rankmap[channel]);
3723 MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK
3724 }
3725}
3726
3727static int encode_5d10(int ns)
3728{
3729 return (ns + 499) / 500;
3730}
3731
3732/* FIXME: values in this function should be hardware revision-dependent. */
3733static void final_registers(ramctr_timing * ctrl)
3734{
3735 int channel;
3736 int t1_cycles = 0, t1_ns = 0, t2_ns;
3737 int t3_ns;
3738 u32 r32;
3739
3740 write32(DEFAULT_MCHBAR + 0x4cd4, 0x00000046);
3741
3742 write32(DEFAULT_MCHBAR + 0x400c, (read32(DEFAULT_MCHBAR + 0x400c) & 0xFFFFCFFF) | 0x1000); // OK
3743 write32(DEFAULT_MCHBAR + 0x440c, (read32(DEFAULT_MCHBAR + 0x440c) & 0xFFFFCFFF) | 0x1000); // OK
3744 write32(DEFAULT_MCHBAR + 0x4cb0, 0x00000740);
3745 write32(DEFAULT_MCHBAR + 0x4380, 0x00000aaa); // OK
3746 write32(DEFAULT_MCHBAR + 0x4780, 0x00000aaa); // OK
3747 write32(DEFAULT_MCHBAR + 0x4f88, 0x5f7003ff); // OK
3748 write32(DEFAULT_MCHBAR + 0x5064, 0x00073000 | ctrl->reg_5064b0); // OK
3749
3750 FOR_ALL_CHANNELS {
3751 switch (ctrl->rankmap[channel]) {
3752 /* Unpopulated channel. */
3753 case 0:
3754 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0);
3755 break;
3756 /* Only single-ranked dimms. */
3757 case 1:
3758 case 4:
3759 case 5:
3760 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x373131);
3761 break;
3762 /* Dual-ranked dimms present. */
3763 default:
3764 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x9b6ea1);
3765 break;
3766 }
3767 }
3768
3769 write32 (DEFAULT_MCHBAR + 0x5880, 0xca9171e5);
3770 write32 (DEFAULT_MCHBAR + 0x5888,
3771 (read32 (DEFAULT_MCHBAR + 0x5888) & ~0xffffff) | 0xe4d5d0);
3772 write32 (DEFAULT_MCHBAR + 0x58a8, read32 (DEFAULT_MCHBAR + 0x58a8) & ~0x1f);
3773 write32 (DEFAULT_MCHBAR + 0x4294,
3774 (read32 (DEFAULT_MCHBAR + 0x4294) & ~0x30000)
3775 | (1 << 16));
3776 write32 (DEFAULT_MCHBAR + 0x4694,
3777 (read32 (DEFAULT_MCHBAR + 0x4694) & ~0x30000)
3778 | (1 << 16));
3779
3780 MCHBAR32(0x5030) |= 1; // OK
3781 MCHBAR32(0x5030) |= 0x80; // OK
3782 MCHBAR32(0x5f18) = 0xfa; // OK
3783
3784 /* Find a populated channel. */
3785 FOR_ALL_POPULATED_CHANNELS
3786 break;
3787
3788 t1_cycles = ((read32(DEFAULT_MCHBAR + 0x4290 + channel * 0x400) >> 8) & 0xff);
3789 r32 = read32(DEFAULT_MCHBAR + 0x5064);
3790 if (r32 & 0x20000)
3791 t1_cycles += (r32 & 0xfff);
3792 t1_cycles += (read32(DEFAULT_MCHBAR + channel * 0x400 + 0x42a4) & 0xfff);
3793 t1_ns = t1_cycles * ctrl->tCK / 256 + 544;
3794 if (!(r32 & 0x20000))
3795 t1_ns += 500;
3796
3797 t2_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f10) >> 8) & 0xfff);
3798 if ( read32(DEFAULT_MCHBAR + 0x5f00) & 8 )
3799 {
3800 t3_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f20) >> 8) & 0xfff);
3801 t3_ns += 10 * (read32(DEFAULT_MCHBAR + 0x5f18) & 0xff);
3802 }
3803 else
3804 {
3805 t3_ns = 500;
3806 }
3807 printk(BIOS_DEBUG, "t123: %d, %d, %d\n",
3808 t1_ns, t2_ns, t3_ns);
3809 write32 (DEFAULT_MCHBAR + 0x5d10,
3810 ((encode_5d10(t1_ns) + encode_5d10(t2_ns)) << 16)
3811 | (encode_5d10(t1_ns) << 8)
3812 | ((encode_5d10(t3_ns) + encode_5d10(t2_ns) + encode_5d10(t1_ns)) << 24)
3813 | (read32(DEFAULT_MCHBAR + 0x5d10) & 0xC0C0C0C0)
3814 | 0xc);
3815}
3816
3817static void save_timings(ramctr_timing * ctrl)
3818{
3819 struct mrc_data_container *mrcdata;
3820 int output_len = ALIGN(sizeof (*ctrl), 16);
3821
3822 /* Save the MRC S3 restore data to cbmem */
3823 mrcdata = cbmem_add
3824 (CBMEM_ID_MRCDATA,
3825 output_len + sizeof(struct mrc_data_container));
3826
3827 printk(BIOS_DEBUG, "Relocate MRC DATA from %p to %p (%u bytes)\n",
3828 ctrl, mrcdata, output_len);
3829
3830 mrcdata->mrc_signature = MRC_DATA_SIGNATURE;
3831 mrcdata->mrc_data_size = output_len;
3832 mrcdata->reserved = 0;
3833 memcpy(mrcdata->mrc_data, ctrl, sizeof (*ctrl));
3834
3835 /* Zero the unused space in aligned buffer. */
3836 if (output_len > sizeof (*ctrl))
3837 memset(mrcdata->mrc_data+sizeof (*ctrl), 0,
3838 output_len - sizeof (*ctrl));
3839
3840 mrcdata->mrc_checksum = compute_ip_checksum(mrcdata->mrc_data,
3841 mrcdata->mrc_data_size);
3842}
3843
3844static void restore_timings(ramctr_timing * ctrl)
3845{
3846 int channel, slotrank, lane;
3847
3848 FOR_ALL_POPULATED_CHANNELS
3849 MCHBAR32(0x4004 + 0x400 * channel) =
3850 ctrl->tRRD
3851 | (ctrl->tRTP << 4)
3852 | (ctrl->tCKE << 8)
3853 | (ctrl->tWTR << 12)
3854 | (ctrl->tFAW << 16)
3855 | (ctrl->tWR << 24)
3856 | (ctrl->cmd_stretch[channel] << 30);
3857
3858 udelay(1);
3859
3860 FOR_ALL_POPULATED_CHANNELS {
3861 wait_428c(channel);
3862 }
3863
3864 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3865 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
3866 + 4 * lane, 0);
3867 }
3868
3869 FOR_ALL_POPULATED_CHANNELS
3870 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
3871 read32(DEFAULT_MCHBAR + 0x4008 +
3872 0x400 * channel) | 0x8000000);
3873
3874 FOR_ALL_POPULATED_CHANNELS {
3875 udelay (1);
3876 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
3877 read32(DEFAULT_MCHBAR + 0x4020 +
3878 0x400 * channel) | 0x200000);
3879 }
3880
3881 printram("CPE\n");
3882
3883 write32(DEFAULT_MCHBAR + 0x3400, 0);
3884 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3885
3886 printram("CP5b\n");
3887
3888 FOR_ALL_POPULATED_CHANNELS {
3889 program_timings(ctrl, channel);
3890 }
3891
3892 u32 reg, addr;
3893
3894 while (!(MCHBAR32(0x5084) & 0x10000)) ;
3895 do {
3896 reg = MCHBAR32(0x428c);
3897 } while ((reg & 0x14) == 0);
3898
3899 // Set state of memory controller
3900 MCHBAR32(0x5030) = 0x116;
3901 MCHBAR32(0x4ea0) = 0;
3902
3903 // Wait 500us
3904 udelay(500);
3905
3906 FOR_ALL_CHANNELS {
3907 // Set valid rank CKE
3908 reg = 0;
3909 reg = (reg & ~0xf) | ctrl->rankmap[channel];
3910 addr = 0x400 * channel + 0x42a0;
3911 MCHBAR32(addr) = reg;
3912
3913 // Wait 10ns for ranks to settle
3914 //udelay(0.01);
3915
3916 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
3917 MCHBAR32(addr) = reg;
3918
3919 // Write reset using a NOP
3920 write_reset(ctrl);
3921 }
3922
3923 /* mrs commands. */
3924 dram_mrscommands(ctrl);
3925
3926 printram("CP5c\n");
3927
3928 write32(DEFAULT_MCHBAR + 0x3000, 0);
3929
3930 FOR_ALL_CHANNELS {
3931 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3932 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3933 ~0x3f000000));
3934 udelay(2);
3935 }
3936
3937 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3938}
3939
3940void init_dram_ddr3(spd_raw_data * spds, int mobile, int min_tck,
3941 int s3resume)
3942{
3943 int me_uma_size;
3944 int cbmem_was_inited;
Patrick Rudolphb97009e2016-02-28 15:24:04 +01003945 dimm_info info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003946
3947 MCHBAR32(0x5f00) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +02003948
Vadim Bendebury7a3f36a2012-04-18 15:47:32 -07003949 report_platform_info();
3950
Stefan Reinauer00636b02012-04-04 00:08:51 +02003951 /* Wait for ME to be ready */
3952 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003953 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +02003954
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003955 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +02003956
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003957 u32 reg_5d10;
Stefan Reinauer00636b02012-04-04 00:08:51 +02003958
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003959 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +02003960
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003961 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +02003962
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003963 reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10); // !!! = 0x00000000
3964 if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */
3965 && reg_5d10 && !s3resume) {
3966 write32(DEFAULT_MCHBAR + 0x5d10, 0);
3967 /* Need reset. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02003968 outb(0x6, 0xcf9);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003969
Patrick Georgi546953c2014-11-29 10:38:17 +01003970 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02003971 }
Stefan Reinauer00636b02012-04-04 00:08:51 +02003972
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003973 ramctr_timing ctrl;
Vadim Bendebury48a4a7f2012-06-07 18:47:13 -07003974
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003975 memset(&ctrl, 0, sizeof (ctrl));
3976
3977 early_pch_init_native();
3978 early_thermal_init();
3979
3980 ctrl.mobile = mobile;
3981 ctrl.tCK = min_tck;
3982
3983 /* FIXME: for non-S3 we should be able to use timing caching with
3984 proper verification. Right now we use timings only for S3 case.
3985 */
3986 if (s3resume) {
3987 struct mrc_data_container *mrc_cache;
3988
3989 mrc_cache = find_current_mrc_cache();
3990 if (!mrc_cache || mrc_cache->mrc_data_size < sizeof (ctrl)) {
3991 /* Failed S3 resume, reset to come up cleanly */
3992 outb(0x6, 0xcf9);
3993 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02003994 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003995 memcpy(&ctrl, mrc_cache->mrc_data, sizeof (ctrl));
Stefan Reinauer00636b02012-04-04 00:08:51 +02003996 }
3997
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003998 if (!s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003999 /* Get DDR3 SPD data */
4000 dram_find_spds_ddr3(spds, &info, &ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004001
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004002 /* Find fastest common supported parameters */
4003 dram_find_common_params(&info, &ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004004
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004005 dram_dimm_mapping(&info, &ctrl);
4006 }
4007
4008 /* Set MCU frequency */
4009 dram_freq(&ctrl);
4010
4011 if (!s3resume) {
4012 /* Calculate timings */
4013 dram_timing(&ctrl);
4014 }
4015
4016 /* Set version register */
4017 MCHBAR32(0x5034) = 0xC04EB002;
4018
4019 /* Enable crossover */
4020 dram_xover(&ctrl);
4021
4022 /* Set timing and refresh registers */
4023 dram_timing_regs(&ctrl);
4024
4025 /* Power mode preset */
4026 MCHBAR32(0x4e80) = 0x5500;
4027
4028 /* Set scheduler parameters */
4029 MCHBAR32(0x4c20) = 0x10100005;
4030
4031 /* Set cpu specific register */
4032 set_4f8c();
4033
4034 /* Clear IO reset bit */
4035 MCHBAR32(0x5030) &= ~0x20;
4036
4037 /* Set MAD-DIMM registers */
4038 dram_dimm_set_mapping(&ctrl);
4039 printk(BIOS_DEBUG, "Done dimm mapping\n");
4040
4041 /* Zone config */
4042 dram_zones(&ctrl, 1);
4043
4044 /* Set memory map */
4045 dram_memorymap(&ctrl, me_uma_size);
4046 printk(BIOS_DEBUG, "Done memory map\n");
4047
4048 /* Set IO registers */
4049 dram_ioregs(&ctrl);
4050 printk(BIOS_DEBUG, "Done io registers\n");
4051
4052 udelay(1);
4053
4054 if (s3resume) {
4055 restore_timings(&ctrl);
4056 } else {
4057 /* Do jedec ddr3 reset sequence */
4058 dram_jedecreset(&ctrl);
4059 printk(BIOS_DEBUG, "Done jedec reset\n");
4060
4061 /* MRS commands */
4062 dram_mrscommands(&ctrl);
4063 printk(BIOS_DEBUG, "Done MRS commands\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004064
4065 /* Prepare for memory training */
4066 prepare_training(&ctrl);
4067
4068 read_training(&ctrl);
4069 write_training(&ctrl);
4070
4071 printram("CP5a\n");
4072
4073 discover_edges(&ctrl);
4074
4075 printram("CP5b\n");
4076
4077 command_training(&ctrl);
4078
4079 printram("CP5c\n");
4080
4081 discover_edges_write(&ctrl);
4082
4083 discover_timC_write(&ctrl);
4084
4085 normalize_training(&ctrl);
4086 }
4087
4088 set_4008c(&ctrl);
4089
4090 write_controller_mr(&ctrl);
4091
4092 if (!s3resume) {
4093 channel_test(&ctrl);
4094 }
4095
4096 /* FIXME: should be hardware revision-dependent. */
4097 write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
4098
4099 set_scrambling_seed(&ctrl);
4100
4101 set_42a0(&ctrl);
4102
4103 final_registers(&ctrl);
4104
4105 /* Zone config */
4106 dram_zones(&ctrl, 0);
4107
4108 if (!s3resume)
4109 quick_ram_check();
4110
4111 intel_early_me_status();
4112 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
4113 intel_early_me_status();
4114
Stefan Reinauer00636b02012-04-04 00:08:51 +02004115 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004116
4117 cbmem_was_inited = !cbmem_recovery(s3resume);
4118 if (!s3resume)
4119 save_timings(&ctrl);
4120 if (s3resume && !cbmem_was_inited) {
4121 /* Failed S3 resume, reset to come up cleanly */
4122 outb(0x6, 0xcf9);
4123 halt();
4124 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +01004125
4126 fill_smbios17(&info, (1000 << 8) / ctrl.tCK);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004127}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004128
4129#define HOST_BRIDGE PCI_DEVFN(0, 0)
4130#define DEFAULT_TCK TCK_800MHZ
4131
4132static unsigned int get_mem_min_tck(void)
4133{
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004134 u32 reg32;
4135 u8 rev;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004136 const struct device *dev;
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004137 const struct northbridge_intel_sandybridge_config *cfg = NULL;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004138
4139 dev = dev_find_slot(0, HOST_BRIDGE);
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004140 if (dev)
4141 cfg = dev->chip_info;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004142
4143 /* If this is zero, it just means devicetree.cb didn't set it */
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004144 if (!cfg || cfg->max_mem_clock_mhz == 0) {
4145 rev = pci_read_config8(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004146
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004147 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
4148 /* read Capabilities A Register DMFC bits */
4149 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A);
4150 reg32 &= 0x7;
4151
4152 switch (reg32) {
4153 case 7: return TCK_533MHZ;
4154 case 6: return TCK_666MHZ;
4155 case 5: return TCK_800MHZ;
4156 /* reserved: */
4157 default:
4158 break;
4159 }
4160 } else {
4161 /* read Capabilities B Register DMFC bits */
4162 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
4163 reg32 = (reg32 >> 4) & 0x7;
4164
4165 switch (reg32) {
4166 case 7: return TCK_533MHZ;
4167 case 6: return TCK_666MHZ;
4168 case 5: return TCK_800MHZ;
4169 case 4: return TCK_933MHZ;
4170 case 3: return TCK_1066MHZ;
4171 case 2: return TCK_1200MHZ;
4172 case 1: return TCK_1333MHZ;
4173 /* reserved: */
4174 default:
4175 break;
4176 }
4177 }
4178 return DEFAULT_TCK;
4179 } else {
4180 if (cfg->max_mem_clock_mhz >= 800)
4181 return TCK_800MHZ;
4182 else if (cfg->max_mem_clock_mhz >= 666)
4183 return TCK_666MHZ;
4184 else if (cfg->max_mem_clock_mhz >= 533)
4185 return TCK_533MHZ;
4186 else
4187 return TCK_400MHZ;
4188 }
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004189}
4190
4191void perform_raminit(int s3resume)
4192{
4193 spd_raw_data spd[4];
4194
4195 post_code(0x3a);
4196
4197 memset (spd, 0, sizeof (spd));
4198 mainboard_get_spd(spd);
4199
4200 timestamp_add_now(TS_BEFORE_INITRAM);
4201
4202 init_dram_ddr3(spd, 1, get_mem_min_tck(), s3resume);
4203}