blob: 33c88f3f07d54d4ae904e48e9b73e82a9be543f3 [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]));
258}
259
260/*
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100261 * Fill cbmem with information for SMBIOS type 17.
262 */
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100263static void fill_smbios17(ramctr_timing *ctrl)
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100264{
265 struct memory_info *mem_info;
266 int channel, slot;
267 struct dimm_info *dimm;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100268 uint16_t ddr_freq;
269 dimm_info *info = &ctrl->info;
270
271 ddr_freq = (1000 << 8) / ctrl->tCK;
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100272
273 /*
274 * Allocate CBMEM area for DIMM information used to populate SMBIOS
275 * table 17
276 */
277 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
278 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
279 if (!mem_info)
280 return;
281
282 memset(mem_info, 0, sizeof(*mem_info));
283
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200284 FOR_ALL_CHANNELS for (slot = 0; slot < NUM_SLOTS; slot++) {
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100285 dimm = &mem_info->dimm[mem_info->dimm_cnt];
286 if (info->dimm[channel][slot].size_mb) {
287 dimm->ddr_type = MEMORY_TYPE_DDR3;
288 dimm->ddr_frequency = ddr_freq;
289 dimm->dimm_size = info->dimm[channel][slot].size_mb;
290 dimm->channel_num = channel;
291 dimm->rank_per_dimm = info->dimm[channel][slot].ranks;
292 dimm->dimm_num = slot;
293 memcpy(dimm->module_part_number,
294 info->dimm[channel][slot].part_number, 16);
295 dimm->mod_id = info->dimm[channel][slot].manufacturer_id;
296 dimm->mod_type = info->dimm[channel][slot].dimm_type;
297 dimm->bus_width = info->dimm[channel][slot].width;
298 mem_info->dimm_cnt++;
299 }
300 }
301}
302
303/*
Stefan Reinauer00636b02012-04-04 00:08:51 +0200304 * Dump in the log memory controller configuration as read from the memory
305 * controller registers.
306 */
307static void report_memory_config(void)
308{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700309 u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200310 int i;
311
312 addr_decoder_common = MCHBAR32(0x5000);
313 addr_decode_ch[0] = MCHBAR32(0x5004);
314 addr_decode_ch[1] = MCHBAR32(0x5008);
315
316 printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
Patrick Rudolph069018d2016-11-12 11:43:59 +0100317 (MCHBAR32(MC_BIOS_DATA) * 13333 * 2 + 50) / 100);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200318 printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700319 addr_decoder_common & 3, (addr_decoder_common >> 2) & 3,
Stefan Reinauer00636b02012-04-04 00:08:51 +0200320 (addr_decoder_common >> 4) & 3);
321
322 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
323 u32 ch_conf = addr_decode_ch[i];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700324 printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i,
325 ch_conf);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200326 printk(BIOS_DEBUG, " ECC %s\n",
327 ecc_decoder[(ch_conf >> 24) & 3]);
328 printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
329 ((ch_conf >> 22) & 1) ? "on" : "off");
330 printk(BIOS_DEBUG, " rank interleave %s\n",
331 ((ch_conf >> 21) & 1) ? "on" : "off");
332 printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n",
333 ((ch_conf >> 0) & 0xff) * 256,
334 ((ch_conf >> 19) & 1) ? 16 : 8,
335 ((ch_conf >> 17) & 1) ? "dual" : "single",
336 ((ch_conf >> 16) & 1) ? "" : ", selected");
337 printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n",
338 ((ch_conf >> 8) & 0xff) * 256,
339 ((ch_conf >> 20) & 1) ? 16 : 8,
340 ((ch_conf >> 18) & 1) ? "dual" : "single",
341 ((ch_conf >> 16) & 1) ? ", selected" : "");
342 }
343}
344
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100345/*
346 * Return CRC16 match for all SPDs.
347 */
348static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
349{
350 int channel, slot, spd_slot;
351 int match = 1;
352
353 FOR_ALL_CHANNELS {
354 for (slot = 0; slot < NUM_SLOTS; slot++) {
355 spd_slot = 2 * channel + slot;
356 match &= ctrl->spd_crc[channel][slot] ==
357 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
358 }
359 }
360 return match;
361}
362
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700363void read_spd(spd_raw_data * spd, u8 addr)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200364{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700365 int j;
366 for (j = 0; j < 256; j++)
367 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
368}
369
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100370static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700371{
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100372 int dimms = 0, dimms_on_channel;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700373 int channel, slot, spd_slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100374 dimm_info *dimm = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700375
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +0200376 memset (ctrl->rankmap, 0, sizeof(ctrl->rankmap));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700377
378 ctrl->extended_temperature_range = 1;
379 ctrl->auto_self_refresh = 1;
380
381 FOR_ALL_CHANNELS {
382 ctrl->channel_size_mb[channel] = 0;
383
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100384 dimms_on_channel = 0;
385 /* count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700386 for (slot = 0; slot < NUM_SLOTS; slot++) {
387 spd_slot = 2 * channel + slot;
388 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100389 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
390 dimms_on_channel++;
391 }
392
393 for (slot = 0; slot < NUM_SLOTS; slot++) {
394 spd_slot = 2 * channel + slot;
395 /* search for XMP profile */
396 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
397 spd[spd_slot],
398 DDR3_XMP_PROFILE_1);
399
400 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
401 printram("No valid XMP profile found.\n");
402 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
403 } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
404 printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
405 dimm->dimm[channel][slot].dimms_per_channel,
406 dimms_on_channel);
407 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
408 } else if (dimm->dimm[channel][slot].voltage != 1500) {
409 /* TODO: support other DDR3 voltage than 1500mV */
410 printram("XMP profile's requested %u mV is unsupported.\n",
411 dimm->dimm[channel][slot].voltage);
412 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
413 }
414
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100415 /* fill in CRC16 for MRC cache */
416 ctrl->spd_crc[channel][slot] =
417 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
418
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700419 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
420 // set dimm invalid
421 dimm->dimm[channel][slot].ranks = 0;
422 dimm->dimm[channel][slot].size_mb = 0;
423 continue;
424 }
425
426 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
427 dimms++;
428 ctrl->rank_mirror[channel][slot * 2] = 0;
429 ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
430 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
431
432 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
433 ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
434
435 ctrl->rankmap[channel] |= ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100436 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n",
437 channel, ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700438 }
439 if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc)
440 && dimm->dimm[channel][0].reference_card <= 5 && dimm->dimm[channel][1].reference_card <= 5) {
441 const int ref_card_offset_table[6][6] = {
442 { 0, 0, 0, 0, 2, 2, },
443 { 0, 0, 0, 0, 2, 2, },
444 { 0, 0, 0, 0, 2, 2, },
445 { 0, 0, 0, 0, 1, 1, },
446 { 2, 2, 2, 1, 0, 0, },
447 { 2, 2, 2, 1, 0, 0, },
448 };
449 ctrl->ref_card_offset[channel] = ref_card_offset_table[dimm->dimm[channel][0].reference_card]
450 [dimm->dimm[channel][1].reference_card];
451 } else
452 ctrl->ref_card_offset[channel] = 0;
453 }
454
455 if (!dimms)
456 die("No DIMMs were found");
457}
458
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100459static void dram_find_common_params(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700460{
461 size_t valid_dimms;
462 int channel, slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100463 dimm_info *dimms = &ctrl->info;
464
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700465 ctrl->cas_supported = 0xff;
466 valid_dimms = 0;
467 FOR_ALL_CHANNELS for (slot = 0; slot < 2; slot++) {
468 const dimm_attr *dimm = &dimms->dimm[channel][slot];
469 if (dimm->dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3)
470 continue;
471 valid_dimms++;
472
473 /* Find all possible CAS combinations */
474 ctrl->cas_supported &= dimm->cas_supported;
475
476 /* Find the smallest common latencies supported by all DIMMs */
477 ctrl->tCK = MAX(ctrl->tCK, dimm->tCK);
478 ctrl->tAA = MAX(ctrl->tAA, dimm->tAA);
479 ctrl->tWR = MAX(ctrl->tWR, dimm->tWR);
480 ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD);
481 ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD);
482 ctrl->tRP = MAX(ctrl->tRP, dimm->tRP);
483 ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS);
484 ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC);
485 ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR);
486 ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP);
487 ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW);
488 }
489
490 if (!ctrl->cas_supported)
491 die("Unsupported DIMM combination. "
492 "DIMMS do not support common CAS latency");
493 if (!valid_dimms)
494 die("No valid DIMMs found");
495}
496
Patrick Rudolphbec66962016-11-11 19:17:56 +0100497/* CAS write latency. To be programmed in MR2.
498 * See DDR3 SPEC for MR2 documentation. */
499static u8 get_CWL(u32 tCK)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700500{
Patrick Rudolphbec66962016-11-11 19:17:56 +0100501 /* Get CWL based on tCK using the following rule: */
502 switch (tCK) {
503 case TCK_1333MHZ:
504 return 12;
505 case TCK_1200MHZ:
506 case TCK_1100MHZ:
507 return 11;
508 case TCK_1066MHZ:
509 case TCK_1000MHZ:
510 return 10;
511 case TCK_933MHZ:
512 case TCK_900MHZ:
513 return 9;
514 case TCK_800MHZ:
515 case TCK_700MHZ:
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700516 return 8;
Patrick Rudolphbec66962016-11-11 19:17:56 +0100517 case TCK_666MHZ:
518 return 7;
519 case TCK_533MHZ:
520 return 6;
521 default:
522 return 5;
523 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700524}
525
526/* Frequency multiplier. */
527static u32 get_FRQ(u32 tCK)
528{
529 u32 FRQ;
530 FRQ = 256000 / (tCK * BASEFREQ);
531 if (FRQ > 8)
532 return 8;
533 if (FRQ < 3)
534 return 3;
535 return FRQ;
536}
537
538static u32 get_REFI(u32 tCK)
539{
540 /* Get REFI based on MCU frequency using the following rule:
541 * _________________________________________
542 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
543 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 |
544 */
545 static const u32 frq_refi_map[] =
546 { 3120, 4160, 5200, 6240, 7280, 8320 };
547 return frq_refi_map[get_FRQ(tCK) - 3];
548}
549
550static u8 get_XSOffset(u32 tCK)
551{
552 /* Get XSOffset based on MCU frequency using the following rule:
553 * _________________________
554 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
555 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 |
556 */
557 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 };
558 return frq_xs_map[get_FRQ(tCK) - 3];
559}
560
561static u8 get_MOD(u32 tCK)
562{
563 /* Get MOD based on MCU frequency using the following rule:
564 * _____________________________
565 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
566 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 |
567 */
568 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 };
569 return frq_mod_map[get_FRQ(tCK) - 3];
570}
571
572static u8 get_WLO(u32 tCK)
573{
574 /* Get WLO based on MCU frequency using the following rule:
575 * _______________________
576 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
577 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 |
578 */
579 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 };
580 return frq_wlo_map[get_FRQ(tCK) - 3];
581}
582
583static u8 get_CKE(u32 tCK)
584{
585 /* Get CKE based on MCU frequency using the following rule:
586 * _______________________
587 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
588 * CKE : | 3 | 3 | 4 | 4 | 5 | 6 |
589 */
590 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 };
591 return frq_cke_map[get_FRQ(tCK) - 3];
592}
593
594static u8 get_XPDLL(u32 tCK)
595{
596 /* Get XPDLL based on MCU frequency using the following rule:
597 * _____________________________
598 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
599 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 |
600 */
601 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 };
602 return frq_xpdll_map[get_FRQ(tCK) - 3];
603}
604
605static u8 get_XP(u32 tCK)
606{
607 /* Get XP based on MCU frequency using the following rule:
608 * _______________________
609 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
610 * XP : | 3 | 4 | 4 | 5 | 6 | 7 |
611 */
612 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 };
613 return frq_xp_map[get_FRQ(tCK) - 3];
614}
615
616static u8 get_AONPD(u32 tCK)
617{
618 /* Get AONPD based on MCU frequency using the following rule:
619 * ________________________
620 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
621 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 |
622 */
623 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 };
624 return frq_aonpd_map[get_FRQ(tCK) - 3];
625}
626
627static u32 get_COMP2(u32 tCK)
628{
629 /* Get COMP2 based on MCU frequency using the following rule:
630 * ___________________________________________________________
631 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
632 * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C |
633 */
634 static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C,
635 0xC6369CC, 0xC42514C, 0xC21410C
636 };
637 return frq_comp2_map[get_FRQ(tCK) - 3];
638}
639
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100640static u32 get_XOVER_CLK(u8 rankmap)
641{
642 return rankmap << 24;
643}
644
645static u32 get_XOVER_CMD(u8 rankmap)
646{
647 u32 reg;
648
649 // enable xover cmd
650 reg = 0x4000;
651
652 // enable xover ctl
653 if (rankmap & 0x3)
654 reg |= 0x20000;
655
656 if (rankmap & 0xc)
657 reg |= 0x4000000;
658
659 return reg;
660}
661
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700662static void dram_timing(ramctr_timing * ctrl)
663{
664 u8 val;
665 u32 val32;
666
667 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
668 * we cap it if we have faster DIMMs.
669 * Then, align it to the closest JEDEC standard frequency */
670 if (ctrl->tCK <= TCK_1066MHZ) {
671 ctrl->tCK = TCK_1066MHZ;
672 ctrl->edge_offset[0] = 16;
673 ctrl->edge_offset[1] = 7;
674 ctrl->edge_offset[2] = 7;
675 ctrl->timC_offset[0] = 18;
676 ctrl->timC_offset[1] = 7;
677 ctrl->timC_offset[2] = 7;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700678 ctrl->reg_320c_range_threshold = 13;
679 } else if (ctrl->tCK <= TCK_933MHZ) {
680 ctrl->tCK = TCK_933MHZ;
681 ctrl->edge_offset[0] = 14;
682 ctrl->edge_offset[1] = 6;
683 ctrl->edge_offset[2] = 6;
684 ctrl->timC_offset[0] = 15;
685 ctrl->timC_offset[1] = 6;
686 ctrl->timC_offset[2] = 6;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700687 ctrl->reg_320c_range_threshold = 15;
688 } else if (ctrl->tCK <= TCK_800MHZ) {
689 ctrl->tCK = TCK_800MHZ;
690 ctrl->edge_offset[0] = 13;
691 ctrl->edge_offset[1] = 5;
692 ctrl->edge_offset[2] = 5;
693 ctrl->timC_offset[0] = 14;
694 ctrl->timC_offset[1] = 5;
695 ctrl->timC_offset[2] = 5;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700696 ctrl->reg_320c_range_threshold = 15;
697 } else if (ctrl->tCK <= TCK_666MHZ) {
698 ctrl->tCK = TCK_666MHZ;
699 ctrl->edge_offset[0] = 10;
700 ctrl->edge_offset[1] = 4;
701 ctrl->edge_offset[2] = 4;
702 ctrl->timC_offset[0] = 11;
703 ctrl->timC_offset[1] = 4;
704 ctrl->timC_offset[2] = 4;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700705 ctrl->reg_320c_range_threshold = 16;
706 } else if (ctrl->tCK <= TCK_533MHZ) {
707 ctrl->tCK = TCK_533MHZ;
708 ctrl->edge_offset[0] = 8;
709 ctrl->edge_offset[1] = 3;
710 ctrl->edge_offset[2] = 3;
711 ctrl->timC_offset[0] = 9;
712 ctrl->timC_offset[1] = 3;
713 ctrl->timC_offset[2] = 3;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700714 ctrl->reg_320c_range_threshold = 17;
715 } else {
716 ctrl->tCK = TCK_400MHZ;
717 ctrl->edge_offset[0] = 6;
718 ctrl->edge_offset[1] = 2;
719 ctrl->edge_offset[2] = 2;
720 ctrl->timC_offset[0] = 6;
721 ctrl->timC_offset[1] = 2;
722 ctrl->timC_offset[2] = 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700723 ctrl->reg_320c_range_threshold = 17;
724 }
725
Patrick Rudolphd4c53e32016-06-14 20:07:32 +0200726 /* Initial phase between CLK/CMD pins */
727 ctrl->reg_c14_offset = (256000 / ctrl->tCK) / 66;
728
Patrick Rudolphb7b1b282016-06-14 18:44:28 +0200729 /* DLL_CONFIG_MDLL_W_TIMER */
730 ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3;
731
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700732 val32 = (1000 << 8) / ctrl->tCK;
733 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
734
Patrick Rudolphbec66962016-11-11 19:17:56 +0100735 /* Find CAS latency */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700736 val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK;
737 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
738 /* Find lowest supported CAS latency that satisfies the minimum value */
739 while (!((ctrl->cas_supported >> (val - 4)) & 1)
740 && (ctrl->cas_supported >> (val - 4))) {
741 val++;
742 }
743 /* Is CAS supported */
Patrick Rudolph55409eb2016-06-15 20:28:32 +0200744 if (!(ctrl->cas_supported & (1 << (val - 4)))) {
745 printk(BIOS_ERR, "CAS %uT not supported. ", val);
746 val = 18;
747 /* Find highest supported CAS latency */
748 while (!((ctrl->cas_supported >> (val - 4)) & 1))
749 val--;
750
751 printk(BIOS_ERR, "Using CAS %uT instead.\n", val);
752 }
753
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700754 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
755 ctrl->CAS = val;
Patrick Rudolphbec66962016-11-11 19:17:56 +0100756 ctrl->CWL = get_CWL(ctrl->tCK);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700757 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
758
759 /* Find tRCD */
760 ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK;
761 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
762
763 ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK;
764 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
765
766 /* Find tRAS */
767 ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK;
768 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
769
770 /* Find tWR */
771 ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK;
772 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
773
774 /* Find tFAW */
775 ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK;
776 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
777
778 /* Find tRRD */
779 ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK;
780 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
781
782 /* Find tRTP */
783 ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK;
784 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
785
786 /* Find tWTR */
787 ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK;
788 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
789
790 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
791 ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK;
792 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
793
794 ctrl->tREFI = get_REFI(ctrl->tCK);
795 ctrl->tMOD = get_MOD(ctrl->tCK);
796 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
797 ctrl->tWLO = get_WLO(ctrl->tCK);
798 ctrl->tCKE = get_CKE(ctrl->tCK);
799 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
800 ctrl->tXP = get_XP(ctrl->tCK);
801 ctrl->tAONPD = get_AONPD(ctrl->tCK);
802}
803
804static void dram_freq(ramctr_timing * ctrl)
805{
806 if (ctrl->tCK > TCK_400MHZ) {
807 printk (BIOS_ERR, "DRAM frequency is under lowest supported frequency (400 MHz). Increasing to 400 MHz as last resort");
808 ctrl->tCK = TCK_400MHZ;
809 }
810 while (1) {
811 u8 val2;
812 u32 reg1 = 0;
813
814 /* Step 1 - Set target PCU frequency */
815
816 if (ctrl->tCK <= TCK_1066MHZ) {
817 ctrl->tCK = TCK_1066MHZ;
818 } else if (ctrl->tCK <= TCK_933MHZ) {
819 ctrl->tCK = TCK_933MHZ;
820 } else if (ctrl->tCK <= TCK_800MHZ) {
821 ctrl->tCK = TCK_800MHZ;
822 } else if (ctrl->tCK <= TCK_666MHZ) {
823 ctrl->tCK = TCK_666MHZ;
824 } else if (ctrl->tCK <= TCK_533MHZ) {
825 ctrl->tCK = TCK_533MHZ;
826 } else if (ctrl->tCK <= TCK_400MHZ) {
827 ctrl->tCK = TCK_400MHZ;
828 } else {
829 die ("No lock frequency found");
830 }
831
832 /* Frequency mulitplier. */
833 u32 FRQ = get_FRQ(ctrl->tCK);
834
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100835 /* The PLL will never lock if the required frequency is
836 * already set. Exit early to prevent a system hang.
837 */
Patrick Rudolph069018d2016-11-12 11:43:59 +0100838 reg1 = MCHBAR32(MC_BIOS_DATA);
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100839 val2 = (u8) reg1;
Patrick Rudolphf7047542016-11-12 11:39:57 +0100840 if (val2)
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100841 return;
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100842
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700843 /* Step 2 - Select frequency in the MCU */
844 reg1 = FRQ;
845 reg1 |= 0x80000000; // set running bit
Patrick Rudolph069018d2016-11-12 11:43:59 +0100846 MCHBAR32(MC_BIOS_REQ) = reg1;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700847 while (reg1 & 0x80000000) {
848 printk(BIOS_DEBUG, " PLL busy...");
Patrick Rudolph069018d2016-11-12 11:43:59 +0100849 reg1 = MCHBAR32(MC_BIOS_REQ);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700850 }
851 printk(BIOS_DEBUG, "done\n");
852
853 /* Step 3 - Verify lock frequency */
Patrick Rudolph069018d2016-11-12 11:43:59 +0100854 reg1 = MCHBAR32(MC_BIOS_DATA);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700855 val2 = (u8) reg1;
856 if (val2 >= FRQ) {
857 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
858 (1000 << 8) / ctrl->tCK);
859 return;
860 }
861 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
862 ctrl->tCK++;
863 }
864}
865
866static void dram_xover(ramctr_timing * ctrl)
867{
868 u32 reg;
869 int channel;
870
871 FOR_ALL_CHANNELS {
872 // enable xover clk
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100873 reg = get_XOVER_CLK(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100874 printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
875 reg);
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100876 MCHBAR32(channel * 0x100 + 0xc14) = reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700877
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100878 // enable xover ctl & xover cmd
879 reg = get_XOVER_CMD(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100880 printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
881 reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700882 MCHBAR32(0x100 * channel + 0x320c) = reg;
883 }
884}
885
886static void dram_timing_regs(ramctr_timing * ctrl)
887{
888 u32 reg, addr, val32, cpu, stretch;
889 struct cpuid_result cpures;
890 int channel;
891
892 FOR_ALL_CHANNELS {
893 // DBP
894 reg = 0;
895 reg |= ctrl->tRCD;
896 reg |= (ctrl->tRP << 4);
897 reg |= (ctrl->CAS << 8);
898 reg |= (ctrl->CWL << 12);
899 reg |= (ctrl->tRAS << 16);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100900 printram("DBP [%x] = %x\n", 0x400 * channel + 0x4000, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700901 MCHBAR32(0x400 * channel + 0x4000) = reg;
902
903 // RAP
904 reg = 0;
905 reg |= ctrl->tRRD;
906 reg |= (ctrl->tRTP << 4);
907 reg |= (ctrl->tCKE << 8);
908 reg |= (ctrl->tWTR << 12);
909 reg |= (ctrl->tFAW << 16);
910 reg |= (ctrl->tWR << 24);
911 reg |= (3 << 30);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100912 printram("RAP [%x] = %x\n", 0x400 * channel + 0x4004, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700913 MCHBAR32(0x400 * channel + 0x4004) = reg;
914
915 // OTHP
916 addr = 0x400 * channel + 0x400c;
917 reg = 0;
918 reg |= ctrl->tXPDLL;
919 reg |= (ctrl->tXP << 5);
920 reg |= (ctrl->tAONPD << 8);
921 reg |= 0xa0000;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100922 printram("OTHP [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700923 MCHBAR32(addr) = reg;
924
925 MCHBAR32(0x400 * channel + 0x4014) = 0;
926
927 MCHBAR32(addr) |= 0x00020000;
928
929 // ODT stretch
930 reg = 0;
931
Ryan Salsamendie4da9aa2016-06-24 12:01:11 -0700932 cpures = cpuid(1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700933 cpu = cpures.eax;
934 if (IS_IVY_CPU(cpu)
935 || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) {
936 stretch = 2;
937 addr = 0x400 * channel + 0x400c;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100938 printram("ODT stretch [%x] = %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700939 0x400 * channel + 0x400c, reg);
940 reg = MCHBAR32(addr);
941
942 if (((ctrl->rankmap[channel] & 3) == 0)
943 || (ctrl->rankmap[channel] & 0xc) == 0) {
944
945 // Rank 0 - operate on rank 2
946 reg = (reg & ~0xc0000) | (stretch << 18);
947
948 // Rank 2 - operate on rank 0
949 reg = (reg & ~0x30000) | (stretch << 16);
950
Patrick Rudolpha649a542016-01-17 18:32:06 +0100951 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700952 MCHBAR32(addr) = reg;
953 }
954
955 } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) {
956 stretch = 3;
957 addr = 0x400 * channel + 0x401c;
958 reg = MCHBAR32(addr);
959
960 if (((ctrl->rankmap[channel] & 3) == 0)
961 || (ctrl->rankmap[channel] & 0xc) == 0) {
962
963 // Rank 0 - operate on rank 2
964 reg = (reg & ~0x3000) | (stretch << 12);
965
966 // Rank 2 - operate on rank 0
967 reg = (reg & ~0xc00) | (stretch << 10);
968
Patrick Rudolpha649a542016-01-17 18:32:06 +0100969 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700970 MCHBAR32(addr) = reg;
971 }
972 } else {
973 stretch = 0;
974 }
975
976 // REFI
977 reg = 0;
978 val32 = ctrl->tREFI;
979 reg = (reg & ~0xffff) | val32;
980 val32 = ctrl->tRFC;
981 reg = (reg & ~0x1ff0000) | (val32 << 16);
982 val32 = (u32) (ctrl->tREFI * 9) / 1024;
983 reg = (reg & ~0xfe000000) | (val32 << 25);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100984 printram("REFI [%x] = %x\n", 0x400 * channel + 0x4298,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700985 reg);
986 MCHBAR32(0x400 * channel + 0x4298) = reg;
987
988 MCHBAR32(0x400 * channel + 0x4294) |= 0xff;
989
990 // SRFTP
991 reg = 0;
992 val32 = tDLLK;
993 reg = (reg & ~0xfff) | val32;
994 val32 = ctrl->tXSOffset;
995 reg = (reg & ~0xf000) | (val32 << 12);
996 val32 = tDLLK - ctrl->tXSOffset;
997 reg = (reg & ~0x3ff0000) | (val32 << 16);
998 val32 = ctrl->tMOD - 8;
999 reg = (reg & ~0xf0000000) | (val32 << 28);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001000 printram("SRFTP [%x] = %x\n", 0x400 * channel + 0x42a4,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001001 reg);
1002 MCHBAR32(0x400 * channel + 0x42a4) = reg;
1003 }
1004}
1005
Patrick Rudolph735ecce2016-03-26 10:42:27 +01001006static void dram_dimm_mapping(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001007{
1008 u32 reg, val32;
1009 int channel;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01001010 dimm_info *info = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001011
1012 FOR_ALL_CHANNELS {
1013 dimm_attr *dimmA = 0;
1014 dimm_attr *dimmB = 0;
1015 reg = 0;
1016 val32 = 0;
1017 if (info->dimm[channel][0].size_mb >=
1018 info->dimm[channel][1].size_mb) {
1019 // dimm 0 is bigger, set it to dimmA
1020 dimmA = &info->dimm[channel][0];
1021 dimmB = &info->dimm[channel][1];
1022 reg |= (0 << 16);
1023 } else {
1024 // dimm 1 is bigger, set it to dimmA
1025 dimmA = &info->dimm[channel][1];
1026 dimmB = &info->dimm[channel][0];
1027 reg |= (1 << 16);
1028 }
1029 // dimmA
1030 if (dimmA && (dimmA->ranks > 0)) {
1031 val32 = dimmA->size_mb / 256;
1032 reg = (reg & ~0xff) | val32;
1033 val32 = dimmA->ranks - 1;
1034 reg = (reg & ~0x20000) | (val32 << 17);
1035 val32 = (dimmA->width / 8) - 1;
1036 reg = (reg & ~0x80000) | (val32 << 19);
1037 }
1038 // dimmB
1039 if (dimmB && (dimmB->ranks > 0)) {
1040 val32 = dimmB->size_mb / 256;
1041 reg = (reg & ~0xff00) | (val32 << 8);
1042 val32 = dimmB->ranks - 1;
1043 reg = (reg & ~0x40000) | (val32 << 18);
1044 val32 = (dimmB->width / 8) - 1;
1045 reg = (reg & ~0x100000) | (val32 << 20);
1046 }
1047 reg = (reg & ~0x200000) | (1 << 21); // rank interleave
1048 reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave
1049
1050 // Save MAD-DIMM register
1051 if ((dimmA && (dimmA->ranks > 0))
1052 || (dimmB && (dimmB->ranks > 0))) {
1053 ctrl->mad_dimm[channel] = reg;
1054 } else {
1055 ctrl->mad_dimm[channel] = 0;
1056 }
1057 }
1058}
1059
1060static void dram_dimm_set_mapping(ramctr_timing * ctrl)
1061{
1062 int channel;
1063 FOR_ALL_CHANNELS {
1064 MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
1065 }
1066}
1067
1068static void dram_zones(ramctr_timing * ctrl, int training)
1069{
1070 u32 reg, ch0size, ch1size;
1071 u8 val;
1072 reg = 0;
1073 val = 0;
1074 if (training) {
1075 ch0size = ctrl->channel_size_mb[0] ? 256 : 0;
1076 ch1size = ctrl->channel_size_mb[1] ? 256 : 0;
1077 } else {
1078 ch0size = ctrl->channel_size_mb[0];
1079 ch1size = ctrl->channel_size_mb[1];
1080 }
1081
1082 if (ch0size >= ch1size) {
1083 reg = MCHBAR32(0x5014);
1084 val = ch1size / 256;
1085 reg = (reg & ~0xff000000) | val << 24;
1086 reg = (reg & ~0xff0000) | (2 * val) << 16;
1087 MCHBAR32(0x5014) = reg;
1088 MCHBAR32(0x5000) = 0x24;
1089 } else {
1090 reg = MCHBAR32(0x5014);
1091 val = ch0size / 256;
1092 reg = (reg & ~0xff000000) | val << 24;
1093 reg = (reg & ~0xff0000) | (2 * val) << 16;
1094 MCHBAR32(0x5014) = reg;
1095 MCHBAR32(0x5000) = 0x21;
1096 }
1097}
1098
1099static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
1100{
1101 u32 reg, val, reclaim;
1102 u32 tom, gfxstolen, gttsize;
1103 size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase,
1104 tsegbase, mestolenbase;
1105 size_t tsegbasedelta, remapbase, remaplimit;
1106 uint16_t ggc;
1107
Patrick Rudolph266a1f72016-06-09 18:13:34 +02001108 mmiosize = get_mmio_size();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001109
1110 ggc = pci_read_config16(NORTHBRIDGE, GGC);
1111 if (!(ggc & 2)) {
1112 gfxstolen = ((ggc >> 3) & 0x1f) * 32;
1113 gttsize = ((ggc >> 8) & 0x3);
1114 } else {
1115 gfxstolen = 0;
1116 gttsize = 0;
1117 }
1118
1119 tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
1120
1121 tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
1122
1123 mestolenbase = tom - me_uma_size;
1124
1125 toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
1126 tom - me_uma_size);
1127 gfxstolenbase = toludbase - gfxstolen;
1128 gttbase = gfxstolenbase - gttsize;
1129
1130 tsegbase = gttbase - tsegsize;
1131
1132 // Round tsegbase down to nearest address aligned to tsegsize
1133 tsegbasedelta = tsegbase & (tsegsize - 1);
1134 tsegbase &= ~(tsegsize - 1);
1135
1136 gttbase -= tsegbasedelta;
1137 gfxstolenbase -= tsegbasedelta;
1138 toludbase -= tsegbasedelta;
1139
Elyes HAOUAS15279a92016-07-28 21:05:26 +02001140 // Test if it is possible to reclaim a hole in the RAM addressing
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001141 if (tom - me_uma_size > toludbase) {
1142 // Reclaim is possible
1143 reclaim = 1;
1144 remapbase = MAX(4096, tom - me_uma_size);
1145 remaplimit =
1146 remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1;
1147 touudbase = remaplimit + 1;
1148 } else {
1149 // Reclaim not possible
1150 reclaim = 0;
1151 touudbase = tom - me_uma_size;
1152 }
1153
1154 // Update memory map in pci-e configuration space
Patrick Rudolpha649a542016-01-17 18:32:06 +01001155 printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001156
1157 // TOM (top of memory)
1158 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0);
1159 val = tom & 0xfff;
1160 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001161 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001162 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg);
1163
1164 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4);
1165 val = tom & 0xfffff000;
1166 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001167 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001168 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg);
1169
1170 // TOLUD (top of low used dram)
1171 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
1172 val = toludbase & 0xfff;
1173 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001174 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xbc, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001175 pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg);
1176
1177 // TOUUD LSB (top of upper usable dram)
1178 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
1179 val = touudbase & 0xfff;
1180 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001181 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001182 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg);
1183
1184 // TOUUD MSB
1185 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
1186 val = touudbase & 0xfffff000;
1187 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001188 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xac, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001189 pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg);
1190
1191 if (reclaim) {
1192 // REMAP BASE
1193 pcie_write_config32(PCI_DEV(0, 0, 0), 0x90, remapbase << 20);
1194 pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, remapbase >> 12);
1195
1196 // REMAP LIMIT
1197 pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
1198 pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
1199 }
1200 // TSEG
1201 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
1202 val = tsegbase & 0xfff;
1203 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001204 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001205 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg);
1206
1207 // GFX stolen memory
1208 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0);
1209 val = gfxstolenbase & 0xfff;
1210 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001211 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001212 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg);
1213
1214 // GTT stolen memory
1215 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4);
1216 val = gttbase & 0xfff;
1217 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001218 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001219 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
1220
1221 if (me_uma_size) {
1222 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
1223 val = (0x80000 - me_uma_size) & 0xfffff000;
1224 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001225 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x7c, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001226 pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg);
1227
1228 // ME base
1229 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70);
1230 val = mestolenbase & 0xfff;
1231 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001232 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x70, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001233 pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg);
1234
1235 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74);
1236 val = mestolenbase & 0xfffff000;
1237 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001238 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x74, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001239 pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg);
1240
1241 // ME mask
1242 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78);
1243 val = (0x80000 - me_uma_size) & 0xfff;
1244 reg = (reg & ~0xfff00000) | (val << 20);
1245 reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem
1246
1247 reg = (reg & ~0x800) | (1 << 11); // set ME memory enable
Patrick Rudolpha649a542016-01-17 18:32:06 +01001248 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x78, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001249 pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg);
1250 }
1251}
1252
1253static void dram_ioregs(ramctr_timing * ctrl)
1254{
1255 u32 reg, comp2;
1256
1257 int channel;
1258
1259 // IO clock
1260 FOR_ALL_CHANNELS {
1261 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
1262 }
1263
1264 // IO command
1265 FOR_ALL_CHANNELS {
1266 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
1267 }
1268
1269 // IO control
1270 FOR_ALL_POPULATED_CHANNELS {
1271 program_timings(ctrl, channel);
1272 }
1273
1274 // Rcomp
Patrick Rudolpha649a542016-01-17 18:32:06 +01001275 printram("RCOMP...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001276 reg = 0;
1277 while (reg == 0) {
1278 reg = MCHBAR32(0x5084) & 0x10000;
1279 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001280 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001281
1282 // Set comp2
1283 comp2 = get_COMP2(ctrl->tCK);
1284 MCHBAR32(0x3714) = comp2;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001285 printram("COMP2 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001286
1287 // Set comp1
1288 FOR_ALL_POPULATED_CHANNELS {
1289 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
1290 reg = (reg & ~0xe00) | (1 << 9); //odt
1291 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
1292 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
1293 MCHBAR32(0x1810 + channel * 0x100) = reg;
1294 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001295 printram("COMP1 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001296
Patrick Rudolpha649a542016-01-17 18:32:06 +01001297 printram("FORCE RCOMP and wait 20us...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001298 MCHBAR32(0x5f08) |= 0x100;
1299 udelay(20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001300 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001301}
1302
1303static void wait_428c(int channel)
1304{
1305 while (1) {
1306 if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
1307 return;
1308 }
1309}
1310
1311static void write_reset(ramctr_timing * ctrl)
1312{
1313 int channel, slotrank;
1314
1315 /* choose a populated channel. */
1316 channel = (ctrl->rankmap[0]) ? 0 : 1;
1317
1318 wait_428c(channel);
1319
1320 /* choose a populated rank. */
1321 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
1322
Patrick Rudolph371d2912015-10-09 13:33:25 +02001323 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001324 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1325 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01);
1326
1327 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1328 (slotrank << 24) | 0x60000);
1329
1330 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1331
1332 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001);
1333 wait_428c(channel);
1334}
1335
1336static void dram_jedecreset(ramctr_timing * ctrl)
1337{
1338 u32 reg, addr;
1339 int channel;
1340
Elyes HAOUAS7db506c2016-10-02 11:56:39 +02001341 while (!(MCHBAR32(0x5084) & 0x10000));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001342 do {
1343 reg = MCHBAR32(0x428c);
1344 } while ((reg & 0x14) == 0);
1345
1346 // Set state of memory controller
1347 reg = 0x112;
1348 MCHBAR32(0x5030) = reg;
1349 MCHBAR32(0x4ea0) = 0;
1350 reg |= 2; //ddr reset
1351 MCHBAR32(0x5030) = reg;
1352
1353 // Assert dimm reset signal
1354 reg = MCHBAR32(0x5030);
1355 reg &= ~0x2;
1356 MCHBAR32(0x5030) = reg;
1357
1358 // Wait 200us
1359 udelay(200);
1360
1361 // Deassert dimm reset signal
1362 MCHBAR32(0x5030) |= 2;
1363
1364 // Wait 500us
1365 udelay(500);
1366
1367 // Enable DCLK
1368 MCHBAR32(0x5030) |= 4;
1369
1370 // XXX Wait 20ns
1371 udelay(1);
1372
1373 FOR_ALL_CHANNELS {
1374 // Set valid rank CKE
1375 reg = 0;
1376 reg = (reg & ~0xf) | ctrl->rankmap[channel];
1377 addr = 0x400 * channel + 0x42a0;
1378 MCHBAR32(addr) = reg;
1379
1380 // Wait 10ns for ranks to settle
1381 //udelay(0.01);
1382
1383 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
1384 MCHBAR32(addr) = reg;
1385
1386 // Write reset using a NOP
1387 write_reset(ctrl);
1388 }
1389}
1390
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001391static odtmap get_ODT(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001392{
1393 /* Get ODT based on rankmap: */
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001394 int dimms_per_ch = (ctrl->rankmap[channel] & 1)
1395 + ((ctrl->rankmap[channel] >> 2) & 1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001396
1397 if (dimms_per_ch == 1) {
1398 return (const odtmap){60, 60};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001399 } else {
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001400 return (const odtmap){120, 30};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001401 }
1402}
1403
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001404static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001405 int reg, u32 val)
1406{
1407 wait_428c(channel);
1408
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001409 if (ctrl->rank_mirror[channel][slotrank]) {
1410 /* DDR3 Rank1 Address mirror
1411 * swap the following pins:
1412 * A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 */
1413 reg = ((reg >> 1) & 1) | ((reg << 1) & 2);
1414 val = (val & ~0x1f8) | ((val >> 1) & 0xa8)
1415 | ((val & 0xa8) << 1);
1416 }
1417
Patrick Rudolph371d2912015-10-09 13:33:25 +02001418 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001419 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000);
1420 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
1421 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1422 (slotrank << 24) | (reg << 20) | val | 0x60000);
1423 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1424
Patrick Rudolph371d2912015-10-09 13:33:25 +02001425 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001426 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000);
1427 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001);
1428 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
1429 (slotrank << 24) | (reg << 20) | val | 0x60000);
1430 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1431
Patrick Rudolph371d2912015-10-09 13:33:25 +02001432 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001433 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000);
1434 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1435 0x1001 | (ctrl->tMOD << 16));
1436 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1437 (slotrank << 24) | (reg << 20) | val | 0x60000);
1438 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1439 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
1440}
1441
1442static u32 make_mr0(ramctr_timing * ctrl, u8 rank)
1443{
1444 u16 mr0reg, mch_cas, mch_wr;
1445 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 +02001446
1447 /* DLL Reset - self clearing - set after CLK frequency has been changed */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001448 mr0reg = 0x100;
1449
1450 // Convert CAS to MCH register friendly
1451 if (ctrl->CAS < 12) {
1452 mch_cas = (u16) ((ctrl->CAS - 4) << 1);
1453 } else {
1454 mch_cas = (u16) (ctrl->CAS - 12);
1455 mch_cas = ((mch_cas << 1) | 0x1);
1456 }
1457
1458 // Convert tWR to MCH register friendly
1459 mch_wr = mch_wr_t[ctrl->tWR - 5];
1460
1461 mr0reg = (mr0reg & ~0x4) | (mch_cas & 0x1);
1462 mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3);
1463 mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001464
1465 // Precharge PD - Fast (desktop) 0x1 or slow (mobile) 0x0 - mostly power-saving feature
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001466 mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12);
1467 return mr0reg;
1468}
1469
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001470static void dram_mr0(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001471{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001472 write_mrreg(ctrl, channel, rank, 0,
1473 make_mr0(ctrl, rank));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001474}
1475
1476static u32 encode_odt(u32 odt)
1477{
1478 switch (odt) {
1479 case 30:
1480 return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4
1481 case 60:
1482 return (1 << 2); // RZQ/4
1483 case 120:
1484 return (1 << 6); // RZQ/2
1485 default:
1486 case 0:
1487 return 0;
1488 }
1489}
1490
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001491static u32 make_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001492{
1493 odtmap odt;
1494 u32 mr1reg;
1495
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001496 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001497 mr1reg = 0x2;
1498
1499 mr1reg |= encode_odt(odt.rttnom);
1500
1501 return mr1reg;
1502}
1503
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001504static void dram_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001505{
1506 u16 mr1reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001507
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001508 mr1reg = make_mr1(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001509
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001510 write_mrreg(ctrl, channel, rank, 1, mr1reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001511}
1512
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001513static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001514{
1515 u16 pasr, cwl, mr2reg;
1516 odtmap odt;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001517 int srt;
1518
1519 pasr = 0;
1520 cwl = ctrl->CWL - 5;
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001521 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001522
1523 srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh;
1524
1525 mr2reg = 0;
1526 mr2reg = (mr2reg & ~0x7) | pasr;
1527 mr2reg = (mr2reg & ~0x38) | (cwl << 3);
1528 mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6);
1529 mr2reg = (mr2reg & ~0x80) | (srt << 7);
1530 mr2reg |= (odt.rttwr / 60) << 9;
1531
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001532 write_mrreg(ctrl, channel, rank, 2, mr2reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001533}
1534
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001535static void dram_mr3(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001536{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001537 write_mrreg(ctrl, channel, rank, 3, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001538}
1539
1540static void dram_mrscommands(ramctr_timing * ctrl)
1541{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001542 u8 slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001543 u32 reg, addr;
1544 int channel;
1545
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001546 FOR_ALL_POPULATED_CHANNELS {
1547 FOR_ALL_POPULATED_RANKS {
1548 // MR2
1549 dram_mr2(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001550
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001551 // MR3
1552 dram_mr3(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001553
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001554 // MR1
1555 dram_mr1(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001556
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001557 // MR0
1558 dram_mr0(ctrl, slotrank, channel);
1559 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001560 }
1561
Patrick Rudolph371d2912015-10-09 13:33:25 +02001562 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001563 write32(DEFAULT_MCHBAR + 0x4e20, 0x7);
1564 write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001);
1565 write32(DEFAULT_MCHBAR + 0x4e00, 0x60002);
1566 write32(DEFAULT_MCHBAR + 0x4e10, 0);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001567
1568 /* DRAM command ZQCL */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001569 write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003);
1570 write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001);
1571 write32(DEFAULT_MCHBAR + 0x4e04, 0x60400);
1572 write32(DEFAULT_MCHBAR + 0x4e14, 0x288);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001573
1574 /* execute command queue on all channels ? */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001575 write32(DEFAULT_MCHBAR + 0x4e84, 0x40004);
1576
1577 // Drain
1578 FOR_ALL_CHANNELS {
1579 // Wait for ref drained
1580 wait_428c(channel);
1581 }
1582
1583 // Refresh enable
1584 MCHBAR32(0x5030) |= 8;
1585
1586 FOR_ALL_POPULATED_CHANNELS {
1587 addr = 0x400 * channel + 0x4020;
1588 reg = MCHBAR32(addr);
1589 reg &= ~0x200000;
1590 MCHBAR32(addr) = reg;
1591
1592 wait_428c(channel);
1593
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001594 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001595
1596 // Drain
1597 wait_428c(channel);
1598
Patrick Rudolph371d2912015-10-09 13:33:25 +02001599 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001600 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1601 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
1602 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001603 (slotrank << 24) | 0x60000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001604 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
1605 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1);
1606
1607 // Drain
1608 wait_428c(channel);
1609 }
1610}
1611
1612const u32 lane_registers[] = {
1613 0x0000, 0x0200, 0x0400, 0x0600,
1614 0x1000, 0x1200, 0x1400, 0x1600,
1615 0x0800
1616};
1617
1618static void program_timings(ramctr_timing * ctrl, int channel)
1619{
1620 u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028;
1621 int lane;
1622 int slotrank, slot;
1623 int full_shift = 0;
1624 u16 slot320c[NUM_SLOTS];
1625
1626 FOR_ALL_POPULATED_RANKS {
1627 if (full_shift < -ctrl->timings[channel][slotrank].val_320c)
1628 full_shift = -ctrl->timings[channel][slotrank].val_320c;
1629 }
1630
1631 for (slot = 0; slot < NUM_SLOTS; slot++)
1632 switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) {
1633 case 0:
1634 default:
1635 slot320c[slot] = 0x7f;
1636 break;
1637 case 1:
1638 slot320c[slot] =
1639 ctrl->timings[channel][2 * slot + 0].val_320c +
1640 full_shift;
1641 break;
1642 case 2:
1643 slot320c[slot] =
1644 ctrl->timings[channel][2 * slot + 1].val_320c +
1645 full_shift;
1646 break;
1647 case 3:
1648 slot320c[slot] =
1649 (ctrl->timings[channel][2 * slot].val_320c +
1650 ctrl->timings[channel][2 * slot +
1651 1].val_320c) / 2 +
1652 full_shift;
1653 break;
1654 }
1655
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001656 /* enable CMD XOVER */
1657 reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001658 reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
1659 reg32 |= (slot320c[1] & 0x7f) << 18;
1660 reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
1661
1662 MCHBAR32(0x320c + 0x100 * channel) = reg32;
1663
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001664 /* enable CLK XOVER */
1665 reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001666 reg_c18 = 0;
1667
1668 FOR_ALL_POPULATED_RANKS {
1669 int shift =
1670 ctrl->timings[channel][slotrank].val_320c + full_shift;
1671 int offset_val_c14;
1672 if (shift < 0)
1673 shift = 0;
1674 offset_val_c14 = ctrl->reg_c14_offset + shift;
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001675 /* set CLK phase shift */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001676 reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
1677 reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
1678 }
1679
1680 MCHBAR32(0xc14 + channel * 0x100) = reg_c14;
1681 MCHBAR32(0xc18 + channel * 0x100) = reg_c18;
1682
1683 reg_4028 = MCHBAR32(0x4028 + 0x400 * channel);
1684 reg_4028 &= 0xffff0000;
1685
1686 reg_4024 = 0;
1687
1688 FOR_ALL_POPULATED_RANKS {
1689 int post_timA_min_high = 7, post_timA_max_high = 0;
1690 int pre_timA_min_high = 7, pre_timA_max_high = 0;
1691 int shift_402x = 0;
1692 int shift =
1693 ctrl->timings[channel][slotrank].val_320c + full_shift;
1694
1695 if (shift < 0)
1696 shift = 0;
1697
1698 FOR_ALL_LANES {
1699 if (post_timA_min_high >
1700 ((ctrl->timings[channel][slotrank].lanes[lane].
1701 timA + shift) >> 6))
1702 post_timA_min_high =
1703 ((ctrl->timings[channel][slotrank].
1704 lanes[lane].timA + shift) >> 6);
1705 if (pre_timA_min_high >
1706 (ctrl->timings[channel][slotrank].lanes[lane].
1707 timA >> 6))
1708 pre_timA_min_high =
1709 (ctrl->timings[channel][slotrank].
1710 lanes[lane].timA >> 6);
1711 if (post_timA_max_high <
1712 ((ctrl->timings[channel][slotrank].lanes[lane].
1713 timA + shift) >> 6))
1714 post_timA_max_high =
1715 ((ctrl->timings[channel][slotrank].
1716 lanes[lane].timA + shift) >> 6);
1717 if (pre_timA_max_high <
1718 (ctrl->timings[channel][slotrank].lanes[lane].
1719 timA >> 6))
1720 pre_timA_max_high =
1721 (ctrl->timings[channel][slotrank].
1722 lanes[lane].timA >> 6);
1723 }
1724
1725 if (pre_timA_max_high - pre_timA_min_high <
1726 post_timA_max_high - post_timA_min_high)
1727 shift_402x = +1;
1728 else if (pre_timA_max_high - pre_timA_min_high >
1729 post_timA_max_high - post_timA_min_high)
1730 shift_402x = -1;
1731
1732 reg_4028 |=
1733 (ctrl->timings[channel][slotrank].val_4028 + shift_402x -
1734 post_timA_min_high) << (4 * slotrank);
1735 reg_4024 |=
1736 (ctrl->timings[channel][slotrank].val_4024 +
1737 shift_402x) << (8 * slotrank);
1738
1739 FOR_ALL_LANES {
1740 MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel +
1741 4 * slotrank)
1742 =
1743 (((ctrl->timings[channel][slotrank].lanes[lane].
1744 timA + shift) & 0x3f)
1745 |
1746 ((ctrl->timings[channel][slotrank].lanes[lane].
1747 rising + shift) << 8)
1748 |
1749 (((ctrl->timings[channel][slotrank].lanes[lane].
1750 timA + shift -
1751 (post_timA_min_high << 6)) & 0x1c0) << 10)
Patrick Rudolph0188b132016-02-10 19:16:34 +01001752 | ((ctrl->timings[channel][slotrank].lanes[lane].
1753 falling + shift) << 20));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001754
1755 MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel +
1756 4 * slotrank)
1757 =
1758 (((ctrl->timings[channel][slotrank].lanes[lane].
1759 timC + shift) & 0x3f)
1760 |
1761 (((ctrl->timings[channel][slotrank].lanes[lane].
1762 timB + shift) & 0x3f) << 8)
1763 |
1764 (((ctrl->timings[channel][slotrank].lanes[lane].
1765 timB + shift) & 0x1c0) << 9)
1766 |
1767 (((ctrl->timings[channel][slotrank].lanes[lane].
1768 timC + shift) & 0x40) << 13));
1769 }
1770 }
1771 MCHBAR32(0x4024 + 0x400 * channel) = reg_4024;
1772 MCHBAR32(0x4028 + 0x400 * channel) = reg_4028;
1773}
1774
1775static void test_timA(ramctr_timing * ctrl, int channel, int slotrank)
1776{
1777 wait_428c(channel);
1778
Patrick Rudolph371d2912015-10-09 13:33:25 +02001779 /* DRAM command MRS
1780 * write MR3 MPR enable
1781 * in this mode only RD and RDA are allowed
1782 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001783 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
1784 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1785 (0xc01 | (ctrl->tMOD << 16)));
1786 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1787 (slotrank << 24) | 0x360004);
1788 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1789
Patrick Rudolph371d2912015-10-09 13:33:25 +02001790 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001791 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
1792 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01);
1793 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24));
1794 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1795
Patrick Rudolph371d2912015-10-09 13:33:25 +02001796 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001797 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
1798 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1799 0x100f | ((ctrl->CAS + 36) << 16));
1800 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1801 (slotrank << 24) | 0x60000);
1802 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1803
Patrick Rudolph371d2912015-10-09 13:33:25 +02001804 /* DRAM command MRS
1805 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001806 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
1807 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
1808 (0xc01 | (ctrl->tMOD << 16)));
1809 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
1810 (slotrank << 24) | 0x360000);
1811 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
1812
1813 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
1814
1815 wait_428c(channel);
1816}
1817
1818static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank,
1819 int lane)
1820{
1821 u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA;
1822 return ((read32
1823 (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 +
1824 ((timA / 32) & 1) * 4)
1825 >> (timA % 32)) & 1);
1826}
1827
1828struct run {
1829 int middle;
1830 int end;
1831 int start;
1832 int all;
1833 int length;
1834};
1835
1836static struct run get_longest_zero_run(int *seq, int sz)
1837{
1838 int i, ls;
1839 int bl = 0, bs = 0;
1840 struct run ret;
1841
1842 ls = 0;
1843 for (i = 0; i < 2 * sz; i++)
1844 if (seq[i % sz]) {
1845 if (i - ls > bl) {
1846 bl = i - ls;
1847 bs = ls;
1848 }
1849 ls = i + 1;
1850 }
1851 if (bl == 0) {
1852 ret.middle = sz / 2;
1853 ret.start = 0;
1854 ret.end = sz;
1855 ret.all = 1;
1856 return ret;
1857 }
1858
1859 ret.start = bs % sz;
1860 ret.end = (bs + bl - 1) % sz;
1861 ret.middle = (bs + (bl - 1) / 2) % sz;
1862 ret.length = bl;
1863 ret.all = 0;
1864
1865 return ret;
1866}
1867
1868static void discover_timA_coarse(ramctr_timing * ctrl, int channel,
1869 int slotrank, int *upperA)
1870{
1871 int timA;
1872 int statistics[NUM_LANES][128];
1873 int lane;
1874
1875 for (timA = 0; timA < 128; timA++) {
1876 FOR_ALL_LANES {
1877 ctrl->timings[channel][slotrank].lanes[lane].timA = timA;
1878 }
1879 program_timings(ctrl, channel);
1880
1881 test_timA(ctrl, channel, slotrank);
1882
1883 FOR_ALL_LANES {
1884 statistics[lane][timA] =
1885 !does_lane_work(ctrl, channel, slotrank, lane);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001886 printram("Astat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001887 channel, slotrank, lane, timA,
1888 statistics[lane][timA]);
1889 }
1890 }
1891 FOR_ALL_LANES {
1892 struct run rn = get_longest_zero_run(statistics[lane], 128);
1893 ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle;
1894 upperA[lane] = rn.end;
1895 if (upperA[lane] < rn.middle)
1896 upperA[lane] += 128;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001897 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001898 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001899 printram("Aend: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001900 lane, upperA[lane]);
1901 }
1902}
1903
1904static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
1905 int *upperA)
1906{
1907 int timA_delta;
1908 int statistics[NUM_LANES][51];
1909 int lane, i;
1910
1911 memset(statistics, 0, sizeof(statistics));
1912
1913 for (timA_delta = -25; timA_delta <= 25; timA_delta++) {
1914 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
1915 timA = upperA[lane] + timA_delta + 0x40;
1916 program_timings(ctrl, channel);
1917
1918 for (i = 0; i < 100; i++) {
1919 test_timA(ctrl, channel, slotrank);
1920 FOR_ALL_LANES {
1921 statistics[lane][timA_delta + 25] +=
1922 does_lane_work(ctrl, channel, slotrank,
1923 lane);
1924 }
1925 }
1926 }
1927 FOR_ALL_LANES {
1928 int last_zero, first_all;
1929
1930 for (last_zero = -25; last_zero <= 25; last_zero++)
1931 if (statistics[lane][last_zero + 25])
1932 break;
1933 last_zero--;
1934 for (first_all = -25; first_all <= 25; first_all++)
1935 if (statistics[lane][first_all + 25] == 100)
1936 break;
1937
1938 printram("lane %d: %d, %d\n", lane, last_zero,
1939 first_all);
1940
1941 ctrl->timings[channel][slotrank].lanes[lane].timA =
1942 (last_zero + first_all) / 2 + upperA[lane];
Patrick Rudolpha649a542016-01-17 18:32:06 +01001943 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001944 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
1945 }
1946}
1947
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001948static int discover_402x(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001949 int *upperA)
1950{
1951 int works[NUM_LANES];
1952 int lane;
1953 while (1) {
1954 int all_works = 1, some_works = 0;
1955 program_timings(ctrl, channel);
1956 test_timA(ctrl, channel, slotrank);
1957 FOR_ALL_LANES {
1958 works[lane] =
1959 !does_lane_work(ctrl, channel, slotrank, lane);
1960 if (works[lane])
1961 some_works = 1;
1962 else
1963 all_works = 0;
1964 }
1965 if (all_works)
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001966 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001967 if (!some_works) {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001968 if (ctrl->timings[channel][slotrank].val_4024 < 2) {
1969 printk(BIOS_EMERG, "402x discovery failed (1): %d, %d\n",
1970 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001971 return MAKE_ERR;
1972 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001973 ctrl->timings[channel][slotrank].val_4024 -= 2;
1974 printram("4024 -= 2;\n");
1975 continue;
1976 }
1977 ctrl->timings[channel][slotrank].val_4028 += 2;
1978 printram("4028 += 2;\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001979 if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) {
1980 printk(BIOS_EMERG, "402x discovery failed (2): %d, %d\n",
1981 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001982 return MAKE_ERR;
1983 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001984 FOR_ALL_LANES if (works[lane]) {
1985 ctrl->timings[channel][slotrank].lanes[lane].timA +=
1986 128;
1987 upperA[lane] += 128;
1988 printram("increment %d, %d, %d\n", channel,
1989 slotrank, lane);
1990 }
1991 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001992 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001993}
1994
1995struct timA_minmax {
1996 int timA_min_high, timA_max_high;
1997};
1998
1999static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
2000 struct timA_minmax *mnmx)
2001{
2002 int lane;
2003 mnmx->timA_min_high = 7;
2004 mnmx->timA_max_high = 0;
2005
2006 FOR_ALL_LANES {
2007 if (mnmx->timA_min_high >
2008 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
2009 mnmx->timA_min_high =
2010 (ctrl->timings[channel][slotrank].lanes[lane].
2011 timA >> 6);
2012 if (mnmx->timA_max_high <
2013 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
2014 mnmx->timA_max_high =
2015 (ctrl->timings[channel][slotrank].lanes[lane].
2016 timA >> 6);
2017 }
2018}
2019
2020static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
2021 struct timA_minmax *mnmx)
2022{
2023 struct timA_minmax post;
2024 int shift_402x = 0;
2025
2026 /* Get changed maxima. */
2027 pre_timA_change(ctrl, channel, slotrank, &post);
2028
2029 if (mnmx->timA_max_high - mnmx->timA_min_high <
2030 post.timA_max_high - post.timA_min_high)
2031 shift_402x = +1;
2032 else if (mnmx->timA_max_high - mnmx->timA_min_high >
2033 post.timA_max_high - post.timA_min_high)
2034 shift_402x = -1;
2035 else
2036 shift_402x = 0;
2037
2038 ctrl->timings[channel][slotrank].val_4028 += shift_402x;
2039 ctrl->timings[channel][slotrank].val_4024 += shift_402x;
2040 printram("4024 += %d;\n", shift_402x);
2041 printram("4028 += %d;\n", shift_402x);
2042}
2043
Patrick Rudolph371d2912015-10-09 13:33:25 +02002044/* Compensate the skew between DQS and DQs.
2045 * To ease PCB design a small skew between Data Strobe signals and
2046 * Data Signals is allowed.
2047 * The controller has to measure and compensate this skew for every byte-lane.
2048 * By delaying either all DQs signals or DQS signal, a full phase
2049 * shift can be introduced.
2050 * It is assumed that one byte-lane's DQs signals have the same routing delay.
2051 *
2052 * To measure the actual skew, the DRAM is placed in "read leveling" mode.
2053 * In read leveling mode the DRAM-chip outputs an alternating periodic pattern.
2054 * The memory controller iterates over all possible values to do a full phase shift
2055 * and issues read commands.
2056 * With DQS and DQs in phase the data read is expected to alternate on every byte:
2057 * 0xFF 0x00 0xFF ...
2058 * Once the controller has detected this pattern a bit in the result register is
2059 * set for the current phase shift.
2060 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002061static int read_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002062{
2063 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002064 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002065
2066 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002067 int all_high, some_high;
2068 int upperA[NUM_LANES];
2069 struct timA_minmax mnmx;
2070
2071 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002072
2073 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002074 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2075 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2076 0xc01 | (ctrl->tRP << 16));
2077 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2078 (slotrank << 24) | 0x60400);
2079 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2080 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2081
2082 write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001);
2083
2084 ctrl->timings[channel][slotrank].val_4028 = 4;
2085 ctrl->timings[channel][slotrank].val_4024 = 55;
2086 program_timings(ctrl, channel);
2087
2088 discover_timA_coarse(ctrl, channel, slotrank, upperA);
2089
2090 all_high = 1;
2091 some_high = 0;
2092 FOR_ALL_LANES {
2093 if (ctrl->timings[channel][slotrank].lanes[lane].
2094 timA >= 0x40)
2095 some_high = 1;
2096 else
2097 all_high = 0;
2098 }
2099
2100 if (all_high) {
2101 ctrl->timings[channel][slotrank].val_4028--;
2102 printram("4028--;\n");
2103 FOR_ALL_LANES {
2104 ctrl->timings[channel][slotrank].lanes[lane].
2105 timA -= 0x40;
2106 upperA[lane] -= 0x40;
2107
2108 }
2109 } else if (some_high) {
2110 ctrl->timings[channel][slotrank].val_4024++;
2111 ctrl->timings[channel][slotrank].val_4028++;
2112 printram("4024++;\n");
2113 printram("4028++;\n");
2114 }
2115
2116 program_timings(ctrl, channel);
2117
2118 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2119
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002120 err = discover_402x(ctrl, channel, slotrank, upperA);
2121 if (err)
2122 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002123
2124 post_timA_change(ctrl, channel, slotrank, &mnmx);
2125 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2126
2127 discover_timA_fine(ctrl, channel, slotrank, upperA);
2128
2129 post_timA_change(ctrl, channel, slotrank, &mnmx);
2130 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2131
2132 FOR_ALL_LANES {
2133 ctrl->timings[channel][slotrank].lanes[lane].timA -= mnmx.timA_min_high * 0x40;
2134 }
2135 ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high;
2136 printram("4028 -= %d;\n", mnmx.timA_min_high);
2137
2138 post_timA_change(ctrl, channel, slotrank, &mnmx);
2139
2140 printram("4/8: %d, %d, %x, %x\n", channel, slotrank,
2141 ctrl->timings[channel][slotrank].val_4024,
2142 ctrl->timings[channel][slotrank].val_4028);
2143
Patrick Rudolpha649a542016-01-17 18:32:06 +01002144 printram("final results:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002145 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01002146 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002147 lane,
2148 ctrl->timings[channel][slotrank].lanes[lane].timA);
2149
2150 write32(DEFAULT_MCHBAR + 0x3400, 0);
2151
Patrick Rudolph9b515682015-10-09 13:43:51 +02002152 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002153 }
2154
2155 FOR_ALL_POPULATED_CHANNELS {
2156 program_timings(ctrl, channel);
2157 }
2158 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2159 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
2160 + 4 * lane, 0);
2161 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002162 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002163}
2164
2165static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
2166{
2167 int lane;
2168
2169 FOR_ALL_LANES {
2170 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0);
2171 read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane);
2172 }
2173
2174 wait_428c(channel);
2175
Patrick Rudolph371d2912015-10-09 13:33:25 +02002176 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002177 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2178 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2179 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
2180 | 4 | (ctrl->tRCD << 16));
2181
2182 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2183 (slotrank << 24) | (6 << 16));
2184
2185 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
2186
Patrick Rudolph371d2912015-10-09 13:33:25 +02002187 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002188 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2189 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001);
2190 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2191 (slotrank << 24) | 8);
2192 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2193
Patrick Rudolph371d2912015-10-09 13:33:25 +02002194 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002195 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2196 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4);
2197 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2198 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2199
Patrick Rudolph371d2912015-10-09 13:33:25 +02002200 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002201 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2202 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2203 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2204 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2205 (slotrank << 24) | 8);
2206 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2207
2208 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2209
2210 wait_428c(channel);
2211
Patrick Rudolph371d2912015-10-09 13:33:25 +02002212 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002213 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2214 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2215 0xc01 | (ctrl->tRP << 16));
2216 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2217 (slotrank << 24) | 0x60400);
2218 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2219
Patrick Rudolph371d2912015-10-09 13:33:25 +02002220 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002221 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2222 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2223 (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10)
2224 | 8 | (ctrl->CAS << 16));
2225
2226 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2227 (slotrank << 24) | 0x60000);
2228
2229 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244);
2230
Patrick Rudolph371d2912015-10-09 13:33:25 +02002231 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002232 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2233 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2234 0x40011f4 | (max(ctrl->tRTP, 8) << 16));
2235 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2236 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2237
Patrick Rudolph371d2912015-10-09 13:33:25 +02002238 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002239 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2240 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2241 0xc01 | (ctrl->tRP << 16));
2242 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2243 (slotrank << 24) | 0x60400);
2244 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2245 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2246 wait_428c(channel);
2247}
2248
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002249static int discover_timC(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002250{
2251 int timC;
2252 int statistics[NUM_LANES][MAX_TIMC + 1];
2253 int lane;
2254
2255 wait_428c(channel);
2256
Patrick Rudolph371d2912015-10-09 13:33:25 +02002257 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002258 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2259 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2260 0xc01 | (ctrl->tRP << 16));
2261 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2262 (slotrank << 24) | 0x60400);
2263 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2264 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2265
2266 for (timC = 0; timC <= MAX_TIMC; timC++) {
2267 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
2268 timC = timC;
2269 program_timings(ctrl, channel);
2270
2271 test_timC(ctrl, channel, slotrank);
2272
2273 FOR_ALL_LANES {
2274 statistics[lane][timC] =
2275 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2276 0x400 * channel);
2277 printram("Cstat: %d, %d, %d, %x, %x\n",
2278 channel, slotrank, lane, timC,
2279 statistics[lane][timC]);
2280 }
2281 }
2282 FOR_ALL_LANES {
2283 struct run rn =
2284 get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
2285 ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002286 if (rn.all) {
2287 printk(BIOS_EMERG, "timC discovery failed: %d, %d, %d\n",
2288 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002289 return MAKE_ERR;
2290 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002291 printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002292 lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
2293 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002294 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002295}
2296
2297static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
2298{
2299 int channel, ret = 0;
2300 FOR_ALL_POPULATED_CHANNELS if (channel < target_channel)
2301 ret++;
2302 return ret;
2303}
2304
2305static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b)
2306{
2307 unsigned j;
2308 unsigned channel_offset =
2309 get_precedening_channels(ctrl, channel) * 0x40;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002310 for (j = 0; j < 16; j++)
2311 write32((void *)(0x04000000 + channel_offset + 4 * j), j & 2 ? b : a);
2312 sfence();
2313}
2314
2315static int num_of_channels(const ramctr_timing * ctrl)
2316{
2317 int ret = 0;
2318 int channel;
2319 FOR_ALL_POPULATED_CHANNELS ret++;
2320 return ret;
2321}
2322
2323static void fill_pattern1(ramctr_timing * ctrl, int channel)
2324{
2325 unsigned j;
2326 unsigned channel_offset =
2327 get_precedening_channels(ctrl, channel) * 0x40;
2328 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2329 for (j = 0; j < 16; j++)
2330 write32((void *)(0x04000000 + channel_offset + j * 4), 0xffffffff);
2331 for (j = 0; j < 16; j++)
2332 write32((void *)(0x04000000 + channel_offset + channel_step + j * 4), 0);
2333 sfence();
2334}
2335
2336static void precharge(ramctr_timing * ctrl)
2337{
2338 int channel, slotrank, lane;
2339
2340 FOR_ALL_POPULATED_CHANNELS {
2341 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2342 ctrl->timings[channel][slotrank].lanes[lane].falling =
2343 16;
2344 ctrl->timings[channel][slotrank].lanes[lane].rising =
2345 16;
Patrick Rudolpha649a542016-01-17 18:32:06 +01002346 }
2347
2348 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002349
2350 FOR_ALL_POPULATED_RANKS {
2351 wait_428c(channel);
2352
Patrick Rudolph371d2912015-10-09 13:33:25 +02002353 /* DRAM command MRS
2354 * write MR3 MPR enable
2355 * in this mode only RD and RDA are allowed
2356 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002357 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2358 0x1f000);
2359 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2360 0xc01 | (ctrl->tMOD << 16));
2361 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2362 (slotrank << 24) | 0x360004);
2363 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2364
Patrick Rudolph371d2912015-10-09 13:33:25 +02002365 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002366 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2367 0x1f105);
2368 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2369 0x4041003);
2370 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2371 (slotrank << 24) | 0);
2372 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2373
Patrick Rudolph371d2912015-10-09 13:33:25 +02002374 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002375 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2376 0x1f105);
2377 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2378 0x1001 | ((ctrl->CAS + 8) << 16));
2379 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2380 (slotrank << 24) | 0x60000);
2381 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2382
Patrick Rudolph371d2912015-10-09 13:33:25 +02002383 /* DRAM command MRS
2384 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002385 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2386 0x1f000);
2387 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2388 0xc01 | (ctrl->tMOD << 16));
2389 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2390 (slotrank << 24) | 0x360000);
2391 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2392 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2393 0xc0001);
2394
2395 wait_428c(channel);
2396 }
2397
2398 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2399 ctrl->timings[channel][slotrank].lanes[lane].falling =
2400 48;
2401 ctrl->timings[channel][slotrank].lanes[lane].rising =
2402 48;
2403 }
2404
2405 program_timings(ctrl, channel);
2406
2407 FOR_ALL_POPULATED_RANKS {
2408 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002409 /* DRAM command MRS
2410 * write MR3 MPR enable
2411 * in this mode only RD and RDA are allowed
2412 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002413 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2414 0x1f000);
2415 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2416 0xc01 | (ctrl->tMOD << 16));
2417 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2418 (slotrank << 24) | 0x360004);
2419 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2420
Patrick Rudolph371d2912015-10-09 13:33:25 +02002421 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002422 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2423 0x1f105);
2424 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2425 0x4041003);
2426 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2427 (slotrank << 24) | 0);
2428 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2429
Patrick Rudolph371d2912015-10-09 13:33:25 +02002430 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002431 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2432 0x1f105);
2433 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2434 0x1001 | ((ctrl->CAS + 8) << 16));
2435 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2436 (slotrank << 24) | 0x60000);
2437 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2438
Patrick Rudolph371d2912015-10-09 13:33:25 +02002439 /* DRAM command MRS
2440 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002441 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2442 0x1f000);
2443 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2444 0xc01 | (ctrl->tMOD << 16));
2445
2446 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2447 (slotrank << 24) | 0x360000);
2448 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2449
2450 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2451 0xc0001);
2452 wait_428c(channel);
2453 }
2454 }
2455}
2456
2457static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
2458{
Patrick Rudolph371d2912015-10-09 13:33:25 +02002459 /* enable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002460 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002461 0x80 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002462
2463 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002464 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002465 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207);
2466 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2467 0x8000c01 | ((ctrl->CWL + ctrl->tWLO) << 16));
2468 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2469 8 | (slotrank << 24));
2470 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2471
Patrick Rudolph371d2912015-10-09 13:33:25 +02002472 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002473 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107);
2474 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2475 0x4000c01 | ((ctrl->CAS + 38) << 16));
2476 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2477 (slotrank << 24) | 4);
2478 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2479
2480 write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001);
2481 wait_428c(channel);
2482
Patrick Rudolph371d2912015-10-09 13:33:25 +02002483 /* disable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002484 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002485 0x1080 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002486}
2487
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002488static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002489{
2490 int timB;
2491 int statistics[NUM_LANES][128];
2492 int lane;
2493
2494 write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2));
2495
2496 for (timB = 0; timB < 128; timB++) {
2497 FOR_ALL_LANES {
2498 ctrl->timings[channel][slotrank].lanes[lane].timB = timB;
2499 }
2500 program_timings(ctrl, channel);
2501
2502 test_timB(ctrl, channel, slotrank);
2503
2504 FOR_ALL_LANES {
2505 statistics[lane][timB] =
2506 !((read32
2507 (DEFAULT_MCHBAR + lane_registers[lane] +
2508 channel * 0x100 + 4 + ((timB / 32) & 1) * 4)
2509 >> (timB % 32)) & 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002510 printram("Bstat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002511 channel, slotrank, lane, timB,
2512 statistics[lane][timB]);
2513 }
2514 }
2515 FOR_ALL_LANES {
2516 struct run rn = get_longest_zero_run(statistics[lane], 128);
Patrick Rudolphd912f1d2016-02-15 20:07:42 +01002517 /* timC is a direct function of timB's 6 LSBs.
2518 * Some tests increments the value of timB by a small value,
2519 * which might cause the 6bit value to overflow, if it's close
2520 * to 0x3F. Increment the value by a small offset if it's likely
2521 * to overflow, to make sure it won't overflow while running
2522 * tests and bricks the system due to a non matching timC.
2523 *
2524 * TODO: find out why some tests (edge write discovery)
2525 * increment timB. */
2526 if ((rn.start & 0x3F) == 0x3E)
2527 rn.start += 2;
2528 else if ((rn.start & 0x3F) == 0x3F)
2529 rn.start += 1;
Vladimir Serbinenko3141eac2016-01-29 19:42:02 +01002530 ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002531 if (rn.all) {
2532 printk(BIOS_EMERG, "timB discovery failed: %d, %d, %d\n",
2533 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002534 return MAKE_ERR;
2535 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002536 printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002537 lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
2538 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002539 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002540}
2541
2542static int get_timB_high_adjust(u64 val)
2543{
2544 int i;
2545
2546 /* good */
2547 if (val == 0xffffffffffffffffLL)
2548 return 0;
2549
2550 if (val >= 0xf000000000000000LL) {
2551 /* needs negative adjustment */
2552 for (i = 0; i < 8; i++)
2553 if (val << (8 * (7 - i) + 4))
2554 return -i;
2555 } else {
2556 /* needs positive adjustment */
2557 for (i = 0; i < 8; i++)
2558 if (val >> (8 * (7 - i) + 4))
2559 return i;
2560 }
2561 return 8;
2562}
2563
2564static void adjust_high_timB(ramctr_timing * ctrl)
2565{
2566 int channel, slotrank, lane, old;
2567 write32(DEFAULT_MCHBAR + 0x3400, 0x200);
2568 FOR_ALL_POPULATED_CHANNELS {
2569 fill_pattern1(ctrl, channel);
2570 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 1);
2571 }
2572 FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
2573
2574 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001);
2575
2576 wait_428c(channel);
2577
Patrick Rudolph371d2912015-10-09 13:33:25 +02002578 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002579 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2580 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2581 0xc01 | (ctrl->tRCD << 16));
2582 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2583 (slotrank << 24) | 0x60000);
2584 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2585
Patrick Rudolph371d2912015-10-09 13:33:25 +02002586 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002587 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2588 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01);
2589 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2590 (slotrank << 24) | 0x8);
2591 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2592
Patrick Rudolph371d2912015-10-09 13:33:25 +02002593 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002594 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2595 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003);
2596 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2597 (slotrank << 24));
2598 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2);
2599
Patrick Rudolph371d2912015-10-09 13:33:25 +02002600 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002601 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2602 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2603 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2604 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2605 (slotrank << 24) | 0x8);
2606 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2607
2608 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2609
2610 wait_428c(channel);
2611
Patrick Rudolph371d2912015-10-09 13:33:25 +02002612 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002613 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2614 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2615 0xc01 | ((ctrl->tRP) << 16));
2616 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2617 (slotrank << 24) | 0x60400);
2618 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2619
Patrick Rudolph371d2912015-10-09 13:33:25 +02002620 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002621 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2622 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2623 0xc01 | ((ctrl->tRCD) << 16));
2624 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2625 (slotrank << 24) | 0x60000);
2626 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2627
Patrick Rudolph371d2912015-10-09 13:33:25 +02002628 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002629 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105);
2630 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2631 0x4000c01 |
2632 ((ctrl->tRP +
2633 ctrl->timings[channel][slotrank].val_4024 +
2634 ctrl->timings[channel][slotrank].val_4028) << 16));
2635 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2636 (slotrank << 24) | 0x60008);
2637 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2638
2639 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
2640 wait_428c(channel);
2641 FOR_ALL_LANES {
2642 u64 res =
2643 read32(DEFAULT_MCHBAR + lane_registers[lane] +
2644 0x100 * channel + 4);
2645 res |=
2646 ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] +
2647 0x100 * channel + 8)) << 32;
2648 old = ctrl->timings[channel][slotrank].lanes[lane].timB;
2649 ctrl->timings[channel][slotrank].lanes[lane].timB +=
2650 get_timB_high_adjust(res) * 64;
2651
Patrick Rudolpha649a542016-01-17 18:32:06 +01002652 printram("High adjust %d:%016llx\n", lane, res);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002653 printram("Bval+: %d, %d, %d, %x -> %x\n", channel,
2654 slotrank, lane, old,
2655 ctrl->timings[channel][slotrank].lanes[lane].
2656 timB);
2657 }
2658 }
2659 write32(DEFAULT_MCHBAR + 0x3400, 0);
2660}
2661
2662static void write_op(ramctr_timing * ctrl, int channel)
2663{
2664 int slotrank;
2665
2666 wait_428c(channel);
2667
2668 /* choose an existing rank. */
2669 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2670
Patrick Rudolph371d2912015-10-09 13:33:25 +02002671 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002672 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2673 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2674
2675 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2676 (slotrank << 24) | 0x60000);
2677
2678 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2679
2680 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2681 wait_428c(channel);
2682}
2683
Patrick Rudolph371d2912015-10-09 13:33:25 +02002684/* Compensate the skew between CMD/ADDR/CLK and DQ/DQS lanes.
2685 * DDR3 adopted the fly-by topology. The data and strobes signals reach
2686 * the chips at different times with respect to command, address and
2687 * clock signals.
2688 * By delaying either all DQ/DQs or all CMD/ADDR/CLK signals, a full phase
2689 * shift can be introduced.
2690 * It is assumed that the CLK/ADDR/CMD signals have the same routing delay.
2691 *
2692 * To find the required phase shift the DRAM is placed in "write leveling" mode.
2693 * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
2694 * sampled value on the data lanes (DQs).
2695 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002696static int write_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002697{
2698 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002699 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002700
2701 FOR_ALL_POPULATED_CHANNELS
2702 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
2703 read32(DEFAULT_MCHBAR + 0x4008 +
2704 0x400 * channel) | 0x8000000);
2705
2706 FOR_ALL_POPULATED_CHANNELS {
2707 write_op(ctrl, channel);
2708 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2709 read32(DEFAULT_MCHBAR + 0x4020 +
2710 0x400 * channel) | 0x200000);
2711 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002712
2713 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002714 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2715 FOR_ALL_POPULATED_CHANNELS {
2716 write_op(ctrl, channel);
2717 }
2718
Patrick Rudolph371d2912015-10-09 13:33:25 +02002719 /* enable write leveling on all ranks
2720 * disable all DQ outputs
2721 * only NOP is allowed in this mode */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002722 FOR_ALL_CHANNELS
2723 FOR_ALL_POPULATED_RANKS
2724 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002725 make_mr1(ctrl, slotrank, channel) | 0x1080);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002726
2727 write32(DEFAULT_MCHBAR + 0x3400, 0x108052);
2728
Patrick Rudolph9b515682015-10-09 13:43:51 +02002729 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002730
Patrick Rudolph371d2912015-10-09 13:33:25 +02002731 /* set any valid value for timB, it gets corrected later */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002732 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2733 err = discover_timB(ctrl, channel, slotrank);
2734 if (err)
2735 return err;
2736 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002737
Patrick Rudolph371d2912015-10-09 13:33:25 +02002738 /* disable write leveling on all ranks */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002739 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2740 write_mrreg(ctrl, channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002741 slotrank, 1, make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002742
2743 write32(DEFAULT_MCHBAR + 0x3400, 0);
2744
2745 FOR_ALL_POPULATED_CHANNELS
2746 wait_428c(channel);
2747
Patrick Rudolph371d2912015-10-09 13:33:25 +02002748 /* refresh enable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002749 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8);
2750
2751 FOR_ALL_POPULATED_CHANNELS {
2752 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2753 ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 +
2754 0x400 * channel));
2755 read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel);
2756 wait_428c(channel);
2757
Patrick Rudolph371d2912015-10-09 13:33:25 +02002758 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002759 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2760 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
2761 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000);
2762 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2763
2764 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2765 wait_428c(channel);
2766 }
2767
Patrick Rudolph9b515682015-10-09 13:43:51 +02002768 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002769
2770 printram("CPE\n");
2771 precharge(ctrl);
2772 printram("CPF\n");
2773
2774 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2775 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2776 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2777 0);
2778 }
2779
2780 FOR_ALL_POPULATED_CHANNELS {
2781 fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555);
2782 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
2783 }
2784
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002785 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2786 err = discover_timC(ctrl, channel, slotrank);
2787 if (err)
2788 return err;
2789 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002790
2791 FOR_ALL_POPULATED_CHANNELS
2792 program_timings(ctrl, channel);
2793
Patrick Rudolph371d2912015-10-09 13:33:25 +02002794 /* measure and adjust timB timings */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002795 adjust_high_timB(ctrl);
2796
2797 FOR_ALL_POPULATED_CHANNELS
2798 program_timings(ctrl, channel);
2799
2800 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2801 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2802 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2803 0);
2804 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002805 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002806}
2807
2808static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
2809{
2810 struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank];
2811 int timC_delta;
2812 int lanes_ok = 0;
2813 int ctr = 0;
2814 int lane;
2815
2816 for (timC_delta = -5; timC_delta <= 5; timC_delta++) {
2817 FOR_ALL_LANES {
2818 ctrl->timings[channel][slotrank].lanes[lane].timC =
2819 saved_rt.lanes[lane].timC + timC_delta;
2820 }
2821 program_timings(ctrl, channel);
2822 FOR_ALL_LANES {
2823 write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0);
2824 }
2825
2826 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2827
2828 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002829 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002830 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2831 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2832 ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10)
2833 | 8 | (ctrl->tRCD << 16));
2834
2835 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2836 (slotrank << 24) | ctr | 0x60000);
2837
2838 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002839 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002840 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
2841 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2842 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16));
2843 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2844 (slotrank << 24));
2845 write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd);
2846 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42);
2847
Patrick Rudolph371d2912015-10-09 13:33:25 +02002848 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002849 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2850 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2851 0x4001020 | (max(ctrl->tRTP, 8) << 16));
2852 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2853 (slotrank << 24));
2854 write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd);
2855 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42);
2856
Patrick Rudolph371d2912015-10-09 13:33:25 +02002857 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002858 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2859 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001);
2860 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2861 (slotrank << 24) | 0x60400);
2862 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2863
2864 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2865 wait_428c(channel);
2866 FOR_ALL_LANES {
2867 u32 r32 =
2868 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2869 0x400 * channel);
2870
2871 if (r32 == 0)
2872 lanes_ok |= 1 << lane;
2873 }
2874 ctr++;
2875 if (lanes_ok == ((1 << NUM_LANES) - 1))
2876 break;
2877 }
2878
2879 ctrl->timings[channel][slotrank] = saved_rt;
2880
2881 printram("3lanes: %x\n", lanes_ok);
2882 return lanes_ok != ((1 << NUM_LANES) - 1);
2883}
2884
2885#include "raminit_patterns.h"
2886
2887static void fill_pattern5(ramctr_timing * ctrl, int channel, int patno)
2888{
2889 unsigned i, j;
2890 unsigned channel_offset =
2891 get_precedening_channels(ctrl, channel) * 0x40;
2892 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2893
2894 if (patno) {
2895 u8 base8 = 0x80 >> ((patno - 1) % 8);
2896 u32 base = base8 | (base8 << 8) | (base8 << 16) | (base8 << 24);
2897 for (i = 0; i < 32; i++) {
2898 for (j = 0; j < 16; j++) {
2899 u32 val = use_base[patno - 1][i] & (1 << (j / 2)) ? base : 0;
2900 if (invert[patno - 1][i] & (1 << (j / 2)))
2901 val = ~val;
2902 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2903 j * 4), val);
2904 }
2905 }
2906
2907 } else {
2908 for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) {
2909 for (j = 0; j < 16; j++)
2910 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2911 j * 4), pattern[i][j]);
2912 }
2913 sfence();
2914 }
2915}
2916
2917static void reprogram_320c(ramctr_timing * ctrl)
2918{
2919 int channel, slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002920
2921 FOR_ALL_POPULATED_CHANNELS {
2922 wait_428c(channel);
2923
2924 /* choose an existing rank. */
2925 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2926
Patrick Rudolph371d2912015-10-09 13:33:25 +02002927 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002928 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2929 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2930
2931 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2932 (slotrank << 24) | 0x60000);
2933
2934 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2935
2936 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2937 wait_428c(channel);
2938 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2939 read32(DEFAULT_MCHBAR + 0x4020 +
2940 0x400 * channel) | 0x200000);
2941 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002942
2943 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002944 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2945 FOR_ALL_POPULATED_CHANNELS {
2946 wait_428c(channel);
2947
2948 /* choose an existing rank. */
2949 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2950
Patrick Rudolph371d2912015-10-09 13:33:25 +02002951 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002952 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2953 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2954
2955 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2956 (slotrank << 24) | 0x60000);
2957
2958 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2959
2960 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2961 wait_428c(channel);
2962 }
2963
2964 /* jedec reset */
2965 dram_jedecreset(ctrl);
2966 /* mrs commands. */
2967 dram_mrscommands(ctrl);
2968
Patrick Rudolph9b515682015-10-09 13:43:51 +02002969 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002970}
2971
2972#define MIN_C320C_LEN 13
2973
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002974static int try_cmd_stretch(ramctr_timing *ctrl, int channel, int cmd_stretch)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002975{
2976 struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002977 int slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002978 int c320c;
2979 int stat[NUM_SLOTRANKS][256];
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002980 int delta = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002981
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002982 printram("Trying cmd_stretch %d on channel %d\n", cmd_stretch, channel);
2983
2984 FOR_ALL_POPULATED_RANKS {
2985 saved_timings[channel][slotrank] =
2986 ctrl->timings[channel][slotrank];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002987 }
2988
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002989 ctrl->cmd_stretch[channel] = cmd_stretch;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002990
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002991 MCHBAR32(0x4004 + 0x400 * channel) =
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002992 ctrl->tRRD
2993 | (ctrl->tRTP << 4)
2994 | (ctrl->tCKE << 8)
2995 | (ctrl->tWTR << 12)
2996 | (ctrl->tFAW << 16)
2997 | (ctrl->tWR << 24)
2998 | (ctrl->cmd_stretch[channel] << 30);
2999
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003000 if (ctrl->cmd_stretch[channel] == 2)
3001 delta = 2;
3002 else if (ctrl->cmd_stretch[channel] == 0)
3003 delta = 4;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003004
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003005 FOR_ALL_POPULATED_RANKS {
3006 ctrl->timings[channel][slotrank].val_4024 -= delta;
3007 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003008
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003009 for (c320c = -127; c320c <= 127; c320c++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003010 FOR_ALL_POPULATED_RANKS {
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003011 ctrl->timings[channel][slotrank].val_320c = c320c;
3012 }
3013 program_timings(ctrl, channel);
3014 reprogram_320c(ctrl);
3015 FOR_ALL_POPULATED_RANKS {
3016 stat[slotrank][c320c + 127] =
3017 test_320c(ctrl, channel, slotrank);
3018 printram("3stat: %d, %d, %d: %x\n",
3019 channel, slotrank, c320c,
3020 stat[slotrank][c320c + 127]);
3021 }
3022 }
3023 FOR_ALL_POPULATED_RANKS {
3024 struct run rn =
3025 get_longest_zero_run(stat[slotrank], 255);
3026 ctrl->timings[channel][slotrank].val_320c =
3027 rn.middle - 127;
3028 printram("3val: %d, %d: %d\n", channel,
3029 slotrank,
3030 ctrl->timings[channel][slotrank].val_320c);
3031 if (rn.all || rn.length < MIN_C320C_LEN) {
3032 FOR_ALL_POPULATED_RANKS {
3033 ctrl->timings[channel][slotrank] =
3034 saved_timings[channel][slotrank];
3035 }
3036 return MAKE_ERR;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003037 }
3038 }
3039
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003040 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003041}
3042
Patrick Rudolph371d2912015-10-09 13:33:25 +02003043/* Adjust CMD phase shift and try multiple command rates.
3044 * A command rate of 2T doubles the time needed for address and
3045 * command decode. */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003046static int command_training(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003047{
3048 int channel;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003049 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003050
3051 FOR_ALL_POPULATED_CHANNELS {
3052 fill_pattern5(ctrl, channel, 0);
3053 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
3054 }
3055
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003056 FOR_ALL_POPULATED_CHANNELS {
3057 /* try command rate 1T and 2T */
3058 err = try_cmd_stretch(ctrl, channel, 0);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003059 if (err) {
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003060 err = try_cmd_stretch(ctrl, channel, 2);
3061 if (err) {
3062 printk(BIOS_EMERG, "c320c discovery failed\n");
3063 return err;
3064 }
3065 printram("Using CMD rate 2T on channel %u\n", channel);
3066 } else
3067 printram("Using CMD rate 1T on channel %u\n", channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003068 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003069
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003070 FOR_ALL_POPULATED_CHANNELS
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003071 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003072
3073 reprogram_320c(ctrl);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003074 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003075}
3076
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003077static int discover_edges_real(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003078 int *edges)
3079{
3080 int edge;
3081 int statistics[NUM_LANES][MAX_EDGE_TIMING + 1];
3082 int lane;
3083
3084 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3085 FOR_ALL_LANES {
3086 ctrl->timings[channel][slotrank].lanes[lane].rising =
3087 edge;
3088 ctrl->timings[channel][slotrank].lanes[lane].falling =
3089 edge;
3090 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003091 program_timings(ctrl, channel);
3092
3093 FOR_ALL_LANES {
3094 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3095 4 * lane, 0);
3096 read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane +
3097 0x4140);
3098 }
3099
3100 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003101 /* DRAM command MRS
3102 * write MR3 MPR enable
3103 * in this mode only RD and RDA are allowed
3104 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003105 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
3106 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3107 (0xc01 | (ctrl->tMOD << 16)));
3108 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3109 (slotrank << 24) | 0x360004);
3110 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3111
Patrick Rudolph371d2912015-10-09 13:33:25 +02003112 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003113 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
3114 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4);
3115 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3116 (slotrank << 24));
3117 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3118
Patrick Rudolph371d2912015-10-09 13:33:25 +02003119 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003120 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
3121 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3122 0x1001 | ((ctrl->CAS + 8) << 16));
3123 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3124 (slotrank << 24) | 0x60000);
3125 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3126
Patrick Rudolph371d2912015-10-09 13:33:25 +02003127 /* DRAM command MRS
3128 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003129 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
3130 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3131 (0xc01 | (ctrl->tMOD << 16)));
3132 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3133 (slotrank << 24) | 0x360000);
3134 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3135
3136 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
3137
3138 wait_428c(channel);
3139
3140 FOR_ALL_LANES {
3141 statistics[lane][edge] =
3142 read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3143 lane * 4);
3144 }
3145 }
3146 FOR_ALL_LANES {
3147 struct run rn =
3148 get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
3149 edges[lane] = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003150 if (rn.all) {
3151 printk(BIOS_EMERG, "edge discovery failed: %d, %d, %d\n",
3152 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003153 return MAKE_ERR;
3154 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003155 printram("eval %d, %d, %d: %02x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003156 lane, edges[lane]);
3157 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003158 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003159}
3160
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003161static int discover_edges(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003162{
3163 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3164 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3165 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003166 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003167
3168 write32(DEFAULT_MCHBAR + 0x3400, 0);
3169
Patrick Rudolph9b515682015-10-09 13:43:51 +02003170 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003171
3172 FOR_ALL_POPULATED_CHANNELS FOR_ALL_LANES {
3173 write32(DEFAULT_MCHBAR + 4 * lane +
3174 0x400 * channel + 0x4080, 0);
3175 }
3176
3177 FOR_ALL_POPULATED_CHANNELS {
3178 fill_pattern0(ctrl, channel, 0, 0);
3179 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3180 FOR_ALL_LANES {
3181 read32(DEFAULT_MCHBAR + 0x400 * channel +
3182 lane * 4 + 0x4140);
3183 }
3184
3185 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3186 ctrl->timings[channel][slotrank].lanes[lane].falling =
3187 16;
3188 ctrl->timings[channel][slotrank].lanes[lane].rising =
3189 16;
3190 }
3191
3192 program_timings(ctrl, channel);
3193
3194 FOR_ALL_POPULATED_RANKS {
3195 wait_428c(channel);
3196
Patrick Rudolph371d2912015-10-09 13:33:25 +02003197 /* DRAM command MRS
3198 * MR3 enable MPR
3199 * write MR3 MPR enable
3200 * in this mode only RD and RDA are allowed
3201 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003202 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3203 0x1f000);
3204 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3205 0xc01 | (ctrl->tMOD << 16));
3206 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3207 (slotrank << 24) | 0x360004);
3208 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3209
Patrick Rudolph371d2912015-10-09 13:33:25 +02003210 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003211 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3212 0x1f105);
3213 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3214 0x4041003);
3215 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3216 (slotrank << 24) | 0);
3217 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3218
Patrick Rudolph371d2912015-10-09 13:33:25 +02003219 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003220 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3221 0x1f105);
3222 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3223 0x1001 | ((ctrl->CAS + 8) << 16));
3224 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3225 (slotrank << 24) | 0x60000);
3226 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3227
Patrick Rudolph371d2912015-10-09 13:33:25 +02003228 /* DRAM command MRS
3229 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003230 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3231 0x1f000);
3232 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3233 0xc01 | (ctrl->tMOD << 16));
3234 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3235 (slotrank << 24) | 0x360000);
3236 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3237 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3238 0xc0001);
3239
3240 wait_428c(channel);
3241 }
3242
Patrick Rudolph371d2912015-10-09 13:33:25 +02003243 /* XXX: check any measured value ? */
3244
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003245 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3246 ctrl->timings[channel][slotrank].lanes[lane].falling =
3247 48;
3248 ctrl->timings[channel][slotrank].lanes[lane].rising =
3249 48;
3250 }
3251
3252 program_timings(ctrl, channel);
3253
3254 FOR_ALL_POPULATED_RANKS {
3255 wait_428c(channel);
3256
Patrick Rudolph371d2912015-10-09 13:33:25 +02003257 /* DRAM command MRS
3258 * MR3 enable MPR
3259 * write MR3 MPR enable
3260 * in this mode only RD and RDA are allowed
3261 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003262 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3263 0x1f000);
3264 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3265 0xc01 | (ctrl->tMOD << 16));
3266 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3267 (slotrank << 24) | 0x360004);
3268 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3269
Patrick Rudolph371d2912015-10-09 13:33:25 +02003270 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003271 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3272 0x1f105);
3273 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3274 0x4041003);
3275 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3276 (slotrank << 24) | 0);
3277 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3278
Patrick Rudolph371d2912015-10-09 13:33:25 +02003279 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003280 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3281 0x1f105);
3282 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3283 0x1001 | ((ctrl->CAS + 8) << 16));
3284 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3285 (slotrank << 24) | 0x60000);
3286 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3287
Patrick Rudolph371d2912015-10-09 13:33:25 +02003288 /* DRAM command MRS
3289 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003290 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3291 0x1f000);
3292 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3293 0xc01 | (ctrl->tMOD << 16));
3294 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3295 (slotrank << 24) | 0x360000);
3296 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3297
3298 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3299 0xc0001);
3300 wait_428c(channel);
3301 }
3302
Patrick Rudolph371d2912015-10-09 13:33:25 +02003303 /* XXX: check any measured value ? */
3304
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003305 FOR_ALL_LANES {
3306 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel +
3307 lane * 4,
3308 ~read32(DEFAULT_MCHBAR + 0x4040 +
3309 0x400 * channel + lane * 4) & 0xff);
3310 }
3311
3312 fill_pattern0(ctrl, channel, 0, 0xffffffff);
3313 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3314 }
3315
3316 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3317 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003318 printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003319
3320 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003321 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003322 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003323 if (err)
3324 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003325 }
3326
3327 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003328 printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003329
3330 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003331 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003332 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003333 if (err)
3334 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003335 }
3336
3337 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3338
3339 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3340 ctrl->timings[channel][slotrank].lanes[lane].falling =
3341 falling_edges[channel][slotrank][lane];
3342 ctrl->timings[channel][slotrank].lanes[lane].rising =
3343 rising_edges[channel][slotrank][lane];
3344 }
3345
3346 FOR_ALL_POPULATED_CHANNELS {
3347 program_timings(ctrl, channel);
3348 }
3349
3350 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3351 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3352 0);
3353 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003354 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003355}
3356
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003357static int discover_edges_write_real(ramctr_timing *ctrl, int channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003358 int slotrank, int *edges)
3359{
3360 int edge;
3361 u32 raw_statistics[MAX_EDGE_TIMING + 1];
3362 int statistics[MAX_EDGE_TIMING + 1];
3363 const int reg3000b24[] = { 0, 0xc, 0x2c };
3364 int lane, i;
3365 int lower[NUM_LANES];
3366 int upper[NUM_LANES];
3367 int pat;
3368
3369 FOR_ALL_LANES {
3370 lower[lane] = 0;
3371 upper[lane] = MAX_EDGE_TIMING;
3372 }
3373
3374 for (i = 0; i < 3; i++) {
3375 write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel,
3376 reg3000b24[i] << 24);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003377 printram("[%x] = 0x%08x\n",
3378 0x3000 + 0x100 * channel, reg3000b24[i] << 24);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003379 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3380 fill_pattern5(ctrl, channel, pat);
3381 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003382 printram("using pattern %d\n", pat);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003383 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3384 FOR_ALL_LANES {
3385 ctrl->timings[channel][slotrank].lanes[lane].
3386 rising = edge;
3387 ctrl->timings[channel][slotrank].lanes[lane].
3388 falling = edge;
3389 }
3390 program_timings(ctrl, channel);
3391
3392 FOR_ALL_LANES {
3393 write32(DEFAULT_MCHBAR + 0x4340 +
3394 0x400 * channel + 4 * lane, 0);
3395 read32(DEFAULT_MCHBAR + 0x400 * channel +
3396 4 * lane + 0x4140);
3397 }
3398 wait_428c(channel);
3399
Patrick Rudolph371d2912015-10-09 13:33:25 +02003400 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003401 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3402 0x1f006);
3403 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3404 0x4 | (ctrl->tRCD << 16)
3405 | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) <<
3406 10));
3407 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3408 (slotrank << 24) | 0x60000);
3409 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel,
3410 0x240);
3411
Patrick Rudolph371d2912015-10-09 13:33:25 +02003412 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003413 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3414 0x1f201);
3415 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3416 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) <<
3417 16));
3418 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3419 (slotrank << 24));
3420 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel,
3421 0x242);
3422
Patrick Rudolph371d2912015-10-09 13:33:25 +02003423 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003424 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3425 0x1f105);
3426 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3427 0x4005020 | (max(ctrl->tRTP, 8) << 16));
3428 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3429 (slotrank << 24));
3430 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel,
3431 0x242);
3432
Patrick Rudolph371d2912015-10-09 13:33:25 +02003433 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003434 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3435 0x1f002);
3436 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3437 0xc01 | (ctrl->tRP << 16));
3438 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3439 (slotrank << 24) | 0x60400);
3440 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3441
3442 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3443 0xc0001);
3444 wait_428c(channel);
3445 FOR_ALL_LANES {
3446 read32(DEFAULT_MCHBAR + 0x4340 +
3447 0x400 * channel + lane * 4);
3448 }
3449
3450 raw_statistics[edge] =
3451 MCHBAR32(0x436c + 0x400 * channel);
3452 }
3453 FOR_ALL_LANES {
3454 struct run rn;
3455 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++)
3456 statistics[edge] =
3457 ! !(raw_statistics[edge] & (1 << lane));
3458 rn = get_longest_zero_run(statistics,
3459 MAX_EDGE_TIMING + 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003460 printram("edges: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003461 channel, slotrank, i, rn.start, rn.middle,
3462 rn.end, rn.start + ctrl->edge_offset[i],
3463 rn.end - ctrl->edge_offset[i]);
3464 lower[lane] =
3465 max(rn.start + ctrl->edge_offset[i], lower[lane]);
3466 upper[lane] =
3467 min(rn.end - ctrl->edge_offset[i], upper[lane]);
3468 edges[lane] = (lower[lane] + upper[lane]) / 2;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003469 if (rn.all || (lower[lane] > upper[lane])) {
3470 printk(BIOS_EMERG, "edge write discovery failed: %d, %d, %d\n",
3471 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003472 return MAKE_ERR;
3473 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003474 }
3475 }
3476 }
3477
3478 write32(DEFAULT_MCHBAR + 0x3000, 0);
3479 printram("CPA\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003480 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003481}
3482
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003483static int discover_edges_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003484{
3485 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3486 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3487 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003488 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003489
3490 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3491 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003492 printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003493
3494 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003495 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003496 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003497 if (err)
3498 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003499 }
3500
3501 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003502 printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003503
3504 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003505 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003506 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003507 if (err)
3508 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003509 }
3510
3511 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3512
3513 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3514 ctrl->timings[channel][slotrank].lanes[lane].falling =
3515 falling_edges[channel][slotrank][lane];
3516 ctrl->timings[channel][slotrank].lanes[lane].rising =
3517 rising_edges[channel][slotrank][lane];
3518 }
3519
3520 FOR_ALL_POPULATED_CHANNELS
3521 program_timings(ctrl, channel);
3522
3523 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3524 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3525 0);
3526 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003527 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003528}
3529
3530static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
3531{
3532 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003533 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003534 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
3535 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3536 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD)
3537 << 10) | (ctrl->tRCD << 16) | 4);
3538 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3539 (slotrank << 24) | 0x60000);
3540 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
3541
Patrick Rudolph371d2912015-10-09 13:33:25 +02003542 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003543 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
3544 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3545 0x80011e0 |
3546 ((ctrl->tWTR + ctrl->CWL + 8) << 16));
3547 write32(DEFAULT_MCHBAR + 0x4204 +
3548 0x400 * channel, (slotrank << 24));
3549 write32(DEFAULT_MCHBAR + 0x4214 +
3550 0x400 * channel, 0x242);
3551
Patrick Rudolph371d2912015-10-09 13:33:25 +02003552 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003553 write32(DEFAULT_MCHBAR + 0x4228 +
3554 0x400 * channel, 0x1f105);
3555 write32(DEFAULT_MCHBAR + 0x4238 +
3556 0x400 * channel,
3557 0x40011e0 | (max(ctrl->tRTP, 8) << 16));
3558 write32(DEFAULT_MCHBAR + 0x4208 +
3559 0x400 * channel, (slotrank << 24));
3560 write32(DEFAULT_MCHBAR + 0x4218 +
3561 0x400 * channel, 0x242);
3562
Patrick Rudolph371d2912015-10-09 13:33:25 +02003563 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003564 write32(DEFAULT_MCHBAR + 0x422c +
3565 0x400 * channel, 0x1f002);
3566 write32(DEFAULT_MCHBAR + 0x423c +
3567 0x400 * channel,
3568 0x1001 | (ctrl->tRP << 16));
3569 write32(DEFAULT_MCHBAR + 0x420c +
3570 0x400 * channel,
3571 (slotrank << 24) | 0x60400);
3572 write32(DEFAULT_MCHBAR + 0x421c +
3573 0x400 * channel, 0);
3574
3575 write32(DEFAULT_MCHBAR + 0x4284 +
3576 0x400 * channel, 0xc0001);
3577 wait_428c(channel);
3578}
3579
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003580static int discover_timC_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003581{
3582 const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
3583 int i, pat;
3584
3585 int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3586 int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3587 int channel, slotrank, lane;
3588
3589 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3590 lower[channel][slotrank][lane] = 0;
3591 upper[channel][slotrank][lane] = MAX_TIMC;
3592 }
3593
3594 write32(DEFAULT_MCHBAR + 0x4ea8, 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003595 printram("discover timC write:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003596
3597 for (i = 0; i < 3; i++)
3598 FOR_ALL_POPULATED_CHANNELS {
3599 write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100),
3600 (rege3c_b24[i] << 24)
3601 | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100))
3602 & ~0x3f000000));
3603 udelay(2);
3604 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3605 FOR_ALL_POPULATED_RANKS {
3606 int timC;
3607 u32 raw_statistics[MAX_TIMC + 1];
3608 int statistics[MAX_TIMC + 1];
3609
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003610 /* Make sure rn.start < rn.end */
3611 statistics[MAX_TIMC] = 1;
3612
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003613 fill_pattern5(ctrl, channel, pat);
3614 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003615 for (timC = 0; timC < MAX_TIMC; timC++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003616 FOR_ALL_LANES
3617 ctrl->timings[channel][slotrank].lanes[lane].timC = timC;
3618 program_timings(ctrl, channel);
3619
3620 test_timC_write (ctrl, channel, slotrank);
3621
3622 raw_statistics[timC] =
3623 MCHBAR32(0x436c + 0x400 * channel);
3624 }
3625 FOR_ALL_LANES {
3626 struct run rn;
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003627 for (timC = 0; timC < MAX_TIMC; timC++)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003628 statistics[timC] =
3629 !!(raw_statistics[timC] &
3630 (1 << lane));
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003631
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003632 rn = get_longest_zero_run(statistics,
3633 MAX_TIMC + 1);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003634 if (rn.all) {
3635 printk(BIOS_EMERG, "timC write discovery failed: %d, %d, %d\n",
3636 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003637 return MAKE_ERR;
3638 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003639 printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003640 channel, slotrank, i, rn.start,
3641 rn.middle, rn.end,
3642 rn.start + ctrl->timC_offset[i],
3643 rn.end - ctrl->timC_offset[i]);
3644 lower[channel][slotrank][lane] =
3645 max(rn.start + ctrl->timC_offset[i],
3646 lower[channel][slotrank][lane]);
3647 upper[channel][slotrank][lane] =
3648 min(rn.end - ctrl->timC_offset[i],
3649 upper[channel][slotrank][lane]);
3650
3651 }
3652 }
3653 }
3654 }
3655
3656 FOR_ALL_CHANNELS {
3657 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3658 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3659 ~0x3f000000));
3660 udelay(2);
3661 }
3662
3663 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3664
3665 printram("CPB\n");
3666
3667 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
Patrick Rudolpha649a542016-01-17 18:32:06 +01003668 printram("timC %d, %d, %d: %x\n", channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003669 slotrank, lane,
3670 (lower[channel][slotrank][lane] +
3671 upper[channel][slotrank][lane]) / 2);
3672 ctrl->timings[channel][slotrank].lanes[lane].timC =
3673 (lower[channel][slotrank][lane] +
3674 upper[channel][slotrank][lane]) / 2;
3675 }
3676 FOR_ALL_POPULATED_CHANNELS {
3677 program_timings(ctrl, channel);
3678 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003679 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003680}
3681
3682static void normalize_training(ramctr_timing * ctrl)
3683{
3684 int channel, slotrank, lane;
3685 int mat = 0;
3686
3687 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3688 int delta;
3689 FOR_ALL_LANES mat =
3690 max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat);
3691 delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028;
3692 ctrl->timings[channel][slotrank].val_4024 += delta;
3693 ctrl->timings[channel][slotrank].val_4028 += delta;
3694 }
3695
3696 FOR_ALL_POPULATED_CHANNELS {
3697 program_timings(ctrl, channel);
3698 }
3699}
3700
3701static void write_controller_mr(ramctr_timing * ctrl)
3702{
3703 int channel, slotrank;
3704
3705 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3706 write32(DEFAULT_MCHBAR + 0x0004 + (channel << 8) +
3707 lane_registers[slotrank], make_mr0(ctrl, slotrank));
3708 write32(DEFAULT_MCHBAR + 0x0008 + (channel << 8) +
Patrick Rudolph7e513d12016-01-10 14:22:34 +01003709 lane_registers[slotrank],
3710 make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003711 }
3712}
3713
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003714static int channel_test(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003715{
3716 int channel, slotrank, lane;
3717
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003718 slotrank = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003719 FOR_ALL_POPULATED_CHANNELS
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003720 if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) {
3721 printk(BIOS_EMERG, "Mini channel test failed (1): %d\n",
3722 channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003723 return MAKE_ERR;
3724 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003725 FOR_ALL_POPULATED_CHANNELS {
3726 fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
3727
3728 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3729 }
3730
3731 for (slotrank = 0; slotrank < 4; slotrank++)
3732 FOR_ALL_CHANNELS
3733 if (ctrl->rankmap[channel] & (1 << slotrank)) {
3734 FOR_ALL_LANES {
3735 write32(DEFAULT_MCHBAR + (0x4f40 + 4 * lane), 0);
3736 write32(DEFAULT_MCHBAR + (0x4d40 + 4 * lane), 0);
3737 }
3738 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003739 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003740 write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
3741 write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10), 0x0028a004);
3742 write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
3743 0x00060000 | (slotrank << 24));
3744 write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003745 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003746 write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
3747 write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281064);
3748 write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
3749 0x00000000 | (slotrank << 24));
3750 write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003751 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003752 write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f105);
3753 write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x04281064);
3754 write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
3755 0x00000000 | (slotrank << 24));
3756 write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003757 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003758 write32(DEFAULT_MCHBAR + 0x422c + (channel << 10), 0x0001f002);
3759 write32(DEFAULT_MCHBAR + 0x423c + (channel << 10), 0x00280c01);
3760 write32(DEFAULT_MCHBAR + 0x420c + (channel << 10),
3761 0x00060400 | (slotrank << 24));
3762 write32(DEFAULT_MCHBAR + 0x421c + (channel << 10), 0x00000240);
3763 write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
3764 wait_428c(channel);
3765 FOR_ALL_LANES
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003766 if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) {
3767 printk(BIOS_EMERG, "Mini channel test failed (2): %d, %d, %d\n",
3768 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003769 return MAKE_ERR;
3770 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003771 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003772 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003773}
3774
3775static void set_scrambling_seed(ramctr_timing * ctrl)
3776{
3777 int channel;
3778
3779 /* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
3780 I don't think so. */
3781 static u32 seeds[NUM_CHANNELS][3] = {
3782 {0x00009a36, 0xbafcfdcf, 0x46d1ab68},
3783 {0x00028bfa, 0x53fe4b49, 0x19ed5483}
3784 };
3785 FOR_ALL_POPULATED_CHANNELS {
3786 MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
3787 write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
3788 write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
3789 write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
3790 }
3791}
3792
3793static void set_4f8c(void)
3794{
3795 struct cpuid_result cpures;
3796 u32 cpu;
3797
Ryan Salsamendie4da9aa2016-06-24 12:01:11 -07003798 cpures = cpuid(1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003799 cpu = (cpures.eax);
3800 if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) {
3801 MCHBAR32(0x4f8c) = 0x141D1519;
3802 } else {
3803 MCHBAR32(0x4f8c) = 0x551D1519;
3804 }
3805}
3806
3807static void prepare_training(ramctr_timing * ctrl)
3808{
3809 int channel;
3810
3811 FOR_ALL_POPULATED_CHANNELS {
3812 // Always drive command bus
3813 MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000;
3814 }
3815
3816 udelay(1);
3817
3818 FOR_ALL_POPULATED_CHANNELS {
3819 wait_428c(channel);
3820 }
3821}
3822
3823static void set_4008c(ramctr_timing * ctrl)
3824{
3825 int channel, slotrank;
3826 u32 reg;
3827 FOR_ALL_POPULATED_CHANNELS {
3828 u32 b20, b4_8_12;
3829 int min_320c = 10000;
3830 int max_320c = -10000;
3831
3832 FOR_ALL_POPULATED_RANKS {
3833 max_320c = max(ctrl->timings[channel][slotrank].val_320c, max_320c);
3834 min_320c = min(ctrl->timings[channel][slotrank].val_320c, min_320c);
3835 }
3836
3837 if (max_320c - min_320c > 51)
3838 b20 = 0;
3839 else
3840 b20 = ctrl->ref_card_offset[channel];
3841
3842 if (ctrl->reg_320c_range_threshold < max_320c - min_320c)
3843 b4_8_12 = 0x3330;
3844 else
3845 b4_8_12 = 0x2220;
3846
3847 reg = read32(DEFAULT_MCHBAR + 0x400c + (channel << 10));
3848 write32(DEFAULT_MCHBAR + 0x400c + (channel << 10),
3849 (reg & 0xFFF0FFFF)
3850 | (ctrl->ref_card_offset[channel] << 16)
3851 | (ctrl->ref_card_offset[channel] << 18));
3852 write32(DEFAULT_MCHBAR + 0x4008 + (channel << 10),
3853 0x0a000000
3854 | (b20 << 20)
3855 | ((ctrl->ref_card_offset[channel] + 2) << 16)
3856 | b4_8_12);
3857 }
3858}
3859
3860static void set_42a0(ramctr_timing * ctrl)
3861{
3862 int channel;
3863 FOR_ALL_POPULATED_CHANNELS {
3864 write32(DEFAULT_MCHBAR + (0x42a0 + 0x400 * channel),
3865 0x00001000 | ctrl->rankmap[channel]);
3866 MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK
3867 }
3868}
3869
3870static int encode_5d10(int ns)
3871{
3872 return (ns + 499) / 500;
3873}
3874
3875/* FIXME: values in this function should be hardware revision-dependent. */
3876static void final_registers(ramctr_timing * ctrl)
3877{
3878 int channel;
3879 int t1_cycles = 0, t1_ns = 0, t2_ns;
3880 int t3_ns;
3881 u32 r32;
3882
3883 write32(DEFAULT_MCHBAR + 0x4cd4, 0x00000046);
3884
3885 write32(DEFAULT_MCHBAR + 0x400c, (read32(DEFAULT_MCHBAR + 0x400c) & 0xFFFFCFFF) | 0x1000); // OK
3886 write32(DEFAULT_MCHBAR + 0x440c, (read32(DEFAULT_MCHBAR + 0x440c) & 0xFFFFCFFF) | 0x1000); // OK
3887 write32(DEFAULT_MCHBAR + 0x4cb0, 0x00000740);
3888 write32(DEFAULT_MCHBAR + 0x4380, 0x00000aaa); // OK
3889 write32(DEFAULT_MCHBAR + 0x4780, 0x00000aaa); // OK
3890 write32(DEFAULT_MCHBAR + 0x4f88, 0x5f7003ff); // OK
3891 write32(DEFAULT_MCHBAR + 0x5064, 0x00073000 | ctrl->reg_5064b0); // OK
3892
3893 FOR_ALL_CHANNELS {
3894 switch (ctrl->rankmap[channel]) {
3895 /* Unpopulated channel. */
3896 case 0:
3897 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0);
3898 break;
3899 /* Only single-ranked dimms. */
3900 case 1:
3901 case 4:
3902 case 5:
3903 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x373131);
3904 break;
3905 /* Dual-ranked dimms present. */
3906 default:
3907 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x9b6ea1);
3908 break;
3909 }
3910 }
3911
3912 write32 (DEFAULT_MCHBAR + 0x5880, 0xca9171e5);
3913 write32 (DEFAULT_MCHBAR + 0x5888,
3914 (read32 (DEFAULT_MCHBAR + 0x5888) & ~0xffffff) | 0xe4d5d0);
3915 write32 (DEFAULT_MCHBAR + 0x58a8, read32 (DEFAULT_MCHBAR + 0x58a8) & ~0x1f);
3916 write32 (DEFAULT_MCHBAR + 0x4294,
3917 (read32 (DEFAULT_MCHBAR + 0x4294) & ~0x30000)
3918 | (1 << 16));
3919 write32 (DEFAULT_MCHBAR + 0x4694,
3920 (read32 (DEFAULT_MCHBAR + 0x4694) & ~0x30000)
3921 | (1 << 16));
3922
3923 MCHBAR32(0x5030) |= 1; // OK
3924 MCHBAR32(0x5030) |= 0x80; // OK
3925 MCHBAR32(0x5f18) = 0xfa; // OK
3926
3927 /* Find a populated channel. */
3928 FOR_ALL_POPULATED_CHANNELS
3929 break;
3930
3931 t1_cycles = ((read32(DEFAULT_MCHBAR + 0x4290 + channel * 0x400) >> 8) & 0xff);
3932 r32 = read32(DEFAULT_MCHBAR + 0x5064);
3933 if (r32 & 0x20000)
3934 t1_cycles += (r32 & 0xfff);
3935 t1_cycles += (read32(DEFAULT_MCHBAR + channel * 0x400 + 0x42a4) & 0xfff);
3936 t1_ns = t1_cycles * ctrl->tCK / 256 + 544;
3937 if (!(r32 & 0x20000))
3938 t1_ns += 500;
3939
3940 t2_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f10) >> 8) & 0xfff);
3941 if ( read32(DEFAULT_MCHBAR + 0x5f00) & 8 )
3942 {
3943 t3_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f20) >> 8) & 0xfff);
3944 t3_ns += 10 * (read32(DEFAULT_MCHBAR + 0x5f18) & 0xff);
3945 }
3946 else
3947 {
3948 t3_ns = 500;
3949 }
3950 printk(BIOS_DEBUG, "t123: %d, %d, %d\n",
3951 t1_ns, t2_ns, t3_ns);
3952 write32 (DEFAULT_MCHBAR + 0x5d10,
3953 ((encode_5d10(t1_ns) + encode_5d10(t2_ns)) << 16)
3954 | (encode_5d10(t1_ns) << 8)
3955 | ((encode_5d10(t3_ns) + encode_5d10(t2_ns) + encode_5d10(t1_ns)) << 24)
3956 | (read32(DEFAULT_MCHBAR + 0x5d10) & 0xC0C0C0C0)
3957 | 0xc);
3958}
3959
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003960static void save_timings(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003961{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003962 /* Save the MRC S3 restore data to cbmem */
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003963 store_current_mrc_cache(ctrl, sizeof(*ctrl));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003964}
3965
3966static void restore_timings(ramctr_timing * ctrl)
3967{
3968 int channel, slotrank, lane;
3969
3970 FOR_ALL_POPULATED_CHANNELS
3971 MCHBAR32(0x4004 + 0x400 * channel) =
3972 ctrl->tRRD
3973 | (ctrl->tRTP << 4)
3974 | (ctrl->tCKE << 8)
3975 | (ctrl->tWTR << 12)
3976 | (ctrl->tFAW << 16)
3977 | (ctrl->tWR << 24)
3978 | (ctrl->cmd_stretch[channel] << 30);
3979
3980 udelay(1);
3981
3982 FOR_ALL_POPULATED_CHANNELS {
3983 wait_428c(channel);
3984 }
3985
3986 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3987 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
3988 + 4 * lane, 0);
3989 }
3990
3991 FOR_ALL_POPULATED_CHANNELS
3992 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
3993 read32(DEFAULT_MCHBAR + 0x4008 +
3994 0x400 * channel) | 0x8000000);
3995
3996 FOR_ALL_POPULATED_CHANNELS {
3997 udelay (1);
3998 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
3999 read32(DEFAULT_MCHBAR + 0x4020 +
4000 0x400 * channel) | 0x200000);
4001 }
4002
4003 printram("CPE\n");
4004
4005 write32(DEFAULT_MCHBAR + 0x3400, 0);
4006 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
4007
4008 printram("CP5b\n");
4009
4010 FOR_ALL_POPULATED_CHANNELS {
4011 program_timings(ctrl, channel);
4012 }
4013
4014 u32 reg, addr;
4015
Elyes HAOUAS7db506c2016-10-02 11:56:39 +02004016 while (!(MCHBAR32(0x5084) & 0x10000));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004017 do {
4018 reg = MCHBAR32(0x428c);
4019 } while ((reg & 0x14) == 0);
4020
4021 // Set state of memory controller
4022 MCHBAR32(0x5030) = 0x116;
4023 MCHBAR32(0x4ea0) = 0;
4024
4025 // Wait 500us
4026 udelay(500);
4027
4028 FOR_ALL_CHANNELS {
4029 // Set valid rank CKE
4030 reg = 0;
4031 reg = (reg & ~0xf) | ctrl->rankmap[channel];
4032 addr = 0x400 * channel + 0x42a0;
4033 MCHBAR32(addr) = reg;
4034
4035 // Wait 10ns for ranks to settle
4036 //udelay(0.01);
4037
4038 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
4039 MCHBAR32(addr) = reg;
4040
4041 // Write reset using a NOP
4042 write_reset(ctrl);
4043 }
4044
4045 /* mrs commands. */
4046 dram_mrscommands(ctrl);
4047
4048 printram("CP5c\n");
4049
4050 write32(DEFAULT_MCHBAR + 0x3000, 0);
4051
4052 FOR_ALL_CHANNELS {
4053 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
4054 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
4055 ~0x3f000000));
4056 udelay(2);
4057 }
4058
4059 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
4060}
4061
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004062static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot,
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004063 int s3_resume, int me_uma_size)
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004064{
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004065 int err;
4066
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004067 printk(BIOS_DEBUG, "Starting RAM training (%d).\n", fast_boot);
4068
4069 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004070 /* Find fastest common supported parameters */
4071 dram_find_common_params(ctrl);
4072
4073 dram_dimm_mapping(ctrl);
4074 }
4075
4076 /* Set MCU frequency */
4077 dram_freq(ctrl);
4078
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004079 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004080 /* Calculate timings */
4081 dram_timing(ctrl);
4082 }
4083
4084 /* Set version register */
4085 MCHBAR32(0x5034) = 0xC04EB002;
4086
4087 /* Enable crossover */
4088 dram_xover(ctrl);
4089
4090 /* Set timing and refresh registers */
4091 dram_timing_regs(ctrl);
4092
4093 /* Power mode preset */
4094 MCHBAR32(0x4e80) = 0x5500;
4095
4096 /* Set scheduler parameters */
4097 MCHBAR32(0x4c20) = 0x10100005;
4098
Elyes HAOUAS15279a92016-07-28 21:05:26 +02004099 /* Set CPU specific register */
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004100 set_4f8c();
4101
4102 /* Clear IO reset bit */
4103 MCHBAR32(0x5030) &= ~0x20;
4104
4105 /* Set MAD-DIMM registers */
4106 dram_dimm_set_mapping(ctrl);
4107 printk(BIOS_DEBUG, "Done dimm mapping\n");
4108
4109 /* Zone config */
4110 dram_zones(ctrl, 1);
4111
4112 /* Set memory map */
4113 dram_memorymap(ctrl, me_uma_size);
4114 printk(BIOS_DEBUG, "Done memory map\n");
4115
4116 /* Set IO registers */
4117 dram_ioregs(ctrl);
4118 printk(BIOS_DEBUG, "Done io registers\n");
4119
4120 udelay(1);
4121
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004122 if (fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004123 restore_timings(ctrl);
4124 } else {
4125 /* Do jedec ddr3 reset sequence */
4126 dram_jedecreset(ctrl);
4127 printk(BIOS_DEBUG, "Done jedec reset\n");
4128
4129 /* MRS commands */
4130 dram_mrscommands(ctrl);
4131 printk(BIOS_DEBUG, "Done MRS commands\n");
4132
4133 /* Prepare for memory training */
4134 prepare_training(ctrl);
4135
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004136 err = read_training(ctrl);
4137 if (err)
4138 return err;
4139
4140 err = write_training(ctrl);
4141 if (err)
4142 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004143
4144 printram("CP5a\n");
4145
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004146 err = discover_edges(ctrl);
4147 if (err)
4148 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004149
4150 printram("CP5b\n");
4151
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004152 err = command_training(ctrl);
4153 if (err)
4154 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004155
4156 printram("CP5c\n");
4157
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004158 err = discover_edges_write(ctrl);
4159 if (err)
4160 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004161
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004162 err = discover_timC_write(ctrl);
4163 if (err)
4164 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004165
4166 normalize_training(ctrl);
4167 }
4168
4169 set_4008c(ctrl);
4170
4171 write_controller_mr(ctrl);
4172
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004173 if (!s3_resume) {
4174 err = channel_test(ctrl);
4175 if (err)
4176 return err;
4177 }
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004178
4179 return 0;
4180}
4181
4182void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004183 int s3resume)
4184{
4185 int me_uma_size;
4186 int cbmem_was_inited;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004187 ramctr_timing ctrl;
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004188 int fast_boot;
4189 struct mrc_data_container *mrc_cache;
4190 ramctr_timing *ctrl_cached;
Patrick Rudolph31d19592016-03-26 12:22:34 +01004191 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004192
4193 MCHBAR32(0x5f00) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004194
Vadim Bendebury7a3f36a2012-04-18 15:47:32 -07004195 report_platform_info();
4196
Stefan Reinauer00636b02012-04-04 00:08:51 +02004197 /* Wait for ME to be ready */
4198 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004199 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004200
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004201 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +02004202
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004203 u32 reg_5d10;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004204
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004205 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004206
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004207 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +02004208
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004209 reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10); // !!! = 0x00000000
4210 if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */
4211 && reg_5d10 && !s3resume) {
4212 write32(DEFAULT_MCHBAR + 0x5d10, 0);
4213 /* Need reset. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02004214 outb(0x6, 0xcf9);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004215
Patrick Georgi546953c2014-11-29 10:38:17 +01004216 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004217 }
Stefan Reinauer00636b02012-04-04 00:08:51 +02004218
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +02004219 memset(&ctrl, 0, sizeof(ctrl));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004220
4221 early_pch_init_native();
4222 early_thermal_init();
4223
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004224 /* try to find timings in MRC cache */
4225 mrc_cache = find_current_mrc_cache();
4226 if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(ctrl))) {
4227 if (s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004228 /* Failed S3 resume, reset to come up cleanly */
4229 outb(0x6, 0xcf9);
4230 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004231 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004232 ctrl_cached = NULL;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004233 } else {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004234 ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004235 }
4236
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004237 /* verify MRC cache for fast boot */
4238 if (ctrl_cached) {
4239 /* check SPD CRC16 to make sure the DIMMs haven't been replaced */
4240 fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
4241 if (!fast_boot)
4242 printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
4243 if (!fast_boot && s3resume) {
4244 /* Failed S3 resume, reset to come up cleanly */
4245 outb(0x6, 0xcf9);
4246 halt();
4247 }
4248 } else
4249 fast_boot = 0;
4250
4251 if (fast_boot) {
4252 printk(BIOS_DEBUG, "Trying stored timings.\n");
4253 memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
4254
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004255 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004256 if (err) {
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004257 if (s3resume) {
4258 /* Failed S3 resume, reset to come up cleanly */
4259 outb(0x6, 0xcf9);
4260 halt();
4261 }
4262 /* no need to erase bad mrc cache here, it gets overwritten on
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004263 * successful boot. */
4264 printk(BIOS_ERR, "Stored timings are invalid !\n");
4265 fast_boot = 0;
4266 }
4267 }
4268 if (!fast_boot) {
4269 ctrl.mobile = mobile;
4270 ctrl.tCK = min_tck;
4271
4272 /* Get DDR3 SPD data */
4273 dram_find_spds_ddr3(spds, &ctrl);
4274
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004275 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004276 }
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004277
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004278 if (err) {
4279 /* fallback: disable failing channel */
4280 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
4281 printram("Disable failing channel.\n");
4282
4283 /* Reset DDR3 frequency */
4284 dram_find_spds_ddr3(spds, &ctrl);
4285
4286 /* disable failing channel */
4287 disable_channel(&ctrl, GET_ERR_CHANNEL(err));
4288
4289 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
4290 }
4291
Patrick Rudolph31d19592016-03-26 12:22:34 +01004292 if (err)
4293 die("raminit failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004294
4295 /* FIXME: should be hardware revision-dependent. */
4296 write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
4297
4298 set_scrambling_seed(&ctrl);
4299
4300 set_42a0(&ctrl);
4301
4302 final_registers(&ctrl);
4303
4304 /* Zone config */
4305 dram_zones(&ctrl, 0);
4306
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004307 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004308 quick_ram_check();
4309
4310 intel_early_me_status();
4311 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
4312 intel_early_me_status();
4313
Stefan Reinauer00636b02012-04-04 00:08:51 +02004314 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004315
4316 cbmem_was_inited = !cbmem_recovery(s3resume);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004317 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004318 save_timings(&ctrl);
4319 if (s3resume && !cbmem_was_inited) {
4320 /* Failed S3 resume, reset to come up cleanly */
4321 outb(0x6, 0xcf9);
4322 halt();
4323 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +01004324
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004325 fill_smbios17(&ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004326}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004327
4328#define HOST_BRIDGE PCI_DEVFN(0, 0)
4329#define DEFAULT_TCK TCK_800MHZ
4330
4331static unsigned int get_mem_min_tck(void)
4332{
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004333 u32 reg32;
4334 u8 rev;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004335 const struct device *dev;
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004336 const struct northbridge_intel_sandybridge_config *cfg = NULL;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004337
4338 dev = dev_find_slot(0, HOST_BRIDGE);
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004339 if (dev)
4340 cfg = dev->chip_info;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004341
4342 /* If this is zero, it just means devicetree.cb didn't set it */
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004343 if (!cfg || cfg->max_mem_clock_mhz == 0) {
4344 rev = pci_read_config8(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004345
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004346 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
4347 /* read Capabilities A Register DMFC bits */
4348 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A);
4349 reg32 &= 0x7;
4350
4351 switch (reg32) {
4352 case 7: return TCK_533MHZ;
4353 case 6: return TCK_666MHZ;
4354 case 5: return TCK_800MHZ;
4355 /* reserved: */
4356 default:
4357 break;
4358 }
4359 } else {
4360 /* read Capabilities B Register DMFC bits */
4361 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
4362 reg32 = (reg32 >> 4) & 0x7;
4363
4364 switch (reg32) {
4365 case 7: return TCK_533MHZ;
4366 case 6: return TCK_666MHZ;
4367 case 5: return TCK_800MHZ;
4368 case 4: return TCK_933MHZ;
4369 case 3: return TCK_1066MHZ;
4370 case 2: return TCK_1200MHZ;
4371 case 1: return TCK_1333MHZ;
4372 /* reserved: */
4373 default:
4374 break;
4375 }
4376 }
4377 return DEFAULT_TCK;
4378 } else {
Patrick Rudolph7bddd302016-06-11 18:39:35 +02004379 if (cfg->max_mem_clock_mhz >= 1066)
4380 return TCK_1066MHZ;
4381 else if (cfg->max_mem_clock_mhz >= 933)
4382 return TCK_933MHZ;
4383 else if (cfg->max_mem_clock_mhz >= 800)
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004384 return TCK_800MHZ;
4385 else if (cfg->max_mem_clock_mhz >= 666)
4386 return TCK_666MHZ;
4387 else if (cfg->max_mem_clock_mhz >= 533)
4388 return TCK_533MHZ;
4389 else
4390 return TCK_400MHZ;
4391 }
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004392}
4393
Patrick Rudolph266a1f72016-06-09 18:13:34 +02004394#define DEFAULT_PCI_MMIO_SIZE 2048
4395
4396static unsigned int get_mmio_size(void)
4397{
4398 const struct device *dev;
4399 const struct northbridge_intel_sandybridge_config *cfg = NULL;
4400
4401 dev = dev_find_slot(0, HOST_BRIDGE);
4402 if (dev)
4403 cfg = dev->chip_info;
4404
4405 /* If this is zero, it just means devicetree.cb didn't set it */
4406 if (!cfg || cfg->pci_mmio_size == 0)
4407 return DEFAULT_PCI_MMIO_SIZE;
4408 else
4409 return cfg->pci_mmio_size;
4410}
4411
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004412void perform_raminit(int s3resume)
4413{
4414 spd_raw_data spd[4];
4415
4416 post_code(0x3a);
4417
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +02004418 memset (spd, 0, sizeof(spd));
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004419 mainboard_get_spd(spd);
4420
4421 timestamp_add_now(TS_BEFORE_INITRAM);
4422
4423 init_dram_ddr3(spd, 1, get_mem_min_tck(), s3resume);
4424}