blob: 48ec5b50b99954d137f039ae9dc27d649b0898bf [file] [log] [blame]
Stefan Reinauer00636b02012-04-04 00:08:51 +02001/*
2 * This file is part of the coreboot project.
3 *
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004 * Copyright (C) 2014 Damien Zammit <damien@zamaudio.com>
5 * Copyright (C) 2014 Vladimir Serbinenko <phcoder@gmail.com>
Stefan Reinauer00636b02012-04-04 00:08:51 +02006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Stefan Reinauer00636b02012-04-04 00:08:51 +020015 */
16
17#include <console/console.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +020018#include <console/usb.h>
Kyösti Mälkki5687fc92013-11-28 18:11:49 +020019#include <bootmode.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020020#include <string.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020021#include <arch/io.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020022#include <cbmem.h>
23#include <arch/cbfs.h>
24#include <cbfs.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070025#include <halt.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020026#include <ip_checksum.h>
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010027#include <timestamp.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020028#include <pc80/mc146818rtc.h>
Alexander Couzens81c5c762016-03-09 03:13:45 +010029#include <northbridge/intel/common/mrc_cache.h>
Duncan Laurie7b508dd2012-04-09 12:30:43 -070030#include <device/pci_def.h>
Patrick Rudolphb97009e2016-02-28 15:24:04 +010031#include <memory_info.h>
32#include <smbios.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070033#include "raminit_native.h"
Stefan Reinauer00636b02012-04-04 00:08:51 +020034#include "sandybridge.h"
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070035#include <delay.h>
36#include <lib.h>
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010037#include <device/device.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020038
39/* Management Engine is in the southbridge */
40#include "southbridge/intel/bd82x6x/me.h"
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070041/* For SPD. */
42#include "southbridge/intel/bd82x6x/smbus.h"
43#include "arch/cpu.h"
44#include "cpu/x86/msr.h"
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010045#include <northbridge/intel/sandybridge/chip.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020046
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070047/* FIXME: no ECC support. */
48/* FIXME: no support for 3-channel chipsets. */
Stefan Reinauer00636b02012-04-04 00:08:51 +020049
Patrick Rudolph371d2912015-10-09 13:33:25 +020050/*
51 * Register description:
52 * Intel provides a command queue of depth four.
53 * Every command is configured by using multiple registers.
54 * On executing the command queue you have to provide the depth used.
55 *
56 * Known registers:
57 * Channel X = [0, 1]
58 * Command queue index Y = [0, 1, 2, 3]
59 *
60 * DEFAULT_MCHBAR + 0x4220 + 0x400 * X + 4 * Y: command io register
61 * Controls the DRAM command signals
62 * Bit 0: !RAS
63 * Bit 1: !CAS
64 * Bit 2: !WE
65 *
66 * DEFAULT_MCHBAR + 0x4200 + 0x400 * X + 4 * Y: addr bankslot io register
67 * Controls the address, bank address and slotrank signals
68 * Bit 0-15 : Address
69 * Bit 20-22: Bank Address
70 * Bit 24-25: slotrank
71 *
72 * DEFAULT_MCHBAR + 0x4230 + 0x400 * X + 4 * Y: idle register
73 * Controls the idle time after issuing this DRAM command
74 * Bit 16-32: number of clock-cylces to idle
75 *
76 * DEFAULT_MCHBAR + 0x4284 + 0x400 * channel: execute command queue
77 * Starts to execute all queued commands
78 * Bit 0 : start DRAM command execution
79 * Bit 16-20: (number of queued commands - 1) * 4
80 */
81
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070082#define BASEFREQ 133
83#define tDLLK 512
Stefan Reinauer00636b02012-04-04 00:08:51 +020084
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070085#define IS_SANDY_CPU(x) ((x & 0xffff0) == 0x206a0)
86#define IS_SANDY_CPU_C(x) ((x & 0xf) == 4)
87#define IS_SANDY_CPU_D0(x) ((x & 0xf) == 5)
88#define IS_SANDY_CPU_D1(x) ((x & 0xf) == 6)
89#define IS_SANDY_CPU_D2(x) ((x & 0xf) == 7)
Stefan Reinauer00636b02012-04-04 00:08:51 +020090
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070091#define IS_IVY_CPU(x) ((x & 0xffff0) == 0x306a0)
92#define IS_IVY_CPU_C(x) ((x & 0xf) == 4)
93#define IS_IVY_CPU_K(x) ((x & 0xf) == 5)
94#define IS_IVY_CPU_D(x) ((x & 0xf) == 6)
95#define IS_IVY_CPU_E(x) ((x & 0xf) >= 8)
Stefan Reinauer00636b02012-04-04 00:08:51 +020096
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070097#define NUM_CHANNELS 2
98#define NUM_SLOTRANKS 4
99#define NUM_SLOTS 2
100#define NUM_LANES 8
Stefan Reinauer00636b02012-04-04 00:08:51 +0200101
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700102/* FIXME: Vendor BIOS uses 64 but our algorithms are less
103 performant and even 1 seems to be enough in practice. */
104#define NUM_PATTERNS 4
Stefan Reinauer00636b02012-04-04 00:08:51 +0200105
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700106typedef struct odtmap_st {
107 u16 rttwr;
108 u16 rttnom;
109} odtmap;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200110
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700111typedef struct dimm_info_st {
112 dimm_attr dimm[NUM_CHANNELS][NUM_SLOTS];
113} dimm_info;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200114
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700115struct ram_rank_timings {
116 /* Register 4024. One byte per slotrank. */
117 u8 val_4024;
118 /* Register 4028. One nibble per slotrank. */
119 u8 val_4028;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200120
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700121 int val_320c;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200122
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700123 struct ram_lane_timings {
124 /* lane register offset 0x10. */
125 u16 timA; /* bits 0 - 5, bits 16 - 18 */
126 u8 rising; /* bits 8 - 14 */
127 u8 falling; /* bits 20 - 26. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200128
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700129 /* lane register offset 0x20. */
130 int timC; /* bit 0 - 5, 19. */
131 u16 timB; /* bits 8 - 13, 15 - 17. */
132 } lanes[NUM_LANES];
133};
Stefan Reinauer00636b02012-04-04 00:08:51 +0200134
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700135struct ramctr_timing_st;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200136
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700137typedef struct ramctr_timing_st {
138 int mobile;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200139
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700140 u16 cas_supported;
141 /* tLatencies are in units of ns, scaled by x256 */
142 u32 tCK;
143 u32 tAA;
144 u32 tWR;
145 u32 tRCD;
146 u32 tRRD;
147 u32 tRP;
148 u32 tRAS;
149 u32 tRFC;
150 u32 tWTR;
151 u32 tRTP;
152 u32 tFAW;
153 /* Latencies in terms of clock cycles
154 * They are saved separately as they are needed for DRAM MRS commands*/
155 u8 CAS; /* CAS read latency */
156 u8 CWL; /* CAS write latency */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200157
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700158 u32 tREFI;
159 u32 tMOD;
160 u32 tXSOffset;
161 u32 tWLO;
162 u32 tCKE;
163 u32 tXPDLL;
164 u32 tXP;
165 u32 tAONPD;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200166
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700167 u16 reg_5064b0; /* bits 0-11. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200168
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700169 u8 rankmap[NUM_CHANNELS];
170 int ref_card_offset[NUM_CHANNELS];
171 u32 mad_dimm[NUM_CHANNELS];
172 int channel_size_mb[NUM_CHANNELS];
173 u32 cmd_stretch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200174
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700175 int reg_c14_offset;
176 int reg_320c_range_threshold;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200177
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700178 int edge_offset[3];
179 int timC_offset[3];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200180
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700181 int extended_temperature_range;
182 int auto_self_refresh;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200183
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700184 int rank_mirror[NUM_CHANNELS][NUM_SLOTRANKS];
185
186 struct ram_rank_timings timings[NUM_CHANNELS][NUM_SLOTRANKS];
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100187
188 dimm_info info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700189} ramctr_timing;
190
191#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
192#define NORTHBRIDGE PCI_DEV(0, 0x0, 0)
193#define FOR_ALL_LANES for (lane = 0; lane < NUM_LANES; lane++)
194#define FOR_ALL_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++)
195#define FOR_ALL_POPULATED_RANKS for (slotrank = 0; slotrank < NUM_SLOTRANKS; slotrank++) if (ctrl->rankmap[channel] & (1 << slotrank))
196#define FOR_ALL_POPULATED_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) if (ctrl->rankmap[channel])
197#define MAX_EDGE_TIMING 71
198#define MAX_TIMC 127
199#define MAX_TIMB 511
200#define MAX_TIMA 127
201
Patrick Rudolph24a845b2016-03-25 18:19:47 +0100202#define MAKE_ERR ((channel<<16)|(slotrank<<8)|1)
203
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700204static void program_timings(ramctr_timing * ctrl, int channel);
205
206static const char *ecc_decoder[] = {
Stefan Reinauer00636b02012-04-04 00:08:51 +0200207 "inactive",
208 "active on IO",
209 "disabled on IO",
210 "active"
211};
212
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700213static void wait_txt_clear(void)
214{
215 struct cpuid_result cp;
216
217 cp = cpuid_ext(0x1, 0x0);
218 /* Check if TXT is supported? */
219 if (!(cp.ecx & 0x40))
220 return;
221 /* Some TXT public bit. */
222 if (!(read32((void *)0xfed30010) & 1))
223 return;
224 /* Wait for TXT clear. */
225 while (!(read8((void *)0xfed40000) & (1 << 7))) ;
226}
227
228static void sfence(void)
229{
230 asm volatile ("sfence");
231}
232
Patrick Rudolph9b515682015-10-09 13:43:51 +0200233static void toggle_io_reset(void) {
234 /* toggle IO reset bit */
235 u32 r32 = read32(DEFAULT_MCHBAR + 0x5030);
236 write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20);
237 udelay(1);
238 write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20);
239 udelay(1);
240}
241
Stefan Reinauer00636b02012-04-04 00:08:51 +0200242/*
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100243 * Fill cbmem with information for SMBIOS type 17.
244 */
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100245static void fill_smbios17(ramctr_timing *ctrl)
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100246{
247 struct memory_info *mem_info;
248 int channel, slot;
249 struct dimm_info *dimm;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100250 uint16_t ddr_freq;
251 dimm_info *info = &ctrl->info;
252
253 ddr_freq = (1000 << 8) / ctrl->tCK;
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100254
255 /*
256 * Allocate CBMEM area for DIMM information used to populate SMBIOS
257 * table 17
258 */
259 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
260 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
261 if (!mem_info)
262 return;
263
264 memset(mem_info, 0, sizeof(*mem_info));
265
266 FOR_ALL_CHANNELS for(slot = 0; slot < NUM_SLOTS; slot++) {
267 dimm = &mem_info->dimm[mem_info->dimm_cnt];
268 if (info->dimm[channel][slot].size_mb) {
269 dimm->ddr_type = MEMORY_TYPE_DDR3;
270 dimm->ddr_frequency = ddr_freq;
271 dimm->dimm_size = info->dimm[channel][slot].size_mb;
272 dimm->channel_num = channel;
273 dimm->rank_per_dimm = info->dimm[channel][slot].ranks;
274 dimm->dimm_num = slot;
275 memcpy(dimm->module_part_number,
276 info->dimm[channel][slot].part_number, 16);
277 dimm->mod_id = info->dimm[channel][slot].manufacturer_id;
278 dimm->mod_type = info->dimm[channel][slot].dimm_type;
279 dimm->bus_width = info->dimm[channel][slot].width;
280 mem_info->dimm_cnt++;
281 }
282 }
283}
284
285/*
Stefan Reinauer00636b02012-04-04 00:08:51 +0200286 * Dump in the log memory controller configuration as read from the memory
287 * controller registers.
288 */
289static void report_memory_config(void)
290{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700291 u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200292 int i;
293
294 addr_decoder_common = MCHBAR32(0x5000);
295 addr_decode_ch[0] = MCHBAR32(0x5004);
296 addr_decode_ch[1] = MCHBAR32(0x5008);
297
298 printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700299 (MCHBAR32(0x5e04) * 13333 * 2 + 50) / 100);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200300 printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700301 addr_decoder_common & 3, (addr_decoder_common >> 2) & 3,
Stefan Reinauer00636b02012-04-04 00:08:51 +0200302 (addr_decoder_common >> 4) & 3);
303
304 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
305 u32 ch_conf = addr_decode_ch[i];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700306 printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i,
307 ch_conf);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200308 printk(BIOS_DEBUG, " ECC %s\n",
309 ecc_decoder[(ch_conf >> 24) & 3]);
310 printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
311 ((ch_conf >> 22) & 1) ? "on" : "off");
312 printk(BIOS_DEBUG, " rank interleave %s\n",
313 ((ch_conf >> 21) & 1) ? "on" : "off");
314 printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n",
315 ((ch_conf >> 0) & 0xff) * 256,
316 ((ch_conf >> 19) & 1) ? 16 : 8,
317 ((ch_conf >> 17) & 1) ? "dual" : "single",
318 ((ch_conf >> 16) & 1) ? "" : ", selected");
319 printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n",
320 ((ch_conf >> 8) & 0xff) * 256,
321 ((ch_conf >> 20) & 1) ? 16 : 8,
322 ((ch_conf >> 18) & 1) ? "dual" : "single",
323 ((ch_conf >> 16) & 1) ? ", selected" : "");
324 }
325}
326
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700327void read_spd(spd_raw_data * spd, u8 addr)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200328{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700329 int j;
330 for (j = 0; j < 256; j++)
331 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
332}
333
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100334static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700335{
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100336 int dimms = 0, dimms_on_channel;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700337 int channel, slot, spd_slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100338 dimm_info *dimm = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700339
340 memset (ctrl->rankmap, 0, sizeof (ctrl->rankmap));
341
342 ctrl->extended_temperature_range = 1;
343 ctrl->auto_self_refresh = 1;
344
345 FOR_ALL_CHANNELS {
346 ctrl->channel_size_mb[channel] = 0;
347
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100348 dimms_on_channel = 0;
349 /* count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700350 for (slot = 0; slot < NUM_SLOTS; slot++) {
351 spd_slot = 2 * channel + slot;
352 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100353 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
354 dimms_on_channel++;
355 }
356
357 for (slot = 0; slot < NUM_SLOTS; slot++) {
358 spd_slot = 2 * channel + slot;
359 /* search for XMP profile */
360 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
361 spd[spd_slot],
362 DDR3_XMP_PROFILE_1);
363
364 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
365 printram("No valid XMP profile found.\n");
366 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
367 } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
368 printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
369 dimm->dimm[channel][slot].dimms_per_channel,
370 dimms_on_channel);
371 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
372 } else if (dimm->dimm[channel][slot].voltage != 1500) {
373 /* TODO: support other DDR3 voltage than 1500mV */
374 printram("XMP profile's requested %u mV is unsupported.\n",
375 dimm->dimm[channel][slot].voltage);
376 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
377 }
378
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700379 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
380 // set dimm invalid
381 dimm->dimm[channel][slot].ranks = 0;
382 dimm->dimm[channel][slot].size_mb = 0;
383 continue;
384 }
385
386 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
387 dimms++;
388 ctrl->rank_mirror[channel][slot * 2] = 0;
389 ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
390 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
391
392 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
393 ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
394
395 ctrl->rankmap[channel] |= ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100396 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n",
397 channel, ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700398 }
399 if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc)
400 && dimm->dimm[channel][0].reference_card <= 5 && dimm->dimm[channel][1].reference_card <= 5) {
401 const int ref_card_offset_table[6][6] = {
402 { 0, 0, 0, 0, 2, 2, },
403 { 0, 0, 0, 0, 2, 2, },
404 { 0, 0, 0, 0, 2, 2, },
405 { 0, 0, 0, 0, 1, 1, },
406 { 2, 2, 2, 1, 0, 0, },
407 { 2, 2, 2, 1, 0, 0, },
408 };
409 ctrl->ref_card_offset[channel] = ref_card_offset_table[dimm->dimm[channel][0].reference_card]
410 [dimm->dimm[channel][1].reference_card];
411 } else
412 ctrl->ref_card_offset[channel] = 0;
413 }
414
415 if (!dimms)
416 die("No DIMMs were found");
417}
418
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100419static void dram_find_common_params(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700420{
421 size_t valid_dimms;
422 int channel, slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100423 dimm_info *dimms = &ctrl->info;
424
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700425 ctrl->cas_supported = 0xff;
426 valid_dimms = 0;
427 FOR_ALL_CHANNELS for (slot = 0; slot < 2; slot++) {
428 const dimm_attr *dimm = &dimms->dimm[channel][slot];
429 if (dimm->dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3)
430 continue;
431 valid_dimms++;
432
433 /* Find all possible CAS combinations */
434 ctrl->cas_supported &= dimm->cas_supported;
435
436 /* Find the smallest common latencies supported by all DIMMs */
437 ctrl->tCK = MAX(ctrl->tCK, dimm->tCK);
438 ctrl->tAA = MAX(ctrl->tAA, dimm->tAA);
439 ctrl->tWR = MAX(ctrl->tWR, dimm->tWR);
440 ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD);
441 ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD);
442 ctrl->tRP = MAX(ctrl->tRP, dimm->tRP);
443 ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS);
444 ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC);
445 ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR);
446 ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP);
447 ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW);
448 }
449
450 if (!ctrl->cas_supported)
451 die("Unsupported DIMM combination. "
452 "DIMMS do not support common CAS latency");
453 if (!valid_dimms)
454 die("No valid DIMMs found");
455}
456
457static u8 get_CWL(u8 CAS)
458{
459 /* Get CWL based on CAS using the following rule:
460 * _________________________________________
461 * CAS: | 4T | 5T | 6T | 7T | 8T | 9T | 10T | 11T |
462 * CWL: | 5T | 5T | 5T | 6T | 6T | 7T | 7T | 8T |
463 */
464 static const u8 cas_cwl_map[] = { 5, 5, 5, 6, 6, 7, 7, 8 };
465 if (CAS > 11)
466 return 8;
467 return cas_cwl_map[CAS - 4];
468}
469
470/* Frequency multiplier. */
471static u32 get_FRQ(u32 tCK)
472{
473 u32 FRQ;
474 FRQ = 256000 / (tCK * BASEFREQ);
475 if (FRQ > 8)
476 return 8;
477 if (FRQ < 3)
478 return 3;
479 return FRQ;
480}
481
482static u32 get_REFI(u32 tCK)
483{
484 /* Get REFI based on MCU frequency using the following rule:
485 * _________________________________________
486 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
487 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 |
488 */
489 static const u32 frq_refi_map[] =
490 { 3120, 4160, 5200, 6240, 7280, 8320 };
491 return frq_refi_map[get_FRQ(tCK) - 3];
492}
493
494static u8 get_XSOffset(u32 tCK)
495{
496 /* Get XSOffset based on MCU frequency using the following rule:
497 * _________________________
498 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
499 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 |
500 */
501 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 };
502 return frq_xs_map[get_FRQ(tCK) - 3];
503}
504
505static u8 get_MOD(u32 tCK)
506{
507 /* Get MOD based on MCU frequency using the following rule:
508 * _____________________________
509 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
510 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 |
511 */
512 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 };
513 return frq_mod_map[get_FRQ(tCK) - 3];
514}
515
516static u8 get_WLO(u32 tCK)
517{
518 /* Get WLO based on MCU frequency using the following rule:
519 * _______________________
520 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
521 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 |
522 */
523 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 };
524 return frq_wlo_map[get_FRQ(tCK) - 3];
525}
526
527static u8 get_CKE(u32 tCK)
528{
529 /* Get CKE based on MCU frequency using the following rule:
530 * _______________________
531 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
532 * CKE : | 3 | 3 | 4 | 4 | 5 | 6 |
533 */
534 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 };
535 return frq_cke_map[get_FRQ(tCK) - 3];
536}
537
538static u8 get_XPDLL(u32 tCK)
539{
540 /* Get XPDLL based on MCU frequency using the following rule:
541 * _____________________________
542 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
543 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 |
544 */
545 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 };
546 return frq_xpdll_map[get_FRQ(tCK) - 3];
547}
548
549static u8 get_XP(u32 tCK)
550{
551 /* Get XP based on MCU frequency using the following rule:
552 * _______________________
553 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
554 * XP : | 3 | 4 | 4 | 5 | 6 | 7 |
555 */
556 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 };
557 return frq_xp_map[get_FRQ(tCK) - 3];
558}
559
560static u8 get_AONPD(u32 tCK)
561{
562 /* Get AONPD based on MCU frequency using the following rule:
563 * ________________________
564 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
565 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 |
566 */
567 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 };
568 return frq_aonpd_map[get_FRQ(tCK) - 3];
569}
570
571static u32 get_COMP2(u32 tCK)
572{
573 /* Get COMP2 based on MCU frequency using the following rule:
574 * ___________________________________________________________
575 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
576 * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C |
577 */
578 static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C,
579 0xC6369CC, 0xC42514C, 0xC21410C
580 };
581 return frq_comp2_map[get_FRQ(tCK) - 3];
582}
583
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100584static u32 get_XOVER_CLK(u8 rankmap)
585{
586 return rankmap << 24;
587}
588
589static u32 get_XOVER_CMD(u8 rankmap)
590{
591 u32 reg;
592
593 // enable xover cmd
594 reg = 0x4000;
595
596 // enable xover ctl
597 if (rankmap & 0x3)
598 reg |= 0x20000;
599
600 if (rankmap & 0xc)
601 reg |= 0x4000000;
602
603 return reg;
604}
605
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700606static void dram_timing(ramctr_timing * ctrl)
607{
608 u8 val;
609 u32 val32;
610
611 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
612 * we cap it if we have faster DIMMs.
613 * Then, align it to the closest JEDEC standard frequency */
614 if (ctrl->tCK <= TCK_1066MHZ) {
615 ctrl->tCK = TCK_1066MHZ;
616 ctrl->edge_offset[0] = 16;
617 ctrl->edge_offset[1] = 7;
618 ctrl->edge_offset[2] = 7;
619 ctrl->timC_offset[0] = 18;
620 ctrl->timC_offset[1] = 7;
621 ctrl->timC_offset[2] = 7;
622 ctrl->reg_c14_offset = 16;
623 ctrl->reg_5064b0 = 0x218;
624 ctrl->reg_320c_range_threshold = 13;
625 } else if (ctrl->tCK <= TCK_933MHZ) {
626 ctrl->tCK = TCK_933MHZ;
627 ctrl->edge_offset[0] = 14;
628 ctrl->edge_offset[1] = 6;
629 ctrl->edge_offset[2] = 6;
630 ctrl->timC_offset[0] = 15;
631 ctrl->timC_offset[1] = 6;
632 ctrl->timC_offset[2] = 6;
633 ctrl->reg_c14_offset = 14;
634 ctrl->reg_5064b0 = 0x1d5;
635 ctrl->reg_320c_range_threshold = 15;
636 } else if (ctrl->tCK <= TCK_800MHZ) {
637 ctrl->tCK = TCK_800MHZ;
638 ctrl->edge_offset[0] = 13;
639 ctrl->edge_offset[1] = 5;
640 ctrl->edge_offset[2] = 5;
641 ctrl->timC_offset[0] = 14;
642 ctrl->timC_offset[1] = 5;
643 ctrl->timC_offset[2] = 5;
644 ctrl->reg_c14_offset = 12;
645 ctrl->reg_5064b0 = 0x193;
646 ctrl->reg_320c_range_threshold = 15;
647 } else if (ctrl->tCK <= TCK_666MHZ) {
648 ctrl->tCK = TCK_666MHZ;
649 ctrl->edge_offset[0] = 10;
650 ctrl->edge_offset[1] = 4;
651 ctrl->edge_offset[2] = 4;
652 ctrl->timC_offset[0] = 11;
653 ctrl->timC_offset[1] = 4;
654 ctrl->timC_offset[2] = 4;
655 ctrl->reg_c14_offset = 10;
656 ctrl->reg_5064b0 = 0x150;
657 ctrl->reg_320c_range_threshold = 16;
658 } else if (ctrl->tCK <= TCK_533MHZ) {
659 ctrl->tCK = TCK_533MHZ;
660 ctrl->edge_offset[0] = 8;
661 ctrl->edge_offset[1] = 3;
662 ctrl->edge_offset[2] = 3;
663 ctrl->timC_offset[0] = 9;
664 ctrl->timC_offset[1] = 3;
665 ctrl->timC_offset[2] = 3;
666 ctrl->reg_c14_offset = 8;
667 ctrl->reg_5064b0 = 0x10d;
668 ctrl->reg_320c_range_threshold = 17;
669 } else {
670 ctrl->tCK = TCK_400MHZ;
671 ctrl->edge_offset[0] = 6;
672 ctrl->edge_offset[1] = 2;
673 ctrl->edge_offset[2] = 2;
674 ctrl->timC_offset[0] = 6;
675 ctrl->timC_offset[1] = 2;
676 ctrl->timC_offset[2] = 2;
677 ctrl->reg_c14_offset = 8;
678 ctrl->reg_5064b0 = 0xcd;
679 ctrl->reg_320c_range_threshold = 17;
680 }
681
682 val32 = (1000 << 8) / ctrl->tCK;
683 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
684
685 /* Find CAS and CWL latencies */
686 val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK;
687 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
688 /* Find lowest supported CAS latency that satisfies the minimum value */
689 while (!((ctrl->cas_supported >> (val - 4)) & 1)
690 && (ctrl->cas_supported >> (val - 4))) {
691 val++;
692 }
693 /* Is CAS supported */
694 if (!(ctrl->cas_supported & (1 << (val - 4))))
695 printk(BIOS_DEBUG, "CAS not supported\n");
696 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
697 ctrl->CAS = val;
698 ctrl->CWL = get_CWL(ctrl->CAS);
699 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
700
701 /* Find tRCD */
702 ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK;
703 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
704
705 ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK;
706 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
707
708 /* Find tRAS */
709 ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK;
710 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
711
712 /* Find tWR */
713 ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK;
714 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
715
716 /* Find tFAW */
717 ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK;
718 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
719
720 /* Find tRRD */
721 ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK;
722 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
723
724 /* Find tRTP */
725 ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK;
726 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
727
728 /* Find tWTR */
729 ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK;
730 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
731
732 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
733 ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK;
734 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
735
736 ctrl->tREFI = get_REFI(ctrl->tCK);
737 ctrl->tMOD = get_MOD(ctrl->tCK);
738 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
739 ctrl->tWLO = get_WLO(ctrl->tCK);
740 ctrl->tCKE = get_CKE(ctrl->tCK);
741 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
742 ctrl->tXP = get_XP(ctrl->tCK);
743 ctrl->tAONPD = get_AONPD(ctrl->tCK);
744}
745
746static void dram_freq(ramctr_timing * ctrl)
747{
748 if (ctrl->tCK > TCK_400MHZ) {
749 printk (BIOS_ERR, "DRAM frequency is under lowest supported frequency (400 MHz). Increasing to 400 MHz as last resort");
750 ctrl->tCK = TCK_400MHZ;
751 }
752 while (1) {
753 u8 val2;
754 u32 reg1 = 0;
755
756 /* Step 1 - Set target PCU frequency */
757
758 if (ctrl->tCK <= TCK_1066MHZ) {
759 ctrl->tCK = TCK_1066MHZ;
760 } else if (ctrl->tCK <= TCK_933MHZ) {
761 ctrl->tCK = TCK_933MHZ;
762 } else if (ctrl->tCK <= TCK_800MHZ) {
763 ctrl->tCK = TCK_800MHZ;
764 } else if (ctrl->tCK <= TCK_666MHZ) {
765 ctrl->tCK = TCK_666MHZ;
766 } else if (ctrl->tCK <= TCK_533MHZ) {
767 ctrl->tCK = TCK_533MHZ;
768 } else if (ctrl->tCK <= TCK_400MHZ) {
769 ctrl->tCK = TCK_400MHZ;
770 } else {
771 die ("No lock frequency found");
772 }
773
774 /* Frequency mulitplier. */
775 u32 FRQ = get_FRQ(ctrl->tCK);
776
777 /* Step 2 - Select frequency in the MCU */
778 reg1 = FRQ;
779 reg1 |= 0x80000000; // set running bit
780 MCHBAR32(0x5e00) = reg1;
781 while (reg1 & 0x80000000) {
782 printk(BIOS_DEBUG, " PLL busy...");
783 reg1 = MCHBAR32(0x5e00);
784 }
785 printk(BIOS_DEBUG, "done\n");
786
787 /* Step 3 - Verify lock frequency */
788 reg1 = MCHBAR32(0x5e04);
789 val2 = (u8) reg1;
790 if (val2 >= FRQ) {
791 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
792 (1000 << 8) / ctrl->tCK);
793 return;
794 }
795 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
796 ctrl->tCK++;
797 }
798}
799
800static void dram_xover(ramctr_timing * ctrl)
801{
802 u32 reg;
803 int channel;
804
805 FOR_ALL_CHANNELS {
806 // enable xover clk
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100807 reg = get_XOVER_CLK(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100808 printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
809 reg);
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100810 MCHBAR32(channel * 0x100 + 0xc14) = reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700811
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100812 // enable xover ctl & xover cmd
813 reg = get_XOVER_CMD(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100814 printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
815 reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700816 MCHBAR32(0x100 * channel + 0x320c) = reg;
817 }
818}
819
820static void dram_timing_regs(ramctr_timing * ctrl)
821{
822 u32 reg, addr, val32, cpu, stretch;
823 struct cpuid_result cpures;
824 int channel;
825
826 FOR_ALL_CHANNELS {
827 // DBP
828 reg = 0;
829 reg |= ctrl->tRCD;
830 reg |= (ctrl->tRP << 4);
831 reg |= (ctrl->CAS << 8);
832 reg |= (ctrl->CWL << 12);
833 reg |= (ctrl->tRAS << 16);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100834 printram("DBP [%x] = %x\n", 0x400 * channel + 0x4000, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700835 MCHBAR32(0x400 * channel + 0x4000) = reg;
836
837 // RAP
838 reg = 0;
839 reg |= ctrl->tRRD;
840 reg |= (ctrl->tRTP << 4);
841 reg |= (ctrl->tCKE << 8);
842 reg |= (ctrl->tWTR << 12);
843 reg |= (ctrl->tFAW << 16);
844 reg |= (ctrl->tWR << 24);
845 reg |= (3 << 30);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100846 printram("RAP [%x] = %x\n", 0x400 * channel + 0x4004, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700847 MCHBAR32(0x400 * channel + 0x4004) = reg;
848
849 // OTHP
850 addr = 0x400 * channel + 0x400c;
851 reg = 0;
852 reg |= ctrl->tXPDLL;
853 reg |= (ctrl->tXP << 5);
854 reg |= (ctrl->tAONPD << 8);
855 reg |= 0xa0000;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100856 printram("OTHP [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700857 MCHBAR32(addr) = reg;
858
859 MCHBAR32(0x400 * channel + 0x4014) = 0;
860
861 MCHBAR32(addr) |= 0x00020000;
862
863 // ODT stretch
864 reg = 0;
865
866 cpures = cpuid(0);
867 cpu = cpures.eax;
868 if (IS_IVY_CPU(cpu)
869 || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) {
870 stretch = 2;
871 addr = 0x400 * channel + 0x400c;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100872 printram("ODT stretch [%x] = %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700873 0x400 * channel + 0x400c, reg);
874 reg = MCHBAR32(addr);
875
876 if (((ctrl->rankmap[channel] & 3) == 0)
877 || (ctrl->rankmap[channel] & 0xc) == 0) {
878
879 // Rank 0 - operate on rank 2
880 reg = (reg & ~0xc0000) | (stretch << 18);
881
882 // Rank 2 - operate on rank 0
883 reg = (reg & ~0x30000) | (stretch << 16);
884
Patrick Rudolpha649a542016-01-17 18:32:06 +0100885 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700886 MCHBAR32(addr) = reg;
887 }
888
889 } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) {
890 stretch = 3;
891 addr = 0x400 * channel + 0x401c;
892 reg = MCHBAR32(addr);
893
894 if (((ctrl->rankmap[channel] & 3) == 0)
895 || (ctrl->rankmap[channel] & 0xc) == 0) {
896
897 // Rank 0 - operate on rank 2
898 reg = (reg & ~0x3000) | (stretch << 12);
899
900 // Rank 2 - operate on rank 0
901 reg = (reg & ~0xc00) | (stretch << 10);
902
Patrick Rudolpha649a542016-01-17 18:32:06 +0100903 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700904 MCHBAR32(addr) = reg;
905 }
906 } else {
907 stretch = 0;
908 }
909
910 // REFI
911 reg = 0;
912 val32 = ctrl->tREFI;
913 reg = (reg & ~0xffff) | val32;
914 val32 = ctrl->tRFC;
915 reg = (reg & ~0x1ff0000) | (val32 << 16);
916 val32 = (u32) (ctrl->tREFI * 9) / 1024;
917 reg = (reg & ~0xfe000000) | (val32 << 25);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100918 printram("REFI [%x] = %x\n", 0x400 * channel + 0x4298,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700919 reg);
920 MCHBAR32(0x400 * channel + 0x4298) = reg;
921
922 MCHBAR32(0x400 * channel + 0x4294) |= 0xff;
923
924 // SRFTP
925 reg = 0;
926 val32 = tDLLK;
927 reg = (reg & ~0xfff) | val32;
928 val32 = ctrl->tXSOffset;
929 reg = (reg & ~0xf000) | (val32 << 12);
930 val32 = tDLLK - ctrl->tXSOffset;
931 reg = (reg & ~0x3ff0000) | (val32 << 16);
932 val32 = ctrl->tMOD - 8;
933 reg = (reg & ~0xf0000000) | (val32 << 28);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100934 printram("SRFTP [%x] = %x\n", 0x400 * channel + 0x42a4,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700935 reg);
936 MCHBAR32(0x400 * channel + 0x42a4) = reg;
937 }
938}
939
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100940static void dram_dimm_mapping(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700941{
942 u32 reg, val32;
943 int channel;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100944 dimm_info *info = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700945
946 FOR_ALL_CHANNELS {
947 dimm_attr *dimmA = 0;
948 dimm_attr *dimmB = 0;
949 reg = 0;
950 val32 = 0;
951 if (info->dimm[channel][0].size_mb >=
952 info->dimm[channel][1].size_mb) {
953 // dimm 0 is bigger, set it to dimmA
954 dimmA = &info->dimm[channel][0];
955 dimmB = &info->dimm[channel][1];
956 reg |= (0 << 16);
957 } else {
958 // dimm 1 is bigger, set it to dimmA
959 dimmA = &info->dimm[channel][1];
960 dimmB = &info->dimm[channel][0];
961 reg |= (1 << 16);
962 }
963 // dimmA
964 if (dimmA && (dimmA->ranks > 0)) {
965 val32 = dimmA->size_mb / 256;
966 reg = (reg & ~0xff) | val32;
967 val32 = dimmA->ranks - 1;
968 reg = (reg & ~0x20000) | (val32 << 17);
969 val32 = (dimmA->width / 8) - 1;
970 reg = (reg & ~0x80000) | (val32 << 19);
971 }
972 // dimmB
973 if (dimmB && (dimmB->ranks > 0)) {
974 val32 = dimmB->size_mb / 256;
975 reg = (reg & ~0xff00) | (val32 << 8);
976 val32 = dimmB->ranks - 1;
977 reg = (reg & ~0x40000) | (val32 << 18);
978 val32 = (dimmB->width / 8) - 1;
979 reg = (reg & ~0x100000) | (val32 << 20);
980 }
981 reg = (reg & ~0x200000) | (1 << 21); // rank interleave
982 reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave
983
984 // Save MAD-DIMM register
985 if ((dimmA && (dimmA->ranks > 0))
986 || (dimmB && (dimmB->ranks > 0))) {
987 ctrl->mad_dimm[channel] = reg;
988 } else {
989 ctrl->mad_dimm[channel] = 0;
990 }
991 }
992}
993
994static void dram_dimm_set_mapping(ramctr_timing * ctrl)
995{
996 int channel;
997 FOR_ALL_CHANNELS {
998 MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
999 }
1000}
1001
1002static void dram_zones(ramctr_timing * ctrl, int training)
1003{
1004 u32 reg, ch0size, ch1size;
1005 u8 val;
1006 reg = 0;
1007 val = 0;
1008 if (training) {
1009 ch0size = ctrl->channel_size_mb[0] ? 256 : 0;
1010 ch1size = ctrl->channel_size_mb[1] ? 256 : 0;
1011 } else {
1012 ch0size = ctrl->channel_size_mb[0];
1013 ch1size = ctrl->channel_size_mb[1];
1014 }
1015
1016 if (ch0size >= ch1size) {
1017 reg = MCHBAR32(0x5014);
1018 val = ch1size / 256;
1019 reg = (reg & ~0xff000000) | val << 24;
1020 reg = (reg & ~0xff0000) | (2 * val) << 16;
1021 MCHBAR32(0x5014) = reg;
1022 MCHBAR32(0x5000) = 0x24;
1023 } else {
1024 reg = MCHBAR32(0x5014);
1025 val = ch0size / 256;
1026 reg = (reg & ~0xff000000) | val << 24;
1027 reg = (reg & ~0xff0000) | (2 * val) << 16;
1028 MCHBAR32(0x5014) = reg;
1029 MCHBAR32(0x5000) = 0x21;
1030 }
1031}
1032
1033static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
1034{
1035 u32 reg, val, reclaim;
1036 u32 tom, gfxstolen, gttsize;
1037 size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase,
1038 tsegbase, mestolenbase;
1039 size_t tsegbasedelta, remapbase, remaplimit;
1040 uint16_t ggc;
1041
1042 mmiosize = 0x400;
1043
1044 ggc = pci_read_config16(NORTHBRIDGE, GGC);
1045 if (!(ggc & 2)) {
1046 gfxstolen = ((ggc >> 3) & 0x1f) * 32;
1047 gttsize = ((ggc >> 8) & 0x3);
1048 } else {
1049 gfxstolen = 0;
1050 gttsize = 0;
1051 }
1052
1053 tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
1054
1055 tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
1056
1057 mestolenbase = tom - me_uma_size;
1058
1059 toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
1060 tom - me_uma_size);
1061 gfxstolenbase = toludbase - gfxstolen;
1062 gttbase = gfxstolenbase - gttsize;
1063
1064 tsegbase = gttbase - tsegsize;
1065
1066 // Round tsegbase down to nearest address aligned to tsegsize
1067 tsegbasedelta = tsegbase & (tsegsize - 1);
1068 tsegbase &= ~(tsegsize - 1);
1069
1070 gttbase -= tsegbasedelta;
1071 gfxstolenbase -= tsegbasedelta;
1072 toludbase -= tsegbasedelta;
1073
1074 // Test if it is possible to reclaim a hole in the ram addressing
1075 if (tom - me_uma_size > toludbase) {
1076 // Reclaim is possible
1077 reclaim = 1;
1078 remapbase = MAX(4096, tom - me_uma_size);
1079 remaplimit =
1080 remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1;
1081 touudbase = remaplimit + 1;
1082 } else {
1083 // Reclaim not possible
1084 reclaim = 0;
1085 touudbase = tom - me_uma_size;
1086 }
1087
1088 // Update memory map in pci-e configuration space
Patrick Rudolpha649a542016-01-17 18:32:06 +01001089 printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001090
1091 // TOM (top of memory)
1092 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0);
1093 val = tom & 0xfff;
1094 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001095 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001096 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg);
1097
1098 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4);
1099 val = tom & 0xfffff000;
1100 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001101 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001102 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg);
1103
1104 // TOLUD (top of low used dram)
1105 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
1106 val = toludbase & 0xfff;
1107 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001108 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xbc, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001109 pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg);
1110
1111 // TOUUD LSB (top of upper usable dram)
1112 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
1113 val = touudbase & 0xfff;
1114 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001115 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001116 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg);
1117
1118 // TOUUD MSB
1119 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
1120 val = touudbase & 0xfffff000;
1121 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001122 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xac, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001123 pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg);
1124
1125 if (reclaim) {
1126 // REMAP BASE
1127 pcie_write_config32(PCI_DEV(0, 0, 0), 0x90, remapbase << 20);
1128 pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, remapbase >> 12);
1129
1130 // REMAP LIMIT
1131 pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
1132 pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
1133 }
1134 // TSEG
1135 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
1136 val = tsegbase & 0xfff;
1137 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001138 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001139 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg);
1140
1141 // GFX stolen memory
1142 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0);
1143 val = gfxstolenbase & 0xfff;
1144 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001145 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001146 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg);
1147
1148 // GTT stolen memory
1149 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4);
1150 val = gttbase & 0xfff;
1151 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001152 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001153 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
1154
1155 if (me_uma_size) {
1156 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
1157 val = (0x80000 - me_uma_size) & 0xfffff000;
1158 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001159 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x7c, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001160 pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg);
1161
1162 // ME base
1163 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70);
1164 val = mestolenbase & 0xfff;
1165 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001166 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x70, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001167 pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg);
1168
1169 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74);
1170 val = mestolenbase & 0xfffff000;
1171 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001172 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x74, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001173 pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg);
1174
1175 // ME mask
1176 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78);
1177 val = (0x80000 - me_uma_size) & 0xfff;
1178 reg = (reg & ~0xfff00000) | (val << 20);
1179 reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem
1180
1181 reg = (reg & ~0x800) | (1 << 11); // set ME memory enable
Patrick Rudolpha649a542016-01-17 18:32:06 +01001182 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x78, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001183 pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg);
1184 }
1185}
1186
1187static void dram_ioregs(ramctr_timing * ctrl)
1188{
1189 u32 reg, comp2;
1190
1191 int channel;
1192
1193 // IO clock
1194 FOR_ALL_CHANNELS {
1195 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
1196 }
1197
1198 // IO command
1199 FOR_ALL_CHANNELS {
1200 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
1201 }
1202
1203 // IO control
1204 FOR_ALL_POPULATED_CHANNELS {
1205 program_timings(ctrl, channel);
1206 }
1207
1208 // Rcomp
Patrick Rudolpha649a542016-01-17 18:32:06 +01001209 printram("RCOMP...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001210 reg = 0;
1211 while (reg == 0) {
1212 reg = MCHBAR32(0x5084) & 0x10000;
1213 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001214 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001215
1216 // Set comp2
1217 comp2 = get_COMP2(ctrl->tCK);
1218 MCHBAR32(0x3714) = comp2;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001219 printram("COMP2 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001220
1221 // Set comp1
1222 FOR_ALL_POPULATED_CHANNELS {
1223 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
1224 reg = (reg & ~0xe00) | (1 << 9); //odt
1225 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
1226 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
1227 MCHBAR32(0x1810 + channel * 0x100) = reg;
1228 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001229 printram("COMP1 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001230
Patrick Rudolpha649a542016-01-17 18:32:06 +01001231 printram("FORCE RCOMP and wait 20us...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001232 MCHBAR32(0x5f08) |= 0x100;
1233 udelay(20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001234 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001235}
1236
1237static void wait_428c(int channel)
1238{
1239 while (1) {
1240 if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
1241 return;
1242 }
1243}
1244
1245static void write_reset(ramctr_timing * ctrl)
1246{
1247 int channel, slotrank;
1248
1249 /* choose a populated channel. */
1250 channel = (ctrl->rankmap[0]) ? 0 : 1;
1251
1252 wait_428c(channel);
1253
1254 /* choose a populated rank. */
1255 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
1256
Patrick Rudolph371d2912015-10-09 13:33:25 +02001257 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001258 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1259 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01);
1260
1261 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1262 (slotrank << 24) | 0x60000);
1263
1264 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1265
1266 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001);
1267 wait_428c(channel);
1268}
1269
1270static void dram_jedecreset(ramctr_timing * ctrl)
1271{
1272 u32 reg, addr;
1273 int channel;
1274
1275 while (!(MCHBAR32(0x5084) & 0x10000)) ;
1276 do {
1277 reg = MCHBAR32(0x428c);
1278 } while ((reg & 0x14) == 0);
1279
1280 // Set state of memory controller
1281 reg = 0x112;
1282 MCHBAR32(0x5030) = reg;
1283 MCHBAR32(0x4ea0) = 0;
1284 reg |= 2; //ddr reset
1285 MCHBAR32(0x5030) = reg;
1286
1287 // Assert dimm reset signal
1288 reg = MCHBAR32(0x5030);
1289 reg &= ~0x2;
1290 MCHBAR32(0x5030) = reg;
1291
1292 // Wait 200us
1293 udelay(200);
1294
1295 // Deassert dimm reset signal
1296 MCHBAR32(0x5030) |= 2;
1297
1298 // Wait 500us
1299 udelay(500);
1300
1301 // Enable DCLK
1302 MCHBAR32(0x5030) |= 4;
1303
1304 // XXX Wait 20ns
1305 udelay(1);
1306
1307 FOR_ALL_CHANNELS {
1308 // Set valid rank CKE
1309 reg = 0;
1310 reg = (reg & ~0xf) | ctrl->rankmap[channel];
1311 addr = 0x400 * channel + 0x42a0;
1312 MCHBAR32(addr) = reg;
1313
1314 // Wait 10ns for ranks to settle
1315 //udelay(0.01);
1316
1317 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
1318 MCHBAR32(addr) = reg;
1319
1320 // Write reset using a NOP
1321 write_reset(ctrl);
1322 }
1323}
1324
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001325static odtmap get_ODT(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001326{
1327 /* Get ODT based on rankmap: */
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001328 int dimms_per_ch = (ctrl->rankmap[channel] & 1)
1329 + ((ctrl->rankmap[channel] >> 2) & 1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001330
1331 if (dimms_per_ch == 1) {
1332 return (const odtmap){60, 60};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001333 } else {
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001334 return (const odtmap){120, 30};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001335 }
1336}
1337
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001338static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001339 int reg, u32 val)
1340{
1341 wait_428c(channel);
1342
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001343 if (ctrl->rank_mirror[channel][slotrank]) {
1344 /* DDR3 Rank1 Address mirror
1345 * swap the following pins:
1346 * A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 */
1347 reg = ((reg >> 1) & 1) | ((reg << 1) & 2);
1348 val = (val & ~0x1f8) | ((val >> 1) & 0xa8)
1349 | ((val & 0xa8) << 1);
1350 }
1351
Patrick Rudolph371d2912015-10-09 13:33:25 +02001352 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001353 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000);
1354 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
1355 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1356 (slotrank << 24) | (reg << 20) | val | 0x60000);
1357 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1358
Patrick Rudolph371d2912015-10-09 13:33:25 +02001359 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001360 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000);
1361 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001);
1362 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
1363 (slotrank << 24) | (reg << 20) | val | 0x60000);
1364 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1365
Patrick Rudolph371d2912015-10-09 13:33:25 +02001366 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001367 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000);
1368 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1369 0x1001 | (ctrl->tMOD << 16));
1370 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1371 (slotrank << 24) | (reg << 20) | val | 0x60000);
1372 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1373 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
1374}
1375
1376static u32 make_mr0(ramctr_timing * ctrl, u8 rank)
1377{
1378 u16 mr0reg, mch_cas, mch_wr;
1379 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 +02001380
1381 /* DLL Reset - self clearing - set after CLK frequency has been changed */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001382 mr0reg = 0x100;
1383
1384 // Convert CAS to MCH register friendly
1385 if (ctrl->CAS < 12) {
1386 mch_cas = (u16) ((ctrl->CAS - 4) << 1);
1387 } else {
1388 mch_cas = (u16) (ctrl->CAS - 12);
1389 mch_cas = ((mch_cas << 1) | 0x1);
1390 }
1391
1392 // Convert tWR to MCH register friendly
1393 mch_wr = mch_wr_t[ctrl->tWR - 5];
1394
1395 mr0reg = (mr0reg & ~0x4) | (mch_cas & 0x1);
1396 mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3);
1397 mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001398
1399 // Precharge PD - Fast (desktop) 0x1 or slow (mobile) 0x0 - mostly power-saving feature
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001400 mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12);
1401 return mr0reg;
1402}
1403
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001404static void dram_mr0(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001405{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001406 write_mrreg(ctrl, channel, rank, 0,
1407 make_mr0(ctrl, rank));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001408}
1409
1410static u32 encode_odt(u32 odt)
1411{
1412 switch (odt) {
1413 case 30:
1414 return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4
1415 case 60:
1416 return (1 << 2); // RZQ/4
1417 case 120:
1418 return (1 << 6); // RZQ/2
1419 default:
1420 case 0:
1421 return 0;
1422 }
1423}
1424
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001425static u32 make_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001426{
1427 odtmap odt;
1428 u32 mr1reg;
1429
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001430 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001431 mr1reg = 0x2;
1432
1433 mr1reg |= encode_odt(odt.rttnom);
1434
1435 return mr1reg;
1436}
1437
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001438static void dram_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001439{
1440 u16 mr1reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001441
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001442 mr1reg = make_mr1(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001443
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001444 write_mrreg(ctrl, channel, rank, 1, mr1reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001445}
1446
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001447static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001448{
1449 u16 pasr, cwl, mr2reg;
1450 odtmap odt;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001451 int srt;
1452
1453 pasr = 0;
1454 cwl = ctrl->CWL - 5;
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001455 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001456
1457 srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh;
1458
1459 mr2reg = 0;
1460 mr2reg = (mr2reg & ~0x7) | pasr;
1461 mr2reg = (mr2reg & ~0x38) | (cwl << 3);
1462 mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6);
1463 mr2reg = (mr2reg & ~0x80) | (srt << 7);
1464 mr2reg |= (odt.rttwr / 60) << 9;
1465
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001466 write_mrreg(ctrl, channel, rank, 2, mr2reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001467}
1468
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001469static void dram_mr3(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001470{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001471 write_mrreg(ctrl, channel, rank, 3, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001472}
1473
1474static void dram_mrscommands(ramctr_timing * ctrl)
1475{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001476 u8 slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001477 u32 reg, addr;
1478 int channel;
1479
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001480 FOR_ALL_POPULATED_CHANNELS {
1481 FOR_ALL_POPULATED_RANKS {
1482 // MR2
1483 dram_mr2(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001484
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001485 // MR3
1486 dram_mr3(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001487
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001488 // MR1
1489 dram_mr1(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001490
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001491 // MR0
1492 dram_mr0(ctrl, slotrank, channel);
1493 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001494 }
1495
Patrick Rudolph371d2912015-10-09 13:33:25 +02001496 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001497 write32(DEFAULT_MCHBAR + 0x4e20, 0x7);
1498 write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001);
1499 write32(DEFAULT_MCHBAR + 0x4e00, 0x60002);
1500 write32(DEFAULT_MCHBAR + 0x4e10, 0);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001501
1502 /* DRAM command ZQCL */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001503 write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003);
1504 write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001);
1505 write32(DEFAULT_MCHBAR + 0x4e04, 0x60400);
1506 write32(DEFAULT_MCHBAR + 0x4e14, 0x288);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001507
1508 /* execute command queue on all channels ? */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001509 write32(DEFAULT_MCHBAR + 0x4e84, 0x40004);
1510
1511 // Drain
1512 FOR_ALL_CHANNELS {
1513 // Wait for ref drained
1514 wait_428c(channel);
1515 }
1516
1517 // Refresh enable
1518 MCHBAR32(0x5030) |= 8;
1519
1520 FOR_ALL_POPULATED_CHANNELS {
1521 addr = 0x400 * channel + 0x4020;
1522 reg = MCHBAR32(addr);
1523 reg &= ~0x200000;
1524 MCHBAR32(addr) = reg;
1525
1526 wait_428c(channel);
1527
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001528 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001529
1530 // Drain
1531 wait_428c(channel);
1532
Patrick Rudolph371d2912015-10-09 13:33:25 +02001533 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001534 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1535 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
1536 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001537 (slotrank << 24) | 0x60000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001538 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
1539 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1);
1540
1541 // Drain
1542 wait_428c(channel);
1543 }
1544}
1545
1546const u32 lane_registers[] = {
1547 0x0000, 0x0200, 0x0400, 0x0600,
1548 0x1000, 0x1200, 0x1400, 0x1600,
1549 0x0800
1550};
1551
1552static void program_timings(ramctr_timing * ctrl, int channel)
1553{
1554 u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028;
1555 int lane;
1556 int slotrank, slot;
1557 int full_shift = 0;
1558 u16 slot320c[NUM_SLOTS];
1559
1560 FOR_ALL_POPULATED_RANKS {
1561 if (full_shift < -ctrl->timings[channel][slotrank].val_320c)
1562 full_shift = -ctrl->timings[channel][slotrank].val_320c;
1563 }
1564
1565 for (slot = 0; slot < NUM_SLOTS; slot++)
1566 switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) {
1567 case 0:
1568 default:
1569 slot320c[slot] = 0x7f;
1570 break;
1571 case 1:
1572 slot320c[slot] =
1573 ctrl->timings[channel][2 * slot + 0].val_320c +
1574 full_shift;
1575 break;
1576 case 2:
1577 slot320c[slot] =
1578 ctrl->timings[channel][2 * slot + 1].val_320c +
1579 full_shift;
1580 break;
1581 case 3:
1582 slot320c[slot] =
1583 (ctrl->timings[channel][2 * slot].val_320c +
1584 ctrl->timings[channel][2 * slot +
1585 1].val_320c) / 2 +
1586 full_shift;
1587 break;
1588 }
1589
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001590 /* enable CMD XOVER */
1591 reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001592 reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
1593 reg32 |= (slot320c[1] & 0x7f) << 18;
1594 reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
1595
1596 MCHBAR32(0x320c + 0x100 * channel) = reg32;
1597
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001598 /* enable CLK XOVER */
1599 reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001600 reg_c18 = 0;
1601
1602 FOR_ALL_POPULATED_RANKS {
1603 int shift =
1604 ctrl->timings[channel][slotrank].val_320c + full_shift;
1605 int offset_val_c14;
1606 if (shift < 0)
1607 shift = 0;
1608 offset_val_c14 = ctrl->reg_c14_offset + shift;
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001609 /* set CLK phase shift */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001610 reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
1611 reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
1612 }
1613
1614 MCHBAR32(0xc14 + channel * 0x100) = reg_c14;
1615 MCHBAR32(0xc18 + channel * 0x100) = reg_c18;
1616
1617 reg_4028 = MCHBAR32(0x4028 + 0x400 * channel);
1618 reg_4028 &= 0xffff0000;
1619
1620 reg_4024 = 0;
1621
1622 FOR_ALL_POPULATED_RANKS {
1623 int post_timA_min_high = 7, post_timA_max_high = 0;
1624 int pre_timA_min_high = 7, pre_timA_max_high = 0;
1625 int shift_402x = 0;
1626 int shift =
1627 ctrl->timings[channel][slotrank].val_320c + full_shift;
1628
1629 if (shift < 0)
1630 shift = 0;
1631
1632 FOR_ALL_LANES {
1633 if (post_timA_min_high >
1634 ((ctrl->timings[channel][slotrank].lanes[lane].
1635 timA + shift) >> 6))
1636 post_timA_min_high =
1637 ((ctrl->timings[channel][slotrank].
1638 lanes[lane].timA + shift) >> 6);
1639 if (pre_timA_min_high >
1640 (ctrl->timings[channel][slotrank].lanes[lane].
1641 timA >> 6))
1642 pre_timA_min_high =
1643 (ctrl->timings[channel][slotrank].
1644 lanes[lane].timA >> 6);
1645 if (post_timA_max_high <
1646 ((ctrl->timings[channel][slotrank].lanes[lane].
1647 timA + shift) >> 6))
1648 post_timA_max_high =
1649 ((ctrl->timings[channel][slotrank].
1650 lanes[lane].timA + shift) >> 6);
1651 if (pre_timA_max_high <
1652 (ctrl->timings[channel][slotrank].lanes[lane].
1653 timA >> 6))
1654 pre_timA_max_high =
1655 (ctrl->timings[channel][slotrank].
1656 lanes[lane].timA >> 6);
1657 }
1658
1659 if (pre_timA_max_high - pre_timA_min_high <
1660 post_timA_max_high - post_timA_min_high)
1661 shift_402x = +1;
1662 else if (pre_timA_max_high - pre_timA_min_high >
1663 post_timA_max_high - post_timA_min_high)
1664 shift_402x = -1;
1665
1666 reg_4028 |=
1667 (ctrl->timings[channel][slotrank].val_4028 + shift_402x -
1668 post_timA_min_high) << (4 * slotrank);
1669 reg_4024 |=
1670 (ctrl->timings[channel][slotrank].val_4024 +
1671 shift_402x) << (8 * slotrank);
1672
1673 FOR_ALL_LANES {
1674 MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel +
1675 4 * slotrank)
1676 =
1677 (((ctrl->timings[channel][slotrank].lanes[lane].
1678 timA + shift) & 0x3f)
1679 |
1680 ((ctrl->timings[channel][slotrank].lanes[lane].
1681 rising + shift) << 8)
1682 |
1683 (((ctrl->timings[channel][slotrank].lanes[lane].
1684 timA + shift -
1685 (post_timA_min_high << 6)) & 0x1c0) << 10)
Patrick Rudolph0188b132016-02-10 19:16:34 +01001686 | ((ctrl->timings[channel][slotrank].lanes[lane].
1687 falling + shift) << 20));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001688
1689 MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel +
1690 4 * slotrank)
1691 =
1692 (((ctrl->timings[channel][slotrank].lanes[lane].
1693 timC + shift) & 0x3f)
1694 |
1695 (((ctrl->timings[channel][slotrank].lanes[lane].
1696 timB + shift) & 0x3f) << 8)
1697 |
1698 (((ctrl->timings[channel][slotrank].lanes[lane].
1699 timB + shift) & 0x1c0) << 9)
1700 |
1701 (((ctrl->timings[channel][slotrank].lanes[lane].
1702 timC + shift) & 0x40) << 13));
1703 }
1704 }
1705 MCHBAR32(0x4024 + 0x400 * channel) = reg_4024;
1706 MCHBAR32(0x4028 + 0x400 * channel) = reg_4028;
1707}
1708
1709static void test_timA(ramctr_timing * ctrl, int channel, int slotrank)
1710{
1711 wait_428c(channel);
1712
Patrick Rudolph371d2912015-10-09 13:33:25 +02001713 /* DRAM command MRS
1714 * write MR3 MPR enable
1715 * in this mode only RD and RDA are allowed
1716 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001717 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
1718 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1719 (0xc01 | (ctrl->tMOD << 16)));
1720 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1721 (slotrank << 24) | 0x360004);
1722 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1723
Patrick Rudolph371d2912015-10-09 13:33:25 +02001724 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001725 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
1726 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01);
1727 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24));
1728 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1729
Patrick Rudolph371d2912015-10-09 13:33:25 +02001730 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001731 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
1732 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1733 0x100f | ((ctrl->CAS + 36) << 16));
1734 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1735 (slotrank << 24) | 0x60000);
1736 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1737
Patrick Rudolph371d2912015-10-09 13:33:25 +02001738 /* DRAM command MRS
1739 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001740 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
1741 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
1742 (0xc01 | (ctrl->tMOD << 16)));
1743 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
1744 (slotrank << 24) | 0x360000);
1745 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
1746
1747 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
1748
1749 wait_428c(channel);
1750}
1751
1752static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank,
1753 int lane)
1754{
1755 u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA;
1756 return ((read32
1757 (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 +
1758 ((timA / 32) & 1) * 4)
1759 >> (timA % 32)) & 1);
1760}
1761
1762struct run {
1763 int middle;
1764 int end;
1765 int start;
1766 int all;
1767 int length;
1768};
1769
1770static struct run get_longest_zero_run(int *seq, int sz)
1771{
1772 int i, ls;
1773 int bl = 0, bs = 0;
1774 struct run ret;
1775
1776 ls = 0;
1777 for (i = 0; i < 2 * sz; i++)
1778 if (seq[i % sz]) {
1779 if (i - ls > bl) {
1780 bl = i - ls;
1781 bs = ls;
1782 }
1783 ls = i + 1;
1784 }
1785 if (bl == 0) {
1786 ret.middle = sz / 2;
1787 ret.start = 0;
1788 ret.end = sz;
1789 ret.all = 1;
1790 return ret;
1791 }
1792
1793 ret.start = bs % sz;
1794 ret.end = (bs + bl - 1) % sz;
1795 ret.middle = (bs + (bl - 1) / 2) % sz;
1796 ret.length = bl;
1797 ret.all = 0;
1798
1799 return ret;
1800}
1801
1802static void discover_timA_coarse(ramctr_timing * ctrl, int channel,
1803 int slotrank, int *upperA)
1804{
1805 int timA;
1806 int statistics[NUM_LANES][128];
1807 int lane;
1808
1809 for (timA = 0; timA < 128; timA++) {
1810 FOR_ALL_LANES {
1811 ctrl->timings[channel][slotrank].lanes[lane].timA = timA;
1812 }
1813 program_timings(ctrl, channel);
1814
1815 test_timA(ctrl, channel, slotrank);
1816
1817 FOR_ALL_LANES {
1818 statistics[lane][timA] =
1819 !does_lane_work(ctrl, channel, slotrank, lane);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001820 printram("Astat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001821 channel, slotrank, lane, timA,
1822 statistics[lane][timA]);
1823 }
1824 }
1825 FOR_ALL_LANES {
1826 struct run rn = get_longest_zero_run(statistics[lane], 128);
1827 ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle;
1828 upperA[lane] = rn.end;
1829 if (upperA[lane] < rn.middle)
1830 upperA[lane] += 128;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001831 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001832 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001833 printram("Aend: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001834 lane, upperA[lane]);
1835 }
1836}
1837
1838static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
1839 int *upperA)
1840{
1841 int timA_delta;
1842 int statistics[NUM_LANES][51];
1843 int lane, i;
1844
1845 memset(statistics, 0, sizeof(statistics));
1846
1847 for (timA_delta = -25; timA_delta <= 25; timA_delta++) {
1848 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
1849 timA = upperA[lane] + timA_delta + 0x40;
1850 program_timings(ctrl, channel);
1851
1852 for (i = 0; i < 100; i++) {
1853 test_timA(ctrl, channel, slotrank);
1854 FOR_ALL_LANES {
1855 statistics[lane][timA_delta + 25] +=
1856 does_lane_work(ctrl, channel, slotrank,
1857 lane);
1858 }
1859 }
1860 }
1861 FOR_ALL_LANES {
1862 int last_zero, first_all;
1863
1864 for (last_zero = -25; last_zero <= 25; last_zero++)
1865 if (statistics[lane][last_zero + 25])
1866 break;
1867 last_zero--;
1868 for (first_all = -25; first_all <= 25; first_all++)
1869 if (statistics[lane][first_all + 25] == 100)
1870 break;
1871
1872 printram("lane %d: %d, %d\n", lane, last_zero,
1873 first_all);
1874
1875 ctrl->timings[channel][slotrank].lanes[lane].timA =
1876 (last_zero + first_all) / 2 + upperA[lane];
Patrick Rudolpha649a542016-01-17 18:32:06 +01001877 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001878 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
1879 }
1880}
1881
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001882static int discover_402x(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001883 int *upperA)
1884{
1885 int works[NUM_LANES];
1886 int lane;
1887 while (1) {
1888 int all_works = 1, some_works = 0;
1889 program_timings(ctrl, channel);
1890 test_timA(ctrl, channel, slotrank);
1891 FOR_ALL_LANES {
1892 works[lane] =
1893 !does_lane_work(ctrl, channel, slotrank, lane);
1894 if (works[lane])
1895 some_works = 1;
1896 else
1897 all_works = 0;
1898 }
1899 if (all_works)
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001900 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001901 if (!some_works) {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001902 if (ctrl->timings[channel][slotrank].val_4024 < 2) {
1903 printk(BIOS_EMERG, "402x discovery failed (1): %d, %d\n",
1904 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001905 return MAKE_ERR;
1906 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001907 ctrl->timings[channel][slotrank].val_4024 -= 2;
1908 printram("4024 -= 2;\n");
1909 continue;
1910 }
1911 ctrl->timings[channel][slotrank].val_4028 += 2;
1912 printram("4028 += 2;\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001913 if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) {
1914 printk(BIOS_EMERG, "402x discovery failed (2): %d, %d\n",
1915 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001916 return MAKE_ERR;
1917 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001918 FOR_ALL_LANES if (works[lane]) {
1919 ctrl->timings[channel][slotrank].lanes[lane].timA +=
1920 128;
1921 upperA[lane] += 128;
1922 printram("increment %d, %d, %d\n", channel,
1923 slotrank, lane);
1924 }
1925 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001926 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001927}
1928
1929struct timA_minmax {
1930 int timA_min_high, timA_max_high;
1931};
1932
1933static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1934 struct timA_minmax *mnmx)
1935{
1936 int lane;
1937 mnmx->timA_min_high = 7;
1938 mnmx->timA_max_high = 0;
1939
1940 FOR_ALL_LANES {
1941 if (mnmx->timA_min_high >
1942 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1943 mnmx->timA_min_high =
1944 (ctrl->timings[channel][slotrank].lanes[lane].
1945 timA >> 6);
1946 if (mnmx->timA_max_high <
1947 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1948 mnmx->timA_max_high =
1949 (ctrl->timings[channel][slotrank].lanes[lane].
1950 timA >> 6);
1951 }
1952}
1953
1954static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1955 struct timA_minmax *mnmx)
1956{
1957 struct timA_minmax post;
1958 int shift_402x = 0;
1959
1960 /* Get changed maxima. */
1961 pre_timA_change(ctrl, channel, slotrank, &post);
1962
1963 if (mnmx->timA_max_high - mnmx->timA_min_high <
1964 post.timA_max_high - post.timA_min_high)
1965 shift_402x = +1;
1966 else if (mnmx->timA_max_high - mnmx->timA_min_high >
1967 post.timA_max_high - post.timA_min_high)
1968 shift_402x = -1;
1969 else
1970 shift_402x = 0;
1971
1972 ctrl->timings[channel][slotrank].val_4028 += shift_402x;
1973 ctrl->timings[channel][slotrank].val_4024 += shift_402x;
1974 printram("4024 += %d;\n", shift_402x);
1975 printram("4028 += %d;\n", shift_402x);
1976}
1977
Patrick Rudolph371d2912015-10-09 13:33:25 +02001978/* Compensate the skew between DQS and DQs.
1979 * To ease PCB design a small skew between Data Strobe signals and
1980 * Data Signals is allowed.
1981 * The controller has to measure and compensate this skew for every byte-lane.
1982 * By delaying either all DQs signals or DQS signal, a full phase
1983 * shift can be introduced.
1984 * It is assumed that one byte-lane's DQs signals have the same routing delay.
1985 *
1986 * To measure the actual skew, the DRAM is placed in "read leveling" mode.
1987 * In read leveling mode the DRAM-chip outputs an alternating periodic pattern.
1988 * The memory controller iterates over all possible values to do a full phase shift
1989 * and issues read commands.
1990 * With DQS and DQs in phase the data read is expected to alternate on every byte:
1991 * 0xFF 0x00 0xFF ...
1992 * Once the controller has detected this pattern a bit in the result register is
1993 * set for the current phase shift.
1994 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001995static int read_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001996{
1997 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001998 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001999
2000 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002001 int all_high, some_high;
2002 int upperA[NUM_LANES];
2003 struct timA_minmax mnmx;
2004
2005 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002006
2007 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002008 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2009 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2010 0xc01 | (ctrl->tRP << 16));
2011 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2012 (slotrank << 24) | 0x60400);
2013 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2014 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2015
2016 write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001);
2017
2018 ctrl->timings[channel][slotrank].val_4028 = 4;
2019 ctrl->timings[channel][slotrank].val_4024 = 55;
2020 program_timings(ctrl, channel);
2021
2022 discover_timA_coarse(ctrl, channel, slotrank, upperA);
2023
2024 all_high = 1;
2025 some_high = 0;
2026 FOR_ALL_LANES {
2027 if (ctrl->timings[channel][slotrank].lanes[lane].
2028 timA >= 0x40)
2029 some_high = 1;
2030 else
2031 all_high = 0;
2032 }
2033
2034 if (all_high) {
2035 ctrl->timings[channel][slotrank].val_4028--;
2036 printram("4028--;\n");
2037 FOR_ALL_LANES {
2038 ctrl->timings[channel][slotrank].lanes[lane].
2039 timA -= 0x40;
2040 upperA[lane] -= 0x40;
2041
2042 }
2043 } else if (some_high) {
2044 ctrl->timings[channel][slotrank].val_4024++;
2045 ctrl->timings[channel][slotrank].val_4028++;
2046 printram("4024++;\n");
2047 printram("4028++;\n");
2048 }
2049
2050 program_timings(ctrl, channel);
2051
2052 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2053
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002054 err = discover_402x(ctrl, channel, slotrank, upperA);
2055 if (err)
2056 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002057
2058 post_timA_change(ctrl, channel, slotrank, &mnmx);
2059 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2060
2061 discover_timA_fine(ctrl, channel, slotrank, upperA);
2062
2063 post_timA_change(ctrl, channel, slotrank, &mnmx);
2064 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2065
2066 FOR_ALL_LANES {
2067 ctrl->timings[channel][slotrank].lanes[lane].timA -= mnmx.timA_min_high * 0x40;
2068 }
2069 ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high;
2070 printram("4028 -= %d;\n", mnmx.timA_min_high);
2071
2072 post_timA_change(ctrl, channel, slotrank, &mnmx);
2073
2074 printram("4/8: %d, %d, %x, %x\n", channel, slotrank,
2075 ctrl->timings[channel][slotrank].val_4024,
2076 ctrl->timings[channel][slotrank].val_4028);
2077
Patrick Rudolpha649a542016-01-17 18:32:06 +01002078 printram("final results:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002079 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01002080 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002081 lane,
2082 ctrl->timings[channel][slotrank].lanes[lane].timA);
2083
2084 write32(DEFAULT_MCHBAR + 0x3400, 0);
2085
Patrick Rudolph9b515682015-10-09 13:43:51 +02002086 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002087 }
2088
2089 FOR_ALL_POPULATED_CHANNELS {
2090 program_timings(ctrl, channel);
2091 }
2092 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2093 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
2094 + 4 * lane, 0);
2095 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002096 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002097}
2098
2099static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
2100{
2101 int lane;
2102
2103 FOR_ALL_LANES {
2104 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0);
2105 read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane);
2106 }
2107
2108 wait_428c(channel);
2109
Patrick Rudolph371d2912015-10-09 13:33:25 +02002110 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002111 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2112 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2113 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
2114 | 4 | (ctrl->tRCD << 16));
2115
2116 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2117 (slotrank << 24) | (6 << 16));
2118
2119 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
2120
Patrick Rudolph371d2912015-10-09 13:33:25 +02002121 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002122 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2123 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001);
2124 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2125 (slotrank << 24) | 8);
2126 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2127
Patrick Rudolph371d2912015-10-09 13:33:25 +02002128 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002129 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2130 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4);
2131 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2132 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2133
Patrick Rudolph371d2912015-10-09 13:33:25 +02002134 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002135 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2136 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2137 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2138 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2139 (slotrank << 24) | 8);
2140 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2141
2142 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2143
2144 wait_428c(channel);
2145
Patrick Rudolph371d2912015-10-09 13:33:25 +02002146 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002147 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2148 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2149 0xc01 | (ctrl->tRP << 16));
2150 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2151 (slotrank << 24) | 0x60400);
2152 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2153
Patrick Rudolph371d2912015-10-09 13:33:25 +02002154 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002155 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2156 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2157 (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10)
2158 | 8 | (ctrl->CAS << 16));
2159
2160 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2161 (slotrank << 24) | 0x60000);
2162
2163 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244);
2164
Patrick Rudolph371d2912015-10-09 13:33:25 +02002165 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002166 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2167 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2168 0x40011f4 | (max(ctrl->tRTP, 8) << 16));
2169 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2170 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2171
Patrick Rudolph371d2912015-10-09 13:33:25 +02002172 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002173 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2174 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2175 0xc01 | (ctrl->tRP << 16));
2176 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2177 (slotrank << 24) | 0x60400);
2178 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2179 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2180 wait_428c(channel);
2181}
2182
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002183static int discover_timC(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002184{
2185 int timC;
2186 int statistics[NUM_LANES][MAX_TIMC + 1];
2187 int lane;
2188
2189 wait_428c(channel);
2190
Patrick Rudolph371d2912015-10-09 13:33:25 +02002191 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002192 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2193 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2194 0xc01 | (ctrl->tRP << 16));
2195 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2196 (slotrank << 24) | 0x60400);
2197 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2198 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2199
2200 for (timC = 0; timC <= MAX_TIMC; timC++) {
2201 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
2202 timC = timC;
2203 program_timings(ctrl, channel);
2204
2205 test_timC(ctrl, channel, slotrank);
2206
2207 FOR_ALL_LANES {
2208 statistics[lane][timC] =
2209 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2210 0x400 * channel);
2211 printram("Cstat: %d, %d, %d, %x, %x\n",
2212 channel, slotrank, lane, timC,
2213 statistics[lane][timC]);
2214 }
2215 }
2216 FOR_ALL_LANES {
2217 struct run rn =
2218 get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
2219 ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002220 if (rn.all) {
2221 printk(BIOS_EMERG, "timC discovery failed: %d, %d, %d\n",
2222 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002223 return MAKE_ERR;
2224 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002225 printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002226 lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
2227 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002228 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002229}
2230
2231static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
2232{
2233 int channel, ret = 0;
2234 FOR_ALL_POPULATED_CHANNELS if (channel < target_channel)
2235 ret++;
2236 return ret;
2237}
2238
2239static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b)
2240{
2241 unsigned j;
2242 unsigned channel_offset =
2243 get_precedening_channels(ctrl, channel) * 0x40;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002244 for (j = 0; j < 16; j++)
2245 write32((void *)(0x04000000 + channel_offset + 4 * j), j & 2 ? b : a);
2246 sfence();
2247}
2248
2249static int num_of_channels(const ramctr_timing * ctrl)
2250{
2251 int ret = 0;
2252 int channel;
2253 FOR_ALL_POPULATED_CHANNELS ret++;
2254 return ret;
2255}
2256
2257static void fill_pattern1(ramctr_timing * ctrl, int channel)
2258{
2259 unsigned j;
2260 unsigned channel_offset =
2261 get_precedening_channels(ctrl, channel) * 0x40;
2262 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2263 for (j = 0; j < 16; j++)
2264 write32((void *)(0x04000000 + channel_offset + j * 4), 0xffffffff);
2265 for (j = 0; j < 16; j++)
2266 write32((void *)(0x04000000 + channel_offset + channel_step + j * 4), 0);
2267 sfence();
2268}
2269
2270static void precharge(ramctr_timing * ctrl)
2271{
2272 int channel, slotrank, lane;
2273
2274 FOR_ALL_POPULATED_CHANNELS {
2275 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2276 ctrl->timings[channel][slotrank].lanes[lane].falling =
2277 16;
2278 ctrl->timings[channel][slotrank].lanes[lane].rising =
2279 16;
Patrick Rudolpha649a542016-01-17 18:32:06 +01002280 }
2281
2282 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002283
2284 FOR_ALL_POPULATED_RANKS {
2285 wait_428c(channel);
2286
Patrick Rudolph371d2912015-10-09 13:33:25 +02002287 /* DRAM command MRS
2288 * write MR3 MPR enable
2289 * in this mode only RD and RDA are allowed
2290 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002291 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2292 0x1f000);
2293 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2294 0xc01 | (ctrl->tMOD << 16));
2295 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2296 (slotrank << 24) | 0x360004);
2297 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2298
Patrick Rudolph371d2912015-10-09 13:33:25 +02002299 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002300 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2301 0x1f105);
2302 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2303 0x4041003);
2304 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2305 (slotrank << 24) | 0);
2306 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2307
Patrick Rudolph371d2912015-10-09 13:33:25 +02002308 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002309 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2310 0x1f105);
2311 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2312 0x1001 | ((ctrl->CAS + 8) << 16));
2313 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2314 (slotrank << 24) | 0x60000);
2315 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2316
Patrick Rudolph371d2912015-10-09 13:33:25 +02002317 /* DRAM command MRS
2318 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002319 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2320 0x1f000);
2321 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2322 0xc01 | (ctrl->tMOD << 16));
2323 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2324 (slotrank << 24) | 0x360000);
2325 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2326 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2327 0xc0001);
2328
2329 wait_428c(channel);
2330 }
2331
2332 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2333 ctrl->timings[channel][slotrank].lanes[lane].falling =
2334 48;
2335 ctrl->timings[channel][slotrank].lanes[lane].rising =
2336 48;
2337 }
2338
2339 program_timings(ctrl, channel);
2340
2341 FOR_ALL_POPULATED_RANKS {
2342 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002343 /* DRAM command MRS
2344 * write MR3 MPR enable
2345 * in this mode only RD and RDA are allowed
2346 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002347 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2348 0x1f000);
2349 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2350 0xc01 | (ctrl->tMOD << 16));
2351 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2352 (slotrank << 24) | 0x360004);
2353 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2354
Patrick Rudolph371d2912015-10-09 13:33:25 +02002355 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002356 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2357 0x1f105);
2358 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2359 0x4041003);
2360 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2361 (slotrank << 24) | 0);
2362 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2363
Patrick Rudolph371d2912015-10-09 13:33:25 +02002364 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002365 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2366 0x1f105);
2367 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2368 0x1001 | ((ctrl->CAS + 8) << 16));
2369 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2370 (slotrank << 24) | 0x60000);
2371 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2372
Patrick Rudolph371d2912015-10-09 13:33:25 +02002373 /* DRAM command MRS
2374 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002375 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2376 0x1f000);
2377 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2378 0xc01 | (ctrl->tMOD << 16));
2379
2380 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2381 (slotrank << 24) | 0x360000);
2382 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2383
2384 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2385 0xc0001);
2386 wait_428c(channel);
2387 }
2388 }
2389}
2390
2391static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
2392{
Patrick Rudolph371d2912015-10-09 13:33:25 +02002393 /* enable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002394 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002395 0x80 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002396
2397 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002398 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002399 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207);
2400 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2401 0x8000c01 | ((ctrl->CWL + ctrl->tWLO) << 16));
2402 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2403 8 | (slotrank << 24));
2404 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2405
Patrick Rudolph371d2912015-10-09 13:33:25 +02002406 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002407 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107);
2408 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2409 0x4000c01 | ((ctrl->CAS + 38) << 16));
2410 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2411 (slotrank << 24) | 4);
2412 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2413
2414 write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001);
2415 wait_428c(channel);
2416
Patrick Rudolph371d2912015-10-09 13:33:25 +02002417 /* disable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002418 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002419 0x1080 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002420}
2421
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002422static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002423{
2424 int timB;
2425 int statistics[NUM_LANES][128];
2426 int lane;
2427
2428 write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2));
2429
2430 for (timB = 0; timB < 128; timB++) {
2431 FOR_ALL_LANES {
2432 ctrl->timings[channel][slotrank].lanes[lane].timB = timB;
2433 }
2434 program_timings(ctrl, channel);
2435
2436 test_timB(ctrl, channel, slotrank);
2437
2438 FOR_ALL_LANES {
2439 statistics[lane][timB] =
2440 !((read32
2441 (DEFAULT_MCHBAR + lane_registers[lane] +
2442 channel * 0x100 + 4 + ((timB / 32) & 1) * 4)
2443 >> (timB % 32)) & 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002444 printram("Bstat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002445 channel, slotrank, lane, timB,
2446 statistics[lane][timB]);
2447 }
2448 }
2449 FOR_ALL_LANES {
2450 struct run rn = get_longest_zero_run(statistics[lane], 128);
Patrick Rudolphd912f1d2016-02-15 20:07:42 +01002451 /* timC is a direct function of timB's 6 LSBs.
2452 * Some tests increments the value of timB by a small value,
2453 * which might cause the 6bit value to overflow, if it's close
2454 * to 0x3F. Increment the value by a small offset if it's likely
2455 * to overflow, to make sure it won't overflow while running
2456 * tests and bricks the system due to a non matching timC.
2457 *
2458 * TODO: find out why some tests (edge write discovery)
2459 * increment timB. */
2460 if ((rn.start & 0x3F) == 0x3E)
2461 rn.start += 2;
2462 else if ((rn.start & 0x3F) == 0x3F)
2463 rn.start += 1;
Vladimir Serbinenko3141eac2016-01-29 19:42:02 +01002464 ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002465 if (rn.all) {
2466 printk(BIOS_EMERG, "timB discovery failed: %d, %d, %d\n",
2467 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002468 return MAKE_ERR;
2469 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002470 printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002471 lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
2472 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002473 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002474}
2475
2476static int get_timB_high_adjust(u64 val)
2477{
2478 int i;
2479
2480 /* good */
2481 if (val == 0xffffffffffffffffLL)
2482 return 0;
2483
2484 if (val >= 0xf000000000000000LL) {
2485 /* needs negative adjustment */
2486 for (i = 0; i < 8; i++)
2487 if (val << (8 * (7 - i) + 4))
2488 return -i;
2489 } else {
2490 /* needs positive adjustment */
2491 for (i = 0; i < 8; i++)
2492 if (val >> (8 * (7 - i) + 4))
2493 return i;
2494 }
2495 return 8;
2496}
2497
2498static void adjust_high_timB(ramctr_timing * ctrl)
2499{
2500 int channel, slotrank, lane, old;
2501 write32(DEFAULT_MCHBAR + 0x3400, 0x200);
2502 FOR_ALL_POPULATED_CHANNELS {
2503 fill_pattern1(ctrl, channel);
2504 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 1);
2505 }
2506 FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
2507
2508 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001);
2509
2510 wait_428c(channel);
2511
Patrick Rudolph371d2912015-10-09 13:33:25 +02002512 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002513 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2514 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2515 0xc01 | (ctrl->tRCD << 16));
2516 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2517 (slotrank << 24) | 0x60000);
2518 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2519
Patrick Rudolph371d2912015-10-09 13:33:25 +02002520 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002521 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2522 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01);
2523 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2524 (slotrank << 24) | 0x8);
2525 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2526
Patrick Rudolph371d2912015-10-09 13:33:25 +02002527 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002528 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2529 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003);
2530 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2531 (slotrank << 24));
2532 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2);
2533
Patrick Rudolph371d2912015-10-09 13:33:25 +02002534 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002535 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2536 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2537 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2538 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2539 (slotrank << 24) | 0x8);
2540 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2541
2542 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2543
2544 wait_428c(channel);
2545
Patrick Rudolph371d2912015-10-09 13:33:25 +02002546 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002547 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2548 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2549 0xc01 | ((ctrl->tRP) << 16));
2550 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2551 (slotrank << 24) | 0x60400);
2552 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2553
Patrick Rudolph371d2912015-10-09 13:33:25 +02002554 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002555 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2556 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2557 0xc01 | ((ctrl->tRCD) << 16));
2558 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2559 (slotrank << 24) | 0x60000);
2560 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2561
Patrick Rudolph371d2912015-10-09 13:33:25 +02002562 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002563 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105);
2564 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2565 0x4000c01 |
2566 ((ctrl->tRP +
2567 ctrl->timings[channel][slotrank].val_4024 +
2568 ctrl->timings[channel][slotrank].val_4028) << 16));
2569 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2570 (slotrank << 24) | 0x60008);
2571 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2572
2573 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
2574 wait_428c(channel);
2575 FOR_ALL_LANES {
2576 u64 res =
2577 read32(DEFAULT_MCHBAR + lane_registers[lane] +
2578 0x100 * channel + 4);
2579 res |=
2580 ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] +
2581 0x100 * channel + 8)) << 32;
2582 old = ctrl->timings[channel][slotrank].lanes[lane].timB;
2583 ctrl->timings[channel][slotrank].lanes[lane].timB +=
2584 get_timB_high_adjust(res) * 64;
2585
Patrick Rudolpha649a542016-01-17 18:32:06 +01002586 printram("High adjust %d:%016llx\n", lane, res);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002587 printram("Bval+: %d, %d, %d, %x -> %x\n", channel,
2588 slotrank, lane, old,
2589 ctrl->timings[channel][slotrank].lanes[lane].
2590 timB);
2591 }
2592 }
2593 write32(DEFAULT_MCHBAR + 0x3400, 0);
2594}
2595
2596static void write_op(ramctr_timing * ctrl, int channel)
2597{
2598 int slotrank;
2599
2600 wait_428c(channel);
2601
2602 /* choose an existing rank. */
2603 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2604
Patrick Rudolph371d2912015-10-09 13:33:25 +02002605 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002606 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2607 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2608
2609 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2610 (slotrank << 24) | 0x60000);
2611
2612 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2613
2614 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2615 wait_428c(channel);
2616}
2617
Patrick Rudolph371d2912015-10-09 13:33:25 +02002618/* Compensate the skew between CMD/ADDR/CLK and DQ/DQS lanes.
2619 * DDR3 adopted the fly-by topology. The data and strobes signals reach
2620 * the chips at different times with respect to command, address and
2621 * clock signals.
2622 * By delaying either all DQ/DQs or all CMD/ADDR/CLK signals, a full phase
2623 * shift can be introduced.
2624 * It is assumed that the CLK/ADDR/CMD signals have the same routing delay.
2625 *
2626 * To find the required phase shift the DRAM is placed in "write leveling" mode.
2627 * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
2628 * sampled value on the data lanes (DQs).
2629 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002630static int write_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002631{
2632 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002633 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002634
2635 FOR_ALL_POPULATED_CHANNELS
2636 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
2637 read32(DEFAULT_MCHBAR + 0x4008 +
2638 0x400 * channel) | 0x8000000);
2639
2640 FOR_ALL_POPULATED_CHANNELS {
2641 write_op(ctrl, channel);
2642 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2643 read32(DEFAULT_MCHBAR + 0x4020 +
2644 0x400 * channel) | 0x200000);
2645 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002646
2647 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002648 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2649 FOR_ALL_POPULATED_CHANNELS {
2650 write_op(ctrl, channel);
2651 }
2652
Patrick Rudolph371d2912015-10-09 13:33:25 +02002653 /* enable write leveling on all ranks
2654 * disable all DQ outputs
2655 * only NOP is allowed in this mode */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002656 FOR_ALL_CHANNELS
2657 FOR_ALL_POPULATED_RANKS
2658 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002659 make_mr1(ctrl, slotrank, channel) | 0x1080);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002660
2661 write32(DEFAULT_MCHBAR + 0x3400, 0x108052);
2662
Patrick Rudolph9b515682015-10-09 13:43:51 +02002663 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002664
Patrick Rudolph371d2912015-10-09 13:33:25 +02002665 /* set any valid value for timB, it gets corrected later */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002666 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2667 err = discover_timB(ctrl, channel, slotrank);
2668 if (err)
2669 return err;
2670 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002671
Patrick Rudolph371d2912015-10-09 13:33:25 +02002672 /* disable write leveling on all ranks */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002673 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2674 write_mrreg(ctrl, channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002675 slotrank, 1, make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002676
2677 write32(DEFAULT_MCHBAR + 0x3400, 0);
2678
2679 FOR_ALL_POPULATED_CHANNELS
2680 wait_428c(channel);
2681
Patrick Rudolph371d2912015-10-09 13:33:25 +02002682 /* refresh enable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002683 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8);
2684
2685 FOR_ALL_POPULATED_CHANNELS {
2686 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2687 ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 +
2688 0x400 * channel));
2689 read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel);
2690 wait_428c(channel);
2691
Patrick Rudolph371d2912015-10-09 13:33:25 +02002692 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002693 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2694 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
2695 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000);
2696 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2697
2698 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2699 wait_428c(channel);
2700 }
2701
Patrick Rudolph9b515682015-10-09 13:43:51 +02002702 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002703
2704 printram("CPE\n");
2705 precharge(ctrl);
2706 printram("CPF\n");
2707
2708 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2709 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2710 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2711 0);
2712 }
2713
2714 FOR_ALL_POPULATED_CHANNELS {
2715 fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555);
2716 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
2717 }
2718
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002719 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2720 err = discover_timC(ctrl, channel, slotrank);
2721 if (err)
2722 return err;
2723 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002724
2725 FOR_ALL_POPULATED_CHANNELS
2726 program_timings(ctrl, channel);
2727
Patrick Rudolph371d2912015-10-09 13:33:25 +02002728 /* measure and adjust timB timings */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002729 adjust_high_timB(ctrl);
2730
2731 FOR_ALL_POPULATED_CHANNELS
2732 program_timings(ctrl, channel);
2733
2734 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2735 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2736 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2737 0);
2738 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002739 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002740}
2741
2742static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
2743{
2744 struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank];
2745 int timC_delta;
2746 int lanes_ok = 0;
2747 int ctr = 0;
2748 int lane;
2749
2750 for (timC_delta = -5; timC_delta <= 5; timC_delta++) {
2751 FOR_ALL_LANES {
2752 ctrl->timings[channel][slotrank].lanes[lane].timC =
2753 saved_rt.lanes[lane].timC + timC_delta;
2754 }
2755 program_timings(ctrl, channel);
2756 FOR_ALL_LANES {
2757 write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0);
2758 }
2759
2760 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2761
2762 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002763 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002764 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2765 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2766 ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10)
2767 | 8 | (ctrl->tRCD << 16));
2768
2769 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2770 (slotrank << 24) | ctr | 0x60000);
2771
2772 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002773 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002774 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
2775 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2776 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16));
2777 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2778 (slotrank << 24));
2779 write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd);
2780 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42);
2781
Patrick Rudolph371d2912015-10-09 13:33:25 +02002782 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002783 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2784 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2785 0x4001020 | (max(ctrl->tRTP, 8) << 16));
2786 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2787 (slotrank << 24));
2788 write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd);
2789 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42);
2790
Patrick Rudolph371d2912015-10-09 13:33:25 +02002791 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002792 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2793 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001);
2794 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2795 (slotrank << 24) | 0x60400);
2796 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2797
2798 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2799 wait_428c(channel);
2800 FOR_ALL_LANES {
2801 u32 r32 =
2802 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2803 0x400 * channel);
2804
2805 if (r32 == 0)
2806 lanes_ok |= 1 << lane;
2807 }
2808 ctr++;
2809 if (lanes_ok == ((1 << NUM_LANES) - 1))
2810 break;
2811 }
2812
2813 ctrl->timings[channel][slotrank] = saved_rt;
2814
2815 printram("3lanes: %x\n", lanes_ok);
2816 return lanes_ok != ((1 << NUM_LANES) - 1);
2817}
2818
2819#include "raminit_patterns.h"
2820
2821static void fill_pattern5(ramctr_timing * ctrl, int channel, int patno)
2822{
2823 unsigned i, j;
2824 unsigned channel_offset =
2825 get_precedening_channels(ctrl, channel) * 0x40;
2826 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2827
2828 if (patno) {
2829 u8 base8 = 0x80 >> ((patno - 1) % 8);
2830 u32 base = base8 | (base8 << 8) | (base8 << 16) | (base8 << 24);
2831 for (i = 0; i < 32; i++) {
2832 for (j = 0; j < 16; j++) {
2833 u32 val = use_base[patno - 1][i] & (1 << (j / 2)) ? base : 0;
2834 if (invert[patno - 1][i] & (1 << (j / 2)))
2835 val = ~val;
2836 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2837 j * 4), val);
2838 }
2839 }
2840
2841 } else {
2842 for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) {
2843 for (j = 0; j < 16; j++)
2844 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2845 j * 4), pattern[i][j]);
2846 }
2847 sfence();
2848 }
2849}
2850
2851static void reprogram_320c(ramctr_timing * ctrl)
2852{
2853 int channel, slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002854
2855 FOR_ALL_POPULATED_CHANNELS {
2856 wait_428c(channel);
2857
2858 /* choose an existing rank. */
2859 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2860
Patrick Rudolph371d2912015-10-09 13:33:25 +02002861 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002862 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2863 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2864
2865 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2866 (slotrank << 24) | 0x60000);
2867
2868 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2869
2870 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2871 wait_428c(channel);
2872 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2873 read32(DEFAULT_MCHBAR + 0x4020 +
2874 0x400 * channel) | 0x200000);
2875 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002876
2877 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002878 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2879 FOR_ALL_POPULATED_CHANNELS {
2880 wait_428c(channel);
2881
2882 /* choose an existing rank. */
2883 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2884
Patrick Rudolph371d2912015-10-09 13:33:25 +02002885 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002886 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2887 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2888
2889 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2890 (slotrank << 24) | 0x60000);
2891
2892 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2893
2894 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2895 wait_428c(channel);
2896 }
2897
2898 /* jedec reset */
2899 dram_jedecreset(ctrl);
2900 /* mrs commands. */
2901 dram_mrscommands(ctrl);
2902
Patrick Rudolph9b515682015-10-09 13:43:51 +02002903 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002904}
2905
2906#define MIN_C320C_LEN 13
2907
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002908static int try_cmd_stretch(ramctr_timing *ctrl, int cmd_stretch)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002909{
2910 struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
2911 int channel, slotrank;
2912 int c320c;
2913 int stat[NUM_SLOTRANKS][256];
2914
2915 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2916 saved_timings[channel][slotrank] = ctrl->timings[channel][slotrank];
2917 }
2918
2919 FOR_ALL_POPULATED_CHANNELS {
2920 ctrl->cmd_stretch[channel] = cmd_stretch;
2921 }
2922
2923 FOR_ALL_POPULATED_CHANNELS
2924 MCHBAR32(0x4004 + 0x400 * channel) =
2925 ctrl->tRRD
2926 | (ctrl->tRTP << 4)
2927 | (ctrl->tCKE << 8)
2928 | (ctrl->tWTR << 12)
2929 | (ctrl->tFAW << 16)
2930 | (ctrl->tWR << 24)
2931 | (ctrl->cmd_stretch[channel] << 30);
2932
2933
2934 FOR_ALL_CHANNELS {
2935 int delta = 0;
2936 if (ctrl->cmd_stretch[channel] == 2)
2937 delta = 2;
2938 else if (ctrl->cmd_stretch[channel] == 0)
2939 delta = 4;
2940
2941 FOR_ALL_POPULATED_RANKS {
2942 ctrl->timings[channel][slotrank].val_4024 -= delta;
2943 }
2944 }
2945
2946 FOR_ALL_POPULATED_CHANNELS {
2947 for (c320c = -127; c320c <= 127; c320c++) {
2948 FOR_ALL_POPULATED_RANKS {
2949 ctrl->timings[channel][slotrank].val_320c = c320c;
2950 }
2951 program_timings(ctrl, channel);
2952 reprogram_320c(ctrl);
2953 FOR_ALL_POPULATED_RANKS {
2954 stat[slotrank][c320c + 127] =
2955 test_320c(ctrl, channel, slotrank);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002956 printram("3stat: %d, %d, %d: %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002957 channel, slotrank, c320c,
2958 stat[slotrank][c320c + 127]);
2959 }
2960 }
2961 FOR_ALL_POPULATED_RANKS {
2962 struct run rn =
2963 get_longest_zero_run(stat[slotrank], 255);
2964 ctrl->timings[channel][slotrank].val_320c =
2965 rn.middle - 127;
2966 printram("3val: %d, %d: %d\n", channel,
2967 slotrank,
2968 ctrl->timings[channel][slotrank].val_320c);
2969 if (rn.all || rn.length < MIN_C320C_LEN) {
2970 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2971 ctrl->timings[channel][slotrank] = saved_timings[channel][slotrank];
2972 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002973 return MAKE_ERR;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002974 }
2975 }
2976 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002977 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002978}
2979
Patrick Rudolph371d2912015-10-09 13:33:25 +02002980/* Adjust CMD phase shift and try multiple command rates.
2981 * A command rate of 2T doubles the time needed for address and
2982 * command decode. */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002983static int command_training(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002984{
2985 int channel;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002986 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002987
2988 FOR_ALL_POPULATED_CHANNELS {
2989 fill_pattern5(ctrl, channel, 0);
2990 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2991 }
2992
2993 /* try command rate 1T and 2T */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002994 err = try_cmd_stretch(ctrl, 0);
2995 if (err) {
2996 err = try_cmd_stretch(ctrl, 2);
2997 if (err) {
2998 printk(BIOS_EMERG, "c320c discovery failed\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002999 return err;
3000 }
3001 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003002
3003 FOR_ALL_POPULATED_CHANNELS {
3004 program_timings(ctrl, channel);
3005 }
3006
3007 reprogram_320c(ctrl);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003008 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003009}
3010
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003011static int discover_edges_real(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003012 int *edges)
3013{
3014 int edge;
3015 int statistics[NUM_LANES][MAX_EDGE_TIMING + 1];
3016 int lane;
3017
3018 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3019 FOR_ALL_LANES {
3020 ctrl->timings[channel][slotrank].lanes[lane].rising =
3021 edge;
3022 ctrl->timings[channel][slotrank].lanes[lane].falling =
3023 edge;
3024 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003025 program_timings(ctrl, channel);
3026
3027 FOR_ALL_LANES {
3028 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3029 4 * lane, 0);
3030 read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane +
3031 0x4140);
3032 }
3033
3034 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003035 /* DRAM command MRS
3036 * write MR3 MPR enable
3037 * in this mode only RD and RDA are allowed
3038 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003039 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
3040 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3041 (0xc01 | (ctrl->tMOD << 16)));
3042 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3043 (slotrank << 24) | 0x360004);
3044 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3045
Patrick Rudolph371d2912015-10-09 13:33:25 +02003046 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003047 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
3048 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4);
3049 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3050 (slotrank << 24));
3051 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3052
Patrick Rudolph371d2912015-10-09 13:33:25 +02003053 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003054 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
3055 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3056 0x1001 | ((ctrl->CAS + 8) << 16));
3057 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3058 (slotrank << 24) | 0x60000);
3059 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3060
Patrick Rudolph371d2912015-10-09 13:33:25 +02003061 /* DRAM command MRS
3062 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003063 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
3064 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3065 (0xc01 | (ctrl->tMOD << 16)));
3066 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3067 (slotrank << 24) | 0x360000);
3068 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3069
3070 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
3071
3072 wait_428c(channel);
3073
3074 FOR_ALL_LANES {
3075 statistics[lane][edge] =
3076 read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3077 lane * 4);
3078 }
3079 }
3080 FOR_ALL_LANES {
3081 struct run rn =
3082 get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
3083 edges[lane] = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003084 if (rn.all) {
3085 printk(BIOS_EMERG, "edge discovery failed: %d, %d, %d\n",
3086 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003087 return MAKE_ERR;
3088 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003089 printram("eval %d, %d, %d: %02x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003090 lane, edges[lane]);
3091 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003092 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003093}
3094
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003095static int discover_edges(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003096{
3097 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3098 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3099 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003100 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003101
3102 write32(DEFAULT_MCHBAR + 0x3400, 0);
3103
Patrick Rudolph9b515682015-10-09 13:43:51 +02003104 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003105
3106 FOR_ALL_POPULATED_CHANNELS FOR_ALL_LANES {
3107 write32(DEFAULT_MCHBAR + 4 * lane +
3108 0x400 * channel + 0x4080, 0);
3109 }
3110
3111 FOR_ALL_POPULATED_CHANNELS {
3112 fill_pattern0(ctrl, channel, 0, 0);
3113 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3114 FOR_ALL_LANES {
3115 read32(DEFAULT_MCHBAR + 0x400 * channel +
3116 lane * 4 + 0x4140);
3117 }
3118
3119 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3120 ctrl->timings[channel][slotrank].lanes[lane].falling =
3121 16;
3122 ctrl->timings[channel][slotrank].lanes[lane].rising =
3123 16;
3124 }
3125
3126 program_timings(ctrl, channel);
3127
3128 FOR_ALL_POPULATED_RANKS {
3129 wait_428c(channel);
3130
Patrick Rudolph371d2912015-10-09 13:33:25 +02003131 /* DRAM command MRS
3132 * MR3 enable MPR
3133 * write MR3 MPR enable
3134 * in this mode only RD and RDA are allowed
3135 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003136 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3137 0x1f000);
3138 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3139 0xc01 | (ctrl->tMOD << 16));
3140 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3141 (slotrank << 24) | 0x360004);
3142 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3143
Patrick Rudolph371d2912015-10-09 13:33:25 +02003144 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003145 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3146 0x1f105);
3147 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3148 0x4041003);
3149 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3150 (slotrank << 24) | 0);
3151 write32(DEFAULT_MCHBAR + 0x4214 + 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 + 0x4228 + 0x400 * channel,
3155 0x1f105);
3156 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3157 0x1001 | ((ctrl->CAS + 8) << 16));
3158 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3159 (slotrank << 24) | 0x60000);
3160 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3161
Patrick Rudolph371d2912015-10-09 13:33:25 +02003162 /* DRAM command MRS
3163 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003164 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3165 0x1f000);
3166 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3167 0xc01 | (ctrl->tMOD << 16));
3168 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3169 (slotrank << 24) | 0x360000);
3170 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3171 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3172 0xc0001);
3173
3174 wait_428c(channel);
3175 }
3176
Patrick Rudolph371d2912015-10-09 13:33:25 +02003177 /* XXX: check any measured value ? */
3178
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003179 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3180 ctrl->timings[channel][slotrank].lanes[lane].falling =
3181 48;
3182 ctrl->timings[channel][slotrank].lanes[lane].rising =
3183 48;
3184 }
3185
3186 program_timings(ctrl, channel);
3187
3188 FOR_ALL_POPULATED_RANKS {
3189 wait_428c(channel);
3190
Patrick Rudolph371d2912015-10-09 13:33:25 +02003191 /* DRAM command MRS
3192 * MR3 enable MPR
3193 * write MR3 MPR enable
3194 * in this mode only RD and RDA are allowed
3195 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003196 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3197 0x1f000);
3198 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3199 0xc01 | (ctrl->tMOD << 16));
3200 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3201 (slotrank << 24) | 0x360004);
3202 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3203
Patrick Rudolph371d2912015-10-09 13:33:25 +02003204 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003205 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3206 0x1f105);
3207 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3208 0x4041003);
3209 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3210 (slotrank << 24) | 0);
3211 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3212
Patrick Rudolph371d2912015-10-09 13:33:25 +02003213 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003214 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3215 0x1f105);
3216 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3217 0x1001 | ((ctrl->CAS + 8) << 16));
3218 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3219 (slotrank << 24) | 0x60000);
3220 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3221
Patrick Rudolph371d2912015-10-09 13:33:25 +02003222 /* DRAM command MRS
3223 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003224 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3225 0x1f000);
3226 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3227 0xc01 | (ctrl->tMOD << 16));
3228 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3229 (slotrank << 24) | 0x360000);
3230 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3231
3232 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3233 0xc0001);
3234 wait_428c(channel);
3235 }
3236
Patrick Rudolph371d2912015-10-09 13:33:25 +02003237 /* XXX: check any measured value ? */
3238
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003239 FOR_ALL_LANES {
3240 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel +
3241 lane * 4,
3242 ~read32(DEFAULT_MCHBAR + 0x4040 +
3243 0x400 * channel + lane * 4) & 0xff);
3244 }
3245
3246 fill_pattern0(ctrl, channel, 0, 0xffffffff);
3247 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3248 }
3249
3250 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3251 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003252 printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003253
3254 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003255 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003256 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003257 if (err)
3258 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003259 }
3260
3261 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003262 printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003263
3264 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003265 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003266 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003267 if (err)
3268 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003269 }
3270
3271 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3272
3273 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3274 ctrl->timings[channel][slotrank].lanes[lane].falling =
3275 falling_edges[channel][slotrank][lane];
3276 ctrl->timings[channel][slotrank].lanes[lane].rising =
3277 rising_edges[channel][slotrank][lane];
3278 }
3279
3280 FOR_ALL_POPULATED_CHANNELS {
3281 program_timings(ctrl, channel);
3282 }
3283
3284 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3285 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3286 0);
3287 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003288 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003289}
3290
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003291static int discover_edges_write_real(ramctr_timing *ctrl, int channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003292 int slotrank, int *edges)
3293{
3294 int edge;
3295 u32 raw_statistics[MAX_EDGE_TIMING + 1];
3296 int statistics[MAX_EDGE_TIMING + 1];
3297 const int reg3000b24[] = { 0, 0xc, 0x2c };
3298 int lane, i;
3299 int lower[NUM_LANES];
3300 int upper[NUM_LANES];
3301 int pat;
3302
3303 FOR_ALL_LANES {
3304 lower[lane] = 0;
3305 upper[lane] = MAX_EDGE_TIMING;
3306 }
3307
3308 for (i = 0; i < 3; i++) {
3309 write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel,
3310 reg3000b24[i] << 24);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003311 printram("[%x] = 0x%08x\n",
3312 0x3000 + 0x100 * channel, reg3000b24[i] << 24);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003313 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3314 fill_pattern5(ctrl, channel, pat);
3315 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003316 printram("using pattern %d\n", pat);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003317 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3318 FOR_ALL_LANES {
3319 ctrl->timings[channel][slotrank].lanes[lane].
3320 rising = edge;
3321 ctrl->timings[channel][slotrank].lanes[lane].
3322 falling = edge;
3323 }
3324 program_timings(ctrl, channel);
3325
3326 FOR_ALL_LANES {
3327 write32(DEFAULT_MCHBAR + 0x4340 +
3328 0x400 * channel + 4 * lane, 0);
3329 read32(DEFAULT_MCHBAR + 0x400 * channel +
3330 4 * lane + 0x4140);
3331 }
3332 wait_428c(channel);
3333
Patrick Rudolph371d2912015-10-09 13:33:25 +02003334 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003335 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3336 0x1f006);
3337 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3338 0x4 | (ctrl->tRCD << 16)
3339 | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) <<
3340 10));
3341 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3342 (slotrank << 24) | 0x60000);
3343 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel,
3344 0x240);
3345
Patrick Rudolph371d2912015-10-09 13:33:25 +02003346 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003347 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3348 0x1f201);
3349 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3350 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) <<
3351 16));
3352 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3353 (slotrank << 24));
3354 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel,
3355 0x242);
3356
Patrick Rudolph371d2912015-10-09 13:33:25 +02003357 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003358 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3359 0x1f105);
3360 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3361 0x4005020 | (max(ctrl->tRTP, 8) << 16));
3362 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3363 (slotrank << 24));
3364 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel,
3365 0x242);
3366
Patrick Rudolph371d2912015-10-09 13:33:25 +02003367 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003368 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3369 0x1f002);
3370 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3371 0xc01 | (ctrl->tRP << 16));
3372 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3373 (slotrank << 24) | 0x60400);
3374 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3375
3376 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3377 0xc0001);
3378 wait_428c(channel);
3379 FOR_ALL_LANES {
3380 read32(DEFAULT_MCHBAR + 0x4340 +
3381 0x400 * channel + lane * 4);
3382 }
3383
3384 raw_statistics[edge] =
3385 MCHBAR32(0x436c + 0x400 * channel);
3386 }
3387 FOR_ALL_LANES {
3388 struct run rn;
3389 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++)
3390 statistics[edge] =
3391 ! !(raw_statistics[edge] & (1 << lane));
3392 rn = get_longest_zero_run(statistics,
3393 MAX_EDGE_TIMING + 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003394 printram("edges: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003395 channel, slotrank, i, rn.start, rn.middle,
3396 rn.end, rn.start + ctrl->edge_offset[i],
3397 rn.end - ctrl->edge_offset[i]);
3398 lower[lane] =
3399 max(rn.start + ctrl->edge_offset[i], lower[lane]);
3400 upper[lane] =
3401 min(rn.end - ctrl->edge_offset[i], upper[lane]);
3402 edges[lane] = (lower[lane] + upper[lane]) / 2;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003403 if (rn.all || (lower[lane] > upper[lane])) {
3404 printk(BIOS_EMERG, "edge write discovery failed: %d, %d, %d\n",
3405 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003406 return MAKE_ERR;
3407 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003408 }
3409 }
3410 }
3411
3412 write32(DEFAULT_MCHBAR + 0x3000, 0);
3413 printram("CPA\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003414 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003415}
3416
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003417static int discover_edges_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003418{
3419 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3420 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3421 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003422 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003423
3424 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3425 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003426 printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003427
3428 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003429 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003430 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003431 if (err)
3432 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003433 }
3434
3435 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003436 printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003437
3438 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003439 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003440 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003441 if (err)
3442 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003443 }
3444
3445 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3446
3447 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3448 ctrl->timings[channel][slotrank].lanes[lane].falling =
3449 falling_edges[channel][slotrank][lane];
3450 ctrl->timings[channel][slotrank].lanes[lane].rising =
3451 rising_edges[channel][slotrank][lane];
3452 }
3453
3454 FOR_ALL_POPULATED_CHANNELS
3455 program_timings(ctrl, channel);
3456
3457 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3458 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3459 0);
3460 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003461 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003462}
3463
3464static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
3465{
3466 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003467 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003468 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
3469 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3470 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD)
3471 << 10) | (ctrl->tRCD << 16) | 4);
3472 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3473 (slotrank << 24) | 0x60000);
3474 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
3475
Patrick Rudolph371d2912015-10-09 13:33:25 +02003476 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003477 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
3478 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3479 0x80011e0 |
3480 ((ctrl->tWTR + ctrl->CWL + 8) << 16));
3481 write32(DEFAULT_MCHBAR + 0x4204 +
3482 0x400 * channel, (slotrank << 24));
3483 write32(DEFAULT_MCHBAR + 0x4214 +
3484 0x400 * channel, 0x242);
3485
Patrick Rudolph371d2912015-10-09 13:33:25 +02003486 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003487 write32(DEFAULT_MCHBAR + 0x4228 +
3488 0x400 * channel, 0x1f105);
3489 write32(DEFAULT_MCHBAR + 0x4238 +
3490 0x400 * channel,
3491 0x40011e0 | (max(ctrl->tRTP, 8) << 16));
3492 write32(DEFAULT_MCHBAR + 0x4208 +
3493 0x400 * channel, (slotrank << 24));
3494 write32(DEFAULT_MCHBAR + 0x4218 +
3495 0x400 * channel, 0x242);
3496
Patrick Rudolph371d2912015-10-09 13:33:25 +02003497 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003498 write32(DEFAULT_MCHBAR + 0x422c +
3499 0x400 * channel, 0x1f002);
3500 write32(DEFAULT_MCHBAR + 0x423c +
3501 0x400 * channel,
3502 0x1001 | (ctrl->tRP << 16));
3503 write32(DEFAULT_MCHBAR + 0x420c +
3504 0x400 * channel,
3505 (slotrank << 24) | 0x60400);
3506 write32(DEFAULT_MCHBAR + 0x421c +
3507 0x400 * channel, 0);
3508
3509 write32(DEFAULT_MCHBAR + 0x4284 +
3510 0x400 * channel, 0xc0001);
3511 wait_428c(channel);
3512}
3513
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003514static int discover_timC_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003515{
3516 const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
3517 int i, pat;
3518
3519 int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3520 int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3521 int channel, slotrank, lane;
3522
3523 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3524 lower[channel][slotrank][lane] = 0;
3525 upper[channel][slotrank][lane] = MAX_TIMC;
3526 }
3527
3528 write32(DEFAULT_MCHBAR + 0x4ea8, 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003529 printram("discover timC write:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003530
3531 for (i = 0; i < 3; i++)
3532 FOR_ALL_POPULATED_CHANNELS {
3533 write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100),
3534 (rege3c_b24[i] << 24)
3535 | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100))
3536 & ~0x3f000000));
3537 udelay(2);
3538 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3539 FOR_ALL_POPULATED_RANKS {
3540 int timC;
3541 u32 raw_statistics[MAX_TIMC + 1];
3542 int statistics[MAX_TIMC + 1];
3543
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003544 /* Make sure rn.start < rn.end */
3545 statistics[MAX_TIMC] = 1;
3546
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003547 fill_pattern5(ctrl, channel, pat);
3548 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003549 for (timC = 0; timC < MAX_TIMC; timC++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003550 FOR_ALL_LANES
3551 ctrl->timings[channel][slotrank].lanes[lane].timC = timC;
3552 program_timings(ctrl, channel);
3553
3554 test_timC_write (ctrl, channel, slotrank);
3555
3556 raw_statistics[timC] =
3557 MCHBAR32(0x436c + 0x400 * channel);
3558 }
3559 FOR_ALL_LANES {
3560 struct run rn;
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003561 for (timC = 0; timC < MAX_TIMC; timC++)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003562 statistics[timC] =
3563 !!(raw_statistics[timC] &
3564 (1 << lane));
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003565
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003566 rn = get_longest_zero_run(statistics,
3567 MAX_TIMC + 1);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003568 if (rn.all) {
3569 printk(BIOS_EMERG, "timC write discovery failed: %d, %d, %d\n",
3570 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003571 return MAKE_ERR;
3572 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003573 printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003574 channel, slotrank, i, rn.start,
3575 rn.middle, rn.end,
3576 rn.start + ctrl->timC_offset[i],
3577 rn.end - ctrl->timC_offset[i]);
3578 lower[channel][slotrank][lane] =
3579 max(rn.start + ctrl->timC_offset[i],
3580 lower[channel][slotrank][lane]);
3581 upper[channel][slotrank][lane] =
3582 min(rn.end - ctrl->timC_offset[i],
3583 upper[channel][slotrank][lane]);
3584
3585 }
3586 }
3587 }
3588 }
3589
3590 FOR_ALL_CHANNELS {
3591 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3592 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3593 ~0x3f000000));
3594 udelay(2);
3595 }
3596
3597 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3598
3599 printram("CPB\n");
3600
3601 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
Patrick Rudolpha649a542016-01-17 18:32:06 +01003602 printram("timC %d, %d, %d: %x\n", channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003603 slotrank, lane,
3604 (lower[channel][slotrank][lane] +
3605 upper[channel][slotrank][lane]) / 2);
3606 ctrl->timings[channel][slotrank].lanes[lane].timC =
3607 (lower[channel][slotrank][lane] +
3608 upper[channel][slotrank][lane]) / 2;
3609 }
3610 FOR_ALL_POPULATED_CHANNELS {
3611 program_timings(ctrl, channel);
3612 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003613 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003614}
3615
3616static void normalize_training(ramctr_timing * ctrl)
3617{
3618 int channel, slotrank, lane;
3619 int mat = 0;
3620
3621 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3622 int delta;
3623 FOR_ALL_LANES mat =
3624 max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat);
3625 delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028;
3626 ctrl->timings[channel][slotrank].val_4024 += delta;
3627 ctrl->timings[channel][slotrank].val_4028 += delta;
3628 }
3629
3630 FOR_ALL_POPULATED_CHANNELS {
3631 program_timings(ctrl, channel);
3632 }
3633}
3634
3635static void write_controller_mr(ramctr_timing * ctrl)
3636{
3637 int channel, slotrank;
3638
3639 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3640 write32(DEFAULT_MCHBAR + 0x0004 + (channel << 8) +
3641 lane_registers[slotrank], make_mr0(ctrl, slotrank));
3642 write32(DEFAULT_MCHBAR + 0x0008 + (channel << 8) +
Patrick Rudolph7e513d12016-01-10 14:22:34 +01003643 lane_registers[slotrank],
3644 make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003645 }
3646}
3647
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003648static int channel_test(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003649{
3650 int channel, slotrank, lane;
3651
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003652 slotrank = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003653 FOR_ALL_POPULATED_CHANNELS
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003654 if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) {
3655 printk(BIOS_EMERG, "Mini channel test failed (1): %d\n",
3656 channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003657 return MAKE_ERR;
3658 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003659 FOR_ALL_POPULATED_CHANNELS {
3660 fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
3661
3662 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3663 }
3664
3665 for (slotrank = 0; slotrank < 4; slotrank++)
3666 FOR_ALL_CHANNELS
3667 if (ctrl->rankmap[channel] & (1 << slotrank)) {
3668 FOR_ALL_LANES {
3669 write32(DEFAULT_MCHBAR + (0x4f40 + 4 * lane), 0);
3670 write32(DEFAULT_MCHBAR + (0x4d40 + 4 * lane), 0);
3671 }
3672 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003673 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003674 write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
3675 write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10), 0x0028a004);
3676 write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
3677 0x00060000 | (slotrank << 24));
3678 write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003679 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003680 write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
3681 write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281064);
3682 write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
3683 0x00000000 | (slotrank << 24));
3684 write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003685 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003686 write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f105);
3687 write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x04281064);
3688 write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
3689 0x00000000 | (slotrank << 24));
3690 write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003691 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003692 write32(DEFAULT_MCHBAR + 0x422c + (channel << 10), 0x0001f002);
3693 write32(DEFAULT_MCHBAR + 0x423c + (channel << 10), 0x00280c01);
3694 write32(DEFAULT_MCHBAR + 0x420c + (channel << 10),
3695 0x00060400 | (slotrank << 24));
3696 write32(DEFAULT_MCHBAR + 0x421c + (channel << 10), 0x00000240);
3697 write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
3698 wait_428c(channel);
3699 FOR_ALL_LANES
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003700 if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) {
3701 printk(BIOS_EMERG, "Mini channel test failed (2): %d, %d, %d\n",
3702 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003703 return MAKE_ERR;
3704 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003705 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003706 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003707}
3708
3709static void set_scrambling_seed(ramctr_timing * ctrl)
3710{
3711 int channel;
3712
3713 /* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
3714 I don't think so. */
3715 static u32 seeds[NUM_CHANNELS][3] = {
3716 {0x00009a36, 0xbafcfdcf, 0x46d1ab68},
3717 {0x00028bfa, 0x53fe4b49, 0x19ed5483}
3718 };
3719 FOR_ALL_POPULATED_CHANNELS {
3720 MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
3721 write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
3722 write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
3723 write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
3724 }
3725}
3726
3727static void set_4f8c(void)
3728{
3729 struct cpuid_result cpures;
3730 u32 cpu;
3731
3732 cpures = cpuid(0);
3733 cpu = (cpures.eax);
3734 if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) {
3735 MCHBAR32(0x4f8c) = 0x141D1519;
3736 } else {
3737 MCHBAR32(0x4f8c) = 0x551D1519;
3738 }
3739}
3740
3741static void prepare_training(ramctr_timing * ctrl)
3742{
3743 int channel;
3744
3745 FOR_ALL_POPULATED_CHANNELS {
3746 // Always drive command bus
3747 MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000;
3748 }
3749
3750 udelay(1);
3751
3752 FOR_ALL_POPULATED_CHANNELS {
3753 wait_428c(channel);
3754 }
3755}
3756
3757static void set_4008c(ramctr_timing * ctrl)
3758{
3759 int channel, slotrank;
3760 u32 reg;
3761 FOR_ALL_POPULATED_CHANNELS {
3762 u32 b20, b4_8_12;
3763 int min_320c = 10000;
3764 int max_320c = -10000;
3765
3766 FOR_ALL_POPULATED_RANKS {
3767 max_320c = max(ctrl->timings[channel][slotrank].val_320c, max_320c);
3768 min_320c = min(ctrl->timings[channel][slotrank].val_320c, min_320c);
3769 }
3770
3771 if (max_320c - min_320c > 51)
3772 b20 = 0;
3773 else
3774 b20 = ctrl->ref_card_offset[channel];
3775
3776 if (ctrl->reg_320c_range_threshold < max_320c - min_320c)
3777 b4_8_12 = 0x3330;
3778 else
3779 b4_8_12 = 0x2220;
3780
3781 reg = read32(DEFAULT_MCHBAR + 0x400c + (channel << 10));
3782 write32(DEFAULT_MCHBAR + 0x400c + (channel << 10),
3783 (reg & 0xFFF0FFFF)
3784 | (ctrl->ref_card_offset[channel] << 16)
3785 | (ctrl->ref_card_offset[channel] << 18));
3786 write32(DEFAULT_MCHBAR + 0x4008 + (channel << 10),
3787 0x0a000000
3788 | (b20 << 20)
3789 | ((ctrl->ref_card_offset[channel] + 2) << 16)
3790 | b4_8_12);
3791 }
3792}
3793
3794static void set_42a0(ramctr_timing * ctrl)
3795{
3796 int channel;
3797 FOR_ALL_POPULATED_CHANNELS {
3798 write32(DEFAULT_MCHBAR + (0x42a0 + 0x400 * channel),
3799 0x00001000 | ctrl->rankmap[channel]);
3800 MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK
3801 }
3802}
3803
3804static int encode_5d10(int ns)
3805{
3806 return (ns + 499) / 500;
3807}
3808
3809/* FIXME: values in this function should be hardware revision-dependent. */
3810static void final_registers(ramctr_timing * ctrl)
3811{
3812 int channel;
3813 int t1_cycles = 0, t1_ns = 0, t2_ns;
3814 int t3_ns;
3815 u32 r32;
3816
3817 write32(DEFAULT_MCHBAR + 0x4cd4, 0x00000046);
3818
3819 write32(DEFAULT_MCHBAR + 0x400c, (read32(DEFAULT_MCHBAR + 0x400c) & 0xFFFFCFFF) | 0x1000); // OK
3820 write32(DEFAULT_MCHBAR + 0x440c, (read32(DEFAULT_MCHBAR + 0x440c) & 0xFFFFCFFF) | 0x1000); // OK
3821 write32(DEFAULT_MCHBAR + 0x4cb0, 0x00000740);
3822 write32(DEFAULT_MCHBAR + 0x4380, 0x00000aaa); // OK
3823 write32(DEFAULT_MCHBAR + 0x4780, 0x00000aaa); // OK
3824 write32(DEFAULT_MCHBAR + 0x4f88, 0x5f7003ff); // OK
3825 write32(DEFAULT_MCHBAR + 0x5064, 0x00073000 | ctrl->reg_5064b0); // OK
3826
3827 FOR_ALL_CHANNELS {
3828 switch (ctrl->rankmap[channel]) {
3829 /* Unpopulated channel. */
3830 case 0:
3831 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0);
3832 break;
3833 /* Only single-ranked dimms. */
3834 case 1:
3835 case 4:
3836 case 5:
3837 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x373131);
3838 break;
3839 /* Dual-ranked dimms present. */
3840 default:
3841 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x9b6ea1);
3842 break;
3843 }
3844 }
3845
3846 write32 (DEFAULT_MCHBAR + 0x5880, 0xca9171e5);
3847 write32 (DEFAULT_MCHBAR + 0x5888,
3848 (read32 (DEFAULT_MCHBAR + 0x5888) & ~0xffffff) | 0xe4d5d0);
3849 write32 (DEFAULT_MCHBAR + 0x58a8, read32 (DEFAULT_MCHBAR + 0x58a8) & ~0x1f);
3850 write32 (DEFAULT_MCHBAR + 0x4294,
3851 (read32 (DEFAULT_MCHBAR + 0x4294) & ~0x30000)
3852 | (1 << 16));
3853 write32 (DEFAULT_MCHBAR + 0x4694,
3854 (read32 (DEFAULT_MCHBAR + 0x4694) & ~0x30000)
3855 | (1 << 16));
3856
3857 MCHBAR32(0x5030) |= 1; // OK
3858 MCHBAR32(0x5030) |= 0x80; // OK
3859 MCHBAR32(0x5f18) = 0xfa; // OK
3860
3861 /* Find a populated channel. */
3862 FOR_ALL_POPULATED_CHANNELS
3863 break;
3864
3865 t1_cycles = ((read32(DEFAULT_MCHBAR + 0x4290 + channel * 0x400) >> 8) & 0xff);
3866 r32 = read32(DEFAULT_MCHBAR + 0x5064);
3867 if (r32 & 0x20000)
3868 t1_cycles += (r32 & 0xfff);
3869 t1_cycles += (read32(DEFAULT_MCHBAR + channel * 0x400 + 0x42a4) & 0xfff);
3870 t1_ns = t1_cycles * ctrl->tCK / 256 + 544;
3871 if (!(r32 & 0x20000))
3872 t1_ns += 500;
3873
3874 t2_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f10) >> 8) & 0xfff);
3875 if ( read32(DEFAULT_MCHBAR + 0x5f00) & 8 )
3876 {
3877 t3_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f20) >> 8) & 0xfff);
3878 t3_ns += 10 * (read32(DEFAULT_MCHBAR + 0x5f18) & 0xff);
3879 }
3880 else
3881 {
3882 t3_ns = 500;
3883 }
3884 printk(BIOS_DEBUG, "t123: %d, %d, %d\n",
3885 t1_ns, t2_ns, t3_ns);
3886 write32 (DEFAULT_MCHBAR + 0x5d10,
3887 ((encode_5d10(t1_ns) + encode_5d10(t2_ns)) << 16)
3888 | (encode_5d10(t1_ns) << 8)
3889 | ((encode_5d10(t3_ns) + encode_5d10(t2_ns) + encode_5d10(t1_ns)) << 24)
3890 | (read32(DEFAULT_MCHBAR + 0x5d10) & 0xC0C0C0C0)
3891 | 0xc);
3892}
3893
3894static void save_timings(ramctr_timing * ctrl)
3895{
3896 struct mrc_data_container *mrcdata;
3897 int output_len = ALIGN(sizeof (*ctrl), 16);
3898
3899 /* Save the MRC S3 restore data to cbmem */
3900 mrcdata = cbmem_add
3901 (CBMEM_ID_MRCDATA,
3902 output_len + sizeof(struct mrc_data_container));
3903
3904 printk(BIOS_DEBUG, "Relocate MRC DATA from %p to %p (%u bytes)\n",
3905 ctrl, mrcdata, output_len);
3906
3907 mrcdata->mrc_signature = MRC_DATA_SIGNATURE;
3908 mrcdata->mrc_data_size = output_len;
3909 mrcdata->reserved = 0;
3910 memcpy(mrcdata->mrc_data, ctrl, sizeof (*ctrl));
3911
3912 /* Zero the unused space in aligned buffer. */
3913 if (output_len > sizeof (*ctrl))
3914 memset(mrcdata->mrc_data+sizeof (*ctrl), 0,
3915 output_len - sizeof (*ctrl));
3916
3917 mrcdata->mrc_checksum = compute_ip_checksum(mrcdata->mrc_data,
3918 mrcdata->mrc_data_size);
3919}
3920
3921static void restore_timings(ramctr_timing * ctrl)
3922{
3923 int channel, slotrank, lane;
3924
3925 FOR_ALL_POPULATED_CHANNELS
3926 MCHBAR32(0x4004 + 0x400 * channel) =
3927 ctrl->tRRD
3928 | (ctrl->tRTP << 4)
3929 | (ctrl->tCKE << 8)
3930 | (ctrl->tWTR << 12)
3931 | (ctrl->tFAW << 16)
3932 | (ctrl->tWR << 24)
3933 | (ctrl->cmd_stretch[channel] << 30);
3934
3935 udelay(1);
3936
3937 FOR_ALL_POPULATED_CHANNELS {
3938 wait_428c(channel);
3939 }
3940
3941 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3942 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
3943 + 4 * lane, 0);
3944 }
3945
3946 FOR_ALL_POPULATED_CHANNELS
3947 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
3948 read32(DEFAULT_MCHBAR + 0x4008 +
3949 0x400 * channel) | 0x8000000);
3950
3951 FOR_ALL_POPULATED_CHANNELS {
3952 udelay (1);
3953 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
3954 read32(DEFAULT_MCHBAR + 0x4020 +
3955 0x400 * channel) | 0x200000);
3956 }
3957
3958 printram("CPE\n");
3959
3960 write32(DEFAULT_MCHBAR + 0x3400, 0);
3961 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3962
3963 printram("CP5b\n");
3964
3965 FOR_ALL_POPULATED_CHANNELS {
3966 program_timings(ctrl, channel);
3967 }
3968
3969 u32 reg, addr;
3970
3971 while (!(MCHBAR32(0x5084) & 0x10000)) ;
3972 do {
3973 reg = MCHBAR32(0x428c);
3974 } while ((reg & 0x14) == 0);
3975
3976 // Set state of memory controller
3977 MCHBAR32(0x5030) = 0x116;
3978 MCHBAR32(0x4ea0) = 0;
3979
3980 // Wait 500us
3981 udelay(500);
3982
3983 FOR_ALL_CHANNELS {
3984 // Set valid rank CKE
3985 reg = 0;
3986 reg = (reg & ~0xf) | ctrl->rankmap[channel];
3987 addr = 0x400 * channel + 0x42a0;
3988 MCHBAR32(addr) = reg;
3989
3990 // Wait 10ns for ranks to settle
3991 //udelay(0.01);
3992
3993 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
3994 MCHBAR32(addr) = reg;
3995
3996 // Write reset using a NOP
3997 write_reset(ctrl);
3998 }
3999
4000 /* mrs commands. */
4001 dram_mrscommands(ctrl);
4002
4003 printram("CP5c\n");
4004
4005 write32(DEFAULT_MCHBAR + 0x3000, 0);
4006
4007 FOR_ALL_CHANNELS {
4008 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
4009 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
4010 ~0x3f000000));
4011 udelay(2);
4012 }
4013
4014 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
4015}
4016
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004017static int try_init_dram_ddr3(ramctr_timing *ctrl, int s3resume,
4018 int me_uma_size)
4019{
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004020 int err;
4021
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004022 if (!s3resume) {
4023 /* Find fastest common supported parameters */
4024 dram_find_common_params(ctrl);
4025
4026 dram_dimm_mapping(ctrl);
4027 }
4028
4029 /* Set MCU frequency */
4030 dram_freq(ctrl);
4031
4032 if (!s3resume) {
4033 /* Calculate timings */
4034 dram_timing(ctrl);
4035 }
4036
4037 /* Set version register */
4038 MCHBAR32(0x5034) = 0xC04EB002;
4039
4040 /* Enable crossover */
4041 dram_xover(ctrl);
4042
4043 /* Set timing and refresh registers */
4044 dram_timing_regs(ctrl);
4045
4046 /* Power mode preset */
4047 MCHBAR32(0x4e80) = 0x5500;
4048
4049 /* Set scheduler parameters */
4050 MCHBAR32(0x4c20) = 0x10100005;
4051
4052 /* Set cpu specific register */
4053 set_4f8c();
4054
4055 /* Clear IO reset bit */
4056 MCHBAR32(0x5030) &= ~0x20;
4057
4058 /* Set MAD-DIMM registers */
4059 dram_dimm_set_mapping(ctrl);
4060 printk(BIOS_DEBUG, "Done dimm mapping\n");
4061
4062 /* Zone config */
4063 dram_zones(ctrl, 1);
4064
4065 /* Set memory map */
4066 dram_memorymap(ctrl, me_uma_size);
4067 printk(BIOS_DEBUG, "Done memory map\n");
4068
4069 /* Set IO registers */
4070 dram_ioregs(ctrl);
4071 printk(BIOS_DEBUG, "Done io registers\n");
4072
4073 udelay(1);
4074
4075 if (s3resume) {
4076 restore_timings(ctrl);
4077 } else {
4078 /* Do jedec ddr3 reset sequence */
4079 dram_jedecreset(ctrl);
4080 printk(BIOS_DEBUG, "Done jedec reset\n");
4081
4082 /* MRS commands */
4083 dram_mrscommands(ctrl);
4084 printk(BIOS_DEBUG, "Done MRS commands\n");
4085
4086 /* Prepare for memory training */
4087 prepare_training(ctrl);
4088
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004089 err = read_training(ctrl);
4090 if (err)
4091 return err;
4092
4093 err = write_training(ctrl);
4094 if (err)
4095 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004096
4097 printram("CP5a\n");
4098
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004099 err = discover_edges(ctrl);
4100 if (err)
4101 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004102
4103 printram("CP5b\n");
4104
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004105 err = command_training(ctrl);
4106 if (err)
4107 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004108
4109 printram("CP5c\n");
4110
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004111 err = discover_edges_write(ctrl);
4112 if (err)
4113 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004114
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004115 err = discover_timC_write(ctrl);
4116 if (err)
4117 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004118
4119 normalize_training(ctrl);
4120 }
4121
4122 set_4008c(ctrl);
4123
4124 write_controller_mr(ctrl);
4125
4126 if (!s3resume) {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004127 err = channel_test(ctrl);
4128 if (err)
4129 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004130 }
4131
4132 return 0;
4133}
4134
4135void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004136 int s3resume)
4137{
4138 int me_uma_size;
4139 int cbmem_was_inited;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004140 ramctr_timing ctrl;
Patrick Rudolph31d19592016-03-26 12:22:34 +01004141 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004142
4143 MCHBAR32(0x5f00) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004144
Vadim Bendebury7a3f36a2012-04-18 15:47:32 -07004145 report_platform_info();
4146
Stefan Reinauer00636b02012-04-04 00:08:51 +02004147 /* Wait for ME to be ready */
4148 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004149 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004150
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004151 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +02004152
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004153 u32 reg_5d10;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004154
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004155 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004156
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004157 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +02004158
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004159 reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10); // !!! = 0x00000000
4160 if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */
4161 && reg_5d10 && !s3resume) {
4162 write32(DEFAULT_MCHBAR + 0x5d10, 0);
4163 /* Need reset. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02004164 outb(0x6, 0xcf9);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004165
Patrick Georgi546953c2014-11-29 10:38:17 +01004166 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004167 }
Stefan Reinauer00636b02012-04-04 00:08:51 +02004168
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004169 memset(&ctrl, 0, sizeof (ctrl));
4170
4171 early_pch_init_native();
4172 early_thermal_init();
4173
4174 ctrl.mobile = mobile;
4175 ctrl.tCK = min_tck;
4176
4177 /* FIXME: for non-S3 we should be able to use timing caching with
4178 proper verification. Right now we use timings only for S3 case.
4179 */
4180 if (s3resume) {
4181 struct mrc_data_container *mrc_cache;
4182
4183 mrc_cache = find_current_mrc_cache();
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004184 if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(ctrl))) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004185 /* Failed S3 resume, reset to come up cleanly */
4186 outb(0x6, 0xcf9);
4187 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004188 }
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004189 memcpy(&ctrl, mrc_cache->mrc_data, sizeof(ctrl));
4190 } else {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004191 /* Get DDR3 SPD data */
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004192 dram_find_spds_ddr3(spds, &ctrl);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004193 }
4194
Patrick Rudolph31d19592016-03-26 12:22:34 +01004195 err = try_init_dram_ddr3(&ctrl, s3resume, me_uma_size);
4196 if (err)
4197 die("raminit failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004198
4199 /* FIXME: should be hardware revision-dependent. */
4200 write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
4201
4202 set_scrambling_seed(&ctrl);
4203
4204 set_42a0(&ctrl);
4205
4206 final_registers(&ctrl);
4207
4208 /* Zone config */
4209 dram_zones(&ctrl, 0);
4210
4211 if (!s3resume)
4212 quick_ram_check();
4213
4214 intel_early_me_status();
4215 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
4216 intel_early_me_status();
4217
Stefan Reinauer00636b02012-04-04 00:08:51 +02004218 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004219
4220 cbmem_was_inited = !cbmem_recovery(s3resume);
4221 if (!s3resume)
4222 save_timings(&ctrl);
4223 if (s3resume && !cbmem_was_inited) {
4224 /* Failed S3 resume, reset to come up cleanly */
4225 outb(0x6, 0xcf9);
4226 halt();
4227 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +01004228
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004229 fill_smbios17(&ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004230}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004231
4232#define HOST_BRIDGE PCI_DEVFN(0, 0)
4233#define DEFAULT_TCK TCK_800MHZ
4234
4235static unsigned int get_mem_min_tck(void)
4236{
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004237 u32 reg32;
4238 u8 rev;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004239 const struct device *dev;
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004240 const struct northbridge_intel_sandybridge_config *cfg = NULL;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004241
4242 dev = dev_find_slot(0, HOST_BRIDGE);
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004243 if (dev)
4244 cfg = dev->chip_info;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004245
4246 /* If this is zero, it just means devicetree.cb didn't set it */
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004247 if (!cfg || cfg->max_mem_clock_mhz == 0) {
4248 rev = pci_read_config8(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004249
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004250 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
4251 /* read Capabilities A Register DMFC bits */
4252 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A);
4253 reg32 &= 0x7;
4254
4255 switch (reg32) {
4256 case 7: return TCK_533MHZ;
4257 case 6: return TCK_666MHZ;
4258 case 5: return TCK_800MHZ;
4259 /* reserved: */
4260 default:
4261 break;
4262 }
4263 } else {
4264 /* read Capabilities B Register DMFC bits */
4265 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
4266 reg32 = (reg32 >> 4) & 0x7;
4267
4268 switch (reg32) {
4269 case 7: return TCK_533MHZ;
4270 case 6: return TCK_666MHZ;
4271 case 5: return TCK_800MHZ;
4272 case 4: return TCK_933MHZ;
4273 case 3: return TCK_1066MHZ;
4274 case 2: return TCK_1200MHZ;
4275 case 1: return TCK_1333MHZ;
4276 /* reserved: */
4277 default:
4278 break;
4279 }
4280 }
4281 return DEFAULT_TCK;
4282 } else {
4283 if (cfg->max_mem_clock_mhz >= 800)
4284 return TCK_800MHZ;
4285 else if (cfg->max_mem_clock_mhz >= 666)
4286 return TCK_666MHZ;
4287 else if (cfg->max_mem_clock_mhz >= 533)
4288 return TCK_533MHZ;
4289 else
4290 return TCK_400MHZ;
4291 }
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004292}
4293
4294void perform_raminit(int s3resume)
4295{
4296 spd_raw_data spd[4];
4297
4298 post_code(0x3a);
4299
4300 memset (spd, 0, sizeof (spd));
4301 mainboard_get_spd(spd);
4302
4303 timestamp_add_now(TS_BEFORE_INITRAM);
4304
4305 init_dram_ddr3(spd, 1, get_mem_min_tck(), s3resume);
4306}