blob: 65d4348c65e9835667465c086bb8664b2b930fc8 [file] [log] [blame]
Stefan Reinauer00636b02012-04-04 00:08:51 +02001/*
2 * This file is part of the coreboot project.
3 *
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004 * Copyright (C) 2014 Damien Zammit <damien@zamaudio.com>
5 * Copyright (C) 2014 Vladimir Serbinenko <phcoder@gmail.com>
Stefan Reinauer00636b02012-04-04 00:08:51 +02006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Stefan Reinauer00636b02012-04-04 00:08:51 +020015 */
16
17#include <console/console.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +020018#include <console/usb.h>
Kyösti Mälkki5687fc92013-11-28 18:11:49 +020019#include <bootmode.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020020#include <string.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020021#include <arch/io.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020022#include <cbmem.h>
23#include <arch/cbfs.h>
24#include <cbfs.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070025#include <halt.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020026#include <ip_checksum.h>
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010027#include <timestamp.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020028#include <pc80/mc146818rtc.h>
Alexander Couzens81c5c762016-03-09 03:13:45 +010029#include <northbridge/intel/common/mrc_cache.h>
Duncan Laurie7b508dd2012-04-09 12:30:43 -070030#include <device/pci_def.h>
Patrick Rudolphb97009e2016-02-28 15:24:04 +010031#include <memory_info.h>
32#include <smbios.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070033#include "raminit_native.h"
Stefan Reinauer00636b02012-04-04 00:08:51 +020034#include "sandybridge.h"
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070035#include <delay.h>
36#include <lib.h>
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010037#include <device/device.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020038
39/* Management Engine is in the southbridge */
40#include "southbridge/intel/bd82x6x/me.h"
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070041/* For SPD. */
42#include "southbridge/intel/bd82x6x/smbus.h"
43#include "arch/cpu.h"
44#include "cpu/x86/msr.h"
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010045#include <northbridge/intel/sandybridge/chip.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020046
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070047/* FIXME: no ECC support. */
48/* FIXME: no support for 3-channel chipsets. */
Stefan Reinauer00636b02012-04-04 00:08:51 +020049
Patrick Rudolph371d2912015-10-09 13:33:25 +020050/*
51 * Register description:
52 * Intel provides a command queue of depth four.
53 * Every command is configured by using multiple registers.
54 * On executing the command queue you have to provide the depth used.
55 *
56 * Known registers:
57 * Channel X = [0, 1]
58 * Command queue index Y = [0, 1, 2, 3]
59 *
60 * DEFAULT_MCHBAR + 0x4220 + 0x400 * X + 4 * Y: command io register
61 * Controls the DRAM command signals
62 * Bit 0: !RAS
63 * Bit 1: !CAS
64 * Bit 2: !WE
65 *
66 * DEFAULT_MCHBAR + 0x4200 + 0x400 * X + 4 * Y: addr bankslot io register
67 * Controls the address, bank address and slotrank signals
68 * Bit 0-15 : Address
69 * Bit 20-22: Bank Address
70 * Bit 24-25: slotrank
71 *
72 * DEFAULT_MCHBAR + 0x4230 + 0x400 * X + 4 * Y: idle register
73 * Controls the idle time after issuing this DRAM command
74 * Bit 16-32: number of clock-cylces to idle
75 *
76 * DEFAULT_MCHBAR + 0x4284 + 0x400 * channel: execute command queue
77 * Starts to execute all queued commands
78 * Bit 0 : start DRAM command execution
79 * Bit 16-20: (number of queued commands - 1) * 4
80 */
81
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070082#define BASEFREQ 133
83#define tDLLK 512
Stefan Reinauer00636b02012-04-04 00:08:51 +020084
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070085#define IS_SANDY_CPU(x) ((x & 0xffff0) == 0x206a0)
86#define IS_SANDY_CPU_C(x) ((x & 0xf) == 4)
87#define IS_SANDY_CPU_D0(x) ((x & 0xf) == 5)
88#define IS_SANDY_CPU_D1(x) ((x & 0xf) == 6)
89#define IS_SANDY_CPU_D2(x) ((x & 0xf) == 7)
Stefan Reinauer00636b02012-04-04 00:08:51 +020090
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070091#define IS_IVY_CPU(x) ((x & 0xffff0) == 0x306a0)
92#define IS_IVY_CPU_C(x) ((x & 0xf) == 4)
93#define IS_IVY_CPU_K(x) ((x & 0xf) == 5)
94#define IS_IVY_CPU_D(x) ((x & 0xf) == 6)
95#define IS_IVY_CPU_E(x) ((x & 0xf) >= 8)
Stefan Reinauer00636b02012-04-04 00:08:51 +020096
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070097#define NUM_CHANNELS 2
98#define NUM_SLOTRANKS 4
99#define NUM_SLOTS 2
100#define NUM_LANES 8
Stefan Reinauer00636b02012-04-04 00:08:51 +0200101
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700102/* FIXME: Vendor BIOS uses 64 but our algorithms are less
103 performant and even 1 seems to be enough in practice. */
104#define NUM_PATTERNS 4
Stefan Reinauer00636b02012-04-04 00:08:51 +0200105
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700106typedef struct odtmap_st {
107 u16 rttwr;
108 u16 rttnom;
109} odtmap;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200110
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700111typedef struct dimm_info_st {
112 dimm_attr dimm[NUM_CHANNELS][NUM_SLOTS];
113} dimm_info;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200114
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700115struct ram_rank_timings {
116 /* Register 4024. One byte per slotrank. */
117 u8 val_4024;
118 /* Register 4028. One nibble per slotrank. */
119 u8 val_4028;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200120
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700121 int val_320c;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200122
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700123 struct ram_lane_timings {
124 /* lane register offset 0x10. */
125 u16 timA; /* bits 0 - 5, bits 16 - 18 */
126 u8 rising; /* bits 8 - 14 */
127 u8 falling; /* bits 20 - 26. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200128
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700129 /* lane register offset 0x20. */
130 int timC; /* bit 0 - 5, 19. */
131 u16 timB; /* bits 8 - 13, 15 - 17. */
132 } lanes[NUM_LANES];
133};
Stefan Reinauer00636b02012-04-04 00:08:51 +0200134
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700135struct ramctr_timing_st;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200136
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700137typedef struct ramctr_timing_st {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100138 u16 spd_crc[NUM_CHANNELS][NUM_SLOTS];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700139 int mobile;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200140
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700141 u16 cas_supported;
142 /* tLatencies are in units of ns, scaled by x256 */
143 u32 tCK;
144 u32 tAA;
145 u32 tWR;
146 u32 tRCD;
147 u32 tRRD;
148 u32 tRP;
149 u32 tRAS;
150 u32 tRFC;
151 u32 tWTR;
152 u32 tRTP;
153 u32 tFAW;
154 /* Latencies in terms of clock cycles
155 * They are saved separately as they are needed for DRAM MRS commands*/
156 u8 CAS; /* CAS read latency */
157 u8 CWL; /* CAS write latency */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200158
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700159 u32 tREFI;
160 u32 tMOD;
161 u32 tXSOffset;
162 u32 tWLO;
163 u32 tCKE;
164 u32 tXPDLL;
165 u32 tXP;
166 u32 tAONPD;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200167
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700168 u16 reg_5064b0; /* bits 0-11. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200169
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700170 u8 rankmap[NUM_CHANNELS];
171 int ref_card_offset[NUM_CHANNELS];
172 u32 mad_dimm[NUM_CHANNELS];
173 int channel_size_mb[NUM_CHANNELS];
174 u32 cmd_stretch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200175
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700176 int reg_c14_offset;
177 int reg_320c_range_threshold;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200178
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700179 int edge_offset[3];
180 int timC_offset[3];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200181
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700182 int extended_temperature_range;
183 int auto_self_refresh;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200184
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700185 int rank_mirror[NUM_CHANNELS][NUM_SLOTRANKS];
186
187 struct ram_rank_timings timings[NUM_CHANNELS][NUM_SLOTRANKS];
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100188
189 dimm_info info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700190} ramctr_timing;
191
192#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
193#define NORTHBRIDGE PCI_DEV(0, 0x0, 0)
194#define FOR_ALL_LANES for (lane = 0; lane < NUM_LANES; lane++)
195#define FOR_ALL_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++)
196#define FOR_ALL_POPULATED_RANKS for (slotrank = 0; slotrank < NUM_SLOTRANKS; slotrank++) if (ctrl->rankmap[channel] & (1 << slotrank))
197#define FOR_ALL_POPULATED_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) if (ctrl->rankmap[channel])
198#define MAX_EDGE_TIMING 71
199#define MAX_TIMC 127
200#define MAX_TIMB 511
201#define MAX_TIMA 127
202
Patrick Rudolph24a845b2016-03-25 18:19:47 +0100203#define MAKE_ERR ((channel<<16)|(slotrank<<8)|1)
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100204#define GET_ERR_CHANNEL(x) (x>>16)
Patrick Rudolph24a845b2016-03-25 18:19:47 +0100205
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700206static void program_timings(ramctr_timing * ctrl, int channel);
Patrick Rudolph266a1f72016-06-09 18:13:34 +0200207static unsigned int get_mmio_size(void);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700208
209static const char *ecc_decoder[] = {
Stefan Reinauer00636b02012-04-04 00:08:51 +0200210 "inactive",
211 "active on IO",
212 "disabled on IO",
213 "active"
214};
215
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700216static void wait_txt_clear(void)
217{
218 struct cpuid_result cp;
219
220 cp = cpuid_ext(0x1, 0x0);
221 /* Check if TXT is supported? */
222 if (!(cp.ecx & 0x40))
223 return;
224 /* Some TXT public bit. */
225 if (!(read32((void *)0xfed30010) & 1))
226 return;
227 /* Wait for TXT clear. */
Elyes HAOUAS7db506c2016-10-02 11:56:39 +0200228 while (!(read8((void *)0xfed40000) & (1 << 7)));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700229}
230
231static void sfence(void)
232{
233 asm volatile ("sfence");
234}
235
Patrick Rudolph9b515682015-10-09 13:43:51 +0200236static void toggle_io_reset(void) {
237 /* toggle IO reset bit */
238 u32 r32 = read32(DEFAULT_MCHBAR + 0x5030);
239 write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20);
240 udelay(1);
241 write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20);
242 udelay(1);
243}
244
Stefan Reinauer00636b02012-04-04 00:08:51 +0200245/*
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100246 * Disable a channel in ramctr_timing.
247 */
248static void disable_channel(ramctr_timing *ctrl, int channel) {
249 ctrl->rankmap[channel] = 0;
250 memset(&ctrl->rank_mirror[channel][0], 0, sizeof(ctrl->rank_mirror[0]));
251 ctrl->channel_size_mb[channel] = 0;
252 ctrl->cmd_stretch[channel] = 0;
253 ctrl->mad_dimm[channel] = 0;
254 memset(&ctrl->timings[channel][0], 0, sizeof(ctrl->timings[0]));
255}
256
257/*
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100258 * Fill cbmem with information for SMBIOS type 17.
259 */
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100260static void fill_smbios17(ramctr_timing *ctrl)
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100261{
262 struct memory_info *mem_info;
263 int channel, slot;
264 struct dimm_info *dimm;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100265 uint16_t ddr_freq;
266 dimm_info *info = &ctrl->info;
267
268 ddr_freq = (1000 << 8) / ctrl->tCK;
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100269
270 /*
271 * Allocate CBMEM area for DIMM information used to populate SMBIOS
272 * table 17
273 */
274 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
275 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
276 if (!mem_info)
277 return;
278
279 memset(mem_info, 0, sizeof(*mem_info));
280
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200281 FOR_ALL_CHANNELS for (slot = 0; slot < NUM_SLOTS; slot++) {
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100282 dimm = &mem_info->dimm[mem_info->dimm_cnt];
283 if (info->dimm[channel][slot].size_mb) {
284 dimm->ddr_type = MEMORY_TYPE_DDR3;
285 dimm->ddr_frequency = ddr_freq;
286 dimm->dimm_size = info->dimm[channel][slot].size_mb;
287 dimm->channel_num = channel;
288 dimm->rank_per_dimm = info->dimm[channel][slot].ranks;
289 dimm->dimm_num = slot;
290 memcpy(dimm->module_part_number,
291 info->dimm[channel][slot].part_number, 16);
292 dimm->mod_id = info->dimm[channel][slot].manufacturer_id;
293 dimm->mod_type = info->dimm[channel][slot].dimm_type;
294 dimm->bus_width = info->dimm[channel][slot].width;
295 mem_info->dimm_cnt++;
296 }
297 }
298}
299
300/*
Stefan Reinauer00636b02012-04-04 00:08:51 +0200301 * Dump in the log memory controller configuration as read from the memory
302 * controller registers.
303 */
304static void report_memory_config(void)
305{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700306 u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200307 int i;
308
309 addr_decoder_common = MCHBAR32(0x5000);
310 addr_decode_ch[0] = MCHBAR32(0x5004);
311 addr_decode_ch[1] = MCHBAR32(0x5008);
312
313 printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700314 (MCHBAR32(0x5e04) * 13333 * 2 + 50) / 100);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200315 printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700316 addr_decoder_common & 3, (addr_decoder_common >> 2) & 3,
Stefan Reinauer00636b02012-04-04 00:08:51 +0200317 (addr_decoder_common >> 4) & 3);
318
319 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
320 u32 ch_conf = addr_decode_ch[i];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700321 printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i,
322 ch_conf);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200323 printk(BIOS_DEBUG, " ECC %s\n",
324 ecc_decoder[(ch_conf >> 24) & 3]);
325 printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
326 ((ch_conf >> 22) & 1) ? "on" : "off");
327 printk(BIOS_DEBUG, " rank interleave %s\n",
328 ((ch_conf >> 21) & 1) ? "on" : "off");
329 printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n",
330 ((ch_conf >> 0) & 0xff) * 256,
331 ((ch_conf >> 19) & 1) ? 16 : 8,
332 ((ch_conf >> 17) & 1) ? "dual" : "single",
333 ((ch_conf >> 16) & 1) ? "" : ", selected");
334 printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n",
335 ((ch_conf >> 8) & 0xff) * 256,
336 ((ch_conf >> 20) & 1) ? 16 : 8,
337 ((ch_conf >> 18) & 1) ? "dual" : "single",
338 ((ch_conf >> 16) & 1) ? ", selected" : "");
339 }
340}
341
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100342/*
343 * Return CRC16 match for all SPDs.
344 */
345static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
346{
347 int channel, slot, spd_slot;
348 int match = 1;
349
350 FOR_ALL_CHANNELS {
351 for (slot = 0; slot < NUM_SLOTS; slot++) {
352 spd_slot = 2 * channel + slot;
353 match &= ctrl->spd_crc[channel][slot] ==
354 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
355 }
356 }
357 return match;
358}
359
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700360void read_spd(spd_raw_data * spd, u8 addr)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200361{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700362 int j;
363 for (j = 0; j < 256; j++)
364 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
365}
366
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100367static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700368{
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100369 int dimms = 0, dimms_on_channel;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700370 int channel, slot, spd_slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100371 dimm_info *dimm = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700372
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +0200373 memset (ctrl->rankmap, 0, sizeof(ctrl->rankmap));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700374
375 ctrl->extended_temperature_range = 1;
376 ctrl->auto_self_refresh = 1;
377
378 FOR_ALL_CHANNELS {
379 ctrl->channel_size_mb[channel] = 0;
380
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100381 dimms_on_channel = 0;
382 /* count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700383 for (slot = 0; slot < NUM_SLOTS; slot++) {
384 spd_slot = 2 * channel + slot;
385 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100386 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
387 dimms_on_channel++;
388 }
389
390 for (slot = 0; slot < NUM_SLOTS; slot++) {
391 spd_slot = 2 * channel + slot;
392 /* search for XMP profile */
393 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
394 spd[spd_slot],
395 DDR3_XMP_PROFILE_1);
396
397 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
398 printram("No valid XMP profile found.\n");
399 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
400 } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
401 printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
402 dimm->dimm[channel][slot].dimms_per_channel,
403 dimms_on_channel);
404 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
405 } else if (dimm->dimm[channel][slot].voltage != 1500) {
406 /* TODO: support other DDR3 voltage than 1500mV */
407 printram("XMP profile's requested %u mV is unsupported.\n",
408 dimm->dimm[channel][slot].voltage);
409 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
410 }
411
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100412 /* fill in CRC16 for MRC cache */
413 ctrl->spd_crc[channel][slot] =
414 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
415
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700416 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
417 // set dimm invalid
418 dimm->dimm[channel][slot].ranks = 0;
419 dimm->dimm[channel][slot].size_mb = 0;
420 continue;
421 }
422
423 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
424 dimms++;
425 ctrl->rank_mirror[channel][slot * 2] = 0;
426 ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
427 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
428
429 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
430 ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
431
432 ctrl->rankmap[channel] |= ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100433 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n",
434 channel, ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700435 }
436 if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc)
437 && dimm->dimm[channel][0].reference_card <= 5 && dimm->dimm[channel][1].reference_card <= 5) {
438 const int ref_card_offset_table[6][6] = {
439 { 0, 0, 0, 0, 2, 2, },
440 { 0, 0, 0, 0, 2, 2, },
441 { 0, 0, 0, 0, 2, 2, },
442 { 0, 0, 0, 0, 1, 1, },
443 { 2, 2, 2, 1, 0, 0, },
444 { 2, 2, 2, 1, 0, 0, },
445 };
446 ctrl->ref_card_offset[channel] = ref_card_offset_table[dimm->dimm[channel][0].reference_card]
447 [dimm->dimm[channel][1].reference_card];
448 } else
449 ctrl->ref_card_offset[channel] = 0;
450 }
451
452 if (!dimms)
453 die("No DIMMs were found");
454}
455
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100456static void dram_find_common_params(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700457{
458 size_t valid_dimms;
459 int channel, slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100460 dimm_info *dimms = &ctrl->info;
461
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700462 ctrl->cas_supported = 0xff;
463 valid_dimms = 0;
464 FOR_ALL_CHANNELS for (slot = 0; slot < 2; slot++) {
465 const dimm_attr *dimm = &dimms->dimm[channel][slot];
466 if (dimm->dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3)
467 continue;
468 valid_dimms++;
469
470 /* Find all possible CAS combinations */
471 ctrl->cas_supported &= dimm->cas_supported;
472
473 /* Find the smallest common latencies supported by all DIMMs */
474 ctrl->tCK = MAX(ctrl->tCK, dimm->tCK);
475 ctrl->tAA = MAX(ctrl->tAA, dimm->tAA);
476 ctrl->tWR = MAX(ctrl->tWR, dimm->tWR);
477 ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD);
478 ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD);
479 ctrl->tRP = MAX(ctrl->tRP, dimm->tRP);
480 ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS);
481 ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC);
482 ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR);
483 ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP);
484 ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW);
485 }
486
487 if (!ctrl->cas_supported)
488 die("Unsupported DIMM combination. "
489 "DIMMS do not support common CAS latency");
490 if (!valid_dimms)
491 die("No valid DIMMs found");
492}
493
Patrick Rudolphbec66962016-11-11 19:17:56 +0100494/* CAS write latency. To be programmed in MR2.
495 * See DDR3 SPEC for MR2 documentation. */
496static u8 get_CWL(u32 tCK)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700497{
Patrick Rudolphbec66962016-11-11 19:17:56 +0100498 /* Get CWL based on tCK using the following rule: */
499 switch (tCK) {
500 case TCK_1333MHZ:
501 return 12;
502 case TCK_1200MHZ:
503 case TCK_1100MHZ:
504 return 11;
505 case TCK_1066MHZ:
506 case TCK_1000MHZ:
507 return 10;
508 case TCK_933MHZ:
509 case TCK_900MHZ:
510 return 9;
511 case TCK_800MHZ:
512 case TCK_700MHZ:
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700513 return 8;
Patrick Rudolphbec66962016-11-11 19:17:56 +0100514 case TCK_666MHZ:
515 return 7;
516 case TCK_533MHZ:
517 return 6;
518 default:
519 return 5;
520 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700521}
522
523/* Frequency multiplier. */
524static u32 get_FRQ(u32 tCK)
525{
526 u32 FRQ;
527 FRQ = 256000 / (tCK * BASEFREQ);
528 if (FRQ > 8)
529 return 8;
530 if (FRQ < 3)
531 return 3;
532 return FRQ;
533}
534
535static u32 get_REFI(u32 tCK)
536{
537 /* Get REFI based on MCU frequency using the following rule:
538 * _________________________________________
539 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
540 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 |
541 */
542 static const u32 frq_refi_map[] =
543 { 3120, 4160, 5200, 6240, 7280, 8320 };
544 return frq_refi_map[get_FRQ(tCK) - 3];
545}
546
547static u8 get_XSOffset(u32 tCK)
548{
549 /* Get XSOffset based on MCU frequency using the following rule:
550 * _________________________
551 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
552 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 |
553 */
554 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 };
555 return frq_xs_map[get_FRQ(tCK) - 3];
556}
557
558static u8 get_MOD(u32 tCK)
559{
560 /* Get MOD based on MCU frequency using the following rule:
561 * _____________________________
562 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
563 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 |
564 */
565 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 };
566 return frq_mod_map[get_FRQ(tCK) - 3];
567}
568
569static u8 get_WLO(u32 tCK)
570{
571 /* Get WLO based on MCU frequency using the following rule:
572 * _______________________
573 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
574 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 |
575 */
576 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 };
577 return frq_wlo_map[get_FRQ(tCK) - 3];
578}
579
580static u8 get_CKE(u32 tCK)
581{
582 /* Get CKE based on MCU frequency using the following rule:
583 * _______________________
584 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
585 * CKE : | 3 | 3 | 4 | 4 | 5 | 6 |
586 */
587 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 };
588 return frq_cke_map[get_FRQ(tCK) - 3];
589}
590
591static u8 get_XPDLL(u32 tCK)
592{
593 /* Get XPDLL based on MCU frequency using the following rule:
594 * _____________________________
595 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
596 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 |
597 */
598 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 };
599 return frq_xpdll_map[get_FRQ(tCK) - 3];
600}
601
602static u8 get_XP(u32 tCK)
603{
604 /* Get XP based on MCU frequency using the following rule:
605 * _______________________
606 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
607 * XP : | 3 | 4 | 4 | 5 | 6 | 7 |
608 */
609 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 };
610 return frq_xp_map[get_FRQ(tCK) - 3];
611}
612
613static u8 get_AONPD(u32 tCK)
614{
615 /* Get AONPD based on MCU frequency using the following rule:
616 * ________________________
617 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
618 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 |
619 */
620 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 };
621 return frq_aonpd_map[get_FRQ(tCK) - 3];
622}
623
624static u32 get_COMP2(u32 tCK)
625{
626 /* Get COMP2 based on MCU frequency using the following rule:
627 * ___________________________________________________________
628 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
629 * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C |
630 */
631 static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C,
632 0xC6369CC, 0xC42514C, 0xC21410C
633 };
634 return frq_comp2_map[get_FRQ(tCK) - 3];
635}
636
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100637static u32 get_XOVER_CLK(u8 rankmap)
638{
639 return rankmap << 24;
640}
641
642static u32 get_XOVER_CMD(u8 rankmap)
643{
644 u32 reg;
645
646 // enable xover cmd
647 reg = 0x4000;
648
649 // enable xover ctl
650 if (rankmap & 0x3)
651 reg |= 0x20000;
652
653 if (rankmap & 0xc)
654 reg |= 0x4000000;
655
656 return reg;
657}
658
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700659static void dram_timing(ramctr_timing * ctrl)
660{
661 u8 val;
662 u32 val32;
663
664 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
665 * we cap it if we have faster DIMMs.
666 * Then, align it to the closest JEDEC standard frequency */
667 if (ctrl->tCK <= TCK_1066MHZ) {
668 ctrl->tCK = TCK_1066MHZ;
669 ctrl->edge_offset[0] = 16;
670 ctrl->edge_offset[1] = 7;
671 ctrl->edge_offset[2] = 7;
672 ctrl->timC_offset[0] = 18;
673 ctrl->timC_offset[1] = 7;
674 ctrl->timC_offset[2] = 7;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700675 ctrl->reg_320c_range_threshold = 13;
676 } else if (ctrl->tCK <= TCK_933MHZ) {
677 ctrl->tCK = TCK_933MHZ;
678 ctrl->edge_offset[0] = 14;
679 ctrl->edge_offset[1] = 6;
680 ctrl->edge_offset[2] = 6;
681 ctrl->timC_offset[0] = 15;
682 ctrl->timC_offset[1] = 6;
683 ctrl->timC_offset[2] = 6;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700684 ctrl->reg_320c_range_threshold = 15;
685 } else if (ctrl->tCK <= TCK_800MHZ) {
686 ctrl->tCK = TCK_800MHZ;
687 ctrl->edge_offset[0] = 13;
688 ctrl->edge_offset[1] = 5;
689 ctrl->edge_offset[2] = 5;
690 ctrl->timC_offset[0] = 14;
691 ctrl->timC_offset[1] = 5;
692 ctrl->timC_offset[2] = 5;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700693 ctrl->reg_320c_range_threshold = 15;
694 } else if (ctrl->tCK <= TCK_666MHZ) {
695 ctrl->tCK = TCK_666MHZ;
696 ctrl->edge_offset[0] = 10;
697 ctrl->edge_offset[1] = 4;
698 ctrl->edge_offset[2] = 4;
699 ctrl->timC_offset[0] = 11;
700 ctrl->timC_offset[1] = 4;
701 ctrl->timC_offset[2] = 4;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700702 ctrl->reg_320c_range_threshold = 16;
703 } else if (ctrl->tCK <= TCK_533MHZ) {
704 ctrl->tCK = TCK_533MHZ;
705 ctrl->edge_offset[0] = 8;
706 ctrl->edge_offset[1] = 3;
707 ctrl->edge_offset[2] = 3;
708 ctrl->timC_offset[0] = 9;
709 ctrl->timC_offset[1] = 3;
710 ctrl->timC_offset[2] = 3;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700711 ctrl->reg_320c_range_threshold = 17;
712 } else {
713 ctrl->tCK = TCK_400MHZ;
714 ctrl->edge_offset[0] = 6;
715 ctrl->edge_offset[1] = 2;
716 ctrl->edge_offset[2] = 2;
717 ctrl->timC_offset[0] = 6;
718 ctrl->timC_offset[1] = 2;
719 ctrl->timC_offset[2] = 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700720 ctrl->reg_320c_range_threshold = 17;
721 }
722
Patrick Rudolphd4c53e32016-06-14 20:07:32 +0200723 /* Initial phase between CLK/CMD pins */
724 ctrl->reg_c14_offset = (256000 / ctrl->tCK) / 66;
725
Patrick Rudolphb7b1b282016-06-14 18:44:28 +0200726 /* DLL_CONFIG_MDLL_W_TIMER */
727 ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3;
728
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700729 val32 = (1000 << 8) / ctrl->tCK;
730 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
731
Patrick Rudolphbec66962016-11-11 19:17:56 +0100732 /* Find CAS latency */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700733 val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK;
734 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
735 /* Find lowest supported CAS latency that satisfies the minimum value */
736 while (!((ctrl->cas_supported >> (val - 4)) & 1)
737 && (ctrl->cas_supported >> (val - 4))) {
738 val++;
739 }
740 /* Is CAS supported */
Patrick Rudolph55409eb2016-06-15 20:28:32 +0200741 if (!(ctrl->cas_supported & (1 << (val - 4)))) {
742 printk(BIOS_ERR, "CAS %uT not supported. ", val);
743 val = 18;
744 /* Find highest supported CAS latency */
745 while (!((ctrl->cas_supported >> (val - 4)) & 1))
746 val--;
747
748 printk(BIOS_ERR, "Using CAS %uT instead.\n", val);
749 }
750
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700751 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
752 ctrl->CAS = val;
Patrick Rudolphbec66962016-11-11 19:17:56 +0100753 ctrl->CWL = get_CWL(ctrl->tCK);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700754 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
755
756 /* Find tRCD */
757 ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK;
758 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
759
760 ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK;
761 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
762
763 /* Find tRAS */
764 ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK;
765 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
766
767 /* Find tWR */
768 ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK;
769 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
770
771 /* Find tFAW */
772 ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK;
773 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
774
775 /* Find tRRD */
776 ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK;
777 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
778
779 /* Find tRTP */
780 ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK;
781 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
782
783 /* Find tWTR */
784 ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK;
785 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
786
787 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
788 ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK;
789 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
790
791 ctrl->tREFI = get_REFI(ctrl->tCK);
792 ctrl->tMOD = get_MOD(ctrl->tCK);
793 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
794 ctrl->tWLO = get_WLO(ctrl->tCK);
795 ctrl->tCKE = get_CKE(ctrl->tCK);
796 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
797 ctrl->tXP = get_XP(ctrl->tCK);
798 ctrl->tAONPD = get_AONPD(ctrl->tCK);
799}
800
801static void dram_freq(ramctr_timing * ctrl)
802{
803 if (ctrl->tCK > TCK_400MHZ) {
804 printk (BIOS_ERR, "DRAM frequency is under lowest supported frequency (400 MHz). Increasing to 400 MHz as last resort");
805 ctrl->tCK = TCK_400MHZ;
806 }
807 while (1) {
808 u8 val2;
809 u32 reg1 = 0;
810
811 /* Step 1 - Set target PCU frequency */
812
813 if (ctrl->tCK <= TCK_1066MHZ) {
814 ctrl->tCK = TCK_1066MHZ;
815 } else if (ctrl->tCK <= TCK_933MHZ) {
816 ctrl->tCK = TCK_933MHZ;
817 } else if (ctrl->tCK <= TCK_800MHZ) {
818 ctrl->tCK = TCK_800MHZ;
819 } else if (ctrl->tCK <= TCK_666MHZ) {
820 ctrl->tCK = TCK_666MHZ;
821 } else if (ctrl->tCK <= TCK_533MHZ) {
822 ctrl->tCK = TCK_533MHZ;
823 } else if (ctrl->tCK <= TCK_400MHZ) {
824 ctrl->tCK = TCK_400MHZ;
825 } else {
826 die ("No lock frequency found");
827 }
828
829 /* Frequency mulitplier. */
830 u32 FRQ = get_FRQ(ctrl->tCK);
831
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100832 /* The PLL will never lock if the required frequency is
833 * already set. Exit early to prevent a system hang.
834 */
835 reg1 = MCHBAR32(0x5e04);
836 val2 = (u8) reg1;
Patrick Rudolphf7047542016-11-12 11:39:57 +0100837 if (val2)
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100838 return;
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100839
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700840 /* Step 2 - Select frequency in the MCU */
841 reg1 = FRQ;
842 reg1 |= 0x80000000; // set running bit
843 MCHBAR32(0x5e00) = reg1;
844 while (reg1 & 0x80000000) {
845 printk(BIOS_DEBUG, " PLL busy...");
846 reg1 = MCHBAR32(0x5e00);
847 }
848 printk(BIOS_DEBUG, "done\n");
849
850 /* Step 3 - Verify lock frequency */
851 reg1 = MCHBAR32(0x5e04);
852 val2 = (u8) reg1;
853 if (val2 >= FRQ) {
854 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
855 (1000 << 8) / ctrl->tCK);
856 return;
857 }
858 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
859 ctrl->tCK++;
860 }
861}
862
863static void dram_xover(ramctr_timing * ctrl)
864{
865 u32 reg;
866 int channel;
867
868 FOR_ALL_CHANNELS {
869 // enable xover clk
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100870 reg = get_XOVER_CLK(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100871 printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
872 reg);
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100873 MCHBAR32(channel * 0x100 + 0xc14) = reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700874
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100875 // enable xover ctl & xover cmd
876 reg = get_XOVER_CMD(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100877 printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
878 reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700879 MCHBAR32(0x100 * channel + 0x320c) = reg;
880 }
881}
882
883static void dram_timing_regs(ramctr_timing * ctrl)
884{
885 u32 reg, addr, val32, cpu, stretch;
886 struct cpuid_result cpures;
887 int channel;
888
889 FOR_ALL_CHANNELS {
890 // DBP
891 reg = 0;
892 reg |= ctrl->tRCD;
893 reg |= (ctrl->tRP << 4);
894 reg |= (ctrl->CAS << 8);
895 reg |= (ctrl->CWL << 12);
896 reg |= (ctrl->tRAS << 16);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100897 printram("DBP [%x] = %x\n", 0x400 * channel + 0x4000, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700898 MCHBAR32(0x400 * channel + 0x4000) = reg;
899
900 // RAP
901 reg = 0;
902 reg |= ctrl->tRRD;
903 reg |= (ctrl->tRTP << 4);
904 reg |= (ctrl->tCKE << 8);
905 reg |= (ctrl->tWTR << 12);
906 reg |= (ctrl->tFAW << 16);
907 reg |= (ctrl->tWR << 24);
908 reg |= (3 << 30);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100909 printram("RAP [%x] = %x\n", 0x400 * channel + 0x4004, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700910 MCHBAR32(0x400 * channel + 0x4004) = reg;
911
912 // OTHP
913 addr = 0x400 * channel + 0x400c;
914 reg = 0;
915 reg |= ctrl->tXPDLL;
916 reg |= (ctrl->tXP << 5);
917 reg |= (ctrl->tAONPD << 8);
918 reg |= 0xa0000;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100919 printram("OTHP [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700920 MCHBAR32(addr) = reg;
921
922 MCHBAR32(0x400 * channel + 0x4014) = 0;
923
924 MCHBAR32(addr) |= 0x00020000;
925
926 // ODT stretch
927 reg = 0;
928
Ryan Salsamendie4da9aa2016-06-24 12:01:11 -0700929 cpures = cpuid(1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700930 cpu = cpures.eax;
931 if (IS_IVY_CPU(cpu)
932 || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) {
933 stretch = 2;
934 addr = 0x400 * channel + 0x400c;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100935 printram("ODT stretch [%x] = %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700936 0x400 * channel + 0x400c, reg);
937 reg = MCHBAR32(addr);
938
939 if (((ctrl->rankmap[channel] & 3) == 0)
940 || (ctrl->rankmap[channel] & 0xc) == 0) {
941
942 // Rank 0 - operate on rank 2
943 reg = (reg & ~0xc0000) | (stretch << 18);
944
945 // Rank 2 - operate on rank 0
946 reg = (reg & ~0x30000) | (stretch << 16);
947
Patrick Rudolpha649a542016-01-17 18:32:06 +0100948 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700949 MCHBAR32(addr) = reg;
950 }
951
952 } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) {
953 stretch = 3;
954 addr = 0x400 * channel + 0x401c;
955 reg = MCHBAR32(addr);
956
957 if (((ctrl->rankmap[channel] & 3) == 0)
958 || (ctrl->rankmap[channel] & 0xc) == 0) {
959
960 // Rank 0 - operate on rank 2
961 reg = (reg & ~0x3000) | (stretch << 12);
962
963 // Rank 2 - operate on rank 0
964 reg = (reg & ~0xc00) | (stretch << 10);
965
Patrick Rudolpha649a542016-01-17 18:32:06 +0100966 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700967 MCHBAR32(addr) = reg;
968 }
969 } else {
970 stretch = 0;
971 }
972
973 // REFI
974 reg = 0;
975 val32 = ctrl->tREFI;
976 reg = (reg & ~0xffff) | val32;
977 val32 = ctrl->tRFC;
978 reg = (reg & ~0x1ff0000) | (val32 << 16);
979 val32 = (u32) (ctrl->tREFI * 9) / 1024;
980 reg = (reg & ~0xfe000000) | (val32 << 25);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100981 printram("REFI [%x] = %x\n", 0x400 * channel + 0x4298,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700982 reg);
983 MCHBAR32(0x400 * channel + 0x4298) = reg;
984
985 MCHBAR32(0x400 * channel + 0x4294) |= 0xff;
986
987 // SRFTP
988 reg = 0;
989 val32 = tDLLK;
990 reg = (reg & ~0xfff) | val32;
991 val32 = ctrl->tXSOffset;
992 reg = (reg & ~0xf000) | (val32 << 12);
993 val32 = tDLLK - ctrl->tXSOffset;
994 reg = (reg & ~0x3ff0000) | (val32 << 16);
995 val32 = ctrl->tMOD - 8;
996 reg = (reg & ~0xf0000000) | (val32 << 28);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100997 printram("SRFTP [%x] = %x\n", 0x400 * channel + 0x42a4,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700998 reg);
999 MCHBAR32(0x400 * channel + 0x42a4) = reg;
1000 }
1001}
1002
Patrick Rudolph735ecce2016-03-26 10:42:27 +01001003static void dram_dimm_mapping(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001004{
1005 u32 reg, val32;
1006 int channel;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01001007 dimm_info *info = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001008
1009 FOR_ALL_CHANNELS {
1010 dimm_attr *dimmA = 0;
1011 dimm_attr *dimmB = 0;
1012 reg = 0;
1013 val32 = 0;
1014 if (info->dimm[channel][0].size_mb >=
1015 info->dimm[channel][1].size_mb) {
1016 // dimm 0 is bigger, set it to dimmA
1017 dimmA = &info->dimm[channel][0];
1018 dimmB = &info->dimm[channel][1];
1019 reg |= (0 << 16);
1020 } else {
1021 // dimm 1 is bigger, set it to dimmA
1022 dimmA = &info->dimm[channel][1];
1023 dimmB = &info->dimm[channel][0];
1024 reg |= (1 << 16);
1025 }
1026 // dimmA
1027 if (dimmA && (dimmA->ranks > 0)) {
1028 val32 = dimmA->size_mb / 256;
1029 reg = (reg & ~0xff) | val32;
1030 val32 = dimmA->ranks - 1;
1031 reg = (reg & ~0x20000) | (val32 << 17);
1032 val32 = (dimmA->width / 8) - 1;
1033 reg = (reg & ~0x80000) | (val32 << 19);
1034 }
1035 // dimmB
1036 if (dimmB && (dimmB->ranks > 0)) {
1037 val32 = dimmB->size_mb / 256;
1038 reg = (reg & ~0xff00) | (val32 << 8);
1039 val32 = dimmB->ranks - 1;
1040 reg = (reg & ~0x40000) | (val32 << 18);
1041 val32 = (dimmB->width / 8) - 1;
1042 reg = (reg & ~0x100000) | (val32 << 20);
1043 }
1044 reg = (reg & ~0x200000) | (1 << 21); // rank interleave
1045 reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave
1046
1047 // Save MAD-DIMM register
1048 if ((dimmA && (dimmA->ranks > 0))
1049 || (dimmB && (dimmB->ranks > 0))) {
1050 ctrl->mad_dimm[channel] = reg;
1051 } else {
1052 ctrl->mad_dimm[channel] = 0;
1053 }
1054 }
1055}
1056
1057static void dram_dimm_set_mapping(ramctr_timing * ctrl)
1058{
1059 int channel;
1060 FOR_ALL_CHANNELS {
1061 MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
1062 }
1063}
1064
1065static void dram_zones(ramctr_timing * ctrl, int training)
1066{
1067 u32 reg, ch0size, ch1size;
1068 u8 val;
1069 reg = 0;
1070 val = 0;
1071 if (training) {
1072 ch0size = ctrl->channel_size_mb[0] ? 256 : 0;
1073 ch1size = ctrl->channel_size_mb[1] ? 256 : 0;
1074 } else {
1075 ch0size = ctrl->channel_size_mb[0];
1076 ch1size = ctrl->channel_size_mb[1];
1077 }
1078
1079 if (ch0size >= ch1size) {
1080 reg = MCHBAR32(0x5014);
1081 val = ch1size / 256;
1082 reg = (reg & ~0xff000000) | val << 24;
1083 reg = (reg & ~0xff0000) | (2 * val) << 16;
1084 MCHBAR32(0x5014) = reg;
1085 MCHBAR32(0x5000) = 0x24;
1086 } else {
1087 reg = MCHBAR32(0x5014);
1088 val = ch0size / 256;
1089 reg = (reg & ~0xff000000) | val << 24;
1090 reg = (reg & ~0xff0000) | (2 * val) << 16;
1091 MCHBAR32(0x5014) = reg;
1092 MCHBAR32(0x5000) = 0x21;
1093 }
1094}
1095
1096static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
1097{
1098 u32 reg, val, reclaim;
1099 u32 tom, gfxstolen, gttsize;
1100 size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase,
1101 tsegbase, mestolenbase;
1102 size_t tsegbasedelta, remapbase, remaplimit;
1103 uint16_t ggc;
1104
Patrick Rudolph266a1f72016-06-09 18:13:34 +02001105 mmiosize = get_mmio_size();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001106
1107 ggc = pci_read_config16(NORTHBRIDGE, GGC);
1108 if (!(ggc & 2)) {
1109 gfxstolen = ((ggc >> 3) & 0x1f) * 32;
1110 gttsize = ((ggc >> 8) & 0x3);
1111 } else {
1112 gfxstolen = 0;
1113 gttsize = 0;
1114 }
1115
1116 tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
1117
1118 tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
1119
1120 mestolenbase = tom - me_uma_size;
1121
1122 toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
1123 tom - me_uma_size);
1124 gfxstolenbase = toludbase - gfxstolen;
1125 gttbase = gfxstolenbase - gttsize;
1126
1127 tsegbase = gttbase - tsegsize;
1128
1129 // Round tsegbase down to nearest address aligned to tsegsize
1130 tsegbasedelta = tsegbase & (tsegsize - 1);
1131 tsegbase &= ~(tsegsize - 1);
1132
1133 gttbase -= tsegbasedelta;
1134 gfxstolenbase -= tsegbasedelta;
1135 toludbase -= tsegbasedelta;
1136
Elyes HAOUAS15279a92016-07-28 21:05:26 +02001137 // Test if it is possible to reclaim a hole in the RAM addressing
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001138 if (tom - me_uma_size > toludbase) {
1139 // Reclaim is possible
1140 reclaim = 1;
1141 remapbase = MAX(4096, tom - me_uma_size);
1142 remaplimit =
1143 remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1;
1144 touudbase = remaplimit + 1;
1145 } else {
1146 // Reclaim not possible
1147 reclaim = 0;
1148 touudbase = tom - me_uma_size;
1149 }
1150
1151 // Update memory map in pci-e configuration space
Patrick Rudolpha649a542016-01-17 18:32:06 +01001152 printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001153
1154 // TOM (top of memory)
1155 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0);
1156 val = tom & 0xfff;
1157 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001158 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001159 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg);
1160
1161 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4);
1162 val = tom & 0xfffff000;
1163 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001164 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001165 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg);
1166
1167 // TOLUD (top of low used dram)
1168 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
1169 val = toludbase & 0xfff;
1170 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001171 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xbc, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001172 pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg);
1173
1174 // TOUUD LSB (top of upper usable dram)
1175 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
1176 val = touudbase & 0xfff;
1177 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001178 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001179 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg);
1180
1181 // TOUUD MSB
1182 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
1183 val = touudbase & 0xfffff000;
1184 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001185 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xac, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001186 pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg);
1187
1188 if (reclaim) {
1189 // REMAP BASE
1190 pcie_write_config32(PCI_DEV(0, 0, 0), 0x90, remapbase << 20);
1191 pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, remapbase >> 12);
1192
1193 // REMAP LIMIT
1194 pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
1195 pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
1196 }
1197 // TSEG
1198 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
1199 val = tsegbase & 0xfff;
1200 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001201 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001202 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg);
1203
1204 // GFX stolen memory
1205 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0);
1206 val = gfxstolenbase & 0xfff;
1207 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001208 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001209 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg);
1210
1211 // GTT stolen memory
1212 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4);
1213 val = gttbase & 0xfff;
1214 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001215 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001216 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
1217
1218 if (me_uma_size) {
1219 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
1220 val = (0x80000 - me_uma_size) & 0xfffff000;
1221 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001222 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x7c, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001223 pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg);
1224
1225 // ME base
1226 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70);
1227 val = mestolenbase & 0xfff;
1228 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001229 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x70, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001230 pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg);
1231
1232 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74);
1233 val = mestolenbase & 0xfffff000;
1234 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001235 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x74, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001236 pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg);
1237
1238 // ME mask
1239 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78);
1240 val = (0x80000 - me_uma_size) & 0xfff;
1241 reg = (reg & ~0xfff00000) | (val << 20);
1242 reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem
1243
1244 reg = (reg & ~0x800) | (1 << 11); // set ME memory enable
Patrick Rudolpha649a542016-01-17 18:32:06 +01001245 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x78, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001246 pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg);
1247 }
1248}
1249
1250static void dram_ioregs(ramctr_timing * ctrl)
1251{
1252 u32 reg, comp2;
1253
1254 int channel;
1255
1256 // IO clock
1257 FOR_ALL_CHANNELS {
1258 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
1259 }
1260
1261 // IO command
1262 FOR_ALL_CHANNELS {
1263 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
1264 }
1265
1266 // IO control
1267 FOR_ALL_POPULATED_CHANNELS {
1268 program_timings(ctrl, channel);
1269 }
1270
1271 // Rcomp
Patrick Rudolpha649a542016-01-17 18:32:06 +01001272 printram("RCOMP...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001273 reg = 0;
1274 while (reg == 0) {
1275 reg = MCHBAR32(0x5084) & 0x10000;
1276 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001277 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001278
1279 // Set comp2
1280 comp2 = get_COMP2(ctrl->tCK);
1281 MCHBAR32(0x3714) = comp2;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001282 printram("COMP2 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001283
1284 // Set comp1
1285 FOR_ALL_POPULATED_CHANNELS {
1286 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
1287 reg = (reg & ~0xe00) | (1 << 9); //odt
1288 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
1289 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
1290 MCHBAR32(0x1810 + channel * 0x100) = reg;
1291 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001292 printram("COMP1 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001293
Patrick Rudolpha649a542016-01-17 18:32:06 +01001294 printram("FORCE RCOMP and wait 20us...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001295 MCHBAR32(0x5f08) |= 0x100;
1296 udelay(20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001297 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001298}
1299
1300static void wait_428c(int channel)
1301{
1302 while (1) {
1303 if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
1304 return;
1305 }
1306}
1307
1308static void write_reset(ramctr_timing * ctrl)
1309{
1310 int channel, slotrank;
1311
1312 /* choose a populated channel. */
1313 channel = (ctrl->rankmap[0]) ? 0 : 1;
1314
1315 wait_428c(channel);
1316
1317 /* choose a populated rank. */
1318 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
1319
Patrick Rudolph371d2912015-10-09 13:33:25 +02001320 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001321 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1322 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01);
1323
1324 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1325 (slotrank << 24) | 0x60000);
1326
1327 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1328
1329 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001);
1330 wait_428c(channel);
1331}
1332
1333static void dram_jedecreset(ramctr_timing * ctrl)
1334{
1335 u32 reg, addr;
1336 int channel;
1337
Elyes HAOUAS7db506c2016-10-02 11:56:39 +02001338 while (!(MCHBAR32(0x5084) & 0x10000));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001339 do {
1340 reg = MCHBAR32(0x428c);
1341 } while ((reg & 0x14) == 0);
1342
1343 // Set state of memory controller
1344 reg = 0x112;
1345 MCHBAR32(0x5030) = reg;
1346 MCHBAR32(0x4ea0) = 0;
1347 reg |= 2; //ddr reset
1348 MCHBAR32(0x5030) = reg;
1349
1350 // Assert dimm reset signal
1351 reg = MCHBAR32(0x5030);
1352 reg &= ~0x2;
1353 MCHBAR32(0x5030) = reg;
1354
1355 // Wait 200us
1356 udelay(200);
1357
1358 // Deassert dimm reset signal
1359 MCHBAR32(0x5030) |= 2;
1360
1361 // Wait 500us
1362 udelay(500);
1363
1364 // Enable DCLK
1365 MCHBAR32(0x5030) |= 4;
1366
1367 // XXX Wait 20ns
1368 udelay(1);
1369
1370 FOR_ALL_CHANNELS {
1371 // Set valid rank CKE
1372 reg = 0;
1373 reg = (reg & ~0xf) | ctrl->rankmap[channel];
1374 addr = 0x400 * channel + 0x42a0;
1375 MCHBAR32(addr) = reg;
1376
1377 // Wait 10ns for ranks to settle
1378 //udelay(0.01);
1379
1380 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
1381 MCHBAR32(addr) = reg;
1382
1383 // Write reset using a NOP
1384 write_reset(ctrl);
1385 }
1386}
1387
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001388static odtmap get_ODT(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001389{
1390 /* Get ODT based on rankmap: */
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001391 int dimms_per_ch = (ctrl->rankmap[channel] & 1)
1392 + ((ctrl->rankmap[channel] >> 2) & 1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001393
1394 if (dimms_per_ch == 1) {
1395 return (const odtmap){60, 60};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001396 } else {
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001397 return (const odtmap){120, 30};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001398 }
1399}
1400
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001401static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001402 int reg, u32 val)
1403{
1404 wait_428c(channel);
1405
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001406 if (ctrl->rank_mirror[channel][slotrank]) {
1407 /* DDR3 Rank1 Address mirror
1408 * swap the following pins:
1409 * A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 */
1410 reg = ((reg >> 1) & 1) | ((reg << 1) & 2);
1411 val = (val & ~0x1f8) | ((val >> 1) & 0xa8)
1412 | ((val & 0xa8) << 1);
1413 }
1414
Patrick Rudolph371d2912015-10-09 13:33:25 +02001415 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001416 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000);
1417 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
1418 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1419 (slotrank << 24) | (reg << 20) | val | 0x60000);
1420 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1421
Patrick Rudolph371d2912015-10-09 13:33:25 +02001422 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001423 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000);
1424 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001);
1425 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
1426 (slotrank << 24) | (reg << 20) | val | 0x60000);
1427 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1428
Patrick Rudolph371d2912015-10-09 13:33:25 +02001429 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001430 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000);
1431 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1432 0x1001 | (ctrl->tMOD << 16));
1433 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1434 (slotrank << 24) | (reg << 20) | val | 0x60000);
1435 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1436 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
1437}
1438
1439static u32 make_mr0(ramctr_timing * ctrl, u8 rank)
1440{
1441 u16 mr0reg, mch_cas, mch_wr;
1442 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 +02001443
1444 /* DLL Reset - self clearing - set after CLK frequency has been changed */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001445 mr0reg = 0x100;
1446
1447 // Convert CAS to MCH register friendly
1448 if (ctrl->CAS < 12) {
1449 mch_cas = (u16) ((ctrl->CAS - 4) << 1);
1450 } else {
1451 mch_cas = (u16) (ctrl->CAS - 12);
1452 mch_cas = ((mch_cas << 1) | 0x1);
1453 }
1454
1455 // Convert tWR to MCH register friendly
1456 mch_wr = mch_wr_t[ctrl->tWR - 5];
1457
1458 mr0reg = (mr0reg & ~0x4) | (mch_cas & 0x1);
1459 mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3);
1460 mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001461
1462 // Precharge PD - Fast (desktop) 0x1 or slow (mobile) 0x0 - mostly power-saving feature
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001463 mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12);
1464 return mr0reg;
1465}
1466
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001467static void dram_mr0(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001468{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001469 write_mrreg(ctrl, channel, rank, 0,
1470 make_mr0(ctrl, rank));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001471}
1472
1473static u32 encode_odt(u32 odt)
1474{
1475 switch (odt) {
1476 case 30:
1477 return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4
1478 case 60:
1479 return (1 << 2); // RZQ/4
1480 case 120:
1481 return (1 << 6); // RZQ/2
1482 default:
1483 case 0:
1484 return 0;
1485 }
1486}
1487
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001488static u32 make_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001489{
1490 odtmap odt;
1491 u32 mr1reg;
1492
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001493 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001494 mr1reg = 0x2;
1495
1496 mr1reg |= encode_odt(odt.rttnom);
1497
1498 return mr1reg;
1499}
1500
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001501static void dram_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001502{
1503 u16 mr1reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001504
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001505 mr1reg = make_mr1(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001506
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001507 write_mrreg(ctrl, channel, rank, 1, mr1reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001508}
1509
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001510static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001511{
1512 u16 pasr, cwl, mr2reg;
1513 odtmap odt;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001514 int srt;
1515
1516 pasr = 0;
1517 cwl = ctrl->CWL - 5;
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001518 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001519
1520 srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh;
1521
1522 mr2reg = 0;
1523 mr2reg = (mr2reg & ~0x7) | pasr;
1524 mr2reg = (mr2reg & ~0x38) | (cwl << 3);
1525 mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6);
1526 mr2reg = (mr2reg & ~0x80) | (srt << 7);
1527 mr2reg |= (odt.rttwr / 60) << 9;
1528
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001529 write_mrreg(ctrl, channel, rank, 2, mr2reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001530}
1531
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001532static void dram_mr3(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001533{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001534 write_mrreg(ctrl, channel, rank, 3, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001535}
1536
1537static void dram_mrscommands(ramctr_timing * ctrl)
1538{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001539 u8 slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001540 u32 reg, addr;
1541 int channel;
1542
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001543 FOR_ALL_POPULATED_CHANNELS {
1544 FOR_ALL_POPULATED_RANKS {
1545 // MR2
1546 dram_mr2(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001547
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001548 // MR3
1549 dram_mr3(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001550
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001551 // MR1
1552 dram_mr1(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001553
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001554 // MR0
1555 dram_mr0(ctrl, slotrank, channel);
1556 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001557 }
1558
Patrick Rudolph371d2912015-10-09 13:33:25 +02001559 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001560 write32(DEFAULT_MCHBAR + 0x4e20, 0x7);
1561 write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001);
1562 write32(DEFAULT_MCHBAR + 0x4e00, 0x60002);
1563 write32(DEFAULT_MCHBAR + 0x4e10, 0);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001564
1565 /* DRAM command ZQCL */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001566 write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003);
1567 write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001);
1568 write32(DEFAULT_MCHBAR + 0x4e04, 0x60400);
1569 write32(DEFAULT_MCHBAR + 0x4e14, 0x288);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001570
1571 /* execute command queue on all channels ? */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001572 write32(DEFAULT_MCHBAR + 0x4e84, 0x40004);
1573
1574 // Drain
1575 FOR_ALL_CHANNELS {
1576 // Wait for ref drained
1577 wait_428c(channel);
1578 }
1579
1580 // Refresh enable
1581 MCHBAR32(0x5030) |= 8;
1582
1583 FOR_ALL_POPULATED_CHANNELS {
1584 addr = 0x400 * channel + 0x4020;
1585 reg = MCHBAR32(addr);
1586 reg &= ~0x200000;
1587 MCHBAR32(addr) = reg;
1588
1589 wait_428c(channel);
1590
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001591 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001592
1593 // Drain
1594 wait_428c(channel);
1595
Patrick Rudolph371d2912015-10-09 13:33:25 +02001596 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001597 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1598 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
1599 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001600 (slotrank << 24) | 0x60000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001601 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
1602 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1);
1603
1604 // Drain
1605 wait_428c(channel);
1606 }
1607}
1608
1609const u32 lane_registers[] = {
1610 0x0000, 0x0200, 0x0400, 0x0600,
1611 0x1000, 0x1200, 0x1400, 0x1600,
1612 0x0800
1613};
1614
1615static void program_timings(ramctr_timing * ctrl, int channel)
1616{
1617 u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028;
1618 int lane;
1619 int slotrank, slot;
1620 int full_shift = 0;
1621 u16 slot320c[NUM_SLOTS];
1622
1623 FOR_ALL_POPULATED_RANKS {
1624 if (full_shift < -ctrl->timings[channel][slotrank].val_320c)
1625 full_shift = -ctrl->timings[channel][slotrank].val_320c;
1626 }
1627
1628 for (slot = 0; slot < NUM_SLOTS; slot++)
1629 switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) {
1630 case 0:
1631 default:
1632 slot320c[slot] = 0x7f;
1633 break;
1634 case 1:
1635 slot320c[slot] =
1636 ctrl->timings[channel][2 * slot + 0].val_320c +
1637 full_shift;
1638 break;
1639 case 2:
1640 slot320c[slot] =
1641 ctrl->timings[channel][2 * slot + 1].val_320c +
1642 full_shift;
1643 break;
1644 case 3:
1645 slot320c[slot] =
1646 (ctrl->timings[channel][2 * slot].val_320c +
1647 ctrl->timings[channel][2 * slot +
1648 1].val_320c) / 2 +
1649 full_shift;
1650 break;
1651 }
1652
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001653 /* enable CMD XOVER */
1654 reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001655 reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
1656 reg32 |= (slot320c[1] & 0x7f) << 18;
1657 reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
1658
1659 MCHBAR32(0x320c + 0x100 * channel) = reg32;
1660
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001661 /* enable CLK XOVER */
1662 reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001663 reg_c18 = 0;
1664
1665 FOR_ALL_POPULATED_RANKS {
1666 int shift =
1667 ctrl->timings[channel][slotrank].val_320c + full_shift;
1668 int offset_val_c14;
1669 if (shift < 0)
1670 shift = 0;
1671 offset_val_c14 = ctrl->reg_c14_offset + shift;
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001672 /* set CLK phase shift */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001673 reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
1674 reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
1675 }
1676
1677 MCHBAR32(0xc14 + channel * 0x100) = reg_c14;
1678 MCHBAR32(0xc18 + channel * 0x100) = reg_c18;
1679
1680 reg_4028 = MCHBAR32(0x4028 + 0x400 * channel);
1681 reg_4028 &= 0xffff0000;
1682
1683 reg_4024 = 0;
1684
1685 FOR_ALL_POPULATED_RANKS {
1686 int post_timA_min_high = 7, post_timA_max_high = 0;
1687 int pre_timA_min_high = 7, pre_timA_max_high = 0;
1688 int shift_402x = 0;
1689 int shift =
1690 ctrl->timings[channel][slotrank].val_320c + full_shift;
1691
1692 if (shift < 0)
1693 shift = 0;
1694
1695 FOR_ALL_LANES {
1696 if (post_timA_min_high >
1697 ((ctrl->timings[channel][slotrank].lanes[lane].
1698 timA + shift) >> 6))
1699 post_timA_min_high =
1700 ((ctrl->timings[channel][slotrank].
1701 lanes[lane].timA + shift) >> 6);
1702 if (pre_timA_min_high >
1703 (ctrl->timings[channel][slotrank].lanes[lane].
1704 timA >> 6))
1705 pre_timA_min_high =
1706 (ctrl->timings[channel][slotrank].
1707 lanes[lane].timA >> 6);
1708 if (post_timA_max_high <
1709 ((ctrl->timings[channel][slotrank].lanes[lane].
1710 timA + shift) >> 6))
1711 post_timA_max_high =
1712 ((ctrl->timings[channel][slotrank].
1713 lanes[lane].timA + shift) >> 6);
1714 if (pre_timA_max_high <
1715 (ctrl->timings[channel][slotrank].lanes[lane].
1716 timA >> 6))
1717 pre_timA_max_high =
1718 (ctrl->timings[channel][slotrank].
1719 lanes[lane].timA >> 6);
1720 }
1721
1722 if (pre_timA_max_high - pre_timA_min_high <
1723 post_timA_max_high - post_timA_min_high)
1724 shift_402x = +1;
1725 else if (pre_timA_max_high - pre_timA_min_high >
1726 post_timA_max_high - post_timA_min_high)
1727 shift_402x = -1;
1728
1729 reg_4028 |=
1730 (ctrl->timings[channel][slotrank].val_4028 + shift_402x -
1731 post_timA_min_high) << (4 * slotrank);
1732 reg_4024 |=
1733 (ctrl->timings[channel][slotrank].val_4024 +
1734 shift_402x) << (8 * slotrank);
1735
1736 FOR_ALL_LANES {
1737 MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel +
1738 4 * slotrank)
1739 =
1740 (((ctrl->timings[channel][slotrank].lanes[lane].
1741 timA + shift) & 0x3f)
1742 |
1743 ((ctrl->timings[channel][slotrank].lanes[lane].
1744 rising + shift) << 8)
1745 |
1746 (((ctrl->timings[channel][slotrank].lanes[lane].
1747 timA + shift -
1748 (post_timA_min_high << 6)) & 0x1c0) << 10)
Patrick Rudolph0188b132016-02-10 19:16:34 +01001749 | ((ctrl->timings[channel][slotrank].lanes[lane].
1750 falling + shift) << 20));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001751
1752 MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel +
1753 4 * slotrank)
1754 =
1755 (((ctrl->timings[channel][slotrank].lanes[lane].
1756 timC + shift) & 0x3f)
1757 |
1758 (((ctrl->timings[channel][slotrank].lanes[lane].
1759 timB + shift) & 0x3f) << 8)
1760 |
1761 (((ctrl->timings[channel][slotrank].lanes[lane].
1762 timB + shift) & 0x1c0) << 9)
1763 |
1764 (((ctrl->timings[channel][slotrank].lanes[lane].
1765 timC + shift) & 0x40) << 13));
1766 }
1767 }
1768 MCHBAR32(0x4024 + 0x400 * channel) = reg_4024;
1769 MCHBAR32(0x4028 + 0x400 * channel) = reg_4028;
1770}
1771
1772static void test_timA(ramctr_timing * ctrl, int channel, int slotrank)
1773{
1774 wait_428c(channel);
1775
Patrick Rudolph371d2912015-10-09 13:33:25 +02001776 /* DRAM command MRS
1777 * write MR3 MPR enable
1778 * in this mode only RD and RDA are allowed
1779 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001780 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
1781 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1782 (0xc01 | (ctrl->tMOD << 16)));
1783 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1784 (slotrank << 24) | 0x360004);
1785 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1786
Patrick Rudolph371d2912015-10-09 13:33:25 +02001787 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001788 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
1789 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01);
1790 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24));
1791 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1792
Patrick Rudolph371d2912015-10-09 13:33:25 +02001793 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001794 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
1795 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1796 0x100f | ((ctrl->CAS + 36) << 16));
1797 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1798 (slotrank << 24) | 0x60000);
1799 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1800
Patrick Rudolph371d2912015-10-09 13:33:25 +02001801 /* DRAM command MRS
1802 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001803 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
1804 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
1805 (0xc01 | (ctrl->tMOD << 16)));
1806 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
1807 (slotrank << 24) | 0x360000);
1808 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
1809
1810 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
1811
1812 wait_428c(channel);
1813}
1814
1815static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank,
1816 int lane)
1817{
1818 u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA;
1819 return ((read32
1820 (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 +
1821 ((timA / 32) & 1) * 4)
1822 >> (timA % 32)) & 1);
1823}
1824
1825struct run {
1826 int middle;
1827 int end;
1828 int start;
1829 int all;
1830 int length;
1831};
1832
1833static struct run get_longest_zero_run(int *seq, int sz)
1834{
1835 int i, ls;
1836 int bl = 0, bs = 0;
1837 struct run ret;
1838
1839 ls = 0;
1840 for (i = 0; i < 2 * sz; i++)
1841 if (seq[i % sz]) {
1842 if (i - ls > bl) {
1843 bl = i - ls;
1844 bs = ls;
1845 }
1846 ls = i + 1;
1847 }
1848 if (bl == 0) {
1849 ret.middle = sz / 2;
1850 ret.start = 0;
1851 ret.end = sz;
1852 ret.all = 1;
1853 return ret;
1854 }
1855
1856 ret.start = bs % sz;
1857 ret.end = (bs + bl - 1) % sz;
1858 ret.middle = (bs + (bl - 1) / 2) % sz;
1859 ret.length = bl;
1860 ret.all = 0;
1861
1862 return ret;
1863}
1864
1865static void discover_timA_coarse(ramctr_timing * ctrl, int channel,
1866 int slotrank, int *upperA)
1867{
1868 int timA;
1869 int statistics[NUM_LANES][128];
1870 int lane;
1871
1872 for (timA = 0; timA < 128; timA++) {
1873 FOR_ALL_LANES {
1874 ctrl->timings[channel][slotrank].lanes[lane].timA = timA;
1875 }
1876 program_timings(ctrl, channel);
1877
1878 test_timA(ctrl, channel, slotrank);
1879
1880 FOR_ALL_LANES {
1881 statistics[lane][timA] =
1882 !does_lane_work(ctrl, channel, slotrank, lane);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001883 printram("Astat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001884 channel, slotrank, lane, timA,
1885 statistics[lane][timA]);
1886 }
1887 }
1888 FOR_ALL_LANES {
1889 struct run rn = get_longest_zero_run(statistics[lane], 128);
1890 ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle;
1891 upperA[lane] = rn.end;
1892 if (upperA[lane] < rn.middle)
1893 upperA[lane] += 128;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001894 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001895 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001896 printram("Aend: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001897 lane, upperA[lane]);
1898 }
1899}
1900
1901static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
1902 int *upperA)
1903{
1904 int timA_delta;
1905 int statistics[NUM_LANES][51];
1906 int lane, i;
1907
1908 memset(statistics, 0, sizeof(statistics));
1909
1910 for (timA_delta = -25; timA_delta <= 25; timA_delta++) {
1911 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
1912 timA = upperA[lane] + timA_delta + 0x40;
1913 program_timings(ctrl, channel);
1914
1915 for (i = 0; i < 100; i++) {
1916 test_timA(ctrl, channel, slotrank);
1917 FOR_ALL_LANES {
1918 statistics[lane][timA_delta + 25] +=
1919 does_lane_work(ctrl, channel, slotrank,
1920 lane);
1921 }
1922 }
1923 }
1924 FOR_ALL_LANES {
1925 int last_zero, first_all;
1926
1927 for (last_zero = -25; last_zero <= 25; last_zero++)
1928 if (statistics[lane][last_zero + 25])
1929 break;
1930 last_zero--;
1931 for (first_all = -25; first_all <= 25; first_all++)
1932 if (statistics[lane][first_all + 25] == 100)
1933 break;
1934
1935 printram("lane %d: %d, %d\n", lane, last_zero,
1936 first_all);
1937
1938 ctrl->timings[channel][slotrank].lanes[lane].timA =
1939 (last_zero + first_all) / 2 + upperA[lane];
Patrick Rudolpha649a542016-01-17 18:32:06 +01001940 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001941 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
1942 }
1943}
1944
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001945static int discover_402x(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001946 int *upperA)
1947{
1948 int works[NUM_LANES];
1949 int lane;
1950 while (1) {
1951 int all_works = 1, some_works = 0;
1952 program_timings(ctrl, channel);
1953 test_timA(ctrl, channel, slotrank);
1954 FOR_ALL_LANES {
1955 works[lane] =
1956 !does_lane_work(ctrl, channel, slotrank, lane);
1957 if (works[lane])
1958 some_works = 1;
1959 else
1960 all_works = 0;
1961 }
1962 if (all_works)
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001963 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001964 if (!some_works) {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001965 if (ctrl->timings[channel][slotrank].val_4024 < 2) {
1966 printk(BIOS_EMERG, "402x discovery failed (1): %d, %d\n",
1967 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001968 return MAKE_ERR;
1969 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001970 ctrl->timings[channel][slotrank].val_4024 -= 2;
1971 printram("4024 -= 2;\n");
1972 continue;
1973 }
1974 ctrl->timings[channel][slotrank].val_4028 += 2;
1975 printram("4028 += 2;\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001976 if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) {
1977 printk(BIOS_EMERG, "402x discovery failed (2): %d, %d\n",
1978 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001979 return MAKE_ERR;
1980 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001981 FOR_ALL_LANES if (works[lane]) {
1982 ctrl->timings[channel][slotrank].lanes[lane].timA +=
1983 128;
1984 upperA[lane] += 128;
1985 printram("increment %d, %d, %d\n", channel,
1986 slotrank, lane);
1987 }
1988 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001989 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001990}
1991
1992struct timA_minmax {
1993 int timA_min_high, timA_max_high;
1994};
1995
1996static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1997 struct timA_minmax *mnmx)
1998{
1999 int lane;
2000 mnmx->timA_min_high = 7;
2001 mnmx->timA_max_high = 0;
2002
2003 FOR_ALL_LANES {
2004 if (mnmx->timA_min_high >
2005 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
2006 mnmx->timA_min_high =
2007 (ctrl->timings[channel][slotrank].lanes[lane].
2008 timA >> 6);
2009 if (mnmx->timA_max_high <
2010 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
2011 mnmx->timA_max_high =
2012 (ctrl->timings[channel][slotrank].lanes[lane].
2013 timA >> 6);
2014 }
2015}
2016
2017static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
2018 struct timA_minmax *mnmx)
2019{
2020 struct timA_minmax post;
2021 int shift_402x = 0;
2022
2023 /* Get changed maxima. */
2024 pre_timA_change(ctrl, channel, slotrank, &post);
2025
2026 if (mnmx->timA_max_high - mnmx->timA_min_high <
2027 post.timA_max_high - post.timA_min_high)
2028 shift_402x = +1;
2029 else if (mnmx->timA_max_high - mnmx->timA_min_high >
2030 post.timA_max_high - post.timA_min_high)
2031 shift_402x = -1;
2032 else
2033 shift_402x = 0;
2034
2035 ctrl->timings[channel][slotrank].val_4028 += shift_402x;
2036 ctrl->timings[channel][slotrank].val_4024 += shift_402x;
2037 printram("4024 += %d;\n", shift_402x);
2038 printram("4028 += %d;\n", shift_402x);
2039}
2040
Patrick Rudolph371d2912015-10-09 13:33:25 +02002041/* Compensate the skew between DQS and DQs.
2042 * To ease PCB design a small skew between Data Strobe signals and
2043 * Data Signals is allowed.
2044 * The controller has to measure and compensate this skew for every byte-lane.
2045 * By delaying either all DQs signals or DQS signal, a full phase
2046 * shift can be introduced.
2047 * It is assumed that one byte-lane's DQs signals have the same routing delay.
2048 *
2049 * To measure the actual skew, the DRAM is placed in "read leveling" mode.
2050 * In read leveling mode the DRAM-chip outputs an alternating periodic pattern.
2051 * The memory controller iterates over all possible values to do a full phase shift
2052 * and issues read commands.
2053 * With DQS and DQs in phase the data read is expected to alternate on every byte:
2054 * 0xFF 0x00 0xFF ...
2055 * Once the controller has detected this pattern a bit in the result register is
2056 * set for the current phase shift.
2057 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002058static int read_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002059{
2060 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002061 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002062
2063 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002064 int all_high, some_high;
2065 int upperA[NUM_LANES];
2066 struct timA_minmax mnmx;
2067
2068 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002069
2070 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002071 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2072 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2073 0xc01 | (ctrl->tRP << 16));
2074 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2075 (slotrank << 24) | 0x60400);
2076 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2077 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2078
2079 write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001);
2080
2081 ctrl->timings[channel][slotrank].val_4028 = 4;
2082 ctrl->timings[channel][slotrank].val_4024 = 55;
2083 program_timings(ctrl, channel);
2084
2085 discover_timA_coarse(ctrl, channel, slotrank, upperA);
2086
2087 all_high = 1;
2088 some_high = 0;
2089 FOR_ALL_LANES {
2090 if (ctrl->timings[channel][slotrank].lanes[lane].
2091 timA >= 0x40)
2092 some_high = 1;
2093 else
2094 all_high = 0;
2095 }
2096
2097 if (all_high) {
2098 ctrl->timings[channel][slotrank].val_4028--;
2099 printram("4028--;\n");
2100 FOR_ALL_LANES {
2101 ctrl->timings[channel][slotrank].lanes[lane].
2102 timA -= 0x40;
2103 upperA[lane] -= 0x40;
2104
2105 }
2106 } else if (some_high) {
2107 ctrl->timings[channel][slotrank].val_4024++;
2108 ctrl->timings[channel][slotrank].val_4028++;
2109 printram("4024++;\n");
2110 printram("4028++;\n");
2111 }
2112
2113 program_timings(ctrl, channel);
2114
2115 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2116
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002117 err = discover_402x(ctrl, channel, slotrank, upperA);
2118 if (err)
2119 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002120
2121 post_timA_change(ctrl, channel, slotrank, &mnmx);
2122 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2123
2124 discover_timA_fine(ctrl, channel, slotrank, upperA);
2125
2126 post_timA_change(ctrl, channel, slotrank, &mnmx);
2127 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2128
2129 FOR_ALL_LANES {
2130 ctrl->timings[channel][slotrank].lanes[lane].timA -= mnmx.timA_min_high * 0x40;
2131 }
2132 ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high;
2133 printram("4028 -= %d;\n", mnmx.timA_min_high);
2134
2135 post_timA_change(ctrl, channel, slotrank, &mnmx);
2136
2137 printram("4/8: %d, %d, %x, %x\n", channel, slotrank,
2138 ctrl->timings[channel][slotrank].val_4024,
2139 ctrl->timings[channel][slotrank].val_4028);
2140
Patrick Rudolpha649a542016-01-17 18:32:06 +01002141 printram("final results:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002142 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01002143 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002144 lane,
2145 ctrl->timings[channel][slotrank].lanes[lane].timA);
2146
2147 write32(DEFAULT_MCHBAR + 0x3400, 0);
2148
Patrick Rudolph9b515682015-10-09 13:43:51 +02002149 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002150 }
2151
2152 FOR_ALL_POPULATED_CHANNELS {
2153 program_timings(ctrl, channel);
2154 }
2155 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2156 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
2157 + 4 * lane, 0);
2158 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002159 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002160}
2161
2162static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
2163{
2164 int lane;
2165
2166 FOR_ALL_LANES {
2167 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0);
2168 read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane);
2169 }
2170
2171 wait_428c(channel);
2172
Patrick Rudolph371d2912015-10-09 13:33:25 +02002173 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002174 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2175 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2176 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
2177 | 4 | (ctrl->tRCD << 16));
2178
2179 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2180 (slotrank << 24) | (6 << 16));
2181
2182 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
2183
Patrick Rudolph371d2912015-10-09 13:33:25 +02002184 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002185 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2186 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001);
2187 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2188 (slotrank << 24) | 8);
2189 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2190
Patrick Rudolph371d2912015-10-09 13:33:25 +02002191 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002192 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2193 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4);
2194 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2195 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2196
Patrick Rudolph371d2912015-10-09 13:33:25 +02002197 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002198 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2199 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2200 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2201 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2202 (slotrank << 24) | 8);
2203 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2204
2205 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2206
2207 wait_428c(channel);
2208
Patrick Rudolph371d2912015-10-09 13:33:25 +02002209 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002210 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2211 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2212 0xc01 | (ctrl->tRP << 16));
2213 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2214 (slotrank << 24) | 0x60400);
2215 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2216
Patrick Rudolph371d2912015-10-09 13:33:25 +02002217 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002218 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2219 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2220 (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10)
2221 | 8 | (ctrl->CAS << 16));
2222
2223 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2224 (slotrank << 24) | 0x60000);
2225
2226 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244);
2227
Patrick Rudolph371d2912015-10-09 13:33:25 +02002228 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002229 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2230 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2231 0x40011f4 | (max(ctrl->tRTP, 8) << 16));
2232 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2233 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2234
Patrick Rudolph371d2912015-10-09 13:33:25 +02002235 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002236 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2237 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2238 0xc01 | (ctrl->tRP << 16));
2239 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2240 (slotrank << 24) | 0x60400);
2241 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2242 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2243 wait_428c(channel);
2244}
2245
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002246static int discover_timC(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002247{
2248 int timC;
2249 int statistics[NUM_LANES][MAX_TIMC + 1];
2250 int lane;
2251
2252 wait_428c(channel);
2253
Patrick Rudolph371d2912015-10-09 13:33:25 +02002254 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002255 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2256 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2257 0xc01 | (ctrl->tRP << 16));
2258 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2259 (slotrank << 24) | 0x60400);
2260 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2261 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2262
2263 for (timC = 0; timC <= MAX_TIMC; timC++) {
2264 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
2265 timC = timC;
2266 program_timings(ctrl, channel);
2267
2268 test_timC(ctrl, channel, slotrank);
2269
2270 FOR_ALL_LANES {
2271 statistics[lane][timC] =
2272 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2273 0x400 * channel);
2274 printram("Cstat: %d, %d, %d, %x, %x\n",
2275 channel, slotrank, lane, timC,
2276 statistics[lane][timC]);
2277 }
2278 }
2279 FOR_ALL_LANES {
2280 struct run rn =
2281 get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
2282 ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002283 if (rn.all) {
2284 printk(BIOS_EMERG, "timC discovery failed: %d, %d, %d\n",
2285 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002286 return MAKE_ERR;
2287 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002288 printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002289 lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
2290 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002291 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002292}
2293
2294static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
2295{
2296 int channel, ret = 0;
2297 FOR_ALL_POPULATED_CHANNELS if (channel < target_channel)
2298 ret++;
2299 return ret;
2300}
2301
2302static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b)
2303{
2304 unsigned j;
2305 unsigned channel_offset =
2306 get_precedening_channels(ctrl, channel) * 0x40;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002307 for (j = 0; j < 16; j++)
2308 write32((void *)(0x04000000 + channel_offset + 4 * j), j & 2 ? b : a);
2309 sfence();
2310}
2311
2312static int num_of_channels(const ramctr_timing * ctrl)
2313{
2314 int ret = 0;
2315 int channel;
2316 FOR_ALL_POPULATED_CHANNELS ret++;
2317 return ret;
2318}
2319
2320static void fill_pattern1(ramctr_timing * ctrl, int channel)
2321{
2322 unsigned j;
2323 unsigned channel_offset =
2324 get_precedening_channels(ctrl, channel) * 0x40;
2325 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2326 for (j = 0; j < 16; j++)
2327 write32((void *)(0x04000000 + channel_offset + j * 4), 0xffffffff);
2328 for (j = 0; j < 16; j++)
2329 write32((void *)(0x04000000 + channel_offset + channel_step + j * 4), 0);
2330 sfence();
2331}
2332
2333static void precharge(ramctr_timing * ctrl)
2334{
2335 int channel, slotrank, lane;
2336
2337 FOR_ALL_POPULATED_CHANNELS {
2338 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2339 ctrl->timings[channel][slotrank].lanes[lane].falling =
2340 16;
2341 ctrl->timings[channel][slotrank].lanes[lane].rising =
2342 16;
Patrick Rudolpha649a542016-01-17 18:32:06 +01002343 }
2344
2345 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002346
2347 FOR_ALL_POPULATED_RANKS {
2348 wait_428c(channel);
2349
Patrick Rudolph371d2912015-10-09 13:33:25 +02002350 /* DRAM command MRS
2351 * write MR3 MPR enable
2352 * in this mode only RD and RDA are allowed
2353 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002354 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2355 0x1f000);
2356 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2357 0xc01 | (ctrl->tMOD << 16));
2358 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2359 (slotrank << 24) | 0x360004);
2360 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2361
Patrick Rudolph371d2912015-10-09 13:33:25 +02002362 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002363 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2364 0x1f105);
2365 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2366 0x4041003);
2367 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2368 (slotrank << 24) | 0);
2369 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2370
Patrick Rudolph371d2912015-10-09 13:33:25 +02002371 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002372 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2373 0x1f105);
2374 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2375 0x1001 | ((ctrl->CAS + 8) << 16));
2376 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2377 (slotrank << 24) | 0x60000);
2378 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2379
Patrick Rudolph371d2912015-10-09 13:33:25 +02002380 /* DRAM command MRS
2381 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002382 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2383 0x1f000);
2384 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2385 0xc01 | (ctrl->tMOD << 16));
2386 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2387 (slotrank << 24) | 0x360000);
2388 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2389 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2390 0xc0001);
2391
2392 wait_428c(channel);
2393 }
2394
2395 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2396 ctrl->timings[channel][slotrank].lanes[lane].falling =
2397 48;
2398 ctrl->timings[channel][slotrank].lanes[lane].rising =
2399 48;
2400 }
2401
2402 program_timings(ctrl, channel);
2403
2404 FOR_ALL_POPULATED_RANKS {
2405 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002406 /* DRAM command MRS
2407 * write MR3 MPR enable
2408 * in this mode only RD and RDA are allowed
2409 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002410 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2411 0x1f000);
2412 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2413 0xc01 | (ctrl->tMOD << 16));
2414 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2415 (slotrank << 24) | 0x360004);
2416 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2417
Patrick Rudolph371d2912015-10-09 13:33:25 +02002418 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002419 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2420 0x1f105);
2421 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2422 0x4041003);
2423 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2424 (slotrank << 24) | 0);
2425 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2426
Patrick Rudolph371d2912015-10-09 13:33:25 +02002427 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002428 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2429 0x1f105);
2430 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2431 0x1001 | ((ctrl->CAS + 8) << 16));
2432 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2433 (slotrank << 24) | 0x60000);
2434 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2435
Patrick Rudolph371d2912015-10-09 13:33:25 +02002436 /* DRAM command MRS
2437 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002438 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2439 0x1f000);
2440 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2441 0xc01 | (ctrl->tMOD << 16));
2442
2443 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2444 (slotrank << 24) | 0x360000);
2445 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2446
2447 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2448 0xc0001);
2449 wait_428c(channel);
2450 }
2451 }
2452}
2453
2454static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
2455{
Patrick Rudolph371d2912015-10-09 13:33:25 +02002456 /* enable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002457 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002458 0x80 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002459
2460 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002461 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002462 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207);
2463 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2464 0x8000c01 | ((ctrl->CWL + ctrl->tWLO) << 16));
2465 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2466 8 | (slotrank << 24));
2467 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2468
Patrick Rudolph371d2912015-10-09 13:33:25 +02002469 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002470 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107);
2471 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2472 0x4000c01 | ((ctrl->CAS + 38) << 16));
2473 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2474 (slotrank << 24) | 4);
2475 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2476
2477 write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001);
2478 wait_428c(channel);
2479
Patrick Rudolph371d2912015-10-09 13:33:25 +02002480 /* disable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002481 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002482 0x1080 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002483}
2484
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002485static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002486{
2487 int timB;
2488 int statistics[NUM_LANES][128];
2489 int lane;
2490
2491 write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2));
2492
2493 for (timB = 0; timB < 128; timB++) {
2494 FOR_ALL_LANES {
2495 ctrl->timings[channel][slotrank].lanes[lane].timB = timB;
2496 }
2497 program_timings(ctrl, channel);
2498
2499 test_timB(ctrl, channel, slotrank);
2500
2501 FOR_ALL_LANES {
2502 statistics[lane][timB] =
2503 !((read32
2504 (DEFAULT_MCHBAR + lane_registers[lane] +
2505 channel * 0x100 + 4 + ((timB / 32) & 1) * 4)
2506 >> (timB % 32)) & 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002507 printram("Bstat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002508 channel, slotrank, lane, timB,
2509 statistics[lane][timB]);
2510 }
2511 }
2512 FOR_ALL_LANES {
2513 struct run rn = get_longest_zero_run(statistics[lane], 128);
Patrick Rudolphd912f1d2016-02-15 20:07:42 +01002514 /* timC is a direct function of timB's 6 LSBs.
2515 * Some tests increments the value of timB by a small value,
2516 * which might cause the 6bit value to overflow, if it's close
2517 * to 0x3F. Increment the value by a small offset if it's likely
2518 * to overflow, to make sure it won't overflow while running
2519 * tests and bricks the system due to a non matching timC.
2520 *
2521 * TODO: find out why some tests (edge write discovery)
2522 * increment timB. */
2523 if ((rn.start & 0x3F) == 0x3E)
2524 rn.start += 2;
2525 else if ((rn.start & 0x3F) == 0x3F)
2526 rn.start += 1;
Vladimir Serbinenko3141eac2016-01-29 19:42:02 +01002527 ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002528 if (rn.all) {
2529 printk(BIOS_EMERG, "timB discovery failed: %d, %d, %d\n",
2530 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002531 return MAKE_ERR;
2532 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002533 printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002534 lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
2535 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002536 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002537}
2538
2539static int get_timB_high_adjust(u64 val)
2540{
2541 int i;
2542
2543 /* good */
2544 if (val == 0xffffffffffffffffLL)
2545 return 0;
2546
2547 if (val >= 0xf000000000000000LL) {
2548 /* needs negative adjustment */
2549 for (i = 0; i < 8; i++)
2550 if (val << (8 * (7 - i) + 4))
2551 return -i;
2552 } else {
2553 /* needs positive adjustment */
2554 for (i = 0; i < 8; i++)
2555 if (val >> (8 * (7 - i) + 4))
2556 return i;
2557 }
2558 return 8;
2559}
2560
2561static void adjust_high_timB(ramctr_timing * ctrl)
2562{
2563 int channel, slotrank, lane, old;
2564 write32(DEFAULT_MCHBAR + 0x3400, 0x200);
2565 FOR_ALL_POPULATED_CHANNELS {
2566 fill_pattern1(ctrl, channel);
2567 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 1);
2568 }
2569 FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
2570
2571 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001);
2572
2573 wait_428c(channel);
2574
Patrick Rudolph371d2912015-10-09 13:33:25 +02002575 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002576 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2577 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2578 0xc01 | (ctrl->tRCD << 16));
2579 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2580 (slotrank << 24) | 0x60000);
2581 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2582
Patrick Rudolph371d2912015-10-09 13:33:25 +02002583 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002584 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2585 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01);
2586 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2587 (slotrank << 24) | 0x8);
2588 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2589
Patrick Rudolph371d2912015-10-09 13:33:25 +02002590 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002591 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2592 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003);
2593 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2594 (slotrank << 24));
2595 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2);
2596
Patrick Rudolph371d2912015-10-09 13:33:25 +02002597 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002598 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2599 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2600 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2601 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2602 (slotrank << 24) | 0x8);
2603 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2604
2605 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2606
2607 wait_428c(channel);
2608
Patrick Rudolph371d2912015-10-09 13:33:25 +02002609 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002610 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2611 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2612 0xc01 | ((ctrl->tRP) << 16));
2613 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2614 (slotrank << 24) | 0x60400);
2615 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2616
Patrick Rudolph371d2912015-10-09 13:33:25 +02002617 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002618 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2619 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2620 0xc01 | ((ctrl->tRCD) << 16));
2621 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2622 (slotrank << 24) | 0x60000);
2623 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2624
Patrick Rudolph371d2912015-10-09 13:33:25 +02002625 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002626 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105);
2627 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2628 0x4000c01 |
2629 ((ctrl->tRP +
2630 ctrl->timings[channel][slotrank].val_4024 +
2631 ctrl->timings[channel][slotrank].val_4028) << 16));
2632 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2633 (slotrank << 24) | 0x60008);
2634 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2635
2636 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
2637 wait_428c(channel);
2638 FOR_ALL_LANES {
2639 u64 res =
2640 read32(DEFAULT_MCHBAR + lane_registers[lane] +
2641 0x100 * channel + 4);
2642 res |=
2643 ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] +
2644 0x100 * channel + 8)) << 32;
2645 old = ctrl->timings[channel][slotrank].lanes[lane].timB;
2646 ctrl->timings[channel][slotrank].lanes[lane].timB +=
2647 get_timB_high_adjust(res) * 64;
2648
Patrick Rudolpha649a542016-01-17 18:32:06 +01002649 printram("High adjust %d:%016llx\n", lane, res);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002650 printram("Bval+: %d, %d, %d, %x -> %x\n", channel,
2651 slotrank, lane, old,
2652 ctrl->timings[channel][slotrank].lanes[lane].
2653 timB);
2654 }
2655 }
2656 write32(DEFAULT_MCHBAR + 0x3400, 0);
2657}
2658
2659static void write_op(ramctr_timing * ctrl, int channel)
2660{
2661 int slotrank;
2662
2663 wait_428c(channel);
2664
2665 /* choose an existing rank. */
2666 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2667
Patrick Rudolph371d2912015-10-09 13:33:25 +02002668 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002669 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2670 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2671
2672 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2673 (slotrank << 24) | 0x60000);
2674
2675 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2676
2677 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2678 wait_428c(channel);
2679}
2680
Patrick Rudolph371d2912015-10-09 13:33:25 +02002681/* Compensate the skew between CMD/ADDR/CLK and DQ/DQS lanes.
2682 * DDR3 adopted the fly-by topology. The data and strobes signals reach
2683 * the chips at different times with respect to command, address and
2684 * clock signals.
2685 * By delaying either all DQ/DQs or all CMD/ADDR/CLK signals, a full phase
2686 * shift can be introduced.
2687 * It is assumed that the CLK/ADDR/CMD signals have the same routing delay.
2688 *
2689 * To find the required phase shift the DRAM is placed in "write leveling" mode.
2690 * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
2691 * sampled value on the data lanes (DQs).
2692 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002693static int write_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002694{
2695 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002696 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002697
2698 FOR_ALL_POPULATED_CHANNELS
2699 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
2700 read32(DEFAULT_MCHBAR + 0x4008 +
2701 0x400 * channel) | 0x8000000);
2702
2703 FOR_ALL_POPULATED_CHANNELS {
2704 write_op(ctrl, channel);
2705 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2706 read32(DEFAULT_MCHBAR + 0x4020 +
2707 0x400 * channel) | 0x200000);
2708 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002709
2710 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002711 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2712 FOR_ALL_POPULATED_CHANNELS {
2713 write_op(ctrl, channel);
2714 }
2715
Patrick Rudolph371d2912015-10-09 13:33:25 +02002716 /* enable write leveling on all ranks
2717 * disable all DQ outputs
2718 * only NOP is allowed in this mode */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002719 FOR_ALL_CHANNELS
2720 FOR_ALL_POPULATED_RANKS
2721 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002722 make_mr1(ctrl, slotrank, channel) | 0x1080);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002723
2724 write32(DEFAULT_MCHBAR + 0x3400, 0x108052);
2725
Patrick Rudolph9b515682015-10-09 13:43:51 +02002726 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002727
Patrick Rudolph371d2912015-10-09 13:33:25 +02002728 /* set any valid value for timB, it gets corrected later */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002729 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2730 err = discover_timB(ctrl, channel, slotrank);
2731 if (err)
2732 return err;
2733 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002734
Patrick Rudolph371d2912015-10-09 13:33:25 +02002735 /* disable write leveling on all ranks */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002736 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2737 write_mrreg(ctrl, channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002738 slotrank, 1, make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002739
2740 write32(DEFAULT_MCHBAR + 0x3400, 0);
2741
2742 FOR_ALL_POPULATED_CHANNELS
2743 wait_428c(channel);
2744
Patrick Rudolph371d2912015-10-09 13:33:25 +02002745 /* refresh enable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002746 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8);
2747
2748 FOR_ALL_POPULATED_CHANNELS {
2749 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2750 ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 +
2751 0x400 * channel));
2752 read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel);
2753 wait_428c(channel);
2754
Patrick Rudolph371d2912015-10-09 13:33:25 +02002755 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002756 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2757 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
2758 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000);
2759 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2760
2761 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2762 wait_428c(channel);
2763 }
2764
Patrick Rudolph9b515682015-10-09 13:43:51 +02002765 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002766
2767 printram("CPE\n");
2768 precharge(ctrl);
2769 printram("CPF\n");
2770
2771 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2772 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2773 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2774 0);
2775 }
2776
2777 FOR_ALL_POPULATED_CHANNELS {
2778 fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555);
2779 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
2780 }
2781
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002782 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2783 err = discover_timC(ctrl, channel, slotrank);
2784 if (err)
2785 return err;
2786 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002787
2788 FOR_ALL_POPULATED_CHANNELS
2789 program_timings(ctrl, channel);
2790
Patrick Rudolph371d2912015-10-09 13:33:25 +02002791 /* measure and adjust timB timings */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002792 adjust_high_timB(ctrl);
2793
2794 FOR_ALL_POPULATED_CHANNELS
2795 program_timings(ctrl, channel);
2796
2797 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2798 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2799 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2800 0);
2801 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002802 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002803}
2804
2805static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
2806{
2807 struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank];
2808 int timC_delta;
2809 int lanes_ok = 0;
2810 int ctr = 0;
2811 int lane;
2812
2813 for (timC_delta = -5; timC_delta <= 5; timC_delta++) {
2814 FOR_ALL_LANES {
2815 ctrl->timings[channel][slotrank].lanes[lane].timC =
2816 saved_rt.lanes[lane].timC + timC_delta;
2817 }
2818 program_timings(ctrl, channel);
2819 FOR_ALL_LANES {
2820 write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0);
2821 }
2822
2823 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2824
2825 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002826 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002827 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2828 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2829 ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10)
2830 | 8 | (ctrl->tRCD << 16));
2831
2832 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2833 (slotrank << 24) | ctr | 0x60000);
2834
2835 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002836 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002837 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
2838 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2839 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16));
2840 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2841 (slotrank << 24));
2842 write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd);
2843 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42);
2844
Patrick Rudolph371d2912015-10-09 13:33:25 +02002845 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002846 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2847 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2848 0x4001020 | (max(ctrl->tRTP, 8) << 16));
2849 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2850 (slotrank << 24));
2851 write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd);
2852 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42);
2853
Patrick Rudolph371d2912015-10-09 13:33:25 +02002854 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002855 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2856 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001);
2857 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2858 (slotrank << 24) | 0x60400);
2859 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2860
2861 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2862 wait_428c(channel);
2863 FOR_ALL_LANES {
2864 u32 r32 =
2865 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2866 0x400 * channel);
2867
2868 if (r32 == 0)
2869 lanes_ok |= 1 << lane;
2870 }
2871 ctr++;
2872 if (lanes_ok == ((1 << NUM_LANES) - 1))
2873 break;
2874 }
2875
2876 ctrl->timings[channel][slotrank] = saved_rt;
2877
2878 printram("3lanes: %x\n", lanes_ok);
2879 return lanes_ok != ((1 << NUM_LANES) - 1);
2880}
2881
2882#include "raminit_patterns.h"
2883
2884static void fill_pattern5(ramctr_timing * ctrl, int channel, int patno)
2885{
2886 unsigned i, j;
2887 unsigned channel_offset =
2888 get_precedening_channels(ctrl, channel) * 0x40;
2889 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2890
2891 if (patno) {
2892 u8 base8 = 0x80 >> ((patno - 1) % 8);
2893 u32 base = base8 | (base8 << 8) | (base8 << 16) | (base8 << 24);
2894 for (i = 0; i < 32; i++) {
2895 for (j = 0; j < 16; j++) {
2896 u32 val = use_base[patno - 1][i] & (1 << (j / 2)) ? base : 0;
2897 if (invert[patno - 1][i] & (1 << (j / 2)))
2898 val = ~val;
2899 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2900 j * 4), val);
2901 }
2902 }
2903
2904 } else {
2905 for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) {
2906 for (j = 0; j < 16; j++)
2907 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2908 j * 4), pattern[i][j]);
2909 }
2910 sfence();
2911 }
2912}
2913
2914static void reprogram_320c(ramctr_timing * ctrl)
2915{
2916 int channel, slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002917
2918 FOR_ALL_POPULATED_CHANNELS {
2919 wait_428c(channel);
2920
2921 /* choose an existing rank. */
2922 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2923
Patrick Rudolph371d2912015-10-09 13:33:25 +02002924 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002925 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2926 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2927
2928 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2929 (slotrank << 24) | 0x60000);
2930
2931 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2932
2933 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2934 wait_428c(channel);
2935 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2936 read32(DEFAULT_MCHBAR + 0x4020 +
2937 0x400 * channel) | 0x200000);
2938 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002939
2940 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002941 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2942 FOR_ALL_POPULATED_CHANNELS {
2943 wait_428c(channel);
2944
2945 /* choose an existing rank. */
2946 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2947
Patrick Rudolph371d2912015-10-09 13:33:25 +02002948 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002949 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2950 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2951
2952 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2953 (slotrank << 24) | 0x60000);
2954
2955 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2956
2957 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2958 wait_428c(channel);
2959 }
2960
2961 /* jedec reset */
2962 dram_jedecreset(ctrl);
2963 /* mrs commands. */
2964 dram_mrscommands(ctrl);
2965
Patrick Rudolph9b515682015-10-09 13:43:51 +02002966 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002967}
2968
2969#define MIN_C320C_LEN 13
2970
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002971static int try_cmd_stretch(ramctr_timing *ctrl, int cmd_stretch)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002972{
2973 struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
2974 int channel, slotrank;
2975 int c320c;
2976 int stat[NUM_SLOTRANKS][256];
2977
2978 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2979 saved_timings[channel][slotrank] = ctrl->timings[channel][slotrank];
2980 }
2981
2982 FOR_ALL_POPULATED_CHANNELS {
2983 ctrl->cmd_stretch[channel] = cmd_stretch;
2984 }
2985
2986 FOR_ALL_POPULATED_CHANNELS
2987 MCHBAR32(0x4004 + 0x400 * channel) =
2988 ctrl->tRRD
2989 | (ctrl->tRTP << 4)
2990 | (ctrl->tCKE << 8)
2991 | (ctrl->tWTR << 12)
2992 | (ctrl->tFAW << 16)
2993 | (ctrl->tWR << 24)
2994 | (ctrl->cmd_stretch[channel] << 30);
2995
2996
2997 FOR_ALL_CHANNELS {
2998 int delta = 0;
2999 if (ctrl->cmd_stretch[channel] == 2)
3000 delta = 2;
3001 else if (ctrl->cmd_stretch[channel] == 0)
3002 delta = 4;
3003
3004 FOR_ALL_POPULATED_RANKS {
3005 ctrl->timings[channel][slotrank].val_4024 -= delta;
3006 }
3007 }
3008
3009 FOR_ALL_POPULATED_CHANNELS {
3010 for (c320c = -127; c320c <= 127; c320c++) {
3011 FOR_ALL_POPULATED_RANKS {
3012 ctrl->timings[channel][slotrank].val_320c = c320c;
3013 }
3014 program_timings(ctrl, channel);
3015 reprogram_320c(ctrl);
3016 FOR_ALL_POPULATED_RANKS {
3017 stat[slotrank][c320c + 127] =
3018 test_320c(ctrl, channel, slotrank);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003019 printram("3stat: %d, %d, %d: %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003020 channel, slotrank, c320c,
3021 stat[slotrank][c320c + 127]);
3022 }
3023 }
3024 FOR_ALL_POPULATED_RANKS {
3025 struct run rn =
3026 get_longest_zero_run(stat[slotrank], 255);
3027 ctrl->timings[channel][slotrank].val_320c =
3028 rn.middle - 127;
3029 printram("3val: %d, %d: %d\n", channel,
3030 slotrank,
3031 ctrl->timings[channel][slotrank].val_320c);
3032 if (rn.all || rn.length < MIN_C320C_LEN) {
3033 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3034 ctrl->timings[channel][slotrank] = saved_timings[channel][slotrank];
3035 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003036 return MAKE_ERR;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003037 }
3038 }
3039 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003040 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003041}
3042
Patrick Rudolph371d2912015-10-09 13:33:25 +02003043/* Adjust CMD phase shift and try multiple command rates.
3044 * A command rate of 2T doubles the time needed for address and
3045 * command decode. */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003046static int command_training(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003047{
3048 int channel;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003049 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003050
3051 FOR_ALL_POPULATED_CHANNELS {
3052 fill_pattern5(ctrl, channel, 0);
3053 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
3054 }
3055
3056 /* try command rate 1T and 2T */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003057 err = try_cmd_stretch(ctrl, 0);
3058 if (err) {
3059 err = try_cmd_stretch(ctrl, 2);
3060 if (err) {
3061 printk(BIOS_EMERG, "c320c discovery failed\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003062 return err;
3063 }
3064 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003065
3066 FOR_ALL_POPULATED_CHANNELS {
3067 program_timings(ctrl, channel);
3068 }
3069
3070 reprogram_320c(ctrl);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003071 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003072}
3073
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003074static int discover_edges_real(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003075 int *edges)
3076{
3077 int edge;
3078 int statistics[NUM_LANES][MAX_EDGE_TIMING + 1];
3079 int lane;
3080
3081 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3082 FOR_ALL_LANES {
3083 ctrl->timings[channel][slotrank].lanes[lane].rising =
3084 edge;
3085 ctrl->timings[channel][slotrank].lanes[lane].falling =
3086 edge;
3087 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003088 program_timings(ctrl, channel);
3089
3090 FOR_ALL_LANES {
3091 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3092 4 * lane, 0);
3093 read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane +
3094 0x4140);
3095 }
3096
3097 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003098 /* DRAM command MRS
3099 * write MR3 MPR enable
3100 * in this mode only RD and RDA are allowed
3101 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003102 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
3103 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3104 (0xc01 | (ctrl->tMOD << 16)));
3105 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3106 (slotrank << 24) | 0x360004);
3107 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3108
Patrick Rudolph371d2912015-10-09 13:33:25 +02003109 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003110 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
3111 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4);
3112 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3113 (slotrank << 24));
3114 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3115
Patrick Rudolph371d2912015-10-09 13:33:25 +02003116 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003117 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
3118 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3119 0x1001 | ((ctrl->CAS + 8) << 16));
3120 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3121 (slotrank << 24) | 0x60000);
3122 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3123
Patrick Rudolph371d2912015-10-09 13:33:25 +02003124 /* DRAM command MRS
3125 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003126 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
3127 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3128 (0xc01 | (ctrl->tMOD << 16)));
3129 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3130 (slotrank << 24) | 0x360000);
3131 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3132
3133 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
3134
3135 wait_428c(channel);
3136
3137 FOR_ALL_LANES {
3138 statistics[lane][edge] =
3139 read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3140 lane * 4);
3141 }
3142 }
3143 FOR_ALL_LANES {
3144 struct run rn =
3145 get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
3146 edges[lane] = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003147 if (rn.all) {
3148 printk(BIOS_EMERG, "edge discovery failed: %d, %d, %d\n",
3149 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003150 return MAKE_ERR;
3151 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003152 printram("eval %d, %d, %d: %02x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003153 lane, edges[lane]);
3154 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003155 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003156}
3157
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003158static int discover_edges(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003159{
3160 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3161 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3162 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003163 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003164
3165 write32(DEFAULT_MCHBAR + 0x3400, 0);
3166
Patrick Rudolph9b515682015-10-09 13:43:51 +02003167 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003168
3169 FOR_ALL_POPULATED_CHANNELS FOR_ALL_LANES {
3170 write32(DEFAULT_MCHBAR + 4 * lane +
3171 0x400 * channel + 0x4080, 0);
3172 }
3173
3174 FOR_ALL_POPULATED_CHANNELS {
3175 fill_pattern0(ctrl, channel, 0, 0);
3176 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3177 FOR_ALL_LANES {
3178 read32(DEFAULT_MCHBAR + 0x400 * channel +
3179 lane * 4 + 0x4140);
3180 }
3181
3182 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3183 ctrl->timings[channel][slotrank].lanes[lane].falling =
3184 16;
3185 ctrl->timings[channel][slotrank].lanes[lane].rising =
3186 16;
3187 }
3188
3189 program_timings(ctrl, channel);
3190
3191 FOR_ALL_POPULATED_RANKS {
3192 wait_428c(channel);
3193
Patrick Rudolph371d2912015-10-09 13:33:25 +02003194 /* DRAM command MRS
3195 * MR3 enable MPR
3196 * write MR3 MPR enable
3197 * in this mode only RD and RDA are allowed
3198 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003199 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3200 0x1f000);
3201 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3202 0xc01 | (ctrl->tMOD << 16));
3203 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3204 (slotrank << 24) | 0x360004);
3205 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3206
Patrick Rudolph371d2912015-10-09 13:33:25 +02003207 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003208 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3209 0x1f105);
3210 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3211 0x4041003);
3212 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3213 (slotrank << 24) | 0);
3214 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3215
Patrick Rudolph371d2912015-10-09 13:33:25 +02003216 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003217 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3218 0x1f105);
3219 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3220 0x1001 | ((ctrl->CAS + 8) << 16));
3221 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3222 (slotrank << 24) | 0x60000);
3223 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3224
Patrick Rudolph371d2912015-10-09 13:33:25 +02003225 /* DRAM command MRS
3226 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003227 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3228 0x1f000);
3229 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3230 0xc01 | (ctrl->tMOD << 16));
3231 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3232 (slotrank << 24) | 0x360000);
3233 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3234 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3235 0xc0001);
3236
3237 wait_428c(channel);
3238 }
3239
Patrick Rudolph371d2912015-10-09 13:33:25 +02003240 /* XXX: check any measured value ? */
3241
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003242 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3243 ctrl->timings[channel][slotrank].lanes[lane].falling =
3244 48;
3245 ctrl->timings[channel][slotrank].lanes[lane].rising =
3246 48;
3247 }
3248
3249 program_timings(ctrl, channel);
3250
3251 FOR_ALL_POPULATED_RANKS {
3252 wait_428c(channel);
3253
Patrick Rudolph371d2912015-10-09 13:33:25 +02003254 /* DRAM command MRS
3255 * MR3 enable MPR
3256 * write MR3 MPR enable
3257 * in this mode only RD and RDA are allowed
3258 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003259 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3260 0x1f000);
3261 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3262 0xc01 | (ctrl->tMOD << 16));
3263 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3264 (slotrank << 24) | 0x360004);
3265 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3266
Patrick Rudolph371d2912015-10-09 13:33:25 +02003267 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003268 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3269 0x1f105);
3270 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3271 0x4041003);
3272 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3273 (slotrank << 24) | 0);
3274 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3275
Patrick Rudolph371d2912015-10-09 13:33:25 +02003276 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003277 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3278 0x1f105);
3279 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3280 0x1001 | ((ctrl->CAS + 8) << 16));
3281 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3282 (slotrank << 24) | 0x60000);
3283 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3284
Patrick Rudolph371d2912015-10-09 13:33:25 +02003285 /* DRAM command MRS
3286 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003287 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3288 0x1f000);
3289 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3290 0xc01 | (ctrl->tMOD << 16));
3291 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3292 (slotrank << 24) | 0x360000);
3293 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3294
3295 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3296 0xc0001);
3297 wait_428c(channel);
3298 }
3299
Patrick Rudolph371d2912015-10-09 13:33:25 +02003300 /* XXX: check any measured value ? */
3301
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003302 FOR_ALL_LANES {
3303 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel +
3304 lane * 4,
3305 ~read32(DEFAULT_MCHBAR + 0x4040 +
3306 0x400 * channel + lane * 4) & 0xff);
3307 }
3308
3309 fill_pattern0(ctrl, channel, 0, 0xffffffff);
3310 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3311 }
3312
3313 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3314 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003315 printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003316
3317 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003318 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003319 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003320 if (err)
3321 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003322 }
3323
3324 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003325 printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003326
3327 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003328 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003329 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003330 if (err)
3331 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003332 }
3333
3334 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3335
3336 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3337 ctrl->timings[channel][slotrank].lanes[lane].falling =
3338 falling_edges[channel][slotrank][lane];
3339 ctrl->timings[channel][slotrank].lanes[lane].rising =
3340 rising_edges[channel][slotrank][lane];
3341 }
3342
3343 FOR_ALL_POPULATED_CHANNELS {
3344 program_timings(ctrl, channel);
3345 }
3346
3347 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3348 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3349 0);
3350 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003351 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003352}
3353
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003354static int discover_edges_write_real(ramctr_timing *ctrl, int channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003355 int slotrank, int *edges)
3356{
3357 int edge;
3358 u32 raw_statistics[MAX_EDGE_TIMING + 1];
3359 int statistics[MAX_EDGE_TIMING + 1];
3360 const int reg3000b24[] = { 0, 0xc, 0x2c };
3361 int lane, i;
3362 int lower[NUM_LANES];
3363 int upper[NUM_LANES];
3364 int pat;
3365
3366 FOR_ALL_LANES {
3367 lower[lane] = 0;
3368 upper[lane] = MAX_EDGE_TIMING;
3369 }
3370
3371 for (i = 0; i < 3; i++) {
3372 write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel,
3373 reg3000b24[i] << 24);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003374 printram("[%x] = 0x%08x\n",
3375 0x3000 + 0x100 * channel, reg3000b24[i] << 24);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003376 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3377 fill_pattern5(ctrl, channel, pat);
3378 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003379 printram("using pattern %d\n", pat);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003380 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3381 FOR_ALL_LANES {
3382 ctrl->timings[channel][slotrank].lanes[lane].
3383 rising = edge;
3384 ctrl->timings[channel][slotrank].lanes[lane].
3385 falling = edge;
3386 }
3387 program_timings(ctrl, channel);
3388
3389 FOR_ALL_LANES {
3390 write32(DEFAULT_MCHBAR + 0x4340 +
3391 0x400 * channel + 4 * lane, 0);
3392 read32(DEFAULT_MCHBAR + 0x400 * channel +
3393 4 * lane + 0x4140);
3394 }
3395 wait_428c(channel);
3396
Patrick Rudolph371d2912015-10-09 13:33:25 +02003397 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003398 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3399 0x1f006);
3400 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3401 0x4 | (ctrl->tRCD << 16)
3402 | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) <<
3403 10));
3404 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3405 (slotrank << 24) | 0x60000);
3406 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel,
3407 0x240);
3408
Patrick Rudolph371d2912015-10-09 13:33:25 +02003409 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003410 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3411 0x1f201);
3412 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3413 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) <<
3414 16));
3415 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3416 (slotrank << 24));
3417 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel,
3418 0x242);
3419
Patrick Rudolph371d2912015-10-09 13:33:25 +02003420 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003421 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3422 0x1f105);
3423 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3424 0x4005020 | (max(ctrl->tRTP, 8) << 16));
3425 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3426 (slotrank << 24));
3427 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel,
3428 0x242);
3429
Patrick Rudolph371d2912015-10-09 13:33:25 +02003430 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003431 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3432 0x1f002);
3433 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3434 0xc01 | (ctrl->tRP << 16));
3435 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3436 (slotrank << 24) | 0x60400);
3437 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3438
3439 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3440 0xc0001);
3441 wait_428c(channel);
3442 FOR_ALL_LANES {
3443 read32(DEFAULT_MCHBAR + 0x4340 +
3444 0x400 * channel + lane * 4);
3445 }
3446
3447 raw_statistics[edge] =
3448 MCHBAR32(0x436c + 0x400 * channel);
3449 }
3450 FOR_ALL_LANES {
3451 struct run rn;
3452 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++)
3453 statistics[edge] =
3454 ! !(raw_statistics[edge] & (1 << lane));
3455 rn = get_longest_zero_run(statistics,
3456 MAX_EDGE_TIMING + 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003457 printram("edges: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003458 channel, slotrank, i, rn.start, rn.middle,
3459 rn.end, rn.start + ctrl->edge_offset[i],
3460 rn.end - ctrl->edge_offset[i]);
3461 lower[lane] =
3462 max(rn.start + ctrl->edge_offset[i], lower[lane]);
3463 upper[lane] =
3464 min(rn.end - ctrl->edge_offset[i], upper[lane]);
3465 edges[lane] = (lower[lane] + upper[lane]) / 2;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003466 if (rn.all || (lower[lane] > upper[lane])) {
3467 printk(BIOS_EMERG, "edge write discovery failed: %d, %d, %d\n",
3468 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003469 return MAKE_ERR;
3470 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003471 }
3472 }
3473 }
3474
3475 write32(DEFAULT_MCHBAR + 0x3000, 0);
3476 printram("CPA\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003477 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003478}
3479
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003480static int discover_edges_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003481{
3482 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3483 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3484 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003485 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003486
3487 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3488 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003489 printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003490
3491 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003492 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003493 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003494 if (err)
3495 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003496 }
3497
3498 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003499 printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003500
3501 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003502 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003503 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003504 if (err)
3505 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003506 }
3507
3508 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3509
3510 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3511 ctrl->timings[channel][slotrank].lanes[lane].falling =
3512 falling_edges[channel][slotrank][lane];
3513 ctrl->timings[channel][slotrank].lanes[lane].rising =
3514 rising_edges[channel][slotrank][lane];
3515 }
3516
3517 FOR_ALL_POPULATED_CHANNELS
3518 program_timings(ctrl, channel);
3519
3520 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3521 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3522 0);
3523 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003524 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003525}
3526
3527static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
3528{
3529 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003530 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003531 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
3532 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3533 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD)
3534 << 10) | (ctrl->tRCD << 16) | 4);
3535 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3536 (slotrank << 24) | 0x60000);
3537 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
3538
Patrick Rudolph371d2912015-10-09 13:33:25 +02003539 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003540 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
3541 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3542 0x80011e0 |
3543 ((ctrl->tWTR + ctrl->CWL + 8) << 16));
3544 write32(DEFAULT_MCHBAR + 0x4204 +
3545 0x400 * channel, (slotrank << 24));
3546 write32(DEFAULT_MCHBAR + 0x4214 +
3547 0x400 * channel, 0x242);
3548
Patrick Rudolph371d2912015-10-09 13:33:25 +02003549 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003550 write32(DEFAULT_MCHBAR + 0x4228 +
3551 0x400 * channel, 0x1f105);
3552 write32(DEFAULT_MCHBAR + 0x4238 +
3553 0x400 * channel,
3554 0x40011e0 | (max(ctrl->tRTP, 8) << 16));
3555 write32(DEFAULT_MCHBAR + 0x4208 +
3556 0x400 * channel, (slotrank << 24));
3557 write32(DEFAULT_MCHBAR + 0x4218 +
3558 0x400 * channel, 0x242);
3559
Patrick Rudolph371d2912015-10-09 13:33:25 +02003560 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003561 write32(DEFAULT_MCHBAR + 0x422c +
3562 0x400 * channel, 0x1f002);
3563 write32(DEFAULT_MCHBAR + 0x423c +
3564 0x400 * channel,
3565 0x1001 | (ctrl->tRP << 16));
3566 write32(DEFAULT_MCHBAR + 0x420c +
3567 0x400 * channel,
3568 (slotrank << 24) | 0x60400);
3569 write32(DEFAULT_MCHBAR + 0x421c +
3570 0x400 * channel, 0);
3571
3572 write32(DEFAULT_MCHBAR + 0x4284 +
3573 0x400 * channel, 0xc0001);
3574 wait_428c(channel);
3575}
3576
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003577static int discover_timC_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003578{
3579 const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
3580 int i, pat;
3581
3582 int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3583 int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3584 int channel, slotrank, lane;
3585
3586 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3587 lower[channel][slotrank][lane] = 0;
3588 upper[channel][slotrank][lane] = MAX_TIMC;
3589 }
3590
3591 write32(DEFAULT_MCHBAR + 0x4ea8, 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003592 printram("discover timC write:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003593
3594 for (i = 0; i < 3; i++)
3595 FOR_ALL_POPULATED_CHANNELS {
3596 write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100),
3597 (rege3c_b24[i] << 24)
3598 | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100))
3599 & ~0x3f000000));
3600 udelay(2);
3601 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3602 FOR_ALL_POPULATED_RANKS {
3603 int timC;
3604 u32 raw_statistics[MAX_TIMC + 1];
3605 int statistics[MAX_TIMC + 1];
3606
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003607 /* Make sure rn.start < rn.end */
3608 statistics[MAX_TIMC] = 1;
3609
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003610 fill_pattern5(ctrl, channel, pat);
3611 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003612 for (timC = 0; timC < MAX_TIMC; timC++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003613 FOR_ALL_LANES
3614 ctrl->timings[channel][slotrank].lanes[lane].timC = timC;
3615 program_timings(ctrl, channel);
3616
3617 test_timC_write (ctrl, channel, slotrank);
3618
3619 raw_statistics[timC] =
3620 MCHBAR32(0x436c + 0x400 * channel);
3621 }
3622 FOR_ALL_LANES {
3623 struct run rn;
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003624 for (timC = 0; timC < MAX_TIMC; timC++)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003625 statistics[timC] =
3626 !!(raw_statistics[timC] &
3627 (1 << lane));
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003628
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003629 rn = get_longest_zero_run(statistics,
3630 MAX_TIMC + 1);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003631 if (rn.all) {
3632 printk(BIOS_EMERG, "timC write discovery failed: %d, %d, %d\n",
3633 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003634 return MAKE_ERR;
3635 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003636 printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003637 channel, slotrank, i, rn.start,
3638 rn.middle, rn.end,
3639 rn.start + ctrl->timC_offset[i],
3640 rn.end - ctrl->timC_offset[i]);
3641 lower[channel][slotrank][lane] =
3642 max(rn.start + ctrl->timC_offset[i],
3643 lower[channel][slotrank][lane]);
3644 upper[channel][slotrank][lane] =
3645 min(rn.end - ctrl->timC_offset[i],
3646 upper[channel][slotrank][lane]);
3647
3648 }
3649 }
3650 }
3651 }
3652
3653 FOR_ALL_CHANNELS {
3654 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3655 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3656 ~0x3f000000));
3657 udelay(2);
3658 }
3659
3660 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3661
3662 printram("CPB\n");
3663
3664 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
Patrick Rudolpha649a542016-01-17 18:32:06 +01003665 printram("timC %d, %d, %d: %x\n", channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003666 slotrank, lane,
3667 (lower[channel][slotrank][lane] +
3668 upper[channel][slotrank][lane]) / 2);
3669 ctrl->timings[channel][slotrank].lanes[lane].timC =
3670 (lower[channel][slotrank][lane] +
3671 upper[channel][slotrank][lane]) / 2;
3672 }
3673 FOR_ALL_POPULATED_CHANNELS {
3674 program_timings(ctrl, channel);
3675 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003676 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003677}
3678
3679static void normalize_training(ramctr_timing * ctrl)
3680{
3681 int channel, slotrank, lane;
3682 int mat = 0;
3683
3684 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3685 int delta;
3686 FOR_ALL_LANES mat =
3687 max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat);
3688 delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028;
3689 ctrl->timings[channel][slotrank].val_4024 += delta;
3690 ctrl->timings[channel][slotrank].val_4028 += delta;
3691 }
3692
3693 FOR_ALL_POPULATED_CHANNELS {
3694 program_timings(ctrl, channel);
3695 }
3696}
3697
3698static void write_controller_mr(ramctr_timing * ctrl)
3699{
3700 int channel, slotrank;
3701
3702 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3703 write32(DEFAULT_MCHBAR + 0x0004 + (channel << 8) +
3704 lane_registers[slotrank], make_mr0(ctrl, slotrank));
3705 write32(DEFAULT_MCHBAR + 0x0008 + (channel << 8) +
Patrick Rudolph7e513d12016-01-10 14:22:34 +01003706 lane_registers[slotrank],
3707 make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003708 }
3709}
3710
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003711static int channel_test(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003712{
3713 int channel, slotrank, lane;
3714
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003715 slotrank = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003716 FOR_ALL_POPULATED_CHANNELS
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003717 if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) {
3718 printk(BIOS_EMERG, "Mini channel test failed (1): %d\n",
3719 channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003720 return MAKE_ERR;
3721 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003722 FOR_ALL_POPULATED_CHANNELS {
3723 fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
3724
3725 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3726 }
3727
3728 for (slotrank = 0; slotrank < 4; slotrank++)
3729 FOR_ALL_CHANNELS
3730 if (ctrl->rankmap[channel] & (1 << slotrank)) {
3731 FOR_ALL_LANES {
3732 write32(DEFAULT_MCHBAR + (0x4f40 + 4 * lane), 0);
3733 write32(DEFAULT_MCHBAR + (0x4d40 + 4 * lane), 0);
3734 }
3735 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003736 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003737 write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
3738 write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10), 0x0028a004);
3739 write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
3740 0x00060000 | (slotrank << 24));
3741 write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003742 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003743 write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
3744 write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281064);
3745 write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
3746 0x00000000 | (slotrank << 24));
3747 write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003748 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003749 write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f105);
3750 write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x04281064);
3751 write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
3752 0x00000000 | (slotrank << 24));
3753 write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003754 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003755 write32(DEFAULT_MCHBAR + 0x422c + (channel << 10), 0x0001f002);
3756 write32(DEFAULT_MCHBAR + 0x423c + (channel << 10), 0x00280c01);
3757 write32(DEFAULT_MCHBAR + 0x420c + (channel << 10),
3758 0x00060400 | (slotrank << 24));
3759 write32(DEFAULT_MCHBAR + 0x421c + (channel << 10), 0x00000240);
3760 write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
3761 wait_428c(channel);
3762 FOR_ALL_LANES
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003763 if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) {
3764 printk(BIOS_EMERG, "Mini channel test failed (2): %d, %d, %d\n",
3765 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003766 return MAKE_ERR;
3767 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003768 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003769 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003770}
3771
3772static void set_scrambling_seed(ramctr_timing * ctrl)
3773{
3774 int channel;
3775
3776 /* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
3777 I don't think so. */
3778 static u32 seeds[NUM_CHANNELS][3] = {
3779 {0x00009a36, 0xbafcfdcf, 0x46d1ab68},
3780 {0x00028bfa, 0x53fe4b49, 0x19ed5483}
3781 };
3782 FOR_ALL_POPULATED_CHANNELS {
3783 MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
3784 write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
3785 write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
3786 write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
3787 }
3788}
3789
3790static void set_4f8c(void)
3791{
3792 struct cpuid_result cpures;
3793 u32 cpu;
3794
Ryan Salsamendie4da9aa2016-06-24 12:01:11 -07003795 cpures = cpuid(1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003796 cpu = (cpures.eax);
3797 if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) {
3798 MCHBAR32(0x4f8c) = 0x141D1519;
3799 } else {
3800 MCHBAR32(0x4f8c) = 0x551D1519;
3801 }
3802}
3803
3804static void prepare_training(ramctr_timing * ctrl)
3805{
3806 int channel;
3807
3808 FOR_ALL_POPULATED_CHANNELS {
3809 // Always drive command bus
3810 MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000;
3811 }
3812
3813 udelay(1);
3814
3815 FOR_ALL_POPULATED_CHANNELS {
3816 wait_428c(channel);
3817 }
3818}
3819
3820static void set_4008c(ramctr_timing * ctrl)
3821{
3822 int channel, slotrank;
3823 u32 reg;
3824 FOR_ALL_POPULATED_CHANNELS {
3825 u32 b20, b4_8_12;
3826 int min_320c = 10000;
3827 int max_320c = -10000;
3828
3829 FOR_ALL_POPULATED_RANKS {
3830 max_320c = max(ctrl->timings[channel][slotrank].val_320c, max_320c);
3831 min_320c = min(ctrl->timings[channel][slotrank].val_320c, min_320c);
3832 }
3833
3834 if (max_320c - min_320c > 51)
3835 b20 = 0;
3836 else
3837 b20 = ctrl->ref_card_offset[channel];
3838
3839 if (ctrl->reg_320c_range_threshold < max_320c - min_320c)
3840 b4_8_12 = 0x3330;
3841 else
3842 b4_8_12 = 0x2220;
3843
3844 reg = read32(DEFAULT_MCHBAR + 0x400c + (channel << 10));
3845 write32(DEFAULT_MCHBAR + 0x400c + (channel << 10),
3846 (reg & 0xFFF0FFFF)
3847 | (ctrl->ref_card_offset[channel] << 16)
3848 | (ctrl->ref_card_offset[channel] << 18));
3849 write32(DEFAULT_MCHBAR + 0x4008 + (channel << 10),
3850 0x0a000000
3851 | (b20 << 20)
3852 | ((ctrl->ref_card_offset[channel] + 2) << 16)
3853 | b4_8_12);
3854 }
3855}
3856
3857static void set_42a0(ramctr_timing * ctrl)
3858{
3859 int channel;
3860 FOR_ALL_POPULATED_CHANNELS {
3861 write32(DEFAULT_MCHBAR + (0x42a0 + 0x400 * channel),
3862 0x00001000 | ctrl->rankmap[channel]);
3863 MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK
3864 }
3865}
3866
3867static int encode_5d10(int ns)
3868{
3869 return (ns + 499) / 500;
3870}
3871
3872/* FIXME: values in this function should be hardware revision-dependent. */
3873static void final_registers(ramctr_timing * ctrl)
3874{
3875 int channel;
3876 int t1_cycles = 0, t1_ns = 0, t2_ns;
3877 int t3_ns;
3878 u32 r32;
3879
3880 write32(DEFAULT_MCHBAR + 0x4cd4, 0x00000046);
3881
3882 write32(DEFAULT_MCHBAR + 0x400c, (read32(DEFAULT_MCHBAR + 0x400c) & 0xFFFFCFFF) | 0x1000); // OK
3883 write32(DEFAULT_MCHBAR + 0x440c, (read32(DEFAULT_MCHBAR + 0x440c) & 0xFFFFCFFF) | 0x1000); // OK
3884 write32(DEFAULT_MCHBAR + 0x4cb0, 0x00000740);
3885 write32(DEFAULT_MCHBAR + 0x4380, 0x00000aaa); // OK
3886 write32(DEFAULT_MCHBAR + 0x4780, 0x00000aaa); // OK
3887 write32(DEFAULT_MCHBAR + 0x4f88, 0x5f7003ff); // OK
3888 write32(DEFAULT_MCHBAR + 0x5064, 0x00073000 | ctrl->reg_5064b0); // OK
3889
3890 FOR_ALL_CHANNELS {
3891 switch (ctrl->rankmap[channel]) {
3892 /* Unpopulated channel. */
3893 case 0:
3894 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0);
3895 break;
3896 /* Only single-ranked dimms. */
3897 case 1:
3898 case 4:
3899 case 5:
3900 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x373131);
3901 break;
3902 /* Dual-ranked dimms present. */
3903 default:
3904 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x9b6ea1);
3905 break;
3906 }
3907 }
3908
3909 write32 (DEFAULT_MCHBAR + 0x5880, 0xca9171e5);
3910 write32 (DEFAULT_MCHBAR + 0x5888,
3911 (read32 (DEFAULT_MCHBAR + 0x5888) & ~0xffffff) | 0xe4d5d0);
3912 write32 (DEFAULT_MCHBAR + 0x58a8, read32 (DEFAULT_MCHBAR + 0x58a8) & ~0x1f);
3913 write32 (DEFAULT_MCHBAR + 0x4294,
3914 (read32 (DEFAULT_MCHBAR + 0x4294) & ~0x30000)
3915 | (1 << 16));
3916 write32 (DEFAULT_MCHBAR + 0x4694,
3917 (read32 (DEFAULT_MCHBAR + 0x4694) & ~0x30000)
3918 | (1 << 16));
3919
3920 MCHBAR32(0x5030) |= 1; // OK
3921 MCHBAR32(0x5030) |= 0x80; // OK
3922 MCHBAR32(0x5f18) = 0xfa; // OK
3923
3924 /* Find a populated channel. */
3925 FOR_ALL_POPULATED_CHANNELS
3926 break;
3927
3928 t1_cycles = ((read32(DEFAULT_MCHBAR + 0x4290 + channel * 0x400) >> 8) & 0xff);
3929 r32 = read32(DEFAULT_MCHBAR + 0x5064);
3930 if (r32 & 0x20000)
3931 t1_cycles += (r32 & 0xfff);
3932 t1_cycles += (read32(DEFAULT_MCHBAR + channel * 0x400 + 0x42a4) & 0xfff);
3933 t1_ns = t1_cycles * ctrl->tCK / 256 + 544;
3934 if (!(r32 & 0x20000))
3935 t1_ns += 500;
3936
3937 t2_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f10) >> 8) & 0xfff);
3938 if ( read32(DEFAULT_MCHBAR + 0x5f00) & 8 )
3939 {
3940 t3_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f20) >> 8) & 0xfff);
3941 t3_ns += 10 * (read32(DEFAULT_MCHBAR + 0x5f18) & 0xff);
3942 }
3943 else
3944 {
3945 t3_ns = 500;
3946 }
3947 printk(BIOS_DEBUG, "t123: %d, %d, %d\n",
3948 t1_ns, t2_ns, t3_ns);
3949 write32 (DEFAULT_MCHBAR + 0x5d10,
3950 ((encode_5d10(t1_ns) + encode_5d10(t2_ns)) << 16)
3951 | (encode_5d10(t1_ns) << 8)
3952 | ((encode_5d10(t3_ns) + encode_5d10(t2_ns) + encode_5d10(t1_ns)) << 24)
3953 | (read32(DEFAULT_MCHBAR + 0x5d10) & 0xC0C0C0C0)
3954 | 0xc);
3955}
3956
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003957static void save_timings(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003958{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003959 /* Save the MRC S3 restore data to cbmem */
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003960 store_current_mrc_cache(ctrl, sizeof(*ctrl));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003961}
3962
3963static void restore_timings(ramctr_timing * ctrl)
3964{
3965 int channel, slotrank, lane;
3966
3967 FOR_ALL_POPULATED_CHANNELS
3968 MCHBAR32(0x4004 + 0x400 * channel) =
3969 ctrl->tRRD
3970 | (ctrl->tRTP << 4)
3971 | (ctrl->tCKE << 8)
3972 | (ctrl->tWTR << 12)
3973 | (ctrl->tFAW << 16)
3974 | (ctrl->tWR << 24)
3975 | (ctrl->cmd_stretch[channel] << 30);
3976
3977 udelay(1);
3978
3979 FOR_ALL_POPULATED_CHANNELS {
3980 wait_428c(channel);
3981 }
3982
3983 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3984 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
3985 + 4 * lane, 0);
3986 }
3987
3988 FOR_ALL_POPULATED_CHANNELS
3989 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
3990 read32(DEFAULT_MCHBAR + 0x4008 +
3991 0x400 * channel) | 0x8000000);
3992
3993 FOR_ALL_POPULATED_CHANNELS {
3994 udelay (1);
3995 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
3996 read32(DEFAULT_MCHBAR + 0x4020 +
3997 0x400 * channel) | 0x200000);
3998 }
3999
4000 printram("CPE\n");
4001
4002 write32(DEFAULT_MCHBAR + 0x3400, 0);
4003 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
4004
4005 printram("CP5b\n");
4006
4007 FOR_ALL_POPULATED_CHANNELS {
4008 program_timings(ctrl, channel);
4009 }
4010
4011 u32 reg, addr;
4012
Elyes HAOUAS7db506c2016-10-02 11:56:39 +02004013 while (!(MCHBAR32(0x5084) & 0x10000));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004014 do {
4015 reg = MCHBAR32(0x428c);
4016 } while ((reg & 0x14) == 0);
4017
4018 // Set state of memory controller
4019 MCHBAR32(0x5030) = 0x116;
4020 MCHBAR32(0x4ea0) = 0;
4021
4022 // Wait 500us
4023 udelay(500);
4024
4025 FOR_ALL_CHANNELS {
4026 // Set valid rank CKE
4027 reg = 0;
4028 reg = (reg & ~0xf) | ctrl->rankmap[channel];
4029 addr = 0x400 * channel + 0x42a0;
4030 MCHBAR32(addr) = reg;
4031
4032 // Wait 10ns for ranks to settle
4033 //udelay(0.01);
4034
4035 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
4036 MCHBAR32(addr) = reg;
4037
4038 // Write reset using a NOP
4039 write_reset(ctrl);
4040 }
4041
4042 /* mrs commands. */
4043 dram_mrscommands(ctrl);
4044
4045 printram("CP5c\n");
4046
4047 write32(DEFAULT_MCHBAR + 0x3000, 0);
4048
4049 FOR_ALL_CHANNELS {
4050 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
4051 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
4052 ~0x3f000000));
4053 udelay(2);
4054 }
4055
4056 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
4057}
4058
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004059static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot,
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004060 int s3_resume, int me_uma_size)
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004061{
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004062 int err;
4063
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004064 printk(BIOS_DEBUG, "Starting RAM training (%d).\n", fast_boot);
4065
4066 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004067 /* Find fastest common supported parameters */
4068 dram_find_common_params(ctrl);
4069
4070 dram_dimm_mapping(ctrl);
4071 }
4072
4073 /* Set MCU frequency */
4074 dram_freq(ctrl);
4075
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004076 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004077 /* Calculate timings */
4078 dram_timing(ctrl);
4079 }
4080
4081 /* Set version register */
4082 MCHBAR32(0x5034) = 0xC04EB002;
4083
4084 /* Enable crossover */
4085 dram_xover(ctrl);
4086
4087 /* Set timing and refresh registers */
4088 dram_timing_regs(ctrl);
4089
4090 /* Power mode preset */
4091 MCHBAR32(0x4e80) = 0x5500;
4092
4093 /* Set scheduler parameters */
4094 MCHBAR32(0x4c20) = 0x10100005;
4095
Elyes HAOUAS15279a92016-07-28 21:05:26 +02004096 /* Set CPU specific register */
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004097 set_4f8c();
4098
4099 /* Clear IO reset bit */
4100 MCHBAR32(0x5030) &= ~0x20;
4101
4102 /* Set MAD-DIMM registers */
4103 dram_dimm_set_mapping(ctrl);
4104 printk(BIOS_DEBUG, "Done dimm mapping\n");
4105
4106 /* Zone config */
4107 dram_zones(ctrl, 1);
4108
4109 /* Set memory map */
4110 dram_memorymap(ctrl, me_uma_size);
4111 printk(BIOS_DEBUG, "Done memory map\n");
4112
4113 /* Set IO registers */
4114 dram_ioregs(ctrl);
4115 printk(BIOS_DEBUG, "Done io registers\n");
4116
4117 udelay(1);
4118
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004119 if (fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004120 restore_timings(ctrl);
4121 } else {
4122 /* Do jedec ddr3 reset sequence */
4123 dram_jedecreset(ctrl);
4124 printk(BIOS_DEBUG, "Done jedec reset\n");
4125
4126 /* MRS commands */
4127 dram_mrscommands(ctrl);
4128 printk(BIOS_DEBUG, "Done MRS commands\n");
4129
4130 /* Prepare for memory training */
4131 prepare_training(ctrl);
4132
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004133 err = read_training(ctrl);
4134 if (err)
4135 return err;
4136
4137 err = write_training(ctrl);
4138 if (err)
4139 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004140
4141 printram("CP5a\n");
4142
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004143 err = discover_edges(ctrl);
4144 if (err)
4145 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004146
4147 printram("CP5b\n");
4148
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004149 err = command_training(ctrl);
4150 if (err)
4151 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004152
4153 printram("CP5c\n");
4154
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004155 err = discover_edges_write(ctrl);
4156 if (err)
4157 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004158
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004159 err = discover_timC_write(ctrl);
4160 if (err)
4161 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004162
4163 normalize_training(ctrl);
4164 }
4165
4166 set_4008c(ctrl);
4167
4168 write_controller_mr(ctrl);
4169
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004170 if (!s3_resume) {
4171 err = channel_test(ctrl);
4172 if (err)
4173 return err;
4174 }
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004175
4176 return 0;
4177}
4178
4179void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004180 int s3resume)
4181{
4182 int me_uma_size;
4183 int cbmem_was_inited;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004184 ramctr_timing ctrl;
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004185 int fast_boot;
4186 struct mrc_data_container *mrc_cache;
4187 ramctr_timing *ctrl_cached;
Patrick Rudolph31d19592016-03-26 12:22:34 +01004188 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004189
4190 MCHBAR32(0x5f00) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004191
Vadim Bendebury7a3f36a2012-04-18 15:47:32 -07004192 report_platform_info();
4193
Stefan Reinauer00636b02012-04-04 00:08:51 +02004194 /* Wait for ME to be ready */
4195 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004196 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004197
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004198 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +02004199
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004200 u32 reg_5d10;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004201
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004202 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004203
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004204 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +02004205
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004206 reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10); // !!! = 0x00000000
4207 if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */
4208 && reg_5d10 && !s3resume) {
4209 write32(DEFAULT_MCHBAR + 0x5d10, 0);
4210 /* Need reset. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02004211 outb(0x6, 0xcf9);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004212
Patrick Georgi546953c2014-11-29 10:38:17 +01004213 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004214 }
Stefan Reinauer00636b02012-04-04 00:08:51 +02004215
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +02004216 memset(&ctrl, 0, sizeof(ctrl));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004217
4218 early_pch_init_native();
4219 early_thermal_init();
4220
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004221 /* try to find timings in MRC cache */
4222 mrc_cache = find_current_mrc_cache();
4223 if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(ctrl))) {
4224 if (s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004225 /* Failed S3 resume, reset to come up cleanly */
4226 outb(0x6, 0xcf9);
4227 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004228 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004229 ctrl_cached = NULL;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004230 } else {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004231 ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004232 }
4233
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004234 /* verify MRC cache for fast boot */
4235 if (ctrl_cached) {
4236 /* check SPD CRC16 to make sure the DIMMs haven't been replaced */
4237 fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
4238 if (!fast_boot)
4239 printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
4240 if (!fast_boot && s3resume) {
4241 /* Failed S3 resume, reset to come up cleanly */
4242 outb(0x6, 0xcf9);
4243 halt();
4244 }
4245 } else
4246 fast_boot = 0;
4247
4248 if (fast_boot) {
4249 printk(BIOS_DEBUG, "Trying stored timings.\n");
4250 memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
4251
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004252 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004253 if (err) {
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004254 if (s3resume) {
4255 /* Failed S3 resume, reset to come up cleanly */
4256 outb(0x6, 0xcf9);
4257 halt();
4258 }
4259 /* no need to erase bad mrc cache here, it gets overwritten on
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004260 * successful boot. */
4261 printk(BIOS_ERR, "Stored timings are invalid !\n");
4262 fast_boot = 0;
4263 }
4264 }
4265 if (!fast_boot) {
4266 ctrl.mobile = mobile;
4267 ctrl.tCK = min_tck;
4268
4269 /* Get DDR3 SPD data */
4270 dram_find_spds_ddr3(spds, &ctrl);
4271
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004272 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004273 }
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004274
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004275 if (err) {
4276 /* fallback: disable failing channel */
4277 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
4278 printram("Disable failing channel.\n");
4279
4280 /* Reset DDR3 frequency */
4281 dram_find_spds_ddr3(spds, &ctrl);
4282
4283 /* disable failing channel */
4284 disable_channel(&ctrl, GET_ERR_CHANNEL(err));
4285
4286 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
4287 }
4288
Patrick Rudolph31d19592016-03-26 12:22:34 +01004289 if (err)
4290 die("raminit failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004291
4292 /* FIXME: should be hardware revision-dependent. */
4293 write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
4294
4295 set_scrambling_seed(&ctrl);
4296
4297 set_42a0(&ctrl);
4298
4299 final_registers(&ctrl);
4300
4301 /* Zone config */
4302 dram_zones(&ctrl, 0);
4303
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004304 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004305 quick_ram_check();
4306
4307 intel_early_me_status();
4308 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
4309 intel_early_me_status();
4310
Stefan Reinauer00636b02012-04-04 00:08:51 +02004311 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004312
4313 cbmem_was_inited = !cbmem_recovery(s3resume);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004314 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004315 save_timings(&ctrl);
4316 if (s3resume && !cbmem_was_inited) {
4317 /* Failed S3 resume, reset to come up cleanly */
4318 outb(0x6, 0xcf9);
4319 halt();
4320 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +01004321
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004322 fill_smbios17(&ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004323}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004324
4325#define HOST_BRIDGE PCI_DEVFN(0, 0)
4326#define DEFAULT_TCK TCK_800MHZ
4327
4328static unsigned int get_mem_min_tck(void)
4329{
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004330 u32 reg32;
4331 u8 rev;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004332 const struct device *dev;
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004333 const struct northbridge_intel_sandybridge_config *cfg = NULL;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004334
4335 dev = dev_find_slot(0, HOST_BRIDGE);
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004336 if (dev)
4337 cfg = dev->chip_info;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004338
4339 /* If this is zero, it just means devicetree.cb didn't set it */
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004340 if (!cfg || cfg->max_mem_clock_mhz == 0) {
4341 rev = pci_read_config8(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004342
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004343 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
4344 /* read Capabilities A Register DMFC bits */
4345 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A);
4346 reg32 &= 0x7;
4347
4348 switch (reg32) {
4349 case 7: return TCK_533MHZ;
4350 case 6: return TCK_666MHZ;
4351 case 5: return TCK_800MHZ;
4352 /* reserved: */
4353 default:
4354 break;
4355 }
4356 } else {
4357 /* read Capabilities B Register DMFC bits */
4358 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
4359 reg32 = (reg32 >> 4) & 0x7;
4360
4361 switch (reg32) {
4362 case 7: return TCK_533MHZ;
4363 case 6: return TCK_666MHZ;
4364 case 5: return TCK_800MHZ;
4365 case 4: return TCK_933MHZ;
4366 case 3: return TCK_1066MHZ;
4367 case 2: return TCK_1200MHZ;
4368 case 1: return TCK_1333MHZ;
4369 /* reserved: */
4370 default:
4371 break;
4372 }
4373 }
4374 return DEFAULT_TCK;
4375 } else {
Patrick Rudolph7bddd302016-06-11 18:39:35 +02004376 if (cfg->max_mem_clock_mhz >= 1066)
4377 return TCK_1066MHZ;
4378 else if (cfg->max_mem_clock_mhz >= 933)
4379 return TCK_933MHZ;
4380 else if (cfg->max_mem_clock_mhz >= 800)
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004381 return TCK_800MHZ;
4382 else if (cfg->max_mem_clock_mhz >= 666)
4383 return TCK_666MHZ;
4384 else if (cfg->max_mem_clock_mhz >= 533)
4385 return TCK_533MHZ;
4386 else
4387 return TCK_400MHZ;
4388 }
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004389}
4390
Patrick Rudolph266a1f72016-06-09 18:13:34 +02004391#define DEFAULT_PCI_MMIO_SIZE 2048
4392
4393static unsigned int get_mmio_size(void)
4394{
4395 const struct device *dev;
4396 const struct northbridge_intel_sandybridge_config *cfg = NULL;
4397
4398 dev = dev_find_slot(0, HOST_BRIDGE);
4399 if (dev)
4400 cfg = dev->chip_info;
4401
4402 /* If this is zero, it just means devicetree.cb didn't set it */
4403 if (!cfg || cfg->pci_mmio_size == 0)
4404 return DEFAULT_PCI_MMIO_SIZE;
4405 else
4406 return cfg->pci_mmio_size;
4407}
4408
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004409void perform_raminit(int s3resume)
4410{
4411 spd_raw_data spd[4];
4412
4413 post_code(0x3a);
4414
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +02004415 memset (spd, 0, sizeof(spd));
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004416 mainboard_get_spd(spd);
4417
4418 timestamp_add_now(TS_BEFORE_INITRAM);
4419
4420 init_dram_ddr3(spd, 1, get_mem_min_tck(), s3resume);
4421}