blob: ba03bbbc9273d46b09892a5a6737e5bd92affa16 [file] [log] [blame]
Stefan Reinauer00636b02012-04-04 00:08:51 +02001/*
2 * This file is part of the coreboot project.
3 *
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004 * Copyright (C) 2014 Damien Zammit <damien@zamaudio.com>
5 * Copyright (C) 2014 Vladimir Serbinenko <phcoder@gmail.com>
Stefan Reinauer00636b02012-04-04 00:08:51 +02006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Stefan Reinauer00636b02012-04-04 00:08:51 +020015 */
16
17#include <console/console.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +020018#include <console/usb.h>
Kyösti Mälkki5687fc92013-11-28 18:11:49 +020019#include <bootmode.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020020#include <string.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020021#include <arch/io.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020022#include <cbmem.h>
23#include <arch/cbfs.h>
24#include <cbfs.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070025#include <halt.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020026#include <ip_checksum.h>
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010027#include <timestamp.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020028#include <pc80/mc146818rtc.h>
Alexander Couzens81c5c762016-03-09 03:13:45 +010029#include <northbridge/intel/common/mrc_cache.h>
Duncan Laurie7b508dd2012-04-09 12:30:43 -070030#include <device/pci_def.h>
Patrick Rudolphb97009e2016-02-28 15:24:04 +010031#include <memory_info.h>
32#include <smbios.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070033#include "raminit_native.h"
Stefan Reinauer00636b02012-04-04 00:08:51 +020034#include "sandybridge.h"
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070035#include <delay.h>
36#include <lib.h>
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010037#include <device/device.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020038
39/* Management Engine is in the southbridge */
40#include "southbridge/intel/bd82x6x/me.h"
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070041/* For SPD. */
42#include "southbridge/intel/bd82x6x/smbus.h"
43#include "arch/cpu.h"
44#include "cpu/x86/msr.h"
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010045#include <northbridge/intel/sandybridge/chip.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020046
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070047/* FIXME: no ECC support. */
48/* FIXME: no support for 3-channel chipsets. */
Stefan Reinauer00636b02012-04-04 00:08:51 +020049
Patrick Rudolph371d2912015-10-09 13:33:25 +020050/*
51 * Register description:
52 * Intel provides a command queue of depth four.
53 * Every command is configured by using multiple registers.
54 * On executing the command queue you have to provide the depth used.
55 *
56 * Known registers:
57 * Channel X = [0, 1]
58 * Command queue index Y = [0, 1, 2, 3]
59 *
60 * DEFAULT_MCHBAR + 0x4220 + 0x400 * X + 4 * Y: command io register
61 * Controls the DRAM command signals
62 * Bit 0: !RAS
63 * Bit 1: !CAS
64 * Bit 2: !WE
65 *
66 * DEFAULT_MCHBAR + 0x4200 + 0x400 * X + 4 * Y: addr bankslot io register
67 * Controls the address, bank address and slotrank signals
68 * Bit 0-15 : Address
69 * Bit 20-22: Bank Address
70 * Bit 24-25: slotrank
71 *
72 * DEFAULT_MCHBAR + 0x4230 + 0x400 * X + 4 * Y: idle register
73 * Controls the idle time after issuing this DRAM command
74 * Bit 16-32: number of clock-cylces to idle
75 *
76 * DEFAULT_MCHBAR + 0x4284 + 0x400 * channel: execute command queue
77 * Starts to execute all queued commands
78 * Bit 0 : start DRAM command execution
79 * Bit 16-20: (number of queued commands - 1) * 4
80 */
81
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070082#define BASEFREQ 133
83#define tDLLK 512
Stefan Reinauer00636b02012-04-04 00:08:51 +020084
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070085#define IS_SANDY_CPU(x) ((x & 0xffff0) == 0x206a0)
86#define IS_SANDY_CPU_C(x) ((x & 0xf) == 4)
87#define IS_SANDY_CPU_D0(x) ((x & 0xf) == 5)
88#define IS_SANDY_CPU_D1(x) ((x & 0xf) == 6)
89#define IS_SANDY_CPU_D2(x) ((x & 0xf) == 7)
Stefan Reinauer00636b02012-04-04 00:08:51 +020090
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070091#define IS_IVY_CPU(x) ((x & 0xffff0) == 0x306a0)
92#define IS_IVY_CPU_C(x) ((x & 0xf) == 4)
93#define IS_IVY_CPU_K(x) ((x & 0xf) == 5)
94#define IS_IVY_CPU_D(x) ((x & 0xf) == 6)
95#define IS_IVY_CPU_E(x) ((x & 0xf) >= 8)
Stefan Reinauer00636b02012-04-04 00:08:51 +020096
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070097#define NUM_CHANNELS 2
98#define NUM_SLOTRANKS 4
99#define NUM_SLOTS 2
100#define NUM_LANES 8
Stefan Reinauer00636b02012-04-04 00:08:51 +0200101
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700102/* FIXME: Vendor BIOS uses 64 but our algorithms are less
103 performant and even 1 seems to be enough in practice. */
104#define NUM_PATTERNS 4
Stefan Reinauer00636b02012-04-04 00:08:51 +0200105
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700106typedef struct odtmap_st {
107 u16 rttwr;
108 u16 rttnom;
109} odtmap;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200110
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700111typedef struct dimm_info_st {
112 dimm_attr dimm[NUM_CHANNELS][NUM_SLOTS];
113} dimm_info;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200114
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700115struct ram_rank_timings {
116 /* Register 4024. One byte per slotrank. */
117 u8 val_4024;
118 /* Register 4028. One nibble per slotrank. */
119 u8 val_4028;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200120
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700121 int val_320c;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200122
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700123 struct ram_lane_timings {
124 /* lane register offset 0x10. */
125 u16 timA; /* bits 0 - 5, bits 16 - 18 */
126 u8 rising; /* bits 8 - 14 */
127 u8 falling; /* bits 20 - 26. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200128
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700129 /* lane register offset 0x20. */
130 int timC; /* bit 0 - 5, 19. */
131 u16 timB; /* bits 8 - 13, 15 - 17. */
132 } lanes[NUM_LANES];
133};
Stefan Reinauer00636b02012-04-04 00:08:51 +0200134
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700135struct ramctr_timing_st;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200136
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700137typedef struct ramctr_timing_st {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100138 u16 spd_crc[NUM_CHANNELS][NUM_SLOTS];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700139 int mobile;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200140
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700141 u16 cas_supported;
142 /* tLatencies are in units of ns, scaled by x256 */
143 u32 tCK;
144 u32 tAA;
145 u32 tWR;
146 u32 tRCD;
147 u32 tRRD;
148 u32 tRP;
149 u32 tRAS;
150 u32 tRFC;
151 u32 tWTR;
152 u32 tRTP;
153 u32 tFAW;
154 /* Latencies in terms of clock cycles
155 * They are saved separately as they are needed for DRAM MRS commands*/
156 u8 CAS; /* CAS read latency */
157 u8 CWL; /* CAS write latency */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200158
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700159 u32 tREFI;
160 u32 tMOD;
161 u32 tXSOffset;
162 u32 tWLO;
163 u32 tCKE;
164 u32 tXPDLL;
165 u32 tXP;
166 u32 tAONPD;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200167
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700168 u16 reg_5064b0; /* bits 0-11. */
Stefan Reinauer00636b02012-04-04 00:08:51 +0200169
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700170 u8 rankmap[NUM_CHANNELS];
171 int ref_card_offset[NUM_CHANNELS];
172 u32 mad_dimm[NUM_CHANNELS];
173 int channel_size_mb[NUM_CHANNELS];
174 u32 cmd_stretch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200175
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700176 int reg_c14_offset;
177 int reg_320c_range_threshold;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200178
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700179 int edge_offset[3];
180 int timC_offset[3];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200181
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700182 int extended_temperature_range;
183 int auto_self_refresh;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200184
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700185 int rank_mirror[NUM_CHANNELS][NUM_SLOTRANKS];
186
187 struct ram_rank_timings timings[NUM_CHANNELS][NUM_SLOTRANKS];
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100188
189 dimm_info info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700190} ramctr_timing;
191
192#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
193#define NORTHBRIDGE PCI_DEV(0, 0x0, 0)
194#define FOR_ALL_LANES for (lane = 0; lane < NUM_LANES; lane++)
195#define FOR_ALL_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++)
196#define FOR_ALL_POPULATED_RANKS for (slotrank = 0; slotrank < NUM_SLOTRANKS; slotrank++) if (ctrl->rankmap[channel] & (1 << slotrank))
197#define FOR_ALL_POPULATED_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) if (ctrl->rankmap[channel])
198#define MAX_EDGE_TIMING 71
199#define MAX_TIMC 127
200#define MAX_TIMB 511
201#define MAX_TIMA 127
202
Patrick Rudolph24a845b2016-03-25 18:19:47 +0100203#define MAKE_ERR ((channel<<16)|(slotrank<<8)|1)
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100204#define GET_ERR_CHANNEL(x) (x>>16)
Patrick Rudolph24a845b2016-03-25 18:19:47 +0100205
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700206static void program_timings(ramctr_timing * ctrl, int channel);
Patrick Rudolph266a1f72016-06-09 18:13:34 +0200207static unsigned int get_mmio_size(void);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700208
209static const char *ecc_decoder[] = {
Stefan Reinauer00636b02012-04-04 00:08:51 +0200210 "inactive",
211 "active on IO",
212 "disabled on IO",
213 "active"
214};
215
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700216static void wait_txt_clear(void)
217{
218 struct cpuid_result cp;
219
220 cp = cpuid_ext(0x1, 0x0);
221 /* Check if TXT is supported? */
222 if (!(cp.ecx & 0x40))
223 return;
224 /* Some TXT public bit. */
225 if (!(read32((void *)0xfed30010) & 1))
226 return;
227 /* Wait for TXT clear. */
228 while (!(read8((void *)0xfed40000) & (1 << 7))) ;
229}
230
231static void sfence(void)
232{
233 asm volatile ("sfence");
234}
235
Patrick Rudolph9b515682015-10-09 13:43:51 +0200236static void toggle_io_reset(void) {
237 /* toggle IO reset bit */
238 u32 r32 = read32(DEFAULT_MCHBAR + 0x5030);
239 write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20);
240 udelay(1);
241 write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20);
242 udelay(1);
243}
244
Stefan Reinauer00636b02012-04-04 00:08:51 +0200245/*
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100246 * Disable a channel in ramctr_timing.
247 */
248static void disable_channel(ramctr_timing *ctrl, int channel) {
249 ctrl->rankmap[channel] = 0;
250 memset(&ctrl->rank_mirror[channel][0], 0, sizeof(ctrl->rank_mirror[0]));
251 ctrl->channel_size_mb[channel] = 0;
252 ctrl->cmd_stretch[channel] = 0;
253 ctrl->mad_dimm[channel] = 0;
254 memset(&ctrl->timings[channel][0], 0, sizeof(ctrl->timings[0]));
255}
256
257/*
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100258 * Fill cbmem with information for SMBIOS type 17.
259 */
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100260static void fill_smbios17(ramctr_timing *ctrl)
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100261{
262 struct memory_info *mem_info;
263 int channel, slot;
264 struct dimm_info *dimm;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100265 uint16_t ddr_freq;
266 dimm_info *info = &ctrl->info;
267
268 ddr_freq = (1000 << 8) / ctrl->tCK;
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100269
270 /*
271 * Allocate CBMEM area for DIMM information used to populate SMBIOS
272 * table 17
273 */
274 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
275 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
276 if (!mem_info)
277 return;
278
279 memset(mem_info, 0, sizeof(*mem_info));
280
281 FOR_ALL_CHANNELS for(slot = 0; slot < NUM_SLOTS; slot++) {
282 dimm = &mem_info->dimm[mem_info->dimm_cnt];
283 if (info->dimm[channel][slot].size_mb) {
284 dimm->ddr_type = MEMORY_TYPE_DDR3;
285 dimm->ddr_frequency = ddr_freq;
286 dimm->dimm_size = info->dimm[channel][slot].size_mb;
287 dimm->channel_num = channel;
288 dimm->rank_per_dimm = info->dimm[channel][slot].ranks;
289 dimm->dimm_num = slot;
290 memcpy(dimm->module_part_number,
291 info->dimm[channel][slot].part_number, 16);
292 dimm->mod_id = info->dimm[channel][slot].manufacturer_id;
293 dimm->mod_type = info->dimm[channel][slot].dimm_type;
294 dimm->bus_width = info->dimm[channel][slot].width;
295 mem_info->dimm_cnt++;
296 }
297 }
298}
299
300/*
Stefan Reinauer00636b02012-04-04 00:08:51 +0200301 * Dump in the log memory controller configuration as read from the memory
302 * controller registers.
303 */
304static void report_memory_config(void)
305{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700306 u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200307 int i;
308
309 addr_decoder_common = MCHBAR32(0x5000);
310 addr_decode_ch[0] = MCHBAR32(0x5004);
311 addr_decode_ch[1] = MCHBAR32(0x5008);
312
313 printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700314 (MCHBAR32(0x5e04) * 13333 * 2 + 50) / 100);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200315 printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700316 addr_decoder_common & 3, (addr_decoder_common >> 2) & 3,
Stefan Reinauer00636b02012-04-04 00:08:51 +0200317 (addr_decoder_common >> 4) & 3);
318
319 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
320 u32 ch_conf = addr_decode_ch[i];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700321 printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i,
322 ch_conf);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200323 printk(BIOS_DEBUG, " ECC %s\n",
324 ecc_decoder[(ch_conf >> 24) & 3]);
325 printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
326 ((ch_conf >> 22) & 1) ? "on" : "off");
327 printk(BIOS_DEBUG, " rank interleave %s\n",
328 ((ch_conf >> 21) & 1) ? "on" : "off");
329 printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n",
330 ((ch_conf >> 0) & 0xff) * 256,
331 ((ch_conf >> 19) & 1) ? 16 : 8,
332 ((ch_conf >> 17) & 1) ? "dual" : "single",
333 ((ch_conf >> 16) & 1) ? "" : ", selected");
334 printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n",
335 ((ch_conf >> 8) & 0xff) * 256,
336 ((ch_conf >> 20) & 1) ? 16 : 8,
337 ((ch_conf >> 18) & 1) ? "dual" : "single",
338 ((ch_conf >> 16) & 1) ? ", selected" : "");
339 }
340}
341
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100342/*
343 * Return CRC16 match for all SPDs.
344 */
345static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
346{
347 int channel, slot, spd_slot;
348 int match = 1;
349
350 FOR_ALL_CHANNELS {
351 for (slot = 0; slot < NUM_SLOTS; slot++) {
352 spd_slot = 2 * channel + slot;
353 match &= ctrl->spd_crc[channel][slot] ==
354 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
355 }
356 }
357 return match;
358}
359
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700360void read_spd(spd_raw_data * spd, u8 addr)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200361{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700362 int j;
363 for (j = 0; j < 256; j++)
364 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
365}
366
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100367static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700368{
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100369 int dimms = 0, dimms_on_channel;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700370 int channel, slot, spd_slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100371 dimm_info *dimm = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700372
373 memset (ctrl->rankmap, 0, sizeof (ctrl->rankmap));
374
375 ctrl->extended_temperature_range = 1;
376 ctrl->auto_self_refresh = 1;
377
378 FOR_ALL_CHANNELS {
379 ctrl->channel_size_mb[channel] = 0;
380
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100381 dimms_on_channel = 0;
382 /* count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700383 for (slot = 0; slot < NUM_SLOTS; slot++) {
384 spd_slot = 2 * channel + slot;
385 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100386 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
387 dimms_on_channel++;
388 }
389
390 for (slot = 0; slot < NUM_SLOTS; slot++) {
391 spd_slot = 2 * channel + slot;
392 /* search for XMP profile */
393 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
394 spd[spd_slot],
395 DDR3_XMP_PROFILE_1);
396
397 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
398 printram("No valid XMP profile found.\n");
399 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
400 } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
401 printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
402 dimm->dimm[channel][slot].dimms_per_channel,
403 dimms_on_channel);
404 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
405 } else if (dimm->dimm[channel][slot].voltage != 1500) {
406 /* TODO: support other DDR3 voltage than 1500mV */
407 printram("XMP profile's requested %u mV is unsupported.\n",
408 dimm->dimm[channel][slot].voltage);
409 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
410 }
411
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100412 /* fill in CRC16 for MRC cache */
413 ctrl->spd_crc[channel][slot] =
414 spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data));
415
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700416 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
417 // set dimm invalid
418 dimm->dimm[channel][slot].ranks = 0;
419 dimm->dimm[channel][slot].size_mb = 0;
420 continue;
421 }
422
423 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
424 dimms++;
425 ctrl->rank_mirror[channel][slot * 2] = 0;
426 ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
427 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
428
429 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
430 ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
431
432 ctrl->rankmap[channel] |= ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100433 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n",
434 channel, ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700435 }
436 if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc)
437 && dimm->dimm[channel][0].reference_card <= 5 && dimm->dimm[channel][1].reference_card <= 5) {
438 const int ref_card_offset_table[6][6] = {
439 { 0, 0, 0, 0, 2, 2, },
440 { 0, 0, 0, 0, 2, 2, },
441 { 0, 0, 0, 0, 2, 2, },
442 { 0, 0, 0, 0, 1, 1, },
443 { 2, 2, 2, 1, 0, 0, },
444 { 2, 2, 2, 1, 0, 0, },
445 };
446 ctrl->ref_card_offset[channel] = ref_card_offset_table[dimm->dimm[channel][0].reference_card]
447 [dimm->dimm[channel][1].reference_card];
448 } else
449 ctrl->ref_card_offset[channel] = 0;
450 }
451
452 if (!dimms)
453 die("No DIMMs were found");
454}
455
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100456static void dram_find_common_params(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700457{
458 size_t valid_dimms;
459 int channel, slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100460 dimm_info *dimms = &ctrl->info;
461
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700462 ctrl->cas_supported = 0xff;
463 valid_dimms = 0;
464 FOR_ALL_CHANNELS for (slot = 0; slot < 2; slot++) {
465 const dimm_attr *dimm = &dimms->dimm[channel][slot];
466 if (dimm->dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3)
467 continue;
468 valid_dimms++;
469
470 /* Find all possible CAS combinations */
471 ctrl->cas_supported &= dimm->cas_supported;
472
473 /* Find the smallest common latencies supported by all DIMMs */
474 ctrl->tCK = MAX(ctrl->tCK, dimm->tCK);
475 ctrl->tAA = MAX(ctrl->tAA, dimm->tAA);
476 ctrl->tWR = MAX(ctrl->tWR, dimm->tWR);
477 ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD);
478 ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD);
479 ctrl->tRP = MAX(ctrl->tRP, dimm->tRP);
480 ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS);
481 ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC);
482 ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR);
483 ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP);
484 ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW);
485 }
486
487 if (!ctrl->cas_supported)
488 die("Unsupported DIMM combination. "
489 "DIMMS do not support common CAS latency");
490 if (!valid_dimms)
491 die("No valid DIMMs found");
492}
493
494static u8 get_CWL(u8 CAS)
495{
496 /* Get CWL based on CAS using the following rule:
497 * _________________________________________
498 * CAS: | 4T | 5T | 6T | 7T | 8T | 9T | 10T | 11T |
499 * CWL: | 5T | 5T | 5T | 6T | 6T | 7T | 7T | 8T |
500 */
501 static const u8 cas_cwl_map[] = { 5, 5, 5, 6, 6, 7, 7, 8 };
502 if (CAS > 11)
503 return 8;
504 return cas_cwl_map[CAS - 4];
505}
506
507/* Frequency multiplier. */
508static u32 get_FRQ(u32 tCK)
509{
510 u32 FRQ;
511 FRQ = 256000 / (tCK * BASEFREQ);
512 if (FRQ > 8)
513 return 8;
514 if (FRQ < 3)
515 return 3;
516 return FRQ;
517}
518
519static u32 get_REFI(u32 tCK)
520{
521 /* Get REFI based on MCU frequency using the following rule:
522 * _________________________________________
523 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
524 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 |
525 */
526 static const u32 frq_refi_map[] =
527 { 3120, 4160, 5200, 6240, 7280, 8320 };
528 return frq_refi_map[get_FRQ(tCK) - 3];
529}
530
531static u8 get_XSOffset(u32 tCK)
532{
533 /* Get XSOffset based on MCU frequency using the following rule:
534 * _________________________
535 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
536 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 |
537 */
538 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 };
539 return frq_xs_map[get_FRQ(tCK) - 3];
540}
541
542static u8 get_MOD(u32 tCK)
543{
544 /* Get MOD based on MCU frequency using the following rule:
545 * _____________________________
546 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
547 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 |
548 */
549 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 };
550 return frq_mod_map[get_FRQ(tCK) - 3];
551}
552
553static u8 get_WLO(u32 tCK)
554{
555 /* Get WLO based on MCU frequency using the following rule:
556 * _______________________
557 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
558 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 |
559 */
560 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 };
561 return frq_wlo_map[get_FRQ(tCK) - 3];
562}
563
564static u8 get_CKE(u32 tCK)
565{
566 /* Get CKE based on MCU frequency using the following rule:
567 * _______________________
568 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
569 * CKE : | 3 | 3 | 4 | 4 | 5 | 6 |
570 */
571 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 };
572 return frq_cke_map[get_FRQ(tCK) - 3];
573}
574
575static u8 get_XPDLL(u32 tCK)
576{
577 /* Get XPDLL based on MCU frequency using the following rule:
578 * _____________________________
579 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
580 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 |
581 */
582 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 };
583 return frq_xpdll_map[get_FRQ(tCK) - 3];
584}
585
586static u8 get_XP(u32 tCK)
587{
588 /* Get XP based on MCU frequency using the following rule:
589 * _______________________
590 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
591 * XP : | 3 | 4 | 4 | 5 | 6 | 7 |
592 */
593 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 };
594 return frq_xp_map[get_FRQ(tCK) - 3];
595}
596
597static u8 get_AONPD(u32 tCK)
598{
599 /* Get AONPD based on MCU frequency using the following rule:
600 * ________________________
601 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
602 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 |
603 */
604 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 };
605 return frq_aonpd_map[get_FRQ(tCK) - 3];
606}
607
608static u32 get_COMP2(u32 tCK)
609{
610 /* Get COMP2 based on MCU frequency using the following rule:
611 * ___________________________________________________________
612 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
613 * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C |
614 */
615 static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C,
616 0xC6369CC, 0xC42514C, 0xC21410C
617 };
618 return frq_comp2_map[get_FRQ(tCK) - 3];
619}
620
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100621static u32 get_XOVER_CLK(u8 rankmap)
622{
623 return rankmap << 24;
624}
625
626static u32 get_XOVER_CMD(u8 rankmap)
627{
628 u32 reg;
629
630 // enable xover cmd
631 reg = 0x4000;
632
633 // enable xover ctl
634 if (rankmap & 0x3)
635 reg |= 0x20000;
636
637 if (rankmap & 0xc)
638 reg |= 0x4000000;
639
640 return reg;
641}
642
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700643static void dram_timing(ramctr_timing * ctrl)
644{
645 u8 val;
646 u32 val32;
647
648 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
649 * we cap it if we have faster DIMMs.
650 * Then, align it to the closest JEDEC standard frequency */
651 if (ctrl->tCK <= TCK_1066MHZ) {
652 ctrl->tCK = TCK_1066MHZ;
653 ctrl->edge_offset[0] = 16;
654 ctrl->edge_offset[1] = 7;
655 ctrl->edge_offset[2] = 7;
656 ctrl->timC_offset[0] = 18;
657 ctrl->timC_offset[1] = 7;
658 ctrl->timC_offset[2] = 7;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700659 ctrl->reg_320c_range_threshold = 13;
660 } else if (ctrl->tCK <= TCK_933MHZ) {
661 ctrl->tCK = TCK_933MHZ;
662 ctrl->edge_offset[0] = 14;
663 ctrl->edge_offset[1] = 6;
664 ctrl->edge_offset[2] = 6;
665 ctrl->timC_offset[0] = 15;
666 ctrl->timC_offset[1] = 6;
667 ctrl->timC_offset[2] = 6;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700668 ctrl->reg_320c_range_threshold = 15;
669 } else if (ctrl->tCK <= TCK_800MHZ) {
670 ctrl->tCK = TCK_800MHZ;
671 ctrl->edge_offset[0] = 13;
672 ctrl->edge_offset[1] = 5;
673 ctrl->edge_offset[2] = 5;
674 ctrl->timC_offset[0] = 14;
675 ctrl->timC_offset[1] = 5;
676 ctrl->timC_offset[2] = 5;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700677 ctrl->reg_320c_range_threshold = 15;
678 } else if (ctrl->tCK <= TCK_666MHZ) {
679 ctrl->tCK = TCK_666MHZ;
680 ctrl->edge_offset[0] = 10;
681 ctrl->edge_offset[1] = 4;
682 ctrl->edge_offset[2] = 4;
683 ctrl->timC_offset[0] = 11;
684 ctrl->timC_offset[1] = 4;
685 ctrl->timC_offset[2] = 4;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700686 ctrl->reg_320c_range_threshold = 16;
687 } else if (ctrl->tCK <= TCK_533MHZ) {
688 ctrl->tCK = TCK_533MHZ;
689 ctrl->edge_offset[0] = 8;
690 ctrl->edge_offset[1] = 3;
691 ctrl->edge_offset[2] = 3;
692 ctrl->timC_offset[0] = 9;
693 ctrl->timC_offset[1] = 3;
694 ctrl->timC_offset[2] = 3;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700695 ctrl->reg_320c_range_threshold = 17;
696 } else {
697 ctrl->tCK = TCK_400MHZ;
698 ctrl->edge_offset[0] = 6;
699 ctrl->edge_offset[1] = 2;
700 ctrl->edge_offset[2] = 2;
701 ctrl->timC_offset[0] = 6;
702 ctrl->timC_offset[1] = 2;
703 ctrl->timC_offset[2] = 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700704 ctrl->reg_320c_range_threshold = 17;
705 }
706
Patrick Rudolphd4c53e32016-06-14 20:07:32 +0200707 /* Initial phase between CLK/CMD pins */
708 ctrl->reg_c14_offset = (256000 / ctrl->tCK) / 66;
709
Patrick Rudolphb7b1b282016-06-14 18:44:28 +0200710 /* DLL_CONFIG_MDLL_W_TIMER */
711 ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3;
712
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700713 val32 = (1000 << 8) / ctrl->tCK;
714 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
715
716 /* Find CAS and CWL latencies */
717 val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK;
718 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
719 /* Find lowest supported CAS latency that satisfies the minimum value */
720 while (!((ctrl->cas_supported >> (val - 4)) & 1)
721 && (ctrl->cas_supported >> (val - 4))) {
722 val++;
723 }
724 /* Is CAS supported */
725 if (!(ctrl->cas_supported & (1 << (val - 4))))
726 printk(BIOS_DEBUG, "CAS not supported\n");
727 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
728 ctrl->CAS = val;
729 ctrl->CWL = get_CWL(ctrl->CAS);
730 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
731
732 /* Find tRCD */
733 ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK;
734 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
735
736 ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK;
737 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
738
739 /* Find tRAS */
740 ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK;
741 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
742
743 /* Find tWR */
744 ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK;
745 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
746
747 /* Find tFAW */
748 ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK;
749 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
750
751 /* Find tRRD */
752 ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK;
753 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
754
755 /* Find tRTP */
756 ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK;
757 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
758
759 /* Find tWTR */
760 ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK;
761 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
762
763 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
764 ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK;
765 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
766
767 ctrl->tREFI = get_REFI(ctrl->tCK);
768 ctrl->tMOD = get_MOD(ctrl->tCK);
769 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
770 ctrl->tWLO = get_WLO(ctrl->tCK);
771 ctrl->tCKE = get_CKE(ctrl->tCK);
772 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
773 ctrl->tXP = get_XP(ctrl->tCK);
774 ctrl->tAONPD = get_AONPD(ctrl->tCK);
775}
776
777static void dram_freq(ramctr_timing * ctrl)
778{
779 if (ctrl->tCK > TCK_400MHZ) {
780 printk (BIOS_ERR, "DRAM frequency is under lowest supported frequency (400 MHz). Increasing to 400 MHz as last resort");
781 ctrl->tCK = TCK_400MHZ;
782 }
783 while (1) {
784 u8 val2;
785 u32 reg1 = 0;
786
787 /* Step 1 - Set target PCU frequency */
788
789 if (ctrl->tCK <= TCK_1066MHZ) {
790 ctrl->tCK = TCK_1066MHZ;
791 } else if (ctrl->tCK <= TCK_933MHZ) {
792 ctrl->tCK = TCK_933MHZ;
793 } else if (ctrl->tCK <= TCK_800MHZ) {
794 ctrl->tCK = TCK_800MHZ;
795 } else if (ctrl->tCK <= TCK_666MHZ) {
796 ctrl->tCK = TCK_666MHZ;
797 } else if (ctrl->tCK <= TCK_533MHZ) {
798 ctrl->tCK = TCK_533MHZ;
799 } else if (ctrl->tCK <= TCK_400MHZ) {
800 ctrl->tCK = TCK_400MHZ;
801 } else {
802 die ("No lock frequency found");
803 }
804
805 /* Frequency mulitplier. */
806 u32 FRQ = get_FRQ(ctrl->tCK);
807
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100808 /* The PLL will never lock if the required frequency is
809 * already set. Exit early to prevent a system hang.
810 */
811 reg1 = MCHBAR32(0x5e04);
812 val2 = (u8) reg1;
813 if (val2 == FRQ) {
814 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
815 (1000 << 8) / ctrl->tCK);
816 return;
817 }
818
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700819 /* Step 2 - Select frequency in the MCU */
820 reg1 = FRQ;
821 reg1 |= 0x80000000; // set running bit
822 MCHBAR32(0x5e00) = reg1;
823 while (reg1 & 0x80000000) {
824 printk(BIOS_DEBUG, " PLL busy...");
825 reg1 = MCHBAR32(0x5e00);
826 }
827 printk(BIOS_DEBUG, "done\n");
828
829 /* Step 3 - Verify lock frequency */
830 reg1 = MCHBAR32(0x5e04);
831 val2 = (u8) reg1;
832 if (val2 >= FRQ) {
833 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
834 (1000 << 8) / ctrl->tCK);
835 return;
836 }
837 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
838 ctrl->tCK++;
839 }
840}
841
842static void dram_xover(ramctr_timing * ctrl)
843{
844 u32 reg;
845 int channel;
846
847 FOR_ALL_CHANNELS {
848 // enable xover clk
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100849 reg = get_XOVER_CLK(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100850 printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
851 reg);
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100852 MCHBAR32(channel * 0x100 + 0xc14) = reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700853
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100854 // enable xover ctl & xover cmd
855 reg = get_XOVER_CMD(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100856 printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
857 reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700858 MCHBAR32(0x100 * channel + 0x320c) = reg;
859 }
860}
861
862static void dram_timing_regs(ramctr_timing * ctrl)
863{
864 u32 reg, addr, val32, cpu, stretch;
865 struct cpuid_result cpures;
866 int channel;
867
868 FOR_ALL_CHANNELS {
869 // DBP
870 reg = 0;
871 reg |= ctrl->tRCD;
872 reg |= (ctrl->tRP << 4);
873 reg |= (ctrl->CAS << 8);
874 reg |= (ctrl->CWL << 12);
875 reg |= (ctrl->tRAS << 16);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100876 printram("DBP [%x] = %x\n", 0x400 * channel + 0x4000, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700877 MCHBAR32(0x400 * channel + 0x4000) = reg;
878
879 // RAP
880 reg = 0;
881 reg |= ctrl->tRRD;
882 reg |= (ctrl->tRTP << 4);
883 reg |= (ctrl->tCKE << 8);
884 reg |= (ctrl->tWTR << 12);
885 reg |= (ctrl->tFAW << 16);
886 reg |= (ctrl->tWR << 24);
887 reg |= (3 << 30);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100888 printram("RAP [%x] = %x\n", 0x400 * channel + 0x4004, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700889 MCHBAR32(0x400 * channel + 0x4004) = reg;
890
891 // OTHP
892 addr = 0x400 * channel + 0x400c;
893 reg = 0;
894 reg |= ctrl->tXPDLL;
895 reg |= (ctrl->tXP << 5);
896 reg |= (ctrl->tAONPD << 8);
897 reg |= 0xa0000;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100898 printram("OTHP [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700899 MCHBAR32(addr) = reg;
900
901 MCHBAR32(0x400 * channel + 0x4014) = 0;
902
903 MCHBAR32(addr) |= 0x00020000;
904
905 // ODT stretch
906 reg = 0;
907
908 cpures = cpuid(0);
909 cpu = cpures.eax;
910 if (IS_IVY_CPU(cpu)
911 || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) {
912 stretch = 2;
913 addr = 0x400 * channel + 0x400c;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100914 printram("ODT stretch [%x] = %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700915 0x400 * channel + 0x400c, reg);
916 reg = MCHBAR32(addr);
917
918 if (((ctrl->rankmap[channel] & 3) == 0)
919 || (ctrl->rankmap[channel] & 0xc) == 0) {
920
921 // Rank 0 - operate on rank 2
922 reg = (reg & ~0xc0000) | (stretch << 18);
923
924 // Rank 2 - operate on rank 0
925 reg = (reg & ~0x30000) | (stretch << 16);
926
Patrick Rudolpha649a542016-01-17 18:32:06 +0100927 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700928 MCHBAR32(addr) = reg;
929 }
930
931 } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) {
932 stretch = 3;
933 addr = 0x400 * channel + 0x401c;
934 reg = MCHBAR32(addr);
935
936 if (((ctrl->rankmap[channel] & 3) == 0)
937 || (ctrl->rankmap[channel] & 0xc) == 0) {
938
939 // Rank 0 - operate on rank 2
940 reg = (reg & ~0x3000) | (stretch << 12);
941
942 // Rank 2 - operate on rank 0
943 reg = (reg & ~0xc00) | (stretch << 10);
944
Patrick Rudolpha649a542016-01-17 18:32:06 +0100945 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700946 MCHBAR32(addr) = reg;
947 }
948 } else {
949 stretch = 0;
950 }
951
952 // REFI
953 reg = 0;
954 val32 = ctrl->tREFI;
955 reg = (reg & ~0xffff) | val32;
956 val32 = ctrl->tRFC;
957 reg = (reg & ~0x1ff0000) | (val32 << 16);
958 val32 = (u32) (ctrl->tREFI * 9) / 1024;
959 reg = (reg & ~0xfe000000) | (val32 << 25);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100960 printram("REFI [%x] = %x\n", 0x400 * channel + 0x4298,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700961 reg);
962 MCHBAR32(0x400 * channel + 0x4298) = reg;
963
964 MCHBAR32(0x400 * channel + 0x4294) |= 0xff;
965
966 // SRFTP
967 reg = 0;
968 val32 = tDLLK;
969 reg = (reg & ~0xfff) | val32;
970 val32 = ctrl->tXSOffset;
971 reg = (reg & ~0xf000) | (val32 << 12);
972 val32 = tDLLK - ctrl->tXSOffset;
973 reg = (reg & ~0x3ff0000) | (val32 << 16);
974 val32 = ctrl->tMOD - 8;
975 reg = (reg & ~0xf0000000) | (val32 << 28);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100976 printram("SRFTP [%x] = %x\n", 0x400 * channel + 0x42a4,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700977 reg);
978 MCHBAR32(0x400 * channel + 0x42a4) = reg;
979 }
980}
981
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100982static void dram_dimm_mapping(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700983{
984 u32 reg, val32;
985 int channel;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100986 dimm_info *info = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700987
988 FOR_ALL_CHANNELS {
989 dimm_attr *dimmA = 0;
990 dimm_attr *dimmB = 0;
991 reg = 0;
992 val32 = 0;
993 if (info->dimm[channel][0].size_mb >=
994 info->dimm[channel][1].size_mb) {
995 // dimm 0 is bigger, set it to dimmA
996 dimmA = &info->dimm[channel][0];
997 dimmB = &info->dimm[channel][1];
998 reg |= (0 << 16);
999 } else {
1000 // dimm 1 is bigger, set it to dimmA
1001 dimmA = &info->dimm[channel][1];
1002 dimmB = &info->dimm[channel][0];
1003 reg |= (1 << 16);
1004 }
1005 // dimmA
1006 if (dimmA && (dimmA->ranks > 0)) {
1007 val32 = dimmA->size_mb / 256;
1008 reg = (reg & ~0xff) | val32;
1009 val32 = dimmA->ranks - 1;
1010 reg = (reg & ~0x20000) | (val32 << 17);
1011 val32 = (dimmA->width / 8) - 1;
1012 reg = (reg & ~0x80000) | (val32 << 19);
1013 }
1014 // dimmB
1015 if (dimmB && (dimmB->ranks > 0)) {
1016 val32 = dimmB->size_mb / 256;
1017 reg = (reg & ~0xff00) | (val32 << 8);
1018 val32 = dimmB->ranks - 1;
1019 reg = (reg & ~0x40000) | (val32 << 18);
1020 val32 = (dimmB->width / 8) - 1;
1021 reg = (reg & ~0x100000) | (val32 << 20);
1022 }
1023 reg = (reg & ~0x200000) | (1 << 21); // rank interleave
1024 reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave
1025
1026 // Save MAD-DIMM register
1027 if ((dimmA && (dimmA->ranks > 0))
1028 || (dimmB && (dimmB->ranks > 0))) {
1029 ctrl->mad_dimm[channel] = reg;
1030 } else {
1031 ctrl->mad_dimm[channel] = 0;
1032 }
1033 }
1034}
1035
1036static void dram_dimm_set_mapping(ramctr_timing * ctrl)
1037{
1038 int channel;
1039 FOR_ALL_CHANNELS {
1040 MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
1041 }
1042}
1043
1044static void dram_zones(ramctr_timing * ctrl, int training)
1045{
1046 u32 reg, ch0size, ch1size;
1047 u8 val;
1048 reg = 0;
1049 val = 0;
1050 if (training) {
1051 ch0size = ctrl->channel_size_mb[0] ? 256 : 0;
1052 ch1size = ctrl->channel_size_mb[1] ? 256 : 0;
1053 } else {
1054 ch0size = ctrl->channel_size_mb[0];
1055 ch1size = ctrl->channel_size_mb[1];
1056 }
1057
1058 if (ch0size >= ch1size) {
1059 reg = MCHBAR32(0x5014);
1060 val = ch1size / 256;
1061 reg = (reg & ~0xff000000) | val << 24;
1062 reg = (reg & ~0xff0000) | (2 * val) << 16;
1063 MCHBAR32(0x5014) = reg;
1064 MCHBAR32(0x5000) = 0x24;
1065 } else {
1066 reg = MCHBAR32(0x5014);
1067 val = ch0size / 256;
1068 reg = (reg & ~0xff000000) | val << 24;
1069 reg = (reg & ~0xff0000) | (2 * val) << 16;
1070 MCHBAR32(0x5014) = reg;
1071 MCHBAR32(0x5000) = 0x21;
1072 }
1073}
1074
1075static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
1076{
1077 u32 reg, val, reclaim;
1078 u32 tom, gfxstolen, gttsize;
1079 size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase,
1080 tsegbase, mestolenbase;
1081 size_t tsegbasedelta, remapbase, remaplimit;
1082 uint16_t ggc;
1083
Patrick Rudolph266a1f72016-06-09 18:13:34 +02001084 mmiosize = get_mmio_size();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001085
1086 ggc = pci_read_config16(NORTHBRIDGE, GGC);
1087 if (!(ggc & 2)) {
1088 gfxstolen = ((ggc >> 3) & 0x1f) * 32;
1089 gttsize = ((ggc >> 8) & 0x3);
1090 } else {
1091 gfxstolen = 0;
1092 gttsize = 0;
1093 }
1094
1095 tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
1096
1097 tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
1098
1099 mestolenbase = tom - me_uma_size;
1100
1101 toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
1102 tom - me_uma_size);
1103 gfxstolenbase = toludbase - gfxstolen;
1104 gttbase = gfxstolenbase - gttsize;
1105
1106 tsegbase = gttbase - tsegsize;
1107
1108 // Round tsegbase down to nearest address aligned to tsegsize
1109 tsegbasedelta = tsegbase & (tsegsize - 1);
1110 tsegbase &= ~(tsegsize - 1);
1111
1112 gttbase -= tsegbasedelta;
1113 gfxstolenbase -= tsegbasedelta;
1114 toludbase -= tsegbasedelta;
1115
1116 // Test if it is possible to reclaim a hole in the ram addressing
1117 if (tom - me_uma_size > toludbase) {
1118 // Reclaim is possible
1119 reclaim = 1;
1120 remapbase = MAX(4096, tom - me_uma_size);
1121 remaplimit =
1122 remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1;
1123 touudbase = remaplimit + 1;
1124 } else {
1125 // Reclaim not possible
1126 reclaim = 0;
1127 touudbase = tom - me_uma_size;
1128 }
1129
1130 // Update memory map in pci-e configuration space
Patrick Rudolpha649a542016-01-17 18:32:06 +01001131 printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001132
1133 // TOM (top of memory)
1134 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0);
1135 val = tom & 0xfff;
1136 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001137 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001138 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg);
1139
1140 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4);
1141 val = tom & 0xfffff000;
1142 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001143 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001144 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg);
1145
1146 // TOLUD (top of low used dram)
1147 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
1148 val = toludbase & 0xfff;
1149 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001150 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xbc, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001151 pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg);
1152
1153 // TOUUD LSB (top of upper usable dram)
1154 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
1155 val = touudbase & 0xfff;
1156 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001157 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001158 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg);
1159
1160 // TOUUD MSB
1161 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
1162 val = touudbase & 0xfffff000;
1163 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001164 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xac, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001165 pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg);
1166
1167 if (reclaim) {
1168 // REMAP BASE
1169 pcie_write_config32(PCI_DEV(0, 0, 0), 0x90, remapbase << 20);
1170 pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, remapbase >> 12);
1171
1172 // REMAP LIMIT
1173 pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
1174 pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
1175 }
1176 // TSEG
1177 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
1178 val = tsegbase & 0xfff;
1179 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001180 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001181 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg);
1182
1183 // GFX stolen memory
1184 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0);
1185 val = gfxstolenbase & 0xfff;
1186 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001187 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001188 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg);
1189
1190 // GTT stolen memory
1191 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4);
1192 val = gttbase & 0xfff;
1193 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001194 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001195 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
1196
1197 if (me_uma_size) {
1198 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
1199 val = (0x80000 - me_uma_size) & 0xfffff000;
1200 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001201 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x7c, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001202 pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg);
1203
1204 // ME base
1205 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70);
1206 val = mestolenbase & 0xfff;
1207 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001208 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x70, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001209 pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg);
1210
1211 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74);
1212 val = mestolenbase & 0xfffff000;
1213 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001214 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x74, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001215 pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg);
1216
1217 // ME mask
1218 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78);
1219 val = (0x80000 - me_uma_size) & 0xfff;
1220 reg = (reg & ~0xfff00000) | (val << 20);
1221 reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem
1222
1223 reg = (reg & ~0x800) | (1 << 11); // set ME memory enable
Patrick Rudolpha649a542016-01-17 18:32:06 +01001224 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x78, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001225 pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg);
1226 }
1227}
1228
1229static void dram_ioregs(ramctr_timing * ctrl)
1230{
1231 u32 reg, comp2;
1232
1233 int channel;
1234
1235 // IO clock
1236 FOR_ALL_CHANNELS {
1237 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
1238 }
1239
1240 // IO command
1241 FOR_ALL_CHANNELS {
1242 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
1243 }
1244
1245 // IO control
1246 FOR_ALL_POPULATED_CHANNELS {
1247 program_timings(ctrl, channel);
1248 }
1249
1250 // Rcomp
Patrick Rudolpha649a542016-01-17 18:32:06 +01001251 printram("RCOMP...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001252 reg = 0;
1253 while (reg == 0) {
1254 reg = MCHBAR32(0x5084) & 0x10000;
1255 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001256 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001257
1258 // Set comp2
1259 comp2 = get_COMP2(ctrl->tCK);
1260 MCHBAR32(0x3714) = comp2;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001261 printram("COMP2 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001262
1263 // Set comp1
1264 FOR_ALL_POPULATED_CHANNELS {
1265 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
1266 reg = (reg & ~0xe00) | (1 << 9); //odt
1267 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
1268 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
1269 MCHBAR32(0x1810 + channel * 0x100) = reg;
1270 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001271 printram("COMP1 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001272
Patrick Rudolpha649a542016-01-17 18:32:06 +01001273 printram("FORCE RCOMP and wait 20us...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001274 MCHBAR32(0x5f08) |= 0x100;
1275 udelay(20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001276 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001277}
1278
1279static void wait_428c(int channel)
1280{
1281 while (1) {
1282 if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
1283 return;
1284 }
1285}
1286
1287static void write_reset(ramctr_timing * ctrl)
1288{
1289 int channel, slotrank;
1290
1291 /* choose a populated channel. */
1292 channel = (ctrl->rankmap[0]) ? 0 : 1;
1293
1294 wait_428c(channel);
1295
1296 /* choose a populated rank. */
1297 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
1298
Patrick Rudolph371d2912015-10-09 13:33:25 +02001299 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001300 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1301 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01);
1302
1303 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1304 (slotrank << 24) | 0x60000);
1305
1306 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1307
1308 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001);
1309 wait_428c(channel);
1310}
1311
1312static void dram_jedecreset(ramctr_timing * ctrl)
1313{
1314 u32 reg, addr;
1315 int channel;
1316
1317 while (!(MCHBAR32(0x5084) & 0x10000)) ;
1318 do {
1319 reg = MCHBAR32(0x428c);
1320 } while ((reg & 0x14) == 0);
1321
1322 // Set state of memory controller
1323 reg = 0x112;
1324 MCHBAR32(0x5030) = reg;
1325 MCHBAR32(0x4ea0) = 0;
1326 reg |= 2; //ddr reset
1327 MCHBAR32(0x5030) = reg;
1328
1329 // Assert dimm reset signal
1330 reg = MCHBAR32(0x5030);
1331 reg &= ~0x2;
1332 MCHBAR32(0x5030) = reg;
1333
1334 // Wait 200us
1335 udelay(200);
1336
1337 // Deassert dimm reset signal
1338 MCHBAR32(0x5030) |= 2;
1339
1340 // Wait 500us
1341 udelay(500);
1342
1343 // Enable DCLK
1344 MCHBAR32(0x5030) |= 4;
1345
1346 // XXX Wait 20ns
1347 udelay(1);
1348
1349 FOR_ALL_CHANNELS {
1350 // Set valid rank CKE
1351 reg = 0;
1352 reg = (reg & ~0xf) | ctrl->rankmap[channel];
1353 addr = 0x400 * channel + 0x42a0;
1354 MCHBAR32(addr) = reg;
1355
1356 // Wait 10ns for ranks to settle
1357 //udelay(0.01);
1358
1359 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
1360 MCHBAR32(addr) = reg;
1361
1362 // Write reset using a NOP
1363 write_reset(ctrl);
1364 }
1365}
1366
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001367static odtmap get_ODT(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001368{
1369 /* Get ODT based on rankmap: */
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001370 int dimms_per_ch = (ctrl->rankmap[channel] & 1)
1371 + ((ctrl->rankmap[channel] >> 2) & 1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001372
1373 if (dimms_per_ch == 1) {
1374 return (const odtmap){60, 60};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001375 } else {
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001376 return (const odtmap){120, 30};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001377 }
1378}
1379
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001380static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001381 int reg, u32 val)
1382{
1383 wait_428c(channel);
1384
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001385 if (ctrl->rank_mirror[channel][slotrank]) {
1386 /* DDR3 Rank1 Address mirror
1387 * swap the following pins:
1388 * A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 */
1389 reg = ((reg >> 1) & 1) | ((reg << 1) & 2);
1390 val = (val & ~0x1f8) | ((val >> 1) & 0xa8)
1391 | ((val & 0xa8) << 1);
1392 }
1393
Patrick Rudolph371d2912015-10-09 13:33:25 +02001394 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001395 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000);
1396 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
1397 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1398 (slotrank << 24) | (reg << 20) | val | 0x60000);
1399 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1400
Patrick Rudolph371d2912015-10-09 13:33:25 +02001401 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001402 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000);
1403 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001);
1404 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
1405 (slotrank << 24) | (reg << 20) | val | 0x60000);
1406 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1407
Patrick Rudolph371d2912015-10-09 13:33:25 +02001408 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001409 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000);
1410 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1411 0x1001 | (ctrl->tMOD << 16));
1412 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1413 (slotrank << 24) | (reg << 20) | val | 0x60000);
1414 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1415 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
1416}
1417
1418static u32 make_mr0(ramctr_timing * ctrl, u8 rank)
1419{
1420 u16 mr0reg, mch_cas, mch_wr;
1421 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 +02001422
1423 /* DLL Reset - self clearing - set after CLK frequency has been changed */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001424 mr0reg = 0x100;
1425
1426 // Convert CAS to MCH register friendly
1427 if (ctrl->CAS < 12) {
1428 mch_cas = (u16) ((ctrl->CAS - 4) << 1);
1429 } else {
1430 mch_cas = (u16) (ctrl->CAS - 12);
1431 mch_cas = ((mch_cas << 1) | 0x1);
1432 }
1433
1434 // Convert tWR to MCH register friendly
1435 mch_wr = mch_wr_t[ctrl->tWR - 5];
1436
1437 mr0reg = (mr0reg & ~0x4) | (mch_cas & 0x1);
1438 mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3);
1439 mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001440
1441 // Precharge PD - Fast (desktop) 0x1 or slow (mobile) 0x0 - mostly power-saving feature
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001442 mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12);
1443 return mr0reg;
1444}
1445
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001446static void dram_mr0(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001447{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001448 write_mrreg(ctrl, channel, rank, 0,
1449 make_mr0(ctrl, rank));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001450}
1451
1452static u32 encode_odt(u32 odt)
1453{
1454 switch (odt) {
1455 case 30:
1456 return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4
1457 case 60:
1458 return (1 << 2); // RZQ/4
1459 case 120:
1460 return (1 << 6); // RZQ/2
1461 default:
1462 case 0:
1463 return 0;
1464 }
1465}
1466
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001467static u32 make_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001468{
1469 odtmap odt;
1470 u32 mr1reg;
1471
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001472 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001473 mr1reg = 0x2;
1474
1475 mr1reg |= encode_odt(odt.rttnom);
1476
1477 return mr1reg;
1478}
1479
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001480static void dram_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001481{
1482 u16 mr1reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001483
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001484 mr1reg = make_mr1(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001485
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001486 write_mrreg(ctrl, channel, rank, 1, mr1reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001487}
1488
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001489static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001490{
1491 u16 pasr, cwl, mr2reg;
1492 odtmap odt;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001493 int srt;
1494
1495 pasr = 0;
1496 cwl = ctrl->CWL - 5;
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001497 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001498
1499 srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh;
1500
1501 mr2reg = 0;
1502 mr2reg = (mr2reg & ~0x7) | pasr;
1503 mr2reg = (mr2reg & ~0x38) | (cwl << 3);
1504 mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6);
1505 mr2reg = (mr2reg & ~0x80) | (srt << 7);
1506 mr2reg |= (odt.rttwr / 60) << 9;
1507
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001508 write_mrreg(ctrl, channel, rank, 2, mr2reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001509}
1510
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001511static void dram_mr3(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001512{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001513 write_mrreg(ctrl, channel, rank, 3, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001514}
1515
1516static void dram_mrscommands(ramctr_timing * ctrl)
1517{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001518 u8 slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001519 u32 reg, addr;
1520 int channel;
1521
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001522 FOR_ALL_POPULATED_CHANNELS {
1523 FOR_ALL_POPULATED_RANKS {
1524 // MR2
1525 dram_mr2(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001526
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001527 // MR3
1528 dram_mr3(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001529
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001530 // MR1
1531 dram_mr1(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001532
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001533 // MR0
1534 dram_mr0(ctrl, slotrank, channel);
1535 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001536 }
1537
Patrick Rudolph371d2912015-10-09 13:33:25 +02001538 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001539 write32(DEFAULT_MCHBAR + 0x4e20, 0x7);
1540 write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001);
1541 write32(DEFAULT_MCHBAR + 0x4e00, 0x60002);
1542 write32(DEFAULT_MCHBAR + 0x4e10, 0);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001543
1544 /* DRAM command ZQCL */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001545 write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003);
1546 write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001);
1547 write32(DEFAULT_MCHBAR + 0x4e04, 0x60400);
1548 write32(DEFAULT_MCHBAR + 0x4e14, 0x288);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001549
1550 /* execute command queue on all channels ? */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001551 write32(DEFAULT_MCHBAR + 0x4e84, 0x40004);
1552
1553 // Drain
1554 FOR_ALL_CHANNELS {
1555 // Wait for ref drained
1556 wait_428c(channel);
1557 }
1558
1559 // Refresh enable
1560 MCHBAR32(0x5030) |= 8;
1561
1562 FOR_ALL_POPULATED_CHANNELS {
1563 addr = 0x400 * channel + 0x4020;
1564 reg = MCHBAR32(addr);
1565 reg &= ~0x200000;
1566 MCHBAR32(addr) = reg;
1567
1568 wait_428c(channel);
1569
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001570 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001571
1572 // Drain
1573 wait_428c(channel);
1574
Patrick Rudolph371d2912015-10-09 13:33:25 +02001575 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001576 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1577 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
1578 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001579 (slotrank << 24) | 0x60000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001580 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
1581 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1);
1582
1583 // Drain
1584 wait_428c(channel);
1585 }
1586}
1587
1588const u32 lane_registers[] = {
1589 0x0000, 0x0200, 0x0400, 0x0600,
1590 0x1000, 0x1200, 0x1400, 0x1600,
1591 0x0800
1592};
1593
1594static void program_timings(ramctr_timing * ctrl, int channel)
1595{
1596 u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028;
1597 int lane;
1598 int slotrank, slot;
1599 int full_shift = 0;
1600 u16 slot320c[NUM_SLOTS];
1601
1602 FOR_ALL_POPULATED_RANKS {
1603 if (full_shift < -ctrl->timings[channel][slotrank].val_320c)
1604 full_shift = -ctrl->timings[channel][slotrank].val_320c;
1605 }
1606
1607 for (slot = 0; slot < NUM_SLOTS; slot++)
1608 switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) {
1609 case 0:
1610 default:
1611 slot320c[slot] = 0x7f;
1612 break;
1613 case 1:
1614 slot320c[slot] =
1615 ctrl->timings[channel][2 * slot + 0].val_320c +
1616 full_shift;
1617 break;
1618 case 2:
1619 slot320c[slot] =
1620 ctrl->timings[channel][2 * slot + 1].val_320c +
1621 full_shift;
1622 break;
1623 case 3:
1624 slot320c[slot] =
1625 (ctrl->timings[channel][2 * slot].val_320c +
1626 ctrl->timings[channel][2 * slot +
1627 1].val_320c) / 2 +
1628 full_shift;
1629 break;
1630 }
1631
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001632 /* enable CMD XOVER */
1633 reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001634 reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
1635 reg32 |= (slot320c[1] & 0x7f) << 18;
1636 reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
1637
1638 MCHBAR32(0x320c + 0x100 * channel) = reg32;
1639
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001640 /* enable CLK XOVER */
1641 reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001642 reg_c18 = 0;
1643
1644 FOR_ALL_POPULATED_RANKS {
1645 int shift =
1646 ctrl->timings[channel][slotrank].val_320c + full_shift;
1647 int offset_val_c14;
1648 if (shift < 0)
1649 shift = 0;
1650 offset_val_c14 = ctrl->reg_c14_offset + shift;
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001651 /* set CLK phase shift */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001652 reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
1653 reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
1654 }
1655
1656 MCHBAR32(0xc14 + channel * 0x100) = reg_c14;
1657 MCHBAR32(0xc18 + channel * 0x100) = reg_c18;
1658
1659 reg_4028 = MCHBAR32(0x4028 + 0x400 * channel);
1660 reg_4028 &= 0xffff0000;
1661
1662 reg_4024 = 0;
1663
1664 FOR_ALL_POPULATED_RANKS {
1665 int post_timA_min_high = 7, post_timA_max_high = 0;
1666 int pre_timA_min_high = 7, pre_timA_max_high = 0;
1667 int shift_402x = 0;
1668 int shift =
1669 ctrl->timings[channel][slotrank].val_320c + full_shift;
1670
1671 if (shift < 0)
1672 shift = 0;
1673
1674 FOR_ALL_LANES {
1675 if (post_timA_min_high >
1676 ((ctrl->timings[channel][slotrank].lanes[lane].
1677 timA + shift) >> 6))
1678 post_timA_min_high =
1679 ((ctrl->timings[channel][slotrank].
1680 lanes[lane].timA + shift) >> 6);
1681 if (pre_timA_min_high >
1682 (ctrl->timings[channel][slotrank].lanes[lane].
1683 timA >> 6))
1684 pre_timA_min_high =
1685 (ctrl->timings[channel][slotrank].
1686 lanes[lane].timA >> 6);
1687 if (post_timA_max_high <
1688 ((ctrl->timings[channel][slotrank].lanes[lane].
1689 timA + shift) >> 6))
1690 post_timA_max_high =
1691 ((ctrl->timings[channel][slotrank].
1692 lanes[lane].timA + shift) >> 6);
1693 if (pre_timA_max_high <
1694 (ctrl->timings[channel][slotrank].lanes[lane].
1695 timA >> 6))
1696 pre_timA_max_high =
1697 (ctrl->timings[channel][slotrank].
1698 lanes[lane].timA >> 6);
1699 }
1700
1701 if (pre_timA_max_high - pre_timA_min_high <
1702 post_timA_max_high - post_timA_min_high)
1703 shift_402x = +1;
1704 else if (pre_timA_max_high - pre_timA_min_high >
1705 post_timA_max_high - post_timA_min_high)
1706 shift_402x = -1;
1707
1708 reg_4028 |=
1709 (ctrl->timings[channel][slotrank].val_4028 + shift_402x -
1710 post_timA_min_high) << (4 * slotrank);
1711 reg_4024 |=
1712 (ctrl->timings[channel][slotrank].val_4024 +
1713 shift_402x) << (8 * slotrank);
1714
1715 FOR_ALL_LANES {
1716 MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel +
1717 4 * slotrank)
1718 =
1719 (((ctrl->timings[channel][slotrank].lanes[lane].
1720 timA + shift) & 0x3f)
1721 |
1722 ((ctrl->timings[channel][slotrank].lanes[lane].
1723 rising + shift) << 8)
1724 |
1725 (((ctrl->timings[channel][slotrank].lanes[lane].
1726 timA + shift -
1727 (post_timA_min_high << 6)) & 0x1c0) << 10)
Patrick Rudolph0188b132016-02-10 19:16:34 +01001728 | ((ctrl->timings[channel][slotrank].lanes[lane].
1729 falling + shift) << 20));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001730
1731 MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel +
1732 4 * slotrank)
1733 =
1734 (((ctrl->timings[channel][slotrank].lanes[lane].
1735 timC + shift) & 0x3f)
1736 |
1737 (((ctrl->timings[channel][slotrank].lanes[lane].
1738 timB + shift) & 0x3f) << 8)
1739 |
1740 (((ctrl->timings[channel][slotrank].lanes[lane].
1741 timB + shift) & 0x1c0) << 9)
1742 |
1743 (((ctrl->timings[channel][slotrank].lanes[lane].
1744 timC + shift) & 0x40) << 13));
1745 }
1746 }
1747 MCHBAR32(0x4024 + 0x400 * channel) = reg_4024;
1748 MCHBAR32(0x4028 + 0x400 * channel) = reg_4028;
1749}
1750
1751static void test_timA(ramctr_timing * ctrl, int channel, int slotrank)
1752{
1753 wait_428c(channel);
1754
Patrick Rudolph371d2912015-10-09 13:33:25 +02001755 /* DRAM command MRS
1756 * write MR3 MPR enable
1757 * in this mode only RD and RDA are allowed
1758 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001759 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
1760 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1761 (0xc01 | (ctrl->tMOD << 16)));
1762 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1763 (slotrank << 24) | 0x360004);
1764 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1765
Patrick Rudolph371d2912015-10-09 13:33:25 +02001766 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001767 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
1768 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01);
1769 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24));
1770 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1771
Patrick Rudolph371d2912015-10-09 13:33:25 +02001772 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001773 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
1774 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1775 0x100f | ((ctrl->CAS + 36) << 16));
1776 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1777 (slotrank << 24) | 0x60000);
1778 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1779
Patrick Rudolph371d2912015-10-09 13:33:25 +02001780 /* DRAM command MRS
1781 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001782 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
1783 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
1784 (0xc01 | (ctrl->tMOD << 16)));
1785 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
1786 (slotrank << 24) | 0x360000);
1787 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
1788
1789 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
1790
1791 wait_428c(channel);
1792}
1793
1794static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank,
1795 int lane)
1796{
1797 u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA;
1798 return ((read32
1799 (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 +
1800 ((timA / 32) & 1) * 4)
1801 >> (timA % 32)) & 1);
1802}
1803
1804struct run {
1805 int middle;
1806 int end;
1807 int start;
1808 int all;
1809 int length;
1810};
1811
1812static struct run get_longest_zero_run(int *seq, int sz)
1813{
1814 int i, ls;
1815 int bl = 0, bs = 0;
1816 struct run ret;
1817
1818 ls = 0;
1819 for (i = 0; i < 2 * sz; i++)
1820 if (seq[i % sz]) {
1821 if (i - ls > bl) {
1822 bl = i - ls;
1823 bs = ls;
1824 }
1825 ls = i + 1;
1826 }
1827 if (bl == 0) {
1828 ret.middle = sz / 2;
1829 ret.start = 0;
1830 ret.end = sz;
1831 ret.all = 1;
1832 return ret;
1833 }
1834
1835 ret.start = bs % sz;
1836 ret.end = (bs + bl - 1) % sz;
1837 ret.middle = (bs + (bl - 1) / 2) % sz;
1838 ret.length = bl;
1839 ret.all = 0;
1840
1841 return ret;
1842}
1843
1844static void discover_timA_coarse(ramctr_timing * ctrl, int channel,
1845 int slotrank, int *upperA)
1846{
1847 int timA;
1848 int statistics[NUM_LANES][128];
1849 int lane;
1850
1851 for (timA = 0; timA < 128; timA++) {
1852 FOR_ALL_LANES {
1853 ctrl->timings[channel][slotrank].lanes[lane].timA = timA;
1854 }
1855 program_timings(ctrl, channel);
1856
1857 test_timA(ctrl, channel, slotrank);
1858
1859 FOR_ALL_LANES {
1860 statistics[lane][timA] =
1861 !does_lane_work(ctrl, channel, slotrank, lane);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001862 printram("Astat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001863 channel, slotrank, lane, timA,
1864 statistics[lane][timA]);
1865 }
1866 }
1867 FOR_ALL_LANES {
1868 struct run rn = get_longest_zero_run(statistics[lane], 128);
1869 ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle;
1870 upperA[lane] = rn.end;
1871 if (upperA[lane] < rn.middle)
1872 upperA[lane] += 128;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001873 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001874 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001875 printram("Aend: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001876 lane, upperA[lane]);
1877 }
1878}
1879
1880static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
1881 int *upperA)
1882{
1883 int timA_delta;
1884 int statistics[NUM_LANES][51];
1885 int lane, i;
1886
1887 memset(statistics, 0, sizeof(statistics));
1888
1889 for (timA_delta = -25; timA_delta <= 25; timA_delta++) {
1890 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
1891 timA = upperA[lane] + timA_delta + 0x40;
1892 program_timings(ctrl, channel);
1893
1894 for (i = 0; i < 100; i++) {
1895 test_timA(ctrl, channel, slotrank);
1896 FOR_ALL_LANES {
1897 statistics[lane][timA_delta + 25] +=
1898 does_lane_work(ctrl, channel, slotrank,
1899 lane);
1900 }
1901 }
1902 }
1903 FOR_ALL_LANES {
1904 int last_zero, first_all;
1905
1906 for (last_zero = -25; last_zero <= 25; last_zero++)
1907 if (statistics[lane][last_zero + 25])
1908 break;
1909 last_zero--;
1910 for (first_all = -25; first_all <= 25; first_all++)
1911 if (statistics[lane][first_all + 25] == 100)
1912 break;
1913
1914 printram("lane %d: %d, %d\n", lane, last_zero,
1915 first_all);
1916
1917 ctrl->timings[channel][slotrank].lanes[lane].timA =
1918 (last_zero + first_all) / 2 + upperA[lane];
Patrick Rudolpha649a542016-01-17 18:32:06 +01001919 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001920 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
1921 }
1922}
1923
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001924static int discover_402x(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001925 int *upperA)
1926{
1927 int works[NUM_LANES];
1928 int lane;
1929 while (1) {
1930 int all_works = 1, some_works = 0;
1931 program_timings(ctrl, channel);
1932 test_timA(ctrl, channel, slotrank);
1933 FOR_ALL_LANES {
1934 works[lane] =
1935 !does_lane_work(ctrl, channel, slotrank, lane);
1936 if (works[lane])
1937 some_works = 1;
1938 else
1939 all_works = 0;
1940 }
1941 if (all_works)
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001942 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001943 if (!some_works) {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001944 if (ctrl->timings[channel][slotrank].val_4024 < 2) {
1945 printk(BIOS_EMERG, "402x discovery failed (1): %d, %d\n",
1946 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001947 return MAKE_ERR;
1948 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001949 ctrl->timings[channel][slotrank].val_4024 -= 2;
1950 printram("4024 -= 2;\n");
1951 continue;
1952 }
1953 ctrl->timings[channel][slotrank].val_4028 += 2;
1954 printram("4028 += 2;\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001955 if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) {
1956 printk(BIOS_EMERG, "402x discovery failed (2): %d, %d\n",
1957 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001958 return MAKE_ERR;
1959 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001960 FOR_ALL_LANES if (works[lane]) {
1961 ctrl->timings[channel][slotrank].lanes[lane].timA +=
1962 128;
1963 upperA[lane] += 128;
1964 printram("increment %d, %d, %d\n", channel,
1965 slotrank, lane);
1966 }
1967 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001968 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001969}
1970
1971struct timA_minmax {
1972 int timA_min_high, timA_max_high;
1973};
1974
1975static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1976 struct timA_minmax *mnmx)
1977{
1978 int lane;
1979 mnmx->timA_min_high = 7;
1980 mnmx->timA_max_high = 0;
1981
1982 FOR_ALL_LANES {
1983 if (mnmx->timA_min_high >
1984 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1985 mnmx->timA_min_high =
1986 (ctrl->timings[channel][slotrank].lanes[lane].
1987 timA >> 6);
1988 if (mnmx->timA_max_high <
1989 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
1990 mnmx->timA_max_high =
1991 (ctrl->timings[channel][slotrank].lanes[lane].
1992 timA >> 6);
1993 }
1994}
1995
1996static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
1997 struct timA_minmax *mnmx)
1998{
1999 struct timA_minmax post;
2000 int shift_402x = 0;
2001
2002 /* Get changed maxima. */
2003 pre_timA_change(ctrl, channel, slotrank, &post);
2004
2005 if (mnmx->timA_max_high - mnmx->timA_min_high <
2006 post.timA_max_high - post.timA_min_high)
2007 shift_402x = +1;
2008 else if (mnmx->timA_max_high - mnmx->timA_min_high >
2009 post.timA_max_high - post.timA_min_high)
2010 shift_402x = -1;
2011 else
2012 shift_402x = 0;
2013
2014 ctrl->timings[channel][slotrank].val_4028 += shift_402x;
2015 ctrl->timings[channel][slotrank].val_4024 += shift_402x;
2016 printram("4024 += %d;\n", shift_402x);
2017 printram("4028 += %d;\n", shift_402x);
2018}
2019
Patrick Rudolph371d2912015-10-09 13:33:25 +02002020/* Compensate the skew between DQS and DQs.
2021 * To ease PCB design a small skew between Data Strobe signals and
2022 * Data Signals is allowed.
2023 * The controller has to measure and compensate this skew for every byte-lane.
2024 * By delaying either all DQs signals or DQS signal, a full phase
2025 * shift can be introduced.
2026 * It is assumed that one byte-lane's DQs signals have the same routing delay.
2027 *
2028 * To measure the actual skew, the DRAM is placed in "read leveling" mode.
2029 * In read leveling mode the DRAM-chip outputs an alternating periodic pattern.
2030 * The memory controller iterates over all possible values to do a full phase shift
2031 * and issues read commands.
2032 * With DQS and DQs in phase the data read is expected to alternate on every byte:
2033 * 0xFF 0x00 0xFF ...
2034 * Once the controller has detected this pattern a bit in the result register is
2035 * set for the current phase shift.
2036 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002037static int read_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002038{
2039 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002040 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002041
2042 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002043 int all_high, some_high;
2044 int upperA[NUM_LANES];
2045 struct timA_minmax mnmx;
2046
2047 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002048
2049 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002050 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2051 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2052 0xc01 | (ctrl->tRP << 16));
2053 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2054 (slotrank << 24) | 0x60400);
2055 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2056 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2057
2058 write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001);
2059
2060 ctrl->timings[channel][slotrank].val_4028 = 4;
2061 ctrl->timings[channel][slotrank].val_4024 = 55;
2062 program_timings(ctrl, channel);
2063
2064 discover_timA_coarse(ctrl, channel, slotrank, upperA);
2065
2066 all_high = 1;
2067 some_high = 0;
2068 FOR_ALL_LANES {
2069 if (ctrl->timings[channel][slotrank].lanes[lane].
2070 timA >= 0x40)
2071 some_high = 1;
2072 else
2073 all_high = 0;
2074 }
2075
2076 if (all_high) {
2077 ctrl->timings[channel][slotrank].val_4028--;
2078 printram("4028--;\n");
2079 FOR_ALL_LANES {
2080 ctrl->timings[channel][slotrank].lanes[lane].
2081 timA -= 0x40;
2082 upperA[lane] -= 0x40;
2083
2084 }
2085 } else if (some_high) {
2086 ctrl->timings[channel][slotrank].val_4024++;
2087 ctrl->timings[channel][slotrank].val_4028++;
2088 printram("4024++;\n");
2089 printram("4028++;\n");
2090 }
2091
2092 program_timings(ctrl, channel);
2093
2094 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2095
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002096 err = discover_402x(ctrl, channel, slotrank, upperA);
2097 if (err)
2098 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002099
2100 post_timA_change(ctrl, channel, slotrank, &mnmx);
2101 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2102
2103 discover_timA_fine(ctrl, channel, slotrank, upperA);
2104
2105 post_timA_change(ctrl, channel, slotrank, &mnmx);
2106 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2107
2108 FOR_ALL_LANES {
2109 ctrl->timings[channel][slotrank].lanes[lane].timA -= mnmx.timA_min_high * 0x40;
2110 }
2111 ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high;
2112 printram("4028 -= %d;\n", mnmx.timA_min_high);
2113
2114 post_timA_change(ctrl, channel, slotrank, &mnmx);
2115
2116 printram("4/8: %d, %d, %x, %x\n", channel, slotrank,
2117 ctrl->timings[channel][slotrank].val_4024,
2118 ctrl->timings[channel][slotrank].val_4028);
2119
Patrick Rudolpha649a542016-01-17 18:32:06 +01002120 printram("final results:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002121 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01002122 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002123 lane,
2124 ctrl->timings[channel][slotrank].lanes[lane].timA);
2125
2126 write32(DEFAULT_MCHBAR + 0x3400, 0);
2127
Patrick Rudolph9b515682015-10-09 13:43:51 +02002128 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002129 }
2130
2131 FOR_ALL_POPULATED_CHANNELS {
2132 program_timings(ctrl, channel);
2133 }
2134 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2135 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
2136 + 4 * lane, 0);
2137 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002138 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002139}
2140
2141static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
2142{
2143 int lane;
2144
2145 FOR_ALL_LANES {
2146 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0);
2147 read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane);
2148 }
2149
2150 wait_428c(channel);
2151
Patrick Rudolph371d2912015-10-09 13:33:25 +02002152 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002153 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2154 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2155 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
2156 | 4 | (ctrl->tRCD << 16));
2157
2158 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2159 (slotrank << 24) | (6 << 16));
2160
2161 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
2162
Patrick Rudolph371d2912015-10-09 13:33:25 +02002163 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002164 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2165 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001);
2166 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2167 (slotrank << 24) | 8);
2168 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2169
Patrick Rudolph371d2912015-10-09 13:33:25 +02002170 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002171 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2172 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4);
2173 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2174 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2175
Patrick Rudolph371d2912015-10-09 13:33:25 +02002176 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002177 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2178 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2179 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2180 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2181 (slotrank << 24) | 8);
2182 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2183
2184 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2185
2186 wait_428c(channel);
2187
Patrick Rudolph371d2912015-10-09 13:33:25 +02002188 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002189 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2190 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2191 0xc01 | (ctrl->tRP << 16));
2192 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2193 (slotrank << 24) | 0x60400);
2194 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2195
Patrick Rudolph371d2912015-10-09 13:33:25 +02002196 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002197 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2198 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2199 (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10)
2200 | 8 | (ctrl->CAS << 16));
2201
2202 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2203 (slotrank << 24) | 0x60000);
2204
2205 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244);
2206
Patrick Rudolph371d2912015-10-09 13:33:25 +02002207 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002208 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2209 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2210 0x40011f4 | (max(ctrl->tRTP, 8) << 16));
2211 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2212 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2213
Patrick Rudolph371d2912015-10-09 13:33:25 +02002214 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002215 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2216 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2217 0xc01 | (ctrl->tRP << 16));
2218 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2219 (slotrank << 24) | 0x60400);
2220 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2221 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2222 wait_428c(channel);
2223}
2224
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002225static int discover_timC(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002226{
2227 int timC;
2228 int statistics[NUM_LANES][MAX_TIMC + 1];
2229 int lane;
2230
2231 wait_428c(channel);
2232
Patrick Rudolph371d2912015-10-09 13:33:25 +02002233 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002234 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2235 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2236 0xc01 | (ctrl->tRP << 16));
2237 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2238 (slotrank << 24) | 0x60400);
2239 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2240 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2241
2242 for (timC = 0; timC <= MAX_TIMC; timC++) {
2243 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
2244 timC = timC;
2245 program_timings(ctrl, channel);
2246
2247 test_timC(ctrl, channel, slotrank);
2248
2249 FOR_ALL_LANES {
2250 statistics[lane][timC] =
2251 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2252 0x400 * channel);
2253 printram("Cstat: %d, %d, %d, %x, %x\n",
2254 channel, slotrank, lane, timC,
2255 statistics[lane][timC]);
2256 }
2257 }
2258 FOR_ALL_LANES {
2259 struct run rn =
2260 get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
2261 ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002262 if (rn.all) {
2263 printk(BIOS_EMERG, "timC discovery failed: %d, %d, %d\n",
2264 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002265 return MAKE_ERR;
2266 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002267 printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002268 lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
2269 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002270 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002271}
2272
2273static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
2274{
2275 int channel, ret = 0;
2276 FOR_ALL_POPULATED_CHANNELS if (channel < target_channel)
2277 ret++;
2278 return ret;
2279}
2280
2281static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b)
2282{
2283 unsigned j;
2284 unsigned channel_offset =
2285 get_precedening_channels(ctrl, channel) * 0x40;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002286 for (j = 0; j < 16; j++)
2287 write32((void *)(0x04000000 + channel_offset + 4 * j), j & 2 ? b : a);
2288 sfence();
2289}
2290
2291static int num_of_channels(const ramctr_timing * ctrl)
2292{
2293 int ret = 0;
2294 int channel;
2295 FOR_ALL_POPULATED_CHANNELS ret++;
2296 return ret;
2297}
2298
2299static void fill_pattern1(ramctr_timing * ctrl, int channel)
2300{
2301 unsigned j;
2302 unsigned channel_offset =
2303 get_precedening_channels(ctrl, channel) * 0x40;
2304 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2305 for (j = 0; j < 16; j++)
2306 write32((void *)(0x04000000 + channel_offset + j * 4), 0xffffffff);
2307 for (j = 0; j < 16; j++)
2308 write32((void *)(0x04000000 + channel_offset + channel_step + j * 4), 0);
2309 sfence();
2310}
2311
2312static void precharge(ramctr_timing * ctrl)
2313{
2314 int channel, slotrank, lane;
2315
2316 FOR_ALL_POPULATED_CHANNELS {
2317 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2318 ctrl->timings[channel][slotrank].lanes[lane].falling =
2319 16;
2320 ctrl->timings[channel][slotrank].lanes[lane].rising =
2321 16;
Patrick Rudolpha649a542016-01-17 18:32:06 +01002322 }
2323
2324 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002325
2326 FOR_ALL_POPULATED_RANKS {
2327 wait_428c(channel);
2328
Patrick Rudolph371d2912015-10-09 13:33:25 +02002329 /* DRAM command MRS
2330 * write MR3 MPR enable
2331 * in this mode only RD and RDA are allowed
2332 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002333 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2334 0x1f000);
2335 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2336 0xc01 | (ctrl->tMOD << 16));
2337 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2338 (slotrank << 24) | 0x360004);
2339 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2340
Patrick Rudolph371d2912015-10-09 13:33:25 +02002341 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002342 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2343 0x1f105);
2344 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2345 0x4041003);
2346 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2347 (slotrank << 24) | 0);
2348 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2349
Patrick Rudolph371d2912015-10-09 13:33:25 +02002350 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002351 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2352 0x1f105);
2353 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2354 0x1001 | ((ctrl->CAS + 8) << 16));
2355 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2356 (slotrank << 24) | 0x60000);
2357 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2358
Patrick Rudolph371d2912015-10-09 13:33:25 +02002359 /* DRAM command MRS
2360 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002361 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2362 0x1f000);
2363 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2364 0xc01 | (ctrl->tMOD << 16));
2365 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2366 (slotrank << 24) | 0x360000);
2367 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2368 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2369 0xc0001);
2370
2371 wait_428c(channel);
2372 }
2373
2374 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2375 ctrl->timings[channel][slotrank].lanes[lane].falling =
2376 48;
2377 ctrl->timings[channel][slotrank].lanes[lane].rising =
2378 48;
2379 }
2380
2381 program_timings(ctrl, channel);
2382
2383 FOR_ALL_POPULATED_RANKS {
2384 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002385 /* DRAM command MRS
2386 * write MR3 MPR enable
2387 * in this mode only RD and RDA are allowed
2388 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002389 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2390 0x1f000);
2391 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2392 0xc01 | (ctrl->tMOD << 16));
2393 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2394 (slotrank << 24) | 0x360004);
2395 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2396
Patrick Rudolph371d2912015-10-09 13:33:25 +02002397 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002398 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2399 0x1f105);
2400 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2401 0x4041003);
2402 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2403 (slotrank << 24) | 0);
2404 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2405
Patrick Rudolph371d2912015-10-09 13:33:25 +02002406 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002407 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2408 0x1f105);
2409 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2410 0x1001 | ((ctrl->CAS + 8) << 16));
2411 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2412 (slotrank << 24) | 0x60000);
2413 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2414
Patrick Rudolph371d2912015-10-09 13:33:25 +02002415 /* DRAM command MRS
2416 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002417 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2418 0x1f000);
2419 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2420 0xc01 | (ctrl->tMOD << 16));
2421
2422 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2423 (slotrank << 24) | 0x360000);
2424 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2425
2426 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2427 0xc0001);
2428 wait_428c(channel);
2429 }
2430 }
2431}
2432
2433static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
2434{
Patrick Rudolph371d2912015-10-09 13:33:25 +02002435 /* enable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002436 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002437 0x80 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002438
2439 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002440 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002441 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207);
2442 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2443 0x8000c01 | ((ctrl->CWL + ctrl->tWLO) << 16));
2444 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2445 8 | (slotrank << 24));
2446 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2447
Patrick Rudolph371d2912015-10-09 13:33:25 +02002448 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002449 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107);
2450 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2451 0x4000c01 | ((ctrl->CAS + 38) << 16));
2452 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2453 (slotrank << 24) | 4);
2454 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2455
2456 write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001);
2457 wait_428c(channel);
2458
Patrick Rudolph371d2912015-10-09 13:33:25 +02002459 /* disable 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 0x1080 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002462}
2463
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002464static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002465{
2466 int timB;
2467 int statistics[NUM_LANES][128];
2468 int lane;
2469
2470 write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2));
2471
2472 for (timB = 0; timB < 128; timB++) {
2473 FOR_ALL_LANES {
2474 ctrl->timings[channel][slotrank].lanes[lane].timB = timB;
2475 }
2476 program_timings(ctrl, channel);
2477
2478 test_timB(ctrl, channel, slotrank);
2479
2480 FOR_ALL_LANES {
2481 statistics[lane][timB] =
2482 !((read32
2483 (DEFAULT_MCHBAR + lane_registers[lane] +
2484 channel * 0x100 + 4 + ((timB / 32) & 1) * 4)
2485 >> (timB % 32)) & 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002486 printram("Bstat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002487 channel, slotrank, lane, timB,
2488 statistics[lane][timB]);
2489 }
2490 }
2491 FOR_ALL_LANES {
2492 struct run rn = get_longest_zero_run(statistics[lane], 128);
Patrick Rudolphd912f1d2016-02-15 20:07:42 +01002493 /* timC is a direct function of timB's 6 LSBs.
2494 * Some tests increments the value of timB by a small value,
2495 * which might cause the 6bit value to overflow, if it's close
2496 * to 0x3F. Increment the value by a small offset if it's likely
2497 * to overflow, to make sure it won't overflow while running
2498 * tests and bricks the system due to a non matching timC.
2499 *
2500 * TODO: find out why some tests (edge write discovery)
2501 * increment timB. */
2502 if ((rn.start & 0x3F) == 0x3E)
2503 rn.start += 2;
2504 else if ((rn.start & 0x3F) == 0x3F)
2505 rn.start += 1;
Vladimir Serbinenko3141eac2016-01-29 19:42:02 +01002506 ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002507 if (rn.all) {
2508 printk(BIOS_EMERG, "timB discovery failed: %d, %d, %d\n",
2509 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002510 return MAKE_ERR;
2511 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002512 printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002513 lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
2514 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002515 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002516}
2517
2518static int get_timB_high_adjust(u64 val)
2519{
2520 int i;
2521
2522 /* good */
2523 if (val == 0xffffffffffffffffLL)
2524 return 0;
2525
2526 if (val >= 0xf000000000000000LL) {
2527 /* needs negative adjustment */
2528 for (i = 0; i < 8; i++)
2529 if (val << (8 * (7 - i) + 4))
2530 return -i;
2531 } else {
2532 /* needs positive adjustment */
2533 for (i = 0; i < 8; i++)
2534 if (val >> (8 * (7 - i) + 4))
2535 return i;
2536 }
2537 return 8;
2538}
2539
2540static void adjust_high_timB(ramctr_timing * ctrl)
2541{
2542 int channel, slotrank, lane, old;
2543 write32(DEFAULT_MCHBAR + 0x3400, 0x200);
2544 FOR_ALL_POPULATED_CHANNELS {
2545 fill_pattern1(ctrl, channel);
2546 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 1);
2547 }
2548 FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
2549
2550 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001);
2551
2552 wait_428c(channel);
2553
Patrick Rudolph371d2912015-10-09 13:33:25 +02002554 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002555 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2556 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2557 0xc01 | (ctrl->tRCD << 16));
2558 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2559 (slotrank << 24) | 0x60000);
2560 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2561
Patrick Rudolph371d2912015-10-09 13:33:25 +02002562 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002563 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2564 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01);
2565 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2566 (slotrank << 24) | 0x8);
2567 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2568
Patrick Rudolph371d2912015-10-09 13:33:25 +02002569 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002570 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2571 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003);
2572 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2573 (slotrank << 24));
2574 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2);
2575
Patrick Rudolph371d2912015-10-09 13:33:25 +02002576 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002577 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2578 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2579 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2580 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2581 (slotrank << 24) | 0x8);
2582 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2583
2584 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2585
2586 wait_428c(channel);
2587
Patrick Rudolph371d2912015-10-09 13:33:25 +02002588 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002589 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2590 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2591 0xc01 | ((ctrl->tRP) << 16));
2592 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2593 (slotrank << 24) | 0x60400);
2594 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2595
Patrick Rudolph371d2912015-10-09 13:33:25 +02002596 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002597 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2598 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2599 0xc01 | ((ctrl->tRCD) << 16));
2600 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2601 (slotrank << 24) | 0x60000);
2602 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2603
Patrick Rudolph371d2912015-10-09 13:33:25 +02002604 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002605 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105);
2606 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2607 0x4000c01 |
2608 ((ctrl->tRP +
2609 ctrl->timings[channel][slotrank].val_4024 +
2610 ctrl->timings[channel][slotrank].val_4028) << 16));
2611 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2612 (slotrank << 24) | 0x60008);
2613 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2614
2615 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
2616 wait_428c(channel);
2617 FOR_ALL_LANES {
2618 u64 res =
2619 read32(DEFAULT_MCHBAR + lane_registers[lane] +
2620 0x100 * channel + 4);
2621 res |=
2622 ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] +
2623 0x100 * channel + 8)) << 32;
2624 old = ctrl->timings[channel][slotrank].lanes[lane].timB;
2625 ctrl->timings[channel][slotrank].lanes[lane].timB +=
2626 get_timB_high_adjust(res) * 64;
2627
Patrick Rudolpha649a542016-01-17 18:32:06 +01002628 printram("High adjust %d:%016llx\n", lane, res);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002629 printram("Bval+: %d, %d, %d, %x -> %x\n", channel,
2630 slotrank, lane, old,
2631 ctrl->timings[channel][slotrank].lanes[lane].
2632 timB);
2633 }
2634 }
2635 write32(DEFAULT_MCHBAR + 0x3400, 0);
2636}
2637
2638static void write_op(ramctr_timing * ctrl, int channel)
2639{
2640 int slotrank;
2641
2642 wait_428c(channel);
2643
2644 /* choose an existing rank. */
2645 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2646
Patrick Rudolph371d2912015-10-09 13:33:25 +02002647 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002648 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2649 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2650
2651 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2652 (slotrank << 24) | 0x60000);
2653
2654 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2655
2656 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2657 wait_428c(channel);
2658}
2659
Patrick Rudolph371d2912015-10-09 13:33:25 +02002660/* Compensate the skew between CMD/ADDR/CLK and DQ/DQS lanes.
2661 * DDR3 adopted the fly-by topology. The data and strobes signals reach
2662 * the chips at different times with respect to command, address and
2663 * clock signals.
2664 * By delaying either all DQ/DQs or all CMD/ADDR/CLK signals, a full phase
2665 * shift can be introduced.
2666 * It is assumed that the CLK/ADDR/CMD signals have the same routing delay.
2667 *
2668 * To find the required phase shift the DRAM is placed in "write leveling" mode.
2669 * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
2670 * sampled value on the data lanes (DQs).
2671 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002672static int write_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002673{
2674 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002675 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002676
2677 FOR_ALL_POPULATED_CHANNELS
2678 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
2679 read32(DEFAULT_MCHBAR + 0x4008 +
2680 0x400 * channel) | 0x8000000);
2681
2682 FOR_ALL_POPULATED_CHANNELS {
2683 write_op(ctrl, channel);
2684 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2685 read32(DEFAULT_MCHBAR + 0x4020 +
2686 0x400 * channel) | 0x200000);
2687 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002688
2689 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002690 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2691 FOR_ALL_POPULATED_CHANNELS {
2692 write_op(ctrl, channel);
2693 }
2694
Patrick Rudolph371d2912015-10-09 13:33:25 +02002695 /* enable write leveling on all ranks
2696 * disable all DQ outputs
2697 * only NOP is allowed in this mode */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002698 FOR_ALL_CHANNELS
2699 FOR_ALL_POPULATED_RANKS
2700 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002701 make_mr1(ctrl, slotrank, channel) | 0x1080);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002702
2703 write32(DEFAULT_MCHBAR + 0x3400, 0x108052);
2704
Patrick Rudolph9b515682015-10-09 13:43:51 +02002705 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002706
Patrick Rudolph371d2912015-10-09 13:33:25 +02002707 /* set any valid value for timB, it gets corrected later */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002708 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2709 err = discover_timB(ctrl, channel, slotrank);
2710 if (err)
2711 return err;
2712 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002713
Patrick Rudolph371d2912015-10-09 13:33:25 +02002714 /* disable write leveling on all ranks */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002715 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2716 write_mrreg(ctrl, channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002717 slotrank, 1, make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002718
2719 write32(DEFAULT_MCHBAR + 0x3400, 0);
2720
2721 FOR_ALL_POPULATED_CHANNELS
2722 wait_428c(channel);
2723
Patrick Rudolph371d2912015-10-09 13:33:25 +02002724 /* refresh enable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002725 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8);
2726
2727 FOR_ALL_POPULATED_CHANNELS {
2728 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2729 ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 +
2730 0x400 * channel));
2731 read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel);
2732 wait_428c(channel);
2733
Patrick Rudolph371d2912015-10-09 13:33:25 +02002734 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002735 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2736 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
2737 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000);
2738 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2739
2740 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2741 wait_428c(channel);
2742 }
2743
Patrick Rudolph9b515682015-10-09 13:43:51 +02002744 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002745
2746 printram("CPE\n");
2747 precharge(ctrl);
2748 printram("CPF\n");
2749
2750 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2751 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2752 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2753 0);
2754 }
2755
2756 FOR_ALL_POPULATED_CHANNELS {
2757 fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555);
2758 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
2759 }
2760
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002761 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2762 err = discover_timC(ctrl, channel, slotrank);
2763 if (err)
2764 return err;
2765 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002766
2767 FOR_ALL_POPULATED_CHANNELS
2768 program_timings(ctrl, channel);
2769
Patrick Rudolph371d2912015-10-09 13:33:25 +02002770 /* measure and adjust timB timings */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002771 adjust_high_timB(ctrl);
2772
2773 FOR_ALL_POPULATED_CHANNELS
2774 program_timings(ctrl, channel);
2775
2776 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2777 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2778 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2779 0);
2780 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002781 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002782}
2783
2784static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
2785{
2786 struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank];
2787 int timC_delta;
2788 int lanes_ok = 0;
2789 int ctr = 0;
2790 int lane;
2791
2792 for (timC_delta = -5; timC_delta <= 5; timC_delta++) {
2793 FOR_ALL_LANES {
2794 ctrl->timings[channel][slotrank].lanes[lane].timC =
2795 saved_rt.lanes[lane].timC + timC_delta;
2796 }
2797 program_timings(ctrl, channel);
2798 FOR_ALL_LANES {
2799 write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0);
2800 }
2801
2802 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2803
2804 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002805 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002806 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2807 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2808 ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10)
2809 | 8 | (ctrl->tRCD << 16));
2810
2811 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2812 (slotrank << 24) | ctr | 0x60000);
2813
2814 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002815 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002816 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
2817 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2818 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16));
2819 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2820 (slotrank << 24));
2821 write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd);
2822 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42);
2823
Patrick Rudolph371d2912015-10-09 13:33:25 +02002824 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002825 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2826 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2827 0x4001020 | (max(ctrl->tRTP, 8) << 16));
2828 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2829 (slotrank << 24));
2830 write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd);
2831 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42);
2832
Patrick Rudolph371d2912015-10-09 13:33:25 +02002833 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002834 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2835 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001);
2836 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2837 (slotrank << 24) | 0x60400);
2838 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2839
2840 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2841 wait_428c(channel);
2842 FOR_ALL_LANES {
2843 u32 r32 =
2844 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2845 0x400 * channel);
2846
2847 if (r32 == 0)
2848 lanes_ok |= 1 << lane;
2849 }
2850 ctr++;
2851 if (lanes_ok == ((1 << NUM_LANES) - 1))
2852 break;
2853 }
2854
2855 ctrl->timings[channel][slotrank] = saved_rt;
2856
2857 printram("3lanes: %x\n", lanes_ok);
2858 return lanes_ok != ((1 << NUM_LANES) - 1);
2859}
2860
2861#include "raminit_patterns.h"
2862
2863static void fill_pattern5(ramctr_timing * ctrl, int channel, int patno)
2864{
2865 unsigned i, j;
2866 unsigned channel_offset =
2867 get_precedening_channels(ctrl, channel) * 0x40;
2868 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2869
2870 if (patno) {
2871 u8 base8 = 0x80 >> ((patno - 1) % 8);
2872 u32 base = base8 | (base8 << 8) | (base8 << 16) | (base8 << 24);
2873 for (i = 0; i < 32; i++) {
2874 for (j = 0; j < 16; j++) {
2875 u32 val = use_base[patno - 1][i] & (1 << (j / 2)) ? base : 0;
2876 if (invert[patno - 1][i] & (1 << (j / 2)))
2877 val = ~val;
2878 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2879 j * 4), val);
2880 }
2881 }
2882
2883 } else {
2884 for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) {
2885 for (j = 0; j < 16; j++)
2886 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2887 j * 4), pattern[i][j]);
2888 }
2889 sfence();
2890 }
2891}
2892
2893static void reprogram_320c(ramctr_timing * ctrl)
2894{
2895 int channel, slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002896
2897 FOR_ALL_POPULATED_CHANNELS {
2898 wait_428c(channel);
2899
2900 /* choose an existing rank. */
2901 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2902
Patrick Rudolph371d2912015-10-09 13:33:25 +02002903 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002904 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2905 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2906
2907 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2908 (slotrank << 24) | 0x60000);
2909
2910 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2911
2912 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2913 wait_428c(channel);
2914 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2915 read32(DEFAULT_MCHBAR + 0x4020 +
2916 0x400 * channel) | 0x200000);
2917 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002918
2919 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002920 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
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 }
2939
2940 /* jedec reset */
2941 dram_jedecreset(ctrl);
2942 /* mrs commands. */
2943 dram_mrscommands(ctrl);
2944
Patrick Rudolph9b515682015-10-09 13:43:51 +02002945 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002946}
2947
2948#define MIN_C320C_LEN 13
2949
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002950static int try_cmd_stretch(ramctr_timing *ctrl, int cmd_stretch)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002951{
2952 struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
2953 int channel, slotrank;
2954 int c320c;
2955 int stat[NUM_SLOTRANKS][256];
2956
2957 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2958 saved_timings[channel][slotrank] = ctrl->timings[channel][slotrank];
2959 }
2960
2961 FOR_ALL_POPULATED_CHANNELS {
2962 ctrl->cmd_stretch[channel] = cmd_stretch;
2963 }
2964
2965 FOR_ALL_POPULATED_CHANNELS
2966 MCHBAR32(0x4004 + 0x400 * channel) =
2967 ctrl->tRRD
2968 | (ctrl->tRTP << 4)
2969 | (ctrl->tCKE << 8)
2970 | (ctrl->tWTR << 12)
2971 | (ctrl->tFAW << 16)
2972 | (ctrl->tWR << 24)
2973 | (ctrl->cmd_stretch[channel] << 30);
2974
2975
2976 FOR_ALL_CHANNELS {
2977 int delta = 0;
2978 if (ctrl->cmd_stretch[channel] == 2)
2979 delta = 2;
2980 else if (ctrl->cmd_stretch[channel] == 0)
2981 delta = 4;
2982
2983 FOR_ALL_POPULATED_RANKS {
2984 ctrl->timings[channel][slotrank].val_4024 -= delta;
2985 }
2986 }
2987
2988 FOR_ALL_POPULATED_CHANNELS {
2989 for (c320c = -127; c320c <= 127; c320c++) {
2990 FOR_ALL_POPULATED_RANKS {
2991 ctrl->timings[channel][slotrank].val_320c = c320c;
2992 }
2993 program_timings(ctrl, channel);
2994 reprogram_320c(ctrl);
2995 FOR_ALL_POPULATED_RANKS {
2996 stat[slotrank][c320c + 127] =
2997 test_320c(ctrl, channel, slotrank);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002998 printram("3stat: %d, %d, %d: %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002999 channel, slotrank, c320c,
3000 stat[slotrank][c320c + 127]);
3001 }
3002 }
3003 FOR_ALL_POPULATED_RANKS {
3004 struct run rn =
3005 get_longest_zero_run(stat[slotrank], 255);
3006 ctrl->timings[channel][slotrank].val_320c =
3007 rn.middle - 127;
3008 printram("3val: %d, %d: %d\n", channel,
3009 slotrank,
3010 ctrl->timings[channel][slotrank].val_320c);
3011 if (rn.all || rn.length < MIN_C320C_LEN) {
3012 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3013 ctrl->timings[channel][slotrank] = saved_timings[channel][slotrank];
3014 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003015 return MAKE_ERR;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003016 }
3017 }
3018 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003019 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003020}
3021
Patrick Rudolph371d2912015-10-09 13:33:25 +02003022/* Adjust CMD phase shift and try multiple command rates.
3023 * A command rate of 2T doubles the time needed for address and
3024 * command decode. */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003025static int command_training(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003026{
3027 int channel;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003028 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003029
3030 FOR_ALL_POPULATED_CHANNELS {
3031 fill_pattern5(ctrl, channel, 0);
3032 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
3033 }
3034
3035 /* try command rate 1T and 2T */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003036 err = try_cmd_stretch(ctrl, 0);
3037 if (err) {
3038 err = try_cmd_stretch(ctrl, 2);
3039 if (err) {
3040 printk(BIOS_EMERG, "c320c discovery failed\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003041 return err;
3042 }
3043 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003044
3045 FOR_ALL_POPULATED_CHANNELS {
3046 program_timings(ctrl, channel);
3047 }
3048
3049 reprogram_320c(ctrl);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003050 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003051}
3052
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003053static int discover_edges_real(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003054 int *edges)
3055{
3056 int edge;
3057 int statistics[NUM_LANES][MAX_EDGE_TIMING + 1];
3058 int lane;
3059
3060 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3061 FOR_ALL_LANES {
3062 ctrl->timings[channel][slotrank].lanes[lane].rising =
3063 edge;
3064 ctrl->timings[channel][slotrank].lanes[lane].falling =
3065 edge;
3066 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003067 program_timings(ctrl, channel);
3068
3069 FOR_ALL_LANES {
3070 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3071 4 * lane, 0);
3072 read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane +
3073 0x4140);
3074 }
3075
3076 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003077 /* DRAM command MRS
3078 * write MR3 MPR enable
3079 * in this mode only RD and RDA are allowed
3080 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003081 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
3082 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3083 (0xc01 | (ctrl->tMOD << 16)));
3084 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3085 (slotrank << 24) | 0x360004);
3086 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3087
Patrick Rudolph371d2912015-10-09 13:33:25 +02003088 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003089 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
3090 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4);
3091 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3092 (slotrank << 24));
3093 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3094
Patrick Rudolph371d2912015-10-09 13:33:25 +02003095 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003096 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
3097 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3098 0x1001 | ((ctrl->CAS + 8) << 16));
3099 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3100 (slotrank << 24) | 0x60000);
3101 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3102
Patrick Rudolph371d2912015-10-09 13:33:25 +02003103 /* DRAM command MRS
3104 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003105 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
3106 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3107 (0xc01 | (ctrl->tMOD << 16)));
3108 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3109 (slotrank << 24) | 0x360000);
3110 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3111
3112 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
3113
3114 wait_428c(channel);
3115
3116 FOR_ALL_LANES {
3117 statistics[lane][edge] =
3118 read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3119 lane * 4);
3120 }
3121 }
3122 FOR_ALL_LANES {
3123 struct run rn =
3124 get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
3125 edges[lane] = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003126 if (rn.all) {
3127 printk(BIOS_EMERG, "edge discovery failed: %d, %d, %d\n",
3128 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003129 return MAKE_ERR;
3130 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003131 printram("eval %d, %d, %d: %02x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003132 lane, edges[lane]);
3133 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003134 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003135}
3136
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003137static int discover_edges(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003138{
3139 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3140 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3141 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003142 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003143
3144 write32(DEFAULT_MCHBAR + 0x3400, 0);
3145
Patrick Rudolph9b515682015-10-09 13:43:51 +02003146 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003147
3148 FOR_ALL_POPULATED_CHANNELS FOR_ALL_LANES {
3149 write32(DEFAULT_MCHBAR + 4 * lane +
3150 0x400 * channel + 0x4080, 0);
3151 }
3152
3153 FOR_ALL_POPULATED_CHANNELS {
3154 fill_pattern0(ctrl, channel, 0, 0);
3155 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3156 FOR_ALL_LANES {
3157 read32(DEFAULT_MCHBAR + 0x400 * channel +
3158 lane * 4 + 0x4140);
3159 }
3160
3161 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3162 ctrl->timings[channel][slotrank].lanes[lane].falling =
3163 16;
3164 ctrl->timings[channel][slotrank].lanes[lane].rising =
3165 16;
3166 }
3167
3168 program_timings(ctrl, channel);
3169
3170 FOR_ALL_POPULATED_RANKS {
3171 wait_428c(channel);
3172
Patrick Rudolph371d2912015-10-09 13:33:25 +02003173 /* DRAM command MRS
3174 * MR3 enable MPR
3175 * write MR3 MPR enable
3176 * in this mode only RD and RDA are allowed
3177 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003178 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3179 0x1f000);
3180 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3181 0xc01 | (ctrl->tMOD << 16));
3182 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3183 (slotrank << 24) | 0x360004);
3184 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3185
Patrick Rudolph371d2912015-10-09 13:33:25 +02003186 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003187 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3188 0x1f105);
3189 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3190 0x4041003);
3191 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3192 (slotrank << 24) | 0);
3193 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3194
Patrick Rudolph371d2912015-10-09 13:33:25 +02003195 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003196 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3197 0x1f105);
3198 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3199 0x1001 | ((ctrl->CAS + 8) << 16));
3200 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3201 (slotrank << 24) | 0x60000);
3202 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3203
Patrick Rudolph371d2912015-10-09 13:33:25 +02003204 /* DRAM command MRS
3205 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003206 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3207 0x1f000);
3208 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3209 0xc01 | (ctrl->tMOD << 16));
3210 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3211 (slotrank << 24) | 0x360000);
3212 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3213 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3214 0xc0001);
3215
3216 wait_428c(channel);
3217 }
3218
Patrick Rudolph371d2912015-10-09 13:33:25 +02003219 /* XXX: check any measured value ? */
3220
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003221 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3222 ctrl->timings[channel][slotrank].lanes[lane].falling =
3223 48;
3224 ctrl->timings[channel][slotrank].lanes[lane].rising =
3225 48;
3226 }
3227
3228 program_timings(ctrl, channel);
3229
3230 FOR_ALL_POPULATED_RANKS {
3231 wait_428c(channel);
3232
Patrick Rudolph371d2912015-10-09 13:33:25 +02003233 /* DRAM command MRS
3234 * MR3 enable MPR
3235 * write MR3 MPR enable
3236 * in this mode only RD and RDA are allowed
3237 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003238 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3239 0x1f000);
3240 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3241 0xc01 | (ctrl->tMOD << 16));
3242 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3243 (slotrank << 24) | 0x360004);
3244 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3245
Patrick Rudolph371d2912015-10-09 13:33:25 +02003246 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003247 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3248 0x1f105);
3249 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3250 0x4041003);
3251 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3252 (slotrank << 24) | 0);
3253 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3254
Patrick Rudolph371d2912015-10-09 13:33:25 +02003255 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003256 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3257 0x1f105);
3258 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3259 0x1001 | ((ctrl->CAS + 8) << 16));
3260 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3261 (slotrank << 24) | 0x60000);
3262 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3263
Patrick Rudolph371d2912015-10-09 13:33:25 +02003264 /* DRAM command MRS
3265 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003266 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3267 0x1f000);
3268 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3269 0xc01 | (ctrl->tMOD << 16));
3270 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3271 (slotrank << 24) | 0x360000);
3272 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3273
3274 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3275 0xc0001);
3276 wait_428c(channel);
3277 }
3278
Patrick Rudolph371d2912015-10-09 13:33:25 +02003279 /* XXX: check any measured value ? */
3280
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003281 FOR_ALL_LANES {
3282 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel +
3283 lane * 4,
3284 ~read32(DEFAULT_MCHBAR + 0x4040 +
3285 0x400 * channel + lane * 4) & 0xff);
3286 }
3287
3288 fill_pattern0(ctrl, channel, 0, 0xffffffff);
3289 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3290 }
3291
3292 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3293 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003294 printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003295
3296 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003297 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003298 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003299 if (err)
3300 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003301 }
3302
3303 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003304 printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003305
3306 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003307 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003308 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003309 if (err)
3310 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003311 }
3312
3313 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3314
3315 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3316 ctrl->timings[channel][slotrank].lanes[lane].falling =
3317 falling_edges[channel][slotrank][lane];
3318 ctrl->timings[channel][slotrank].lanes[lane].rising =
3319 rising_edges[channel][slotrank][lane];
3320 }
3321
3322 FOR_ALL_POPULATED_CHANNELS {
3323 program_timings(ctrl, channel);
3324 }
3325
3326 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3327 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3328 0);
3329 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003330 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003331}
3332
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003333static int discover_edges_write_real(ramctr_timing *ctrl, int channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003334 int slotrank, int *edges)
3335{
3336 int edge;
3337 u32 raw_statistics[MAX_EDGE_TIMING + 1];
3338 int statistics[MAX_EDGE_TIMING + 1];
3339 const int reg3000b24[] = { 0, 0xc, 0x2c };
3340 int lane, i;
3341 int lower[NUM_LANES];
3342 int upper[NUM_LANES];
3343 int pat;
3344
3345 FOR_ALL_LANES {
3346 lower[lane] = 0;
3347 upper[lane] = MAX_EDGE_TIMING;
3348 }
3349
3350 for (i = 0; i < 3; i++) {
3351 write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel,
3352 reg3000b24[i] << 24);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003353 printram("[%x] = 0x%08x\n",
3354 0x3000 + 0x100 * channel, reg3000b24[i] << 24);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003355 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3356 fill_pattern5(ctrl, channel, pat);
3357 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003358 printram("using pattern %d\n", pat);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003359 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3360 FOR_ALL_LANES {
3361 ctrl->timings[channel][slotrank].lanes[lane].
3362 rising = edge;
3363 ctrl->timings[channel][slotrank].lanes[lane].
3364 falling = edge;
3365 }
3366 program_timings(ctrl, channel);
3367
3368 FOR_ALL_LANES {
3369 write32(DEFAULT_MCHBAR + 0x4340 +
3370 0x400 * channel + 4 * lane, 0);
3371 read32(DEFAULT_MCHBAR + 0x400 * channel +
3372 4 * lane + 0x4140);
3373 }
3374 wait_428c(channel);
3375
Patrick Rudolph371d2912015-10-09 13:33:25 +02003376 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003377 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3378 0x1f006);
3379 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3380 0x4 | (ctrl->tRCD << 16)
3381 | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) <<
3382 10));
3383 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3384 (slotrank << 24) | 0x60000);
3385 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel,
3386 0x240);
3387
Patrick Rudolph371d2912015-10-09 13:33:25 +02003388 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003389 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3390 0x1f201);
3391 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3392 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) <<
3393 16));
3394 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3395 (slotrank << 24));
3396 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel,
3397 0x242);
3398
Patrick Rudolph371d2912015-10-09 13:33:25 +02003399 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003400 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3401 0x1f105);
3402 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3403 0x4005020 | (max(ctrl->tRTP, 8) << 16));
3404 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3405 (slotrank << 24));
3406 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel,
3407 0x242);
3408
Patrick Rudolph371d2912015-10-09 13:33:25 +02003409 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003410 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3411 0x1f002);
3412 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3413 0xc01 | (ctrl->tRP << 16));
3414 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3415 (slotrank << 24) | 0x60400);
3416 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3417
3418 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3419 0xc0001);
3420 wait_428c(channel);
3421 FOR_ALL_LANES {
3422 read32(DEFAULT_MCHBAR + 0x4340 +
3423 0x400 * channel + lane * 4);
3424 }
3425
3426 raw_statistics[edge] =
3427 MCHBAR32(0x436c + 0x400 * channel);
3428 }
3429 FOR_ALL_LANES {
3430 struct run rn;
3431 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++)
3432 statistics[edge] =
3433 ! !(raw_statistics[edge] & (1 << lane));
3434 rn = get_longest_zero_run(statistics,
3435 MAX_EDGE_TIMING + 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003436 printram("edges: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003437 channel, slotrank, i, rn.start, rn.middle,
3438 rn.end, rn.start + ctrl->edge_offset[i],
3439 rn.end - ctrl->edge_offset[i]);
3440 lower[lane] =
3441 max(rn.start + ctrl->edge_offset[i], lower[lane]);
3442 upper[lane] =
3443 min(rn.end - ctrl->edge_offset[i], upper[lane]);
3444 edges[lane] = (lower[lane] + upper[lane]) / 2;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003445 if (rn.all || (lower[lane] > upper[lane])) {
3446 printk(BIOS_EMERG, "edge write discovery failed: %d, %d, %d\n",
3447 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003448 return MAKE_ERR;
3449 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003450 }
3451 }
3452 }
3453
3454 write32(DEFAULT_MCHBAR + 0x3000, 0);
3455 printram("CPA\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003456 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003457}
3458
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003459static int discover_edges_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003460{
3461 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3462 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3463 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003464 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003465
3466 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3467 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003468 printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003469
3470 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003471 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003472 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003473 if (err)
3474 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003475 }
3476
3477 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003478 printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003479
3480 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003481 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003482 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003483 if (err)
3484 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003485 }
3486
3487 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3488
3489 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3490 ctrl->timings[channel][slotrank].lanes[lane].falling =
3491 falling_edges[channel][slotrank][lane];
3492 ctrl->timings[channel][slotrank].lanes[lane].rising =
3493 rising_edges[channel][slotrank][lane];
3494 }
3495
3496 FOR_ALL_POPULATED_CHANNELS
3497 program_timings(ctrl, channel);
3498
3499 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3500 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3501 0);
3502 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003503 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003504}
3505
3506static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
3507{
3508 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003509 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003510 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
3511 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3512 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD)
3513 << 10) | (ctrl->tRCD << 16) | 4);
3514 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3515 (slotrank << 24) | 0x60000);
3516 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
3517
Patrick Rudolph371d2912015-10-09 13:33:25 +02003518 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003519 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
3520 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3521 0x80011e0 |
3522 ((ctrl->tWTR + ctrl->CWL + 8) << 16));
3523 write32(DEFAULT_MCHBAR + 0x4204 +
3524 0x400 * channel, (slotrank << 24));
3525 write32(DEFAULT_MCHBAR + 0x4214 +
3526 0x400 * channel, 0x242);
3527
Patrick Rudolph371d2912015-10-09 13:33:25 +02003528 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003529 write32(DEFAULT_MCHBAR + 0x4228 +
3530 0x400 * channel, 0x1f105);
3531 write32(DEFAULT_MCHBAR + 0x4238 +
3532 0x400 * channel,
3533 0x40011e0 | (max(ctrl->tRTP, 8) << 16));
3534 write32(DEFAULT_MCHBAR + 0x4208 +
3535 0x400 * channel, (slotrank << 24));
3536 write32(DEFAULT_MCHBAR + 0x4218 +
3537 0x400 * channel, 0x242);
3538
Patrick Rudolph371d2912015-10-09 13:33:25 +02003539 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003540 write32(DEFAULT_MCHBAR + 0x422c +
3541 0x400 * channel, 0x1f002);
3542 write32(DEFAULT_MCHBAR + 0x423c +
3543 0x400 * channel,
3544 0x1001 | (ctrl->tRP << 16));
3545 write32(DEFAULT_MCHBAR + 0x420c +
3546 0x400 * channel,
3547 (slotrank << 24) | 0x60400);
3548 write32(DEFAULT_MCHBAR + 0x421c +
3549 0x400 * channel, 0);
3550
3551 write32(DEFAULT_MCHBAR + 0x4284 +
3552 0x400 * channel, 0xc0001);
3553 wait_428c(channel);
3554}
3555
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003556static int discover_timC_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003557{
3558 const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
3559 int i, pat;
3560
3561 int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3562 int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3563 int channel, slotrank, lane;
3564
3565 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3566 lower[channel][slotrank][lane] = 0;
3567 upper[channel][slotrank][lane] = MAX_TIMC;
3568 }
3569
3570 write32(DEFAULT_MCHBAR + 0x4ea8, 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003571 printram("discover timC write:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003572
3573 for (i = 0; i < 3; i++)
3574 FOR_ALL_POPULATED_CHANNELS {
3575 write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100),
3576 (rege3c_b24[i] << 24)
3577 | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100))
3578 & ~0x3f000000));
3579 udelay(2);
3580 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3581 FOR_ALL_POPULATED_RANKS {
3582 int timC;
3583 u32 raw_statistics[MAX_TIMC + 1];
3584 int statistics[MAX_TIMC + 1];
3585
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003586 /* Make sure rn.start < rn.end */
3587 statistics[MAX_TIMC] = 1;
3588
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003589 fill_pattern5(ctrl, channel, pat);
3590 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003591 for (timC = 0; timC < MAX_TIMC; timC++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003592 FOR_ALL_LANES
3593 ctrl->timings[channel][slotrank].lanes[lane].timC = timC;
3594 program_timings(ctrl, channel);
3595
3596 test_timC_write (ctrl, channel, slotrank);
3597
3598 raw_statistics[timC] =
3599 MCHBAR32(0x436c + 0x400 * channel);
3600 }
3601 FOR_ALL_LANES {
3602 struct run rn;
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003603 for (timC = 0; timC < MAX_TIMC; timC++)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003604 statistics[timC] =
3605 !!(raw_statistics[timC] &
3606 (1 << lane));
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003607
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003608 rn = get_longest_zero_run(statistics,
3609 MAX_TIMC + 1);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003610 if (rn.all) {
3611 printk(BIOS_EMERG, "timC write discovery failed: %d, %d, %d\n",
3612 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003613 return MAKE_ERR;
3614 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003615 printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003616 channel, slotrank, i, rn.start,
3617 rn.middle, rn.end,
3618 rn.start + ctrl->timC_offset[i],
3619 rn.end - ctrl->timC_offset[i]);
3620 lower[channel][slotrank][lane] =
3621 max(rn.start + ctrl->timC_offset[i],
3622 lower[channel][slotrank][lane]);
3623 upper[channel][slotrank][lane] =
3624 min(rn.end - ctrl->timC_offset[i],
3625 upper[channel][slotrank][lane]);
3626
3627 }
3628 }
3629 }
3630 }
3631
3632 FOR_ALL_CHANNELS {
3633 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3634 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3635 ~0x3f000000));
3636 udelay(2);
3637 }
3638
3639 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3640
3641 printram("CPB\n");
3642
3643 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
Patrick Rudolpha649a542016-01-17 18:32:06 +01003644 printram("timC %d, %d, %d: %x\n", channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003645 slotrank, lane,
3646 (lower[channel][slotrank][lane] +
3647 upper[channel][slotrank][lane]) / 2);
3648 ctrl->timings[channel][slotrank].lanes[lane].timC =
3649 (lower[channel][slotrank][lane] +
3650 upper[channel][slotrank][lane]) / 2;
3651 }
3652 FOR_ALL_POPULATED_CHANNELS {
3653 program_timings(ctrl, channel);
3654 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003655 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003656}
3657
3658static void normalize_training(ramctr_timing * ctrl)
3659{
3660 int channel, slotrank, lane;
3661 int mat = 0;
3662
3663 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3664 int delta;
3665 FOR_ALL_LANES mat =
3666 max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat);
3667 delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028;
3668 ctrl->timings[channel][slotrank].val_4024 += delta;
3669 ctrl->timings[channel][slotrank].val_4028 += delta;
3670 }
3671
3672 FOR_ALL_POPULATED_CHANNELS {
3673 program_timings(ctrl, channel);
3674 }
3675}
3676
3677static void write_controller_mr(ramctr_timing * ctrl)
3678{
3679 int channel, slotrank;
3680
3681 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3682 write32(DEFAULT_MCHBAR + 0x0004 + (channel << 8) +
3683 lane_registers[slotrank], make_mr0(ctrl, slotrank));
3684 write32(DEFAULT_MCHBAR + 0x0008 + (channel << 8) +
Patrick Rudolph7e513d12016-01-10 14:22:34 +01003685 lane_registers[slotrank],
3686 make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003687 }
3688}
3689
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003690static int channel_test(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003691{
3692 int channel, slotrank, lane;
3693
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003694 slotrank = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003695 FOR_ALL_POPULATED_CHANNELS
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003696 if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) {
3697 printk(BIOS_EMERG, "Mini channel test failed (1): %d\n",
3698 channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003699 return MAKE_ERR;
3700 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003701 FOR_ALL_POPULATED_CHANNELS {
3702 fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
3703
3704 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3705 }
3706
3707 for (slotrank = 0; slotrank < 4; slotrank++)
3708 FOR_ALL_CHANNELS
3709 if (ctrl->rankmap[channel] & (1 << slotrank)) {
3710 FOR_ALL_LANES {
3711 write32(DEFAULT_MCHBAR + (0x4f40 + 4 * lane), 0);
3712 write32(DEFAULT_MCHBAR + (0x4d40 + 4 * lane), 0);
3713 }
3714 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003715 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003716 write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
3717 write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10), 0x0028a004);
3718 write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
3719 0x00060000 | (slotrank << 24));
3720 write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003721 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003722 write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
3723 write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281064);
3724 write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
3725 0x00000000 | (slotrank << 24));
3726 write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003727 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003728 write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f105);
3729 write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x04281064);
3730 write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
3731 0x00000000 | (slotrank << 24));
3732 write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003733 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003734 write32(DEFAULT_MCHBAR + 0x422c + (channel << 10), 0x0001f002);
3735 write32(DEFAULT_MCHBAR + 0x423c + (channel << 10), 0x00280c01);
3736 write32(DEFAULT_MCHBAR + 0x420c + (channel << 10),
3737 0x00060400 | (slotrank << 24));
3738 write32(DEFAULT_MCHBAR + 0x421c + (channel << 10), 0x00000240);
3739 write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
3740 wait_428c(channel);
3741 FOR_ALL_LANES
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003742 if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) {
3743 printk(BIOS_EMERG, "Mini channel test failed (2): %d, %d, %d\n",
3744 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003745 return MAKE_ERR;
3746 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003747 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003748 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003749}
3750
3751static void set_scrambling_seed(ramctr_timing * ctrl)
3752{
3753 int channel;
3754
3755 /* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
3756 I don't think so. */
3757 static u32 seeds[NUM_CHANNELS][3] = {
3758 {0x00009a36, 0xbafcfdcf, 0x46d1ab68},
3759 {0x00028bfa, 0x53fe4b49, 0x19ed5483}
3760 };
3761 FOR_ALL_POPULATED_CHANNELS {
3762 MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
3763 write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
3764 write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
3765 write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
3766 }
3767}
3768
3769static void set_4f8c(void)
3770{
3771 struct cpuid_result cpures;
3772 u32 cpu;
3773
3774 cpures = cpuid(0);
3775 cpu = (cpures.eax);
3776 if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) {
3777 MCHBAR32(0x4f8c) = 0x141D1519;
3778 } else {
3779 MCHBAR32(0x4f8c) = 0x551D1519;
3780 }
3781}
3782
3783static void prepare_training(ramctr_timing * ctrl)
3784{
3785 int channel;
3786
3787 FOR_ALL_POPULATED_CHANNELS {
3788 // Always drive command bus
3789 MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000;
3790 }
3791
3792 udelay(1);
3793
3794 FOR_ALL_POPULATED_CHANNELS {
3795 wait_428c(channel);
3796 }
3797}
3798
3799static void set_4008c(ramctr_timing * ctrl)
3800{
3801 int channel, slotrank;
3802 u32 reg;
3803 FOR_ALL_POPULATED_CHANNELS {
3804 u32 b20, b4_8_12;
3805 int min_320c = 10000;
3806 int max_320c = -10000;
3807
3808 FOR_ALL_POPULATED_RANKS {
3809 max_320c = max(ctrl->timings[channel][slotrank].val_320c, max_320c);
3810 min_320c = min(ctrl->timings[channel][slotrank].val_320c, min_320c);
3811 }
3812
3813 if (max_320c - min_320c > 51)
3814 b20 = 0;
3815 else
3816 b20 = ctrl->ref_card_offset[channel];
3817
3818 if (ctrl->reg_320c_range_threshold < max_320c - min_320c)
3819 b4_8_12 = 0x3330;
3820 else
3821 b4_8_12 = 0x2220;
3822
3823 reg = read32(DEFAULT_MCHBAR + 0x400c + (channel << 10));
3824 write32(DEFAULT_MCHBAR + 0x400c + (channel << 10),
3825 (reg & 0xFFF0FFFF)
3826 | (ctrl->ref_card_offset[channel] << 16)
3827 | (ctrl->ref_card_offset[channel] << 18));
3828 write32(DEFAULT_MCHBAR + 0x4008 + (channel << 10),
3829 0x0a000000
3830 | (b20 << 20)
3831 | ((ctrl->ref_card_offset[channel] + 2) << 16)
3832 | b4_8_12);
3833 }
3834}
3835
3836static void set_42a0(ramctr_timing * ctrl)
3837{
3838 int channel;
3839 FOR_ALL_POPULATED_CHANNELS {
3840 write32(DEFAULT_MCHBAR + (0x42a0 + 0x400 * channel),
3841 0x00001000 | ctrl->rankmap[channel]);
3842 MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK
3843 }
3844}
3845
3846static int encode_5d10(int ns)
3847{
3848 return (ns + 499) / 500;
3849}
3850
3851/* FIXME: values in this function should be hardware revision-dependent. */
3852static void final_registers(ramctr_timing * ctrl)
3853{
3854 int channel;
3855 int t1_cycles = 0, t1_ns = 0, t2_ns;
3856 int t3_ns;
3857 u32 r32;
3858
3859 write32(DEFAULT_MCHBAR + 0x4cd4, 0x00000046);
3860
3861 write32(DEFAULT_MCHBAR + 0x400c, (read32(DEFAULT_MCHBAR + 0x400c) & 0xFFFFCFFF) | 0x1000); // OK
3862 write32(DEFAULT_MCHBAR + 0x440c, (read32(DEFAULT_MCHBAR + 0x440c) & 0xFFFFCFFF) | 0x1000); // OK
3863 write32(DEFAULT_MCHBAR + 0x4cb0, 0x00000740);
3864 write32(DEFAULT_MCHBAR + 0x4380, 0x00000aaa); // OK
3865 write32(DEFAULT_MCHBAR + 0x4780, 0x00000aaa); // OK
3866 write32(DEFAULT_MCHBAR + 0x4f88, 0x5f7003ff); // OK
3867 write32(DEFAULT_MCHBAR + 0x5064, 0x00073000 | ctrl->reg_5064b0); // OK
3868
3869 FOR_ALL_CHANNELS {
3870 switch (ctrl->rankmap[channel]) {
3871 /* Unpopulated channel. */
3872 case 0:
3873 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0);
3874 break;
3875 /* Only single-ranked dimms. */
3876 case 1:
3877 case 4:
3878 case 5:
3879 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x373131);
3880 break;
3881 /* Dual-ranked dimms present. */
3882 default:
3883 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x9b6ea1);
3884 break;
3885 }
3886 }
3887
3888 write32 (DEFAULT_MCHBAR + 0x5880, 0xca9171e5);
3889 write32 (DEFAULT_MCHBAR + 0x5888,
3890 (read32 (DEFAULT_MCHBAR + 0x5888) & ~0xffffff) | 0xe4d5d0);
3891 write32 (DEFAULT_MCHBAR + 0x58a8, read32 (DEFAULT_MCHBAR + 0x58a8) & ~0x1f);
3892 write32 (DEFAULT_MCHBAR + 0x4294,
3893 (read32 (DEFAULT_MCHBAR + 0x4294) & ~0x30000)
3894 | (1 << 16));
3895 write32 (DEFAULT_MCHBAR + 0x4694,
3896 (read32 (DEFAULT_MCHBAR + 0x4694) & ~0x30000)
3897 | (1 << 16));
3898
3899 MCHBAR32(0x5030) |= 1; // OK
3900 MCHBAR32(0x5030) |= 0x80; // OK
3901 MCHBAR32(0x5f18) = 0xfa; // OK
3902
3903 /* Find a populated channel. */
3904 FOR_ALL_POPULATED_CHANNELS
3905 break;
3906
3907 t1_cycles = ((read32(DEFAULT_MCHBAR + 0x4290 + channel * 0x400) >> 8) & 0xff);
3908 r32 = read32(DEFAULT_MCHBAR + 0x5064);
3909 if (r32 & 0x20000)
3910 t1_cycles += (r32 & 0xfff);
3911 t1_cycles += (read32(DEFAULT_MCHBAR + channel * 0x400 + 0x42a4) & 0xfff);
3912 t1_ns = t1_cycles * ctrl->tCK / 256 + 544;
3913 if (!(r32 & 0x20000))
3914 t1_ns += 500;
3915
3916 t2_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f10) >> 8) & 0xfff);
3917 if ( read32(DEFAULT_MCHBAR + 0x5f00) & 8 )
3918 {
3919 t3_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f20) >> 8) & 0xfff);
3920 t3_ns += 10 * (read32(DEFAULT_MCHBAR + 0x5f18) & 0xff);
3921 }
3922 else
3923 {
3924 t3_ns = 500;
3925 }
3926 printk(BIOS_DEBUG, "t123: %d, %d, %d\n",
3927 t1_ns, t2_ns, t3_ns);
3928 write32 (DEFAULT_MCHBAR + 0x5d10,
3929 ((encode_5d10(t1_ns) + encode_5d10(t2_ns)) << 16)
3930 | (encode_5d10(t1_ns) << 8)
3931 | ((encode_5d10(t3_ns) + encode_5d10(t2_ns) + encode_5d10(t1_ns)) << 24)
3932 | (read32(DEFAULT_MCHBAR + 0x5d10) & 0xC0C0C0C0)
3933 | 0xc);
3934}
3935
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003936static void save_timings(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003937{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003938 /* Save the MRC S3 restore data to cbmem */
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003939 store_current_mrc_cache(ctrl, sizeof(*ctrl));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003940}
3941
3942static void restore_timings(ramctr_timing * ctrl)
3943{
3944 int channel, slotrank, lane;
3945
3946 FOR_ALL_POPULATED_CHANNELS
3947 MCHBAR32(0x4004 + 0x400 * channel) =
3948 ctrl->tRRD
3949 | (ctrl->tRTP << 4)
3950 | (ctrl->tCKE << 8)
3951 | (ctrl->tWTR << 12)
3952 | (ctrl->tFAW << 16)
3953 | (ctrl->tWR << 24)
3954 | (ctrl->cmd_stretch[channel] << 30);
3955
3956 udelay(1);
3957
3958 FOR_ALL_POPULATED_CHANNELS {
3959 wait_428c(channel);
3960 }
3961
3962 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3963 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
3964 + 4 * lane, 0);
3965 }
3966
3967 FOR_ALL_POPULATED_CHANNELS
3968 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
3969 read32(DEFAULT_MCHBAR + 0x4008 +
3970 0x400 * channel) | 0x8000000);
3971
3972 FOR_ALL_POPULATED_CHANNELS {
3973 udelay (1);
3974 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
3975 read32(DEFAULT_MCHBAR + 0x4020 +
3976 0x400 * channel) | 0x200000);
3977 }
3978
3979 printram("CPE\n");
3980
3981 write32(DEFAULT_MCHBAR + 0x3400, 0);
3982 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3983
3984 printram("CP5b\n");
3985
3986 FOR_ALL_POPULATED_CHANNELS {
3987 program_timings(ctrl, channel);
3988 }
3989
3990 u32 reg, addr;
3991
3992 while (!(MCHBAR32(0x5084) & 0x10000)) ;
3993 do {
3994 reg = MCHBAR32(0x428c);
3995 } while ((reg & 0x14) == 0);
3996
3997 // Set state of memory controller
3998 MCHBAR32(0x5030) = 0x116;
3999 MCHBAR32(0x4ea0) = 0;
4000
4001 // Wait 500us
4002 udelay(500);
4003
4004 FOR_ALL_CHANNELS {
4005 // Set valid rank CKE
4006 reg = 0;
4007 reg = (reg & ~0xf) | ctrl->rankmap[channel];
4008 addr = 0x400 * channel + 0x42a0;
4009 MCHBAR32(addr) = reg;
4010
4011 // Wait 10ns for ranks to settle
4012 //udelay(0.01);
4013
4014 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
4015 MCHBAR32(addr) = reg;
4016
4017 // Write reset using a NOP
4018 write_reset(ctrl);
4019 }
4020
4021 /* mrs commands. */
4022 dram_mrscommands(ctrl);
4023
4024 printram("CP5c\n");
4025
4026 write32(DEFAULT_MCHBAR + 0x3000, 0);
4027
4028 FOR_ALL_CHANNELS {
4029 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
4030 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
4031 ~0x3f000000));
4032 udelay(2);
4033 }
4034
4035 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
4036}
4037
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004038static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot,
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004039 int s3_resume, int me_uma_size)
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004040{
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004041 int err;
4042
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004043 printk(BIOS_DEBUG, "Starting RAM training (%d).\n", fast_boot);
4044
4045 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004046 /* Find fastest common supported parameters */
4047 dram_find_common_params(ctrl);
4048
4049 dram_dimm_mapping(ctrl);
4050 }
4051
4052 /* Set MCU frequency */
4053 dram_freq(ctrl);
4054
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004055 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004056 /* Calculate timings */
4057 dram_timing(ctrl);
4058 }
4059
4060 /* Set version register */
4061 MCHBAR32(0x5034) = 0xC04EB002;
4062
4063 /* Enable crossover */
4064 dram_xover(ctrl);
4065
4066 /* Set timing and refresh registers */
4067 dram_timing_regs(ctrl);
4068
4069 /* Power mode preset */
4070 MCHBAR32(0x4e80) = 0x5500;
4071
4072 /* Set scheduler parameters */
4073 MCHBAR32(0x4c20) = 0x10100005;
4074
4075 /* Set cpu specific register */
4076 set_4f8c();
4077
4078 /* Clear IO reset bit */
4079 MCHBAR32(0x5030) &= ~0x20;
4080
4081 /* Set MAD-DIMM registers */
4082 dram_dimm_set_mapping(ctrl);
4083 printk(BIOS_DEBUG, "Done dimm mapping\n");
4084
4085 /* Zone config */
4086 dram_zones(ctrl, 1);
4087
4088 /* Set memory map */
4089 dram_memorymap(ctrl, me_uma_size);
4090 printk(BIOS_DEBUG, "Done memory map\n");
4091
4092 /* Set IO registers */
4093 dram_ioregs(ctrl);
4094 printk(BIOS_DEBUG, "Done io registers\n");
4095
4096 udelay(1);
4097
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004098 if (fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004099 restore_timings(ctrl);
4100 } else {
4101 /* Do jedec ddr3 reset sequence */
4102 dram_jedecreset(ctrl);
4103 printk(BIOS_DEBUG, "Done jedec reset\n");
4104
4105 /* MRS commands */
4106 dram_mrscommands(ctrl);
4107 printk(BIOS_DEBUG, "Done MRS commands\n");
4108
4109 /* Prepare for memory training */
4110 prepare_training(ctrl);
4111
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004112 err = read_training(ctrl);
4113 if (err)
4114 return err;
4115
4116 err = write_training(ctrl);
4117 if (err)
4118 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004119
4120 printram("CP5a\n");
4121
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004122 err = discover_edges(ctrl);
4123 if (err)
4124 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004125
4126 printram("CP5b\n");
4127
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004128 err = command_training(ctrl);
4129 if (err)
4130 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004131
4132 printram("CP5c\n");
4133
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004134 err = discover_edges_write(ctrl);
4135 if (err)
4136 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004137
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004138 err = discover_timC_write(ctrl);
4139 if (err)
4140 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004141
4142 normalize_training(ctrl);
4143 }
4144
4145 set_4008c(ctrl);
4146
4147 write_controller_mr(ctrl);
4148
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004149 if (!s3_resume) {
4150 err = channel_test(ctrl);
4151 if (err)
4152 return err;
4153 }
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004154
4155 return 0;
4156}
4157
4158void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004159 int s3resume)
4160{
4161 int me_uma_size;
4162 int cbmem_was_inited;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004163 ramctr_timing ctrl;
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004164 int fast_boot;
4165 struct mrc_data_container *mrc_cache;
4166 ramctr_timing *ctrl_cached;
Patrick Rudolph31d19592016-03-26 12:22:34 +01004167 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004168
4169 MCHBAR32(0x5f00) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004170
Vadim Bendebury7a3f36a2012-04-18 15:47:32 -07004171 report_platform_info();
4172
Stefan Reinauer00636b02012-04-04 00:08:51 +02004173 /* Wait for ME to be ready */
4174 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004175 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004176
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004177 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +02004178
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004179 u32 reg_5d10;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004180
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004181 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004182
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004183 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +02004184
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004185 reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10); // !!! = 0x00000000
4186 if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */
4187 && reg_5d10 && !s3resume) {
4188 write32(DEFAULT_MCHBAR + 0x5d10, 0);
4189 /* Need reset. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02004190 outb(0x6, 0xcf9);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004191
Patrick Georgi546953c2014-11-29 10:38:17 +01004192 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004193 }
Stefan Reinauer00636b02012-04-04 00:08:51 +02004194
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004195 memset(&ctrl, 0, sizeof (ctrl));
4196
4197 early_pch_init_native();
4198 early_thermal_init();
4199
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004200 /* try to find timings in MRC cache */
4201 mrc_cache = find_current_mrc_cache();
4202 if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(ctrl))) {
4203 if (s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004204 /* Failed S3 resume, reset to come up cleanly */
4205 outb(0x6, 0xcf9);
4206 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004207 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004208 ctrl_cached = NULL;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004209 } else {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004210 ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004211 }
4212
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004213 /* verify MRC cache for fast boot */
4214 if (ctrl_cached) {
4215 /* check SPD CRC16 to make sure the DIMMs haven't been replaced */
4216 fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
4217 if (!fast_boot)
4218 printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
4219 if (!fast_boot && s3resume) {
4220 /* Failed S3 resume, reset to come up cleanly */
4221 outb(0x6, 0xcf9);
4222 halt();
4223 }
4224 } else
4225 fast_boot = 0;
4226
4227 if (fast_boot) {
4228 printk(BIOS_DEBUG, "Trying stored timings.\n");
4229 memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
4230
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004231 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004232 if (err) {
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004233 if (s3resume) {
4234 /* Failed S3 resume, reset to come up cleanly */
4235 outb(0x6, 0xcf9);
4236 halt();
4237 }
4238 /* no need to erase bad mrc cache here, it gets overwritten on
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004239 * successful boot. */
4240 printk(BIOS_ERR, "Stored timings are invalid !\n");
4241 fast_boot = 0;
4242 }
4243 }
4244 if (!fast_boot) {
4245 ctrl.mobile = mobile;
4246 ctrl.tCK = min_tck;
4247
4248 /* Get DDR3 SPD data */
4249 dram_find_spds_ddr3(spds, &ctrl);
4250
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004251 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004252 }
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004253
4254 if (err && (ctrl.tCK < TCK_400MHZ)) {
4255 /* fallback: lower clock frequency */
4256 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
4257 printram("Decreasing clock frequency.\n");
4258 ctrl.tCK++;
4259 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
4260 }
4261
4262 if (err && (ctrl.tCK < TCK_400MHZ)) {
4263 /* fallback: lower clock frequency */
4264 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
4265 printram("Decreasing clock frequency.\n");
4266 ctrl.tCK++;
4267 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
4268 }
4269
4270 if (err) {
4271 /* fallback: disable failing channel */
4272 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
4273 printram("Disable failing channel.\n");
4274
4275 /* Reset DDR3 frequency */
4276 dram_find_spds_ddr3(spds, &ctrl);
4277
4278 /* disable failing channel */
4279 disable_channel(&ctrl, GET_ERR_CHANNEL(err));
4280
4281 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
4282 }
4283
Patrick Rudolph31d19592016-03-26 12:22:34 +01004284 if (err)
4285 die("raminit failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004286
4287 /* FIXME: should be hardware revision-dependent. */
4288 write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
4289
4290 set_scrambling_seed(&ctrl);
4291
4292 set_42a0(&ctrl);
4293
4294 final_registers(&ctrl);
4295
4296 /* Zone config */
4297 dram_zones(&ctrl, 0);
4298
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004299 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004300 quick_ram_check();
4301
4302 intel_early_me_status();
4303 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
4304 intel_early_me_status();
4305
Stefan Reinauer00636b02012-04-04 00:08:51 +02004306 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004307
4308 cbmem_was_inited = !cbmem_recovery(s3resume);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004309 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004310 save_timings(&ctrl);
4311 if (s3resume && !cbmem_was_inited) {
4312 /* Failed S3 resume, reset to come up cleanly */
4313 outb(0x6, 0xcf9);
4314 halt();
4315 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +01004316
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004317 fill_smbios17(&ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004318}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004319
4320#define HOST_BRIDGE PCI_DEVFN(0, 0)
4321#define DEFAULT_TCK TCK_800MHZ
4322
4323static unsigned int get_mem_min_tck(void)
4324{
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004325 u32 reg32;
4326 u8 rev;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004327 const struct device *dev;
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004328 const struct northbridge_intel_sandybridge_config *cfg = NULL;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004329
4330 dev = dev_find_slot(0, HOST_BRIDGE);
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004331 if (dev)
4332 cfg = dev->chip_info;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004333
4334 /* If this is zero, it just means devicetree.cb didn't set it */
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004335 if (!cfg || cfg->max_mem_clock_mhz == 0) {
4336 rev = pci_read_config8(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004337
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004338 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
4339 /* read Capabilities A Register DMFC bits */
4340 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A);
4341 reg32 &= 0x7;
4342
4343 switch (reg32) {
4344 case 7: return TCK_533MHZ;
4345 case 6: return TCK_666MHZ;
4346 case 5: return TCK_800MHZ;
4347 /* reserved: */
4348 default:
4349 break;
4350 }
4351 } else {
4352 /* read Capabilities B Register DMFC bits */
4353 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
4354 reg32 = (reg32 >> 4) & 0x7;
4355
4356 switch (reg32) {
4357 case 7: return TCK_533MHZ;
4358 case 6: return TCK_666MHZ;
4359 case 5: return TCK_800MHZ;
4360 case 4: return TCK_933MHZ;
4361 case 3: return TCK_1066MHZ;
4362 case 2: return TCK_1200MHZ;
4363 case 1: return TCK_1333MHZ;
4364 /* reserved: */
4365 default:
4366 break;
4367 }
4368 }
4369 return DEFAULT_TCK;
4370 } else {
Patrick Rudolph7bddd302016-06-11 18:39:35 +02004371 if (cfg->max_mem_clock_mhz >= 1066)
4372 return TCK_1066MHZ;
4373 else if (cfg->max_mem_clock_mhz >= 933)
4374 return TCK_933MHZ;
4375 else if (cfg->max_mem_clock_mhz >= 800)
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004376 return TCK_800MHZ;
4377 else if (cfg->max_mem_clock_mhz >= 666)
4378 return TCK_666MHZ;
4379 else if (cfg->max_mem_clock_mhz >= 533)
4380 return TCK_533MHZ;
4381 else
4382 return TCK_400MHZ;
4383 }
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004384}
4385
Patrick Rudolph266a1f72016-06-09 18:13:34 +02004386#define DEFAULT_PCI_MMIO_SIZE 2048
4387
4388static unsigned int get_mmio_size(void)
4389{
4390 const struct device *dev;
4391 const struct northbridge_intel_sandybridge_config *cfg = NULL;
4392
4393 dev = dev_find_slot(0, HOST_BRIDGE);
4394 if (dev)
4395 cfg = dev->chip_info;
4396
4397 /* If this is zero, it just means devicetree.cb didn't set it */
4398 if (!cfg || cfg->pci_mmio_size == 0)
4399 return DEFAULT_PCI_MMIO_SIZE;
4400 else
4401 return cfg->pci_mmio_size;
4402}
4403
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004404void perform_raminit(int s3resume)
4405{
4406 spd_raw_data spd[4];
4407
4408 post_code(0x3a);
4409
4410 memset (spd, 0, sizeof (spd));
4411 mainboard_get_spd(spd);
4412
4413 timestamp_add_now(TS_BEFORE_INITRAM);
4414
4415 init_dram_ddr3(spd, 1, get_mem_min_tck(), s3resume);
4416}