blob: 0842d4bf9380c6f899b33bc64c65f5cd4f9a97fc [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
Patrick Rudolph069018d2016-11-12 11:43:59 +0100206#define MC_BIOS_REQ 0x5e00
207#define MC_BIOS_DATA 0x5e04
208
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700209static void program_timings(ramctr_timing * ctrl, int channel);
Patrick Rudolph266a1f72016-06-09 18:13:34 +0200210static unsigned int get_mmio_size(void);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700211
212static const char *ecc_decoder[] = {
Stefan Reinauer00636b02012-04-04 00:08:51 +0200213 "inactive",
214 "active on IO",
215 "disabled on IO",
216 "active"
217};
218
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700219static void wait_txt_clear(void)
220{
221 struct cpuid_result cp;
222
223 cp = cpuid_ext(0x1, 0x0);
224 /* Check if TXT is supported? */
225 if (!(cp.ecx & 0x40))
226 return;
227 /* Some TXT public bit. */
228 if (!(read32((void *)0xfed30010) & 1))
229 return;
230 /* Wait for TXT clear. */
Elyes HAOUAS7db506c2016-10-02 11:56:39 +0200231 while (!(read8((void *)0xfed40000) & (1 << 7)));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700232}
233
234static void sfence(void)
235{
236 asm volatile ("sfence");
237}
238
Patrick Rudolph9b515682015-10-09 13:43:51 +0200239static void toggle_io_reset(void) {
240 /* toggle IO reset bit */
241 u32 r32 = read32(DEFAULT_MCHBAR + 0x5030);
242 write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20);
243 udelay(1);
244 write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20);
245 udelay(1);
246}
247
Stefan Reinauer00636b02012-04-04 00:08:51 +0200248/*
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100249 * Disable a channel in ramctr_timing.
250 */
251static void disable_channel(ramctr_timing *ctrl, int channel) {
252 ctrl->rankmap[channel] = 0;
253 memset(&ctrl->rank_mirror[channel][0], 0, sizeof(ctrl->rank_mirror[0]));
254 ctrl->channel_size_mb[channel] = 0;
255 ctrl->cmd_stretch[channel] = 0;
256 ctrl->mad_dimm[channel] = 0;
257 memset(&ctrl->timings[channel][0], 0, sizeof(ctrl->timings[0]));
Patrick Rudolph74163d62016-11-17 20:02:43 +0100258 memset(&ctrl->info.dimm[channel][0], 0, sizeof(ctrl->info.dimm[0]));
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100259}
260
261/*
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100262 * Fill cbmem with information for SMBIOS type 17.
263 */
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100264static void fill_smbios17(ramctr_timing *ctrl)
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100265{
266 struct memory_info *mem_info;
267 int channel, slot;
268 struct dimm_info *dimm;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100269 uint16_t ddr_freq;
270 dimm_info *info = &ctrl->info;
271
272 ddr_freq = (1000 << 8) / ctrl->tCK;
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100273
274 /*
275 * Allocate CBMEM area for DIMM information used to populate SMBIOS
276 * table 17
277 */
278 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
279 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
280 if (!mem_info)
281 return;
282
283 memset(mem_info, 0, sizeof(*mem_info));
284
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200285 FOR_ALL_CHANNELS for (slot = 0; slot < NUM_SLOTS; slot++) {
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100286 dimm = &mem_info->dimm[mem_info->dimm_cnt];
287 if (info->dimm[channel][slot].size_mb) {
288 dimm->ddr_type = MEMORY_TYPE_DDR3;
289 dimm->ddr_frequency = ddr_freq;
290 dimm->dimm_size = info->dimm[channel][slot].size_mb;
291 dimm->channel_num = channel;
292 dimm->rank_per_dimm = info->dimm[channel][slot].ranks;
293 dimm->dimm_num = slot;
294 memcpy(dimm->module_part_number,
295 info->dimm[channel][slot].part_number, 16);
296 dimm->mod_id = info->dimm[channel][slot].manufacturer_id;
297 dimm->mod_type = info->dimm[channel][slot].dimm_type;
298 dimm->bus_width = info->dimm[channel][slot].width;
299 mem_info->dimm_cnt++;
300 }
301 }
302}
303
304/*
Stefan Reinauer00636b02012-04-04 00:08:51 +0200305 * Dump in the log memory controller configuration as read from the memory
306 * controller registers.
307 */
308static void report_memory_config(void)
309{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700310 u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200311 int i;
312
313 addr_decoder_common = MCHBAR32(0x5000);
314 addr_decode_ch[0] = MCHBAR32(0x5004);
315 addr_decode_ch[1] = MCHBAR32(0x5008);
316
317 printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
Patrick Rudolph069018d2016-11-12 11:43:59 +0100318 (MCHBAR32(MC_BIOS_DATA) * 13333 * 2 + 50) / 100);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200319 printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700320 addr_decoder_common & 3, (addr_decoder_common >> 2) & 3,
Stefan Reinauer00636b02012-04-04 00:08:51 +0200321 (addr_decoder_common >> 4) & 3);
322
323 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
324 u32 ch_conf = addr_decode_ch[i];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700325 printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i,
326 ch_conf);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200327 printk(BIOS_DEBUG, " ECC %s\n",
328 ecc_decoder[(ch_conf >> 24) & 3]);
329 printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
330 ((ch_conf >> 22) & 1) ? "on" : "off");
331 printk(BIOS_DEBUG, " rank interleave %s\n",
332 ((ch_conf >> 21) & 1) ? "on" : "off");
333 printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n",
334 ((ch_conf >> 0) & 0xff) * 256,
335 ((ch_conf >> 19) & 1) ? 16 : 8,
336 ((ch_conf >> 17) & 1) ? "dual" : "single",
337 ((ch_conf >> 16) & 1) ? "" : ", selected");
338 printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n",
339 ((ch_conf >> 8) & 0xff) * 256,
340 ((ch_conf >> 20) & 1) ? 16 : 8,
341 ((ch_conf >> 18) & 1) ? "dual" : "single",
342 ((ch_conf >> 16) & 1) ? ", selected" : "");
343 }
344}
345
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100346/*
347 * Return CRC16 match for all SPDs.
348 */
349static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
350{
351 int channel, slot, spd_slot;
352 int match = 1;
353
354 FOR_ALL_CHANNELS {
355 for (slot = 0; slot < NUM_SLOTS; slot++) {
356 spd_slot = 2 * channel + slot;
357 match &= ctrl->spd_crc[channel][slot] ==
358 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
359 }
360 }
361 return match;
362}
363
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700364void read_spd(spd_raw_data * spd, u8 addr)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200365{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700366 int j;
367 for (j = 0; j < 256; j++)
368 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
369}
370
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100371static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700372{
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100373 int dimms = 0, dimms_on_channel;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700374 int channel, slot, spd_slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100375 dimm_info *dimm = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700376
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +0200377 memset (ctrl->rankmap, 0, sizeof(ctrl->rankmap));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700378
379 ctrl->extended_temperature_range = 1;
380 ctrl->auto_self_refresh = 1;
381
382 FOR_ALL_CHANNELS {
383 ctrl->channel_size_mb[channel] = 0;
384
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100385 dimms_on_channel = 0;
386 /* count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700387 for (slot = 0; slot < NUM_SLOTS; slot++) {
388 spd_slot = 2 * channel + slot;
389 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100390 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
391 dimms_on_channel++;
392 }
393
394 for (slot = 0; slot < NUM_SLOTS; slot++) {
395 spd_slot = 2 * channel + slot;
396 /* search for XMP profile */
397 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
398 spd[spd_slot],
399 DDR3_XMP_PROFILE_1);
400
401 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
402 printram("No valid XMP profile found.\n");
403 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
404 } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
405 printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
406 dimm->dimm[channel][slot].dimms_per_channel,
407 dimms_on_channel);
408 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
409 } else if (dimm->dimm[channel][slot].voltage != 1500) {
410 /* TODO: support other DDR3 voltage than 1500mV */
411 printram("XMP profile's requested %u mV is unsupported.\n",
412 dimm->dimm[channel][slot].voltage);
413 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
414 }
415
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100416 /* fill in CRC16 for MRC cache */
417 ctrl->spd_crc[channel][slot] =
418 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
419
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700420 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
421 // set dimm invalid
422 dimm->dimm[channel][slot].ranks = 0;
423 dimm->dimm[channel][slot].size_mb = 0;
424 continue;
425 }
426
427 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
428 dimms++;
429 ctrl->rank_mirror[channel][slot * 2] = 0;
430 ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
431 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
432
433 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
434 ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
435
436 ctrl->rankmap[channel] |= ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100437 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n",
438 channel, ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700439 }
440 if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc)
441 && dimm->dimm[channel][0].reference_card <= 5 && dimm->dimm[channel][1].reference_card <= 5) {
442 const int ref_card_offset_table[6][6] = {
443 { 0, 0, 0, 0, 2, 2, },
444 { 0, 0, 0, 0, 2, 2, },
445 { 0, 0, 0, 0, 2, 2, },
446 { 0, 0, 0, 0, 1, 1, },
447 { 2, 2, 2, 1, 0, 0, },
448 { 2, 2, 2, 1, 0, 0, },
449 };
450 ctrl->ref_card_offset[channel] = ref_card_offset_table[dimm->dimm[channel][0].reference_card]
451 [dimm->dimm[channel][1].reference_card];
452 } else
453 ctrl->ref_card_offset[channel] = 0;
454 }
455
456 if (!dimms)
457 die("No DIMMs were found");
458}
459
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100460static void dram_find_common_params(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700461{
462 size_t valid_dimms;
463 int channel, slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100464 dimm_info *dimms = &ctrl->info;
465
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700466 ctrl->cas_supported = 0xff;
467 valid_dimms = 0;
468 FOR_ALL_CHANNELS for (slot = 0; slot < 2; slot++) {
469 const dimm_attr *dimm = &dimms->dimm[channel][slot];
470 if (dimm->dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3)
471 continue;
472 valid_dimms++;
473
474 /* Find all possible CAS combinations */
475 ctrl->cas_supported &= dimm->cas_supported;
476
477 /* Find the smallest common latencies supported by all DIMMs */
478 ctrl->tCK = MAX(ctrl->tCK, dimm->tCK);
479 ctrl->tAA = MAX(ctrl->tAA, dimm->tAA);
480 ctrl->tWR = MAX(ctrl->tWR, dimm->tWR);
481 ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD);
482 ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD);
483 ctrl->tRP = MAX(ctrl->tRP, dimm->tRP);
484 ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS);
485 ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC);
486 ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR);
487 ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP);
488 ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW);
489 }
490
491 if (!ctrl->cas_supported)
492 die("Unsupported DIMM combination. "
493 "DIMMS do not support common CAS latency");
494 if (!valid_dimms)
495 die("No valid DIMMs found");
496}
497
Patrick Rudolphbec66962016-11-11 19:17:56 +0100498/* CAS write latency. To be programmed in MR2.
499 * See DDR3 SPEC for MR2 documentation. */
500static u8 get_CWL(u32 tCK)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700501{
Patrick Rudolphbec66962016-11-11 19:17:56 +0100502 /* Get CWL based on tCK using the following rule: */
503 switch (tCK) {
504 case TCK_1333MHZ:
505 return 12;
506 case TCK_1200MHZ:
507 case TCK_1100MHZ:
508 return 11;
509 case TCK_1066MHZ:
510 case TCK_1000MHZ:
511 return 10;
512 case TCK_933MHZ:
513 case TCK_900MHZ:
514 return 9;
515 case TCK_800MHZ:
516 case TCK_700MHZ:
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700517 return 8;
Patrick Rudolphbec66962016-11-11 19:17:56 +0100518 case TCK_666MHZ:
519 return 7;
520 case TCK_533MHZ:
521 return 6;
522 default:
523 return 5;
524 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700525}
526
527/* Frequency multiplier. */
528static u32 get_FRQ(u32 tCK)
529{
530 u32 FRQ;
531 FRQ = 256000 / (tCK * BASEFREQ);
532 if (FRQ > 8)
533 return 8;
534 if (FRQ < 3)
535 return 3;
536 return FRQ;
537}
538
539static u32 get_REFI(u32 tCK)
540{
541 /* Get REFI based on MCU frequency using the following rule:
542 * _________________________________________
543 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
544 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 |
545 */
546 static const u32 frq_refi_map[] =
547 { 3120, 4160, 5200, 6240, 7280, 8320 };
548 return frq_refi_map[get_FRQ(tCK) - 3];
549}
550
551static u8 get_XSOffset(u32 tCK)
552{
553 /* Get XSOffset based on MCU frequency using the following rule:
554 * _________________________
555 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
556 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 |
557 */
558 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 };
559 return frq_xs_map[get_FRQ(tCK) - 3];
560}
561
562static u8 get_MOD(u32 tCK)
563{
564 /* Get MOD based on MCU frequency using the following rule:
565 * _____________________________
566 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
567 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 |
568 */
569 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 };
570 return frq_mod_map[get_FRQ(tCK) - 3];
571}
572
573static u8 get_WLO(u32 tCK)
574{
575 /* Get WLO based on MCU frequency using the following rule:
576 * _______________________
577 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
578 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 |
579 */
580 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 };
581 return frq_wlo_map[get_FRQ(tCK) - 3];
582}
583
584static u8 get_CKE(u32 tCK)
585{
586 /* Get CKE based on MCU frequency using the following rule:
587 * _______________________
588 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
589 * CKE : | 3 | 3 | 4 | 4 | 5 | 6 |
590 */
591 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 };
592 return frq_cke_map[get_FRQ(tCK) - 3];
593}
594
595static u8 get_XPDLL(u32 tCK)
596{
597 /* Get XPDLL based on MCU frequency using the following rule:
598 * _____________________________
599 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
600 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 |
601 */
602 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 };
603 return frq_xpdll_map[get_FRQ(tCK) - 3];
604}
605
606static u8 get_XP(u32 tCK)
607{
608 /* Get XP based on MCU frequency using the following rule:
609 * _______________________
610 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
611 * XP : | 3 | 4 | 4 | 5 | 6 | 7 |
612 */
613 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 };
614 return frq_xp_map[get_FRQ(tCK) - 3];
615}
616
617static u8 get_AONPD(u32 tCK)
618{
619 /* Get AONPD based on MCU frequency using the following rule:
620 * ________________________
621 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
622 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 |
623 */
624 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 };
625 return frq_aonpd_map[get_FRQ(tCK) - 3];
626}
627
628static u32 get_COMP2(u32 tCK)
629{
630 /* Get COMP2 based on MCU frequency using the following rule:
631 * ___________________________________________________________
632 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
633 * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C |
634 */
635 static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C,
636 0xC6369CC, 0xC42514C, 0xC21410C
637 };
638 return frq_comp2_map[get_FRQ(tCK) - 3];
639}
640
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100641static u32 get_XOVER_CLK(u8 rankmap)
642{
643 return rankmap << 24;
644}
645
646static u32 get_XOVER_CMD(u8 rankmap)
647{
648 u32 reg;
649
650 // enable xover cmd
651 reg = 0x4000;
652
653 // enable xover ctl
654 if (rankmap & 0x3)
655 reg |= 0x20000;
656
657 if (rankmap & 0xc)
658 reg |= 0x4000000;
659
660 return reg;
661}
662
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700663static void dram_timing(ramctr_timing * ctrl)
664{
665 u8 val;
666 u32 val32;
667
668 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
669 * we cap it if we have faster DIMMs.
670 * Then, align it to the closest JEDEC standard frequency */
671 if (ctrl->tCK <= TCK_1066MHZ) {
672 ctrl->tCK = TCK_1066MHZ;
673 ctrl->edge_offset[0] = 16;
674 ctrl->edge_offset[1] = 7;
675 ctrl->edge_offset[2] = 7;
676 ctrl->timC_offset[0] = 18;
677 ctrl->timC_offset[1] = 7;
678 ctrl->timC_offset[2] = 7;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700679 ctrl->reg_320c_range_threshold = 13;
680 } else if (ctrl->tCK <= TCK_933MHZ) {
681 ctrl->tCK = TCK_933MHZ;
682 ctrl->edge_offset[0] = 14;
683 ctrl->edge_offset[1] = 6;
684 ctrl->edge_offset[2] = 6;
685 ctrl->timC_offset[0] = 15;
686 ctrl->timC_offset[1] = 6;
687 ctrl->timC_offset[2] = 6;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700688 ctrl->reg_320c_range_threshold = 15;
689 } else if (ctrl->tCK <= TCK_800MHZ) {
690 ctrl->tCK = TCK_800MHZ;
691 ctrl->edge_offset[0] = 13;
692 ctrl->edge_offset[1] = 5;
693 ctrl->edge_offset[2] = 5;
694 ctrl->timC_offset[0] = 14;
695 ctrl->timC_offset[1] = 5;
696 ctrl->timC_offset[2] = 5;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700697 ctrl->reg_320c_range_threshold = 15;
698 } else if (ctrl->tCK <= TCK_666MHZ) {
699 ctrl->tCK = TCK_666MHZ;
700 ctrl->edge_offset[0] = 10;
701 ctrl->edge_offset[1] = 4;
702 ctrl->edge_offset[2] = 4;
703 ctrl->timC_offset[0] = 11;
704 ctrl->timC_offset[1] = 4;
705 ctrl->timC_offset[2] = 4;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700706 ctrl->reg_320c_range_threshold = 16;
707 } else if (ctrl->tCK <= TCK_533MHZ) {
708 ctrl->tCK = TCK_533MHZ;
709 ctrl->edge_offset[0] = 8;
710 ctrl->edge_offset[1] = 3;
711 ctrl->edge_offset[2] = 3;
712 ctrl->timC_offset[0] = 9;
713 ctrl->timC_offset[1] = 3;
714 ctrl->timC_offset[2] = 3;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700715 ctrl->reg_320c_range_threshold = 17;
716 } else {
717 ctrl->tCK = TCK_400MHZ;
718 ctrl->edge_offset[0] = 6;
719 ctrl->edge_offset[1] = 2;
720 ctrl->edge_offset[2] = 2;
721 ctrl->timC_offset[0] = 6;
722 ctrl->timC_offset[1] = 2;
723 ctrl->timC_offset[2] = 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700724 ctrl->reg_320c_range_threshold = 17;
725 }
726
Patrick Rudolphd4c53e32016-06-14 20:07:32 +0200727 /* Initial phase between CLK/CMD pins */
728 ctrl->reg_c14_offset = (256000 / ctrl->tCK) / 66;
729
Patrick Rudolphb7b1b282016-06-14 18:44:28 +0200730 /* DLL_CONFIG_MDLL_W_TIMER */
731 ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3;
732
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700733 val32 = (1000 << 8) / ctrl->tCK;
734 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
735
Patrick Rudolphbec66962016-11-11 19:17:56 +0100736 /* Find CAS latency */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700737 val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK;
738 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
739 /* Find lowest supported CAS latency that satisfies the minimum value */
740 while (!((ctrl->cas_supported >> (val - 4)) & 1)
741 && (ctrl->cas_supported >> (val - 4))) {
742 val++;
743 }
744 /* Is CAS supported */
Patrick Rudolph55409eb2016-06-15 20:28:32 +0200745 if (!(ctrl->cas_supported & (1 << (val - 4)))) {
746 printk(BIOS_ERR, "CAS %uT not supported. ", val);
747 val = 18;
748 /* Find highest supported CAS latency */
749 while (!((ctrl->cas_supported >> (val - 4)) & 1))
750 val--;
751
752 printk(BIOS_ERR, "Using CAS %uT instead.\n", val);
753 }
754
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700755 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
756 ctrl->CAS = val;
Patrick Rudolphbec66962016-11-11 19:17:56 +0100757 ctrl->CWL = get_CWL(ctrl->tCK);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700758 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
759
760 /* Find tRCD */
761 ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK;
762 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
763
764 ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK;
765 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
766
767 /* Find tRAS */
768 ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK;
769 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
770
771 /* Find tWR */
772 ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK;
773 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
774
775 /* Find tFAW */
776 ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK;
777 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
778
779 /* Find tRRD */
780 ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK;
781 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
782
783 /* Find tRTP */
784 ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK;
785 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
786
787 /* Find tWTR */
788 ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK;
789 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
790
791 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
792 ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK;
793 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
794
795 ctrl->tREFI = get_REFI(ctrl->tCK);
796 ctrl->tMOD = get_MOD(ctrl->tCK);
797 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
798 ctrl->tWLO = get_WLO(ctrl->tCK);
799 ctrl->tCKE = get_CKE(ctrl->tCK);
800 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
801 ctrl->tXP = get_XP(ctrl->tCK);
802 ctrl->tAONPD = get_AONPD(ctrl->tCK);
803}
804
805static void dram_freq(ramctr_timing * ctrl)
806{
807 if (ctrl->tCK > TCK_400MHZ) {
808 printk (BIOS_ERR, "DRAM frequency is under lowest supported frequency (400 MHz). Increasing to 400 MHz as last resort");
809 ctrl->tCK = TCK_400MHZ;
810 }
811 while (1) {
812 u8 val2;
813 u32 reg1 = 0;
814
815 /* Step 1 - Set target PCU frequency */
816
817 if (ctrl->tCK <= TCK_1066MHZ) {
818 ctrl->tCK = TCK_1066MHZ;
819 } else if (ctrl->tCK <= TCK_933MHZ) {
820 ctrl->tCK = TCK_933MHZ;
821 } else if (ctrl->tCK <= TCK_800MHZ) {
822 ctrl->tCK = TCK_800MHZ;
823 } else if (ctrl->tCK <= TCK_666MHZ) {
824 ctrl->tCK = TCK_666MHZ;
825 } else if (ctrl->tCK <= TCK_533MHZ) {
826 ctrl->tCK = TCK_533MHZ;
827 } else if (ctrl->tCK <= TCK_400MHZ) {
828 ctrl->tCK = TCK_400MHZ;
829 } else {
830 die ("No lock frequency found");
831 }
832
833 /* Frequency mulitplier. */
834 u32 FRQ = get_FRQ(ctrl->tCK);
835
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100836 /* The PLL will never lock if the required frequency is
837 * already set. Exit early to prevent a system hang.
838 */
Patrick Rudolph069018d2016-11-12 11:43:59 +0100839 reg1 = MCHBAR32(MC_BIOS_DATA);
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100840 val2 = (u8) reg1;
Patrick Rudolphf7047542016-11-12 11:39:57 +0100841 if (val2)
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100842 return;
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100843
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700844 /* Step 2 - Select frequency in the MCU */
845 reg1 = FRQ;
846 reg1 |= 0x80000000; // set running bit
Patrick Rudolph069018d2016-11-12 11:43:59 +0100847 MCHBAR32(MC_BIOS_REQ) = reg1;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700848 while (reg1 & 0x80000000) {
849 printk(BIOS_DEBUG, " PLL busy...");
Patrick Rudolph069018d2016-11-12 11:43:59 +0100850 reg1 = MCHBAR32(MC_BIOS_REQ);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700851 }
852 printk(BIOS_DEBUG, "done\n");
853
854 /* Step 3 - Verify lock frequency */
Patrick Rudolph069018d2016-11-12 11:43:59 +0100855 reg1 = MCHBAR32(MC_BIOS_DATA);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700856 val2 = (u8) reg1;
857 if (val2 >= FRQ) {
858 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
859 (1000 << 8) / ctrl->tCK);
860 return;
861 }
862 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
863 ctrl->tCK++;
864 }
865}
866
867static void dram_xover(ramctr_timing * ctrl)
868{
869 u32 reg;
870 int channel;
871
872 FOR_ALL_CHANNELS {
873 // enable xover clk
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100874 reg = get_XOVER_CLK(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100875 printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
876 reg);
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100877 MCHBAR32(channel * 0x100 + 0xc14) = reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700878
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100879 // enable xover ctl & xover cmd
880 reg = get_XOVER_CMD(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100881 printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
882 reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700883 MCHBAR32(0x100 * channel + 0x320c) = reg;
884 }
885}
886
887static void dram_timing_regs(ramctr_timing * ctrl)
888{
889 u32 reg, addr, val32, cpu, stretch;
890 struct cpuid_result cpures;
891 int channel;
892
893 FOR_ALL_CHANNELS {
894 // DBP
895 reg = 0;
896 reg |= ctrl->tRCD;
897 reg |= (ctrl->tRP << 4);
898 reg |= (ctrl->CAS << 8);
899 reg |= (ctrl->CWL << 12);
900 reg |= (ctrl->tRAS << 16);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100901 printram("DBP [%x] = %x\n", 0x400 * channel + 0x4000, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700902 MCHBAR32(0x400 * channel + 0x4000) = reg;
903
904 // RAP
905 reg = 0;
906 reg |= ctrl->tRRD;
907 reg |= (ctrl->tRTP << 4);
908 reg |= (ctrl->tCKE << 8);
909 reg |= (ctrl->tWTR << 12);
910 reg |= (ctrl->tFAW << 16);
911 reg |= (ctrl->tWR << 24);
912 reg |= (3 << 30);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100913 printram("RAP [%x] = %x\n", 0x400 * channel + 0x4004, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700914 MCHBAR32(0x400 * channel + 0x4004) = reg;
915
916 // OTHP
917 addr = 0x400 * channel + 0x400c;
918 reg = 0;
919 reg |= ctrl->tXPDLL;
920 reg |= (ctrl->tXP << 5);
921 reg |= (ctrl->tAONPD << 8);
922 reg |= 0xa0000;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100923 printram("OTHP [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700924 MCHBAR32(addr) = reg;
925
926 MCHBAR32(0x400 * channel + 0x4014) = 0;
927
928 MCHBAR32(addr) |= 0x00020000;
929
930 // ODT stretch
931 reg = 0;
932
Ryan Salsamendie4da9aa2016-06-24 12:01:11 -0700933 cpures = cpuid(1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700934 cpu = cpures.eax;
935 if (IS_IVY_CPU(cpu)
936 || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) {
937 stretch = 2;
938 addr = 0x400 * channel + 0x400c;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100939 printram("ODT stretch [%x] = %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700940 0x400 * channel + 0x400c, reg);
941 reg = MCHBAR32(addr);
942
943 if (((ctrl->rankmap[channel] & 3) == 0)
944 || (ctrl->rankmap[channel] & 0xc) == 0) {
945
946 // Rank 0 - operate on rank 2
947 reg = (reg & ~0xc0000) | (stretch << 18);
948
949 // Rank 2 - operate on rank 0
950 reg = (reg & ~0x30000) | (stretch << 16);
951
Patrick Rudolpha649a542016-01-17 18:32:06 +0100952 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700953 MCHBAR32(addr) = reg;
954 }
955
956 } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) {
957 stretch = 3;
958 addr = 0x400 * channel + 0x401c;
959 reg = MCHBAR32(addr);
960
961 if (((ctrl->rankmap[channel] & 3) == 0)
962 || (ctrl->rankmap[channel] & 0xc) == 0) {
963
964 // Rank 0 - operate on rank 2
965 reg = (reg & ~0x3000) | (stretch << 12);
966
967 // Rank 2 - operate on rank 0
968 reg = (reg & ~0xc00) | (stretch << 10);
969
Patrick Rudolpha649a542016-01-17 18:32:06 +0100970 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700971 MCHBAR32(addr) = reg;
972 }
973 } else {
974 stretch = 0;
975 }
976
977 // REFI
978 reg = 0;
979 val32 = ctrl->tREFI;
980 reg = (reg & ~0xffff) | val32;
981 val32 = ctrl->tRFC;
982 reg = (reg & ~0x1ff0000) | (val32 << 16);
983 val32 = (u32) (ctrl->tREFI * 9) / 1024;
984 reg = (reg & ~0xfe000000) | (val32 << 25);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100985 printram("REFI [%x] = %x\n", 0x400 * channel + 0x4298,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700986 reg);
987 MCHBAR32(0x400 * channel + 0x4298) = reg;
988
989 MCHBAR32(0x400 * channel + 0x4294) |= 0xff;
990
991 // SRFTP
992 reg = 0;
993 val32 = tDLLK;
994 reg = (reg & ~0xfff) | val32;
995 val32 = ctrl->tXSOffset;
996 reg = (reg & ~0xf000) | (val32 << 12);
997 val32 = tDLLK - ctrl->tXSOffset;
998 reg = (reg & ~0x3ff0000) | (val32 << 16);
999 val32 = ctrl->tMOD - 8;
1000 reg = (reg & ~0xf0000000) | (val32 << 28);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001001 printram("SRFTP [%x] = %x\n", 0x400 * channel + 0x42a4,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001002 reg);
1003 MCHBAR32(0x400 * channel + 0x42a4) = reg;
1004 }
1005}
1006
Patrick Rudolph735ecce2016-03-26 10:42:27 +01001007static void dram_dimm_mapping(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001008{
1009 u32 reg, val32;
1010 int channel;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01001011 dimm_info *info = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001012
1013 FOR_ALL_CHANNELS {
1014 dimm_attr *dimmA = 0;
1015 dimm_attr *dimmB = 0;
1016 reg = 0;
1017 val32 = 0;
1018 if (info->dimm[channel][0].size_mb >=
1019 info->dimm[channel][1].size_mb) {
1020 // dimm 0 is bigger, set it to dimmA
1021 dimmA = &info->dimm[channel][0];
1022 dimmB = &info->dimm[channel][1];
1023 reg |= (0 << 16);
1024 } else {
1025 // dimm 1 is bigger, set it to dimmA
1026 dimmA = &info->dimm[channel][1];
1027 dimmB = &info->dimm[channel][0];
1028 reg |= (1 << 16);
1029 }
1030 // dimmA
1031 if (dimmA && (dimmA->ranks > 0)) {
1032 val32 = dimmA->size_mb / 256;
1033 reg = (reg & ~0xff) | val32;
1034 val32 = dimmA->ranks - 1;
1035 reg = (reg & ~0x20000) | (val32 << 17);
1036 val32 = (dimmA->width / 8) - 1;
1037 reg = (reg & ~0x80000) | (val32 << 19);
1038 }
1039 // dimmB
1040 if (dimmB && (dimmB->ranks > 0)) {
1041 val32 = dimmB->size_mb / 256;
1042 reg = (reg & ~0xff00) | (val32 << 8);
1043 val32 = dimmB->ranks - 1;
1044 reg = (reg & ~0x40000) | (val32 << 18);
1045 val32 = (dimmB->width / 8) - 1;
1046 reg = (reg & ~0x100000) | (val32 << 20);
1047 }
1048 reg = (reg & ~0x200000) | (1 << 21); // rank interleave
1049 reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave
1050
1051 // Save MAD-DIMM register
1052 if ((dimmA && (dimmA->ranks > 0))
1053 || (dimmB && (dimmB->ranks > 0))) {
1054 ctrl->mad_dimm[channel] = reg;
1055 } else {
1056 ctrl->mad_dimm[channel] = 0;
1057 }
1058 }
1059}
1060
1061static void dram_dimm_set_mapping(ramctr_timing * ctrl)
1062{
1063 int channel;
1064 FOR_ALL_CHANNELS {
1065 MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
1066 }
1067}
1068
1069static void dram_zones(ramctr_timing * ctrl, int training)
1070{
1071 u32 reg, ch0size, ch1size;
1072 u8 val;
1073 reg = 0;
1074 val = 0;
1075 if (training) {
1076 ch0size = ctrl->channel_size_mb[0] ? 256 : 0;
1077 ch1size = ctrl->channel_size_mb[1] ? 256 : 0;
1078 } else {
1079 ch0size = ctrl->channel_size_mb[0];
1080 ch1size = ctrl->channel_size_mb[1];
1081 }
1082
1083 if (ch0size >= ch1size) {
1084 reg = MCHBAR32(0x5014);
1085 val = ch1size / 256;
1086 reg = (reg & ~0xff000000) | val << 24;
1087 reg = (reg & ~0xff0000) | (2 * val) << 16;
1088 MCHBAR32(0x5014) = reg;
1089 MCHBAR32(0x5000) = 0x24;
1090 } else {
1091 reg = MCHBAR32(0x5014);
1092 val = ch0size / 256;
1093 reg = (reg & ~0xff000000) | val << 24;
1094 reg = (reg & ~0xff0000) | (2 * val) << 16;
1095 MCHBAR32(0x5014) = reg;
1096 MCHBAR32(0x5000) = 0x21;
1097 }
1098}
1099
1100static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
1101{
1102 u32 reg, val, reclaim;
1103 u32 tom, gfxstolen, gttsize;
1104 size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase,
1105 tsegbase, mestolenbase;
1106 size_t tsegbasedelta, remapbase, remaplimit;
1107 uint16_t ggc;
1108
Patrick Rudolph266a1f72016-06-09 18:13:34 +02001109 mmiosize = get_mmio_size();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001110
1111 ggc = pci_read_config16(NORTHBRIDGE, GGC);
1112 if (!(ggc & 2)) {
1113 gfxstolen = ((ggc >> 3) & 0x1f) * 32;
1114 gttsize = ((ggc >> 8) & 0x3);
1115 } else {
1116 gfxstolen = 0;
1117 gttsize = 0;
1118 }
1119
1120 tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
1121
1122 tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
1123
1124 mestolenbase = tom - me_uma_size;
1125
1126 toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
1127 tom - me_uma_size);
1128 gfxstolenbase = toludbase - gfxstolen;
1129 gttbase = gfxstolenbase - gttsize;
1130
1131 tsegbase = gttbase - tsegsize;
1132
1133 // Round tsegbase down to nearest address aligned to tsegsize
1134 tsegbasedelta = tsegbase & (tsegsize - 1);
1135 tsegbase &= ~(tsegsize - 1);
1136
1137 gttbase -= tsegbasedelta;
1138 gfxstolenbase -= tsegbasedelta;
1139 toludbase -= tsegbasedelta;
1140
Elyes HAOUAS15279a92016-07-28 21:05:26 +02001141 // Test if it is possible to reclaim a hole in the RAM addressing
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001142 if (tom - me_uma_size > toludbase) {
1143 // Reclaim is possible
1144 reclaim = 1;
1145 remapbase = MAX(4096, tom - me_uma_size);
1146 remaplimit =
1147 remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1;
1148 touudbase = remaplimit + 1;
1149 } else {
1150 // Reclaim not possible
1151 reclaim = 0;
1152 touudbase = tom - me_uma_size;
1153 }
1154
1155 // Update memory map in pci-e configuration space
Patrick Rudolpha649a542016-01-17 18:32:06 +01001156 printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001157
1158 // TOM (top of memory)
1159 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0);
1160 val = tom & 0xfff;
1161 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001162 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001163 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg);
1164
1165 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4);
1166 val = tom & 0xfffff000;
1167 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001168 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001169 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg);
1170
1171 // TOLUD (top of low used dram)
1172 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
1173 val = toludbase & 0xfff;
1174 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001175 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xbc, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001176 pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg);
1177
1178 // TOUUD LSB (top of upper usable dram)
1179 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
1180 val = touudbase & 0xfff;
1181 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001182 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001183 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg);
1184
1185 // TOUUD MSB
1186 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
1187 val = touudbase & 0xfffff000;
1188 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001189 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xac, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001190 pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg);
1191
1192 if (reclaim) {
1193 // REMAP BASE
1194 pcie_write_config32(PCI_DEV(0, 0, 0), 0x90, remapbase << 20);
1195 pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, remapbase >> 12);
1196
1197 // REMAP LIMIT
1198 pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
1199 pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
1200 }
1201 // TSEG
1202 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
1203 val = tsegbase & 0xfff;
1204 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001205 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001206 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg);
1207
1208 // GFX stolen memory
1209 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0);
1210 val = gfxstolenbase & 0xfff;
1211 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001212 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001213 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg);
1214
1215 // GTT stolen memory
1216 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4);
1217 val = gttbase & 0xfff;
1218 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001219 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001220 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
1221
1222 if (me_uma_size) {
1223 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
1224 val = (0x80000 - me_uma_size) & 0xfffff000;
1225 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001226 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x7c, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001227 pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg);
1228
1229 // ME base
1230 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70);
1231 val = mestolenbase & 0xfff;
1232 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001233 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x70, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001234 pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg);
1235
1236 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74);
1237 val = mestolenbase & 0xfffff000;
1238 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001239 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x74, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001240 pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg);
1241
1242 // ME mask
1243 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78);
1244 val = (0x80000 - me_uma_size) & 0xfff;
1245 reg = (reg & ~0xfff00000) | (val << 20);
1246 reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem
1247
1248 reg = (reg & ~0x800) | (1 << 11); // set ME memory enable
Patrick Rudolpha649a542016-01-17 18:32:06 +01001249 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x78, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001250 pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg);
1251 }
1252}
1253
1254static void dram_ioregs(ramctr_timing * ctrl)
1255{
1256 u32 reg, comp2;
1257
1258 int channel;
1259
1260 // IO clock
1261 FOR_ALL_CHANNELS {
1262 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
1263 }
1264
1265 // IO command
1266 FOR_ALL_CHANNELS {
1267 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
1268 }
1269
1270 // IO control
1271 FOR_ALL_POPULATED_CHANNELS {
1272 program_timings(ctrl, channel);
1273 }
1274
1275 // Rcomp
Patrick Rudolpha649a542016-01-17 18:32:06 +01001276 printram("RCOMP...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001277 reg = 0;
1278 while (reg == 0) {
1279 reg = MCHBAR32(0x5084) & 0x10000;
1280 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001281 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001282
1283 // Set comp2
1284 comp2 = get_COMP2(ctrl->tCK);
1285 MCHBAR32(0x3714) = comp2;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001286 printram("COMP2 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001287
1288 // Set comp1
1289 FOR_ALL_POPULATED_CHANNELS {
1290 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
1291 reg = (reg & ~0xe00) | (1 << 9); //odt
1292 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
1293 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
1294 MCHBAR32(0x1810 + channel * 0x100) = reg;
1295 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001296 printram("COMP1 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001297
Patrick Rudolpha649a542016-01-17 18:32:06 +01001298 printram("FORCE RCOMP and wait 20us...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001299 MCHBAR32(0x5f08) |= 0x100;
1300 udelay(20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001301 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001302}
1303
1304static void wait_428c(int channel)
1305{
1306 while (1) {
1307 if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
1308 return;
1309 }
1310}
1311
1312static void write_reset(ramctr_timing * ctrl)
1313{
1314 int channel, slotrank;
1315
1316 /* choose a populated channel. */
1317 channel = (ctrl->rankmap[0]) ? 0 : 1;
1318
1319 wait_428c(channel);
1320
1321 /* choose a populated rank. */
1322 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
1323
Patrick Rudolph371d2912015-10-09 13:33:25 +02001324 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001325 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1326 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01);
1327
1328 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1329 (slotrank << 24) | 0x60000);
1330
1331 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1332
1333 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001);
1334 wait_428c(channel);
1335}
1336
1337static void dram_jedecreset(ramctr_timing * ctrl)
1338{
1339 u32 reg, addr;
1340 int channel;
1341
Elyes HAOUAS7db506c2016-10-02 11:56:39 +02001342 while (!(MCHBAR32(0x5084) & 0x10000));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001343 do {
1344 reg = MCHBAR32(0x428c);
1345 } while ((reg & 0x14) == 0);
1346
1347 // Set state of memory controller
1348 reg = 0x112;
1349 MCHBAR32(0x5030) = reg;
1350 MCHBAR32(0x4ea0) = 0;
1351 reg |= 2; //ddr reset
1352 MCHBAR32(0x5030) = reg;
1353
1354 // Assert dimm reset signal
1355 reg = MCHBAR32(0x5030);
1356 reg &= ~0x2;
1357 MCHBAR32(0x5030) = reg;
1358
1359 // Wait 200us
1360 udelay(200);
1361
1362 // Deassert dimm reset signal
1363 MCHBAR32(0x5030) |= 2;
1364
1365 // Wait 500us
1366 udelay(500);
1367
1368 // Enable DCLK
1369 MCHBAR32(0x5030) |= 4;
1370
1371 // XXX Wait 20ns
1372 udelay(1);
1373
1374 FOR_ALL_CHANNELS {
1375 // Set valid rank CKE
1376 reg = 0;
1377 reg = (reg & ~0xf) | ctrl->rankmap[channel];
1378 addr = 0x400 * channel + 0x42a0;
1379 MCHBAR32(addr) = reg;
1380
1381 // Wait 10ns for ranks to settle
1382 //udelay(0.01);
1383
1384 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
1385 MCHBAR32(addr) = reg;
1386
1387 // Write reset using a NOP
1388 write_reset(ctrl);
1389 }
1390}
1391
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001392static odtmap get_ODT(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001393{
1394 /* Get ODT based on rankmap: */
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001395 int dimms_per_ch = (ctrl->rankmap[channel] & 1)
1396 + ((ctrl->rankmap[channel] >> 2) & 1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001397
1398 if (dimms_per_ch == 1) {
1399 return (const odtmap){60, 60};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001400 } else {
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001401 return (const odtmap){120, 30};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001402 }
1403}
1404
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001405static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001406 int reg, u32 val)
1407{
1408 wait_428c(channel);
1409
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001410 if (ctrl->rank_mirror[channel][slotrank]) {
1411 /* DDR3 Rank1 Address mirror
1412 * swap the following pins:
1413 * A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 */
1414 reg = ((reg >> 1) & 1) | ((reg << 1) & 2);
1415 val = (val & ~0x1f8) | ((val >> 1) & 0xa8)
1416 | ((val & 0xa8) << 1);
1417 }
1418
Patrick Rudolph371d2912015-10-09 13:33:25 +02001419 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001420 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000);
1421 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
1422 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1423 (slotrank << 24) | (reg << 20) | val | 0x60000);
1424 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1425
Patrick Rudolph371d2912015-10-09 13:33:25 +02001426 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001427 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000);
1428 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001);
1429 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
1430 (slotrank << 24) | (reg << 20) | val | 0x60000);
1431 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1432
Patrick Rudolph371d2912015-10-09 13:33:25 +02001433 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001434 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000);
1435 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1436 0x1001 | (ctrl->tMOD << 16));
1437 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1438 (slotrank << 24) | (reg << 20) | val | 0x60000);
1439 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1440 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
1441}
1442
1443static u32 make_mr0(ramctr_timing * ctrl, u8 rank)
1444{
1445 u16 mr0reg, mch_cas, mch_wr;
1446 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 +02001447
1448 /* DLL Reset - self clearing - set after CLK frequency has been changed */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001449 mr0reg = 0x100;
1450
1451 // Convert CAS to MCH register friendly
1452 if (ctrl->CAS < 12) {
1453 mch_cas = (u16) ((ctrl->CAS - 4) << 1);
1454 } else {
1455 mch_cas = (u16) (ctrl->CAS - 12);
1456 mch_cas = ((mch_cas << 1) | 0x1);
1457 }
1458
1459 // Convert tWR to MCH register friendly
1460 mch_wr = mch_wr_t[ctrl->tWR - 5];
1461
1462 mr0reg = (mr0reg & ~0x4) | (mch_cas & 0x1);
1463 mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3);
1464 mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001465
1466 // Precharge PD - Fast (desktop) 0x1 or slow (mobile) 0x0 - mostly power-saving feature
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001467 mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12);
1468 return mr0reg;
1469}
1470
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001471static void dram_mr0(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001472{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001473 write_mrreg(ctrl, channel, rank, 0,
1474 make_mr0(ctrl, rank));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001475}
1476
1477static u32 encode_odt(u32 odt)
1478{
1479 switch (odt) {
1480 case 30:
1481 return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4
1482 case 60:
1483 return (1 << 2); // RZQ/4
1484 case 120:
1485 return (1 << 6); // RZQ/2
1486 default:
1487 case 0:
1488 return 0;
1489 }
1490}
1491
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001492static u32 make_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001493{
1494 odtmap odt;
1495 u32 mr1reg;
1496
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001497 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001498 mr1reg = 0x2;
1499
1500 mr1reg |= encode_odt(odt.rttnom);
1501
1502 return mr1reg;
1503}
1504
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001505static void dram_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001506{
1507 u16 mr1reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001508
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001509 mr1reg = make_mr1(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001510
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001511 write_mrreg(ctrl, channel, rank, 1, mr1reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001512}
1513
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001514static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001515{
1516 u16 pasr, cwl, mr2reg;
1517 odtmap odt;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001518 int srt;
1519
1520 pasr = 0;
1521 cwl = ctrl->CWL - 5;
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001522 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001523
1524 srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh;
1525
1526 mr2reg = 0;
1527 mr2reg = (mr2reg & ~0x7) | pasr;
1528 mr2reg = (mr2reg & ~0x38) | (cwl << 3);
1529 mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6);
1530 mr2reg = (mr2reg & ~0x80) | (srt << 7);
1531 mr2reg |= (odt.rttwr / 60) << 9;
1532
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001533 write_mrreg(ctrl, channel, rank, 2, mr2reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001534}
1535
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001536static void dram_mr3(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001537{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001538 write_mrreg(ctrl, channel, rank, 3, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001539}
1540
1541static void dram_mrscommands(ramctr_timing * ctrl)
1542{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001543 u8 slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001544 u32 reg, addr;
1545 int channel;
1546
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001547 FOR_ALL_POPULATED_CHANNELS {
1548 FOR_ALL_POPULATED_RANKS {
1549 // MR2
1550 dram_mr2(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001551
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001552 // MR3
1553 dram_mr3(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001554
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001555 // MR1
1556 dram_mr1(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001557
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001558 // MR0
1559 dram_mr0(ctrl, slotrank, channel);
1560 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001561 }
1562
Patrick Rudolph371d2912015-10-09 13:33:25 +02001563 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001564 write32(DEFAULT_MCHBAR + 0x4e20, 0x7);
1565 write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001);
1566 write32(DEFAULT_MCHBAR + 0x4e00, 0x60002);
1567 write32(DEFAULT_MCHBAR + 0x4e10, 0);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001568
1569 /* DRAM command ZQCL */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001570 write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003);
1571 write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001);
1572 write32(DEFAULT_MCHBAR + 0x4e04, 0x60400);
1573 write32(DEFAULT_MCHBAR + 0x4e14, 0x288);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001574
1575 /* execute command queue on all channels ? */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001576 write32(DEFAULT_MCHBAR + 0x4e84, 0x40004);
1577
1578 // Drain
1579 FOR_ALL_CHANNELS {
1580 // Wait for ref drained
1581 wait_428c(channel);
1582 }
1583
1584 // Refresh enable
1585 MCHBAR32(0x5030) |= 8;
1586
1587 FOR_ALL_POPULATED_CHANNELS {
1588 addr = 0x400 * channel + 0x4020;
1589 reg = MCHBAR32(addr);
1590 reg &= ~0x200000;
1591 MCHBAR32(addr) = reg;
1592
1593 wait_428c(channel);
1594
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001595 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001596
1597 // Drain
1598 wait_428c(channel);
1599
Patrick Rudolph371d2912015-10-09 13:33:25 +02001600 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001601 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1602 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
1603 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001604 (slotrank << 24) | 0x60000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001605 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
1606 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1);
1607
1608 // Drain
1609 wait_428c(channel);
1610 }
1611}
1612
1613const u32 lane_registers[] = {
1614 0x0000, 0x0200, 0x0400, 0x0600,
1615 0x1000, 0x1200, 0x1400, 0x1600,
1616 0x0800
1617};
1618
1619static void program_timings(ramctr_timing * ctrl, int channel)
1620{
1621 u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028;
1622 int lane;
1623 int slotrank, slot;
1624 int full_shift = 0;
1625 u16 slot320c[NUM_SLOTS];
1626
1627 FOR_ALL_POPULATED_RANKS {
1628 if (full_shift < -ctrl->timings[channel][slotrank].val_320c)
1629 full_shift = -ctrl->timings[channel][slotrank].val_320c;
1630 }
1631
1632 for (slot = 0; slot < NUM_SLOTS; slot++)
1633 switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) {
1634 case 0:
1635 default:
1636 slot320c[slot] = 0x7f;
1637 break;
1638 case 1:
1639 slot320c[slot] =
1640 ctrl->timings[channel][2 * slot + 0].val_320c +
1641 full_shift;
1642 break;
1643 case 2:
1644 slot320c[slot] =
1645 ctrl->timings[channel][2 * slot + 1].val_320c +
1646 full_shift;
1647 break;
1648 case 3:
1649 slot320c[slot] =
1650 (ctrl->timings[channel][2 * slot].val_320c +
1651 ctrl->timings[channel][2 * slot +
1652 1].val_320c) / 2 +
1653 full_shift;
1654 break;
1655 }
1656
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001657 /* enable CMD XOVER */
1658 reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001659 reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
1660 reg32 |= (slot320c[1] & 0x7f) << 18;
1661 reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
1662
1663 MCHBAR32(0x320c + 0x100 * channel) = reg32;
1664
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001665 /* enable CLK XOVER */
1666 reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001667 reg_c18 = 0;
1668
1669 FOR_ALL_POPULATED_RANKS {
1670 int shift =
1671 ctrl->timings[channel][slotrank].val_320c + full_shift;
1672 int offset_val_c14;
1673 if (shift < 0)
1674 shift = 0;
1675 offset_val_c14 = ctrl->reg_c14_offset + shift;
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001676 /* set CLK phase shift */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001677 reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
1678 reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
1679 }
1680
1681 MCHBAR32(0xc14 + channel * 0x100) = reg_c14;
1682 MCHBAR32(0xc18 + channel * 0x100) = reg_c18;
1683
1684 reg_4028 = MCHBAR32(0x4028 + 0x400 * channel);
1685 reg_4028 &= 0xffff0000;
1686
1687 reg_4024 = 0;
1688
1689 FOR_ALL_POPULATED_RANKS {
1690 int post_timA_min_high = 7, post_timA_max_high = 0;
1691 int pre_timA_min_high = 7, pre_timA_max_high = 0;
1692 int shift_402x = 0;
1693 int shift =
1694 ctrl->timings[channel][slotrank].val_320c + full_shift;
1695
1696 if (shift < 0)
1697 shift = 0;
1698
1699 FOR_ALL_LANES {
1700 if (post_timA_min_high >
1701 ((ctrl->timings[channel][slotrank].lanes[lane].
1702 timA + shift) >> 6))
1703 post_timA_min_high =
1704 ((ctrl->timings[channel][slotrank].
1705 lanes[lane].timA + shift) >> 6);
1706 if (pre_timA_min_high >
1707 (ctrl->timings[channel][slotrank].lanes[lane].
1708 timA >> 6))
1709 pre_timA_min_high =
1710 (ctrl->timings[channel][slotrank].
1711 lanes[lane].timA >> 6);
1712 if (post_timA_max_high <
1713 ((ctrl->timings[channel][slotrank].lanes[lane].
1714 timA + shift) >> 6))
1715 post_timA_max_high =
1716 ((ctrl->timings[channel][slotrank].
1717 lanes[lane].timA + shift) >> 6);
1718 if (pre_timA_max_high <
1719 (ctrl->timings[channel][slotrank].lanes[lane].
1720 timA >> 6))
1721 pre_timA_max_high =
1722 (ctrl->timings[channel][slotrank].
1723 lanes[lane].timA >> 6);
1724 }
1725
1726 if (pre_timA_max_high - pre_timA_min_high <
1727 post_timA_max_high - post_timA_min_high)
1728 shift_402x = +1;
1729 else if (pre_timA_max_high - pre_timA_min_high >
1730 post_timA_max_high - post_timA_min_high)
1731 shift_402x = -1;
1732
1733 reg_4028 |=
1734 (ctrl->timings[channel][slotrank].val_4028 + shift_402x -
1735 post_timA_min_high) << (4 * slotrank);
1736 reg_4024 |=
1737 (ctrl->timings[channel][slotrank].val_4024 +
1738 shift_402x) << (8 * slotrank);
1739
1740 FOR_ALL_LANES {
1741 MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel +
1742 4 * slotrank)
1743 =
1744 (((ctrl->timings[channel][slotrank].lanes[lane].
1745 timA + shift) & 0x3f)
1746 |
1747 ((ctrl->timings[channel][slotrank].lanes[lane].
1748 rising + shift) << 8)
1749 |
1750 (((ctrl->timings[channel][slotrank].lanes[lane].
1751 timA + shift -
1752 (post_timA_min_high << 6)) & 0x1c0) << 10)
Patrick Rudolph0188b132016-02-10 19:16:34 +01001753 | ((ctrl->timings[channel][slotrank].lanes[lane].
1754 falling + shift) << 20));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001755
1756 MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel +
1757 4 * slotrank)
1758 =
1759 (((ctrl->timings[channel][slotrank].lanes[lane].
1760 timC + shift) & 0x3f)
1761 |
1762 (((ctrl->timings[channel][slotrank].lanes[lane].
1763 timB + shift) & 0x3f) << 8)
1764 |
1765 (((ctrl->timings[channel][slotrank].lanes[lane].
1766 timB + shift) & 0x1c0) << 9)
1767 |
1768 (((ctrl->timings[channel][slotrank].lanes[lane].
1769 timC + shift) & 0x40) << 13));
1770 }
1771 }
1772 MCHBAR32(0x4024 + 0x400 * channel) = reg_4024;
1773 MCHBAR32(0x4028 + 0x400 * channel) = reg_4028;
1774}
1775
1776static void test_timA(ramctr_timing * ctrl, int channel, int slotrank)
1777{
1778 wait_428c(channel);
1779
Patrick Rudolph371d2912015-10-09 13:33:25 +02001780 /* DRAM command MRS
1781 * write MR3 MPR enable
1782 * in this mode only RD and RDA are allowed
1783 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001784 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
1785 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1786 (0xc01 | (ctrl->tMOD << 16)));
1787 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1788 (slotrank << 24) | 0x360004);
1789 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1790
Patrick Rudolph371d2912015-10-09 13:33:25 +02001791 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001792 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
1793 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01);
1794 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24));
1795 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1796
Patrick Rudolph371d2912015-10-09 13:33:25 +02001797 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001798 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
1799 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1800 0x100f | ((ctrl->CAS + 36) << 16));
1801 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1802 (slotrank << 24) | 0x60000);
1803 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1804
Patrick Rudolph371d2912015-10-09 13:33:25 +02001805 /* DRAM command MRS
1806 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001807 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
1808 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
1809 (0xc01 | (ctrl->tMOD << 16)));
1810 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
1811 (slotrank << 24) | 0x360000);
1812 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
1813
1814 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
1815
1816 wait_428c(channel);
1817}
1818
1819static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank,
1820 int lane)
1821{
1822 u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA;
1823 return ((read32
1824 (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 +
1825 ((timA / 32) & 1) * 4)
1826 >> (timA % 32)) & 1);
1827}
1828
1829struct run {
1830 int middle;
1831 int end;
1832 int start;
1833 int all;
1834 int length;
1835};
1836
1837static struct run get_longest_zero_run(int *seq, int sz)
1838{
1839 int i, ls;
1840 int bl = 0, bs = 0;
1841 struct run ret;
1842
1843 ls = 0;
1844 for (i = 0; i < 2 * sz; i++)
1845 if (seq[i % sz]) {
1846 if (i - ls > bl) {
1847 bl = i - ls;
1848 bs = ls;
1849 }
1850 ls = i + 1;
1851 }
1852 if (bl == 0) {
1853 ret.middle = sz / 2;
1854 ret.start = 0;
1855 ret.end = sz;
1856 ret.all = 1;
1857 return ret;
1858 }
1859
1860 ret.start = bs % sz;
1861 ret.end = (bs + bl - 1) % sz;
1862 ret.middle = (bs + (bl - 1) / 2) % sz;
1863 ret.length = bl;
1864 ret.all = 0;
1865
1866 return ret;
1867}
1868
1869static void discover_timA_coarse(ramctr_timing * ctrl, int channel,
1870 int slotrank, int *upperA)
1871{
1872 int timA;
1873 int statistics[NUM_LANES][128];
1874 int lane;
1875
1876 for (timA = 0; timA < 128; timA++) {
1877 FOR_ALL_LANES {
1878 ctrl->timings[channel][slotrank].lanes[lane].timA = timA;
1879 }
1880 program_timings(ctrl, channel);
1881
1882 test_timA(ctrl, channel, slotrank);
1883
1884 FOR_ALL_LANES {
1885 statistics[lane][timA] =
1886 !does_lane_work(ctrl, channel, slotrank, lane);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001887 printram("Astat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001888 channel, slotrank, lane, timA,
1889 statistics[lane][timA]);
1890 }
1891 }
1892 FOR_ALL_LANES {
1893 struct run rn = get_longest_zero_run(statistics[lane], 128);
1894 ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle;
1895 upperA[lane] = rn.end;
1896 if (upperA[lane] < rn.middle)
1897 upperA[lane] += 128;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001898 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001899 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001900 printram("Aend: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001901 lane, upperA[lane]);
1902 }
1903}
1904
1905static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
1906 int *upperA)
1907{
1908 int timA_delta;
1909 int statistics[NUM_LANES][51];
1910 int lane, i;
1911
1912 memset(statistics, 0, sizeof(statistics));
1913
1914 for (timA_delta = -25; timA_delta <= 25; timA_delta++) {
1915 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
1916 timA = upperA[lane] + timA_delta + 0x40;
1917 program_timings(ctrl, channel);
1918
1919 for (i = 0; i < 100; i++) {
1920 test_timA(ctrl, channel, slotrank);
1921 FOR_ALL_LANES {
1922 statistics[lane][timA_delta + 25] +=
1923 does_lane_work(ctrl, channel, slotrank,
1924 lane);
1925 }
1926 }
1927 }
1928 FOR_ALL_LANES {
1929 int last_zero, first_all;
1930
1931 for (last_zero = -25; last_zero <= 25; last_zero++)
1932 if (statistics[lane][last_zero + 25])
1933 break;
1934 last_zero--;
1935 for (first_all = -25; first_all <= 25; first_all++)
1936 if (statistics[lane][first_all + 25] == 100)
1937 break;
1938
1939 printram("lane %d: %d, %d\n", lane, last_zero,
1940 first_all);
1941
1942 ctrl->timings[channel][slotrank].lanes[lane].timA =
1943 (last_zero + first_all) / 2 + upperA[lane];
Patrick Rudolpha649a542016-01-17 18:32:06 +01001944 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001945 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
1946 }
1947}
1948
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001949static int discover_402x(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001950 int *upperA)
1951{
1952 int works[NUM_LANES];
1953 int lane;
1954 while (1) {
1955 int all_works = 1, some_works = 0;
1956 program_timings(ctrl, channel);
1957 test_timA(ctrl, channel, slotrank);
1958 FOR_ALL_LANES {
1959 works[lane] =
1960 !does_lane_work(ctrl, channel, slotrank, lane);
1961 if (works[lane])
1962 some_works = 1;
1963 else
1964 all_works = 0;
1965 }
1966 if (all_works)
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001967 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001968 if (!some_works) {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001969 if (ctrl->timings[channel][slotrank].val_4024 < 2) {
1970 printk(BIOS_EMERG, "402x discovery failed (1): %d, %d\n",
1971 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001972 return MAKE_ERR;
1973 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001974 ctrl->timings[channel][slotrank].val_4024 -= 2;
1975 printram("4024 -= 2;\n");
1976 continue;
1977 }
1978 ctrl->timings[channel][slotrank].val_4028 += 2;
1979 printram("4028 += 2;\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001980 if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) {
1981 printk(BIOS_EMERG, "402x discovery failed (2): %d, %d\n",
1982 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001983 return MAKE_ERR;
1984 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001985 FOR_ALL_LANES if (works[lane]) {
1986 ctrl->timings[channel][slotrank].lanes[lane].timA +=
1987 128;
1988 upperA[lane] += 128;
1989 printram("increment %d, %d, %d\n", channel,
1990 slotrank, lane);
1991 }
1992 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001993 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001994}
1995
1996struct timA_minmax {
1997 int timA_min_high, timA_max_high;
1998};
1999
2000static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
2001 struct timA_minmax *mnmx)
2002{
2003 int lane;
2004 mnmx->timA_min_high = 7;
2005 mnmx->timA_max_high = 0;
2006
2007 FOR_ALL_LANES {
2008 if (mnmx->timA_min_high >
2009 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
2010 mnmx->timA_min_high =
2011 (ctrl->timings[channel][slotrank].lanes[lane].
2012 timA >> 6);
2013 if (mnmx->timA_max_high <
2014 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
2015 mnmx->timA_max_high =
2016 (ctrl->timings[channel][slotrank].lanes[lane].
2017 timA >> 6);
2018 }
2019}
2020
2021static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
2022 struct timA_minmax *mnmx)
2023{
2024 struct timA_minmax post;
2025 int shift_402x = 0;
2026
2027 /* Get changed maxima. */
2028 pre_timA_change(ctrl, channel, slotrank, &post);
2029
2030 if (mnmx->timA_max_high - mnmx->timA_min_high <
2031 post.timA_max_high - post.timA_min_high)
2032 shift_402x = +1;
2033 else if (mnmx->timA_max_high - mnmx->timA_min_high >
2034 post.timA_max_high - post.timA_min_high)
2035 shift_402x = -1;
2036 else
2037 shift_402x = 0;
2038
2039 ctrl->timings[channel][slotrank].val_4028 += shift_402x;
2040 ctrl->timings[channel][slotrank].val_4024 += shift_402x;
2041 printram("4024 += %d;\n", shift_402x);
2042 printram("4028 += %d;\n", shift_402x);
2043}
2044
Patrick Rudolph371d2912015-10-09 13:33:25 +02002045/* Compensate the skew between DQS and DQs.
2046 * To ease PCB design a small skew between Data Strobe signals and
2047 * Data Signals is allowed.
2048 * The controller has to measure and compensate this skew for every byte-lane.
2049 * By delaying either all DQs signals or DQS signal, a full phase
2050 * shift can be introduced.
2051 * It is assumed that one byte-lane's DQs signals have the same routing delay.
2052 *
2053 * To measure the actual skew, the DRAM is placed in "read leveling" mode.
2054 * In read leveling mode the DRAM-chip outputs an alternating periodic pattern.
2055 * The memory controller iterates over all possible values to do a full phase shift
2056 * and issues read commands.
2057 * With DQS and DQs in phase the data read is expected to alternate on every byte:
2058 * 0xFF 0x00 0xFF ...
2059 * Once the controller has detected this pattern a bit in the result register is
2060 * set for the current phase shift.
2061 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002062static int read_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002063{
2064 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002065 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002066
2067 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002068 int all_high, some_high;
2069 int upperA[NUM_LANES];
2070 struct timA_minmax mnmx;
2071
2072 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002073
2074 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002075 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2076 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2077 0xc01 | (ctrl->tRP << 16));
2078 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2079 (slotrank << 24) | 0x60400);
2080 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2081 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2082
2083 write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001);
2084
2085 ctrl->timings[channel][slotrank].val_4028 = 4;
2086 ctrl->timings[channel][slotrank].val_4024 = 55;
2087 program_timings(ctrl, channel);
2088
2089 discover_timA_coarse(ctrl, channel, slotrank, upperA);
2090
2091 all_high = 1;
2092 some_high = 0;
2093 FOR_ALL_LANES {
2094 if (ctrl->timings[channel][slotrank].lanes[lane].
2095 timA >= 0x40)
2096 some_high = 1;
2097 else
2098 all_high = 0;
2099 }
2100
2101 if (all_high) {
2102 ctrl->timings[channel][slotrank].val_4028--;
2103 printram("4028--;\n");
2104 FOR_ALL_LANES {
2105 ctrl->timings[channel][slotrank].lanes[lane].
2106 timA -= 0x40;
2107 upperA[lane] -= 0x40;
2108
2109 }
2110 } else if (some_high) {
2111 ctrl->timings[channel][slotrank].val_4024++;
2112 ctrl->timings[channel][slotrank].val_4028++;
2113 printram("4024++;\n");
2114 printram("4028++;\n");
2115 }
2116
2117 program_timings(ctrl, channel);
2118
2119 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2120
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002121 err = discover_402x(ctrl, channel, slotrank, upperA);
2122 if (err)
2123 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002124
2125 post_timA_change(ctrl, channel, slotrank, &mnmx);
2126 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2127
2128 discover_timA_fine(ctrl, channel, slotrank, upperA);
2129
2130 post_timA_change(ctrl, channel, slotrank, &mnmx);
2131 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2132
2133 FOR_ALL_LANES {
2134 ctrl->timings[channel][slotrank].lanes[lane].timA -= mnmx.timA_min_high * 0x40;
2135 }
2136 ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high;
2137 printram("4028 -= %d;\n", mnmx.timA_min_high);
2138
2139 post_timA_change(ctrl, channel, slotrank, &mnmx);
2140
2141 printram("4/8: %d, %d, %x, %x\n", channel, slotrank,
2142 ctrl->timings[channel][slotrank].val_4024,
2143 ctrl->timings[channel][slotrank].val_4028);
2144
Patrick Rudolpha649a542016-01-17 18:32:06 +01002145 printram("final results:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002146 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01002147 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002148 lane,
2149 ctrl->timings[channel][slotrank].lanes[lane].timA);
2150
2151 write32(DEFAULT_MCHBAR + 0x3400, 0);
2152
Patrick Rudolph9b515682015-10-09 13:43:51 +02002153 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002154 }
2155
2156 FOR_ALL_POPULATED_CHANNELS {
2157 program_timings(ctrl, channel);
2158 }
2159 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2160 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
2161 + 4 * lane, 0);
2162 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002163 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002164}
2165
2166static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
2167{
2168 int lane;
2169
2170 FOR_ALL_LANES {
2171 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0);
2172 read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane);
2173 }
2174
2175 wait_428c(channel);
2176
Patrick Rudolph371d2912015-10-09 13:33:25 +02002177 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002178 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2179 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2180 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
2181 | 4 | (ctrl->tRCD << 16));
2182
2183 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2184 (slotrank << 24) | (6 << 16));
2185
2186 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
2187
Patrick Rudolph371d2912015-10-09 13:33:25 +02002188 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002189 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2190 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001);
2191 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2192 (slotrank << 24) | 8);
2193 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2194
Patrick Rudolph371d2912015-10-09 13:33:25 +02002195 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002196 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2197 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4);
2198 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2199 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2200
Patrick Rudolph371d2912015-10-09 13:33:25 +02002201 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002202 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2203 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2204 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2205 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2206 (slotrank << 24) | 8);
2207 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2208
2209 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2210
2211 wait_428c(channel);
2212
Patrick Rudolph371d2912015-10-09 13:33:25 +02002213 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002214 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2215 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2216 0xc01 | (ctrl->tRP << 16));
2217 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2218 (slotrank << 24) | 0x60400);
2219 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2220
Patrick Rudolph371d2912015-10-09 13:33:25 +02002221 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002222 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2223 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2224 (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10)
2225 | 8 | (ctrl->CAS << 16));
2226
2227 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2228 (slotrank << 24) | 0x60000);
2229
2230 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244);
2231
Patrick Rudolph371d2912015-10-09 13:33:25 +02002232 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002233 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2234 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2235 0x40011f4 | (max(ctrl->tRTP, 8) << 16));
2236 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2237 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2238
Patrick Rudolph371d2912015-10-09 13:33:25 +02002239 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002240 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2241 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2242 0xc01 | (ctrl->tRP << 16));
2243 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2244 (slotrank << 24) | 0x60400);
2245 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2246 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2247 wait_428c(channel);
2248}
2249
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002250static int discover_timC(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002251{
2252 int timC;
2253 int statistics[NUM_LANES][MAX_TIMC + 1];
2254 int lane;
2255
2256 wait_428c(channel);
2257
Patrick Rudolph371d2912015-10-09 13:33:25 +02002258 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002259 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2260 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2261 0xc01 | (ctrl->tRP << 16));
2262 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2263 (slotrank << 24) | 0x60400);
2264 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2265 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2266
2267 for (timC = 0; timC <= MAX_TIMC; timC++) {
2268 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
2269 timC = timC;
2270 program_timings(ctrl, channel);
2271
2272 test_timC(ctrl, channel, slotrank);
2273
2274 FOR_ALL_LANES {
2275 statistics[lane][timC] =
2276 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2277 0x400 * channel);
2278 printram("Cstat: %d, %d, %d, %x, %x\n",
2279 channel, slotrank, lane, timC,
2280 statistics[lane][timC]);
2281 }
2282 }
2283 FOR_ALL_LANES {
2284 struct run rn =
2285 get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
2286 ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002287 if (rn.all) {
2288 printk(BIOS_EMERG, "timC discovery failed: %d, %d, %d\n",
2289 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002290 return MAKE_ERR;
2291 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002292 printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002293 lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
2294 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002295 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002296}
2297
2298static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
2299{
2300 int channel, ret = 0;
2301 FOR_ALL_POPULATED_CHANNELS if (channel < target_channel)
2302 ret++;
2303 return ret;
2304}
2305
2306static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b)
2307{
2308 unsigned j;
2309 unsigned channel_offset =
2310 get_precedening_channels(ctrl, channel) * 0x40;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002311 for (j = 0; j < 16; j++)
2312 write32((void *)(0x04000000 + channel_offset + 4 * j), j & 2 ? b : a);
2313 sfence();
2314}
2315
2316static int num_of_channels(const ramctr_timing * ctrl)
2317{
2318 int ret = 0;
2319 int channel;
2320 FOR_ALL_POPULATED_CHANNELS ret++;
2321 return ret;
2322}
2323
2324static void fill_pattern1(ramctr_timing * ctrl, int channel)
2325{
2326 unsigned j;
2327 unsigned channel_offset =
2328 get_precedening_channels(ctrl, channel) * 0x40;
2329 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2330 for (j = 0; j < 16; j++)
2331 write32((void *)(0x04000000 + channel_offset + j * 4), 0xffffffff);
2332 for (j = 0; j < 16; j++)
2333 write32((void *)(0x04000000 + channel_offset + channel_step + j * 4), 0);
2334 sfence();
2335}
2336
2337static void precharge(ramctr_timing * ctrl)
2338{
2339 int channel, slotrank, lane;
2340
2341 FOR_ALL_POPULATED_CHANNELS {
2342 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2343 ctrl->timings[channel][slotrank].lanes[lane].falling =
2344 16;
2345 ctrl->timings[channel][slotrank].lanes[lane].rising =
2346 16;
Patrick Rudolpha649a542016-01-17 18:32:06 +01002347 }
2348
2349 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002350
2351 FOR_ALL_POPULATED_RANKS {
2352 wait_428c(channel);
2353
Patrick Rudolph371d2912015-10-09 13:33:25 +02002354 /* DRAM command MRS
2355 * write MR3 MPR enable
2356 * in this mode only RD and RDA are allowed
2357 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002358 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2359 0x1f000);
2360 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2361 0xc01 | (ctrl->tMOD << 16));
2362 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2363 (slotrank << 24) | 0x360004);
2364 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2365
Patrick Rudolph371d2912015-10-09 13:33:25 +02002366 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002367 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2368 0x1f105);
2369 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2370 0x4041003);
2371 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2372 (slotrank << 24) | 0);
2373 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2374
Patrick Rudolph371d2912015-10-09 13:33:25 +02002375 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002376 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2377 0x1f105);
2378 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2379 0x1001 | ((ctrl->CAS + 8) << 16));
2380 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2381 (slotrank << 24) | 0x60000);
2382 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2383
Patrick Rudolph371d2912015-10-09 13:33:25 +02002384 /* DRAM command MRS
2385 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002386 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2387 0x1f000);
2388 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2389 0xc01 | (ctrl->tMOD << 16));
2390 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2391 (slotrank << 24) | 0x360000);
2392 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2393 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2394 0xc0001);
2395
2396 wait_428c(channel);
2397 }
2398
2399 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2400 ctrl->timings[channel][slotrank].lanes[lane].falling =
2401 48;
2402 ctrl->timings[channel][slotrank].lanes[lane].rising =
2403 48;
2404 }
2405
2406 program_timings(ctrl, channel);
2407
2408 FOR_ALL_POPULATED_RANKS {
2409 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002410 /* DRAM command MRS
2411 * write MR3 MPR enable
2412 * in this mode only RD and RDA are allowed
2413 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002414 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2415 0x1f000);
2416 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2417 0xc01 | (ctrl->tMOD << 16));
2418 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2419 (slotrank << 24) | 0x360004);
2420 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2421
Patrick Rudolph371d2912015-10-09 13:33:25 +02002422 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002423 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2424 0x1f105);
2425 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2426 0x4041003);
2427 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2428 (slotrank << 24) | 0);
2429 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2430
Patrick Rudolph371d2912015-10-09 13:33:25 +02002431 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002432 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2433 0x1f105);
2434 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2435 0x1001 | ((ctrl->CAS + 8) << 16));
2436 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2437 (slotrank << 24) | 0x60000);
2438 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2439
Patrick Rudolph371d2912015-10-09 13:33:25 +02002440 /* DRAM command MRS
2441 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002442 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2443 0x1f000);
2444 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2445 0xc01 | (ctrl->tMOD << 16));
2446
2447 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2448 (slotrank << 24) | 0x360000);
2449 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2450
2451 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2452 0xc0001);
2453 wait_428c(channel);
2454 }
2455 }
2456}
2457
2458static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
2459{
Patrick Rudolph371d2912015-10-09 13:33:25 +02002460 /* enable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002461 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002462 0x80 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002463
2464 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002465 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002466 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207);
2467 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2468 0x8000c01 | ((ctrl->CWL + ctrl->tWLO) << 16));
2469 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2470 8 | (slotrank << 24));
2471 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2472
Patrick Rudolph371d2912015-10-09 13:33:25 +02002473 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002474 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107);
2475 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2476 0x4000c01 | ((ctrl->CAS + 38) << 16));
2477 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2478 (slotrank << 24) | 4);
2479 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2480
2481 write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001);
2482 wait_428c(channel);
2483
Patrick Rudolph371d2912015-10-09 13:33:25 +02002484 /* disable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002485 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002486 0x1080 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002487}
2488
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002489static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002490{
2491 int timB;
2492 int statistics[NUM_LANES][128];
2493 int lane;
2494
2495 write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2));
2496
2497 for (timB = 0; timB < 128; timB++) {
2498 FOR_ALL_LANES {
2499 ctrl->timings[channel][slotrank].lanes[lane].timB = timB;
2500 }
2501 program_timings(ctrl, channel);
2502
2503 test_timB(ctrl, channel, slotrank);
2504
2505 FOR_ALL_LANES {
2506 statistics[lane][timB] =
2507 !((read32
2508 (DEFAULT_MCHBAR + lane_registers[lane] +
2509 channel * 0x100 + 4 + ((timB / 32) & 1) * 4)
2510 >> (timB % 32)) & 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002511 printram("Bstat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002512 channel, slotrank, lane, timB,
2513 statistics[lane][timB]);
2514 }
2515 }
2516 FOR_ALL_LANES {
2517 struct run rn = get_longest_zero_run(statistics[lane], 128);
Patrick Rudolphd912f1d2016-02-15 20:07:42 +01002518 /* timC is a direct function of timB's 6 LSBs.
2519 * Some tests increments the value of timB by a small value,
2520 * which might cause the 6bit value to overflow, if it's close
2521 * to 0x3F. Increment the value by a small offset if it's likely
2522 * to overflow, to make sure it won't overflow while running
2523 * tests and bricks the system due to a non matching timC.
2524 *
2525 * TODO: find out why some tests (edge write discovery)
2526 * increment timB. */
2527 if ((rn.start & 0x3F) == 0x3E)
2528 rn.start += 2;
2529 else if ((rn.start & 0x3F) == 0x3F)
2530 rn.start += 1;
Vladimir Serbinenko3141eac2016-01-29 19:42:02 +01002531 ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002532 if (rn.all) {
2533 printk(BIOS_EMERG, "timB discovery failed: %d, %d, %d\n",
2534 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002535 return MAKE_ERR;
2536 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002537 printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002538 lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
2539 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002540 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002541}
2542
2543static int get_timB_high_adjust(u64 val)
2544{
2545 int i;
2546
2547 /* good */
2548 if (val == 0xffffffffffffffffLL)
2549 return 0;
2550
2551 if (val >= 0xf000000000000000LL) {
2552 /* needs negative adjustment */
2553 for (i = 0; i < 8; i++)
2554 if (val << (8 * (7 - i) + 4))
2555 return -i;
2556 } else {
2557 /* needs positive adjustment */
2558 for (i = 0; i < 8; i++)
2559 if (val >> (8 * (7 - i) + 4))
2560 return i;
2561 }
2562 return 8;
2563}
2564
2565static void adjust_high_timB(ramctr_timing * ctrl)
2566{
2567 int channel, slotrank, lane, old;
2568 write32(DEFAULT_MCHBAR + 0x3400, 0x200);
2569 FOR_ALL_POPULATED_CHANNELS {
2570 fill_pattern1(ctrl, channel);
2571 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 1);
2572 }
2573 FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
2574
2575 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001);
2576
2577 wait_428c(channel);
2578
Patrick Rudolph371d2912015-10-09 13:33:25 +02002579 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002580 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2581 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2582 0xc01 | (ctrl->tRCD << 16));
2583 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2584 (slotrank << 24) | 0x60000);
2585 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2586
Patrick Rudolph371d2912015-10-09 13:33:25 +02002587 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002588 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2589 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01);
2590 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2591 (slotrank << 24) | 0x8);
2592 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2593
Patrick Rudolph371d2912015-10-09 13:33:25 +02002594 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002595 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2596 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003);
2597 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2598 (slotrank << 24));
2599 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2);
2600
Patrick Rudolph371d2912015-10-09 13:33:25 +02002601 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002602 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2603 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2604 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2605 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2606 (slotrank << 24) | 0x8);
2607 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2608
2609 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2610
2611 wait_428c(channel);
2612
Patrick Rudolph371d2912015-10-09 13:33:25 +02002613 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002614 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2615 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2616 0xc01 | ((ctrl->tRP) << 16));
2617 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2618 (slotrank << 24) | 0x60400);
2619 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2620
Patrick Rudolph371d2912015-10-09 13:33:25 +02002621 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002622 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2623 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2624 0xc01 | ((ctrl->tRCD) << 16));
2625 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2626 (slotrank << 24) | 0x60000);
2627 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2628
Patrick Rudolph371d2912015-10-09 13:33:25 +02002629 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002630 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105);
2631 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2632 0x4000c01 |
2633 ((ctrl->tRP +
2634 ctrl->timings[channel][slotrank].val_4024 +
2635 ctrl->timings[channel][slotrank].val_4028) << 16));
2636 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2637 (slotrank << 24) | 0x60008);
2638 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2639
2640 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
2641 wait_428c(channel);
2642 FOR_ALL_LANES {
2643 u64 res =
2644 read32(DEFAULT_MCHBAR + lane_registers[lane] +
2645 0x100 * channel + 4);
2646 res |=
2647 ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] +
2648 0x100 * channel + 8)) << 32;
2649 old = ctrl->timings[channel][slotrank].lanes[lane].timB;
2650 ctrl->timings[channel][slotrank].lanes[lane].timB +=
2651 get_timB_high_adjust(res) * 64;
2652
Patrick Rudolpha649a542016-01-17 18:32:06 +01002653 printram("High adjust %d:%016llx\n", lane, res);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002654 printram("Bval+: %d, %d, %d, %x -> %x\n", channel,
2655 slotrank, lane, old,
2656 ctrl->timings[channel][slotrank].lanes[lane].
2657 timB);
2658 }
2659 }
2660 write32(DEFAULT_MCHBAR + 0x3400, 0);
2661}
2662
2663static void write_op(ramctr_timing * ctrl, int channel)
2664{
2665 int slotrank;
2666
2667 wait_428c(channel);
2668
2669 /* choose an existing rank. */
2670 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2671
Patrick Rudolph371d2912015-10-09 13:33:25 +02002672 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002673 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2674 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2675
2676 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2677 (slotrank << 24) | 0x60000);
2678
2679 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2680
2681 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2682 wait_428c(channel);
2683}
2684
Patrick Rudolph371d2912015-10-09 13:33:25 +02002685/* Compensate the skew between CMD/ADDR/CLK and DQ/DQS lanes.
2686 * DDR3 adopted the fly-by topology. The data and strobes signals reach
2687 * the chips at different times with respect to command, address and
2688 * clock signals.
2689 * By delaying either all DQ/DQs or all CMD/ADDR/CLK signals, a full phase
2690 * shift can be introduced.
2691 * It is assumed that the CLK/ADDR/CMD signals have the same routing delay.
2692 *
2693 * To find the required phase shift the DRAM is placed in "write leveling" mode.
2694 * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
2695 * sampled value on the data lanes (DQs).
2696 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002697static int write_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002698{
2699 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002700 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002701
2702 FOR_ALL_POPULATED_CHANNELS
2703 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
2704 read32(DEFAULT_MCHBAR + 0x4008 +
2705 0x400 * channel) | 0x8000000);
2706
2707 FOR_ALL_POPULATED_CHANNELS {
2708 write_op(ctrl, channel);
2709 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2710 read32(DEFAULT_MCHBAR + 0x4020 +
2711 0x400 * channel) | 0x200000);
2712 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002713
2714 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002715 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2716 FOR_ALL_POPULATED_CHANNELS {
2717 write_op(ctrl, channel);
2718 }
2719
Patrick Rudolph371d2912015-10-09 13:33:25 +02002720 /* enable write leveling on all ranks
2721 * disable all DQ outputs
2722 * only NOP is allowed in this mode */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002723 FOR_ALL_CHANNELS
2724 FOR_ALL_POPULATED_RANKS
2725 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002726 make_mr1(ctrl, slotrank, channel) | 0x1080);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002727
2728 write32(DEFAULT_MCHBAR + 0x3400, 0x108052);
2729
Patrick Rudolph9b515682015-10-09 13:43:51 +02002730 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002731
Patrick Rudolph371d2912015-10-09 13:33:25 +02002732 /* set any valid value for timB, it gets corrected later */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002733 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2734 err = discover_timB(ctrl, channel, slotrank);
2735 if (err)
2736 return err;
2737 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002738
Patrick Rudolph371d2912015-10-09 13:33:25 +02002739 /* disable write leveling on all ranks */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002740 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2741 write_mrreg(ctrl, channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002742 slotrank, 1, make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002743
2744 write32(DEFAULT_MCHBAR + 0x3400, 0);
2745
2746 FOR_ALL_POPULATED_CHANNELS
2747 wait_428c(channel);
2748
Patrick Rudolph371d2912015-10-09 13:33:25 +02002749 /* refresh enable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002750 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8);
2751
2752 FOR_ALL_POPULATED_CHANNELS {
2753 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2754 ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 +
2755 0x400 * channel));
2756 read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel);
2757 wait_428c(channel);
2758
Patrick Rudolph371d2912015-10-09 13:33:25 +02002759 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002760 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2761 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
2762 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000);
2763 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2764
2765 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2766 wait_428c(channel);
2767 }
2768
Patrick Rudolph9b515682015-10-09 13:43:51 +02002769 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002770
2771 printram("CPE\n");
2772 precharge(ctrl);
2773 printram("CPF\n");
2774
2775 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2776 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2777 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2778 0);
2779 }
2780
2781 FOR_ALL_POPULATED_CHANNELS {
2782 fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555);
2783 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
2784 }
2785
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002786 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2787 err = discover_timC(ctrl, channel, slotrank);
2788 if (err)
2789 return err;
2790 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002791
2792 FOR_ALL_POPULATED_CHANNELS
2793 program_timings(ctrl, channel);
2794
Patrick Rudolph371d2912015-10-09 13:33:25 +02002795 /* measure and adjust timB timings */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002796 adjust_high_timB(ctrl);
2797
2798 FOR_ALL_POPULATED_CHANNELS
2799 program_timings(ctrl, channel);
2800
2801 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2802 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2803 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2804 0);
2805 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002806 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002807}
2808
2809static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
2810{
2811 struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank];
2812 int timC_delta;
2813 int lanes_ok = 0;
2814 int ctr = 0;
2815 int lane;
2816
2817 for (timC_delta = -5; timC_delta <= 5; timC_delta++) {
2818 FOR_ALL_LANES {
2819 ctrl->timings[channel][slotrank].lanes[lane].timC =
2820 saved_rt.lanes[lane].timC + timC_delta;
2821 }
2822 program_timings(ctrl, channel);
2823 FOR_ALL_LANES {
2824 write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0);
2825 }
2826
2827 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2828
2829 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002830 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002831 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2832 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2833 ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10)
2834 | 8 | (ctrl->tRCD << 16));
2835
2836 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2837 (slotrank << 24) | ctr | 0x60000);
2838
2839 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002840 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002841 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
2842 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2843 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16));
2844 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2845 (slotrank << 24));
2846 write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd);
2847 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42);
2848
Patrick Rudolph371d2912015-10-09 13:33:25 +02002849 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002850 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2851 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2852 0x4001020 | (max(ctrl->tRTP, 8) << 16));
2853 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2854 (slotrank << 24));
2855 write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd);
2856 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42);
2857
Patrick Rudolph371d2912015-10-09 13:33:25 +02002858 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002859 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2860 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001);
2861 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2862 (slotrank << 24) | 0x60400);
2863 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2864
2865 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2866 wait_428c(channel);
2867 FOR_ALL_LANES {
2868 u32 r32 =
2869 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2870 0x400 * channel);
2871
2872 if (r32 == 0)
2873 lanes_ok |= 1 << lane;
2874 }
2875 ctr++;
2876 if (lanes_ok == ((1 << NUM_LANES) - 1))
2877 break;
2878 }
2879
2880 ctrl->timings[channel][slotrank] = saved_rt;
2881
2882 printram("3lanes: %x\n", lanes_ok);
2883 return lanes_ok != ((1 << NUM_LANES) - 1);
2884}
2885
2886#include "raminit_patterns.h"
2887
2888static void fill_pattern5(ramctr_timing * ctrl, int channel, int patno)
2889{
2890 unsigned i, j;
2891 unsigned channel_offset =
2892 get_precedening_channels(ctrl, channel) * 0x40;
2893 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2894
2895 if (patno) {
2896 u8 base8 = 0x80 >> ((patno - 1) % 8);
2897 u32 base = base8 | (base8 << 8) | (base8 << 16) | (base8 << 24);
2898 for (i = 0; i < 32; i++) {
2899 for (j = 0; j < 16; j++) {
2900 u32 val = use_base[patno - 1][i] & (1 << (j / 2)) ? base : 0;
2901 if (invert[patno - 1][i] & (1 << (j / 2)))
2902 val = ~val;
2903 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2904 j * 4), val);
2905 }
2906 }
2907
2908 } else {
2909 for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) {
2910 for (j = 0; j < 16; j++)
2911 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2912 j * 4), pattern[i][j]);
2913 }
2914 sfence();
2915 }
2916}
2917
2918static void reprogram_320c(ramctr_timing * ctrl)
2919{
2920 int channel, slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002921
2922 FOR_ALL_POPULATED_CHANNELS {
2923 wait_428c(channel);
2924
2925 /* choose an existing rank. */
2926 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2927
Patrick Rudolph371d2912015-10-09 13:33:25 +02002928 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002929 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2930 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2931
2932 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2933 (slotrank << 24) | 0x60000);
2934
2935 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2936
2937 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2938 wait_428c(channel);
2939 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2940 read32(DEFAULT_MCHBAR + 0x4020 +
2941 0x400 * channel) | 0x200000);
2942 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002943
2944 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002945 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2946 FOR_ALL_POPULATED_CHANNELS {
2947 wait_428c(channel);
2948
2949 /* choose an existing rank. */
2950 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2951
Patrick Rudolph371d2912015-10-09 13:33:25 +02002952 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002953 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2954 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2955
2956 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2957 (slotrank << 24) | 0x60000);
2958
2959 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2960
2961 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2962 wait_428c(channel);
2963 }
2964
2965 /* jedec reset */
2966 dram_jedecreset(ctrl);
2967 /* mrs commands. */
2968 dram_mrscommands(ctrl);
2969
Patrick Rudolph9b515682015-10-09 13:43:51 +02002970 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002971}
2972
2973#define MIN_C320C_LEN 13
2974
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002975static int try_cmd_stretch(ramctr_timing *ctrl, int channel, int cmd_stretch)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002976{
2977 struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002978 int slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002979 int c320c;
2980 int stat[NUM_SLOTRANKS][256];
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002981 int delta = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002982
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002983 printram("Trying cmd_stretch %d on channel %d\n", cmd_stretch, channel);
2984
2985 FOR_ALL_POPULATED_RANKS {
2986 saved_timings[channel][slotrank] =
2987 ctrl->timings[channel][slotrank];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002988 }
2989
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002990 ctrl->cmd_stretch[channel] = cmd_stretch;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002991
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002992 MCHBAR32(0x4004 + 0x400 * channel) =
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002993 ctrl->tRRD
2994 | (ctrl->tRTP << 4)
2995 | (ctrl->tCKE << 8)
2996 | (ctrl->tWTR << 12)
2997 | (ctrl->tFAW << 16)
2998 | (ctrl->tWR << 24)
2999 | (ctrl->cmd_stretch[channel] << 30);
3000
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003001 if (ctrl->cmd_stretch[channel] == 2)
3002 delta = 2;
3003 else if (ctrl->cmd_stretch[channel] == 0)
3004 delta = 4;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003005
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003006 FOR_ALL_POPULATED_RANKS {
3007 ctrl->timings[channel][slotrank].val_4024 -= delta;
3008 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003009
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003010 for (c320c = -127; c320c <= 127; c320c++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003011 FOR_ALL_POPULATED_RANKS {
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003012 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);
3019 printram("3stat: %d, %d, %d: %x\n",
3020 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_POPULATED_RANKS {
3034 ctrl->timings[channel][slotrank] =
3035 saved_timings[channel][slotrank];
3036 }
3037 return MAKE_ERR;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003038 }
3039 }
3040
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003041 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003042}
3043
Patrick Rudolph371d2912015-10-09 13:33:25 +02003044/* Adjust CMD phase shift and try multiple command rates.
3045 * A command rate of 2T doubles the time needed for address and
3046 * command decode. */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003047static int command_training(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003048{
3049 int channel;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003050 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003051
3052 FOR_ALL_POPULATED_CHANNELS {
3053 fill_pattern5(ctrl, channel, 0);
3054 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
3055 }
3056
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003057 FOR_ALL_POPULATED_CHANNELS {
3058 /* try command rate 1T and 2T */
3059 err = try_cmd_stretch(ctrl, channel, 0);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003060 if (err) {
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003061 err = try_cmd_stretch(ctrl, channel, 2);
3062 if (err) {
3063 printk(BIOS_EMERG, "c320c discovery failed\n");
3064 return err;
3065 }
3066 printram("Using CMD rate 2T on channel %u\n", channel);
3067 } else
3068 printram("Using CMD rate 1T on channel %u\n", channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003069 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003070
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003071 FOR_ALL_POPULATED_CHANNELS
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003072 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003073
3074 reprogram_320c(ctrl);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003075 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003076}
3077
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003078static int discover_edges_real(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003079 int *edges)
3080{
3081 int edge;
3082 int statistics[NUM_LANES][MAX_EDGE_TIMING + 1];
3083 int lane;
3084
3085 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3086 FOR_ALL_LANES {
3087 ctrl->timings[channel][slotrank].lanes[lane].rising =
3088 edge;
3089 ctrl->timings[channel][slotrank].lanes[lane].falling =
3090 edge;
3091 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003092 program_timings(ctrl, channel);
3093
3094 FOR_ALL_LANES {
3095 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3096 4 * lane, 0);
3097 read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane +
3098 0x4140);
3099 }
3100
3101 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003102 /* DRAM command MRS
3103 * write MR3 MPR enable
3104 * in this mode only RD and RDA are allowed
3105 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003106 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
3107 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3108 (0xc01 | (ctrl->tMOD << 16)));
3109 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3110 (slotrank << 24) | 0x360004);
3111 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3112
Patrick Rudolph371d2912015-10-09 13:33:25 +02003113 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003114 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
3115 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4);
3116 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3117 (slotrank << 24));
3118 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3119
Patrick Rudolph371d2912015-10-09 13:33:25 +02003120 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003121 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
3122 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3123 0x1001 | ((ctrl->CAS + 8) << 16));
3124 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3125 (slotrank << 24) | 0x60000);
3126 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3127
Patrick Rudolph371d2912015-10-09 13:33:25 +02003128 /* DRAM command MRS
3129 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003130 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
3131 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3132 (0xc01 | (ctrl->tMOD << 16)));
3133 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3134 (slotrank << 24) | 0x360000);
3135 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3136
3137 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
3138
3139 wait_428c(channel);
3140
3141 FOR_ALL_LANES {
3142 statistics[lane][edge] =
3143 read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3144 lane * 4);
3145 }
3146 }
3147 FOR_ALL_LANES {
3148 struct run rn =
3149 get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
3150 edges[lane] = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003151 if (rn.all) {
3152 printk(BIOS_EMERG, "edge discovery failed: %d, %d, %d\n",
3153 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003154 return MAKE_ERR;
3155 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003156 printram("eval %d, %d, %d: %02x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003157 lane, edges[lane]);
3158 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003159 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003160}
3161
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003162static int discover_edges(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003163{
3164 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3165 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3166 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003167 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003168
3169 write32(DEFAULT_MCHBAR + 0x3400, 0);
3170
Patrick Rudolph9b515682015-10-09 13:43:51 +02003171 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003172
3173 FOR_ALL_POPULATED_CHANNELS FOR_ALL_LANES {
3174 write32(DEFAULT_MCHBAR + 4 * lane +
3175 0x400 * channel + 0x4080, 0);
3176 }
3177
3178 FOR_ALL_POPULATED_CHANNELS {
3179 fill_pattern0(ctrl, channel, 0, 0);
3180 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3181 FOR_ALL_LANES {
3182 read32(DEFAULT_MCHBAR + 0x400 * channel +
3183 lane * 4 + 0x4140);
3184 }
3185
3186 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3187 ctrl->timings[channel][slotrank].lanes[lane].falling =
3188 16;
3189 ctrl->timings[channel][slotrank].lanes[lane].rising =
3190 16;
3191 }
3192
3193 program_timings(ctrl, channel);
3194
3195 FOR_ALL_POPULATED_RANKS {
3196 wait_428c(channel);
3197
Patrick Rudolph371d2912015-10-09 13:33:25 +02003198 /* DRAM command MRS
3199 * MR3 enable MPR
3200 * write MR3 MPR enable
3201 * in this mode only RD and RDA are allowed
3202 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003203 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3204 0x1f000);
3205 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3206 0xc01 | (ctrl->tMOD << 16));
3207 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3208 (slotrank << 24) | 0x360004);
3209 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3210
Patrick Rudolph371d2912015-10-09 13:33:25 +02003211 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003212 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3213 0x1f105);
3214 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3215 0x4041003);
3216 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3217 (slotrank << 24) | 0);
3218 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3219
Patrick Rudolph371d2912015-10-09 13:33:25 +02003220 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003221 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3222 0x1f105);
3223 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3224 0x1001 | ((ctrl->CAS + 8) << 16));
3225 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3226 (slotrank << 24) | 0x60000);
3227 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3228
Patrick Rudolph371d2912015-10-09 13:33:25 +02003229 /* DRAM command MRS
3230 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003231 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3232 0x1f000);
3233 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3234 0xc01 | (ctrl->tMOD << 16));
3235 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3236 (slotrank << 24) | 0x360000);
3237 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3238 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3239 0xc0001);
3240
3241 wait_428c(channel);
3242 }
3243
Patrick Rudolph371d2912015-10-09 13:33:25 +02003244 /* XXX: check any measured value ? */
3245
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003246 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3247 ctrl->timings[channel][slotrank].lanes[lane].falling =
3248 48;
3249 ctrl->timings[channel][slotrank].lanes[lane].rising =
3250 48;
3251 }
3252
3253 program_timings(ctrl, channel);
3254
3255 FOR_ALL_POPULATED_RANKS {
3256 wait_428c(channel);
3257
Patrick Rudolph371d2912015-10-09 13:33:25 +02003258 /* DRAM command MRS
3259 * MR3 enable MPR
3260 * write MR3 MPR enable
3261 * in this mode only RD and RDA are allowed
3262 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003263 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3264 0x1f000);
3265 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3266 0xc01 | (ctrl->tMOD << 16));
3267 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3268 (slotrank << 24) | 0x360004);
3269 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3270
Patrick Rudolph371d2912015-10-09 13:33:25 +02003271 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003272 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3273 0x1f105);
3274 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3275 0x4041003);
3276 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3277 (slotrank << 24) | 0);
3278 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3279
Patrick Rudolph371d2912015-10-09 13:33:25 +02003280 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003281 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3282 0x1f105);
3283 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3284 0x1001 | ((ctrl->CAS + 8) << 16));
3285 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3286 (slotrank << 24) | 0x60000);
3287 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3288
Patrick Rudolph371d2912015-10-09 13:33:25 +02003289 /* DRAM command MRS
3290 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003291 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3292 0x1f000);
3293 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3294 0xc01 | (ctrl->tMOD << 16));
3295 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3296 (slotrank << 24) | 0x360000);
3297 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3298
3299 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3300 0xc0001);
3301 wait_428c(channel);
3302 }
3303
Patrick Rudolph371d2912015-10-09 13:33:25 +02003304 /* XXX: check any measured value ? */
3305
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003306 FOR_ALL_LANES {
3307 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel +
3308 lane * 4,
3309 ~read32(DEFAULT_MCHBAR + 0x4040 +
3310 0x400 * channel + lane * 4) & 0xff);
3311 }
3312
3313 fill_pattern0(ctrl, channel, 0, 0xffffffff);
3314 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3315 }
3316
3317 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3318 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003319 printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003320
3321 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003322 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003323 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003324 if (err)
3325 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003326 }
3327
3328 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003329 printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003330
3331 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003332 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003333 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003334 if (err)
3335 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003336 }
3337
3338 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3339
3340 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3341 ctrl->timings[channel][slotrank].lanes[lane].falling =
3342 falling_edges[channel][slotrank][lane];
3343 ctrl->timings[channel][slotrank].lanes[lane].rising =
3344 rising_edges[channel][slotrank][lane];
3345 }
3346
3347 FOR_ALL_POPULATED_CHANNELS {
3348 program_timings(ctrl, channel);
3349 }
3350
3351 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3352 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3353 0);
3354 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003355 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003356}
3357
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003358static int discover_edges_write_real(ramctr_timing *ctrl, int channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003359 int slotrank, int *edges)
3360{
3361 int edge;
3362 u32 raw_statistics[MAX_EDGE_TIMING + 1];
3363 int statistics[MAX_EDGE_TIMING + 1];
3364 const int reg3000b24[] = { 0, 0xc, 0x2c };
3365 int lane, i;
3366 int lower[NUM_LANES];
3367 int upper[NUM_LANES];
3368 int pat;
3369
3370 FOR_ALL_LANES {
3371 lower[lane] = 0;
3372 upper[lane] = MAX_EDGE_TIMING;
3373 }
3374
3375 for (i = 0; i < 3; i++) {
3376 write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel,
3377 reg3000b24[i] << 24);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003378 printram("[%x] = 0x%08x\n",
3379 0x3000 + 0x100 * channel, reg3000b24[i] << 24);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003380 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3381 fill_pattern5(ctrl, channel, pat);
3382 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003383 printram("using pattern %d\n", pat);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003384 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3385 FOR_ALL_LANES {
3386 ctrl->timings[channel][slotrank].lanes[lane].
3387 rising = edge;
3388 ctrl->timings[channel][slotrank].lanes[lane].
3389 falling = edge;
3390 }
3391 program_timings(ctrl, channel);
3392
3393 FOR_ALL_LANES {
3394 write32(DEFAULT_MCHBAR + 0x4340 +
3395 0x400 * channel + 4 * lane, 0);
3396 read32(DEFAULT_MCHBAR + 0x400 * channel +
3397 4 * lane + 0x4140);
3398 }
3399 wait_428c(channel);
3400
Patrick Rudolph371d2912015-10-09 13:33:25 +02003401 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003402 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3403 0x1f006);
3404 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3405 0x4 | (ctrl->tRCD << 16)
3406 | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) <<
3407 10));
3408 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3409 (slotrank << 24) | 0x60000);
3410 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel,
3411 0x240);
3412
Patrick Rudolph371d2912015-10-09 13:33:25 +02003413 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003414 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3415 0x1f201);
3416 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3417 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) <<
3418 16));
3419 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3420 (slotrank << 24));
3421 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel,
3422 0x242);
3423
Patrick Rudolph371d2912015-10-09 13:33:25 +02003424 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003425 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3426 0x1f105);
3427 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3428 0x4005020 | (max(ctrl->tRTP, 8) << 16));
3429 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3430 (slotrank << 24));
3431 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel,
3432 0x242);
3433
Patrick Rudolph371d2912015-10-09 13:33:25 +02003434 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003435 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3436 0x1f002);
3437 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3438 0xc01 | (ctrl->tRP << 16));
3439 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3440 (slotrank << 24) | 0x60400);
3441 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3442
3443 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3444 0xc0001);
3445 wait_428c(channel);
3446 FOR_ALL_LANES {
3447 read32(DEFAULT_MCHBAR + 0x4340 +
3448 0x400 * channel + lane * 4);
3449 }
3450
3451 raw_statistics[edge] =
3452 MCHBAR32(0x436c + 0x400 * channel);
3453 }
3454 FOR_ALL_LANES {
3455 struct run rn;
3456 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++)
3457 statistics[edge] =
3458 ! !(raw_statistics[edge] & (1 << lane));
3459 rn = get_longest_zero_run(statistics,
3460 MAX_EDGE_TIMING + 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003461 printram("edges: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003462 channel, slotrank, i, rn.start, rn.middle,
3463 rn.end, rn.start + ctrl->edge_offset[i],
3464 rn.end - ctrl->edge_offset[i]);
3465 lower[lane] =
3466 max(rn.start + ctrl->edge_offset[i], lower[lane]);
3467 upper[lane] =
3468 min(rn.end - ctrl->edge_offset[i], upper[lane]);
3469 edges[lane] = (lower[lane] + upper[lane]) / 2;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003470 if (rn.all || (lower[lane] > upper[lane])) {
3471 printk(BIOS_EMERG, "edge write discovery failed: %d, %d, %d\n",
3472 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003473 return MAKE_ERR;
3474 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003475 }
3476 }
3477 }
3478
3479 write32(DEFAULT_MCHBAR + 0x3000, 0);
3480 printram("CPA\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003481 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003482}
3483
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003484static int discover_edges_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003485{
3486 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3487 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3488 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003489 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003490
3491 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3492 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003493 printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003494
3495 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003496 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003497 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003498 if (err)
3499 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003500 }
3501
3502 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003503 printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003504
3505 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003506 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003507 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003508 if (err)
3509 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003510 }
3511
3512 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3513
3514 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3515 ctrl->timings[channel][slotrank].lanes[lane].falling =
3516 falling_edges[channel][slotrank][lane];
3517 ctrl->timings[channel][slotrank].lanes[lane].rising =
3518 rising_edges[channel][slotrank][lane];
3519 }
3520
3521 FOR_ALL_POPULATED_CHANNELS
3522 program_timings(ctrl, channel);
3523
3524 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3525 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3526 0);
3527 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003528 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003529}
3530
3531static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
3532{
3533 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003534 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003535 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
3536 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3537 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD)
3538 << 10) | (ctrl->tRCD << 16) | 4);
3539 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3540 (slotrank << 24) | 0x60000);
3541 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
3542
Patrick Rudolph371d2912015-10-09 13:33:25 +02003543 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003544 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
3545 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3546 0x80011e0 |
3547 ((ctrl->tWTR + ctrl->CWL + 8) << 16));
3548 write32(DEFAULT_MCHBAR + 0x4204 +
3549 0x400 * channel, (slotrank << 24));
3550 write32(DEFAULT_MCHBAR + 0x4214 +
3551 0x400 * channel, 0x242);
3552
Patrick Rudolph371d2912015-10-09 13:33:25 +02003553 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003554 write32(DEFAULT_MCHBAR + 0x4228 +
3555 0x400 * channel, 0x1f105);
3556 write32(DEFAULT_MCHBAR + 0x4238 +
3557 0x400 * channel,
3558 0x40011e0 | (max(ctrl->tRTP, 8) << 16));
3559 write32(DEFAULT_MCHBAR + 0x4208 +
3560 0x400 * channel, (slotrank << 24));
3561 write32(DEFAULT_MCHBAR + 0x4218 +
3562 0x400 * channel, 0x242);
3563
Patrick Rudolph371d2912015-10-09 13:33:25 +02003564 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003565 write32(DEFAULT_MCHBAR + 0x422c +
3566 0x400 * channel, 0x1f002);
3567 write32(DEFAULT_MCHBAR + 0x423c +
3568 0x400 * channel,
3569 0x1001 | (ctrl->tRP << 16));
3570 write32(DEFAULT_MCHBAR + 0x420c +
3571 0x400 * channel,
3572 (slotrank << 24) | 0x60400);
3573 write32(DEFAULT_MCHBAR + 0x421c +
3574 0x400 * channel, 0);
3575
3576 write32(DEFAULT_MCHBAR + 0x4284 +
3577 0x400 * channel, 0xc0001);
3578 wait_428c(channel);
3579}
3580
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003581static int discover_timC_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003582{
3583 const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
3584 int i, pat;
3585
3586 int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3587 int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3588 int channel, slotrank, lane;
3589
3590 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3591 lower[channel][slotrank][lane] = 0;
3592 upper[channel][slotrank][lane] = MAX_TIMC;
3593 }
3594
3595 write32(DEFAULT_MCHBAR + 0x4ea8, 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003596 printram("discover timC write:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003597
3598 for (i = 0; i < 3; i++)
3599 FOR_ALL_POPULATED_CHANNELS {
3600 write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100),
3601 (rege3c_b24[i] << 24)
3602 | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100))
3603 & ~0x3f000000));
3604 udelay(2);
3605 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3606 FOR_ALL_POPULATED_RANKS {
3607 int timC;
3608 u32 raw_statistics[MAX_TIMC + 1];
3609 int statistics[MAX_TIMC + 1];
3610
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003611 /* Make sure rn.start < rn.end */
3612 statistics[MAX_TIMC] = 1;
3613
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003614 fill_pattern5(ctrl, channel, pat);
3615 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003616 for (timC = 0; timC < MAX_TIMC; timC++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003617 FOR_ALL_LANES
3618 ctrl->timings[channel][slotrank].lanes[lane].timC = timC;
3619 program_timings(ctrl, channel);
3620
3621 test_timC_write (ctrl, channel, slotrank);
3622
3623 raw_statistics[timC] =
3624 MCHBAR32(0x436c + 0x400 * channel);
3625 }
3626 FOR_ALL_LANES {
3627 struct run rn;
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003628 for (timC = 0; timC < MAX_TIMC; timC++)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003629 statistics[timC] =
3630 !!(raw_statistics[timC] &
3631 (1 << lane));
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003632
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003633 rn = get_longest_zero_run(statistics,
3634 MAX_TIMC + 1);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003635 if (rn.all) {
3636 printk(BIOS_EMERG, "timC write discovery failed: %d, %d, %d\n",
3637 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003638 return MAKE_ERR;
3639 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003640 printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003641 channel, slotrank, i, rn.start,
3642 rn.middle, rn.end,
3643 rn.start + ctrl->timC_offset[i],
3644 rn.end - ctrl->timC_offset[i]);
3645 lower[channel][slotrank][lane] =
3646 max(rn.start + ctrl->timC_offset[i],
3647 lower[channel][slotrank][lane]);
3648 upper[channel][slotrank][lane] =
3649 min(rn.end - ctrl->timC_offset[i],
3650 upper[channel][slotrank][lane]);
3651
3652 }
3653 }
3654 }
3655 }
3656
3657 FOR_ALL_CHANNELS {
3658 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3659 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3660 ~0x3f000000));
3661 udelay(2);
3662 }
3663
3664 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3665
3666 printram("CPB\n");
3667
3668 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
Patrick Rudolpha649a542016-01-17 18:32:06 +01003669 printram("timC %d, %d, %d: %x\n", channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003670 slotrank, lane,
3671 (lower[channel][slotrank][lane] +
3672 upper[channel][slotrank][lane]) / 2);
3673 ctrl->timings[channel][slotrank].lanes[lane].timC =
3674 (lower[channel][slotrank][lane] +
3675 upper[channel][slotrank][lane]) / 2;
3676 }
3677 FOR_ALL_POPULATED_CHANNELS {
3678 program_timings(ctrl, channel);
3679 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003680 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003681}
3682
3683static void normalize_training(ramctr_timing * ctrl)
3684{
3685 int channel, slotrank, lane;
3686 int mat = 0;
3687
3688 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3689 int delta;
3690 FOR_ALL_LANES mat =
3691 max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat);
3692 delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028;
3693 ctrl->timings[channel][slotrank].val_4024 += delta;
3694 ctrl->timings[channel][slotrank].val_4028 += delta;
3695 }
3696
3697 FOR_ALL_POPULATED_CHANNELS {
3698 program_timings(ctrl, channel);
3699 }
3700}
3701
3702static void write_controller_mr(ramctr_timing * ctrl)
3703{
3704 int channel, slotrank;
3705
3706 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3707 write32(DEFAULT_MCHBAR + 0x0004 + (channel << 8) +
3708 lane_registers[slotrank], make_mr0(ctrl, slotrank));
3709 write32(DEFAULT_MCHBAR + 0x0008 + (channel << 8) +
Patrick Rudolph7e513d12016-01-10 14:22:34 +01003710 lane_registers[slotrank],
3711 make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003712 }
3713}
3714
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003715static int channel_test(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003716{
3717 int channel, slotrank, lane;
3718
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003719 slotrank = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003720 FOR_ALL_POPULATED_CHANNELS
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003721 if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) {
3722 printk(BIOS_EMERG, "Mini channel test failed (1): %d\n",
3723 channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003724 return MAKE_ERR;
3725 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003726 FOR_ALL_POPULATED_CHANNELS {
3727 fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
3728
3729 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3730 }
3731
3732 for (slotrank = 0; slotrank < 4; slotrank++)
3733 FOR_ALL_CHANNELS
3734 if (ctrl->rankmap[channel] & (1 << slotrank)) {
3735 FOR_ALL_LANES {
3736 write32(DEFAULT_MCHBAR + (0x4f40 + 4 * lane), 0);
3737 write32(DEFAULT_MCHBAR + (0x4d40 + 4 * lane), 0);
3738 }
3739 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003740 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003741 write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
3742 write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10), 0x0028a004);
3743 write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
3744 0x00060000 | (slotrank << 24));
3745 write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003746 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003747 write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
3748 write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281064);
3749 write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
3750 0x00000000 | (slotrank << 24));
3751 write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003752 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003753 write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f105);
3754 write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x04281064);
3755 write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
3756 0x00000000 | (slotrank << 24));
3757 write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003758 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003759 write32(DEFAULT_MCHBAR + 0x422c + (channel << 10), 0x0001f002);
3760 write32(DEFAULT_MCHBAR + 0x423c + (channel << 10), 0x00280c01);
3761 write32(DEFAULT_MCHBAR + 0x420c + (channel << 10),
3762 0x00060400 | (slotrank << 24));
3763 write32(DEFAULT_MCHBAR + 0x421c + (channel << 10), 0x00000240);
3764 write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
3765 wait_428c(channel);
3766 FOR_ALL_LANES
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003767 if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) {
3768 printk(BIOS_EMERG, "Mini channel test failed (2): %d, %d, %d\n",
3769 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003770 return MAKE_ERR;
3771 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003772 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003773 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003774}
3775
3776static void set_scrambling_seed(ramctr_timing * ctrl)
3777{
3778 int channel;
3779
3780 /* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
3781 I don't think so. */
3782 static u32 seeds[NUM_CHANNELS][3] = {
3783 {0x00009a36, 0xbafcfdcf, 0x46d1ab68},
3784 {0x00028bfa, 0x53fe4b49, 0x19ed5483}
3785 };
3786 FOR_ALL_POPULATED_CHANNELS {
3787 MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
3788 write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
3789 write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
3790 write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
3791 }
3792}
3793
3794static void set_4f8c(void)
3795{
3796 struct cpuid_result cpures;
3797 u32 cpu;
3798
Ryan Salsamendie4da9aa2016-06-24 12:01:11 -07003799 cpures = cpuid(1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003800 cpu = (cpures.eax);
3801 if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) {
3802 MCHBAR32(0x4f8c) = 0x141D1519;
3803 } else {
3804 MCHBAR32(0x4f8c) = 0x551D1519;
3805 }
3806}
3807
3808static void prepare_training(ramctr_timing * ctrl)
3809{
3810 int channel;
3811
3812 FOR_ALL_POPULATED_CHANNELS {
3813 // Always drive command bus
3814 MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000;
3815 }
3816
3817 udelay(1);
3818
3819 FOR_ALL_POPULATED_CHANNELS {
3820 wait_428c(channel);
3821 }
3822}
3823
3824static void set_4008c(ramctr_timing * ctrl)
3825{
3826 int channel, slotrank;
3827 u32 reg;
3828 FOR_ALL_POPULATED_CHANNELS {
3829 u32 b20, b4_8_12;
3830 int min_320c = 10000;
3831 int max_320c = -10000;
3832
3833 FOR_ALL_POPULATED_RANKS {
3834 max_320c = max(ctrl->timings[channel][slotrank].val_320c, max_320c);
3835 min_320c = min(ctrl->timings[channel][slotrank].val_320c, min_320c);
3836 }
3837
3838 if (max_320c - min_320c > 51)
3839 b20 = 0;
3840 else
3841 b20 = ctrl->ref_card_offset[channel];
3842
3843 if (ctrl->reg_320c_range_threshold < max_320c - min_320c)
3844 b4_8_12 = 0x3330;
3845 else
3846 b4_8_12 = 0x2220;
3847
3848 reg = read32(DEFAULT_MCHBAR + 0x400c + (channel << 10));
3849 write32(DEFAULT_MCHBAR + 0x400c + (channel << 10),
3850 (reg & 0xFFF0FFFF)
3851 | (ctrl->ref_card_offset[channel] << 16)
3852 | (ctrl->ref_card_offset[channel] << 18));
3853 write32(DEFAULT_MCHBAR + 0x4008 + (channel << 10),
3854 0x0a000000
3855 | (b20 << 20)
3856 | ((ctrl->ref_card_offset[channel] + 2) << 16)
3857 | b4_8_12);
3858 }
3859}
3860
3861static void set_42a0(ramctr_timing * ctrl)
3862{
3863 int channel;
3864 FOR_ALL_POPULATED_CHANNELS {
3865 write32(DEFAULT_MCHBAR + (0x42a0 + 0x400 * channel),
3866 0x00001000 | ctrl->rankmap[channel]);
3867 MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK
3868 }
3869}
3870
3871static int encode_5d10(int ns)
3872{
3873 return (ns + 499) / 500;
3874}
3875
3876/* FIXME: values in this function should be hardware revision-dependent. */
3877static void final_registers(ramctr_timing * ctrl)
3878{
3879 int channel;
3880 int t1_cycles = 0, t1_ns = 0, t2_ns;
3881 int t3_ns;
3882 u32 r32;
3883
3884 write32(DEFAULT_MCHBAR + 0x4cd4, 0x00000046);
3885
3886 write32(DEFAULT_MCHBAR + 0x400c, (read32(DEFAULT_MCHBAR + 0x400c) & 0xFFFFCFFF) | 0x1000); // OK
3887 write32(DEFAULT_MCHBAR + 0x440c, (read32(DEFAULT_MCHBAR + 0x440c) & 0xFFFFCFFF) | 0x1000); // OK
3888 write32(DEFAULT_MCHBAR + 0x4cb0, 0x00000740);
3889 write32(DEFAULT_MCHBAR + 0x4380, 0x00000aaa); // OK
3890 write32(DEFAULT_MCHBAR + 0x4780, 0x00000aaa); // OK
3891 write32(DEFAULT_MCHBAR + 0x4f88, 0x5f7003ff); // OK
3892 write32(DEFAULT_MCHBAR + 0x5064, 0x00073000 | ctrl->reg_5064b0); // OK
3893
3894 FOR_ALL_CHANNELS {
3895 switch (ctrl->rankmap[channel]) {
3896 /* Unpopulated channel. */
3897 case 0:
3898 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0);
3899 break;
3900 /* Only single-ranked dimms. */
3901 case 1:
3902 case 4:
3903 case 5:
3904 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x373131);
3905 break;
3906 /* Dual-ranked dimms present. */
3907 default:
3908 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x9b6ea1);
3909 break;
3910 }
3911 }
3912
3913 write32 (DEFAULT_MCHBAR + 0x5880, 0xca9171e5);
3914 write32 (DEFAULT_MCHBAR + 0x5888,
3915 (read32 (DEFAULT_MCHBAR + 0x5888) & ~0xffffff) | 0xe4d5d0);
3916 write32 (DEFAULT_MCHBAR + 0x58a8, read32 (DEFAULT_MCHBAR + 0x58a8) & ~0x1f);
3917 write32 (DEFAULT_MCHBAR + 0x4294,
3918 (read32 (DEFAULT_MCHBAR + 0x4294) & ~0x30000)
3919 | (1 << 16));
3920 write32 (DEFAULT_MCHBAR + 0x4694,
3921 (read32 (DEFAULT_MCHBAR + 0x4694) & ~0x30000)
3922 | (1 << 16));
3923
3924 MCHBAR32(0x5030) |= 1; // OK
3925 MCHBAR32(0x5030) |= 0x80; // OK
3926 MCHBAR32(0x5f18) = 0xfa; // OK
3927
3928 /* Find a populated channel. */
3929 FOR_ALL_POPULATED_CHANNELS
3930 break;
3931
3932 t1_cycles = ((read32(DEFAULT_MCHBAR + 0x4290 + channel * 0x400) >> 8) & 0xff);
3933 r32 = read32(DEFAULT_MCHBAR + 0x5064);
3934 if (r32 & 0x20000)
3935 t1_cycles += (r32 & 0xfff);
3936 t1_cycles += (read32(DEFAULT_MCHBAR + channel * 0x400 + 0x42a4) & 0xfff);
3937 t1_ns = t1_cycles * ctrl->tCK / 256 + 544;
3938 if (!(r32 & 0x20000))
3939 t1_ns += 500;
3940
3941 t2_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f10) >> 8) & 0xfff);
3942 if ( read32(DEFAULT_MCHBAR + 0x5f00) & 8 )
3943 {
3944 t3_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f20) >> 8) & 0xfff);
3945 t3_ns += 10 * (read32(DEFAULT_MCHBAR + 0x5f18) & 0xff);
3946 }
3947 else
3948 {
3949 t3_ns = 500;
3950 }
3951 printk(BIOS_DEBUG, "t123: %d, %d, %d\n",
3952 t1_ns, t2_ns, t3_ns);
3953 write32 (DEFAULT_MCHBAR + 0x5d10,
3954 ((encode_5d10(t1_ns) + encode_5d10(t2_ns)) << 16)
3955 | (encode_5d10(t1_ns) << 8)
3956 | ((encode_5d10(t3_ns) + encode_5d10(t2_ns) + encode_5d10(t1_ns)) << 24)
3957 | (read32(DEFAULT_MCHBAR + 0x5d10) & 0xC0C0C0C0)
3958 | 0xc);
3959}
3960
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003961static void save_timings(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003962{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003963 /* Save the MRC S3 restore data to cbmem */
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003964 store_current_mrc_cache(ctrl, sizeof(*ctrl));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003965}
3966
3967static void restore_timings(ramctr_timing * ctrl)
3968{
3969 int channel, slotrank, lane;
3970
3971 FOR_ALL_POPULATED_CHANNELS
3972 MCHBAR32(0x4004 + 0x400 * channel) =
3973 ctrl->tRRD
3974 | (ctrl->tRTP << 4)
3975 | (ctrl->tCKE << 8)
3976 | (ctrl->tWTR << 12)
3977 | (ctrl->tFAW << 16)
3978 | (ctrl->tWR << 24)
3979 | (ctrl->cmd_stretch[channel] << 30);
3980
3981 udelay(1);
3982
3983 FOR_ALL_POPULATED_CHANNELS {
3984 wait_428c(channel);
3985 }
3986
3987 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3988 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
3989 + 4 * lane, 0);
3990 }
3991
3992 FOR_ALL_POPULATED_CHANNELS
3993 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
3994 read32(DEFAULT_MCHBAR + 0x4008 +
3995 0x400 * channel) | 0x8000000);
3996
3997 FOR_ALL_POPULATED_CHANNELS {
3998 udelay (1);
3999 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
4000 read32(DEFAULT_MCHBAR + 0x4020 +
4001 0x400 * channel) | 0x200000);
4002 }
4003
4004 printram("CPE\n");
4005
4006 write32(DEFAULT_MCHBAR + 0x3400, 0);
4007 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
4008
4009 printram("CP5b\n");
4010
4011 FOR_ALL_POPULATED_CHANNELS {
4012 program_timings(ctrl, channel);
4013 }
4014
4015 u32 reg, addr;
4016
Elyes HAOUAS7db506c2016-10-02 11:56:39 +02004017 while (!(MCHBAR32(0x5084) & 0x10000));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004018 do {
4019 reg = MCHBAR32(0x428c);
4020 } while ((reg & 0x14) == 0);
4021
4022 // Set state of memory controller
4023 MCHBAR32(0x5030) = 0x116;
4024 MCHBAR32(0x4ea0) = 0;
4025
4026 // Wait 500us
4027 udelay(500);
4028
4029 FOR_ALL_CHANNELS {
4030 // Set valid rank CKE
4031 reg = 0;
4032 reg = (reg & ~0xf) | ctrl->rankmap[channel];
4033 addr = 0x400 * channel + 0x42a0;
4034 MCHBAR32(addr) = reg;
4035
4036 // Wait 10ns for ranks to settle
4037 //udelay(0.01);
4038
4039 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
4040 MCHBAR32(addr) = reg;
4041
4042 // Write reset using a NOP
4043 write_reset(ctrl);
4044 }
4045
4046 /* mrs commands. */
4047 dram_mrscommands(ctrl);
4048
4049 printram("CP5c\n");
4050
4051 write32(DEFAULT_MCHBAR + 0x3000, 0);
4052
4053 FOR_ALL_CHANNELS {
4054 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
4055 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
4056 ~0x3f000000));
4057 udelay(2);
4058 }
4059
4060 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
4061}
4062
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004063static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot,
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004064 int s3_resume, int me_uma_size)
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004065{
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004066 int err;
4067
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004068 printk(BIOS_DEBUG, "Starting RAM training (%d).\n", fast_boot);
4069
4070 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004071 /* Find fastest common supported parameters */
4072 dram_find_common_params(ctrl);
4073
4074 dram_dimm_mapping(ctrl);
4075 }
4076
4077 /* Set MCU frequency */
4078 dram_freq(ctrl);
4079
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004080 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004081 /* Calculate timings */
4082 dram_timing(ctrl);
4083 }
4084
4085 /* Set version register */
4086 MCHBAR32(0x5034) = 0xC04EB002;
4087
4088 /* Enable crossover */
4089 dram_xover(ctrl);
4090
4091 /* Set timing and refresh registers */
4092 dram_timing_regs(ctrl);
4093
4094 /* Power mode preset */
4095 MCHBAR32(0x4e80) = 0x5500;
4096
4097 /* Set scheduler parameters */
4098 MCHBAR32(0x4c20) = 0x10100005;
4099
Elyes HAOUAS15279a92016-07-28 21:05:26 +02004100 /* Set CPU specific register */
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004101 set_4f8c();
4102
4103 /* Clear IO reset bit */
4104 MCHBAR32(0x5030) &= ~0x20;
4105
4106 /* Set MAD-DIMM registers */
4107 dram_dimm_set_mapping(ctrl);
4108 printk(BIOS_DEBUG, "Done dimm mapping\n");
4109
4110 /* Zone config */
4111 dram_zones(ctrl, 1);
4112
4113 /* Set memory map */
4114 dram_memorymap(ctrl, me_uma_size);
4115 printk(BIOS_DEBUG, "Done memory map\n");
4116
4117 /* Set IO registers */
4118 dram_ioregs(ctrl);
4119 printk(BIOS_DEBUG, "Done io registers\n");
4120
4121 udelay(1);
4122
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004123 if (fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004124 restore_timings(ctrl);
4125 } else {
4126 /* Do jedec ddr3 reset sequence */
4127 dram_jedecreset(ctrl);
4128 printk(BIOS_DEBUG, "Done jedec reset\n");
4129
4130 /* MRS commands */
4131 dram_mrscommands(ctrl);
4132 printk(BIOS_DEBUG, "Done MRS commands\n");
4133
4134 /* Prepare for memory training */
4135 prepare_training(ctrl);
4136
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004137 err = read_training(ctrl);
4138 if (err)
4139 return err;
4140
4141 err = write_training(ctrl);
4142 if (err)
4143 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004144
4145 printram("CP5a\n");
4146
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004147 err = discover_edges(ctrl);
4148 if (err)
4149 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004150
4151 printram("CP5b\n");
4152
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004153 err = command_training(ctrl);
4154 if (err)
4155 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004156
4157 printram("CP5c\n");
4158
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004159 err = discover_edges_write(ctrl);
4160 if (err)
4161 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004162
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004163 err = discover_timC_write(ctrl);
4164 if (err)
4165 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004166
4167 normalize_training(ctrl);
4168 }
4169
4170 set_4008c(ctrl);
4171
4172 write_controller_mr(ctrl);
4173
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004174 if (!s3_resume) {
4175 err = channel_test(ctrl);
4176 if (err)
4177 return err;
4178 }
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004179
4180 return 0;
4181}
4182
4183void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004184 int s3resume)
4185{
4186 int me_uma_size;
4187 int cbmem_was_inited;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004188 ramctr_timing ctrl;
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004189 int fast_boot;
4190 struct mrc_data_container *mrc_cache;
4191 ramctr_timing *ctrl_cached;
Patrick Rudolph31d19592016-03-26 12:22:34 +01004192 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004193
4194 MCHBAR32(0x5f00) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004195
Vadim Bendebury7a3f36a2012-04-18 15:47:32 -07004196 report_platform_info();
4197
Stefan Reinauer00636b02012-04-04 00:08:51 +02004198 /* Wait for ME to be ready */
4199 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004200 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004201
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004202 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +02004203
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004204 u32 reg_5d10;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004205
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004206 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004207
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004208 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +02004209
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004210 reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10); // !!! = 0x00000000
4211 if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */
4212 && reg_5d10 && !s3resume) {
4213 write32(DEFAULT_MCHBAR + 0x5d10, 0);
4214 /* Need reset. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02004215 outb(0x6, 0xcf9);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004216
Patrick Georgi546953c2014-11-29 10:38:17 +01004217 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004218 }
Stefan Reinauer00636b02012-04-04 00:08:51 +02004219
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +02004220 memset(&ctrl, 0, sizeof(ctrl));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004221
4222 early_pch_init_native();
4223 early_thermal_init();
4224
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004225 /* try to find timings in MRC cache */
4226 mrc_cache = find_current_mrc_cache();
4227 if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(ctrl))) {
4228 if (s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004229 /* Failed S3 resume, reset to come up cleanly */
4230 outb(0x6, 0xcf9);
4231 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004232 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004233 ctrl_cached = NULL;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004234 } else {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004235 ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004236 }
4237
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004238 /* verify MRC cache for fast boot */
4239 if (ctrl_cached) {
4240 /* check SPD CRC16 to make sure the DIMMs haven't been replaced */
4241 fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
4242 if (!fast_boot)
4243 printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
4244 if (!fast_boot && s3resume) {
4245 /* Failed S3 resume, reset to come up cleanly */
4246 outb(0x6, 0xcf9);
4247 halt();
4248 }
4249 } else
4250 fast_boot = 0;
4251
4252 if (fast_boot) {
4253 printk(BIOS_DEBUG, "Trying stored timings.\n");
4254 memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
4255
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004256 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004257 if (err) {
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004258 if (s3resume) {
4259 /* Failed S3 resume, reset to come up cleanly */
4260 outb(0x6, 0xcf9);
4261 halt();
4262 }
4263 /* no need to erase bad mrc cache here, it gets overwritten on
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004264 * successful boot. */
4265 printk(BIOS_ERR, "Stored timings are invalid !\n");
4266 fast_boot = 0;
4267 }
4268 }
4269 if (!fast_boot) {
4270 ctrl.mobile = mobile;
4271 ctrl.tCK = min_tck;
4272
4273 /* Get DDR3 SPD data */
4274 dram_find_spds_ddr3(spds, &ctrl);
4275
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004276 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004277 }
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004278
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004279 if (err) {
4280 /* fallback: disable failing channel */
4281 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
4282 printram("Disable failing channel.\n");
4283
4284 /* Reset DDR3 frequency */
4285 dram_find_spds_ddr3(spds, &ctrl);
4286
4287 /* disable failing channel */
4288 disable_channel(&ctrl, GET_ERR_CHANNEL(err));
4289
4290 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
4291 }
4292
Patrick Rudolph31d19592016-03-26 12:22:34 +01004293 if (err)
4294 die("raminit failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004295
4296 /* FIXME: should be hardware revision-dependent. */
4297 write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
4298
4299 set_scrambling_seed(&ctrl);
4300
4301 set_42a0(&ctrl);
4302
4303 final_registers(&ctrl);
4304
4305 /* Zone config */
4306 dram_zones(&ctrl, 0);
4307
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004308 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004309 quick_ram_check();
4310
4311 intel_early_me_status();
4312 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
4313 intel_early_me_status();
4314
Stefan Reinauer00636b02012-04-04 00:08:51 +02004315 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004316
4317 cbmem_was_inited = !cbmem_recovery(s3resume);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004318 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004319 save_timings(&ctrl);
4320 if (s3resume && !cbmem_was_inited) {
4321 /* Failed S3 resume, reset to come up cleanly */
4322 outb(0x6, 0xcf9);
4323 halt();
4324 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +01004325
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004326 fill_smbios17(&ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004327}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004328
4329#define HOST_BRIDGE PCI_DEVFN(0, 0)
4330#define DEFAULT_TCK TCK_800MHZ
4331
4332static unsigned int get_mem_min_tck(void)
4333{
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004334 u32 reg32;
4335 u8 rev;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004336 const struct device *dev;
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004337 const struct northbridge_intel_sandybridge_config *cfg = NULL;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004338
4339 dev = dev_find_slot(0, HOST_BRIDGE);
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004340 if (dev)
4341 cfg = dev->chip_info;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004342
4343 /* If this is zero, it just means devicetree.cb didn't set it */
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004344 if (!cfg || cfg->max_mem_clock_mhz == 0) {
4345 rev = pci_read_config8(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004346
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004347 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
4348 /* read Capabilities A Register DMFC bits */
4349 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A);
4350 reg32 &= 0x7;
4351
4352 switch (reg32) {
4353 case 7: return TCK_533MHZ;
4354 case 6: return TCK_666MHZ;
4355 case 5: return TCK_800MHZ;
4356 /* reserved: */
4357 default:
4358 break;
4359 }
4360 } else {
4361 /* read Capabilities B Register DMFC bits */
4362 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
4363 reg32 = (reg32 >> 4) & 0x7;
4364
4365 switch (reg32) {
4366 case 7: return TCK_533MHZ;
4367 case 6: return TCK_666MHZ;
4368 case 5: return TCK_800MHZ;
4369 case 4: return TCK_933MHZ;
4370 case 3: return TCK_1066MHZ;
4371 case 2: return TCK_1200MHZ;
4372 case 1: return TCK_1333MHZ;
4373 /* reserved: */
4374 default:
4375 break;
4376 }
4377 }
4378 return DEFAULT_TCK;
4379 } else {
Patrick Rudolph7bddd302016-06-11 18:39:35 +02004380 if (cfg->max_mem_clock_mhz >= 1066)
4381 return TCK_1066MHZ;
4382 else if (cfg->max_mem_clock_mhz >= 933)
4383 return TCK_933MHZ;
4384 else if (cfg->max_mem_clock_mhz >= 800)
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004385 return TCK_800MHZ;
4386 else if (cfg->max_mem_clock_mhz >= 666)
4387 return TCK_666MHZ;
4388 else if (cfg->max_mem_clock_mhz >= 533)
4389 return TCK_533MHZ;
4390 else
4391 return TCK_400MHZ;
4392 }
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004393}
4394
Patrick Rudolph266a1f72016-06-09 18:13:34 +02004395#define DEFAULT_PCI_MMIO_SIZE 2048
4396
4397static unsigned int get_mmio_size(void)
4398{
4399 const struct device *dev;
4400 const struct northbridge_intel_sandybridge_config *cfg = NULL;
4401
4402 dev = dev_find_slot(0, HOST_BRIDGE);
4403 if (dev)
4404 cfg = dev->chip_info;
4405
4406 /* If this is zero, it just means devicetree.cb didn't set it */
4407 if (!cfg || cfg->pci_mmio_size == 0)
4408 return DEFAULT_PCI_MMIO_SIZE;
4409 else
4410 return cfg->pci_mmio_size;
4411}
4412
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004413void perform_raminit(int s3resume)
4414{
4415 spd_raw_data spd[4];
4416
4417 post_code(0x3a);
4418
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +02004419 memset (spd, 0, sizeof(spd));
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004420 mainboard_get_spd(spd);
4421
4422 timestamp_add_now(TS_BEFORE_INITRAM);
4423
4424 init_dram_ddr3(spd, 1, get_mem_min_tck(), s3resume);
4425}