blob: 042898dfb62a147155002af96e912153e4f735c3 [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)
204
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700205static void program_timings(ramctr_timing * ctrl, int channel);
206
207static const char *ecc_decoder[] = {
Stefan Reinauer00636b02012-04-04 00:08:51 +0200208 "inactive",
209 "active on IO",
210 "disabled on IO",
211 "active"
212};
213
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700214static void wait_txt_clear(void)
215{
216 struct cpuid_result cp;
217
218 cp = cpuid_ext(0x1, 0x0);
219 /* Check if TXT is supported? */
220 if (!(cp.ecx & 0x40))
221 return;
222 /* Some TXT public bit. */
223 if (!(read32((void *)0xfed30010) & 1))
224 return;
225 /* Wait for TXT clear. */
226 while (!(read8((void *)0xfed40000) & (1 << 7))) ;
227}
228
229static void sfence(void)
230{
231 asm volatile ("sfence");
232}
233
Patrick Rudolph9b515682015-10-09 13:43:51 +0200234static void toggle_io_reset(void) {
235 /* toggle IO reset bit */
236 u32 r32 = read32(DEFAULT_MCHBAR + 0x5030);
237 write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20);
238 udelay(1);
239 write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20);
240 udelay(1);
241}
242
Stefan Reinauer00636b02012-04-04 00:08:51 +0200243/*
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100244 * Fill cbmem with information for SMBIOS type 17.
245 */
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100246static void fill_smbios17(ramctr_timing *ctrl)
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100247{
248 struct memory_info *mem_info;
249 int channel, slot;
250 struct dimm_info *dimm;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100251 uint16_t ddr_freq;
252 dimm_info *info = &ctrl->info;
253
254 ddr_freq = (1000 << 8) / ctrl->tCK;
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100255
256 /*
257 * Allocate CBMEM area for DIMM information used to populate SMBIOS
258 * table 17
259 */
260 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
261 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
262 if (!mem_info)
263 return;
264
265 memset(mem_info, 0, sizeof(*mem_info));
266
267 FOR_ALL_CHANNELS for(slot = 0; slot < NUM_SLOTS; slot++) {
268 dimm = &mem_info->dimm[mem_info->dimm_cnt];
269 if (info->dimm[channel][slot].size_mb) {
270 dimm->ddr_type = MEMORY_TYPE_DDR3;
271 dimm->ddr_frequency = ddr_freq;
272 dimm->dimm_size = info->dimm[channel][slot].size_mb;
273 dimm->channel_num = channel;
274 dimm->rank_per_dimm = info->dimm[channel][slot].ranks;
275 dimm->dimm_num = slot;
276 memcpy(dimm->module_part_number,
277 info->dimm[channel][slot].part_number, 16);
278 dimm->mod_id = info->dimm[channel][slot].manufacturer_id;
279 dimm->mod_type = info->dimm[channel][slot].dimm_type;
280 dimm->bus_width = info->dimm[channel][slot].width;
281 mem_info->dimm_cnt++;
282 }
283 }
284}
285
286/*
Stefan Reinauer00636b02012-04-04 00:08:51 +0200287 * Dump in the log memory controller configuration as read from the memory
288 * controller registers.
289 */
290static void report_memory_config(void)
291{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700292 u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200293 int i;
294
295 addr_decoder_common = MCHBAR32(0x5000);
296 addr_decode_ch[0] = MCHBAR32(0x5004);
297 addr_decode_ch[1] = MCHBAR32(0x5008);
298
299 printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700300 (MCHBAR32(0x5e04) * 13333 * 2 + 50) / 100);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200301 printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700302 addr_decoder_common & 3, (addr_decoder_common >> 2) & 3,
Stefan Reinauer00636b02012-04-04 00:08:51 +0200303 (addr_decoder_common >> 4) & 3);
304
305 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
306 u32 ch_conf = addr_decode_ch[i];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700307 printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i,
308 ch_conf);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200309 printk(BIOS_DEBUG, " ECC %s\n",
310 ecc_decoder[(ch_conf >> 24) & 3]);
311 printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
312 ((ch_conf >> 22) & 1) ? "on" : "off");
313 printk(BIOS_DEBUG, " rank interleave %s\n",
314 ((ch_conf >> 21) & 1) ? "on" : "off");
315 printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n",
316 ((ch_conf >> 0) & 0xff) * 256,
317 ((ch_conf >> 19) & 1) ? 16 : 8,
318 ((ch_conf >> 17) & 1) ? "dual" : "single",
319 ((ch_conf >> 16) & 1) ? "" : ", selected");
320 printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n",
321 ((ch_conf >> 8) & 0xff) * 256,
322 ((ch_conf >> 20) & 1) ? 16 : 8,
323 ((ch_conf >> 18) & 1) ? "dual" : "single",
324 ((ch_conf >> 16) & 1) ? ", selected" : "");
325 }
326}
327
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100328/*
329 * Return CRC16 match for all SPDs.
330 */
331static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
332{
333 int channel, slot, spd_slot;
334 int match = 1;
335
336 FOR_ALL_CHANNELS {
337 for (slot = 0; slot < NUM_SLOTS; slot++) {
338 spd_slot = 2 * channel + slot;
339 match &= ctrl->spd_crc[channel][slot] ==
340 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
341 }
342 }
343 return match;
344}
345
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700346void read_spd(spd_raw_data * spd, u8 addr)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200347{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700348 int j;
349 for (j = 0; j < 256; j++)
350 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
351}
352
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100353static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700354{
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100355 int dimms = 0, dimms_on_channel;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700356 int channel, slot, spd_slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100357 dimm_info *dimm = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700358
359 memset (ctrl->rankmap, 0, sizeof (ctrl->rankmap));
360
361 ctrl->extended_temperature_range = 1;
362 ctrl->auto_self_refresh = 1;
363
364 FOR_ALL_CHANNELS {
365 ctrl->channel_size_mb[channel] = 0;
366
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100367 dimms_on_channel = 0;
368 /* count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700369 for (slot = 0; slot < NUM_SLOTS; slot++) {
370 spd_slot = 2 * channel + slot;
371 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100372 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
373 dimms_on_channel++;
374 }
375
376 for (slot = 0; slot < NUM_SLOTS; slot++) {
377 spd_slot = 2 * channel + slot;
378 /* search for XMP profile */
379 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
380 spd[spd_slot],
381 DDR3_XMP_PROFILE_1);
382
383 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
384 printram("No valid XMP profile found.\n");
385 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
386 } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
387 printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
388 dimm->dimm[channel][slot].dimms_per_channel,
389 dimms_on_channel);
390 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
391 } else if (dimm->dimm[channel][slot].voltage != 1500) {
392 /* TODO: support other DDR3 voltage than 1500mV */
393 printram("XMP profile's requested %u mV is unsupported.\n",
394 dimm->dimm[channel][slot].voltage);
395 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
396 }
397
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100398 /* fill in CRC16 for MRC cache */
399 ctrl->spd_crc[channel][slot] =
400 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
401
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700402 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
403 // set dimm invalid
404 dimm->dimm[channel][slot].ranks = 0;
405 dimm->dimm[channel][slot].size_mb = 0;
406 continue;
407 }
408
409 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
410 dimms++;
411 ctrl->rank_mirror[channel][slot * 2] = 0;
412 ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
413 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
414
415 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
416 ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
417
418 ctrl->rankmap[channel] |= ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100419 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n",
420 channel, ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700421 }
422 if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc)
423 && dimm->dimm[channel][0].reference_card <= 5 && dimm->dimm[channel][1].reference_card <= 5) {
424 const int ref_card_offset_table[6][6] = {
425 { 0, 0, 0, 0, 2, 2, },
426 { 0, 0, 0, 0, 2, 2, },
427 { 0, 0, 0, 0, 2, 2, },
428 { 0, 0, 0, 0, 1, 1, },
429 { 2, 2, 2, 1, 0, 0, },
430 { 2, 2, 2, 1, 0, 0, },
431 };
432 ctrl->ref_card_offset[channel] = ref_card_offset_table[dimm->dimm[channel][0].reference_card]
433 [dimm->dimm[channel][1].reference_card];
434 } else
435 ctrl->ref_card_offset[channel] = 0;
436 }
437
438 if (!dimms)
439 die("No DIMMs were found");
440}
441
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100442static void dram_find_common_params(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700443{
444 size_t valid_dimms;
445 int channel, slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100446 dimm_info *dimms = &ctrl->info;
447
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700448 ctrl->cas_supported = 0xff;
449 valid_dimms = 0;
450 FOR_ALL_CHANNELS for (slot = 0; slot < 2; slot++) {
451 const dimm_attr *dimm = &dimms->dimm[channel][slot];
452 if (dimm->dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3)
453 continue;
454 valid_dimms++;
455
456 /* Find all possible CAS combinations */
457 ctrl->cas_supported &= dimm->cas_supported;
458
459 /* Find the smallest common latencies supported by all DIMMs */
460 ctrl->tCK = MAX(ctrl->tCK, dimm->tCK);
461 ctrl->tAA = MAX(ctrl->tAA, dimm->tAA);
462 ctrl->tWR = MAX(ctrl->tWR, dimm->tWR);
463 ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD);
464 ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD);
465 ctrl->tRP = MAX(ctrl->tRP, dimm->tRP);
466 ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS);
467 ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC);
468 ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR);
469 ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP);
470 ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW);
471 }
472
473 if (!ctrl->cas_supported)
474 die("Unsupported DIMM combination. "
475 "DIMMS do not support common CAS latency");
476 if (!valid_dimms)
477 die("No valid DIMMs found");
478}
479
480static u8 get_CWL(u8 CAS)
481{
482 /* Get CWL based on CAS using the following rule:
483 * _________________________________________
484 * CAS: | 4T | 5T | 6T | 7T | 8T | 9T | 10T | 11T |
485 * CWL: | 5T | 5T | 5T | 6T | 6T | 7T | 7T | 8T |
486 */
487 static const u8 cas_cwl_map[] = { 5, 5, 5, 6, 6, 7, 7, 8 };
488 if (CAS > 11)
489 return 8;
490 return cas_cwl_map[CAS - 4];
491}
492
493/* Frequency multiplier. */
494static u32 get_FRQ(u32 tCK)
495{
496 u32 FRQ;
497 FRQ = 256000 / (tCK * BASEFREQ);
498 if (FRQ > 8)
499 return 8;
500 if (FRQ < 3)
501 return 3;
502 return FRQ;
503}
504
505static u32 get_REFI(u32 tCK)
506{
507 /* Get REFI based on MCU frequency using the following rule:
508 * _________________________________________
509 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
510 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 |
511 */
512 static const u32 frq_refi_map[] =
513 { 3120, 4160, 5200, 6240, 7280, 8320 };
514 return frq_refi_map[get_FRQ(tCK) - 3];
515}
516
517static u8 get_XSOffset(u32 tCK)
518{
519 /* Get XSOffset based on MCU frequency using the following rule:
520 * _________________________
521 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
522 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 |
523 */
524 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 };
525 return frq_xs_map[get_FRQ(tCK) - 3];
526}
527
528static u8 get_MOD(u32 tCK)
529{
530 /* Get MOD based on MCU frequency using the following rule:
531 * _____________________________
532 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
533 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 |
534 */
535 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 };
536 return frq_mod_map[get_FRQ(tCK) - 3];
537}
538
539static u8 get_WLO(u32 tCK)
540{
541 /* Get WLO based on MCU frequency using the following rule:
542 * _______________________
543 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
544 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 |
545 */
546 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 };
547 return frq_wlo_map[get_FRQ(tCK) - 3];
548}
549
550static u8 get_CKE(u32 tCK)
551{
552 /* Get CKE based on MCU frequency using the following rule:
553 * _______________________
554 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
555 * CKE : | 3 | 3 | 4 | 4 | 5 | 6 |
556 */
557 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 };
558 return frq_cke_map[get_FRQ(tCK) - 3];
559}
560
561static u8 get_XPDLL(u32 tCK)
562{
563 /* Get XPDLL based on MCU frequency using the following rule:
564 * _____________________________
565 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
566 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 |
567 */
568 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 };
569 return frq_xpdll_map[get_FRQ(tCK) - 3];
570}
571
572static u8 get_XP(u32 tCK)
573{
574 /* Get XP based on MCU frequency using the following rule:
575 * _______________________
576 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
577 * XP : | 3 | 4 | 4 | 5 | 6 | 7 |
578 */
579 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 };
580 return frq_xp_map[get_FRQ(tCK) - 3];
581}
582
583static u8 get_AONPD(u32 tCK)
584{
585 /* Get AONPD based on MCU frequency using the following rule:
586 * ________________________
587 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
588 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 |
589 */
590 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 };
591 return frq_aonpd_map[get_FRQ(tCK) - 3];
592}
593
594static u32 get_COMP2(u32 tCK)
595{
596 /* Get COMP2 based on MCU frequency using the following rule:
597 * ___________________________________________________________
598 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
599 * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C |
600 */
601 static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C,
602 0xC6369CC, 0xC42514C, 0xC21410C
603 };
604 return frq_comp2_map[get_FRQ(tCK) - 3];
605}
606
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100607static u32 get_XOVER_CLK(u8 rankmap)
608{
609 return rankmap << 24;
610}
611
612static u32 get_XOVER_CMD(u8 rankmap)
613{
614 u32 reg;
615
616 // enable xover cmd
617 reg = 0x4000;
618
619 // enable xover ctl
620 if (rankmap & 0x3)
621 reg |= 0x20000;
622
623 if (rankmap & 0xc)
624 reg |= 0x4000000;
625
626 return reg;
627}
628
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700629static void dram_timing(ramctr_timing * ctrl)
630{
631 u8 val;
632 u32 val32;
633
634 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
635 * we cap it if we have faster DIMMs.
636 * Then, align it to the closest JEDEC standard frequency */
637 if (ctrl->tCK <= TCK_1066MHZ) {
638 ctrl->tCK = TCK_1066MHZ;
639 ctrl->edge_offset[0] = 16;
640 ctrl->edge_offset[1] = 7;
641 ctrl->edge_offset[2] = 7;
642 ctrl->timC_offset[0] = 18;
643 ctrl->timC_offset[1] = 7;
644 ctrl->timC_offset[2] = 7;
645 ctrl->reg_c14_offset = 16;
646 ctrl->reg_5064b0 = 0x218;
647 ctrl->reg_320c_range_threshold = 13;
648 } else if (ctrl->tCK <= TCK_933MHZ) {
649 ctrl->tCK = TCK_933MHZ;
650 ctrl->edge_offset[0] = 14;
651 ctrl->edge_offset[1] = 6;
652 ctrl->edge_offset[2] = 6;
653 ctrl->timC_offset[0] = 15;
654 ctrl->timC_offset[1] = 6;
655 ctrl->timC_offset[2] = 6;
656 ctrl->reg_c14_offset = 14;
657 ctrl->reg_5064b0 = 0x1d5;
658 ctrl->reg_320c_range_threshold = 15;
659 } else if (ctrl->tCK <= TCK_800MHZ) {
660 ctrl->tCK = TCK_800MHZ;
661 ctrl->edge_offset[0] = 13;
662 ctrl->edge_offset[1] = 5;
663 ctrl->edge_offset[2] = 5;
664 ctrl->timC_offset[0] = 14;
665 ctrl->timC_offset[1] = 5;
666 ctrl->timC_offset[2] = 5;
667 ctrl->reg_c14_offset = 12;
668 ctrl->reg_5064b0 = 0x193;
669 ctrl->reg_320c_range_threshold = 15;
670 } else if (ctrl->tCK <= TCK_666MHZ) {
671 ctrl->tCK = TCK_666MHZ;
672 ctrl->edge_offset[0] = 10;
673 ctrl->edge_offset[1] = 4;
674 ctrl->edge_offset[2] = 4;
675 ctrl->timC_offset[0] = 11;
676 ctrl->timC_offset[1] = 4;
677 ctrl->timC_offset[2] = 4;
678 ctrl->reg_c14_offset = 10;
679 ctrl->reg_5064b0 = 0x150;
680 ctrl->reg_320c_range_threshold = 16;
681 } else if (ctrl->tCK <= TCK_533MHZ) {
682 ctrl->tCK = TCK_533MHZ;
683 ctrl->edge_offset[0] = 8;
684 ctrl->edge_offset[1] = 3;
685 ctrl->edge_offset[2] = 3;
686 ctrl->timC_offset[0] = 9;
687 ctrl->timC_offset[1] = 3;
688 ctrl->timC_offset[2] = 3;
689 ctrl->reg_c14_offset = 8;
690 ctrl->reg_5064b0 = 0x10d;
691 ctrl->reg_320c_range_threshold = 17;
692 } else {
693 ctrl->tCK = TCK_400MHZ;
694 ctrl->edge_offset[0] = 6;
695 ctrl->edge_offset[1] = 2;
696 ctrl->edge_offset[2] = 2;
697 ctrl->timC_offset[0] = 6;
698 ctrl->timC_offset[1] = 2;
699 ctrl->timC_offset[2] = 2;
700 ctrl->reg_c14_offset = 8;
701 ctrl->reg_5064b0 = 0xcd;
702 ctrl->reg_320c_range_threshold = 17;
703 }
704
705 val32 = (1000 << 8) / ctrl->tCK;
706 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
707
708 /* Find CAS and CWL latencies */
709 val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK;
710 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
711 /* Find lowest supported CAS latency that satisfies the minimum value */
712 while (!((ctrl->cas_supported >> (val - 4)) & 1)
713 && (ctrl->cas_supported >> (val - 4))) {
714 val++;
715 }
716 /* Is CAS supported */
717 if (!(ctrl->cas_supported & (1 << (val - 4))))
718 printk(BIOS_DEBUG, "CAS not supported\n");
719 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
720 ctrl->CAS = val;
721 ctrl->CWL = get_CWL(ctrl->CAS);
722 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
723
724 /* Find tRCD */
725 ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK;
726 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
727
728 ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK;
729 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
730
731 /* Find tRAS */
732 ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK;
733 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
734
735 /* Find tWR */
736 ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK;
737 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
738
739 /* Find tFAW */
740 ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK;
741 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
742
743 /* Find tRRD */
744 ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK;
745 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
746
747 /* Find tRTP */
748 ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK;
749 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
750
751 /* Find tWTR */
752 ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK;
753 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
754
755 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
756 ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK;
757 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
758
759 ctrl->tREFI = get_REFI(ctrl->tCK);
760 ctrl->tMOD = get_MOD(ctrl->tCK);
761 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
762 ctrl->tWLO = get_WLO(ctrl->tCK);
763 ctrl->tCKE = get_CKE(ctrl->tCK);
764 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
765 ctrl->tXP = get_XP(ctrl->tCK);
766 ctrl->tAONPD = get_AONPD(ctrl->tCK);
767}
768
769static void dram_freq(ramctr_timing * ctrl)
770{
771 if (ctrl->tCK > TCK_400MHZ) {
772 printk (BIOS_ERR, "DRAM frequency is under lowest supported frequency (400 MHz). Increasing to 400 MHz as last resort");
773 ctrl->tCK = TCK_400MHZ;
774 }
775 while (1) {
776 u8 val2;
777 u32 reg1 = 0;
778
779 /* Step 1 - Set target PCU frequency */
780
781 if (ctrl->tCK <= TCK_1066MHZ) {
782 ctrl->tCK = TCK_1066MHZ;
783 } else if (ctrl->tCK <= TCK_933MHZ) {
784 ctrl->tCK = TCK_933MHZ;
785 } else if (ctrl->tCK <= TCK_800MHZ) {
786 ctrl->tCK = TCK_800MHZ;
787 } else if (ctrl->tCK <= TCK_666MHZ) {
788 ctrl->tCK = TCK_666MHZ;
789 } else if (ctrl->tCK <= TCK_533MHZ) {
790 ctrl->tCK = TCK_533MHZ;
791 } else if (ctrl->tCK <= TCK_400MHZ) {
792 ctrl->tCK = TCK_400MHZ;
793 } else {
794 die ("No lock frequency found");
795 }
796
797 /* Frequency mulitplier. */
798 u32 FRQ = get_FRQ(ctrl->tCK);
799
800 /* Step 2 - Select frequency in the MCU */
801 reg1 = FRQ;
802 reg1 |= 0x80000000; // set running bit
803 MCHBAR32(0x5e00) = reg1;
804 while (reg1 & 0x80000000) {
805 printk(BIOS_DEBUG, " PLL busy...");
806 reg1 = MCHBAR32(0x5e00);
807 }
808 printk(BIOS_DEBUG, "done\n");
809
810 /* Step 3 - Verify lock frequency */
811 reg1 = MCHBAR32(0x5e04);
812 val2 = (u8) reg1;
813 if (val2 >= FRQ) {
814 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
815 (1000 << 8) / ctrl->tCK);
816 return;
817 }
818 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
819 ctrl->tCK++;
820 }
821}
822
823static void dram_xover(ramctr_timing * ctrl)
824{
825 u32 reg;
826 int channel;
827
828 FOR_ALL_CHANNELS {
829 // enable xover clk
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100830 reg = get_XOVER_CLK(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100831 printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
832 reg);
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100833 MCHBAR32(channel * 0x100 + 0xc14) = reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700834
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100835 // enable xover ctl & xover cmd
836 reg = get_XOVER_CMD(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100837 printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
838 reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700839 MCHBAR32(0x100 * channel + 0x320c) = reg;
840 }
841}
842
843static void dram_timing_regs(ramctr_timing * ctrl)
844{
845 u32 reg, addr, val32, cpu, stretch;
846 struct cpuid_result cpures;
847 int channel;
848
849 FOR_ALL_CHANNELS {
850 // DBP
851 reg = 0;
852 reg |= ctrl->tRCD;
853 reg |= (ctrl->tRP << 4);
854 reg |= (ctrl->CAS << 8);
855 reg |= (ctrl->CWL << 12);
856 reg |= (ctrl->tRAS << 16);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100857 printram("DBP [%x] = %x\n", 0x400 * channel + 0x4000, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700858 MCHBAR32(0x400 * channel + 0x4000) = reg;
859
860 // RAP
861 reg = 0;
862 reg |= ctrl->tRRD;
863 reg |= (ctrl->tRTP << 4);
864 reg |= (ctrl->tCKE << 8);
865 reg |= (ctrl->tWTR << 12);
866 reg |= (ctrl->tFAW << 16);
867 reg |= (ctrl->tWR << 24);
868 reg |= (3 << 30);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100869 printram("RAP [%x] = %x\n", 0x400 * channel + 0x4004, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700870 MCHBAR32(0x400 * channel + 0x4004) = reg;
871
872 // OTHP
873 addr = 0x400 * channel + 0x400c;
874 reg = 0;
875 reg |= ctrl->tXPDLL;
876 reg |= (ctrl->tXP << 5);
877 reg |= (ctrl->tAONPD << 8);
878 reg |= 0xa0000;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100879 printram("OTHP [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700880 MCHBAR32(addr) = reg;
881
882 MCHBAR32(0x400 * channel + 0x4014) = 0;
883
884 MCHBAR32(addr) |= 0x00020000;
885
886 // ODT stretch
887 reg = 0;
888
889 cpures = cpuid(0);
890 cpu = cpures.eax;
891 if (IS_IVY_CPU(cpu)
892 || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) {
893 stretch = 2;
894 addr = 0x400 * channel + 0x400c;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100895 printram("ODT stretch [%x] = %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700896 0x400 * channel + 0x400c, reg);
897 reg = MCHBAR32(addr);
898
899 if (((ctrl->rankmap[channel] & 3) == 0)
900 || (ctrl->rankmap[channel] & 0xc) == 0) {
901
902 // Rank 0 - operate on rank 2
903 reg = (reg & ~0xc0000) | (stretch << 18);
904
905 // Rank 2 - operate on rank 0
906 reg = (reg & ~0x30000) | (stretch << 16);
907
Patrick Rudolpha649a542016-01-17 18:32:06 +0100908 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700909 MCHBAR32(addr) = reg;
910 }
911
912 } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) {
913 stretch = 3;
914 addr = 0x400 * channel + 0x401c;
915 reg = MCHBAR32(addr);
916
917 if (((ctrl->rankmap[channel] & 3) == 0)
918 || (ctrl->rankmap[channel] & 0xc) == 0) {
919
920 // Rank 0 - operate on rank 2
921 reg = (reg & ~0x3000) | (stretch << 12);
922
923 // Rank 2 - operate on rank 0
924 reg = (reg & ~0xc00) | (stretch << 10);
925
Patrick Rudolpha649a542016-01-17 18:32:06 +0100926 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700927 MCHBAR32(addr) = reg;
928 }
929 } else {
930 stretch = 0;
931 }
932
933 // REFI
934 reg = 0;
935 val32 = ctrl->tREFI;
936 reg = (reg & ~0xffff) | val32;
937 val32 = ctrl->tRFC;
938 reg = (reg & ~0x1ff0000) | (val32 << 16);
939 val32 = (u32) (ctrl->tREFI * 9) / 1024;
940 reg = (reg & ~0xfe000000) | (val32 << 25);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100941 printram("REFI [%x] = %x\n", 0x400 * channel + 0x4298,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700942 reg);
943 MCHBAR32(0x400 * channel + 0x4298) = reg;
944
945 MCHBAR32(0x400 * channel + 0x4294) |= 0xff;
946
947 // SRFTP
948 reg = 0;
949 val32 = tDLLK;
950 reg = (reg & ~0xfff) | val32;
951 val32 = ctrl->tXSOffset;
952 reg = (reg & ~0xf000) | (val32 << 12);
953 val32 = tDLLK - ctrl->tXSOffset;
954 reg = (reg & ~0x3ff0000) | (val32 << 16);
955 val32 = ctrl->tMOD - 8;
956 reg = (reg & ~0xf0000000) | (val32 << 28);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100957 printram("SRFTP [%x] = %x\n", 0x400 * channel + 0x42a4,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700958 reg);
959 MCHBAR32(0x400 * channel + 0x42a4) = reg;
960 }
961}
962
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100963static void dram_dimm_mapping(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700964{
965 u32 reg, val32;
966 int channel;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100967 dimm_info *info = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700968
969 FOR_ALL_CHANNELS {
970 dimm_attr *dimmA = 0;
971 dimm_attr *dimmB = 0;
972 reg = 0;
973 val32 = 0;
974 if (info->dimm[channel][0].size_mb >=
975 info->dimm[channel][1].size_mb) {
976 // dimm 0 is bigger, set it to dimmA
977 dimmA = &info->dimm[channel][0];
978 dimmB = &info->dimm[channel][1];
979 reg |= (0 << 16);
980 } else {
981 // dimm 1 is bigger, set it to dimmA
982 dimmA = &info->dimm[channel][1];
983 dimmB = &info->dimm[channel][0];
984 reg |= (1 << 16);
985 }
986 // dimmA
987 if (dimmA && (dimmA->ranks > 0)) {
988 val32 = dimmA->size_mb / 256;
989 reg = (reg & ~0xff) | val32;
990 val32 = dimmA->ranks - 1;
991 reg = (reg & ~0x20000) | (val32 << 17);
992 val32 = (dimmA->width / 8) - 1;
993 reg = (reg & ~0x80000) | (val32 << 19);
994 }
995 // dimmB
996 if (dimmB && (dimmB->ranks > 0)) {
997 val32 = dimmB->size_mb / 256;
998 reg = (reg & ~0xff00) | (val32 << 8);
999 val32 = dimmB->ranks - 1;
1000 reg = (reg & ~0x40000) | (val32 << 18);
1001 val32 = (dimmB->width / 8) - 1;
1002 reg = (reg & ~0x100000) | (val32 << 20);
1003 }
1004 reg = (reg & ~0x200000) | (1 << 21); // rank interleave
1005 reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave
1006
1007 // Save MAD-DIMM register
1008 if ((dimmA && (dimmA->ranks > 0))
1009 || (dimmB && (dimmB->ranks > 0))) {
1010 ctrl->mad_dimm[channel] = reg;
1011 } else {
1012 ctrl->mad_dimm[channel] = 0;
1013 }
1014 }
1015}
1016
1017static void dram_dimm_set_mapping(ramctr_timing * ctrl)
1018{
1019 int channel;
1020 FOR_ALL_CHANNELS {
1021 MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
1022 }
1023}
1024
1025static void dram_zones(ramctr_timing * ctrl, int training)
1026{
1027 u32 reg, ch0size, ch1size;
1028 u8 val;
1029 reg = 0;
1030 val = 0;
1031 if (training) {
1032 ch0size = ctrl->channel_size_mb[0] ? 256 : 0;
1033 ch1size = ctrl->channel_size_mb[1] ? 256 : 0;
1034 } else {
1035 ch0size = ctrl->channel_size_mb[0];
1036 ch1size = ctrl->channel_size_mb[1];
1037 }
1038
1039 if (ch0size >= ch1size) {
1040 reg = MCHBAR32(0x5014);
1041 val = ch1size / 256;
1042 reg = (reg & ~0xff000000) | val << 24;
1043 reg = (reg & ~0xff0000) | (2 * val) << 16;
1044 MCHBAR32(0x5014) = reg;
1045 MCHBAR32(0x5000) = 0x24;
1046 } else {
1047 reg = MCHBAR32(0x5014);
1048 val = ch0size / 256;
1049 reg = (reg & ~0xff000000) | val << 24;
1050 reg = (reg & ~0xff0000) | (2 * val) << 16;
1051 MCHBAR32(0x5014) = reg;
1052 MCHBAR32(0x5000) = 0x21;
1053 }
1054}
1055
1056static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
1057{
1058 u32 reg, val, reclaim;
1059 u32 tom, gfxstolen, gttsize;
1060 size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase,
1061 tsegbase, mestolenbase;
1062 size_t tsegbasedelta, remapbase, remaplimit;
1063 uint16_t ggc;
1064
1065 mmiosize = 0x400;
1066
1067 ggc = pci_read_config16(NORTHBRIDGE, GGC);
1068 if (!(ggc & 2)) {
1069 gfxstolen = ((ggc >> 3) & 0x1f) * 32;
1070 gttsize = ((ggc >> 8) & 0x3);
1071 } else {
1072 gfxstolen = 0;
1073 gttsize = 0;
1074 }
1075
1076 tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
1077
1078 tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
1079
1080 mestolenbase = tom - me_uma_size;
1081
1082 toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
1083 tom - me_uma_size);
1084 gfxstolenbase = toludbase - gfxstolen;
1085 gttbase = gfxstolenbase - gttsize;
1086
1087 tsegbase = gttbase - tsegsize;
1088
1089 // Round tsegbase down to nearest address aligned to tsegsize
1090 tsegbasedelta = tsegbase & (tsegsize - 1);
1091 tsegbase &= ~(tsegsize - 1);
1092
1093 gttbase -= tsegbasedelta;
1094 gfxstolenbase -= tsegbasedelta;
1095 toludbase -= tsegbasedelta;
1096
1097 // Test if it is possible to reclaim a hole in the ram addressing
1098 if (tom - me_uma_size > toludbase) {
1099 // Reclaim is possible
1100 reclaim = 1;
1101 remapbase = MAX(4096, tom - me_uma_size);
1102 remaplimit =
1103 remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1;
1104 touudbase = remaplimit + 1;
1105 } else {
1106 // Reclaim not possible
1107 reclaim = 0;
1108 touudbase = tom - me_uma_size;
1109 }
1110
1111 // Update memory map in pci-e configuration space
Patrick Rudolpha649a542016-01-17 18:32:06 +01001112 printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001113
1114 // TOM (top of memory)
1115 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0);
1116 val = tom & 0xfff;
1117 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001118 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001119 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg);
1120
1121 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4);
1122 val = tom & 0xfffff000;
1123 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001124 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001125 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg);
1126
1127 // TOLUD (top of low used dram)
1128 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
1129 val = toludbase & 0xfff;
1130 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001131 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xbc, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001132 pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg);
1133
1134 // TOUUD LSB (top of upper usable dram)
1135 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
1136 val = touudbase & 0xfff;
1137 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001138 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001139 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg);
1140
1141 // TOUUD MSB
1142 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
1143 val = touudbase & 0xfffff000;
1144 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001145 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xac, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001146 pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg);
1147
1148 if (reclaim) {
1149 // REMAP BASE
1150 pcie_write_config32(PCI_DEV(0, 0, 0), 0x90, remapbase << 20);
1151 pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, remapbase >> 12);
1152
1153 // REMAP LIMIT
1154 pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
1155 pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
1156 }
1157 // TSEG
1158 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
1159 val = tsegbase & 0xfff;
1160 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001161 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001162 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg);
1163
1164 // GFX stolen memory
1165 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0);
1166 val = gfxstolenbase & 0xfff;
1167 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001168 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001169 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg);
1170
1171 // GTT stolen memory
1172 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4);
1173 val = gttbase & 0xfff;
1174 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001175 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001176 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
1177
1178 if (me_uma_size) {
1179 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
1180 val = (0x80000 - me_uma_size) & 0xfffff000;
1181 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001182 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x7c, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001183 pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg);
1184
1185 // ME base
1186 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70);
1187 val = mestolenbase & 0xfff;
1188 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001189 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x70, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001190 pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg);
1191
1192 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74);
1193 val = mestolenbase & 0xfffff000;
1194 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001195 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x74, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001196 pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg);
1197
1198 // ME mask
1199 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78);
1200 val = (0x80000 - me_uma_size) & 0xfff;
1201 reg = (reg & ~0xfff00000) | (val << 20);
1202 reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem
1203
1204 reg = (reg & ~0x800) | (1 << 11); // set ME memory enable
Patrick Rudolpha649a542016-01-17 18:32:06 +01001205 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x78, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001206 pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg);
1207 }
1208}
1209
1210static void dram_ioregs(ramctr_timing * ctrl)
1211{
1212 u32 reg, comp2;
1213
1214 int channel;
1215
1216 // IO clock
1217 FOR_ALL_CHANNELS {
1218 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
1219 }
1220
1221 // IO command
1222 FOR_ALL_CHANNELS {
1223 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
1224 }
1225
1226 // IO control
1227 FOR_ALL_POPULATED_CHANNELS {
1228 program_timings(ctrl, channel);
1229 }
1230
1231 // Rcomp
Patrick Rudolpha649a542016-01-17 18:32:06 +01001232 printram("RCOMP...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001233 reg = 0;
1234 while (reg == 0) {
1235 reg = MCHBAR32(0x5084) & 0x10000;
1236 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001237 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001238
1239 // Set comp2
1240 comp2 = get_COMP2(ctrl->tCK);
1241 MCHBAR32(0x3714) = comp2;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001242 printram("COMP2 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001243
1244 // Set comp1
1245 FOR_ALL_POPULATED_CHANNELS {
1246 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
1247 reg = (reg & ~0xe00) | (1 << 9); //odt
1248 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
1249 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
1250 MCHBAR32(0x1810 + channel * 0x100) = reg;
1251 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001252 printram("COMP1 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001253
Patrick Rudolpha649a542016-01-17 18:32:06 +01001254 printram("FORCE RCOMP and wait 20us...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001255 MCHBAR32(0x5f08) |= 0x100;
1256 udelay(20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001257 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001258}
1259
1260static void wait_428c(int channel)
1261{
1262 while (1) {
1263 if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
1264 return;
1265 }
1266}
1267
1268static void write_reset(ramctr_timing * ctrl)
1269{
1270 int channel, slotrank;
1271
1272 /* choose a populated channel. */
1273 channel = (ctrl->rankmap[0]) ? 0 : 1;
1274
1275 wait_428c(channel);
1276
1277 /* choose a populated rank. */
1278 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
1279
Patrick Rudolph371d2912015-10-09 13:33:25 +02001280 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001281 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1282 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01);
1283
1284 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1285 (slotrank << 24) | 0x60000);
1286
1287 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1288
1289 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001);
1290 wait_428c(channel);
1291}
1292
1293static void dram_jedecreset(ramctr_timing * ctrl)
1294{
1295 u32 reg, addr;
1296 int channel;
1297
1298 while (!(MCHBAR32(0x5084) & 0x10000)) ;
1299 do {
1300 reg = MCHBAR32(0x428c);
1301 } while ((reg & 0x14) == 0);
1302
1303 // Set state of memory controller
1304 reg = 0x112;
1305 MCHBAR32(0x5030) = reg;
1306 MCHBAR32(0x4ea0) = 0;
1307 reg |= 2; //ddr reset
1308 MCHBAR32(0x5030) = reg;
1309
1310 // Assert dimm reset signal
1311 reg = MCHBAR32(0x5030);
1312 reg &= ~0x2;
1313 MCHBAR32(0x5030) = reg;
1314
1315 // Wait 200us
1316 udelay(200);
1317
1318 // Deassert dimm reset signal
1319 MCHBAR32(0x5030) |= 2;
1320
1321 // Wait 500us
1322 udelay(500);
1323
1324 // Enable DCLK
1325 MCHBAR32(0x5030) |= 4;
1326
1327 // XXX Wait 20ns
1328 udelay(1);
1329
1330 FOR_ALL_CHANNELS {
1331 // Set valid rank CKE
1332 reg = 0;
1333 reg = (reg & ~0xf) | ctrl->rankmap[channel];
1334 addr = 0x400 * channel + 0x42a0;
1335 MCHBAR32(addr) = reg;
1336
1337 // Wait 10ns for ranks to settle
1338 //udelay(0.01);
1339
1340 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
1341 MCHBAR32(addr) = reg;
1342
1343 // Write reset using a NOP
1344 write_reset(ctrl);
1345 }
1346}
1347
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001348static odtmap get_ODT(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001349{
1350 /* Get ODT based on rankmap: */
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001351 int dimms_per_ch = (ctrl->rankmap[channel] & 1)
1352 + ((ctrl->rankmap[channel] >> 2) & 1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001353
1354 if (dimms_per_ch == 1) {
1355 return (const odtmap){60, 60};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001356 } else {
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001357 return (const odtmap){120, 30};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001358 }
1359}
1360
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001361static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001362 int reg, u32 val)
1363{
1364 wait_428c(channel);
1365
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001366 if (ctrl->rank_mirror[channel][slotrank]) {
1367 /* DDR3 Rank1 Address mirror
1368 * swap the following pins:
1369 * A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 */
1370 reg = ((reg >> 1) & 1) | ((reg << 1) & 2);
1371 val = (val & ~0x1f8) | ((val >> 1) & 0xa8)
1372 | ((val & 0xa8) << 1);
1373 }
1374
Patrick Rudolph371d2912015-10-09 13:33:25 +02001375 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001376 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000);
1377 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
1378 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1379 (slotrank << 24) | (reg << 20) | val | 0x60000);
1380 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1381
Patrick Rudolph371d2912015-10-09 13:33:25 +02001382 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001383 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000);
1384 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001);
1385 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
1386 (slotrank << 24) | (reg << 20) | val | 0x60000);
1387 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1388
Patrick Rudolph371d2912015-10-09 13:33:25 +02001389 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001390 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000);
1391 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1392 0x1001 | (ctrl->tMOD << 16));
1393 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1394 (slotrank << 24) | (reg << 20) | val | 0x60000);
1395 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1396 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
1397}
1398
1399static u32 make_mr0(ramctr_timing * ctrl, u8 rank)
1400{
1401 u16 mr0reg, mch_cas, mch_wr;
1402 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 +02001403
1404 /* DLL Reset - self clearing - set after CLK frequency has been changed */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001405 mr0reg = 0x100;
1406
1407 // Convert CAS to MCH register friendly
1408 if (ctrl->CAS < 12) {
1409 mch_cas = (u16) ((ctrl->CAS - 4) << 1);
1410 } else {
1411 mch_cas = (u16) (ctrl->CAS - 12);
1412 mch_cas = ((mch_cas << 1) | 0x1);
1413 }
1414
1415 // Convert tWR to MCH register friendly
1416 mch_wr = mch_wr_t[ctrl->tWR - 5];
1417
1418 mr0reg = (mr0reg & ~0x4) | (mch_cas & 0x1);
1419 mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3);
1420 mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001421
1422 // Precharge PD - Fast (desktop) 0x1 or slow (mobile) 0x0 - mostly power-saving feature
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001423 mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12);
1424 return mr0reg;
1425}
1426
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001427static void dram_mr0(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001428{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001429 write_mrreg(ctrl, channel, rank, 0,
1430 make_mr0(ctrl, rank));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001431}
1432
1433static u32 encode_odt(u32 odt)
1434{
1435 switch (odt) {
1436 case 30:
1437 return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4
1438 case 60:
1439 return (1 << 2); // RZQ/4
1440 case 120:
1441 return (1 << 6); // RZQ/2
1442 default:
1443 case 0:
1444 return 0;
1445 }
1446}
1447
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001448static u32 make_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001449{
1450 odtmap odt;
1451 u32 mr1reg;
1452
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001453 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001454 mr1reg = 0x2;
1455
1456 mr1reg |= encode_odt(odt.rttnom);
1457
1458 return mr1reg;
1459}
1460
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001461static void dram_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001462{
1463 u16 mr1reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001464
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001465 mr1reg = make_mr1(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001466
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001467 write_mrreg(ctrl, channel, rank, 1, mr1reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001468}
1469
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001470static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001471{
1472 u16 pasr, cwl, mr2reg;
1473 odtmap odt;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001474 int srt;
1475
1476 pasr = 0;
1477 cwl = ctrl->CWL - 5;
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001478 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001479
1480 srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh;
1481
1482 mr2reg = 0;
1483 mr2reg = (mr2reg & ~0x7) | pasr;
1484 mr2reg = (mr2reg & ~0x38) | (cwl << 3);
1485 mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6);
1486 mr2reg = (mr2reg & ~0x80) | (srt << 7);
1487 mr2reg |= (odt.rttwr / 60) << 9;
1488
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001489 write_mrreg(ctrl, channel, rank, 2, mr2reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001490}
1491
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001492static void dram_mr3(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001493{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001494 write_mrreg(ctrl, channel, rank, 3, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001495}
1496
1497static void dram_mrscommands(ramctr_timing * ctrl)
1498{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001499 u8 slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001500 u32 reg, addr;
1501 int channel;
1502
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001503 FOR_ALL_POPULATED_CHANNELS {
1504 FOR_ALL_POPULATED_RANKS {
1505 // MR2
1506 dram_mr2(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001507
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001508 // MR3
1509 dram_mr3(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001510
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001511 // MR1
1512 dram_mr1(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001513
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001514 // MR0
1515 dram_mr0(ctrl, slotrank, channel);
1516 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001517 }
1518
Patrick Rudolph371d2912015-10-09 13:33:25 +02001519 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001520 write32(DEFAULT_MCHBAR + 0x4e20, 0x7);
1521 write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001);
1522 write32(DEFAULT_MCHBAR + 0x4e00, 0x60002);
1523 write32(DEFAULT_MCHBAR + 0x4e10, 0);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001524
1525 /* DRAM command ZQCL */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001526 write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003);
1527 write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001);
1528 write32(DEFAULT_MCHBAR + 0x4e04, 0x60400);
1529 write32(DEFAULT_MCHBAR + 0x4e14, 0x288);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001530
1531 /* execute command queue on all channels ? */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001532 write32(DEFAULT_MCHBAR + 0x4e84, 0x40004);
1533
1534 // Drain
1535 FOR_ALL_CHANNELS {
1536 // Wait for ref drained
1537 wait_428c(channel);
1538 }
1539
1540 // Refresh enable
1541 MCHBAR32(0x5030) |= 8;
1542
1543 FOR_ALL_POPULATED_CHANNELS {
1544 addr = 0x400 * channel + 0x4020;
1545 reg = MCHBAR32(addr);
1546 reg &= ~0x200000;
1547 MCHBAR32(addr) = reg;
1548
1549 wait_428c(channel);
1550
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001551 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001552
1553 // Drain
1554 wait_428c(channel);
1555
Patrick Rudolph371d2912015-10-09 13:33:25 +02001556 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001557 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1558 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
1559 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001560 (slotrank << 24) | 0x60000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001561 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
1562 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1);
1563
1564 // Drain
1565 wait_428c(channel);
1566 }
1567}
1568
1569const u32 lane_registers[] = {
1570 0x0000, 0x0200, 0x0400, 0x0600,
1571 0x1000, 0x1200, 0x1400, 0x1600,
1572 0x0800
1573};
1574
1575static void program_timings(ramctr_timing * ctrl, int channel)
1576{
1577 u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028;
1578 int lane;
1579 int slotrank, slot;
1580 int full_shift = 0;
1581 u16 slot320c[NUM_SLOTS];
1582
1583 FOR_ALL_POPULATED_RANKS {
1584 if (full_shift < -ctrl->timings[channel][slotrank].val_320c)
1585 full_shift = -ctrl->timings[channel][slotrank].val_320c;
1586 }
1587
1588 for (slot = 0; slot < NUM_SLOTS; slot++)
1589 switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) {
1590 case 0:
1591 default:
1592 slot320c[slot] = 0x7f;
1593 break;
1594 case 1:
1595 slot320c[slot] =
1596 ctrl->timings[channel][2 * slot + 0].val_320c +
1597 full_shift;
1598 break;
1599 case 2:
1600 slot320c[slot] =
1601 ctrl->timings[channel][2 * slot + 1].val_320c +
1602 full_shift;
1603 break;
1604 case 3:
1605 slot320c[slot] =
1606 (ctrl->timings[channel][2 * slot].val_320c +
1607 ctrl->timings[channel][2 * slot +
1608 1].val_320c) / 2 +
1609 full_shift;
1610 break;
1611 }
1612
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001613 /* enable CMD XOVER */
1614 reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001615 reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
1616 reg32 |= (slot320c[1] & 0x7f) << 18;
1617 reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
1618
1619 MCHBAR32(0x320c + 0x100 * channel) = reg32;
1620
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001621 /* enable CLK XOVER */
1622 reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001623 reg_c18 = 0;
1624
1625 FOR_ALL_POPULATED_RANKS {
1626 int shift =
1627 ctrl->timings[channel][slotrank].val_320c + full_shift;
1628 int offset_val_c14;
1629 if (shift < 0)
1630 shift = 0;
1631 offset_val_c14 = ctrl->reg_c14_offset + shift;
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001632 /* set CLK phase shift */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001633 reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
1634 reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
1635 }
1636
1637 MCHBAR32(0xc14 + channel * 0x100) = reg_c14;
1638 MCHBAR32(0xc18 + channel * 0x100) = reg_c18;
1639
1640 reg_4028 = MCHBAR32(0x4028 + 0x400 * channel);
1641 reg_4028 &= 0xffff0000;
1642
1643 reg_4024 = 0;
1644
1645 FOR_ALL_POPULATED_RANKS {
1646 int post_timA_min_high = 7, post_timA_max_high = 0;
1647 int pre_timA_min_high = 7, pre_timA_max_high = 0;
1648 int shift_402x = 0;
1649 int shift =
1650 ctrl->timings[channel][slotrank].val_320c + full_shift;
1651
1652 if (shift < 0)
1653 shift = 0;
1654
1655 FOR_ALL_LANES {
1656 if (post_timA_min_high >
1657 ((ctrl->timings[channel][slotrank].lanes[lane].
1658 timA + shift) >> 6))
1659 post_timA_min_high =
1660 ((ctrl->timings[channel][slotrank].
1661 lanes[lane].timA + shift) >> 6);
1662 if (pre_timA_min_high >
1663 (ctrl->timings[channel][slotrank].lanes[lane].
1664 timA >> 6))
1665 pre_timA_min_high =
1666 (ctrl->timings[channel][slotrank].
1667 lanes[lane].timA >> 6);
1668 if (post_timA_max_high <
1669 ((ctrl->timings[channel][slotrank].lanes[lane].
1670 timA + shift) >> 6))
1671 post_timA_max_high =
1672 ((ctrl->timings[channel][slotrank].
1673 lanes[lane].timA + shift) >> 6);
1674 if (pre_timA_max_high <
1675 (ctrl->timings[channel][slotrank].lanes[lane].
1676 timA >> 6))
1677 pre_timA_max_high =
1678 (ctrl->timings[channel][slotrank].
1679 lanes[lane].timA >> 6);
1680 }
1681
1682 if (pre_timA_max_high - pre_timA_min_high <
1683 post_timA_max_high - post_timA_min_high)
1684 shift_402x = +1;
1685 else if (pre_timA_max_high - pre_timA_min_high >
1686 post_timA_max_high - post_timA_min_high)
1687 shift_402x = -1;
1688
1689 reg_4028 |=
1690 (ctrl->timings[channel][slotrank].val_4028 + shift_402x -
1691 post_timA_min_high) << (4 * slotrank);
1692 reg_4024 |=
1693 (ctrl->timings[channel][slotrank].val_4024 +
1694 shift_402x) << (8 * slotrank);
1695
1696 FOR_ALL_LANES {
1697 MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel +
1698 4 * slotrank)
1699 =
1700 (((ctrl->timings[channel][slotrank].lanes[lane].
1701 timA + shift) & 0x3f)
1702 |
1703 ((ctrl->timings[channel][slotrank].lanes[lane].
1704 rising + shift) << 8)
1705 |
1706 (((ctrl->timings[channel][slotrank].lanes[lane].
1707 timA + shift -
1708 (post_timA_min_high << 6)) & 0x1c0) << 10)
Patrick Rudolph0188b132016-02-10 19:16:34 +01001709 | ((ctrl->timings[channel][slotrank].lanes[lane].
1710 falling + shift) << 20));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001711
1712 MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel +
1713 4 * slotrank)
1714 =
1715 (((ctrl->timings[channel][slotrank].lanes[lane].
1716 timC + shift) & 0x3f)
1717 |
1718 (((ctrl->timings[channel][slotrank].lanes[lane].
1719 timB + shift) & 0x3f) << 8)
1720 |
1721 (((ctrl->timings[channel][slotrank].lanes[lane].
1722 timB + shift) & 0x1c0) << 9)
1723 |
1724 (((ctrl->timings[channel][slotrank].lanes[lane].
1725 timC + shift) & 0x40) << 13));
1726 }
1727 }
1728 MCHBAR32(0x4024 + 0x400 * channel) = reg_4024;
1729 MCHBAR32(0x4028 + 0x400 * channel) = reg_4028;
1730}
1731
1732static void test_timA(ramctr_timing * ctrl, int channel, int slotrank)
1733{
1734 wait_428c(channel);
1735
Patrick Rudolph371d2912015-10-09 13:33:25 +02001736 /* DRAM command MRS
1737 * write MR3 MPR enable
1738 * in this mode only RD and RDA are allowed
1739 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001740 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
1741 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1742 (0xc01 | (ctrl->tMOD << 16)));
1743 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1744 (slotrank << 24) | 0x360004);
1745 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1746
Patrick Rudolph371d2912015-10-09 13:33:25 +02001747 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001748 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
1749 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01);
1750 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24));
1751 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1752
Patrick Rudolph371d2912015-10-09 13:33:25 +02001753 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001754 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
1755 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1756 0x100f | ((ctrl->CAS + 36) << 16));
1757 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1758 (slotrank << 24) | 0x60000);
1759 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1760
Patrick Rudolph371d2912015-10-09 13:33:25 +02001761 /* DRAM command MRS
1762 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001763 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
1764 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
1765 (0xc01 | (ctrl->tMOD << 16)));
1766 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
1767 (slotrank << 24) | 0x360000);
1768 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
1769
1770 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
1771
1772 wait_428c(channel);
1773}
1774
1775static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank,
1776 int lane)
1777{
1778 u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA;
1779 return ((read32
1780 (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 +
1781 ((timA / 32) & 1) * 4)
1782 >> (timA % 32)) & 1);
1783}
1784
1785struct run {
1786 int middle;
1787 int end;
1788 int start;
1789 int all;
1790 int length;
1791};
1792
1793static struct run get_longest_zero_run(int *seq, int sz)
1794{
1795 int i, ls;
1796 int bl = 0, bs = 0;
1797 struct run ret;
1798
1799 ls = 0;
1800 for (i = 0; i < 2 * sz; i++)
1801 if (seq[i % sz]) {
1802 if (i - ls > bl) {
1803 bl = i - ls;
1804 bs = ls;
1805 }
1806 ls = i + 1;
1807 }
1808 if (bl == 0) {
1809 ret.middle = sz / 2;
1810 ret.start = 0;
1811 ret.end = sz;
1812 ret.all = 1;
1813 return ret;
1814 }
1815
1816 ret.start = bs % sz;
1817 ret.end = (bs + bl - 1) % sz;
1818 ret.middle = (bs + (bl - 1) / 2) % sz;
1819 ret.length = bl;
1820 ret.all = 0;
1821
1822 return ret;
1823}
1824
1825static void discover_timA_coarse(ramctr_timing * ctrl, int channel,
1826 int slotrank, int *upperA)
1827{
1828 int timA;
1829 int statistics[NUM_LANES][128];
1830 int lane;
1831
1832 for (timA = 0; timA < 128; timA++) {
1833 FOR_ALL_LANES {
1834 ctrl->timings[channel][slotrank].lanes[lane].timA = timA;
1835 }
1836 program_timings(ctrl, channel);
1837
1838 test_timA(ctrl, channel, slotrank);
1839
1840 FOR_ALL_LANES {
1841 statistics[lane][timA] =
1842 !does_lane_work(ctrl, channel, slotrank, lane);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001843 printram("Astat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001844 channel, slotrank, lane, timA,
1845 statistics[lane][timA]);
1846 }
1847 }
1848 FOR_ALL_LANES {
1849 struct run rn = get_longest_zero_run(statistics[lane], 128);
1850 ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle;
1851 upperA[lane] = rn.end;
1852 if (upperA[lane] < rn.middle)
1853 upperA[lane] += 128;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001854 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001855 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001856 printram("Aend: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001857 lane, upperA[lane]);
1858 }
1859}
1860
1861static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
1862 int *upperA)
1863{
1864 int timA_delta;
1865 int statistics[NUM_LANES][51];
1866 int lane, i;
1867
1868 memset(statistics, 0, sizeof(statistics));
1869
1870 for (timA_delta = -25; timA_delta <= 25; timA_delta++) {
1871 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
1872 timA = upperA[lane] + timA_delta + 0x40;
1873 program_timings(ctrl, channel);
1874
1875 for (i = 0; i < 100; i++) {
1876 test_timA(ctrl, channel, slotrank);
1877 FOR_ALL_LANES {
1878 statistics[lane][timA_delta + 25] +=
1879 does_lane_work(ctrl, channel, slotrank,
1880 lane);
1881 }
1882 }
1883 }
1884 FOR_ALL_LANES {
1885 int last_zero, first_all;
1886
1887 for (last_zero = -25; last_zero <= 25; last_zero++)
1888 if (statistics[lane][last_zero + 25])
1889 break;
1890 last_zero--;
1891 for (first_all = -25; first_all <= 25; first_all++)
1892 if (statistics[lane][first_all + 25] == 100)
1893 break;
1894
1895 printram("lane %d: %d, %d\n", lane, last_zero,
1896 first_all);
1897
1898 ctrl->timings[channel][slotrank].lanes[lane].timA =
1899 (last_zero + first_all) / 2 + upperA[lane];
Patrick Rudolpha649a542016-01-17 18:32:06 +01001900 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001901 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
1902 }
1903}
1904
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001905static int discover_402x(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001906 int *upperA)
1907{
1908 int works[NUM_LANES];
1909 int lane;
1910 while (1) {
1911 int all_works = 1, some_works = 0;
1912 program_timings(ctrl, channel);
1913 test_timA(ctrl, channel, slotrank);
1914 FOR_ALL_LANES {
1915 works[lane] =
1916 !does_lane_work(ctrl, channel, slotrank, lane);
1917 if (works[lane])
1918 some_works = 1;
1919 else
1920 all_works = 0;
1921 }
1922 if (all_works)
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001923 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001924 if (!some_works) {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001925 if (ctrl->timings[channel][slotrank].val_4024 < 2) {
1926 printk(BIOS_EMERG, "402x discovery failed (1): %d, %d\n",
1927 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001928 return MAKE_ERR;
1929 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001930 ctrl->timings[channel][slotrank].val_4024 -= 2;
1931 printram("4024 -= 2;\n");
1932 continue;
1933 }
1934 ctrl->timings[channel][slotrank].val_4028 += 2;
1935 printram("4028 += 2;\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001936 if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) {
1937 printk(BIOS_EMERG, "402x discovery failed (2): %d, %d\n",
1938 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001939 return MAKE_ERR;
1940 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001941 FOR_ALL_LANES if (works[lane]) {
1942 ctrl->timings[channel][slotrank].lanes[lane].timA +=
1943 128;
1944 upperA[lane] += 128;
1945 printram("increment %d, %d, %d\n", channel,
1946 slotrank, lane);
1947 }
1948 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001949 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001950}
1951
1952struct timA_minmax {
1953 int timA_min_high, timA_max_high;
1954};
1955
1956static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1957 struct timA_minmax *mnmx)
1958{
1959 int lane;
1960 mnmx->timA_min_high = 7;
1961 mnmx->timA_max_high = 0;
1962
1963 FOR_ALL_LANES {
1964 if (mnmx->timA_min_high >
1965 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1966 mnmx->timA_min_high =
1967 (ctrl->timings[channel][slotrank].lanes[lane].
1968 timA >> 6);
1969 if (mnmx->timA_max_high <
1970 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1971 mnmx->timA_max_high =
1972 (ctrl->timings[channel][slotrank].lanes[lane].
1973 timA >> 6);
1974 }
1975}
1976
1977static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1978 struct timA_minmax *mnmx)
1979{
1980 struct timA_minmax post;
1981 int shift_402x = 0;
1982
1983 /* Get changed maxima. */
1984 pre_timA_change(ctrl, channel, slotrank, &post);
1985
1986 if (mnmx->timA_max_high - mnmx->timA_min_high <
1987 post.timA_max_high - post.timA_min_high)
1988 shift_402x = +1;
1989 else if (mnmx->timA_max_high - mnmx->timA_min_high >
1990 post.timA_max_high - post.timA_min_high)
1991 shift_402x = -1;
1992 else
1993 shift_402x = 0;
1994
1995 ctrl->timings[channel][slotrank].val_4028 += shift_402x;
1996 ctrl->timings[channel][slotrank].val_4024 += shift_402x;
1997 printram("4024 += %d;\n", shift_402x);
1998 printram("4028 += %d;\n", shift_402x);
1999}
2000
Patrick Rudolph371d2912015-10-09 13:33:25 +02002001/* Compensate the skew between DQS and DQs.
2002 * To ease PCB design a small skew between Data Strobe signals and
2003 * Data Signals is allowed.
2004 * The controller has to measure and compensate this skew for every byte-lane.
2005 * By delaying either all DQs signals or DQS signal, a full phase
2006 * shift can be introduced.
2007 * It is assumed that one byte-lane's DQs signals have the same routing delay.
2008 *
2009 * To measure the actual skew, the DRAM is placed in "read leveling" mode.
2010 * In read leveling mode the DRAM-chip outputs an alternating periodic pattern.
2011 * The memory controller iterates over all possible values to do a full phase shift
2012 * and issues read commands.
2013 * With DQS and DQs in phase the data read is expected to alternate on every byte:
2014 * 0xFF 0x00 0xFF ...
2015 * Once the controller has detected this pattern a bit in the result register is
2016 * set for the current phase shift.
2017 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002018static int read_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002019{
2020 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002021 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002022
2023 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002024 int all_high, some_high;
2025 int upperA[NUM_LANES];
2026 struct timA_minmax mnmx;
2027
2028 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002029
2030 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002031 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2032 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2033 0xc01 | (ctrl->tRP << 16));
2034 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2035 (slotrank << 24) | 0x60400);
2036 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2037 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2038
2039 write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001);
2040
2041 ctrl->timings[channel][slotrank].val_4028 = 4;
2042 ctrl->timings[channel][slotrank].val_4024 = 55;
2043 program_timings(ctrl, channel);
2044
2045 discover_timA_coarse(ctrl, channel, slotrank, upperA);
2046
2047 all_high = 1;
2048 some_high = 0;
2049 FOR_ALL_LANES {
2050 if (ctrl->timings[channel][slotrank].lanes[lane].
2051 timA >= 0x40)
2052 some_high = 1;
2053 else
2054 all_high = 0;
2055 }
2056
2057 if (all_high) {
2058 ctrl->timings[channel][slotrank].val_4028--;
2059 printram("4028--;\n");
2060 FOR_ALL_LANES {
2061 ctrl->timings[channel][slotrank].lanes[lane].
2062 timA -= 0x40;
2063 upperA[lane] -= 0x40;
2064
2065 }
2066 } else if (some_high) {
2067 ctrl->timings[channel][slotrank].val_4024++;
2068 ctrl->timings[channel][slotrank].val_4028++;
2069 printram("4024++;\n");
2070 printram("4028++;\n");
2071 }
2072
2073 program_timings(ctrl, channel);
2074
2075 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2076
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002077 err = discover_402x(ctrl, channel, slotrank, upperA);
2078 if (err)
2079 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002080
2081 post_timA_change(ctrl, channel, slotrank, &mnmx);
2082 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2083
2084 discover_timA_fine(ctrl, channel, slotrank, upperA);
2085
2086 post_timA_change(ctrl, channel, slotrank, &mnmx);
2087 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2088
2089 FOR_ALL_LANES {
2090 ctrl->timings[channel][slotrank].lanes[lane].timA -= mnmx.timA_min_high * 0x40;
2091 }
2092 ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high;
2093 printram("4028 -= %d;\n", mnmx.timA_min_high);
2094
2095 post_timA_change(ctrl, channel, slotrank, &mnmx);
2096
2097 printram("4/8: %d, %d, %x, %x\n", channel, slotrank,
2098 ctrl->timings[channel][slotrank].val_4024,
2099 ctrl->timings[channel][slotrank].val_4028);
2100
Patrick Rudolpha649a542016-01-17 18:32:06 +01002101 printram("final results:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002102 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01002103 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002104 lane,
2105 ctrl->timings[channel][slotrank].lanes[lane].timA);
2106
2107 write32(DEFAULT_MCHBAR + 0x3400, 0);
2108
Patrick Rudolph9b515682015-10-09 13:43:51 +02002109 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002110 }
2111
2112 FOR_ALL_POPULATED_CHANNELS {
2113 program_timings(ctrl, channel);
2114 }
2115 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2116 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
2117 + 4 * lane, 0);
2118 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002119 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002120}
2121
2122static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
2123{
2124 int lane;
2125
2126 FOR_ALL_LANES {
2127 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0);
2128 read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane);
2129 }
2130
2131 wait_428c(channel);
2132
Patrick Rudolph371d2912015-10-09 13:33:25 +02002133 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002134 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2135 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2136 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
2137 | 4 | (ctrl->tRCD << 16));
2138
2139 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2140 (slotrank << 24) | (6 << 16));
2141
2142 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
2143
Patrick Rudolph371d2912015-10-09 13:33:25 +02002144 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002145 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2146 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001);
2147 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2148 (slotrank << 24) | 8);
2149 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2150
Patrick Rudolph371d2912015-10-09 13:33:25 +02002151 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002152 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2153 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4);
2154 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2155 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2156
Patrick Rudolph371d2912015-10-09 13:33:25 +02002157 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002158 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2159 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2160 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2161 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2162 (slotrank << 24) | 8);
2163 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2164
2165 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2166
2167 wait_428c(channel);
2168
Patrick Rudolph371d2912015-10-09 13:33:25 +02002169 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002170 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2171 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2172 0xc01 | (ctrl->tRP << 16));
2173 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2174 (slotrank << 24) | 0x60400);
2175 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2176
Patrick Rudolph371d2912015-10-09 13:33:25 +02002177 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002178 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2179 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2180 (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10)
2181 | 8 | (ctrl->CAS << 16));
2182
2183 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2184 (slotrank << 24) | 0x60000);
2185
2186 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244);
2187
Patrick Rudolph371d2912015-10-09 13:33:25 +02002188 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002189 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2190 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2191 0x40011f4 | (max(ctrl->tRTP, 8) << 16));
2192 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2193 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2194
Patrick Rudolph371d2912015-10-09 13:33:25 +02002195 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002196 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2197 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2198 0xc01 | (ctrl->tRP << 16));
2199 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2200 (slotrank << 24) | 0x60400);
2201 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2202 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2203 wait_428c(channel);
2204}
2205
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002206static int discover_timC(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002207{
2208 int timC;
2209 int statistics[NUM_LANES][MAX_TIMC + 1];
2210 int lane;
2211
2212 wait_428c(channel);
2213
Patrick Rudolph371d2912015-10-09 13:33:25 +02002214 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002215 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2216 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2217 0xc01 | (ctrl->tRP << 16));
2218 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2219 (slotrank << 24) | 0x60400);
2220 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2221 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2222
2223 for (timC = 0; timC <= MAX_TIMC; timC++) {
2224 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
2225 timC = timC;
2226 program_timings(ctrl, channel);
2227
2228 test_timC(ctrl, channel, slotrank);
2229
2230 FOR_ALL_LANES {
2231 statistics[lane][timC] =
2232 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2233 0x400 * channel);
2234 printram("Cstat: %d, %d, %d, %x, %x\n",
2235 channel, slotrank, lane, timC,
2236 statistics[lane][timC]);
2237 }
2238 }
2239 FOR_ALL_LANES {
2240 struct run rn =
2241 get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
2242 ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002243 if (rn.all) {
2244 printk(BIOS_EMERG, "timC discovery failed: %d, %d, %d\n",
2245 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002246 return MAKE_ERR;
2247 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002248 printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002249 lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
2250 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002251 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002252}
2253
2254static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
2255{
2256 int channel, ret = 0;
2257 FOR_ALL_POPULATED_CHANNELS if (channel < target_channel)
2258 ret++;
2259 return ret;
2260}
2261
2262static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b)
2263{
2264 unsigned j;
2265 unsigned channel_offset =
2266 get_precedening_channels(ctrl, channel) * 0x40;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002267 for (j = 0; j < 16; j++)
2268 write32((void *)(0x04000000 + channel_offset + 4 * j), j & 2 ? b : a);
2269 sfence();
2270}
2271
2272static int num_of_channels(const ramctr_timing * ctrl)
2273{
2274 int ret = 0;
2275 int channel;
2276 FOR_ALL_POPULATED_CHANNELS ret++;
2277 return ret;
2278}
2279
2280static void fill_pattern1(ramctr_timing * ctrl, int channel)
2281{
2282 unsigned j;
2283 unsigned channel_offset =
2284 get_precedening_channels(ctrl, channel) * 0x40;
2285 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2286 for (j = 0; j < 16; j++)
2287 write32((void *)(0x04000000 + channel_offset + j * 4), 0xffffffff);
2288 for (j = 0; j < 16; j++)
2289 write32((void *)(0x04000000 + channel_offset + channel_step + j * 4), 0);
2290 sfence();
2291}
2292
2293static void precharge(ramctr_timing * ctrl)
2294{
2295 int channel, slotrank, lane;
2296
2297 FOR_ALL_POPULATED_CHANNELS {
2298 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2299 ctrl->timings[channel][slotrank].lanes[lane].falling =
2300 16;
2301 ctrl->timings[channel][slotrank].lanes[lane].rising =
2302 16;
Patrick Rudolpha649a542016-01-17 18:32:06 +01002303 }
2304
2305 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002306
2307 FOR_ALL_POPULATED_RANKS {
2308 wait_428c(channel);
2309
Patrick Rudolph371d2912015-10-09 13:33:25 +02002310 /* DRAM command MRS
2311 * write MR3 MPR enable
2312 * in this mode only RD and RDA are allowed
2313 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002314 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2315 0x1f000);
2316 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2317 0xc01 | (ctrl->tMOD << 16));
2318 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2319 (slotrank << 24) | 0x360004);
2320 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2321
Patrick Rudolph371d2912015-10-09 13:33:25 +02002322 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002323 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2324 0x1f105);
2325 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2326 0x4041003);
2327 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2328 (slotrank << 24) | 0);
2329 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2330
Patrick Rudolph371d2912015-10-09 13:33:25 +02002331 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002332 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2333 0x1f105);
2334 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2335 0x1001 | ((ctrl->CAS + 8) << 16));
2336 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2337 (slotrank << 24) | 0x60000);
2338 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2339
Patrick Rudolph371d2912015-10-09 13:33:25 +02002340 /* DRAM command MRS
2341 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002342 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2343 0x1f000);
2344 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2345 0xc01 | (ctrl->tMOD << 16));
2346 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2347 (slotrank << 24) | 0x360000);
2348 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2349 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2350 0xc0001);
2351
2352 wait_428c(channel);
2353 }
2354
2355 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2356 ctrl->timings[channel][slotrank].lanes[lane].falling =
2357 48;
2358 ctrl->timings[channel][slotrank].lanes[lane].rising =
2359 48;
2360 }
2361
2362 program_timings(ctrl, channel);
2363
2364 FOR_ALL_POPULATED_RANKS {
2365 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002366 /* DRAM command MRS
2367 * write MR3 MPR enable
2368 * in this mode only RD and RDA are allowed
2369 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002370 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2371 0x1f000);
2372 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2373 0xc01 | (ctrl->tMOD << 16));
2374 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2375 (slotrank << 24) | 0x360004);
2376 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2377
Patrick Rudolph371d2912015-10-09 13:33:25 +02002378 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002379 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2380 0x1f105);
2381 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2382 0x4041003);
2383 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2384 (slotrank << 24) | 0);
2385 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2386
Patrick Rudolph371d2912015-10-09 13:33:25 +02002387 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002388 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2389 0x1f105);
2390 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2391 0x1001 | ((ctrl->CAS + 8) << 16));
2392 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2393 (slotrank << 24) | 0x60000);
2394 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2395
Patrick Rudolph371d2912015-10-09 13:33:25 +02002396 /* DRAM command MRS
2397 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002398 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2399 0x1f000);
2400 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2401 0xc01 | (ctrl->tMOD << 16));
2402
2403 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2404 (slotrank << 24) | 0x360000);
2405 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2406
2407 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2408 0xc0001);
2409 wait_428c(channel);
2410 }
2411 }
2412}
2413
2414static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
2415{
Patrick Rudolph371d2912015-10-09 13:33:25 +02002416 /* enable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002417 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002418 0x80 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002419
2420 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002421 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002422 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207);
2423 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2424 0x8000c01 | ((ctrl->CWL + ctrl->tWLO) << 16));
2425 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2426 8 | (slotrank << 24));
2427 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2428
Patrick Rudolph371d2912015-10-09 13:33:25 +02002429 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002430 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107);
2431 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2432 0x4000c01 | ((ctrl->CAS + 38) << 16));
2433 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2434 (slotrank << 24) | 4);
2435 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2436
2437 write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001);
2438 wait_428c(channel);
2439
Patrick Rudolph371d2912015-10-09 13:33:25 +02002440 /* disable 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 0x1080 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002443}
2444
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002445static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002446{
2447 int timB;
2448 int statistics[NUM_LANES][128];
2449 int lane;
2450
2451 write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2));
2452
2453 for (timB = 0; timB < 128; timB++) {
2454 FOR_ALL_LANES {
2455 ctrl->timings[channel][slotrank].lanes[lane].timB = timB;
2456 }
2457 program_timings(ctrl, channel);
2458
2459 test_timB(ctrl, channel, slotrank);
2460
2461 FOR_ALL_LANES {
2462 statistics[lane][timB] =
2463 !((read32
2464 (DEFAULT_MCHBAR + lane_registers[lane] +
2465 channel * 0x100 + 4 + ((timB / 32) & 1) * 4)
2466 >> (timB % 32)) & 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002467 printram("Bstat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002468 channel, slotrank, lane, timB,
2469 statistics[lane][timB]);
2470 }
2471 }
2472 FOR_ALL_LANES {
2473 struct run rn = get_longest_zero_run(statistics[lane], 128);
Patrick Rudolphd912f1d2016-02-15 20:07:42 +01002474 /* timC is a direct function of timB's 6 LSBs.
2475 * Some tests increments the value of timB by a small value,
2476 * which might cause the 6bit value to overflow, if it's close
2477 * to 0x3F. Increment the value by a small offset if it's likely
2478 * to overflow, to make sure it won't overflow while running
2479 * tests and bricks the system due to a non matching timC.
2480 *
2481 * TODO: find out why some tests (edge write discovery)
2482 * increment timB. */
2483 if ((rn.start & 0x3F) == 0x3E)
2484 rn.start += 2;
2485 else if ((rn.start & 0x3F) == 0x3F)
2486 rn.start += 1;
Vladimir Serbinenko3141eac2016-01-29 19:42:02 +01002487 ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002488 if (rn.all) {
2489 printk(BIOS_EMERG, "timB discovery failed: %d, %d, %d\n",
2490 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002491 return MAKE_ERR;
2492 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002493 printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002494 lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
2495 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002496 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002497}
2498
2499static int get_timB_high_adjust(u64 val)
2500{
2501 int i;
2502
2503 /* good */
2504 if (val == 0xffffffffffffffffLL)
2505 return 0;
2506
2507 if (val >= 0xf000000000000000LL) {
2508 /* needs negative adjustment */
2509 for (i = 0; i < 8; i++)
2510 if (val << (8 * (7 - i) + 4))
2511 return -i;
2512 } else {
2513 /* needs positive adjustment */
2514 for (i = 0; i < 8; i++)
2515 if (val >> (8 * (7 - i) + 4))
2516 return i;
2517 }
2518 return 8;
2519}
2520
2521static void adjust_high_timB(ramctr_timing * ctrl)
2522{
2523 int channel, slotrank, lane, old;
2524 write32(DEFAULT_MCHBAR + 0x3400, 0x200);
2525 FOR_ALL_POPULATED_CHANNELS {
2526 fill_pattern1(ctrl, channel);
2527 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 1);
2528 }
2529 FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
2530
2531 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001);
2532
2533 wait_428c(channel);
2534
Patrick Rudolph371d2912015-10-09 13:33:25 +02002535 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002536 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2537 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2538 0xc01 | (ctrl->tRCD << 16));
2539 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2540 (slotrank << 24) | 0x60000);
2541 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2542
Patrick Rudolph371d2912015-10-09 13:33:25 +02002543 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002544 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2545 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01);
2546 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2547 (slotrank << 24) | 0x8);
2548 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2549
Patrick Rudolph371d2912015-10-09 13:33:25 +02002550 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002551 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2552 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003);
2553 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2554 (slotrank << 24));
2555 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2);
2556
Patrick Rudolph371d2912015-10-09 13:33:25 +02002557 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002558 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2559 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2560 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2561 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2562 (slotrank << 24) | 0x8);
2563 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2564
2565 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2566
2567 wait_428c(channel);
2568
Patrick Rudolph371d2912015-10-09 13:33:25 +02002569 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002570 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2571 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2572 0xc01 | ((ctrl->tRP) << 16));
2573 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2574 (slotrank << 24) | 0x60400);
2575 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2576
Patrick Rudolph371d2912015-10-09 13:33:25 +02002577 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002578 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2579 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2580 0xc01 | ((ctrl->tRCD) << 16));
2581 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2582 (slotrank << 24) | 0x60000);
2583 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2584
Patrick Rudolph371d2912015-10-09 13:33:25 +02002585 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002586 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105);
2587 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2588 0x4000c01 |
2589 ((ctrl->tRP +
2590 ctrl->timings[channel][slotrank].val_4024 +
2591 ctrl->timings[channel][slotrank].val_4028) << 16));
2592 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2593 (slotrank << 24) | 0x60008);
2594 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2595
2596 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
2597 wait_428c(channel);
2598 FOR_ALL_LANES {
2599 u64 res =
2600 read32(DEFAULT_MCHBAR + lane_registers[lane] +
2601 0x100 * channel + 4);
2602 res |=
2603 ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] +
2604 0x100 * channel + 8)) << 32;
2605 old = ctrl->timings[channel][slotrank].lanes[lane].timB;
2606 ctrl->timings[channel][slotrank].lanes[lane].timB +=
2607 get_timB_high_adjust(res) * 64;
2608
Patrick Rudolpha649a542016-01-17 18:32:06 +01002609 printram("High adjust %d:%016llx\n", lane, res);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002610 printram("Bval+: %d, %d, %d, %x -> %x\n", channel,
2611 slotrank, lane, old,
2612 ctrl->timings[channel][slotrank].lanes[lane].
2613 timB);
2614 }
2615 }
2616 write32(DEFAULT_MCHBAR + 0x3400, 0);
2617}
2618
2619static void write_op(ramctr_timing * ctrl, int channel)
2620{
2621 int slotrank;
2622
2623 wait_428c(channel);
2624
2625 /* choose an existing rank. */
2626 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2627
Patrick Rudolph371d2912015-10-09 13:33:25 +02002628 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002629 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2630 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2631
2632 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2633 (slotrank << 24) | 0x60000);
2634
2635 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2636
2637 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2638 wait_428c(channel);
2639}
2640
Patrick Rudolph371d2912015-10-09 13:33:25 +02002641/* Compensate the skew between CMD/ADDR/CLK and DQ/DQS lanes.
2642 * DDR3 adopted the fly-by topology. The data and strobes signals reach
2643 * the chips at different times with respect to command, address and
2644 * clock signals.
2645 * By delaying either all DQ/DQs or all CMD/ADDR/CLK signals, a full phase
2646 * shift can be introduced.
2647 * It is assumed that the CLK/ADDR/CMD signals have the same routing delay.
2648 *
2649 * To find the required phase shift the DRAM is placed in "write leveling" mode.
2650 * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
2651 * sampled value on the data lanes (DQs).
2652 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002653static int write_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002654{
2655 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002656 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002657
2658 FOR_ALL_POPULATED_CHANNELS
2659 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
2660 read32(DEFAULT_MCHBAR + 0x4008 +
2661 0x400 * channel) | 0x8000000);
2662
2663 FOR_ALL_POPULATED_CHANNELS {
2664 write_op(ctrl, channel);
2665 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2666 read32(DEFAULT_MCHBAR + 0x4020 +
2667 0x400 * channel) | 0x200000);
2668 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002669
2670 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002671 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2672 FOR_ALL_POPULATED_CHANNELS {
2673 write_op(ctrl, channel);
2674 }
2675
Patrick Rudolph371d2912015-10-09 13:33:25 +02002676 /* enable write leveling on all ranks
2677 * disable all DQ outputs
2678 * only NOP is allowed in this mode */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002679 FOR_ALL_CHANNELS
2680 FOR_ALL_POPULATED_RANKS
2681 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002682 make_mr1(ctrl, slotrank, channel) | 0x1080);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002683
2684 write32(DEFAULT_MCHBAR + 0x3400, 0x108052);
2685
Patrick Rudolph9b515682015-10-09 13:43:51 +02002686 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002687
Patrick Rudolph371d2912015-10-09 13:33:25 +02002688 /* set any valid value for timB, it gets corrected later */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002689 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2690 err = discover_timB(ctrl, channel, slotrank);
2691 if (err)
2692 return err;
2693 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002694
Patrick Rudolph371d2912015-10-09 13:33:25 +02002695 /* disable write leveling on all ranks */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002696 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2697 write_mrreg(ctrl, channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002698 slotrank, 1, make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002699
2700 write32(DEFAULT_MCHBAR + 0x3400, 0);
2701
2702 FOR_ALL_POPULATED_CHANNELS
2703 wait_428c(channel);
2704
Patrick Rudolph371d2912015-10-09 13:33:25 +02002705 /* refresh enable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002706 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8);
2707
2708 FOR_ALL_POPULATED_CHANNELS {
2709 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2710 ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 +
2711 0x400 * channel));
2712 read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel);
2713 wait_428c(channel);
2714
Patrick Rudolph371d2912015-10-09 13:33:25 +02002715 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002716 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2717 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
2718 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000);
2719 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2720
2721 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2722 wait_428c(channel);
2723 }
2724
Patrick Rudolph9b515682015-10-09 13:43:51 +02002725 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002726
2727 printram("CPE\n");
2728 precharge(ctrl);
2729 printram("CPF\n");
2730
2731 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2732 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2733 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2734 0);
2735 }
2736
2737 FOR_ALL_POPULATED_CHANNELS {
2738 fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555);
2739 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
2740 }
2741
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002742 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2743 err = discover_timC(ctrl, channel, slotrank);
2744 if (err)
2745 return err;
2746 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002747
2748 FOR_ALL_POPULATED_CHANNELS
2749 program_timings(ctrl, channel);
2750
Patrick Rudolph371d2912015-10-09 13:33:25 +02002751 /* measure and adjust timB timings */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002752 adjust_high_timB(ctrl);
2753
2754 FOR_ALL_POPULATED_CHANNELS
2755 program_timings(ctrl, channel);
2756
2757 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2758 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2759 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2760 0);
2761 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002762 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002763}
2764
2765static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
2766{
2767 struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank];
2768 int timC_delta;
2769 int lanes_ok = 0;
2770 int ctr = 0;
2771 int lane;
2772
2773 for (timC_delta = -5; timC_delta <= 5; timC_delta++) {
2774 FOR_ALL_LANES {
2775 ctrl->timings[channel][slotrank].lanes[lane].timC =
2776 saved_rt.lanes[lane].timC + timC_delta;
2777 }
2778 program_timings(ctrl, channel);
2779 FOR_ALL_LANES {
2780 write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0);
2781 }
2782
2783 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2784
2785 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002786 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002787 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2788 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2789 ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10)
2790 | 8 | (ctrl->tRCD << 16));
2791
2792 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2793 (slotrank << 24) | ctr | 0x60000);
2794
2795 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002796 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002797 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
2798 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2799 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16));
2800 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2801 (slotrank << 24));
2802 write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd);
2803 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42);
2804
Patrick Rudolph371d2912015-10-09 13:33:25 +02002805 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002806 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2807 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2808 0x4001020 | (max(ctrl->tRTP, 8) << 16));
2809 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2810 (slotrank << 24));
2811 write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd);
2812 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42);
2813
Patrick Rudolph371d2912015-10-09 13:33:25 +02002814 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002815 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2816 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001);
2817 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2818 (slotrank << 24) | 0x60400);
2819 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2820
2821 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2822 wait_428c(channel);
2823 FOR_ALL_LANES {
2824 u32 r32 =
2825 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2826 0x400 * channel);
2827
2828 if (r32 == 0)
2829 lanes_ok |= 1 << lane;
2830 }
2831 ctr++;
2832 if (lanes_ok == ((1 << NUM_LANES) - 1))
2833 break;
2834 }
2835
2836 ctrl->timings[channel][slotrank] = saved_rt;
2837
2838 printram("3lanes: %x\n", lanes_ok);
2839 return lanes_ok != ((1 << NUM_LANES) - 1);
2840}
2841
2842#include "raminit_patterns.h"
2843
2844static void fill_pattern5(ramctr_timing * ctrl, int channel, int patno)
2845{
2846 unsigned i, j;
2847 unsigned channel_offset =
2848 get_precedening_channels(ctrl, channel) * 0x40;
2849 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2850
2851 if (patno) {
2852 u8 base8 = 0x80 >> ((patno - 1) % 8);
2853 u32 base = base8 | (base8 << 8) | (base8 << 16) | (base8 << 24);
2854 for (i = 0; i < 32; i++) {
2855 for (j = 0; j < 16; j++) {
2856 u32 val = use_base[patno - 1][i] & (1 << (j / 2)) ? base : 0;
2857 if (invert[patno - 1][i] & (1 << (j / 2)))
2858 val = ~val;
2859 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2860 j * 4), val);
2861 }
2862 }
2863
2864 } else {
2865 for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) {
2866 for (j = 0; j < 16; j++)
2867 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2868 j * 4), pattern[i][j]);
2869 }
2870 sfence();
2871 }
2872}
2873
2874static void reprogram_320c(ramctr_timing * ctrl)
2875{
2876 int channel, slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002877
2878 FOR_ALL_POPULATED_CHANNELS {
2879 wait_428c(channel);
2880
2881 /* choose an existing rank. */
2882 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2883
Patrick Rudolph371d2912015-10-09 13:33:25 +02002884 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002885 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2886 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2887
2888 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2889 (slotrank << 24) | 0x60000);
2890
2891 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2892
2893 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2894 wait_428c(channel);
2895 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2896 read32(DEFAULT_MCHBAR + 0x4020 +
2897 0x400 * channel) | 0x200000);
2898 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002899
2900 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002901 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
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 }
2920
2921 /* jedec reset */
2922 dram_jedecreset(ctrl);
2923 /* mrs commands. */
2924 dram_mrscommands(ctrl);
2925
Patrick Rudolph9b515682015-10-09 13:43:51 +02002926 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002927}
2928
2929#define MIN_C320C_LEN 13
2930
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002931static int try_cmd_stretch(ramctr_timing *ctrl, int cmd_stretch)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002932{
2933 struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
2934 int channel, slotrank;
2935 int c320c;
2936 int stat[NUM_SLOTRANKS][256];
2937
2938 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2939 saved_timings[channel][slotrank] = ctrl->timings[channel][slotrank];
2940 }
2941
2942 FOR_ALL_POPULATED_CHANNELS {
2943 ctrl->cmd_stretch[channel] = cmd_stretch;
2944 }
2945
2946 FOR_ALL_POPULATED_CHANNELS
2947 MCHBAR32(0x4004 + 0x400 * channel) =
2948 ctrl->tRRD
2949 | (ctrl->tRTP << 4)
2950 | (ctrl->tCKE << 8)
2951 | (ctrl->tWTR << 12)
2952 | (ctrl->tFAW << 16)
2953 | (ctrl->tWR << 24)
2954 | (ctrl->cmd_stretch[channel] << 30);
2955
2956
2957 FOR_ALL_CHANNELS {
2958 int delta = 0;
2959 if (ctrl->cmd_stretch[channel] == 2)
2960 delta = 2;
2961 else if (ctrl->cmd_stretch[channel] == 0)
2962 delta = 4;
2963
2964 FOR_ALL_POPULATED_RANKS {
2965 ctrl->timings[channel][slotrank].val_4024 -= delta;
2966 }
2967 }
2968
2969 FOR_ALL_POPULATED_CHANNELS {
2970 for (c320c = -127; c320c <= 127; c320c++) {
2971 FOR_ALL_POPULATED_RANKS {
2972 ctrl->timings[channel][slotrank].val_320c = c320c;
2973 }
2974 program_timings(ctrl, channel);
2975 reprogram_320c(ctrl);
2976 FOR_ALL_POPULATED_RANKS {
2977 stat[slotrank][c320c + 127] =
2978 test_320c(ctrl, channel, slotrank);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002979 printram("3stat: %d, %d, %d: %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002980 channel, slotrank, c320c,
2981 stat[slotrank][c320c + 127]);
2982 }
2983 }
2984 FOR_ALL_POPULATED_RANKS {
2985 struct run rn =
2986 get_longest_zero_run(stat[slotrank], 255);
2987 ctrl->timings[channel][slotrank].val_320c =
2988 rn.middle - 127;
2989 printram("3val: %d, %d: %d\n", channel,
2990 slotrank,
2991 ctrl->timings[channel][slotrank].val_320c);
2992 if (rn.all || rn.length < MIN_C320C_LEN) {
2993 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2994 ctrl->timings[channel][slotrank] = saved_timings[channel][slotrank];
2995 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002996 return MAKE_ERR;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002997 }
2998 }
2999 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003000 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003001}
3002
Patrick Rudolph371d2912015-10-09 13:33:25 +02003003/* Adjust CMD phase shift and try multiple command rates.
3004 * A command rate of 2T doubles the time needed for address and
3005 * command decode. */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003006static int command_training(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003007{
3008 int channel;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003009 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003010
3011 FOR_ALL_POPULATED_CHANNELS {
3012 fill_pattern5(ctrl, channel, 0);
3013 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
3014 }
3015
3016 /* try command rate 1T and 2T */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003017 err = try_cmd_stretch(ctrl, 0);
3018 if (err) {
3019 err = try_cmd_stretch(ctrl, 2);
3020 if (err) {
3021 printk(BIOS_EMERG, "c320c discovery failed\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003022 return err;
3023 }
3024 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003025
3026 FOR_ALL_POPULATED_CHANNELS {
3027 program_timings(ctrl, channel);
3028 }
3029
3030 reprogram_320c(ctrl);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003031 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003032}
3033
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003034static int discover_edges_real(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003035 int *edges)
3036{
3037 int edge;
3038 int statistics[NUM_LANES][MAX_EDGE_TIMING + 1];
3039 int lane;
3040
3041 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3042 FOR_ALL_LANES {
3043 ctrl->timings[channel][slotrank].lanes[lane].rising =
3044 edge;
3045 ctrl->timings[channel][slotrank].lanes[lane].falling =
3046 edge;
3047 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003048 program_timings(ctrl, channel);
3049
3050 FOR_ALL_LANES {
3051 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3052 4 * lane, 0);
3053 read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane +
3054 0x4140);
3055 }
3056
3057 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003058 /* DRAM command MRS
3059 * write MR3 MPR enable
3060 * in this mode only RD and RDA are allowed
3061 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003062 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
3063 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3064 (0xc01 | (ctrl->tMOD << 16)));
3065 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3066 (slotrank << 24) | 0x360004);
3067 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3068
Patrick Rudolph371d2912015-10-09 13:33:25 +02003069 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003070 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
3071 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4);
3072 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3073 (slotrank << 24));
3074 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3075
Patrick Rudolph371d2912015-10-09 13:33:25 +02003076 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003077 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
3078 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3079 0x1001 | ((ctrl->CAS + 8) << 16));
3080 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3081 (slotrank << 24) | 0x60000);
3082 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3083
Patrick Rudolph371d2912015-10-09 13:33:25 +02003084 /* DRAM command MRS
3085 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003086 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
3087 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3088 (0xc01 | (ctrl->tMOD << 16)));
3089 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3090 (slotrank << 24) | 0x360000);
3091 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3092
3093 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
3094
3095 wait_428c(channel);
3096
3097 FOR_ALL_LANES {
3098 statistics[lane][edge] =
3099 read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3100 lane * 4);
3101 }
3102 }
3103 FOR_ALL_LANES {
3104 struct run rn =
3105 get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
3106 edges[lane] = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003107 if (rn.all) {
3108 printk(BIOS_EMERG, "edge discovery failed: %d, %d, %d\n",
3109 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003110 return MAKE_ERR;
3111 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003112 printram("eval %d, %d, %d: %02x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003113 lane, edges[lane]);
3114 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003115 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003116}
3117
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003118static int discover_edges(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003119{
3120 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3121 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3122 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003123 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003124
3125 write32(DEFAULT_MCHBAR + 0x3400, 0);
3126
Patrick Rudolph9b515682015-10-09 13:43:51 +02003127 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003128
3129 FOR_ALL_POPULATED_CHANNELS FOR_ALL_LANES {
3130 write32(DEFAULT_MCHBAR + 4 * lane +
3131 0x400 * channel + 0x4080, 0);
3132 }
3133
3134 FOR_ALL_POPULATED_CHANNELS {
3135 fill_pattern0(ctrl, channel, 0, 0);
3136 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3137 FOR_ALL_LANES {
3138 read32(DEFAULT_MCHBAR + 0x400 * channel +
3139 lane * 4 + 0x4140);
3140 }
3141
3142 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3143 ctrl->timings[channel][slotrank].lanes[lane].falling =
3144 16;
3145 ctrl->timings[channel][slotrank].lanes[lane].rising =
3146 16;
3147 }
3148
3149 program_timings(ctrl, channel);
3150
3151 FOR_ALL_POPULATED_RANKS {
3152 wait_428c(channel);
3153
Patrick Rudolph371d2912015-10-09 13:33:25 +02003154 /* DRAM command MRS
3155 * MR3 enable MPR
3156 * write MR3 MPR enable
3157 * in this mode only RD and RDA are allowed
3158 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003159 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3160 0x1f000);
3161 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3162 0xc01 | (ctrl->tMOD << 16));
3163 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3164 (slotrank << 24) | 0x360004);
3165 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3166
Patrick Rudolph371d2912015-10-09 13:33:25 +02003167 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003168 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3169 0x1f105);
3170 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3171 0x4041003);
3172 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3173 (slotrank << 24) | 0);
3174 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3175
Patrick Rudolph371d2912015-10-09 13:33:25 +02003176 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003177 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3178 0x1f105);
3179 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3180 0x1001 | ((ctrl->CAS + 8) << 16));
3181 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3182 (slotrank << 24) | 0x60000);
3183 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3184
Patrick Rudolph371d2912015-10-09 13:33:25 +02003185 /* DRAM command MRS
3186 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003187 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3188 0x1f000);
3189 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3190 0xc01 | (ctrl->tMOD << 16));
3191 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3192 (slotrank << 24) | 0x360000);
3193 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3194 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3195 0xc0001);
3196
3197 wait_428c(channel);
3198 }
3199
Patrick Rudolph371d2912015-10-09 13:33:25 +02003200 /* XXX: check any measured value ? */
3201
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003202 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3203 ctrl->timings[channel][slotrank].lanes[lane].falling =
3204 48;
3205 ctrl->timings[channel][slotrank].lanes[lane].rising =
3206 48;
3207 }
3208
3209 program_timings(ctrl, channel);
3210
3211 FOR_ALL_POPULATED_RANKS {
3212 wait_428c(channel);
3213
Patrick Rudolph371d2912015-10-09 13:33:25 +02003214 /* DRAM command MRS
3215 * MR3 enable MPR
3216 * write MR3 MPR enable
3217 * in this mode only RD and RDA are allowed
3218 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003219 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3220 0x1f000);
3221 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3222 0xc01 | (ctrl->tMOD << 16));
3223 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3224 (slotrank << 24) | 0x360004);
3225 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3226
Patrick Rudolph371d2912015-10-09 13:33:25 +02003227 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003228 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3229 0x1f105);
3230 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3231 0x4041003);
3232 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3233 (slotrank << 24) | 0);
3234 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3235
Patrick Rudolph371d2912015-10-09 13:33:25 +02003236 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003237 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3238 0x1f105);
3239 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3240 0x1001 | ((ctrl->CAS + 8) << 16));
3241 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3242 (slotrank << 24) | 0x60000);
3243 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3244
Patrick Rudolph371d2912015-10-09 13:33:25 +02003245 /* DRAM command MRS
3246 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003247 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3248 0x1f000);
3249 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3250 0xc01 | (ctrl->tMOD << 16));
3251 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3252 (slotrank << 24) | 0x360000);
3253 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3254
3255 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3256 0xc0001);
3257 wait_428c(channel);
3258 }
3259
Patrick Rudolph371d2912015-10-09 13:33:25 +02003260 /* XXX: check any measured value ? */
3261
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003262 FOR_ALL_LANES {
3263 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel +
3264 lane * 4,
3265 ~read32(DEFAULT_MCHBAR + 0x4040 +
3266 0x400 * channel + lane * 4) & 0xff);
3267 }
3268
3269 fill_pattern0(ctrl, channel, 0, 0xffffffff);
3270 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3271 }
3272
3273 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3274 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003275 printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003276
3277 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003278 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003279 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003280 if (err)
3281 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003282 }
3283
3284 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003285 printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003286
3287 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003288 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003289 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003290 if (err)
3291 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003292 }
3293
3294 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3295
3296 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3297 ctrl->timings[channel][slotrank].lanes[lane].falling =
3298 falling_edges[channel][slotrank][lane];
3299 ctrl->timings[channel][slotrank].lanes[lane].rising =
3300 rising_edges[channel][slotrank][lane];
3301 }
3302
3303 FOR_ALL_POPULATED_CHANNELS {
3304 program_timings(ctrl, channel);
3305 }
3306
3307 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3308 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3309 0);
3310 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003311 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003312}
3313
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003314static int discover_edges_write_real(ramctr_timing *ctrl, int channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003315 int slotrank, int *edges)
3316{
3317 int edge;
3318 u32 raw_statistics[MAX_EDGE_TIMING + 1];
3319 int statistics[MAX_EDGE_TIMING + 1];
3320 const int reg3000b24[] = { 0, 0xc, 0x2c };
3321 int lane, i;
3322 int lower[NUM_LANES];
3323 int upper[NUM_LANES];
3324 int pat;
3325
3326 FOR_ALL_LANES {
3327 lower[lane] = 0;
3328 upper[lane] = MAX_EDGE_TIMING;
3329 }
3330
3331 for (i = 0; i < 3; i++) {
3332 write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel,
3333 reg3000b24[i] << 24);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003334 printram("[%x] = 0x%08x\n",
3335 0x3000 + 0x100 * channel, reg3000b24[i] << 24);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003336 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3337 fill_pattern5(ctrl, channel, pat);
3338 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003339 printram("using pattern %d\n", pat);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003340 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3341 FOR_ALL_LANES {
3342 ctrl->timings[channel][slotrank].lanes[lane].
3343 rising = edge;
3344 ctrl->timings[channel][slotrank].lanes[lane].
3345 falling = edge;
3346 }
3347 program_timings(ctrl, channel);
3348
3349 FOR_ALL_LANES {
3350 write32(DEFAULT_MCHBAR + 0x4340 +
3351 0x400 * channel + 4 * lane, 0);
3352 read32(DEFAULT_MCHBAR + 0x400 * channel +
3353 4 * lane + 0x4140);
3354 }
3355 wait_428c(channel);
3356
Patrick Rudolph371d2912015-10-09 13:33:25 +02003357 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003358 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3359 0x1f006);
3360 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3361 0x4 | (ctrl->tRCD << 16)
3362 | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) <<
3363 10));
3364 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3365 (slotrank << 24) | 0x60000);
3366 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel,
3367 0x240);
3368
Patrick Rudolph371d2912015-10-09 13:33:25 +02003369 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003370 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3371 0x1f201);
3372 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3373 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) <<
3374 16));
3375 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3376 (slotrank << 24));
3377 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel,
3378 0x242);
3379
Patrick Rudolph371d2912015-10-09 13:33:25 +02003380 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003381 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3382 0x1f105);
3383 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3384 0x4005020 | (max(ctrl->tRTP, 8) << 16));
3385 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3386 (slotrank << 24));
3387 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel,
3388 0x242);
3389
Patrick Rudolph371d2912015-10-09 13:33:25 +02003390 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003391 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3392 0x1f002);
3393 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3394 0xc01 | (ctrl->tRP << 16));
3395 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3396 (slotrank << 24) | 0x60400);
3397 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3398
3399 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3400 0xc0001);
3401 wait_428c(channel);
3402 FOR_ALL_LANES {
3403 read32(DEFAULT_MCHBAR + 0x4340 +
3404 0x400 * channel + lane * 4);
3405 }
3406
3407 raw_statistics[edge] =
3408 MCHBAR32(0x436c + 0x400 * channel);
3409 }
3410 FOR_ALL_LANES {
3411 struct run rn;
3412 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++)
3413 statistics[edge] =
3414 ! !(raw_statistics[edge] & (1 << lane));
3415 rn = get_longest_zero_run(statistics,
3416 MAX_EDGE_TIMING + 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003417 printram("edges: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003418 channel, slotrank, i, rn.start, rn.middle,
3419 rn.end, rn.start + ctrl->edge_offset[i],
3420 rn.end - ctrl->edge_offset[i]);
3421 lower[lane] =
3422 max(rn.start + ctrl->edge_offset[i], lower[lane]);
3423 upper[lane] =
3424 min(rn.end - ctrl->edge_offset[i], upper[lane]);
3425 edges[lane] = (lower[lane] + upper[lane]) / 2;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003426 if (rn.all || (lower[lane] > upper[lane])) {
3427 printk(BIOS_EMERG, "edge write discovery failed: %d, %d, %d\n",
3428 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003429 return MAKE_ERR;
3430 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003431 }
3432 }
3433 }
3434
3435 write32(DEFAULT_MCHBAR + 0x3000, 0);
3436 printram("CPA\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003437 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003438}
3439
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003440static int discover_edges_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003441{
3442 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3443 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3444 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003445 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003446
3447 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3448 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003449 printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003450
3451 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003452 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003453 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003454 if (err)
3455 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003456 }
3457
3458 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003459 printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003460
3461 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003462 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003463 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003464 if (err)
3465 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003466 }
3467
3468 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3469
3470 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3471 ctrl->timings[channel][slotrank].lanes[lane].falling =
3472 falling_edges[channel][slotrank][lane];
3473 ctrl->timings[channel][slotrank].lanes[lane].rising =
3474 rising_edges[channel][slotrank][lane];
3475 }
3476
3477 FOR_ALL_POPULATED_CHANNELS
3478 program_timings(ctrl, channel);
3479
3480 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3481 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3482 0);
3483 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003484 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003485}
3486
3487static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
3488{
3489 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003490 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003491 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
3492 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3493 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD)
3494 << 10) | (ctrl->tRCD << 16) | 4);
3495 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3496 (slotrank << 24) | 0x60000);
3497 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
3498
Patrick Rudolph371d2912015-10-09 13:33:25 +02003499 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003500 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
3501 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3502 0x80011e0 |
3503 ((ctrl->tWTR + ctrl->CWL + 8) << 16));
3504 write32(DEFAULT_MCHBAR + 0x4204 +
3505 0x400 * channel, (slotrank << 24));
3506 write32(DEFAULT_MCHBAR + 0x4214 +
3507 0x400 * channel, 0x242);
3508
Patrick Rudolph371d2912015-10-09 13:33:25 +02003509 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003510 write32(DEFAULT_MCHBAR + 0x4228 +
3511 0x400 * channel, 0x1f105);
3512 write32(DEFAULT_MCHBAR + 0x4238 +
3513 0x400 * channel,
3514 0x40011e0 | (max(ctrl->tRTP, 8) << 16));
3515 write32(DEFAULT_MCHBAR + 0x4208 +
3516 0x400 * channel, (slotrank << 24));
3517 write32(DEFAULT_MCHBAR + 0x4218 +
3518 0x400 * channel, 0x242);
3519
Patrick Rudolph371d2912015-10-09 13:33:25 +02003520 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003521 write32(DEFAULT_MCHBAR + 0x422c +
3522 0x400 * channel, 0x1f002);
3523 write32(DEFAULT_MCHBAR + 0x423c +
3524 0x400 * channel,
3525 0x1001 | (ctrl->tRP << 16));
3526 write32(DEFAULT_MCHBAR + 0x420c +
3527 0x400 * channel,
3528 (slotrank << 24) | 0x60400);
3529 write32(DEFAULT_MCHBAR + 0x421c +
3530 0x400 * channel, 0);
3531
3532 write32(DEFAULT_MCHBAR + 0x4284 +
3533 0x400 * channel, 0xc0001);
3534 wait_428c(channel);
3535}
3536
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003537static int discover_timC_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003538{
3539 const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
3540 int i, pat;
3541
3542 int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3543 int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3544 int channel, slotrank, lane;
3545
3546 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3547 lower[channel][slotrank][lane] = 0;
3548 upper[channel][slotrank][lane] = MAX_TIMC;
3549 }
3550
3551 write32(DEFAULT_MCHBAR + 0x4ea8, 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003552 printram("discover timC write:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003553
3554 for (i = 0; i < 3; i++)
3555 FOR_ALL_POPULATED_CHANNELS {
3556 write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100),
3557 (rege3c_b24[i] << 24)
3558 | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100))
3559 & ~0x3f000000));
3560 udelay(2);
3561 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3562 FOR_ALL_POPULATED_RANKS {
3563 int timC;
3564 u32 raw_statistics[MAX_TIMC + 1];
3565 int statistics[MAX_TIMC + 1];
3566
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003567 /* Make sure rn.start < rn.end */
3568 statistics[MAX_TIMC] = 1;
3569
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003570 fill_pattern5(ctrl, channel, pat);
3571 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003572 for (timC = 0; timC < MAX_TIMC; timC++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003573 FOR_ALL_LANES
3574 ctrl->timings[channel][slotrank].lanes[lane].timC = timC;
3575 program_timings(ctrl, channel);
3576
3577 test_timC_write (ctrl, channel, slotrank);
3578
3579 raw_statistics[timC] =
3580 MCHBAR32(0x436c + 0x400 * channel);
3581 }
3582 FOR_ALL_LANES {
3583 struct run rn;
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003584 for (timC = 0; timC < MAX_TIMC; timC++)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003585 statistics[timC] =
3586 !!(raw_statistics[timC] &
3587 (1 << lane));
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003588
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003589 rn = get_longest_zero_run(statistics,
3590 MAX_TIMC + 1);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003591 if (rn.all) {
3592 printk(BIOS_EMERG, "timC write discovery failed: %d, %d, %d\n",
3593 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003594 return MAKE_ERR;
3595 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003596 printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003597 channel, slotrank, i, rn.start,
3598 rn.middle, rn.end,
3599 rn.start + ctrl->timC_offset[i],
3600 rn.end - ctrl->timC_offset[i]);
3601 lower[channel][slotrank][lane] =
3602 max(rn.start + ctrl->timC_offset[i],
3603 lower[channel][slotrank][lane]);
3604 upper[channel][slotrank][lane] =
3605 min(rn.end - ctrl->timC_offset[i],
3606 upper[channel][slotrank][lane]);
3607
3608 }
3609 }
3610 }
3611 }
3612
3613 FOR_ALL_CHANNELS {
3614 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3615 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3616 ~0x3f000000));
3617 udelay(2);
3618 }
3619
3620 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3621
3622 printram("CPB\n");
3623
3624 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
Patrick Rudolpha649a542016-01-17 18:32:06 +01003625 printram("timC %d, %d, %d: %x\n", channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003626 slotrank, lane,
3627 (lower[channel][slotrank][lane] +
3628 upper[channel][slotrank][lane]) / 2);
3629 ctrl->timings[channel][slotrank].lanes[lane].timC =
3630 (lower[channel][slotrank][lane] +
3631 upper[channel][slotrank][lane]) / 2;
3632 }
3633 FOR_ALL_POPULATED_CHANNELS {
3634 program_timings(ctrl, channel);
3635 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003636 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003637}
3638
3639static void normalize_training(ramctr_timing * ctrl)
3640{
3641 int channel, slotrank, lane;
3642 int mat = 0;
3643
3644 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3645 int delta;
3646 FOR_ALL_LANES mat =
3647 max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat);
3648 delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028;
3649 ctrl->timings[channel][slotrank].val_4024 += delta;
3650 ctrl->timings[channel][slotrank].val_4028 += delta;
3651 }
3652
3653 FOR_ALL_POPULATED_CHANNELS {
3654 program_timings(ctrl, channel);
3655 }
3656}
3657
3658static void write_controller_mr(ramctr_timing * ctrl)
3659{
3660 int channel, slotrank;
3661
3662 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3663 write32(DEFAULT_MCHBAR + 0x0004 + (channel << 8) +
3664 lane_registers[slotrank], make_mr0(ctrl, slotrank));
3665 write32(DEFAULT_MCHBAR + 0x0008 + (channel << 8) +
Patrick Rudolph7e513d12016-01-10 14:22:34 +01003666 lane_registers[slotrank],
3667 make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003668 }
3669}
3670
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003671static int channel_test(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003672{
3673 int channel, slotrank, lane;
3674
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003675 slotrank = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003676 FOR_ALL_POPULATED_CHANNELS
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003677 if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) {
3678 printk(BIOS_EMERG, "Mini channel test failed (1): %d\n",
3679 channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003680 return MAKE_ERR;
3681 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003682 FOR_ALL_POPULATED_CHANNELS {
3683 fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
3684
3685 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3686 }
3687
3688 for (slotrank = 0; slotrank < 4; slotrank++)
3689 FOR_ALL_CHANNELS
3690 if (ctrl->rankmap[channel] & (1 << slotrank)) {
3691 FOR_ALL_LANES {
3692 write32(DEFAULT_MCHBAR + (0x4f40 + 4 * lane), 0);
3693 write32(DEFAULT_MCHBAR + (0x4d40 + 4 * lane), 0);
3694 }
3695 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003696 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003697 write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
3698 write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10), 0x0028a004);
3699 write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
3700 0x00060000 | (slotrank << 24));
3701 write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003702 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003703 write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
3704 write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281064);
3705 write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
3706 0x00000000 | (slotrank << 24));
3707 write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003708 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003709 write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f105);
3710 write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x04281064);
3711 write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
3712 0x00000000 | (slotrank << 24));
3713 write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003714 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003715 write32(DEFAULT_MCHBAR + 0x422c + (channel << 10), 0x0001f002);
3716 write32(DEFAULT_MCHBAR + 0x423c + (channel << 10), 0x00280c01);
3717 write32(DEFAULT_MCHBAR + 0x420c + (channel << 10),
3718 0x00060400 | (slotrank << 24));
3719 write32(DEFAULT_MCHBAR + 0x421c + (channel << 10), 0x00000240);
3720 write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
3721 wait_428c(channel);
3722 FOR_ALL_LANES
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003723 if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) {
3724 printk(BIOS_EMERG, "Mini channel test failed (2): %d, %d, %d\n",
3725 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003726 return MAKE_ERR;
3727 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003728 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003729 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003730}
3731
3732static void set_scrambling_seed(ramctr_timing * ctrl)
3733{
3734 int channel;
3735
3736 /* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
3737 I don't think so. */
3738 static u32 seeds[NUM_CHANNELS][3] = {
3739 {0x00009a36, 0xbafcfdcf, 0x46d1ab68},
3740 {0x00028bfa, 0x53fe4b49, 0x19ed5483}
3741 };
3742 FOR_ALL_POPULATED_CHANNELS {
3743 MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
3744 write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
3745 write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
3746 write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
3747 }
3748}
3749
3750static void set_4f8c(void)
3751{
3752 struct cpuid_result cpures;
3753 u32 cpu;
3754
3755 cpures = cpuid(0);
3756 cpu = (cpures.eax);
3757 if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) {
3758 MCHBAR32(0x4f8c) = 0x141D1519;
3759 } else {
3760 MCHBAR32(0x4f8c) = 0x551D1519;
3761 }
3762}
3763
3764static void prepare_training(ramctr_timing * ctrl)
3765{
3766 int channel;
3767
3768 FOR_ALL_POPULATED_CHANNELS {
3769 // Always drive command bus
3770 MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000;
3771 }
3772
3773 udelay(1);
3774
3775 FOR_ALL_POPULATED_CHANNELS {
3776 wait_428c(channel);
3777 }
3778}
3779
3780static void set_4008c(ramctr_timing * ctrl)
3781{
3782 int channel, slotrank;
3783 u32 reg;
3784 FOR_ALL_POPULATED_CHANNELS {
3785 u32 b20, b4_8_12;
3786 int min_320c = 10000;
3787 int max_320c = -10000;
3788
3789 FOR_ALL_POPULATED_RANKS {
3790 max_320c = max(ctrl->timings[channel][slotrank].val_320c, max_320c);
3791 min_320c = min(ctrl->timings[channel][slotrank].val_320c, min_320c);
3792 }
3793
3794 if (max_320c - min_320c > 51)
3795 b20 = 0;
3796 else
3797 b20 = ctrl->ref_card_offset[channel];
3798
3799 if (ctrl->reg_320c_range_threshold < max_320c - min_320c)
3800 b4_8_12 = 0x3330;
3801 else
3802 b4_8_12 = 0x2220;
3803
3804 reg = read32(DEFAULT_MCHBAR + 0x400c + (channel << 10));
3805 write32(DEFAULT_MCHBAR + 0x400c + (channel << 10),
3806 (reg & 0xFFF0FFFF)
3807 | (ctrl->ref_card_offset[channel] << 16)
3808 | (ctrl->ref_card_offset[channel] << 18));
3809 write32(DEFAULT_MCHBAR + 0x4008 + (channel << 10),
3810 0x0a000000
3811 | (b20 << 20)
3812 | ((ctrl->ref_card_offset[channel] + 2) << 16)
3813 | b4_8_12);
3814 }
3815}
3816
3817static void set_42a0(ramctr_timing * ctrl)
3818{
3819 int channel;
3820 FOR_ALL_POPULATED_CHANNELS {
3821 write32(DEFAULT_MCHBAR + (0x42a0 + 0x400 * channel),
3822 0x00001000 | ctrl->rankmap[channel]);
3823 MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK
3824 }
3825}
3826
3827static int encode_5d10(int ns)
3828{
3829 return (ns + 499) / 500;
3830}
3831
3832/* FIXME: values in this function should be hardware revision-dependent. */
3833static void final_registers(ramctr_timing * ctrl)
3834{
3835 int channel;
3836 int t1_cycles = 0, t1_ns = 0, t2_ns;
3837 int t3_ns;
3838 u32 r32;
3839
3840 write32(DEFAULT_MCHBAR + 0x4cd4, 0x00000046);
3841
3842 write32(DEFAULT_MCHBAR + 0x400c, (read32(DEFAULT_MCHBAR + 0x400c) & 0xFFFFCFFF) | 0x1000); // OK
3843 write32(DEFAULT_MCHBAR + 0x440c, (read32(DEFAULT_MCHBAR + 0x440c) & 0xFFFFCFFF) | 0x1000); // OK
3844 write32(DEFAULT_MCHBAR + 0x4cb0, 0x00000740);
3845 write32(DEFAULT_MCHBAR + 0x4380, 0x00000aaa); // OK
3846 write32(DEFAULT_MCHBAR + 0x4780, 0x00000aaa); // OK
3847 write32(DEFAULT_MCHBAR + 0x4f88, 0x5f7003ff); // OK
3848 write32(DEFAULT_MCHBAR + 0x5064, 0x00073000 | ctrl->reg_5064b0); // OK
3849
3850 FOR_ALL_CHANNELS {
3851 switch (ctrl->rankmap[channel]) {
3852 /* Unpopulated channel. */
3853 case 0:
3854 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0);
3855 break;
3856 /* Only single-ranked dimms. */
3857 case 1:
3858 case 4:
3859 case 5:
3860 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x373131);
3861 break;
3862 /* Dual-ranked dimms present. */
3863 default:
3864 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x9b6ea1);
3865 break;
3866 }
3867 }
3868
3869 write32 (DEFAULT_MCHBAR + 0x5880, 0xca9171e5);
3870 write32 (DEFAULT_MCHBAR + 0x5888,
3871 (read32 (DEFAULT_MCHBAR + 0x5888) & ~0xffffff) | 0xe4d5d0);
3872 write32 (DEFAULT_MCHBAR + 0x58a8, read32 (DEFAULT_MCHBAR + 0x58a8) & ~0x1f);
3873 write32 (DEFAULT_MCHBAR + 0x4294,
3874 (read32 (DEFAULT_MCHBAR + 0x4294) & ~0x30000)
3875 | (1 << 16));
3876 write32 (DEFAULT_MCHBAR + 0x4694,
3877 (read32 (DEFAULT_MCHBAR + 0x4694) & ~0x30000)
3878 | (1 << 16));
3879
3880 MCHBAR32(0x5030) |= 1; // OK
3881 MCHBAR32(0x5030) |= 0x80; // OK
3882 MCHBAR32(0x5f18) = 0xfa; // OK
3883
3884 /* Find a populated channel. */
3885 FOR_ALL_POPULATED_CHANNELS
3886 break;
3887
3888 t1_cycles = ((read32(DEFAULT_MCHBAR + 0x4290 + channel * 0x400) >> 8) & 0xff);
3889 r32 = read32(DEFAULT_MCHBAR + 0x5064);
3890 if (r32 & 0x20000)
3891 t1_cycles += (r32 & 0xfff);
3892 t1_cycles += (read32(DEFAULT_MCHBAR + channel * 0x400 + 0x42a4) & 0xfff);
3893 t1_ns = t1_cycles * ctrl->tCK / 256 + 544;
3894 if (!(r32 & 0x20000))
3895 t1_ns += 500;
3896
3897 t2_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f10) >> 8) & 0xfff);
3898 if ( read32(DEFAULT_MCHBAR + 0x5f00) & 8 )
3899 {
3900 t3_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f20) >> 8) & 0xfff);
3901 t3_ns += 10 * (read32(DEFAULT_MCHBAR + 0x5f18) & 0xff);
3902 }
3903 else
3904 {
3905 t3_ns = 500;
3906 }
3907 printk(BIOS_DEBUG, "t123: %d, %d, %d\n",
3908 t1_ns, t2_ns, t3_ns);
3909 write32 (DEFAULT_MCHBAR + 0x5d10,
3910 ((encode_5d10(t1_ns) + encode_5d10(t2_ns)) << 16)
3911 | (encode_5d10(t1_ns) << 8)
3912 | ((encode_5d10(t3_ns) + encode_5d10(t2_ns) + encode_5d10(t1_ns)) << 24)
3913 | (read32(DEFAULT_MCHBAR + 0x5d10) & 0xC0C0C0C0)
3914 | 0xc);
3915}
3916
3917static void save_timings(ramctr_timing * ctrl)
3918{
3919 struct mrc_data_container *mrcdata;
3920 int output_len = ALIGN(sizeof (*ctrl), 16);
3921
3922 /* Save the MRC S3 restore data to cbmem */
3923 mrcdata = cbmem_add
3924 (CBMEM_ID_MRCDATA,
3925 output_len + sizeof(struct mrc_data_container));
3926
3927 printk(BIOS_DEBUG, "Relocate MRC DATA from %p to %p (%u bytes)\n",
3928 ctrl, mrcdata, output_len);
3929
3930 mrcdata->mrc_signature = MRC_DATA_SIGNATURE;
3931 mrcdata->mrc_data_size = output_len;
3932 mrcdata->reserved = 0;
3933 memcpy(mrcdata->mrc_data, ctrl, sizeof (*ctrl));
3934
3935 /* Zero the unused space in aligned buffer. */
3936 if (output_len > sizeof (*ctrl))
3937 memset(mrcdata->mrc_data+sizeof (*ctrl), 0,
3938 output_len - sizeof (*ctrl));
3939
3940 mrcdata->mrc_checksum = compute_ip_checksum(mrcdata->mrc_data,
3941 mrcdata->mrc_data_size);
3942}
3943
3944static void restore_timings(ramctr_timing * ctrl)
3945{
3946 int channel, slotrank, lane;
3947
3948 FOR_ALL_POPULATED_CHANNELS
3949 MCHBAR32(0x4004 + 0x400 * channel) =
3950 ctrl->tRRD
3951 | (ctrl->tRTP << 4)
3952 | (ctrl->tCKE << 8)
3953 | (ctrl->tWTR << 12)
3954 | (ctrl->tFAW << 16)
3955 | (ctrl->tWR << 24)
3956 | (ctrl->cmd_stretch[channel] << 30);
3957
3958 udelay(1);
3959
3960 FOR_ALL_POPULATED_CHANNELS {
3961 wait_428c(channel);
3962 }
3963
3964 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3965 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
3966 + 4 * lane, 0);
3967 }
3968
3969 FOR_ALL_POPULATED_CHANNELS
3970 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
3971 read32(DEFAULT_MCHBAR + 0x4008 +
3972 0x400 * channel) | 0x8000000);
3973
3974 FOR_ALL_POPULATED_CHANNELS {
3975 udelay (1);
3976 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
3977 read32(DEFAULT_MCHBAR + 0x4020 +
3978 0x400 * channel) | 0x200000);
3979 }
3980
3981 printram("CPE\n");
3982
3983 write32(DEFAULT_MCHBAR + 0x3400, 0);
3984 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3985
3986 printram("CP5b\n");
3987
3988 FOR_ALL_POPULATED_CHANNELS {
3989 program_timings(ctrl, channel);
3990 }
3991
3992 u32 reg, addr;
3993
3994 while (!(MCHBAR32(0x5084) & 0x10000)) ;
3995 do {
3996 reg = MCHBAR32(0x428c);
3997 } while ((reg & 0x14) == 0);
3998
3999 // Set state of memory controller
4000 MCHBAR32(0x5030) = 0x116;
4001 MCHBAR32(0x4ea0) = 0;
4002
4003 // Wait 500us
4004 udelay(500);
4005
4006 FOR_ALL_CHANNELS {
4007 // Set valid rank CKE
4008 reg = 0;
4009 reg = (reg & ~0xf) | ctrl->rankmap[channel];
4010 addr = 0x400 * channel + 0x42a0;
4011 MCHBAR32(addr) = reg;
4012
4013 // Wait 10ns for ranks to settle
4014 //udelay(0.01);
4015
4016 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
4017 MCHBAR32(addr) = reg;
4018
4019 // Write reset using a NOP
4020 write_reset(ctrl);
4021 }
4022
4023 /* mrs commands. */
4024 dram_mrscommands(ctrl);
4025
4026 printram("CP5c\n");
4027
4028 write32(DEFAULT_MCHBAR + 0x3000, 0);
4029
4030 FOR_ALL_CHANNELS {
4031 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
4032 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
4033 ~0x3f000000));
4034 udelay(2);
4035 }
4036
4037 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
4038}
4039
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004040static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot,
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004041 int me_uma_size)
4042{
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004043 int err;
4044
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004045 printk(BIOS_DEBUG, "Starting RAM training (%d).\n", fast_boot);
4046
4047 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004048 /* Find fastest common supported parameters */
4049 dram_find_common_params(ctrl);
4050
4051 dram_dimm_mapping(ctrl);
4052 }
4053
4054 /* Set MCU frequency */
4055 dram_freq(ctrl);
4056
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004057 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004058 /* Calculate timings */
4059 dram_timing(ctrl);
4060 }
4061
4062 /* Set version register */
4063 MCHBAR32(0x5034) = 0xC04EB002;
4064
4065 /* Enable crossover */
4066 dram_xover(ctrl);
4067
4068 /* Set timing and refresh registers */
4069 dram_timing_regs(ctrl);
4070
4071 /* Power mode preset */
4072 MCHBAR32(0x4e80) = 0x5500;
4073
4074 /* Set scheduler parameters */
4075 MCHBAR32(0x4c20) = 0x10100005;
4076
4077 /* Set cpu specific register */
4078 set_4f8c();
4079
4080 /* Clear IO reset bit */
4081 MCHBAR32(0x5030) &= ~0x20;
4082
4083 /* Set MAD-DIMM registers */
4084 dram_dimm_set_mapping(ctrl);
4085 printk(BIOS_DEBUG, "Done dimm mapping\n");
4086
4087 /* Zone config */
4088 dram_zones(ctrl, 1);
4089
4090 /* Set memory map */
4091 dram_memorymap(ctrl, me_uma_size);
4092 printk(BIOS_DEBUG, "Done memory map\n");
4093
4094 /* Set IO registers */
4095 dram_ioregs(ctrl);
4096 printk(BIOS_DEBUG, "Done io registers\n");
4097
4098 udelay(1);
4099
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004100 if (fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004101 restore_timings(ctrl);
4102 } else {
4103 /* Do jedec ddr3 reset sequence */
4104 dram_jedecreset(ctrl);
4105 printk(BIOS_DEBUG, "Done jedec reset\n");
4106
4107 /* MRS commands */
4108 dram_mrscommands(ctrl);
4109 printk(BIOS_DEBUG, "Done MRS commands\n");
4110
4111 /* Prepare for memory training */
4112 prepare_training(ctrl);
4113
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004114 err = read_training(ctrl);
4115 if (err)
4116 return err;
4117
4118 err = write_training(ctrl);
4119 if (err)
4120 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004121
4122 printram("CP5a\n");
4123
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004124 err = discover_edges(ctrl);
4125 if (err)
4126 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004127
4128 printram("CP5b\n");
4129
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004130 err = command_training(ctrl);
4131 if (err)
4132 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004133
4134 printram("CP5c\n");
4135
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004136 err = discover_edges_write(ctrl);
4137 if (err)
4138 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004139
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004140 err = discover_timC_write(ctrl);
4141 if (err)
4142 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004143
4144 normalize_training(ctrl);
4145 }
4146
4147 set_4008c(ctrl);
4148
4149 write_controller_mr(ctrl);
4150
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004151 err = channel_test(ctrl);
4152 if (err)
4153 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004154
4155 return 0;
4156}
4157
4158void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004159 int s3resume)
4160{
4161 int me_uma_size;
4162 int cbmem_was_inited;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004163 ramctr_timing ctrl;
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004164 int fast_boot;
4165 struct mrc_data_container *mrc_cache;
4166 ramctr_timing *ctrl_cached;
Patrick Rudolph31d19592016-03-26 12:22:34 +01004167 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004168
4169 MCHBAR32(0x5f00) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004170
Vadim Bendebury7a3f36a2012-04-18 15:47:32 -07004171 report_platform_info();
4172
Stefan Reinauer00636b02012-04-04 00:08:51 +02004173 /* Wait for ME to be ready */
4174 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004175 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004176
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004177 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +02004178
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004179 u32 reg_5d10;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004180
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004181 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004182
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004183 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +02004184
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004185 reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10); // !!! = 0x00000000
4186 if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */
4187 && reg_5d10 && !s3resume) {
4188 write32(DEFAULT_MCHBAR + 0x5d10, 0);
4189 /* Need reset. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02004190 outb(0x6, 0xcf9);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004191
Patrick Georgi546953c2014-11-29 10:38:17 +01004192 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004193 }
Stefan Reinauer00636b02012-04-04 00:08:51 +02004194
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004195 memset(&ctrl, 0, sizeof (ctrl));
4196
4197 early_pch_init_native();
4198 early_thermal_init();
4199
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004200 /* try to find timings in MRC cache */
4201 mrc_cache = find_current_mrc_cache();
4202 if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(ctrl))) {
4203 if (s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004204 /* Failed S3 resume, reset to come up cleanly */
4205 outb(0x6, 0xcf9);
4206 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004207 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004208 ctrl_cached = NULL;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004209 } else {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004210 ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004211 }
4212
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004213 /* verify MRC cache for fast boot */
4214 if (ctrl_cached) {
4215 /* check SPD CRC16 to make sure the DIMMs haven't been replaced */
4216 fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
4217 if (!fast_boot)
4218 printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
4219 if (!fast_boot && s3resume) {
4220 /* Failed S3 resume, reset to come up cleanly */
4221 outb(0x6, 0xcf9);
4222 halt();
4223 }
4224 } else
4225 fast_boot = 0;
4226
4227 if (fast_boot) {
4228 printk(BIOS_DEBUG, "Trying stored timings.\n");
4229 memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
4230
4231 err = try_init_dram_ddr3(&ctrl, fast_boot, me_uma_size);
4232 if (err) {
4233 /* no need to erase bad mrc cache here, it gets overritten on
4234 * successful boot. */
4235 printk(BIOS_ERR, "Stored timings are invalid !\n");
4236 fast_boot = 0;
4237 }
4238 }
4239 if (!fast_boot) {
4240 ctrl.mobile = mobile;
4241 ctrl.tCK = min_tck;
4242
4243 /* Get DDR3 SPD data */
4244 dram_find_spds_ddr3(spds, &ctrl);
4245
4246 err = try_init_dram_ddr3(&ctrl, fast_boot, me_uma_size);
4247 }
Patrick Rudolph31d19592016-03-26 12:22:34 +01004248 if (err)
4249 die("raminit failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004250
4251 /* FIXME: should be hardware revision-dependent. */
4252 write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
4253
4254 set_scrambling_seed(&ctrl);
4255
4256 set_42a0(&ctrl);
4257
4258 final_registers(&ctrl);
4259
4260 /* Zone config */
4261 dram_zones(&ctrl, 0);
4262
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004263 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004264 quick_ram_check();
4265
4266 intel_early_me_status();
4267 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
4268 intel_early_me_status();
4269
Stefan Reinauer00636b02012-04-04 00:08:51 +02004270 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004271
4272 cbmem_was_inited = !cbmem_recovery(s3resume);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004273 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004274 save_timings(&ctrl);
4275 if (s3resume && !cbmem_was_inited) {
4276 /* Failed S3 resume, reset to come up cleanly */
4277 outb(0x6, 0xcf9);
4278 halt();
4279 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +01004280
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004281 fill_smbios17(&ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004282}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004283
4284#define HOST_BRIDGE PCI_DEVFN(0, 0)
4285#define DEFAULT_TCK TCK_800MHZ
4286
4287static unsigned int get_mem_min_tck(void)
4288{
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004289 u32 reg32;
4290 u8 rev;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004291 const struct device *dev;
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004292 const struct northbridge_intel_sandybridge_config *cfg = NULL;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004293
4294 dev = dev_find_slot(0, HOST_BRIDGE);
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004295 if (dev)
4296 cfg = dev->chip_info;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004297
4298 /* If this is zero, it just means devicetree.cb didn't set it */
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004299 if (!cfg || cfg->max_mem_clock_mhz == 0) {
4300 rev = pci_read_config8(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004301
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004302 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
4303 /* read Capabilities A Register DMFC bits */
4304 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A);
4305 reg32 &= 0x7;
4306
4307 switch (reg32) {
4308 case 7: return TCK_533MHZ;
4309 case 6: return TCK_666MHZ;
4310 case 5: return TCK_800MHZ;
4311 /* reserved: */
4312 default:
4313 break;
4314 }
4315 } else {
4316 /* read Capabilities B Register DMFC bits */
4317 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
4318 reg32 = (reg32 >> 4) & 0x7;
4319
4320 switch (reg32) {
4321 case 7: return TCK_533MHZ;
4322 case 6: return TCK_666MHZ;
4323 case 5: return TCK_800MHZ;
4324 case 4: return TCK_933MHZ;
4325 case 3: return TCK_1066MHZ;
4326 case 2: return TCK_1200MHZ;
4327 case 1: return TCK_1333MHZ;
4328 /* reserved: */
4329 default:
4330 break;
4331 }
4332 }
4333 return DEFAULT_TCK;
4334 } else {
4335 if (cfg->max_mem_clock_mhz >= 800)
4336 return TCK_800MHZ;
4337 else if (cfg->max_mem_clock_mhz >= 666)
4338 return TCK_666MHZ;
4339 else if (cfg->max_mem_clock_mhz >= 533)
4340 return TCK_533MHZ;
4341 else
4342 return TCK_400MHZ;
4343 }
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004344}
4345
4346void perform_raminit(int s3resume)
4347{
4348 spd_raw_data spd[4];
4349
4350 post_code(0x3a);
4351
4352 memset (spd, 0, sizeof (spd));
4353 mainboard_get_spd(spd);
4354
4355 timestamp_add_now(TS_BEFORE_INITRAM);
4356
4357 init_dram_ddr3(spd, 1, get_mem_min_tck(), s3resume);
4358}