blob: 6bb77b2c6aea75db2f5bc8395e90f197767937c6 [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 {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100138 u16 spd_crc[NUM_CHANNELS][NUM_SLOTS];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700139 int mobile;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200140
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700141 u16 cas_supported;
142 /* tLatencies are in units of ns, scaled by x256 */
143 u32 tCK;
144 u32 tAA;
145 u32 tWR;
146 u32 tRCD;
147 u32 tRRD;
148 u32 tRP;
149 u32 tRAS;
150 u32 tRFC;
151 u32 tWTR;
152 u32 tRTP;
153 u32 tFAW;
154 /* Latencies in terms of clock cycles
155 * They are saved separately as they are needed for DRAM MRS commands*/
156 u8 CAS; /* CAS read latency */
157 u8 CWL; /* CAS write latency */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200158
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700159 u32 tREFI;
160 u32 tMOD;
161 u32 tXSOffset;
162 u32 tWLO;
163 u32 tCKE;
164 u32 tXPDLL;
165 u32 tXP;
166 u32 tAONPD;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200167
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700168 u16 reg_5064b0; /* bits 0-11. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200169
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700170 u8 rankmap[NUM_CHANNELS];
171 int ref_card_offset[NUM_CHANNELS];
172 u32 mad_dimm[NUM_CHANNELS];
173 int channel_size_mb[NUM_CHANNELS];
174 u32 cmd_stretch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200175
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700176 int reg_c14_offset;
177 int reg_320c_range_threshold;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200178
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700179 int edge_offset[3];
180 int timC_offset[3];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200181
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700182 int extended_temperature_range;
183 int auto_self_refresh;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200184
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700185 int rank_mirror[NUM_CHANNELS][NUM_SLOTRANKS];
186
187 struct ram_rank_timings timings[NUM_CHANNELS][NUM_SLOTRANKS];
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100188
189 dimm_info info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700190} ramctr_timing;
191
192#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
193#define NORTHBRIDGE PCI_DEV(0, 0x0, 0)
194#define FOR_ALL_LANES for (lane = 0; lane < NUM_LANES; lane++)
195#define FOR_ALL_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++)
196#define FOR_ALL_POPULATED_RANKS for (slotrank = 0; slotrank < NUM_SLOTRANKS; slotrank++) if (ctrl->rankmap[channel] & (1 << slotrank))
197#define FOR_ALL_POPULATED_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) if (ctrl->rankmap[channel])
198#define MAX_EDGE_TIMING 71
199#define MAX_TIMC 127
200#define MAX_TIMB 511
201#define MAX_TIMA 127
202
Patrick Rudolph24a845b2016-03-25 18:19:47 +0100203#define MAKE_ERR ((channel<<16)|(slotrank<<8)|1)
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100204#define GET_ERR_CHANNEL(x) (x>>16)
Patrick Rudolph24a845b2016-03-25 18:19:47 +0100205
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700206static void program_timings(ramctr_timing * ctrl, int channel);
207
208static const char *ecc_decoder[] = {
Stefan Reinauer00636b02012-04-04 00:08:51 +0200209 "inactive",
210 "active on IO",
211 "disabled on IO",
212 "active"
213};
214
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700215static void wait_txt_clear(void)
216{
217 struct cpuid_result cp;
218
219 cp = cpuid_ext(0x1, 0x0);
220 /* Check if TXT is supported? */
221 if (!(cp.ecx & 0x40))
222 return;
223 /* Some TXT public bit. */
224 if (!(read32((void *)0xfed30010) & 1))
225 return;
226 /* Wait for TXT clear. */
227 while (!(read8((void *)0xfed40000) & (1 << 7))) ;
228}
229
230static void sfence(void)
231{
232 asm volatile ("sfence");
233}
234
Patrick Rudolph9b515682015-10-09 13:43:51 +0200235static void toggle_io_reset(void) {
236 /* toggle IO reset bit */
237 u32 r32 = read32(DEFAULT_MCHBAR + 0x5030);
238 write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20);
239 udelay(1);
240 write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20);
241 udelay(1);
242}
243
Stefan Reinauer00636b02012-04-04 00:08:51 +0200244/*
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100245 * Disable a channel in ramctr_timing.
246 */
247static void disable_channel(ramctr_timing *ctrl, int channel) {
248 ctrl->rankmap[channel] = 0;
249 memset(&ctrl->rank_mirror[channel][0], 0, sizeof(ctrl->rank_mirror[0]));
250 ctrl->channel_size_mb[channel] = 0;
251 ctrl->cmd_stretch[channel] = 0;
252 ctrl->mad_dimm[channel] = 0;
253 memset(&ctrl->timings[channel][0], 0, sizeof(ctrl->timings[0]));
254}
255
256/*
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100257 * Fill cbmem with information for SMBIOS type 17.
258 */
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100259static void fill_smbios17(ramctr_timing *ctrl)
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100260{
261 struct memory_info *mem_info;
262 int channel, slot;
263 struct dimm_info *dimm;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100264 uint16_t ddr_freq;
265 dimm_info *info = &ctrl->info;
266
267 ddr_freq = (1000 << 8) / ctrl->tCK;
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100268
269 /*
270 * Allocate CBMEM area for DIMM information used to populate SMBIOS
271 * table 17
272 */
273 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
274 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
275 if (!mem_info)
276 return;
277
278 memset(mem_info, 0, sizeof(*mem_info));
279
280 FOR_ALL_CHANNELS for(slot = 0; slot < NUM_SLOTS; slot++) {
281 dimm = &mem_info->dimm[mem_info->dimm_cnt];
282 if (info->dimm[channel][slot].size_mb) {
283 dimm->ddr_type = MEMORY_TYPE_DDR3;
284 dimm->ddr_frequency = ddr_freq;
285 dimm->dimm_size = info->dimm[channel][slot].size_mb;
286 dimm->channel_num = channel;
287 dimm->rank_per_dimm = info->dimm[channel][slot].ranks;
288 dimm->dimm_num = slot;
289 memcpy(dimm->module_part_number,
290 info->dimm[channel][slot].part_number, 16);
291 dimm->mod_id = info->dimm[channel][slot].manufacturer_id;
292 dimm->mod_type = info->dimm[channel][slot].dimm_type;
293 dimm->bus_width = info->dimm[channel][slot].width;
294 mem_info->dimm_cnt++;
295 }
296 }
297}
298
299/*
Stefan Reinauer00636b02012-04-04 00:08:51 +0200300 * Dump in the log memory controller configuration as read from the memory
301 * controller registers.
302 */
303static void report_memory_config(void)
304{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700305 u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200306 int i;
307
308 addr_decoder_common = MCHBAR32(0x5000);
309 addr_decode_ch[0] = MCHBAR32(0x5004);
310 addr_decode_ch[1] = MCHBAR32(0x5008);
311
312 printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700313 (MCHBAR32(0x5e04) * 13333 * 2 + 50) / 100);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200314 printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700315 addr_decoder_common & 3, (addr_decoder_common >> 2) & 3,
Stefan Reinauer00636b02012-04-04 00:08:51 +0200316 (addr_decoder_common >> 4) & 3);
317
318 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
319 u32 ch_conf = addr_decode_ch[i];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700320 printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i,
321 ch_conf);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200322 printk(BIOS_DEBUG, " ECC %s\n",
323 ecc_decoder[(ch_conf >> 24) & 3]);
324 printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
325 ((ch_conf >> 22) & 1) ? "on" : "off");
326 printk(BIOS_DEBUG, " rank interleave %s\n",
327 ((ch_conf >> 21) & 1) ? "on" : "off");
328 printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n",
329 ((ch_conf >> 0) & 0xff) * 256,
330 ((ch_conf >> 19) & 1) ? 16 : 8,
331 ((ch_conf >> 17) & 1) ? "dual" : "single",
332 ((ch_conf >> 16) & 1) ? "" : ", selected");
333 printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n",
334 ((ch_conf >> 8) & 0xff) * 256,
335 ((ch_conf >> 20) & 1) ? 16 : 8,
336 ((ch_conf >> 18) & 1) ? "dual" : "single",
337 ((ch_conf >> 16) & 1) ? ", selected" : "");
338 }
339}
340
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100341/*
342 * Return CRC16 match for all SPDs.
343 */
344static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
345{
346 int channel, slot, spd_slot;
347 int match = 1;
348
349 FOR_ALL_CHANNELS {
350 for (slot = 0; slot < NUM_SLOTS; slot++) {
351 spd_slot = 2 * channel + slot;
352 match &= ctrl->spd_crc[channel][slot] ==
353 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
354 }
355 }
356 return match;
357}
358
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700359void read_spd(spd_raw_data * spd, u8 addr)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200360{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700361 int j;
362 for (j = 0; j < 256; j++)
363 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
364}
365
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100366static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700367{
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100368 int dimms = 0, dimms_on_channel;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700369 int channel, slot, spd_slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100370 dimm_info *dimm = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700371
372 memset (ctrl->rankmap, 0, sizeof (ctrl->rankmap));
373
374 ctrl->extended_temperature_range = 1;
375 ctrl->auto_self_refresh = 1;
376
377 FOR_ALL_CHANNELS {
378 ctrl->channel_size_mb[channel] = 0;
379
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100380 dimms_on_channel = 0;
381 /* count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700382 for (slot = 0; slot < NUM_SLOTS; slot++) {
383 spd_slot = 2 * channel + slot;
384 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100385 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
386 dimms_on_channel++;
387 }
388
389 for (slot = 0; slot < NUM_SLOTS; slot++) {
390 spd_slot = 2 * channel + slot;
391 /* search for XMP profile */
392 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
393 spd[spd_slot],
394 DDR3_XMP_PROFILE_1);
395
396 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
397 printram("No valid XMP profile found.\n");
398 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
399 } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
400 printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
401 dimm->dimm[channel][slot].dimms_per_channel,
402 dimms_on_channel);
403 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
404 } else if (dimm->dimm[channel][slot].voltage != 1500) {
405 /* TODO: support other DDR3 voltage than 1500mV */
406 printram("XMP profile's requested %u mV is unsupported.\n",
407 dimm->dimm[channel][slot].voltage);
408 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
409 }
410
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100411 /* fill in CRC16 for MRC cache */
412 ctrl->spd_crc[channel][slot] =
413 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
414
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700415 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
416 // set dimm invalid
417 dimm->dimm[channel][slot].ranks = 0;
418 dimm->dimm[channel][slot].size_mb = 0;
419 continue;
420 }
421
422 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
423 dimms++;
424 ctrl->rank_mirror[channel][slot * 2] = 0;
425 ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
426 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
427
428 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
429 ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
430
431 ctrl->rankmap[channel] |= ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100432 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n",
433 channel, ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700434 }
435 if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc)
436 && dimm->dimm[channel][0].reference_card <= 5 && dimm->dimm[channel][1].reference_card <= 5) {
437 const int ref_card_offset_table[6][6] = {
438 { 0, 0, 0, 0, 2, 2, },
439 { 0, 0, 0, 0, 2, 2, },
440 { 0, 0, 0, 0, 2, 2, },
441 { 0, 0, 0, 0, 1, 1, },
442 { 2, 2, 2, 1, 0, 0, },
443 { 2, 2, 2, 1, 0, 0, },
444 };
445 ctrl->ref_card_offset[channel] = ref_card_offset_table[dimm->dimm[channel][0].reference_card]
446 [dimm->dimm[channel][1].reference_card];
447 } else
448 ctrl->ref_card_offset[channel] = 0;
449 }
450
451 if (!dimms)
452 die("No DIMMs were found");
453}
454
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100455static void dram_find_common_params(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700456{
457 size_t valid_dimms;
458 int channel, slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100459 dimm_info *dimms = &ctrl->info;
460
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700461 ctrl->cas_supported = 0xff;
462 valid_dimms = 0;
463 FOR_ALL_CHANNELS for (slot = 0; slot < 2; slot++) {
464 const dimm_attr *dimm = &dimms->dimm[channel][slot];
465 if (dimm->dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3)
466 continue;
467 valid_dimms++;
468
469 /* Find all possible CAS combinations */
470 ctrl->cas_supported &= dimm->cas_supported;
471
472 /* Find the smallest common latencies supported by all DIMMs */
473 ctrl->tCK = MAX(ctrl->tCK, dimm->tCK);
474 ctrl->tAA = MAX(ctrl->tAA, dimm->tAA);
475 ctrl->tWR = MAX(ctrl->tWR, dimm->tWR);
476 ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD);
477 ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD);
478 ctrl->tRP = MAX(ctrl->tRP, dimm->tRP);
479 ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS);
480 ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC);
481 ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR);
482 ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP);
483 ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW);
484 }
485
486 if (!ctrl->cas_supported)
487 die("Unsupported DIMM combination. "
488 "DIMMS do not support common CAS latency");
489 if (!valid_dimms)
490 die("No valid DIMMs found");
491}
492
493static u8 get_CWL(u8 CAS)
494{
495 /* Get CWL based on CAS using the following rule:
496 * _________________________________________
497 * CAS: | 4T | 5T | 6T | 7T | 8T | 9T | 10T | 11T |
498 * CWL: | 5T | 5T | 5T | 6T | 6T | 7T | 7T | 8T |
499 */
500 static const u8 cas_cwl_map[] = { 5, 5, 5, 6, 6, 7, 7, 8 };
501 if (CAS > 11)
502 return 8;
503 return cas_cwl_map[CAS - 4];
504}
505
506/* Frequency multiplier. */
507static u32 get_FRQ(u32 tCK)
508{
509 u32 FRQ;
510 FRQ = 256000 / (tCK * BASEFREQ);
511 if (FRQ > 8)
512 return 8;
513 if (FRQ < 3)
514 return 3;
515 return FRQ;
516}
517
518static u32 get_REFI(u32 tCK)
519{
520 /* Get REFI based on MCU frequency using the following rule:
521 * _________________________________________
522 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
523 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 |
524 */
525 static const u32 frq_refi_map[] =
526 { 3120, 4160, 5200, 6240, 7280, 8320 };
527 return frq_refi_map[get_FRQ(tCK) - 3];
528}
529
530static u8 get_XSOffset(u32 tCK)
531{
532 /* Get XSOffset based on MCU frequency using the following rule:
533 * _________________________
534 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
535 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 |
536 */
537 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 };
538 return frq_xs_map[get_FRQ(tCK) - 3];
539}
540
541static u8 get_MOD(u32 tCK)
542{
543 /* Get MOD based on MCU frequency using the following rule:
544 * _____________________________
545 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
546 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 |
547 */
548 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 };
549 return frq_mod_map[get_FRQ(tCK) - 3];
550}
551
552static u8 get_WLO(u32 tCK)
553{
554 /* Get WLO based on MCU frequency using the following rule:
555 * _______________________
556 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
557 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 |
558 */
559 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 };
560 return frq_wlo_map[get_FRQ(tCK) - 3];
561}
562
563static u8 get_CKE(u32 tCK)
564{
565 /* Get CKE based on MCU frequency using the following rule:
566 * _______________________
567 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
568 * CKE : | 3 | 3 | 4 | 4 | 5 | 6 |
569 */
570 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 };
571 return frq_cke_map[get_FRQ(tCK) - 3];
572}
573
574static u8 get_XPDLL(u32 tCK)
575{
576 /* Get XPDLL based on MCU frequency using the following rule:
577 * _____________________________
578 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
579 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 |
580 */
581 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 };
582 return frq_xpdll_map[get_FRQ(tCK) - 3];
583}
584
585static u8 get_XP(u32 tCK)
586{
587 /* Get XP based on MCU frequency using the following rule:
588 * _______________________
589 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
590 * XP : | 3 | 4 | 4 | 5 | 6 | 7 |
591 */
592 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 };
593 return frq_xp_map[get_FRQ(tCK) - 3];
594}
595
596static u8 get_AONPD(u32 tCK)
597{
598 /* Get AONPD based on MCU frequency using the following rule:
599 * ________________________
600 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
601 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 |
602 */
603 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 };
604 return frq_aonpd_map[get_FRQ(tCK) - 3];
605}
606
607static u32 get_COMP2(u32 tCK)
608{
609 /* Get COMP2 based on MCU frequency using the following rule:
610 * ___________________________________________________________
611 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
612 * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C |
613 */
614 static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C,
615 0xC6369CC, 0xC42514C, 0xC21410C
616 };
617 return frq_comp2_map[get_FRQ(tCK) - 3];
618}
619
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100620static u32 get_XOVER_CLK(u8 rankmap)
621{
622 return rankmap << 24;
623}
624
625static u32 get_XOVER_CMD(u8 rankmap)
626{
627 u32 reg;
628
629 // enable xover cmd
630 reg = 0x4000;
631
632 // enable xover ctl
633 if (rankmap & 0x3)
634 reg |= 0x20000;
635
636 if (rankmap & 0xc)
637 reg |= 0x4000000;
638
639 return reg;
640}
641
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700642static void dram_timing(ramctr_timing * ctrl)
643{
644 u8 val;
645 u32 val32;
646
647 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
648 * we cap it if we have faster DIMMs.
649 * Then, align it to the closest JEDEC standard frequency */
650 if (ctrl->tCK <= TCK_1066MHZ) {
651 ctrl->tCK = TCK_1066MHZ;
652 ctrl->edge_offset[0] = 16;
653 ctrl->edge_offset[1] = 7;
654 ctrl->edge_offset[2] = 7;
655 ctrl->timC_offset[0] = 18;
656 ctrl->timC_offset[1] = 7;
657 ctrl->timC_offset[2] = 7;
658 ctrl->reg_c14_offset = 16;
659 ctrl->reg_5064b0 = 0x218;
660 ctrl->reg_320c_range_threshold = 13;
661 } else if (ctrl->tCK <= TCK_933MHZ) {
662 ctrl->tCK = TCK_933MHZ;
663 ctrl->edge_offset[0] = 14;
664 ctrl->edge_offset[1] = 6;
665 ctrl->edge_offset[2] = 6;
666 ctrl->timC_offset[0] = 15;
667 ctrl->timC_offset[1] = 6;
668 ctrl->timC_offset[2] = 6;
669 ctrl->reg_c14_offset = 14;
670 ctrl->reg_5064b0 = 0x1d5;
671 ctrl->reg_320c_range_threshold = 15;
672 } else if (ctrl->tCK <= TCK_800MHZ) {
673 ctrl->tCK = TCK_800MHZ;
674 ctrl->edge_offset[0] = 13;
675 ctrl->edge_offset[1] = 5;
676 ctrl->edge_offset[2] = 5;
677 ctrl->timC_offset[0] = 14;
678 ctrl->timC_offset[1] = 5;
679 ctrl->timC_offset[2] = 5;
680 ctrl->reg_c14_offset = 12;
681 ctrl->reg_5064b0 = 0x193;
682 ctrl->reg_320c_range_threshold = 15;
683 } else if (ctrl->tCK <= TCK_666MHZ) {
684 ctrl->tCK = TCK_666MHZ;
685 ctrl->edge_offset[0] = 10;
686 ctrl->edge_offset[1] = 4;
687 ctrl->edge_offset[2] = 4;
688 ctrl->timC_offset[0] = 11;
689 ctrl->timC_offset[1] = 4;
690 ctrl->timC_offset[2] = 4;
691 ctrl->reg_c14_offset = 10;
692 ctrl->reg_5064b0 = 0x150;
693 ctrl->reg_320c_range_threshold = 16;
694 } else if (ctrl->tCK <= TCK_533MHZ) {
695 ctrl->tCK = TCK_533MHZ;
696 ctrl->edge_offset[0] = 8;
697 ctrl->edge_offset[1] = 3;
698 ctrl->edge_offset[2] = 3;
699 ctrl->timC_offset[0] = 9;
700 ctrl->timC_offset[1] = 3;
701 ctrl->timC_offset[2] = 3;
702 ctrl->reg_c14_offset = 8;
703 ctrl->reg_5064b0 = 0x10d;
704 ctrl->reg_320c_range_threshold = 17;
705 } else {
706 ctrl->tCK = TCK_400MHZ;
707 ctrl->edge_offset[0] = 6;
708 ctrl->edge_offset[1] = 2;
709 ctrl->edge_offset[2] = 2;
710 ctrl->timC_offset[0] = 6;
711 ctrl->timC_offset[1] = 2;
712 ctrl->timC_offset[2] = 2;
713 ctrl->reg_c14_offset = 8;
714 ctrl->reg_5064b0 = 0xcd;
715 ctrl->reg_320c_range_threshold = 17;
716 }
717
718 val32 = (1000 << 8) / ctrl->tCK;
719 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
720
721 /* Find CAS and CWL latencies */
722 val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK;
723 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
724 /* Find lowest supported CAS latency that satisfies the minimum value */
725 while (!((ctrl->cas_supported >> (val - 4)) & 1)
726 && (ctrl->cas_supported >> (val - 4))) {
727 val++;
728 }
729 /* Is CAS supported */
730 if (!(ctrl->cas_supported & (1 << (val - 4))))
731 printk(BIOS_DEBUG, "CAS not supported\n");
732 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
733 ctrl->CAS = val;
734 ctrl->CWL = get_CWL(ctrl->CAS);
735 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
736
737 /* Find tRCD */
738 ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK;
739 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
740
741 ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK;
742 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
743
744 /* Find tRAS */
745 ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK;
746 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
747
748 /* Find tWR */
749 ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK;
750 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
751
752 /* Find tFAW */
753 ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK;
754 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
755
756 /* Find tRRD */
757 ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK;
758 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
759
760 /* Find tRTP */
761 ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK;
762 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
763
764 /* Find tWTR */
765 ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK;
766 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
767
768 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
769 ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK;
770 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
771
772 ctrl->tREFI = get_REFI(ctrl->tCK);
773 ctrl->tMOD = get_MOD(ctrl->tCK);
774 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
775 ctrl->tWLO = get_WLO(ctrl->tCK);
776 ctrl->tCKE = get_CKE(ctrl->tCK);
777 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
778 ctrl->tXP = get_XP(ctrl->tCK);
779 ctrl->tAONPD = get_AONPD(ctrl->tCK);
780}
781
782static void dram_freq(ramctr_timing * ctrl)
783{
784 if (ctrl->tCK > TCK_400MHZ) {
785 printk (BIOS_ERR, "DRAM frequency is under lowest supported frequency (400 MHz). Increasing to 400 MHz as last resort");
786 ctrl->tCK = TCK_400MHZ;
787 }
788 while (1) {
789 u8 val2;
790 u32 reg1 = 0;
791
792 /* Step 1 - Set target PCU frequency */
793
794 if (ctrl->tCK <= TCK_1066MHZ) {
795 ctrl->tCK = TCK_1066MHZ;
796 } else if (ctrl->tCK <= TCK_933MHZ) {
797 ctrl->tCK = TCK_933MHZ;
798 } else if (ctrl->tCK <= TCK_800MHZ) {
799 ctrl->tCK = TCK_800MHZ;
800 } else if (ctrl->tCK <= TCK_666MHZ) {
801 ctrl->tCK = TCK_666MHZ;
802 } else if (ctrl->tCK <= TCK_533MHZ) {
803 ctrl->tCK = TCK_533MHZ;
804 } else if (ctrl->tCK <= TCK_400MHZ) {
805 ctrl->tCK = TCK_400MHZ;
806 } else {
807 die ("No lock frequency found");
808 }
809
810 /* Frequency mulitplier. */
811 u32 FRQ = get_FRQ(ctrl->tCK);
812
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100813 /* The PLL will never lock if the required frequency is
814 * already set. Exit early to prevent a system hang.
815 */
816 reg1 = MCHBAR32(0x5e04);
817 val2 = (u8) reg1;
818 if (val2 == FRQ) {
819 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
820 (1000 << 8) / ctrl->tCK);
821 return;
822 }
823
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700824 /* Step 2 - Select frequency in the MCU */
825 reg1 = FRQ;
826 reg1 |= 0x80000000; // set running bit
827 MCHBAR32(0x5e00) = reg1;
828 while (reg1 & 0x80000000) {
829 printk(BIOS_DEBUG, " PLL busy...");
830 reg1 = MCHBAR32(0x5e00);
831 }
832 printk(BIOS_DEBUG, "done\n");
833
834 /* Step 3 - Verify lock frequency */
835 reg1 = MCHBAR32(0x5e04);
836 val2 = (u8) reg1;
837 if (val2 >= FRQ) {
838 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
839 (1000 << 8) / ctrl->tCK);
840 return;
841 }
842 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
843 ctrl->tCK++;
844 }
845}
846
847static void dram_xover(ramctr_timing * ctrl)
848{
849 u32 reg;
850 int channel;
851
852 FOR_ALL_CHANNELS {
853 // enable xover clk
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100854 reg = get_XOVER_CLK(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100855 printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
856 reg);
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100857 MCHBAR32(channel * 0x100 + 0xc14) = reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700858
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100859 // enable xover ctl & xover cmd
860 reg = get_XOVER_CMD(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100861 printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
862 reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700863 MCHBAR32(0x100 * channel + 0x320c) = reg;
864 }
865}
866
867static void dram_timing_regs(ramctr_timing * ctrl)
868{
869 u32 reg, addr, val32, cpu, stretch;
870 struct cpuid_result cpures;
871 int channel;
872
873 FOR_ALL_CHANNELS {
874 // DBP
875 reg = 0;
876 reg |= ctrl->tRCD;
877 reg |= (ctrl->tRP << 4);
878 reg |= (ctrl->CAS << 8);
879 reg |= (ctrl->CWL << 12);
880 reg |= (ctrl->tRAS << 16);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100881 printram("DBP [%x] = %x\n", 0x400 * channel + 0x4000, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700882 MCHBAR32(0x400 * channel + 0x4000) = reg;
883
884 // RAP
885 reg = 0;
886 reg |= ctrl->tRRD;
887 reg |= (ctrl->tRTP << 4);
888 reg |= (ctrl->tCKE << 8);
889 reg |= (ctrl->tWTR << 12);
890 reg |= (ctrl->tFAW << 16);
891 reg |= (ctrl->tWR << 24);
892 reg |= (3 << 30);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100893 printram("RAP [%x] = %x\n", 0x400 * channel + 0x4004, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700894 MCHBAR32(0x400 * channel + 0x4004) = reg;
895
896 // OTHP
897 addr = 0x400 * channel + 0x400c;
898 reg = 0;
899 reg |= ctrl->tXPDLL;
900 reg |= (ctrl->tXP << 5);
901 reg |= (ctrl->tAONPD << 8);
902 reg |= 0xa0000;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100903 printram("OTHP [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700904 MCHBAR32(addr) = reg;
905
906 MCHBAR32(0x400 * channel + 0x4014) = 0;
907
908 MCHBAR32(addr) |= 0x00020000;
909
910 // ODT stretch
911 reg = 0;
912
913 cpures = cpuid(0);
914 cpu = cpures.eax;
915 if (IS_IVY_CPU(cpu)
916 || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) {
917 stretch = 2;
918 addr = 0x400 * channel + 0x400c;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100919 printram("ODT stretch [%x] = %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700920 0x400 * channel + 0x400c, reg);
921 reg = MCHBAR32(addr);
922
923 if (((ctrl->rankmap[channel] & 3) == 0)
924 || (ctrl->rankmap[channel] & 0xc) == 0) {
925
926 // Rank 0 - operate on rank 2
927 reg = (reg & ~0xc0000) | (stretch << 18);
928
929 // Rank 2 - operate on rank 0
930 reg = (reg & ~0x30000) | (stretch << 16);
931
Patrick Rudolpha649a542016-01-17 18:32:06 +0100932 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700933 MCHBAR32(addr) = reg;
934 }
935
936 } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) {
937 stretch = 3;
938 addr = 0x400 * channel + 0x401c;
939 reg = MCHBAR32(addr);
940
941 if (((ctrl->rankmap[channel] & 3) == 0)
942 || (ctrl->rankmap[channel] & 0xc) == 0) {
943
944 // Rank 0 - operate on rank 2
945 reg = (reg & ~0x3000) | (stretch << 12);
946
947 // Rank 2 - operate on rank 0
948 reg = (reg & ~0xc00) | (stretch << 10);
949
Patrick Rudolpha649a542016-01-17 18:32:06 +0100950 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700951 MCHBAR32(addr) = reg;
952 }
953 } else {
954 stretch = 0;
955 }
956
957 // REFI
958 reg = 0;
959 val32 = ctrl->tREFI;
960 reg = (reg & ~0xffff) | val32;
961 val32 = ctrl->tRFC;
962 reg = (reg & ~0x1ff0000) | (val32 << 16);
963 val32 = (u32) (ctrl->tREFI * 9) / 1024;
964 reg = (reg & ~0xfe000000) | (val32 << 25);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100965 printram("REFI [%x] = %x\n", 0x400 * channel + 0x4298,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700966 reg);
967 MCHBAR32(0x400 * channel + 0x4298) = reg;
968
969 MCHBAR32(0x400 * channel + 0x4294) |= 0xff;
970
971 // SRFTP
972 reg = 0;
973 val32 = tDLLK;
974 reg = (reg & ~0xfff) | val32;
975 val32 = ctrl->tXSOffset;
976 reg = (reg & ~0xf000) | (val32 << 12);
977 val32 = tDLLK - ctrl->tXSOffset;
978 reg = (reg & ~0x3ff0000) | (val32 << 16);
979 val32 = ctrl->tMOD - 8;
980 reg = (reg & ~0xf0000000) | (val32 << 28);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100981 printram("SRFTP [%x] = %x\n", 0x400 * channel + 0x42a4,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700982 reg);
983 MCHBAR32(0x400 * channel + 0x42a4) = reg;
984 }
985}
986
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100987static void dram_dimm_mapping(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700988{
989 u32 reg, val32;
990 int channel;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100991 dimm_info *info = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700992
993 FOR_ALL_CHANNELS {
994 dimm_attr *dimmA = 0;
995 dimm_attr *dimmB = 0;
996 reg = 0;
997 val32 = 0;
998 if (info->dimm[channel][0].size_mb >=
999 info->dimm[channel][1].size_mb) {
1000 // dimm 0 is bigger, set it to dimmA
1001 dimmA = &info->dimm[channel][0];
1002 dimmB = &info->dimm[channel][1];
1003 reg |= (0 << 16);
1004 } else {
1005 // dimm 1 is bigger, set it to dimmA
1006 dimmA = &info->dimm[channel][1];
1007 dimmB = &info->dimm[channel][0];
1008 reg |= (1 << 16);
1009 }
1010 // dimmA
1011 if (dimmA && (dimmA->ranks > 0)) {
1012 val32 = dimmA->size_mb / 256;
1013 reg = (reg & ~0xff) | val32;
1014 val32 = dimmA->ranks - 1;
1015 reg = (reg & ~0x20000) | (val32 << 17);
1016 val32 = (dimmA->width / 8) - 1;
1017 reg = (reg & ~0x80000) | (val32 << 19);
1018 }
1019 // dimmB
1020 if (dimmB && (dimmB->ranks > 0)) {
1021 val32 = dimmB->size_mb / 256;
1022 reg = (reg & ~0xff00) | (val32 << 8);
1023 val32 = dimmB->ranks - 1;
1024 reg = (reg & ~0x40000) | (val32 << 18);
1025 val32 = (dimmB->width / 8) - 1;
1026 reg = (reg & ~0x100000) | (val32 << 20);
1027 }
1028 reg = (reg & ~0x200000) | (1 << 21); // rank interleave
1029 reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave
1030
1031 // Save MAD-DIMM register
1032 if ((dimmA && (dimmA->ranks > 0))
1033 || (dimmB && (dimmB->ranks > 0))) {
1034 ctrl->mad_dimm[channel] = reg;
1035 } else {
1036 ctrl->mad_dimm[channel] = 0;
1037 }
1038 }
1039}
1040
1041static void dram_dimm_set_mapping(ramctr_timing * ctrl)
1042{
1043 int channel;
1044 FOR_ALL_CHANNELS {
1045 MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
1046 }
1047}
1048
1049static void dram_zones(ramctr_timing * ctrl, int training)
1050{
1051 u32 reg, ch0size, ch1size;
1052 u8 val;
1053 reg = 0;
1054 val = 0;
1055 if (training) {
1056 ch0size = ctrl->channel_size_mb[0] ? 256 : 0;
1057 ch1size = ctrl->channel_size_mb[1] ? 256 : 0;
1058 } else {
1059 ch0size = ctrl->channel_size_mb[0];
1060 ch1size = ctrl->channel_size_mb[1];
1061 }
1062
1063 if (ch0size >= ch1size) {
1064 reg = MCHBAR32(0x5014);
1065 val = ch1size / 256;
1066 reg = (reg & ~0xff000000) | val << 24;
1067 reg = (reg & ~0xff0000) | (2 * val) << 16;
1068 MCHBAR32(0x5014) = reg;
1069 MCHBAR32(0x5000) = 0x24;
1070 } else {
1071 reg = MCHBAR32(0x5014);
1072 val = ch0size / 256;
1073 reg = (reg & ~0xff000000) | val << 24;
1074 reg = (reg & ~0xff0000) | (2 * val) << 16;
1075 MCHBAR32(0x5014) = reg;
1076 MCHBAR32(0x5000) = 0x21;
1077 }
1078}
1079
1080static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
1081{
1082 u32 reg, val, reclaim;
1083 u32 tom, gfxstolen, gttsize;
1084 size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase,
1085 tsegbase, mestolenbase;
1086 size_t tsegbasedelta, remapbase, remaplimit;
1087 uint16_t ggc;
1088
1089 mmiosize = 0x400;
1090
1091 ggc = pci_read_config16(NORTHBRIDGE, GGC);
1092 if (!(ggc & 2)) {
1093 gfxstolen = ((ggc >> 3) & 0x1f) * 32;
1094 gttsize = ((ggc >> 8) & 0x3);
1095 } else {
1096 gfxstolen = 0;
1097 gttsize = 0;
1098 }
1099
1100 tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
1101
1102 tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
1103
1104 mestolenbase = tom - me_uma_size;
1105
1106 toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
1107 tom - me_uma_size);
1108 gfxstolenbase = toludbase - gfxstolen;
1109 gttbase = gfxstolenbase - gttsize;
1110
1111 tsegbase = gttbase - tsegsize;
1112
1113 // Round tsegbase down to nearest address aligned to tsegsize
1114 tsegbasedelta = tsegbase & (tsegsize - 1);
1115 tsegbase &= ~(tsegsize - 1);
1116
1117 gttbase -= tsegbasedelta;
1118 gfxstolenbase -= tsegbasedelta;
1119 toludbase -= tsegbasedelta;
1120
1121 // Test if it is possible to reclaim a hole in the ram addressing
1122 if (tom - me_uma_size > toludbase) {
1123 // Reclaim is possible
1124 reclaim = 1;
1125 remapbase = MAX(4096, tom - me_uma_size);
1126 remaplimit =
1127 remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1;
1128 touudbase = remaplimit + 1;
1129 } else {
1130 // Reclaim not possible
1131 reclaim = 0;
1132 touudbase = tom - me_uma_size;
1133 }
1134
1135 // Update memory map in pci-e configuration space
Patrick Rudolpha649a542016-01-17 18:32:06 +01001136 printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001137
1138 // TOM (top of memory)
1139 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0);
1140 val = tom & 0xfff;
1141 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001142 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001143 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg);
1144
1145 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4);
1146 val = tom & 0xfffff000;
1147 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001148 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001149 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg);
1150
1151 // TOLUD (top of low used dram)
1152 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
1153 val = toludbase & 0xfff;
1154 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001155 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xbc, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001156 pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg);
1157
1158 // TOUUD LSB (top of upper usable dram)
1159 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
1160 val = touudbase & 0xfff;
1161 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001162 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001163 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg);
1164
1165 // TOUUD MSB
1166 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
1167 val = touudbase & 0xfffff000;
1168 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001169 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xac, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001170 pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg);
1171
1172 if (reclaim) {
1173 // REMAP BASE
1174 pcie_write_config32(PCI_DEV(0, 0, 0), 0x90, remapbase << 20);
1175 pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, remapbase >> 12);
1176
1177 // REMAP LIMIT
1178 pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
1179 pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
1180 }
1181 // TSEG
1182 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
1183 val = tsegbase & 0xfff;
1184 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001185 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001186 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg);
1187
1188 // GFX stolen memory
1189 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0);
1190 val = gfxstolenbase & 0xfff;
1191 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001192 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001193 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg);
1194
1195 // GTT stolen memory
1196 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4);
1197 val = gttbase & 0xfff;
1198 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001199 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001200 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
1201
1202 if (me_uma_size) {
1203 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
1204 val = (0x80000 - me_uma_size) & 0xfffff000;
1205 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001206 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x7c, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001207 pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg);
1208
1209 // ME base
1210 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70);
1211 val = mestolenbase & 0xfff;
1212 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001213 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x70, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001214 pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg);
1215
1216 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74);
1217 val = mestolenbase & 0xfffff000;
1218 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001219 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x74, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001220 pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg);
1221
1222 // ME mask
1223 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78);
1224 val = (0x80000 - me_uma_size) & 0xfff;
1225 reg = (reg & ~0xfff00000) | (val << 20);
1226 reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem
1227
1228 reg = (reg & ~0x800) | (1 << 11); // set ME memory enable
Patrick Rudolpha649a542016-01-17 18:32:06 +01001229 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x78, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001230 pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg);
1231 }
1232}
1233
1234static void dram_ioregs(ramctr_timing * ctrl)
1235{
1236 u32 reg, comp2;
1237
1238 int channel;
1239
1240 // IO clock
1241 FOR_ALL_CHANNELS {
1242 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
1243 }
1244
1245 // IO command
1246 FOR_ALL_CHANNELS {
1247 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
1248 }
1249
1250 // IO control
1251 FOR_ALL_POPULATED_CHANNELS {
1252 program_timings(ctrl, channel);
1253 }
1254
1255 // Rcomp
Patrick Rudolpha649a542016-01-17 18:32:06 +01001256 printram("RCOMP...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001257 reg = 0;
1258 while (reg == 0) {
1259 reg = MCHBAR32(0x5084) & 0x10000;
1260 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001261 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001262
1263 // Set comp2
1264 comp2 = get_COMP2(ctrl->tCK);
1265 MCHBAR32(0x3714) = comp2;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001266 printram("COMP2 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001267
1268 // Set comp1
1269 FOR_ALL_POPULATED_CHANNELS {
1270 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
1271 reg = (reg & ~0xe00) | (1 << 9); //odt
1272 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
1273 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
1274 MCHBAR32(0x1810 + channel * 0x100) = reg;
1275 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001276 printram("COMP1 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001277
Patrick Rudolpha649a542016-01-17 18:32:06 +01001278 printram("FORCE RCOMP and wait 20us...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001279 MCHBAR32(0x5f08) |= 0x100;
1280 udelay(20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001281 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001282}
1283
1284static void wait_428c(int channel)
1285{
1286 while (1) {
1287 if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
1288 return;
1289 }
1290}
1291
1292static void write_reset(ramctr_timing * ctrl)
1293{
1294 int channel, slotrank;
1295
1296 /* choose a populated channel. */
1297 channel = (ctrl->rankmap[0]) ? 0 : 1;
1298
1299 wait_428c(channel);
1300
1301 /* choose a populated rank. */
1302 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
1303
Patrick Rudolph371d2912015-10-09 13:33:25 +02001304 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001305 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1306 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01);
1307
1308 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1309 (slotrank << 24) | 0x60000);
1310
1311 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1312
1313 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001);
1314 wait_428c(channel);
1315}
1316
1317static void dram_jedecreset(ramctr_timing * ctrl)
1318{
1319 u32 reg, addr;
1320 int channel;
1321
1322 while (!(MCHBAR32(0x5084) & 0x10000)) ;
1323 do {
1324 reg = MCHBAR32(0x428c);
1325 } while ((reg & 0x14) == 0);
1326
1327 // Set state of memory controller
1328 reg = 0x112;
1329 MCHBAR32(0x5030) = reg;
1330 MCHBAR32(0x4ea0) = 0;
1331 reg |= 2; //ddr reset
1332 MCHBAR32(0x5030) = reg;
1333
1334 // Assert dimm reset signal
1335 reg = MCHBAR32(0x5030);
1336 reg &= ~0x2;
1337 MCHBAR32(0x5030) = reg;
1338
1339 // Wait 200us
1340 udelay(200);
1341
1342 // Deassert dimm reset signal
1343 MCHBAR32(0x5030) |= 2;
1344
1345 // Wait 500us
1346 udelay(500);
1347
1348 // Enable DCLK
1349 MCHBAR32(0x5030) |= 4;
1350
1351 // XXX Wait 20ns
1352 udelay(1);
1353
1354 FOR_ALL_CHANNELS {
1355 // Set valid rank CKE
1356 reg = 0;
1357 reg = (reg & ~0xf) | ctrl->rankmap[channel];
1358 addr = 0x400 * channel + 0x42a0;
1359 MCHBAR32(addr) = reg;
1360
1361 // Wait 10ns for ranks to settle
1362 //udelay(0.01);
1363
1364 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
1365 MCHBAR32(addr) = reg;
1366
1367 // Write reset using a NOP
1368 write_reset(ctrl);
1369 }
1370}
1371
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001372static odtmap get_ODT(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001373{
1374 /* Get ODT based on rankmap: */
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001375 int dimms_per_ch = (ctrl->rankmap[channel] & 1)
1376 + ((ctrl->rankmap[channel] >> 2) & 1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001377
1378 if (dimms_per_ch == 1) {
1379 return (const odtmap){60, 60};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001380 } else {
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001381 return (const odtmap){120, 30};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001382 }
1383}
1384
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001385static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001386 int reg, u32 val)
1387{
1388 wait_428c(channel);
1389
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001390 if (ctrl->rank_mirror[channel][slotrank]) {
1391 /* DDR3 Rank1 Address mirror
1392 * swap the following pins:
1393 * A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 */
1394 reg = ((reg >> 1) & 1) | ((reg << 1) & 2);
1395 val = (val & ~0x1f8) | ((val >> 1) & 0xa8)
1396 | ((val & 0xa8) << 1);
1397 }
1398
Patrick Rudolph371d2912015-10-09 13:33:25 +02001399 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001400 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000);
1401 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
1402 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1403 (slotrank << 24) | (reg << 20) | val | 0x60000);
1404 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1405
Patrick Rudolph371d2912015-10-09 13:33:25 +02001406 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001407 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000);
1408 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001);
1409 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
1410 (slotrank << 24) | (reg << 20) | val | 0x60000);
1411 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1412
Patrick Rudolph371d2912015-10-09 13:33:25 +02001413 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001414 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000);
1415 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1416 0x1001 | (ctrl->tMOD << 16));
1417 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1418 (slotrank << 24) | (reg << 20) | val | 0x60000);
1419 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1420 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
1421}
1422
1423static u32 make_mr0(ramctr_timing * ctrl, u8 rank)
1424{
1425 u16 mr0reg, mch_cas, mch_wr;
1426 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 +02001427
1428 /* DLL Reset - self clearing - set after CLK frequency has been changed */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001429 mr0reg = 0x100;
1430
1431 // Convert CAS to MCH register friendly
1432 if (ctrl->CAS < 12) {
1433 mch_cas = (u16) ((ctrl->CAS - 4) << 1);
1434 } else {
1435 mch_cas = (u16) (ctrl->CAS - 12);
1436 mch_cas = ((mch_cas << 1) | 0x1);
1437 }
1438
1439 // Convert tWR to MCH register friendly
1440 mch_wr = mch_wr_t[ctrl->tWR - 5];
1441
1442 mr0reg = (mr0reg & ~0x4) | (mch_cas & 0x1);
1443 mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3);
1444 mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001445
1446 // Precharge PD - Fast (desktop) 0x1 or slow (mobile) 0x0 - mostly power-saving feature
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001447 mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12);
1448 return mr0reg;
1449}
1450
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001451static void dram_mr0(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001452{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001453 write_mrreg(ctrl, channel, rank, 0,
1454 make_mr0(ctrl, rank));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001455}
1456
1457static u32 encode_odt(u32 odt)
1458{
1459 switch (odt) {
1460 case 30:
1461 return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4
1462 case 60:
1463 return (1 << 2); // RZQ/4
1464 case 120:
1465 return (1 << 6); // RZQ/2
1466 default:
1467 case 0:
1468 return 0;
1469 }
1470}
1471
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001472static u32 make_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001473{
1474 odtmap odt;
1475 u32 mr1reg;
1476
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001477 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001478 mr1reg = 0x2;
1479
1480 mr1reg |= encode_odt(odt.rttnom);
1481
1482 return mr1reg;
1483}
1484
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001485static void dram_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001486{
1487 u16 mr1reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001488
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001489 mr1reg = make_mr1(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001490
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001491 write_mrreg(ctrl, channel, rank, 1, mr1reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001492}
1493
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001494static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001495{
1496 u16 pasr, cwl, mr2reg;
1497 odtmap odt;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001498 int srt;
1499
1500 pasr = 0;
1501 cwl = ctrl->CWL - 5;
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001502 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001503
1504 srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh;
1505
1506 mr2reg = 0;
1507 mr2reg = (mr2reg & ~0x7) | pasr;
1508 mr2reg = (mr2reg & ~0x38) | (cwl << 3);
1509 mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6);
1510 mr2reg = (mr2reg & ~0x80) | (srt << 7);
1511 mr2reg |= (odt.rttwr / 60) << 9;
1512
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001513 write_mrreg(ctrl, channel, rank, 2, mr2reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001514}
1515
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001516static void dram_mr3(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001517{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001518 write_mrreg(ctrl, channel, rank, 3, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001519}
1520
1521static void dram_mrscommands(ramctr_timing * ctrl)
1522{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001523 u8 slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001524 u32 reg, addr;
1525 int channel;
1526
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001527 FOR_ALL_POPULATED_CHANNELS {
1528 FOR_ALL_POPULATED_RANKS {
1529 // MR2
1530 dram_mr2(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001531
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001532 // MR3
1533 dram_mr3(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001534
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001535 // MR1
1536 dram_mr1(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001537
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001538 // MR0
1539 dram_mr0(ctrl, slotrank, channel);
1540 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001541 }
1542
Patrick Rudolph371d2912015-10-09 13:33:25 +02001543 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001544 write32(DEFAULT_MCHBAR + 0x4e20, 0x7);
1545 write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001);
1546 write32(DEFAULT_MCHBAR + 0x4e00, 0x60002);
1547 write32(DEFAULT_MCHBAR + 0x4e10, 0);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001548
1549 /* DRAM command ZQCL */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001550 write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003);
1551 write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001);
1552 write32(DEFAULT_MCHBAR + 0x4e04, 0x60400);
1553 write32(DEFAULT_MCHBAR + 0x4e14, 0x288);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001554
1555 /* execute command queue on all channels ? */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001556 write32(DEFAULT_MCHBAR + 0x4e84, 0x40004);
1557
1558 // Drain
1559 FOR_ALL_CHANNELS {
1560 // Wait for ref drained
1561 wait_428c(channel);
1562 }
1563
1564 // Refresh enable
1565 MCHBAR32(0x5030) |= 8;
1566
1567 FOR_ALL_POPULATED_CHANNELS {
1568 addr = 0x400 * channel + 0x4020;
1569 reg = MCHBAR32(addr);
1570 reg &= ~0x200000;
1571 MCHBAR32(addr) = reg;
1572
1573 wait_428c(channel);
1574
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001575 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001576
1577 // Drain
1578 wait_428c(channel);
1579
Patrick Rudolph371d2912015-10-09 13:33:25 +02001580 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001581 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1582 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
1583 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001584 (slotrank << 24) | 0x60000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001585 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
1586 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1);
1587
1588 // Drain
1589 wait_428c(channel);
1590 }
1591}
1592
1593const u32 lane_registers[] = {
1594 0x0000, 0x0200, 0x0400, 0x0600,
1595 0x1000, 0x1200, 0x1400, 0x1600,
1596 0x0800
1597};
1598
1599static void program_timings(ramctr_timing * ctrl, int channel)
1600{
1601 u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028;
1602 int lane;
1603 int slotrank, slot;
1604 int full_shift = 0;
1605 u16 slot320c[NUM_SLOTS];
1606
1607 FOR_ALL_POPULATED_RANKS {
1608 if (full_shift < -ctrl->timings[channel][slotrank].val_320c)
1609 full_shift = -ctrl->timings[channel][slotrank].val_320c;
1610 }
1611
1612 for (slot = 0; slot < NUM_SLOTS; slot++)
1613 switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) {
1614 case 0:
1615 default:
1616 slot320c[slot] = 0x7f;
1617 break;
1618 case 1:
1619 slot320c[slot] =
1620 ctrl->timings[channel][2 * slot + 0].val_320c +
1621 full_shift;
1622 break;
1623 case 2:
1624 slot320c[slot] =
1625 ctrl->timings[channel][2 * slot + 1].val_320c +
1626 full_shift;
1627 break;
1628 case 3:
1629 slot320c[slot] =
1630 (ctrl->timings[channel][2 * slot].val_320c +
1631 ctrl->timings[channel][2 * slot +
1632 1].val_320c) / 2 +
1633 full_shift;
1634 break;
1635 }
1636
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001637 /* enable CMD XOVER */
1638 reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001639 reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
1640 reg32 |= (slot320c[1] & 0x7f) << 18;
1641 reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
1642
1643 MCHBAR32(0x320c + 0x100 * channel) = reg32;
1644
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001645 /* enable CLK XOVER */
1646 reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001647 reg_c18 = 0;
1648
1649 FOR_ALL_POPULATED_RANKS {
1650 int shift =
1651 ctrl->timings[channel][slotrank].val_320c + full_shift;
1652 int offset_val_c14;
1653 if (shift < 0)
1654 shift = 0;
1655 offset_val_c14 = ctrl->reg_c14_offset + shift;
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001656 /* set CLK phase shift */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001657 reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
1658 reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
1659 }
1660
1661 MCHBAR32(0xc14 + channel * 0x100) = reg_c14;
1662 MCHBAR32(0xc18 + channel * 0x100) = reg_c18;
1663
1664 reg_4028 = MCHBAR32(0x4028 + 0x400 * channel);
1665 reg_4028 &= 0xffff0000;
1666
1667 reg_4024 = 0;
1668
1669 FOR_ALL_POPULATED_RANKS {
1670 int post_timA_min_high = 7, post_timA_max_high = 0;
1671 int pre_timA_min_high = 7, pre_timA_max_high = 0;
1672 int shift_402x = 0;
1673 int shift =
1674 ctrl->timings[channel][slotrank].val_320c + full_shift;
1675
1676 if (shift < 0)
1677 shift = 0;
1678
1679 FOR_ALL_LANES {
1680 if (post_timA_min_high >
1681 ((ctrl->timings[channel][slotrank].lanes[lane].
1682 timA + shift) >> 6))
1683 post_timA_min_high =
1684 ((ctrl->timings[channel][slotrank].
1685 lanes[lane].timA + shift) >> 6);
1686 if (pre_timA_min_high >
1687 (ctrl->timings[channel][slotrank].lanes[lane].
1688 timA >> 6))
1689 pre_timA_min_high =
1690 (ctrl->timings[channel][slotrank].
1691 lanes[lane].timA >> 6);
1692 if (post_timA_max_high <
1693 ((ctrl->timings[channel][slotrank].lanes[lane].
1694 timA + shift) >> 6))
1695 post_timA_max_high =
1696 ((ctrl->timings[channel][slotrank].
1697 lanes[lane].timA + shift) >> 6);
1698 if (pre_timA_max_high <
1699 (ctrl->timings[channel][slotrank].lanes[lane].
1700 timA >> 6))
1701 pre_timA_max_high =
1702 (ctrl->timings[channel][slotrank].
1703 lanes[lane].timA >> 6);
1704 }
1705
1706 if (pre_timA_max_high - pre_timA_min_high <
1707 post_timA_max_high - post_timA_min_high)
1708 shift_402x = +1;
1709 else if (pre_timA_max_high - pre_timA_min_high >
1710 post_timA_max_high - post_timA_min_high)
1711 shift_402x = -1;
1712
1713 reg_4028 |=
1714 (ctrl->timings[channel][slotrank].val_4028 + shift_402x -
1715 post_timA_min_high) << (4 * slotrank);
1716 reg_4024 |=
1717 (ctrl->timings[channel][slotrank].val_4024 +
1718 shift_402x) << (8 * slotrank);
1719
1720 FOR_ALL_LANES {
1721 MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel +
1722 4 * slotrank)
1723 =
1724 (((ctrl->timings[channel][slotrank].lanes[lane].
1725 timA + shift) & 0x3f)
1726 |
1727 ((ctrl->timings[channel][slotrank].lanes[lane].
1728 rising + shift) << 8)
1729 |
1730 (((ctrl->timings[channel][slotrank].lanes[lane].
1731 timA + shift -
1732 (post_timA_min_high << 6)) & 0x1c0) << 10)
Patrick Rudolph0188b132016-02-10 19:16:34 +01001733 | ((ctrl->timings[channel][slotrank].lanes[lane].
1734 falling + shift) << 20));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001735
1736 MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel +
1737 4 * slotrank)
1738 =
1739 (((ctrl->timings[channel][slotrank].lanes[lane].
1740 timC + shift) & 0x3f)
1741 |
1742 (((ctrl->timings[channel][slotrank].lanes[lane].
1743 timB + shift) & 0x3f) << 8)
1744 |
1745 (((ctrl->timings[channel][slotrank].lanes[lane].
1746 timB + shift) & 0x1c0) << 9)
1747 |
1748 (((ctrl->timings[channel][slotrank].lanes[lane].
1749 timC + shift) & 0x40) << 13));
1750 }
1751 }
1752 MCHBAR32(0x4024 + 0x400 * channel) = reg_4024;
1753 MCHBAR32(0x4028 + 0x400 * channel) = reg_4028;
1754}
1755
1756static void test_timA(ramctr_timing * ctrl, int channel, int slotrank)
1757{
1758 wait_428c(channel);
1759
Patrick Rudolph371d2912015-10-09 13:33:25 +02001760 /* DRAM command MRS
1761 * write MR3 MPR enable
1762 * in this mode only RD and RDA are allowed
1763 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001764 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
1765 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1766 (0xc01 | (ctrl->tMOD << 16)));
1767 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1768 (slotrank << 24) | 0x360004);
1769 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1770
Patrick Rudolph371d2912015-10-09 13:33:25 +02001771 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001772 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
1773 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01);
1774 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24));
1775 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1776
Patrick Rudolph371d2912015-10-09 13:33:25 +02001777 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001778 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
1779 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1780 0x100f | ((ctrl->CAS + 36) << 16));
1781 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1782 (slotrank << 24) | 0x60000);
1783 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1784
Patrick Rudolph371d2912015-10-09 13:33:25 +02001785 /* DRAM command MRS
1786 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001787 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
1788 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
1789 (0xc01 | (ctrl->tMOD << 16)));
1790 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
1791 (slotrank << 24) | 0x360000);
1792 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
1793
1794 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
1795
1796 wait_428c(channel);
1797}
1798
1799static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank,
1800 int lane)
1801{
1802 u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA;
1803 return ((read32
1804 (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 +
1805 ((timA / 32) & 1) * 4)
1806 >> (timA % 32)) & 1);
1807}
1808
1809struct run {
1810 int middle;
1811 int end;
1812 int start;
1813 int all;
1814 int length;
1815};
1816
1817static struct run get_longest_zero_run(int *seq, int sz)
1818{
1819 int i, ls;
1820 int bl = 0, bs = 0;
1821 struct run ret;
1822
1823 ls = 0;
1824 for (i = 0; i < 2 * sz; i++)
1825 if (seq[i % sz]) {
1826 if (i - ls > bl) {
1827 bl = i - ls;
1828 bs = ls;
1829 }
1830 ls = i + 1;
1831 }
1832 if (bl == 0) {
1833 ret.middle = sz / 2;
1834 ret.start = 0;
1835 ret.end = sz;
1836 ret.all = 1;
1837 return ret;
1838 }
1839
1840 ret.start = bs % sz;
1841 ret.end = (bs + bl - 1) % sz;
1842 ret.middle = (bs + (bl - 1) / 2) % sz;
1843 ret.length = bl;
1844 ret.all = 0;
1845
1846 return ret;
1847}
1848
1849static void discover_timA_coarse(ramctr_timing * ctrl, int channel,
1850 int slotrank, int *upperA)
1851{
1852 int timA;
1853 int statistics[NUM_LANES][128];
1854 int lane;
1855
1856 for (timA = 0; timA < 128; timA++) {
1857 FOR_ALL_LANES {
1858 ctrl->timings[channel][slotrank].lanes[lane].timA = timA;
1859 }
1860 program_timings(ctrl, channel);
1861
1862 test_timA(ctrl, channel, slotrank);
1863
1864 FOR_ALL_LANES {
1865 statistics[lane][timA] =
1866 !does_lane_work(ctrl, channel, slotrank, lane);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001867 printram("Astat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001868 channel, slotrank, lane, timA,
1869 statistics[lane][timA]);
1870 }
1871 }
1872 FOR_ALL_LANES {
1873 struct run rn = get_longest_zero_run(statistics[lane], 128);
1874 ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle;
1875 upperA[lane] = rn.end;
1876 if (upperA[lane] < rn.middle)
1877 upperA[lane] += 128;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001878 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001879 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001880 printram("Aend: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001881 lane, upperA[lane]);
1882 }
1883}
1884
1885static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
1886 int *upperA)
1887{
1888 int timA_delta;
1889 int statistics[NUM_LANES][51];
1890 int lane, i;
1891
1892 memset(statistics, 0, sizeof(statistics));
1893
1894 for (timA_delta = -25; timA_delta <= 25; timA_delta++) {
1895 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
1896 timA = upperA[lane] + timA_delta + 0x40;
1897 program_timings(ctrl, channel);
1898
1899 for (i = 0; i < 100; i++) {
1900 test_timA(ctrl, channel, slotrank);
1901 FOR_ALL_LANES {
1902 statistics[lane][timA_delta + 25] +=
1903 does_lane_work(ctrl, channel, slotrank,
1904 lane);
1905 }
1906 }
1907 }
1908 FOR_ALL_LANES {
1909 int last_zero, first_all;
1910
1911 for (last_zero = -25; last_zero <= 25; last_zero++)
1912 if (statistics[lane][last_zero + 25])
1913 break;
1914 last_zero--;
1915 for (first_all = -25; first_all <= 25; first_all++)
1916 if (statistics[lane][first_all + 25] == 100)
1917 break;
1918
1919 printram("lane %d: %d, %d\n", lane, last_zero,
1920 first_all);
1921
1922 ctrl->timings[channel][slotrank].lanes[lane].timA =
1923 (last_zero + first_all) / 2 + upperA[lane];
Patrick Rudolpha649a542016-01-17 18:32:06 +01001924 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001925 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
1926 }
1927}
1928
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001929static int discover_402x(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001930 int *upperA)
1931{
1932 int works[NUM_LANES];
1933 int lane;
1934 while (1) {
1935 int all_works = 1, some_works = 0;
1936 program_timings(ctrl, channel);
1937 test_timA(ctrl, channel, slotrank);
1938 FOR_ALL_LANES {
1939 works[lane] =
1940 !does_lane_work(ctrl, channel, slotrank, lane);
1941 if (works[lane])
1942 some_works = 1;
1943 else
1944 all_works = 0;
1945 }
1946 if (all_works)
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001947 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001948 if (!some_works) {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001949 if (ctrl->timings[channel][slotrank].val_4024 < 2) {
1950 printk(BIOS_EMERG, "402x discovery failed (1): %d, %d\n",
1951 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001952 return MAKE_ERR;
1953 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001954 ctrl->timings[channel][slotrank].val_4024 -= 2;
1955 printram("4024 -= 2;\n");
1956 continue;
1957 }
1958 ctrl->timings[channel][slotrank].val_4028 += 2;
1959 printram("4028 += 2;\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001960 if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) {
1961 printk(BIOS_EMERG, "402x discovery failed (2): %d, %d\n",
1962 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001963 return MAKE_ERR;
1964 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001965 FOR_ALL_LANES if (works[lane]) {
1966 ctrl->timings[channel][slotrank].lanes[lane].timA +=
1967 128;
1968 upperA[lane] += 128;
1969 printram("increment %d, %d, %d\n", channel,
1970 slotrank, lane);
1971 }
1972 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001973 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001974}
1975
1976struct timA_minmax {
1977 int timA_min_high, timA_max_high;
1978};
1979
1980static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1981 struct timA_minmax *mnmx)
1982{
1983 int lane;
1984 mnmx->timA_min_high = 7;
1985 mnmx->timA_max_high = 0;
1986
1987 FOR_ALL_LANES {
1988 if (mnmx->timA_min_high >
1989 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1990 mnmx->timA_min_high =
1991 (ctrl->timings[channel][slotrank].lanes[lane].
1992 timA >> 6);
1993 if (mnmx->timA_max_high <
1994 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1995 mnmx->timA_max_high =
1996 (ctrl->timings[channel][slotrank].lanes[lane].
1997 timA >> 6);
1998 }
1999}
2000
2001static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
2002 struct timA_minmax *mnmx)
2003{
2004 struct timA_minmax post;
2005 int shift_402x = 0;
2006
2007 /* Get changed maxima. */
2008 pre_timA_change(ctrl, channel, slotrank, &post);
2009
2010 if (mnmx->timA_max_high - mnmx->timA_min_high <
2011 post.timA_max_high - post.timA_min_high)
2012 shift_402x = +1;
2013 else if (mnmx->timA_max_high - mnmx->timA_min_high >
2014 post.timA_max_high - post.timA_min_high)
2015 shift_402x = -1;
2016 else
2017 shift_402x = 0;
2018
2019 ctrl->timings[channel][slotrank].val_4028 += shift_402x;
2020 ctrl->timings[channel][slotrank].val_4024 += shift_402x;
2021 printram("4024 += %d;\n", shift_402x);
2022 printram("4028 += %d;\n", shift_402x);
2023}
2024
Patrick Rudolph371d2912015-10-09 13:33:25 +02002025/* Compensate the skew between DQS and DQs.
2026 * To ease PCB design a small skew between Data Strobe signals and
2027 * Data Signals is allowed.
2028 * The controller has to measure and compensate this skew for every byte-lane.
2029 * By delaying either all DQs signals or DQS signal, a full phase
2030 * shift can be introduced.
2031 * It is assumed that one byte-lane's DQs signals have the same routing delay.
2032 *
2033 * To measure the actual skew, the DRAM is placed in "read leveling" mode.
2034 * In read leveling mode the DRAM-chip outputs an alternating periodic pattern.
2035 * The memory controller iterates over all possible values to do a full phase shift
2036 * and issues read commands.
2037 * With DQS and DQs in phase the data read is expected to alternate on every byte:
2038 * 0xFF 0x00 0xFF ...
2039 * Once the controller has detected this pattern a bit in the result register is
2040 * set for the current phase shift.
2041 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002042static int read_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002043{
2044 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002045 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002046
2047 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002048 int all_high, some_high;
2049 int upperA[NUM_LANES];
2050 struct timA_minmax mnmx;
2051
2052 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002053
2054 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002055 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2056 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2057 0xc01 | (ctrl->tRP << 16));
2058 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2059 (slotrank << 24) | 0x60400);
2060 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2061 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2062
2063 write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001);
2064
2065 ctrl->timings[channel][slotrank].val_4028 = 4;
2066 ctrl->timings[channel][slotrank].val_4024 = 55;
2067 program_timings(ctrl, channel);
2068
2069 discover_timA_coarse(ctrl, channel, slotrank, upperA);
2070
2071 all_high = 1;
2072 some_high = 0;
2073 FOR_ALL_LANES {
2074 if (ctrl->timings[channel][slotrank].lanes[lane].
2075 timA >= 0x40)
2076 some_high = 1;
2077 else
2078 all_high = 0;
2079 }
2080
2081 if (all_high) {
2082 ctrl->timings[channel][slotrank].val_4028--;
2083 printram("4028--;\n");
2084 FOR_ALL_LANES {
2085 ctrl->timings[channel][slotrank].lanes[lane].
2086 timA -= 0x40;
2087 upperA[lane] -= 0x40;
2088
2089 }
2090 } else if (some_high) {
2091 ctrl->timings[channel][slotrank].val_4024++;
2092 ctrl->timings[channel][slotrank].val_4028++;
2093 printram("4024++;\n");
2094 printram("4028++;\n");
2095 }
2096
2097 program_timings(ctrl, channel);
2098
2099 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2100
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002101 err = discover_402x(ctrl, channel, slotrank, upperA);
2102 if (err)
2103 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002104
2105 post_timA_change(ctrl, channel, slotrank, &mnmx);
2106 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2107
2108 discover_timA_fine(ctrl, channel, slotrank, upperA);
2109
2110 post_timA_change(ctrl, channel, slotrank, &mnmx);
2111 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2112
2113 FOR_ALL_LANES {
2114 ctrl->timings[channel][slotrank].lanes[lane].timA -= mnmx.timA_min_high * 0x40;
2115 }
2116 ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high;
2117 printram("4028 -= %d;\n", mnmx.timA_min_high);
2118
2119 post_timA_change(ctrl, channel, slotrank, &mnmx);
2120
2121 printram("4/8: %d, %d, %x, %x\n", channel, slotrank,
2122 ctrl->timings[channel][slotrank].val_4024,
2123 ctrl->timings[channel][slotrank].val_4028);
2124
Patrick Rudolpha649a542016-01-17 18:32:06 +01002125 printram("final results:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002126 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01002127 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002128 lane,
2129 ctrl->timings[channel][slotrank].lanes[lane].timA);
2130
2131 write32(DEFAULT_MCHBAR + 0x3400, 0);
2132
Patrick Rudolph9b515682015-10-09 13:43:51 +02002133 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002134 }
2135
2136 FOR_ALL_POPULATED_CHANNELS {
2137 program_timings(ctrl, channel);
2138 }
2139 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2140 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
2141 + 4 * lane, 0);
2142 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002143 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002144}
2145
2146static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
2147{
2148 int lane;
2149
2150 FOR_ALL_LANES {
2151 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0);
2152 read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane);
2153 }
2154
2155 wait_428c(channel);
2156
Patrick Rudolph371d2912015-10-09 13:33:25 +02002157 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002158 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2159 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2160 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
2161 | 4 | (ctrl->tRCD << 16));
2162
2163 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2164 (slotrank << 24) | (6 << 16));
2165
2166 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
2167
Patrick Rudolph371d2912015-10-09 13:33:25 +02002168 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002169 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2170 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001);
2171 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2172 (slotrank << 24) | 8);
2173 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2174
Patrick Rudolph371d2912015-10-09 13:33:25 +02002175 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002176 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2177 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4);
2178 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2179 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2180
Patrick Rudolph371d2912015-10-09 13:33:25 +02002181 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002182 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2183 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2184 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2185 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2186 (slotrank << 24) | 8);
2187 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2188
2189 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2190
2191 wait_428c(channel);
2192
Patrick Rudolph371d2912015-10-09 13:33:25 +02002193 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002194 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2195 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2196 0xc01 | (ctrl->tRP << 16));
2197 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2198 (slotrank << 24) | 0x60400);
2199 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2200
Patrick Rudolph371d2912015-10-09 13:33:25 +02002201 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002202 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2203 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2204 (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10)
2205 | 8 | (ctrl->CAS << 16));
2206
2207 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2208 (slotrank << 24) | 0x60000);
2209
2210 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244);
2211
Patrick Rudolph371d2912015-10-09 13:33:25 +02002212 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002213 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2214 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2215 0x40011f4 | (max(ctrl->tRTP, 8) << 16));
2216 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2217 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2218
Patrick Rudolph371d2912015-10-09 13:33:25 +02002219 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002220 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2221 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2222 0xc01 | (ctrl->tRP << 16));
2223 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2224 (slotrank << 24) | 0x60400);
2225 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2226 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2227 wait_428c(channel);
2228}
2229
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002230static int discover_timC(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002231{
2232 int timC;
2233 int statistics[NUM_LANES][MAX_TIMC + 1];
2234 int lane;
2235
2236 wait_428c(channel);
2237
Patrick Rudolph371d2912015-10-09 13:33:25 +02002238 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002239 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2240 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2241 0xc01 | (ctrl->tRP << 16));
2242 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2243 (slotrank << 24) | 0x60400);
2244 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2245 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2246
2247 for (timC = 0; timC <= MAX_TIMC; timC++) {
2248 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
2249 timC = timC;
2250 program_timings(ctrl, channel);
2251
2252 test_timC(ctrl, channel, slotrank);
2253
2254 FOR_ALL_LANES {
2255 statistics[lane][timC] =
2256 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2257 0x400 * channel);
2258 printram("Cstat: %d, %d, %d, %x, %x\n",
2259 channel, slotrank, lane, timC,
2260 statistics[lane][timC]);
2261 }
2262 }
2263 FOR_ALL_LANES {
2264 struct run rn =
2265 get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
2266 ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002267 if (rn.all) {
2268 printk(BIOS_EMERG, "timC discovery failed: %d, %d, %d\n",
2269 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002270 return MAKE_ERR;
2271 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002272 printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002273 lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
2274 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002275 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002276}
2277
2278static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
2279{
2280 int channel, ret = 0;
2281 FOR_ALL_POPULATED_CHANNELS if (channel < target_channel)
2282 ret++;
2283 return ret;
2284}
2285
2286static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b)
2287{
2288 unsigned j;
2289 unsigned channel_offset =
2290 get_precedening_channels(ctrl, channel) * 0x40;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002291 for (j = 0; j < 16; j++)
2292 write32((void *)(0x04000000 + channel_offset + 4 * j), j & 2 ? b : a);
2293 sfence();
2294}
2295
2296static int num_of_channels(const ramctr_timing * ctrl)
2297{
2298 int ret = 0;
2299 int channel;
2300 FOR_ALL_POPULATED_CHANNELS ret++;
2301 return ret;
2302}
2303
2304static void fill_pattern1(ramctr_timing * ctrl, int channel)
2305{
2306 unsigned j;
2307 unsigned channel_offset =
2308 get_precedening_channels(ctrl, channel) * 0x40;
2309 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2310 for (j = 0; j < 16; j++)
2311 write32((void *)(0x04000000 + channel_offset + j * 4), 0xffffffff);
2312 for (j = 0; j < 16; j++)
2313 write32((void *)(0x04000000 + channel_offset + channel_step + j * 4), 0);
2314 sfence();
2315}
2316
2317static void precharge(ramctr_timing * ctrl)
2318{
2319 int channel, slotrank, lane;
2320
2321 FOR_ALL_POPULATED_CHANNELS {
2322 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2323 ctrl->timings[channel][slotrank].lanes[lane].falling =
2324 16;
2325 ctrl->timings[channel][slotrank].lanes[lane].rising =
2326 16;
Patrick Rudolpha649a542016-01-17 18:32:06 +01002327 }
2328
2329 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002330
2331 FOR_ALL_POPULATED_RANKS {
2332 wait_428c(channel);
2333
Patrick Rudolph371d2912015-10-09 13:33:25 +02002334 /* DRAM command MRS
2335 * write MR3 MPR enable
2336 * in this mode only RD and RDA are allowed
2337 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002338 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2339 0x1f000);
2340 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2341 0xc01 | (ctrl->tMOD << 16));
2342 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2343 (slotrank << 24) | 0x360004);
2344 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2345
Patrick Rudolph371d2912015-10-09 13:33:25 +02002346 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002347 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2348 0x1f105);
2349 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2350 0x4041003);
2351 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2352 (slotrank << 24) | 0);
2353 write32(DEFAULT_MCHBAR + 0x4214 + 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 + 0x4228 + 0x400 * channel,
2357 0x1f105);
2358 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2359 0x1001 | ((ctrl->CAS + 8) << 16));
2360 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2361 (slotrank << 24) | 0x60000);
2362 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2363
Patrick Rudolph371d2912015-10-09 13:33:25 +02002364 /* DRAM command MRS
2365 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002366 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2367 0x1f000);
2368 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2369 0xc01 | (ctrl->tMOD << 16));
2370 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2371 (slotrank << 24) | 0x360000);
2372 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2373 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2374 0xc0001);
2375
2376 wait_428c(channel);
2377 }
2378
2379 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2380 ctrl->timings[channel][slotrank].lanes[lane].falling =
2381 48;
2382 ctrl->timings[channel][slotrank].lanes[lane].rising =
2383 48;
2384 }
2385
2386 program_timings(ctrl, channel);
2387
2388 FOR_ALL_POPULATED_RANKS {
2389 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002390 /* DRAM command MRS
2391 * write MR3 MPR enable
2392 * in this mode only RD and RDA are allowed
2393 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002394 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2395 0x1f000);
2396 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2397 0xc01 | (ctrl->tMOD << 16));
2398 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2399 (slotrank << 24) | 0x360004);
2400 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2401
Patrick Rudolph371d2912015-10-09 13:33:25 +02002402 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002403 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2404 0x1f105);
2405 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2406 0x4041003);
2407 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2408 (slotrank << 24) | 0);
2409 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2410
Patrick Rudolph371d2912015-10-09 13:33:25 +02002411 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002412 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2413 0x1f105);
2414 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2415 0x1001 | ((ctrl->CAS + 8) << 16));
2416 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2417 (slotrank << 24) | 0x60000);
2418 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2419
Patrick Rudolph371d2912015-10-09 13:33:25 +02002420 /* DRAM command MRS
2421 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002422 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2423 0x1f000);
2424 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2425 0xc01 | (ctrl->tMOD << 16));
2426
2427 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2428 (slotrank << 24) | 0x360000);
2429 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2430
2431 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2432 0xc0001);
2433 wait_428c(channel);
2434 }
2435 }
2436}
2437
2438static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
2439{
Patrick Rudolph371d2912015-10-09 13:33:25 +02002440 /* enable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002441 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002442 0x80 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002443
2444 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002445 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002446 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207);
2447 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2448 0x8000c01 | ((ctrl->CWL + ctrl->tWLO) << 16));
2449 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2450 8 | (slotrank << 24));
2451 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2452
Patrick Rudolph371d2912015-10-09 13:33:25 +02002453 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002454 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107);
2455 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2456 0x4000c01 | ((ctrl->CAS + 38) << 16));
2457 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2458 (slotrank << 24) | 4);
2459 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2460
2461 write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001);
2462 wait_428c(channel);
2463
Patrick Rudolph371d2912015-10-09 13:33:25 +02002464 /* disable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002465 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002466 0x1080 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002467}
2468
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002469static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002470{
2471 int timB;
2472 int statistics[NUM_LANES][128];
2473 int lane;
2474
2475 write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2));
2476
2477 for (timB = 0; timB < 128; timB++) {
2478 FOR_ALL_LANES {
2479 ctrl->timings[channel][slotrank].lanes[lane].timB = timB;
2480 }
2481 program_timings(ctrl, channel);
2482
2483 test_timB(ctrl, channel, slotrank);
2484
2485 FOR_ALL_LANES {
2486 statistics[lane][timB] =
2487 !((read32
2488 (DEFAULT_MCHBAR + lane_registers[lane] +
2489 channel * 0x100 + 4 + ((timB / 32) & 1) * 4)
2490 >> (timB % 32)) & 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002491 printram("Bstat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002492 channel, slotrank, lane, timB,
2493 statistics[lane][timB]);
2494 }
2495 }
2496 FOR_ALL_LANES {
2497 struct run rn = get_longest_zero_run(statistics[lane], 128);
Patrick Rudolphd912f1d2016-02-15 20:07:42 +01002498 /* timC is a direct function of timB's 6 LSBs.
2499 * Some tests increments the value of timB by a small value,
2500 * which might cause the 6bit value to overflow, if it's close
2501 * to 0x3F. Increment the value by a small offset if it's likely
2502 * to overflow, to make sure it won't overflow while running
2503 * tests and bricks the system due to a non matching timC.
2504 *
2505 * TODO: find out why some tests (edge write discovery)
2506 * increment timB. */
2507 if ((rn.start & 0x3F) == 0x3E)
2508 rn.start += 2;
2509 else if ((rn.start & 0x3F) == 0x3F)
2510 rn.start += 1;
Vladimir Serbinenko3141eac2016-01-29 19:42:02 +01002511 ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002512 if (rn.all) {
2513 printk(BIOS_EMERG, "timB discovery failed: %d, %d, %d\n",
2514 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002515 return MAKE_ERR;
2516 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002517 printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002518 lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
2519 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002520 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002521}
2522
2523static int get_timB_high_adjust(u64 val)
2524{
2525 int i;
2526
2527 /* good */
2528 if (val == 0xffffffffffffffffLL)
2529 return 0;
2530
2531 if (val >= 0xf000000000000000LL) {
2532 /* needs negative adjustment */
2533 for (i = 0; i < 8; i++)
2534 if (val << (8 * (7 - i) + 4))
2535 return -i;
2536 } else {
2537 /* needs positive adjustment */
2538 for (i = 0; i < 8; i++)
2539 if (val >> (8 * (7 - i) + 4))
2540 return i;
2541 }
2542 return 8;
2543}
2544
2545static void adjust_high_timB(ramctr_timing * ctrl)
2546{
2547 int channel, slotrank, lane, old;
2548 write32(DEFAULT_MCHBAR + 0x3400, 0x200);
2549 FOR_ALL_POPULATED_CHANNELS {
2550 fill_pattern1(ctrl, channel);
2551 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 1);
2552 }
2553 FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
2554
2555 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001);
2556
2557 wait_428c(channel);
2558
Patrick Rudolph371d2912015-10-09 13:33:25 +02002559 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002560 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2561 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2562 0xc01 | (ctrl->tRCD << 16));
2563 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2564 (slotrank << 24) | 0x60000);
2565 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2566
Patrick Rudolph371d2912015-10-09 13:33:25 +02002567 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002568 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2569 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01);
2570 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2571 (slotrank << 24) | 0x8);
2572 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2573
Patrick Rudolph371d2912015-10-09 13:33:25 +02002574 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002575 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2576 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003);
2577 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2578 (slotrank << 24));
2579 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2);
2580
Patrick Rudolph371d2912015-10-09 13:33:25 +02002581 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002582 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2583 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2584 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2585 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2586 (slotrank << 24) | 0x8);
2587 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2588
2589 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2590
2591 wait_428c(channel);
2592
Patrick Rudolph371d2912015-10-09 13:33:25 +02002593 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002594 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2595 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2596 0xc01 | ((ctrl->tRP) << 16));
2597 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2598 (slotrank << 24) | 0x60400);
2599 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2600
Patrick Rudolph371d2912015-10-09 13:33:25 +02002601 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002602 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2603 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2604 0xc01 | ((ctrl->tRCD) << 16));
2605 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2606 (slotrank << 24) | 0x60000);
2607 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2608
Patrick Rudolph371d2912015-10-09 13:33:25 +02002609 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002610 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105);
2611 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2612 0x4000c01 |
2613 ((ctrl->tRP +
2614 ctrl->timings[channel][slotrank].val_4024 +
2615 ctrl->timings[channel][slotrank].val_4028) << 16));
2616 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2617 (slotrank << 24) | 0x60008);
2618 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2619
2620 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
2621 wait_428c(channel);
2622 FOR_ALL_LANES {
2623 u64 res =
2624 read32(DEFAULT_MCHBAR + lane_registers[lane] +
2625 0x100 * channel + 4);
2626 res |=
2627 ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] +
2628 0x100 * channel + 8)) << 32;
2629 old = ctrl->timings[channel][slotrank].lanes[lane].timB;
2630 ctrl->timings[channel][slotrank].lanes[lane].timB +=
2631 get_timB_high_adjust(res) * 64;
2632
Patrick Rudolpha649a542016-01-17 18:32:06 +01002633 printram("High adjust %d:%016llx\n", lane, res);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002634 printram("Bval+: %d, %d, %d, %x -> %x\n", channel,
2635 slotrank, lane, old,
2636 ctrl->timings[channel][slotrank].lanes[lane].
2637 timB);
2638 }
2639 }
2640 write32(DEFAULT_MCHBAR + 0x3400, 0);
2641}
2642
2643static void write_op(ramctr_timing * ctrl, int channel)
2644{
2645 int slotrank;
2646
2647 wait_428c(channel);
2648
2649 /* choose an existing rank. */
2650 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2651
Patrick Rudolph371d2912015-10-09 13:33:25 +02002652 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002653 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2654 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2655
2656 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2657 (slotrank << 24) | 0x60000);
2658
2659 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2660
2661 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2662 wait_428c(channel);
2663}
2664
Patrick Rudolph371d2912015-10-09 13:33:25 +02002665/* Compensate the skew between CMD/ADDR/CLK and DQ/DQS lanes.
2666 * DDR3 adopted the fly-by topology. The data and strobes signals reach
2667 * the chips at different times with respect to command, address and
2668 * clock signals.
2669 * By delaying either all DQ/DQs or all CMD/ADDR/CLK signals, a full phase
2670 * shift can be introduced.
2671 * It is assumed that the CLK/ADDR/CMD signals have the same routing delay.
2672 *
2673 * To find the required phase shift the DRAM is placed in "write leveling" mode.
2674 * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
2675 * sampled value on the data lanes (DQs).
2676 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002677static int write_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002678{
2679 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002680 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002681
2682 FOR_ALL_POPULATED_CHANNELS
2683 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
2684 read32(DEFAULT_MCHBAR + 0x4008 +
2685 0x400 * channel) | 0x8000000);
2686
2687 FOR_ALL_POPULATED_CHANNELS {
2688 write_op(ctrl, channel);
2689 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2690 read32(DEFAULT_MCHBAR + 0x4020 +
2691 0x400 * channel) | 0x200000);
2692 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002693
2694 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002695 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2696 FOR_ALL_POPULATED_CHANNELS {
2697 write_op(ctrl, channel);
2698 }
2699
Patrick Rudolph371d2912015-10-09 13:33:25 +02002700 /* enable write leveling on all ranks
2701 * disable all DQ outputs
2702 * only NOP is allowed in this mode */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002703 FOR_ALL_CHANNELS
2704 FOR_ALL_POPULATED_RANKS
2705 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002706 make_mr1(ctrl, slotrank, channel) | 0x1080);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002707
2708 write32(DEFAULT_MCHBAR + 0x3400, 0x108052);
2709
Patrick Rudolph9b515682015-10-09 13:43:51 +02002710 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002711
Patrick Rudolph371d2912015-10-09 13:33:25 +02002712 /* set any valid value for timB, it gets corrected later */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002713 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2714 err = discover_timB(ctrl, channel, slotrank);
2715 if (err)
2716 return err;
2717 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002718
Patrick Rudolph371d2912015-10-09 13:33:25 +02002719 /* disable write leveling on all ranks */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002720 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2721 write_mrreg(ctrl, channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002722 slotrank, 1, make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002723
2724 write32(DEFAULT_MCHBAR + 0x3400, 0);
2725
2726 FOR_ALL_POPULATED_CHANNELS
2727 wait_428c(channel);
2728
Patrick Rudolph371d2912015-10-09 13:33:25 +02002729 /* refresh enable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002730 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8);
2731
2732 FOR_ALL_POPULATED_CHANNELS {
2733 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2734 ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 +
2735 0x400 * channel));
2736 read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel);
2737 wait_428c(channel);
2738
Patrick Rudolph371d2912015-10-09 13:33:25 +02002739 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002740 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2741 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
2742 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000);
2743 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2744
2745 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2746 wait_428c(channel);
2747 }
2748
Patrick Rudolph9b515682015-10-09 13:43:51 +02002749 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002750
2751 printram("CPE\n");
2752 precharge(ctrl);
2753 printram("CPF\n");
2754
2755 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2756 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2757 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2758 0);
2759 }
2760
2761 FOR_ALL_POPULATED_CHANNELS {
2762 fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555);
2763 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
2764 }
2765
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002766 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2767 err = discover_timC(ctrl, channel, slotrank);
2768 if (err)
2769 return err;
2770 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002771
2772 FOR_ALL_POPULATED_CHANNELS
2773 program_timings(ctrl, channel);
2774
Patrick Rudolph371d2912015-10-09 13:33:25 +02002775 /* measure and adjust timB timings */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002776 adjust_high_timB(ctrl);
2777
2778 FOR_ALL_POPULATED_CHANNELS
2779 program_timings(ctrl, channel);
2780
2781 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2782 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2783 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2784 0);
2785 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002786 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002787}
2788
2789static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
2790{
2791 struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank];
2792 int timC_delta;
2793 int lanes_ok = 0;
2794 int ctr = 0;
2795 int lane;
2796
2797 for (timC_delta = -5; timC_delta <= 5; timC_delta++) {
2798 FOR_ALL_LANES {
2799 ctrl->timings[channel][slotrank].lanes[lane].timC =
2800 saved_rt.lanes[lane].timC + timC_delta;
2801 }
2802 program_timings(ctrl, channel);
2803 FOR_ALL_LANES {
2804 write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0);
2805 }
2806
2807 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2808
2809 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002810 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002811 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2812 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2813 ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10)
2814 | 8 | (ctrl->tRCD << 16));
2815
2816 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2817 (slotrank << 24) | ctr | 0x60000);
2818
2819 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002820 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002821 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
2822 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2823 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16));
2824 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2825 (slotrank << 24));
2826 write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd);
2827 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42);
2828
Patrick Rudolph371d2912015-10-09 13:33:25 +02002829 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002830 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2831 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2832 0x4001020 | (max(ctrl->tRTP, 8) << 16));
2833 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2834 (slotrank << 24));
2835 write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd);
2836 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42);
2837
Patrick Rudolph371d2912015-10-09 13:33:25 +02002838 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002839 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2840 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001);
2841 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2842 (slotrank << 24) | 0x60400);
2843 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2844
2845 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2846 wait_428c(channel);
2847 FOR_ALL_LANES {
2848 u32 r32 =
2849 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2850 0x400 * channel);
2851
2852 if (r32 == 0)
2853 lanes_ok |= 1 << lane;
2854 }
2855 ctr++;
2856 if (lanes_ok == ((1 << NUM_LANES) - 1))
2857 break;
2858 }
2859
2860 ctrl->timings[channel][slotrank] = saved_rt;
2861
2862 printram("3lanes: %x\n", lanes_ok);
2863 return lanes_ok != ((1 << NUM_LANES) - 1);
2864}
2865
2866#include "raminit_patterns.h"
2867
2868static void fill_pattern5(ramctr_timing * ctrl, int channel, int patno)
2869{
2870 unsigned i, j;
2871 unsigned channel_offset =
2872 get_precedening_channels(ctrl, channel) * 0x40;
2873 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2874
2875 if (patno) {
2876 u8 base8 = 0x80 >> ((patno - 1) % 8);
2877 u32 base = base8 | (base8 << 8) | (base8 << 16) | (base8 << 24);
2878 for (i = 0; i < 32; i++) {
2879 for (j = 0; j < 16; j++) {
2880 u32 val = use_base[patno - 1][i] & (1 << (j / 2)) ? base : 0;
2881 if (invert[patno - 1][i] & (1 << (j / 2)))
2882 val = ~val;
2883 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2884 j * 4), val);
2885 }
2886 }
2887
2888 } else {
2889 for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) {
2890 for (j = 0; j < 16; j++)
2891 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2892 j * 4), pattern[i][j]);
2893 }
2894 sfence();
2895 }
2896}
2897
2898static void reprogram_320c(ramctr_timing * ctrl)
2899{
2900 int channel, slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002901
2902 FOR_ALL_POPULATED_CHANNELS {
2903 wait_428c(channel);
2904
2905 /* choose an existing rank. */
2906 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2907
Patrick Rudolph371d2912015-10-09 13:33:25 +02002908 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002909 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2910 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2911
2912 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2913 (slotrank << 24) | 0x60000);
2914
2915 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2916
2917 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2918 wait_428c(channel);
2919 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2920 read32(DEFAULT_MCHBAR + 0x4020 +
2921 0x400 * channel) | 0x200000);
2922 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002923
2924 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002925 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2926 FOR_ALL_POPULATED_CHANNELS {
2927 wait_428c(channel);
2928
2929 /* choose an existing rank. */
2930 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2931
Patrick Rudolph371d2912015-10-09 13:33:25 +02002932 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002933 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2934 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2935
2936 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2937 (slotrank << 24) | 0x60000);
2938
2939 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2940
2941 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2942 wait_428c(channel);
2943 }
2944
2945 /* jedec reset */
2946 dram_jedecreset(ctrl);
2947 /* mrs commands. */
2948 dram_mrscommands(ctrl);
2949
Patrick Rudolph9b515682015-10-09 13:43:51 +02002950 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002951}
2952
2953#define MIN_C320C_LEN 13
2954
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002955static int try_cmd_stretch(ramctr_timing *ctrl, int cmd_stretch)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002956{
2957 struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
2958 int channel, slotrank;
2959 int c320c;
2960 int stat[NUM_SLOTRANKS][256];
2961
2962 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2963 saved_timings[channel][slotrank] = ctrl->timings[channel][slotrank];
2964 }
2965
2966 FOR_ALL_POPULATED_CHANNELS {
2967 ctrl->cmd_stretch[channel] = cmd_stretch;
2968 }
2969
2970 FOR_ALL_POPULATED_CHANNELS
2971 MCHBAR32(0x4004 + 0x400 * channel) =
2972 ctrl->tRRD
2973 | (ctrl->tRTP << 4)
2974 | (ctrl->tCKE << 8)
2975 | (ctrl->tWTR << 12)
2976 | (ctrl->tFAW << 16)
2977 | (ctrl->tWR << 24)
2978 | (ctrl->cmd_stretch[channel] << 30);
2979
2980
2981 FOR_ALL_CHANNELS {
2982 int delta = 0;
2983 if (ctrl->cmd_stretch[channel] == 2)
2984 delta = 2;
2985 else if (ctrl->cmd_stretch[channel] == 0)
2986 delta = 4;
2987
2988 FOR_ALL_POPULATED_RANKS {
2989 ctrl->timings[channel][slotrank].val_4024 -= delta;
2990 }
2991 }
2992
2993 FOR_ALL_POPULATED_CHANNELS {
2994 for (c320c = -127; c320c <= 127; c320c++) {
2995 FOR_ALL_POPULATED_RANKS {
2996 ctrl->timings[channel][slotrank].val_320c = c320c;
2997 }
2998 program_timings(ctrl, channel);
2999 reprogram_320c(ctrl);
3000 FOR_ALL_POPULATED_RANKS {
3001 stat[slotrank][c320c + 127] =
3002 test_320c(ctrl, channel, slotrank);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003003 printram("3stat: %d, %d, %d: %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003004 channel, slotrank, c320c,
3005 stat[slotrank][c320c + 127]);
3006 }
3007 }
3008 FOR_ALL_POPULATED_RANKS {
3009 struct run rn =
3010 get_longest_zero_run(stat[slotrank], 255);
3011 ctrl->timings[channel][slotrank].val_320c =
3012 rn.middle - 127;
3013 printram("3val: %d, %d: %d\n", channel,
3014 slotrank,
3015 ctrl->timings[channel][slotrank].val_320c);
3016 if (rn.all || rn.length < MIN_C320C_LEN) {
3017 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3018 ctrl->timings[channel][slotrank] = saved_timings[channel][slotrank];
3019 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003020 return MAKE_ERR;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003021 }
3022 }
3023 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003024 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003025}
3026
Patrick Rudolph371d2912015-10-09 13:33:25 +02003027/* Adjust CMD phase shift and try multiple command rates.
3028 * A command rate of 2T doubles the time needed for address and
3029 * command decode. */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003030static int command_training(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003031{
3032 int channel;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003033 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003034
3035 FOR_ALL_POPULATED_CHANNELS {
3036 fill_pattern5(ctrl, channel, 0);
3037 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
3038 }
3039
3040 /* try command rate 1T and 2T */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003041 err = try_cmd_stretch(ctrl, 0);
3042 if (err) {
3043 err = try_cmd_stretch(ctrl, 2);
3044 if (err) {
3045 printk(BIOS_EMERG, "c320c discovery failed\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003046 return err;
3047 }
3048 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003049
3050 FOR_ALL_POPULATED_CHANNELS {
3051 program_timings(ctrl, channel);
3052 }
3053
3054 reprogram_320c(ctrl);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003055 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003056}
3057
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003058static int discover_edges_real(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003059 int *edges)
3060{
3061 int edge;
3062 int statistics[NUM_LANES][MAX_EDGE_TIMING + 1];
3063 int lane;
3064
3065 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3066 FOR_ALL_LANES {
3067 ctrl->timings[channel][slotrank].lanes[lane].rising =
3068 edge;
3069 ctrl->timings[channel][slotrank].lanes[lane].falling =
3070 edge;
3071 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003072 program_timings(ctrl, channel);
3073
3074 FOR_ALL_LANES {
3075 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3076 4 * lane, 0);
3077 read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane +
3078 0x4140);
3079 }
3080
3081 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003082 /* DRAM command MRS
3083 * write MR3 MPR enable
3084 * in this mode only RD and RDA are allowed
3085 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003086 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
3087 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3088 (0xc01 | (ctrl->tMOD << 16)));
3089 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3090 (slotrank << 24) | 0x360004);
3091 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3092
Patrick Rudolph371d2912015-10-09 13:33:25 +02003093 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003094 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
3095 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4);
3096 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3097 (slotrank << 24));
3098 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3099
Patrick Rudolph371d2912015-10-09 13:33:25 +02003100 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003101 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
3102 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3103 0x1001 | ((ctrl->CAS + 8) << 16));
3104 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3105 (slotrank << 24) | 0x60000);
3106 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3107
Patrick Rudolph371d2912015-10-09 13:33:25 +02003108 /* DRAM command MRS
3109 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003110 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
3111 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3112 (0xc01 | (ctrl->tMOD << 16)));
3113 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3114 (slotrank << 24) | 0x360000);
3115 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3116
3117 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
3118
3119 wait_428c(channel);
3120
3121 FOR_ALL_LANES {
3122 statistics[lane][edge] =
3123 read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3124 lane * 4);
3125 }
3126 }
3127 FOR_ALL_LANES {
3128 struct run rn =
3129 get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
3130 edges[lane] = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003131 if (rn.all) {
3132 printk(BIOS_EMERG, "edge discovery failed: %d, %d, %d\n",
3133 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003134 return MAKE_ERR;
3135 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003136 printram("eval %d, %d, %d: %02x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003137 lane, edges[lane]);
3138 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003139 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003140}
3141
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003142static int discover_edges(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003143{
3144 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3145 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3146 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003147 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003148
3149 write32(DEFAULT_MCHBAR + 0x3400, 0);
3150
Patrick Rudolph9b515682015-10-09 13:43:51 +02003151 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003152
3153 FOR_ALL_POPULATED_CHANNELS FOR_ALL_LANES {
3154 write32(DEFAULT_MCHBAR + 4 * lane +
3155 0x400 * channel + 0x4080, 0);
3156 }
3157
3158 FOR_ALL_POPULATED_CHANNELS {
3159 fill_pattern0(ctrl, channel, 0, 0);
3160 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3161 FOR_ALL_LANES {
3162 read32(DEFAULT_MCHBAR + 0x400 * channel +
3163 lane * 4 + 0x4140);
3164 }
3165
3166 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3167 ctrl->timings[channel][slotrank].lanes[lane].falling =
3168 16;
3169 ctrl->timings[channel][slotrank].lanes[lane].rising =
3170 16;
3171 }
3172
3173 program_timings(ctrl, channel);
3174
3175 FOR_ALL_POPULATED_RANKS {
3176 wait_428c(channel);
3177
Patrick Rudolph371d2912015-10-09 13:33:25 +02003178 /* DRAM command MRS
3179 * MR3 enable MPR
3180 * write MR3 MPR enable
3181 * in this mode only RD and RDA are allowed
3182 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003183 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3184 0x1f000);
3185 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3186 0xc01 | (ctrl->tMOD << 16));
3187 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3188 (slotrank << 24) | 0x360004);
3189 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3190
Patrick Rudolph371d2912015-10-09 13:33:25 +02003191 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003192 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3193 0x1f105);
3194 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3195 0x4041003);
3196 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3197 (slotrank << 24) | 0);
3198 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3199
Patrick Rudolph371d2912015-10-09 13:33:25 +02003200 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003201 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3202 0x1f105);
3203 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3204 0x1001 | ((ctrl->CAS + 8) << 16));
3205 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3206 (slotrank << 24) | 0x60000);
3207 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3208
Patrick Rudolph371d2912015-10-09 13:33:25 +02003209 /* DRAM command MRS
3210 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003211 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3212 0x1f000);
3213 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3214 0xc01 | (ctrl->tMOD << 16));
3215 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3216 (slotrank << 24) | 0x360000);
3217 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3218 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3219 0xc0001);
3220
3221 wait_428c(channel);
3222 }
3223
Patrick Rudolph371d2912015-10-09 13:33:25 +02003224 /* XXX: check any measured value ? */
3225
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003226 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3227 ctrl->timings[channel][slotrank].lanes[lane].falling =
3228 48;
3229 ctrl->timings[channel][slotrank].lanes[lane].rising =
3230 48;
3231 }
3232
3233 program_timings(ctrl, channel);
3234
3235 FOR_ALL_POPULATED_RANKS {
3236 wait_428c(channel);
3237
Patrick Rudolph371d2912015-10-09 13:33:25 +02003238 /* DRAM command MRS
3239 * MR3 enable MPR
3240 * write MR3 MPR enable
3241 * in this mode only RD and RDA are allowed
3242 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003243 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3244 0x1f000);
3245 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3246 0xc01 | (ctrl->tMOD << 16));
3247 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3248 (slotrank << 24) | 0x360004);
3249 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3250
Patrick Rudolph371d2912015-10-09 13:33:25 +02003251 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003252 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3253 0x1f105);
3254 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3255 0x4041003);
3256 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3257 (slotrank << 24) | 0);
3258 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3259
Patrick Rudolph371d2912015-10-09 13:33:25 +02003260 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003261 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3262 0x1f105);
3263 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3264 0x1001 | ((ctrl->CAS + 8) << 16));
3265 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3266 (slotrank << 24) | 0x60000);
3267 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3268
Patrick Rudolph371d2912015-10-09 13:33:25 +02003269 /* DRAM command MRS
3270 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003271 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3272 0x1f000);
3273 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3274 0xc01 | (ctrl->tMOD << 16));
3275 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3276 (slotrank << 24) | 0x360000);
3277 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3278
3279 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3280 0xc0001);
3281 wait_428c(channel);
3282 }
3283
Patrick Rudolph371d2912015-10-09 13:33:25 +02003284 /* XXX: check any measured value ? */
3285
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003286 FOR_ALL_LANES {
3287 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel +
3288 lane * 4,
3289 ~read32(DEFAULT_MCHBAR + 0x4040 +
3290 0x400 * channel + lane * 4) & 0xff);
3291 }
3292
3293 fill_pattern0(ctrl, channel, 0, 0xffffffff);
3294 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3295 }
3296
3297 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3298 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003299 printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003300
3301 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003302 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003303 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003304 if (err)
3305 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003306 }
3307
3308 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003309 printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003310
3311 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003312 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003313 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003314 if (err)
3315 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003316 }
3317
3318 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3319
3320 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3321 ctrl->timings[channel][slotrank].lanes[lane].falling =
3322 falling_edges[channel][slotrank][lane];
3323 ctrl->timings[channel][slotrank].lanes[lane].rising =
3324 rising_edges[channel][slotrank][lane];
3325 }
3326
3327 FOR_ALL_POPULATED_CHANNELS {
3328 program_timings(ctrl, channel);
3329 }
3330
3331 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3332 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3333 0);
3334 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003335 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003336}
3337
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003338static int discover_edges_write_real(ramctr_timing *ctrl, int channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003339 int slotrank, int *edges)
3340{
3341 int edge;
3342 u32 raw_statistics[MAX_EDGE_TIMING + 1];
3343 int statistics[MAX_EDGE_TIMING + 1];
3344 const int reg3000b24[] = { 0, 0xc, 0x2c };
3345 int lane, i;
3346 int lower[NUM_LANES];
3347 int upper[NUM_LANES];
3348 int pat;
3349
3350 FOR_ALL_LANES {
3351 lower[lane] = 0;
3352 upper[lane] = MAX_EDGE_TIMING;
3353 }
3354
3355 for (i = 0; i < 3; i++) {
3356 write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel,
3357 reg3000b24[i] << 24);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003358 printram("[%x] = 0x%08x\n",
3359 0x3000 + 0x100 * channel, reg3000b24[i] << 24);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003360 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3361 fill_pattern5(ctrl, channel, pat);
3362 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003363 printram("using pattern %d\n", pat);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003364 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3365 FOR_ALL_LANES {
3366 ctrl->timings[channel][slotrank].lanes[lane].
3367 rising = edge;
3368 ctrl->timings[channel][slotrank].lanes[lane].
3369 falling = edge;
3370 }
3371 program_timings(ctrl, channel);
3372
3373 FOR_ALL_LANES {
3374 write32(DEFAULT_MCHBAR + 0x4340 +
3375 0x400 * channel + 4 * lane, 0);
3376 read32(DEFAULT_MCHBAR + 0x400 * channel +
3377 4 * lane + 0x4140);
3378 }
3379 wait_428c(channel);
3380
Patrick Rudolph371d2912015-10-09 13:33:25 +02003381 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003382 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3383 0x1f006);
3384 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3385 0x4 | (ctrl->tRCD << 16)
3386 | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) <<
3387 10));
3388 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3389 (slotrank << 24) | 0x60000);
3390 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel,
3391 0x240);
3392
Patrick Rudolph371d2912015-10-09 13:33:25 +02003393 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003394 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3395 0x1f201);
3396 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3397 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) <<
3398 16));
3399 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3400 (slotrank << 24));
3401 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel,
3402 0x242);
3403
Patrick Rudolph371d2912015-10-09 13:33:25 +02003404 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003405 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3406 0x1f105);
3407 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3408 0x4005020 | (max(ctrl->tRTP, 8) << 16));
3409 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3410 (slotrank << 24));
3411 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel,
3412 0x242);
3413
Patrick Rudolph371d2912015-10-09 13:33:25 +02003414 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003415 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3416 0x1f002);
3417 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3418 0xc01 | (ctrl->tRP << 16));
3419 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3420 (slotrank << 24) | 0x60400);
3421 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3422
3423 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3424 0xc0001);
3425 wait_428c(channel);
3426 FOR_ALL_LANES {
3427 read32(DEFAULT_MCHBAR + 0x4340 +
3428 0x400 * channel + lane * 4);
3429 }
3430
3431 raw_statistics[edge] =
3432 MCHBAR32(0x436c + 0x400 * channel);
3433 }
3434 FOR_ALL_LANES {
3435 struct run rn;
3436 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++)
3437 statistics[edge] =
3438 ! !(raw_statistics[edge] & (1 << lane));
3439 rn = get_longest_zero_run(statistics,
3440 MAX_EDGE_TIMING + 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003441 printram("edges: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003442 channel, slotrank, i, rn.start, rn.middle,
3443 rn.end, rn.start + ctrl->edge_offset[i],
3444 rn.end - ctrl->edge_offset[i]);
3445 lower[lane] =
3446 max(rn.start + ctrl->edge_offset[i], lower[lane]);
3447 upper[lane] =
3448 min(rn.end - ctrl->edge_offset[i], upper[lane]);
3449 edges[lane] = (lower[lane] + upper[lane]) / 2;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003450 if (rn.all || (lower[lane] > upper[lane])) {
3451 printk(BIOS_EMERG, "edge write discovery failed: %d, %d, %d\n",
3452 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003453 return MAKE_ERR;
3454 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003455 }
3456 }
3457 }
3458
3459 write32(DEFAULT_MCHBAR + 0x3000, 0);
3460 printram("CPA\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003461 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003462}
3463
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003464static int discover_edges_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003465{
3466 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3467 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3468 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003469 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003470
3471 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3472 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003473 printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003474
3475 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003476 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003477 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003478 if (err)
3479 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003480 }
3481
3482 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003483 printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003484
3485 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003486 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003487 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003488 if (err)
3489 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003490 }
3491
3492 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3493
3494 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3495 ctrl->timings[channel][slotrank].lanes[lane].falling =
3496 falling_edges[channel][slotrank][lane];
3497 ctrl->timings[channel][slotrank].lanes[lane].rising =
3498 rising_edges[channel][slotrank][lane];
3499 }
3500
3501 FOR_ALL_POPULATED_CHANNELS
3502 program_timings(ctrl, channel);
3503
3504 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3505 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3506 0);
3507 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003508 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003509}
3510
3511static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
3512{
3513 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003514 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003515 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
3516 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3517 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD)
3518 << 10) | (ctrl->tRCD << 16) | 4);
3519 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3520 (slotrank << 24) | 0x60000);
3521 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
3522
Patrick Rudolph371d2912015-10-09 13:33:25 +02003523 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003524 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
3525 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3526 0x80011e0 |
3527 ((ctrl->tWTR + ctrl->CWL + 8) << 16));
3528 write32(DEFAULT_MCHBAR + 0x4204 +
3529 0x400 * channel, (slotrank << 24));
3530 write32(DEFAULT_MCHBAR + 0x4214 +
3531 0x400 * channel, 0x242);
3532
Patrick Rudolph371d2912015-10-09 13:33:25 +02003533 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003534 write32(DEFAULT_MCHBAR + 0x4228 +
3535 0x400 * channel, 0x1f105);
3536 write32(DEFAULT_MCHBAR + 0x4238 +
3537 0x400 * channel,
3538 0x40011e0 | (max(ctrl->tRTP, 8) << 16));
3539 write32(DEFAULT_MCHBAR + 0x4208 +
3540 0x400 * channel, (slotrank << 24));
3541 write32(DEFAULT_MCHBAR + 0x4218 +
3542 0x400 * channel, 0x242);
3543
Patrick Rudolph371d2912015-10-09 13:33:25 +02003544 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003545 write32(DEFAULT_MCHBAR + 0x422c +
3546 0x400 * channel, 0x1f002);
3547 write32(DEFAULT_MCHBAR + 0x423c +
3548 0x400 * channel,
3549 0x1001 | (ctrl->tRP << 16));
3550 write32(DEFAULT_MCHBAR + 0x420c +
3551 0x400 * channel,
3552 (slotrank << 24) | 0x60400);
3553 write32(DEFAULT_MCHBAR + 0x421c +
3554 0x400 * channel, 0);
3555
3556 write32(DEFAULT_MCHBAR + 0x4284 +
3557 0x400 * channel, 0xc0001);
3558 wait_428c(channel);
3559}
3560
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003561static int discover_timC_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003562{
3563 const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
3564 int i, pat;
3565
3566 int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3567 int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3568 int channel, slotrank, lane;
3569
3570 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3571 lower[channel][slotrank][lane] = 0;
3572 upper[channel][slotrank][lane] = MAX_TIMC;
3573 }
3574
3575 write32(DEFAULT_MCHBAR + 0x4ea8, 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003576 printram("discover timC write:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003577
3578 for (i = 0; i < 3; i++)
3579 FOR_ALL_POPULATED_CHANNELS {
3580 write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100),
3581 (rege3c_b24[i] << 24)
3582 | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100))
3583 & ~0x3f000000));
3584 udelay(2);
3585 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3586 FOR_ALL_POPULATED_RANKS {
3587 int timC;
3588 u32 raw_statistics[MAX_TIMC + 1];
3589 int statistics[MAX_TIMC + 1];
3590
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003591 /* Make sure rn.start < rn.end */
3592 statistics[MAX_TIMC] = 1;
3593
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003594 fill_pattern5(ctrl, channel, pat);
3595 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003596 for (timC = 0; timC < MAX_TIMC; timC++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003597 FOR_ALL_LANES
3598 ctrl->timings[channel][slotrank].lanes[lane].timC = timC;
3599 program_timings(ctrl, channel);
3600
3601 test_timC_write (ctrl, channel, slotrank);
3602
3603 raw_statistics[timC] =
3604 MCHBAR32(0x436c + 0x400 * channel);
3605 }
3606 FOR_ALL_LANES {
3607 struct run rn;
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003608 for (timC = 0; timC < MAX_TIMC; timC++)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003609 statistics[timC] =
3610 !!(raw_statistics[timC] &
3611 (1 << lane));
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003612
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003613 rn = get_longest_zero_run(statistics,
3614 MAX_TIMC + 1);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003615 if (rn.all) {
3616 printk(BIOS_EMERG, "timC write discovery failed: %d, %d, %d\n",
3617 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003618 return MAKE_ERR;
3619 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003620 printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003621 channel, slotrank, i, rn.start,
3622 rn.middle, rn.end,
3623 rn.start + ctrl->timC_offset[i],
3624 rn.end - ctrl->timC_offset[i]);
3625 lower[channel][slotrank][lane] =
3626 max(rn.start + ctrl->timC_offset[i],
3627 lower[channel][slotrank][lane]);
3628 upper[channel][slotrank][lane] =
3629 min(rn.end - ctrl->timC_offset[i],
3630 upper[channel][slotrank][lane]);
3631
3632 }
3633 }
3634 }
3635 }
3636
3637 FOR_ALL_CHANNELS {
3638 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3639 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3640 ~0x3f000000));
3641 udelay(2);
3642 }
3643
3644 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3645
3646 printram("CPB\n");
3647
3648 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
Patrick Rudolpha649a542016-01-17 18:32:06 +01003649 printram("timC %d, %d, %d: %x\n", channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003650 slotrank, lane,
3651 (lower[channel][slotrank][lane] +
3652 upper[channel][slotrank][lane]) / 2);
3653 ctrl->timings[channel][slotrank].lanes[lane].timC =
3654 (lower[channel][slotrank][lane] +
3655 upper[channel][slotrank][lane]) / 2;
3656 }
3657 FOR_ALL_POPULATED_CHANNELS {
3658 program_timings(ctrl, channel);
3659 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003660 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003661}
3662
3663static void normalize_training(ramctr_timing * ctrl)
3664{
3665 int channel, slotrank, lane;
3666 int mat = 0;
3667
3668 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3669 int delta;
3670 FOR_ALL_LANES mat =
3671 max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat);
3672 delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028;
3673 ctrl->timings[channel][slotrank].val_4024 += delta;
3674 ctrl->timings[channel][slotrank].val_4028 += delta;
3675 }
3676
3677 FOR_ALL_POPULATED_CHANNELS {
3678 program_timings(ctrl, channel);
3679 }
3680}
3681
3682static void write_controller_mr(ramctr_timing * ctrl)
3683{
3684 int channel, slotrank;
3685
3686 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3687 write32(DEFAULT_MCHBAR + 0x0004 + (channel << 8) +
3688 lane_registers[slotrank], make_mr0(ctrl, slotrank));
3689 write32(DEFAULT_MCHBAR + 0x0008 + (channel << 8) +
Patrick Rudolph7e513d12016-01-10 14:22:34 +01003690 lane_registers[slotrank],
3691 make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003692 }
3693}
3694
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003695static int channel_test(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003696{
3697 int channel, slotrank, lane;
3698
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003699 slotrank = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003700 FOR_ALL_POPULATED_CHANNELS
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003701 if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) {
3702 printk(BIOS_EMERG, "Mini channel test failed (1): %d\n",
3703 channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003704 return MAKE_ERR;
3705 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003706 FOR_ALL_POPULATED_CHANNELS {
3707 fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
3708
3709 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3710 }
3711
3712 for (slotrank = 0; slotrank < 4; slotrank++)
3713 FOR_ALL_CHANNELS
3714 if (ctrl->rankmap[channel] & (1 << slotrank)) {
3715 FOR_ALL_LANES {
3716 write32(DEFAULT_MCHBAR + (0x4f40 + 4 * lane), 0);
3717 write32(DEFAULT_MCHBAR + (0x4d40 + 4 * lane), 0);
3718 }
3719 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003720 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003721 write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
3722 write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10), 0x0028a004);
3723 write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
3724 0x00060000 | (slotrank << 24));
3725 write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003726 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003727 write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
3728 write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281064);
3729 write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
3730 0x00000000 | (slotrank << 24));
3731 write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003732 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003733 write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f105);
3734 write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x04281064);
3735 write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
3736 0x00000000 | (slotrank << 24));
3737 write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003738 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003739 write32(DEFAULT_MCHBAR + 0x422c + (channel << 10), 0x0001f002);
3740 write32(DEFAULT_MCHBAR + 0x423c + (channel << 10), 0x00280c01);
3741 write32(DEFAULT_MCHBAR + 0x420c + (channel << 10),
3742 0x00060400 | (slotrank << 24));
3743 write32(DEFAULT_MCHBAR + 0x421c + (channel << 10), 0x00000240);
3744 write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
3745 wait_428c(channel);
3746 FOR_ALL_LANES
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003747 if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) {
3748 printk(BIOS_EMERG, "Mini channel test failed (2): %d, %d, %d\n",
3749 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003750 return MAKE_ERR;
3751 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003752 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003753 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003754}
3755
3756static void set_scrambling_seed(ramctr_timing * ctrl)
3757{
3758 int channel;
3759
3760 /* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
3761 I don't think so. */
3762 static u32 seeds[NUM_CHANNELS][3] = {
3763 {0x00009a36, 0xbafcfdcf, 0x46d1ab68},
3764 {0x00028bfa, 0x53fe4b49, 0x19ed5483}
3765 };
3766 FOR_ALL_POPULATED_CHANNELS {
3767 MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
3768 write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
3769 write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
3770 write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
3771 }
3772}
3773
3774static void set_4f8c(void)
3775{
3776 struct cpuid_result cpures;
3777 u32 cpu;
3778
3779 cpures = cpuid(0);
3780 cpu = (cpures.eax);
3781 if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) {
3782 MCHBAR32(0x4f8c) = 0x141D1519;
3783 } else {
3784 MCHBAR32(0x4f8c) = 0x551D1519;
3785 }
3786}
3787
3788static void prepare_training(ramctr_timing * ctrl)
3789{
3790 int channel;
3791
3792 FOR_ALL_POPULATED_CHANNELS {
3793 // Always drive command bus
3794 MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000;
3795 }
3796
3797 udelay(1);
3798
3799 FOR_ALL_POPULATED_CHANNELS {
3800 wait_428c(channel);
3801 }
3802}
3803
3804static void set_4008c(ramctr_timing * ctrl)
3805{
3806 int channel, slotrank;
3807 u32 reg;
3808 FOR_ALL_POPULATED_CHANNELS {
3809 u32 b20, b4_8_12;
3810 int min_320c = 10000;
3811 int max_320c = -10000;
3812
3813 FOR_ALL_POPULATED_RANKS {
3814 max_320c = max(ctrl->timings[channel][slotrank].val_320c, max_320c);
3815 min_320c = min(ctrl->timings[channel][slotrank].val_320c, min_320c);
3816 }
3817
3818 if (max_320c - min_320c > 51)
3819 b20 = 0;
3820 else
3821 b20 = ctrl->ref_card_offset[channel];
3822
3823 if (ctrl->reg_320c_range_threshold < max_320c - min_320c)
3824 b4_8_12 = 0x3330;
3825 else
3826 b4_8_12 = 0x2220;
3827
3828 reg = read32(DEFAULT_MCHBAR + 0x400c + (channel << 10));
3829 write32(DEFAULT_MCHBAR + 0x400c + (channel << 10),
3830 (reg & 0xFFF0FFFF)
3831 | (ctrl->ref_card_offset[channel] << 16)
3832 | (ctrl->ref_card_offset[channel] << 18));
3833 write32(DEFAULT_MCHBAR + 0x4008 + (channel << 10),
3834 0x0a000000
3835 | (b20 << 20)
3836 | ((ctrl->ref_card_offset[channel] + 2) << 16)
3837 | b4_8_12);
3838 }
3839}
3840
3841static void set_42a0(ramctr_timing * ctrl)
3842{
3843 int channel;
3844 FOR_ALL_POPULATED_CHANNELS {
3845 write32(DEFAULT_MCHBAR + (0x42a0 + 0x400 * channel),
3846 0x00001000 | ctrl->rankmap[channel]);
3847 MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK
3848 }
3849}
3850
3851static int encode_5d10(int ns)
3852{
3853 return (ns + 499) / 500;
3854}
3855
3856/* FIXME: values in this function should be hardware revision-dependent. */
3857static void final_registers(ramctr_timing * ctrl)
3858{
3859 int channel;
3860 int t1_cycles = 0, t1_ns = 0, t2_ns;
3861 int t3_ns;
3862 u32 r32;
3863
3864 write32(DEFAULT_MCHBAR + 0x4cd4, 0x00000046);
3865
3866 write32(DEFAULT_MCHBAR + 0x400c, (read32(DEFAULT_MCHBAR + 0x400c) & 0xFFFFCFFF) | 0x1000); // OK
3867 write32(DEFAULT_MCHBAR + 0x440c, (read32(DEFAULT_MCHBAR + 0x440c) & 0xFFFFCFFF) | 0x1000); // OK
3868 write32(DEFAULT_MCHBAR + 0x4cb0, 0x00000740);
3869 write32(DEFAULT_MCHBAR + 0x4380, 0x00000aaa); // OK
3870 write32(DEFAULT_MCHBAR + 0x4780, 0x00000aaa); // OK
3871 write32(DEFAULT_MCHBAR + 0x4f88, 0x5f7003ff); // OK
3872 write32(DEFAULT_MCHBAR + 0x5064, 0x00073000 | ctrl->reg_5064b0); // OK
3873
3874 FOR_ALL_CHANNELS {
3875 switch (ctrl->rankmap[channel]) {
3876 /* Unpopulated channel. */
3877 case 0:
3878 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0);
3879 break;
3880 /* Only single-ranked dimms. */
3881 case 1:
3882 case 4:
3883 case 5:
3884 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x373131);
3885 break;
3886 /* Dual-ranked dimms present. */
3887 default:
3888 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x9b6ea1);
3889 break;
3890 }
3891 }
3892
3893 write32 (DEFAULT_MCHBAR + 0x5880, 0xca9171e5);
3894 write32 (DEFAULT_MCHBAR + 0x5888,
3895 (read32 (DEFAULT_MCHBAR + 0x5888) & ~0xffffff) | 0xe4d5d0);
3896 write32 (DEFAULT_MCHBAR + 0x58a8, read32 (DEFAULT_MCHBAR + 0x58a8) & ~0x1f);
3897 write32 (DEFAULT_MCHBAR + 0x4294,
3898 (read32 (DEFAULT_MCHBAR + 0x4294) & ~0x30000)
3899 | (1 << 16));
3900 write32 (DEFAULT_MCHBAR + 0x4694,
3901 (read32 (DEFAULT_MCHBAR + 0x4694) & ~0x30000)
3902 | (1 << 16));
3903
3904 MCHBAR32(0x5030) |= 1; // OK
3905 MCHBAR32(0x5030) |= 0x80; // OK
3906 MCHBAR32(0x5f18) = 0xfa; // OK
3907
3908 /* Find a populated channel. */
3909 FOR_ALL_POPULATED_CHANNELS
3910 break;
3911
3912 t1_cycles = ((read32(DEFAULT_MCHBAR + 0x4290 + channel * 0x400) >> 8) & 0xff);
3913 r32 = read32(DEFAULT_MCHBAR + 0x5064);
3914 if (r32 & 0x20000)
3915 t1_cycles += (r32 & 0xfff);
3916 t1_cycles += (read32(DEFAULT_MCHBAR + channel * 0x400 + 0x42a4) & 0xfff);
3917 t1_ns = t1_cycles * ctrl->tCK / 256 + 544;
3918 if (!(r32 & 0x20000))
3919 t1_ns += 500;
3920
3921 t2_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f10) >> 8) & 0xfff);
3922 if ( read32(DEFAULT_MCHBAR + 0x5f00) & 8 )
3923 {
3924 t3_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f20) >> 8) & 0xfff);
3925 t3_ns += 10 * (read32(DEFAULT_MCHBAR + 0x5f18) & 0xff);
3926 }
3927 else
3928 {
3929 t3_ns = 500;
3930 }
3931 printk(BIOS_DEBUG, "t123: %d, %d, %d\n",
3932 t1_ns, t2_ns, t3_ns);
3933 write32 (DEFAULT_MCHBAR + 0x5d10,
3934 ((encode_5d10(t1_ns) + encode_5d10(t2_ns)) << 16)
3935 | (encode_5d10(t1_ns) << 8)
3936 | ((encode_5d10(t3_ns) + encode_5d10(t2_ns) + encode_5d10(t1_ns)) << 24)
3937 | (read32(DEFAULT_MCHBAR + 0x5d10) & 0xC0C0C0C0)
3938 | 0xc);
3939}
3940
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003941static void save_timings(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003942{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003943 /* Save the MRC S3 restore data to cbmem */
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003944 store_current_mrc_cache(ctrl, sizeof(*ctrl));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003945}
3946
3947static void restore_timings(ramctr_timing * ctrl)
3948{
3949 int channel, slotrank, lane;
3950
3951 FOR_ALL_POPULATED_CHANNELS
3952 MCHBAR32(0x4004 + 0x400 * channel) =
3953 ctrl->tRRD
3954 | (ctrl->tRTP << 4)
3955 | (ctrl->tCKE << 8)
3956 | (ctrl->tWTR << 12)
3957 | (ctrl->tFAW << 16)
3958 | (ctrl->tWR << 24)
3959 | (ctrl->cmd_stretch[channel] << 30);
3960
3961 udelay(1);
3962
3963 FOR_ALL_POPULATED_CHANNELS {
3964 wait_428c(channel);
3965 }
3966
3967 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3968 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
3969 + 4 * lane, 0);
3970 }
3971
3972 FOR_ALL_POPULATED_CHANNELS
3973 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
3974 read32(DEFAULT_MCHBAR + 0x4008 +
3975 0x400 * channel) | 0x8000000);
3976
3977 FOR_ALL_POPULATED_CHANNELS {
3978 udelay (1);
3979 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
3980 read32(DEFAULT_MCHBAR + 0x4020 +
3981 0x400 * channel) | 0x200000);
3982 }
3983
3984 printram("CPE\n");
3985
3986 write32(DEFAULT_MCHBAR + 0x3400, 0);
3987 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3988
3989 printram("CP5b\n");
3990
3991 FOR_ALL_POPULATED_CHANNELS {
3992 program_timings(ctrl, channel);
3993 }
3994
3995 u32 reg, addr;
3996
3997 while (!(MCHBAR32(0x5084) & 0x10000)) ;
3998 do {
3999 reg = MCHBAR32(0x428c);
4000 } while ((reg & 0x14) == 0);
4001
4002 // Set state of memory controller
4003 MCHBAR32(0x5030) = 0x116;
4004 MCHBAR32(0x4ea0) = 0;
4005
4006 // Wait 500us
4007 udelay(500);
4008
4009 FOR_ALL_CHANNELS {
4010 // Set valid rank CKE
4011 reg = 0;
4012 reg = (reg & ~0xf) | ctrl->rankmap[channel];
4013 addr = 0x400 * channel + 0x42a0;
4014 MCHBAR32(addr) = reg;
4015
4016 // Wait 10ns for ranks to settle
4017 //udelay(0.01);
4018
4019 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
4020 MCHBAR32(addr) = reg;
4021
4022 // Write reset using a NOP
4023 write_reset(ctrl);
4024 }
4025
4026 /* mrs commands. */
4027 dram_mrscommands(ctrl);
4028
4029 printram("CP5c\n");
4030
4031 write32(DEFAULT_MCHBAR + 0x3000, 0);
4032
4033 FOR_ALL_CHANNELS {
4034 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
4035 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
4036 ~0x3f000000));
4037 udelay(2);
4038 }
4039
4040 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
4041}
4042
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004043static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot,
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004044 int s3_resume, int me_uma_size)
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004045{
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004046 int err;
4047
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004048 printk(BIOS_DEBUG, "Starting RAM training (%d).\n", fast_boot);
4049
4050 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004051 /* Find fastest common supported parameters */
4052 dram_find_common_params(ctrl);
4053
4054 dram_dimm_mapping(ctrl);
4055 }
4056
4057 /* Set MCU frequency */
4058 dram_freq(ctrl);
4059
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004060 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004061 /* Calculate timings */
4062 dram_timing(ctrl);
4063 }
4064
4065 /* Set version register */
4066 MCHBAR32(0x5034) = 0xC04EB002;
4067
4068 /* Enable crossover */
4069 dram_xover(ctrl);
4070
4071 /* Set timing and refresh registers */
4072 dram_timing_regs(ctrl);
4073
4074 /* Power mode preset */
4075 MCHBAR32(0x4e80) = 0x5500;
4076
4077 /* Set scheduler parameters */
4078 MCHBAR32(0x4c20) = 0x10100005;
4079
4080 /* Set cpu specific register */
4081 set_4f8c();
4082
4083 /* Clear IO reset bit */
4084 MCHBAR32(0x5030) &= ~0x20;
4085
4086 /* Set MAD-DIMM registers */
4087 dram_dimm_set_mapping(ctrl);
4088 printk(BIOS_DEBUG, "Done dimm mapping\n");
4089
4090 /* Zone config */
4091 dram_zones(ctrl, 1);
4092
4093 /* Set memory map */
4094 dram_memorymap(ctrl, me_uma_size);
4095 printk(BIOS_DEBUG, "Done memory map\n");
4096
4097 /* Set IO registers */
4098 dram_ioregs(ctrl);
4099 printk(BIOS_DEBUG, "Done io registers\n");
4100
4101 udelay(1);
4102
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004103 if (fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004104 restore_timings(ctrl);
4105 } else {
4106 /* Do jedec ddr3 reset sequence */
4107 dram_jedecreset(ctrl);
4108 printk(BIOS_DEBUG, "Done jedec reset\n");
4109
4110 /* MRS commands */
4111 dram_mrscommands(ctrl);
4112 printk(BIOS_DEBUG, "Done MRS commands\n");
4113
4114 /* Prepare for memory training */
4115 prepare_training(ctrl);
4116
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004117 err = read_training(ctrl);
4118 if (err)
4119 return err;
4120
4121 err = write_training(ctrl);
4122 if (err)
4123 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004124
4125 printram("CP5a\n");
4126
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004127 err = discover_edges(ctrl);
4128 if (err)
4129 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004130
4131 printram("CP5b\n");
4132
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004133 err = command_training(ctrl);
4134 if (err)
4135 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004136
4137 printram("CP5c\n");
4138
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004139 err = discover_edges_write(ctrl);
4140 if (err)
4141 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004142
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004143 err = discover_timC_write(ctrl);
4144 if (err)
4145 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004146
4147 normalize_training(ctrl);
4148 }
4149
4150 set_4008c(ctrl);
4151
4152 write_controller_mr(ctrl);
4153
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004154 if (!s3_resume) {
4155 err = channel_test(ctrl);
4156 if (err)
4157 return err;
4158 }
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004159
4160 return 0;
4161}
4162
4163void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004164 int s3resume)
4165{
4166 int me_uma_size;
4167 int cbmem_was_inited;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004168 ramctr_timing ctrl;
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004169 int fast_boot;
4170 struct mrc_data_container *mrc_cache;
4171 ramctr_timing *ctrl_cached;
Patrick Rudolph31d19592016-03-26 12:22:34 +01004172 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004173
4174 MCHBAR32(0x5f00) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004175
Vadim Bendebury7a3f36a2012-04-18 15:47:32 -07004176 report_platform_info();
4177
Stefan Reinauer00636b02012-04-04 00:08:51 +02004178 /* Wait for ME to be ready */
4179 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004180 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004181
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004182 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +02004183
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004184 u32 reg_5d10;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004185
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004186 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004187
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004188 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +02004189
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004190 reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10); // !!! = 0x00000000
4191 if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */
4192 && reg_5d10 && !s3resume) {
4193 write32(DEFAULT_MCHBAR + 0x5d10, 0);
4194 /* Need reset. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02004195 outb(0x6, 0xcf9);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004196
Patrick Georgi546953c2014-11-29 10:38:17 +01004197 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004198 }
Stefan Reinauer00636b02012-04-04 00:08:51 +02004199
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004200 memset(&ctrl, 0, sizeof (ctrl));
4201
4202 early_pch_init_native();
4203 early_thermal_init();
4204
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004205 /* try to find timings in MRC cache */
4206 mrc_cache = find_current_mrc_cache();
4207 if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(ctrl))) {
4208 if (s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004209 /* Failed S3 resume, reset to come up cleanly */
4210 outb(0x6, 0xcf9);
4211 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004212 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004213 ctrl_cached = NULL;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004214 } else {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004215 ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004216 }
4217
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004218 /* verify MRC cache for fast boot */
4219 if (ctrl_cached) {
4220 /* check SPD CRC16 to make sure the DIMMs haven't been replaced */
4221 fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
4222 if (!fast_boot)
4223 printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
4224 if (!fast_boot && s3resume) {
4225 /* Failed S3 resume, reset to come up cleanly */
4226 outb(0x6, 0xcf9);
4227 halt();
4228 }
4229 } else
4230 fast_boot = 0;
4231
4232 if (fast_boot) {
4233 printk(BIOS_DEBUG, "Trying stored timings.\n");
4234 memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
4235
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004236 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004237 if (err) {
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004238 if (s3resume) {
4239 /* Failed S3 resume, reset to come up cleanly */
4240 outb(0x6, 0xcf9);
4241 halt();
4242 }
4243 /* no need to erase bad mrc cache here, it gets overwritten on
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004244 * successful boot. */
4245 printk(BIOS_ERR, "Stored timings are invalid !\n");
4246 fast_boot = 0;
4247 }
4248 }
4249 if (!fast_boot) {
4250 ctrl.mobile = mobile;
4251 ctrl.tCK = min_tck;
4252
4253 /* Get DDR3 SPD data */
4254 dram_find_spds_ddr3(spds, &ctrl);
4255
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004256 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004257 }
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004258
4259 if (err && (ctrl.tCK < TCK_400MHZ)) {
4260 /* fallback: lower clock frequency */
4261 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
4262 printram("Decreasing clock frequency.\n");
4263 ctrl.tCK++;
4264 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
4265 }
4266
4267 if (err && (ctrl.tCK < TCK_400MHZ)) {
4268 /* fallback: lower clock frequency */
4269 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
4270 printram("Decreasing clock frequency.\n");
4271 ctrl.tCK++;
4272 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
4273 }
4274
4275 if (err) {
4276 /* fallback: disable failing channel */
4277 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
4278 printram("Disable failing channel.\n");
4279
4280 /* Reset DDR3 frequency */
4281 dram_find_spds_ddr3(spds, &ctrl);
4282
4283 /* disable failing channel */
4284 disable_channel(&ctrl, GET_ERR_CHANNEL(err));
4285
4286 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
4287 }
4288
Patrick Rudolph31d19592016-03-26 12:22:34 +01004289 if (err)
4290 die("raminit failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004291
4292 /* FIXME: should be hardware revision-dependent. */
4293 write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
4294
4295 set_scrambling_seed(&ctrl);
4296
4297 set_42a0(&ctrl);
4298
4299 final_registers(&ctrl);
4300
4301 /* Zone config */
4302 dram_zones(&ctrl, 0);
4303
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004304 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004305 quick_ram_check();
4306
4307 intel_early_me_status();
4308 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
4309 intel_early_me_status();
4310
Stefan Reinauer00636b02012-04-04 00:08:51 +02004311 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004312
4313 cbmem_was_inited = !cbmem_recovery(s3resume);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004314 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004315 save_timings(&ctrl);
4316 if (s3resume && !cbmem_was_inited) {
4317 /* Failed S3 resume, reset to come up cleanly */
4318 outb(0x6, 0xcf9);
4319 halt();
4320 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +01004321
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004322 fill_smbios17(&ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004323}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004324
4325#define HOST_BRIDGE PCI_DEVFN(0, 0)
4326#define DEFAULT_TCK TCK_800MHZ
4327
4328static unsigned int get_mem_min_tck(void)
4329{
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004330 u32 reg32;
4331 u8 rev;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004332 const struct device *dev;
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004333 const struct northbridge_intel_sandybridge_config *cfg = NULL;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004334
4335 dev = dev_find_slot(0, HOST_BRIDGE);
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004336 if (dev)
4337 cfg = dev->chip_info;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004338
4339 /* If this is zero, it just means devicetree.cb didn't set it */
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004340 if (!cfg || cfg->max_mem_clock_mhz == 0) {
4341 rev = pci_read_config8(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004342
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004343 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
4344 /* read Capabilities A Register DMFC bits */
4345 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A);
4346 reg32 &= 0x7;
4347
4348 switch (reg32) {
4349 case 7: return TCK_533MHZ;
4350 case 6: return TCK_666MHZ;
4351 case 5: return TCK_800MHZ;
4352 /* reserved: */
4353 default:
4354 break;
4355 }
4356 } else {
4357 /* read Capabilities B Register DMFC bits */
4358 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
4359 reg32 = (reg32 >> 4) & 0x7;
4360
4361 switch (reg32) {
4362 case 7: return TCK_533MHZ;
4363 case 6: return TCK_666MHZ;
4364 case 5: return TCK_800MHZ;
4365 case 4: return TCK_933MHZ;
4366 case 3: return TCK_1066MHZ;
4367 case 2: return TCK_1200MHZ;
4368 case 1: return TCK_1333MHZ;
4369 /* reserved: */
4370 default:
4371 break;
4372 }
4373 }
4374 return DEFAULT_TCK;
4375 } else {
4376 if (cfg->max_mem_clock_mhz >= 800)
4377 return TCK_800MHZ;
4378 else if (cfg->max_mem_clock_mhz >= 666)
4379 return TCK_666MHZ;
4380 else if (cfg->max_mem_clock_mhz >= 533)
4381 return TCK_533MHZ;
4382 else
4383 return TCK_400MHZ;
4384 }
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004385}
4386
4387void perform_raminit(int s3resume)
4388{
4389 spd_raw_data spd[4];
4390
4391 post_code(0x3a);
4392
4393 memset (spd, 0, sizeof (spd));
4394 mainboard_get_spd(spd);
4395
4396 timestamp_add_now(TS_BEFORE_INITRAM);
4397
4398 init_dram_ddr3(spd, 1, get_mem_min_tck(), s3resume);
4399}