blob: 166416e287f5395f2a35be0ef39d55da31084516 [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
Martin Roth128c1042016-11-18 09:29:03 -070074 * Bit 16-32: number of clock-cycles to idle
Patrick Rudolph371d2912015-10-09 13:33:25 +020075 *
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
Patrick Rudolph2966c992016-11-19 15:46:42 +0100202#define MAX_CAS 18
203#define MIN_CAS 4
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700204
Patrick Rudolph24a845b2016-03-25 18:19:47 +0100205#define MAKE_ERR ((channel<<16)|(slotrank<<8)|1)
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100206#define GET_ERR_CHANNEL(x) (x>>16)
Patrick Rudolph24a845b2016-03-25 18:19:47 +0100207
Patrick Rudolph069018d2016-11-12 11:43:59 +0100208#define MC_BIOS_REQ 0x5e00
209#define MC_BIOS_DATA 0x5e04
210
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700211static void program_timings(ramctr_timing * ctrl, int channel);
Patrick Rudolph266a1f72016-06-09 18:13:34 +0200212static unsigned int get_mmio_size(void);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700213
214static const char *ecc_decoder[] = {
Stefan Reinauer00636b02012-04-04 00:08:51 +0200215 "inactive",
216 "active on IO",
217 "disabled on IO",
218 "active"
219};
220
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700221static void wait_txt_clear(void)
222{
223 struct cpuid_result cp;
224
225 cp = cpuid_ext(0x1, 0x0);
226 /* Check if TXT is supported? */
227 if (!(cp.ecx & 0x40))
228 return;
229 /* Some TXT public bit. */
230 if (!(read32((void *)0xfed30010) & 1))
231 return;
232 /* Wait for TXT clear. */
Elyes HAOUAS7db506c2016-10-02 11:56:39 +0200233 while (!(read8((void *)0xfed40000) & (1 << 7)));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700234}
235
236static void sfence(void)
237{
238 asm volatile ("sfence");
239}
240
Patrick Rudolph9b515682015-10-09 13:43:51 +0200241static void toggle_io_reset(void) {
242 /* toggle IO reset bit */
243 u32 r32 = read32(DEFAULT_MCHBAR + 0x5030);
244 write32(DEFAULT_MCHBAR + 0x5030, r32 | 0x20);
245 udelay(1);
246 write32(DEFAULT_MCHBAR + 0x5030, r32 & ~0x20);
247 udelay(1);
248}
249
Stefan Reinauer00636b02012-04-04 00:08:51 +0200250/*
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100251 * Disable a channel in ramctr_timing.
252 */
253static void disable_channel(ramctr_timing *ctrl, int channel) {
254 ctrl->rankmap[channel] = 0;
255 memset(&ctrl->rank_mirror[channel][0], 0, sizeof(ctrl->rank_mirror[0]));
256 ctrl->channel_size_mb[channel] = 0;
257 ctrl->cmd_stretch[channel] = 0;
258 ctrl->mad_dimm[channel] = 0;
259 memset(&ctrl->timings[channel][0], 0, sizeof(ctrl->timings[0]));
Patrick Rudolph74163d62016-11-17 20:02:43 +0100260 memset(&ctrl->info.dimm[channel][0], 0, sizeof(ctrl->info.dimm[0]));
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100261}
262
263/*
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100264 * Fill cbmem with information for SMBIOS type 17.
265 */
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100266static void fill_smbios17(ramctr_timing *ctrl)
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100267{
268 struct memory_info *mem_info;
269 int channel, slot;
270 struct dimm_info *dimm;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100271 uint16_t ddr_freq;
272 dimm_info *info = &ctrl->info;
273
274 ddr_freq = (1000 << 8) / ctrl->tCK;
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100275
276 /*
277 * Allocate CBMEM area for DIMM information used to populate SMBIOS
278 * table 17
279 */
280 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
281 printk(BIOS_DEBUG, "CBMEM entry for DIMM info: 0x%p\n", mem_info);
282 if (!mem_info)
283 return;
284
285 memset(mem_info, 0, sizeof(*mem_info));
286
Elyes HAOUAS12df9502016-08-23 21:29:48 +0200287 FOR_ALL_CHANNELS for (slot = 0; slot < NUM_SLOTS; slot++) {
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100288 dimm = &mem_info->dimm[mem_info->dimm_cnt];
289 if (info->dimm[channel][slot].size_mb) {
290 dimm->ddr_type = MEMORY_TYPE_DDR3;
291 dimm->ddr_frequency = ddr_freq;
292 dimm->dimm_size = info->dimm[channel][slot].size_mb;
293 dimm->channel_num = channel;
294 dimm->rank_per_dimm = info->dimm[channel][slot].ranks;
295 dimm->dimm_num = slot;
296 memcpy(dimm->module_part_number,
297 info->dimm[channel][slot].part_number, 16);
298 dimm->mod_id = info->dimm[channel][slot].manufacturer_id;
299 dimm->mod_type = info->dimm[channel][slot].dimm_type;
300 dimm->bus_width = info->dimm[channel][slot].width;
301 mem_info->dimm_cnt++;
302 }
303 }
304}
305
306/*
Stefan Reinauer00636b02012-04-04 00:08:51 +0200307 * Dump in the log memory controller configuration as read from the memory
308 * controller registers.
309 */
310static void report_memory_config(void)
311{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700312 u32 addr_decoder_common, addr_decode_ch[NUM_CHANNELS];
Stefan Reinauer00636b02012-04-04 00:08:51 +0200313 int i;
314
315 addr_decoder_common = MCHBAR32(0x5000);
316 addr_decode_ch[0] = MCHBAR32(0x5004);
317 addr_decode_ch[1] = MCHBAR32(0x5008);
318
319 printk(BIOS_DEBUG, "memcfg DDR3 clock %d MHz\n",
Patrick Rudolph069018d2016-11-12 11:43:59 +0100320 (MCHBAR32(MC_BIOS_DATA) * 13333 * 2 + 50) / 100);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200321 printk(BIOS_DEBUG, "memcfg channel assignment: A: %d, B % d, C % d\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700322 addr_decoder_common & 3, (addr_decoder_common >> 2) & 3,
Stefan Reinauer00636b02012-04-04 00:08:51 +0200323 (addr_decoder_common >> 4) & 3);
324
325 for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
326 u32 ch_conf = addr_decode_ch[i];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700327 printk(BIOS_DEBUG, "memcfg channel[%d] config (%8.8x):\n", i,
328 ch_conf);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200329 printk(BIOS_DEBUG, " ECC %s\n",
330 ecc_decoder[(ch_conf >> 24) & 3]);
331 printk(BIOS_DEBUG, " enhanced interleave mode %s\n",
332 ((ch_conf >> 22) & 1) ? "on" : "off");
333 printk(BIOS_DEBUG, " rank interleave %s\n",
334 ((ch_conf >> 21) & 1) ? "on" : "off");
335 printk(BIOS_DEBUG, " DIMMA %d MB width x%d %s rank%s\n",
336 ((ch_conf >> 0) & 0xff) * 256,
337 ((ch_conf >> 19) & 1) ? 16 : 8,
338 ((ch_conf >> 17) & 1) ? "dual" : "single",
339 ((ch_conf >> 16) & 1) ? "" : ", selected");
340 printk(BIOS_DEBUG, " DIMMB %d MB width x%d %s rank%s\n",
341 ((ch_conf >> 8) & 0xff) * 256,
342 ((ch_conf >> 20) & 1) ? 16 : 8,
343 ((ch_conf >> 18) & 1) ? "dual" : "single",
344 ((ch_conf >> 16) & 1) ? ", selected" : "");
345 }
346}
347
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100348/*
349 * Return CRC16 match for all SPDs.
350 */
351static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
352{
353 int channel, slot, spd_slot;
354 int match = 1;
355
356 FOR_ALL_CHANNELS {
357 for (slot = 0; slot < NUM_SLOTS; slot++) {
358 spd_slot = 2 * channel + slot;
359 match &= ctrl->spd_crc[channel][slot] ==
Kyösti Mälkkifc5d85c2016-11-18 18:52:04 +0200360 spd_ddr3_calc_unique_crc(spd[spd_slot], sizeof(spd_raw_data));
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100361 }
362 }
363 return match;
364}
365
Kyösti Mälkkie258b9a2016-11-18 19:59:23 +0200366void read_spd(spd_raw_data * spd, u8 addr, bool id_only)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200367{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700368 int j;
Kyösti Mälkkie258b9a2016-11-18 19:59:23 +0200369 if (id_only) {
370 for (j = 117; j < 128; j++)
371 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
372 } else {
373 for (j = 0; j < 256; j++)
374 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
375 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700376}
377
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100378static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700379{
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100380 int dimms = 0, dimms_on_channel;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700381 int channel, slot, spd_slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100382 dimm_info *dimm = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700383
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +0200384 memset (ctrl->rankmap, 0, sizeof(ctrl->rankmap));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700385
386 ctrl->extended_temperature_range = 1;
387 ctrl->auto_self_refresh = 1;
388
389 FOR_ALL_CHANNELS {
390 ctrl->channel_size_mb[channel] = 0;
391
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100392 dimms_on_channel = 0;
393 /* count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700394 for (slot = 0; slot < NUM_SLOTS; slot++) {
395 spd_slot = 2 * channel + slot;
396 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100397 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
398 dimms_on_channel++;
399 }
400
401 for (slot = 0; slot < NUM_SLOTS; slot++) {
402 spd_slot = 2 * channel + slot;
403 /* search for XMP profile */
404 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot],
405 spd[spd_slot],
406 DDR3_XMP_PROFILE_1);
407
408 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
409 printram("No valid XMP profile found.\n");
410 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
411 } else if (dimms_on_channel > dimm->dimm[channel][slot].dimms_per_channel) {
412 printram("XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
413 dimm->dimm[channel][slot].dimms_per_channel,
414 dimms_on_channel);
415 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
416 } else if (dimm->dimm[channel][slot].voltage != 1500) {
417 /* TODO: support other DDR3 voltage than 1500mV */
418 printram("XMP profile's requested %u mV is unsupported.\n",
419 dimm->dimm[channel][slot].voltage);
420 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
421 }
422
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100423 /* fill in CRC16 for MRC cache */
424 ctrl->spd_crc[channel][slot] =
Kyösti Mälkkifc5d85c2016-11-18 18:52:04 +0200425 spd_ddr3_calc_unique_crc(spd[spd_slot], sizeof(spd_raw_data));
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100426
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700427 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
428 // set dimm invalid
429 dimm->dimm[channel][slot].ranks = 0;
430 dimm->dimm[channel][slot].size_mb = 0;
431 continue;
432 }
433
434 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
435 dimms++;
436 ctrl->rank_mirror[channel][slot * 2] = 0;
437 ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored;
438 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
439
440 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
441 ctrl->extended_temperature_range &= dimm->dimm[channel][slot].flags.ext_temp_refresh;
442
443 ctrl->rankmap[channel] |= ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100444 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n",
445 channel, ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700446 }
447 if ((ctrl->rankmap[channel] & 3) && (ctrl->rankmap[channel] & 0xc)
448 && dimm->dimm[channel][0].reference_card <= 5 && dimm->dimm[channel][1].reference_card <= 5) {
449 const int ref_card_offset_table[6][6] = {
450 { 0, 0, 0, 0, 2, 2, },
451 { 0, 0, 0, 0, 2, 2, },
452 { 0, 0, 0, 0, 2, 2, },
453 { 0, 0, 0, 0, 1, 1, },
454 { 2, 2, 2, 1, 0, 0, },
455 { 2, 2, 2, 1, 0, 0, },
456 };
457 ctrl->ref_card_offset[channel] = ref_card_offset_table[dimm->dimm[channel][0].reference_card]
458 [dimm->dimm[channel][1].reference_card];
459 } else
460 ctrl->ref_card_offset[channel] = 0;
461 }
462
463 if (!dimms)
464 die("No DIMMs were found");
465}
466
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100467static void dram_find_common_params(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700468{
469 size_t valid_dimms;
470 int channel, slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100471 dimm_info *dimms = &ctrl->info;
472
Patrick Rudolph2966c992016-11-19 15:46:42 +0100473 ctrl->cas_supported = (1 << (MAX_CAS - MIN_CAS + 1)) - 1;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700474 valid_dimms = 0;
475 FOR_ALL_CHANNELS for (slot = 0; slot < 2; slot++) {
476 const dimm_attr *dimm = &dimms->dimm[channel][slot];
477 if (dimm->dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3)
478 continue;
479 valid_dimms++;
480
481 /* Find all possible CAS combinations */
482 ctrl->cas_supported &= dimm->cas_supported;
483
484 /* Find the smallest common latencies supported by all DIMMs */
485 ctrl->tCK = MAX(ctrl->tCK, dimm->tCK);
486 ctrl->tAA = MAX(ctrl->tAA, dimm->tAA);
487 ctrl->tWR = MAX(ctrl->tWR, dimm->tWR);
488 ctrl->tRCD = MAX(ctrl->tRCD, dimm->tRCD);
489 ctrl->tRRD = MAX(ctrl->tRRD, dimm->tRRD);
490 ctrl->tRP = MAX(ctrl->tRP, dimm->tRP);
491 ctrl->tRAS = MAX(ctrl->tRAS, dimm->tRAS);
492 ctrl->tRFC = MAX(ctrl->tRFC, dimm->tRFC);
493 ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR);
494 ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP);
495 ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW);
496 }
497
498 if (!ctrl->cas_supported)
499 die("Unsupported DIMM combination. "
500 "DIMMS do not support common CAS latency");
501 if (!valid_dimms)
502 die("No valid DIMMs found");
503}
504
Patrick Rudolphbec66962016-11-11 19:17:56 +0100505/* CAS write latency. To be programmed in MR2.
506 * See DDR3 SPEC for MR2 documentation. */
507static u8 get_CWL(u32 tCK)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700508{
Patrick Rudolphbec66962016-11-11 19:17:56 +0100509 /* Get CWL based on tCK using the following rule: */
510 switch (tCK) {
511 case TCK_1333MHZ:
512 return 12;
513 case TCK_1200MHZ:
514 case TCK_1100MHZ:
515 return 11;
516 case TCK_1066MHZ:
517 case TCK_1000MHZ:
518 return 10;
519 case TCK_933MHZ:
520 case TCK_900MHZ:
521 return 9;
522 case TCK_800MHZ:
523 case TCK_700MHZ:
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700524 return 8;
Patrick Rudolphbec66962016-11-11 19:17:56 +0100525 case TCK_666MHZ:
526 return 7;
527 case TCK_533MHZ:
528 return 6;
529 default:
530 return 5;
531 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700532}
533
534/* Frequency multiplier. */
535static u32 get_FRQ(u32 tCK)
536{
537 u32 FRQ;
538 FRQ = 256000 / (tCK * BASEFREQ);
539 if (FRQ > 8)
540 return 8;
541 if (FRQ < 3)
542 return 3;
543 return FRQ;
544}
545
546static u32 get_REFI(u32 tCK)
547{
548 /* Get REFI based on MCU frequency using the following rule:
549 * _________________________________________
550 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
551 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 |
552 */
553 static const u32 frq_refi_map[] =
554 { 3120, 4160, 5200, 6240, 7280, 8320 };
555 return frq_refi_map[get_FRQ(tCK) - 3];
556}
557
558static u8 get_XSOffset(u32 tCK)
559{
560 /* Get XSOffset based on MCU frequency using the following rule:
561 * _________________________
562 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
563 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 |
564 */
565 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11 };
566 return frq_xs_map[get_FRQ(tCK) - 3];
567}
568
569static u8 get_MOD(u32 tCK)
570{
571 /* Get MOD based on MCU frequency using the following rule:
572 * _____________________________
573 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
574 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 |
575 */
576 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16 };
577 return frq_mod_map[get_FRQ(tCK) - 3];
578}
579
580static u8 get_WLO(u32 tCK)
581{
582 /* Get WLO based on MCU frequency using the following rule:
583 * _______________________
584 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
585 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 |
586 */
587 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8 };
588 return frq_wlo_map[get_FRQ(tCK) - 3];
589}
590
591static u8 get_CKE(u32 tCK)
592{
593 /* Get CKE based on MCU frequency using the following rule:
594 * _______________________
595 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
596 * CKE : | 3 | 3 | 4 | 4 | 5 | 6 |
597 */
598 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6 };
599 return frq_cke_map[get_FRQ(tCK) - 3];
600}
601
602static u8 get_XPDLL(u32 tCK)
603{
604 /* Get XPDLL based on MCU frequency using the following rule:
605 * _____________________________
606 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
607 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 |
608 */
609 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26 };
610 return frq_xpdll_map[get_FRQ(tCK) - 3];
611}
612
613static u8 get_XP(u32 tCK)
614{
615 /* Get XP based on MCU frequency using the following rule:
616 * _______________________
617 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
618 * XP : | 3 | 4 | 4 | 5 | 6 | 7 |
619 */
620 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 };
621 return frq_xp_map[get_FRQ(tCK) - 3];
622}
623
624static u8 get_AONPD(u32 tCK)
625{
626 /* Get AONPD based on MCU frequency using the following rule:
627 * ________________________
628 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
629 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 |
630 */
631 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10 };
632 return frq_aonpd_map[get_FRQ(tCK) - 3];
633}
634
635static u32 get_COMP2(u32 tCK)
636{
637 /* Get COMP2 based on MCU frequency using the following rule:
638 * ___________________________________________________________
639 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 |
640 * COMP : | D6BEDCC | CE7C34C | CA57A4C | C6369CC | C42514C | C21410C |
641 */
642 static const u32 frq_comp2_map[] = { 0xD6BEDCC, 0xCE7C34C, 0xCA57A4C,
643 0xC6369CC, 0xC42514C, 0xC21410C
644 };
645 return frq_comp2_map[get_FRQ(tCK) - 3];
646}
647
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100648static u32 get_XOVER_CLK(u8 rankmap)
649{
650 return rankmap << 24;
651}
652
653static u32 get_XOVER_CMD(u8 rankmap)
654{
655 u32 reg;
656
657 // enable xover cmd
658 reg = 0x4000;
659
660 // enable xover ctl
661 if (rankmap & 0x3)
662 reg |= 0x20000;
663
664 if (rankmap & 0xc)
665 reg |= 0x4000000;
666
667 return reg;
668}
669
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700670static void dram_timing(ramctr_timing * ctrl)
671{
672 u8 val;
673 u32 val32;
674
675 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
676 * we cap it if we have faster DIMMs.
677 * Then, align it to the closest JEDEC standard frequency */
678 if (ctrl->tCK <= TCK_1066MHZ) {
679 ctrl->tCK = TCK_1066MHZ;
680 ctrl->edge_offset[0] = 16;
681 ctrl->edge_offset[1] = 7;
682 ctrl->edge_offset[2] = 7;
683 ctrl->timC_offset[0] = 18;
684 ctrl->timC_offset[1] = 7;
685 ctrl->timC_offset[2] = 7;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700686 ctrl->reg_320c_range_threshold = 13;
687 } else if (ctrl->tCK <= TCK_933MHZ) {
688 ctrl->tCK = TCK_933MHZ;
689 ctrl->edge_offset[0] = 14;
690 ctrl->edge_offset[1] = 6;
691 ctrl->edge_offset[2] = 6;
692 ctrl->timC_offset[0] = 15;
693 ctrl->timC_offset[1] = 6;
694 ctrl->timC_offset[2] = 6;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700695 ctrl->reg_320c_range_threshold = 15;
696 } else if (ctrl->tCK <= TCK_800MHZ) {
697 ctrl->tCK = TCK_800MHZ;
698 ctrl->edge_offset[0] = 13;
699 ctrl->edge_offset[1] = 5;
700 ctrl->edge_offset[2] = 5;
701 ctrl->timC_offset[0] = 14;
702 ctrl->timC_offset[1] = 5;
703 ctrl->timC_offset[2] = 5;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700704 ctrl->reg_320c_range_threshold = 15;
705 } else if (ctrl->tCK <= TCK_666MHZ) {
706 ctrl->tCK = TCK_666MHZ;
707 ctrl->edge_offset[0] = 10;
708 ctrl->edge_offset[1] = 4;
709 ctrl->edge_offset[2] = 4;
710 ctrl->timC_offset[0] = 11;
711 ctrl->timC_offset[1] = 4;
712 ctrl->timC_offset[2] = 4;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700713 ctrl->reg_320c_range_threshold = 16;
714 } else if (ctrl->tCK <= TCK_533MHZ) {
715 ctrl->tCK = TCK_533MHZ;
716 ctrl->edge_offset[0] = 8;
717 ctrl->edge_offset[1] = 3;
718 ctrl->edge_offset[2] = 3;
719 ctrl->timC_offset[0] = 9;
720 ctrl->timC_offset[1] = 3;
721 ctrl->timC_offset[2] = 3;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700722 ctrl->reg_320c_range_threshold = 17;
723 } else {
724 ctrl->tCK = TCK_400MHZ;
725 ctrl->edge_offset[0] = 6;
726 ctrl->edge_offset[1] = 2;
727 ctrl->edge_offset[2] = 2;
728 ctrl->timC_offset[0] = 6;
729 ctrl->timC_offset[1] = 2;
730 ctrl->timC_offset[2] = 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700731 ctrl->reg_320c_range_threshold = 17;
732 }
733
Patrick Rudolphd4c53e32016-06-14 20:07:32 +0200734 /* Initial phase between CLK/CMD pins */
735 ctrl->reg_c14_offset = (256000 / ctrl->tCK) / 66;
736
Patrick Rudolphb7b1b282016-06-14 18:44:28 +0200737 /* DLL_CONFIG_MDLL_W_TIMER */
738 ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3;
739
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700740 val32 = (1000 << 8) / ctrl->tCK;
741 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
742
Patrick Rudolphbec66962016-11-11 19:17:56 +0100743 /* Find CAS latency */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700744 val = (ctrl->tAA + ctrl->tCK - 1) / ctrl->tCK;
745 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
746 /* Find lowest supported CAS latency that satisfies the minimum value */
Patrick Rudolph2966c992016-11-19 15:46:42 +0100747 while (!((ctrl->cas_supported >> (val - MIN_CAS)) & 1)
748 && (ctrl->cas_supported >> (val - MIN_CAS))) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700749 val++;
750 }
751 /* Is CAS supported */
Patrick Rudolph2966c992016-11-19 15:46:42 +0100752 if (!(ctrl->cas_supported & (1 << (val - MIN_CAS)))) {
Patrick Rudolph55409eb2016-06-15 20:28:32 +0200753 printk(BIOS_ERR, "CAS %uT not supported. ", val);
Patrick Rudolph2966c992016-11-19 15:46:42 +0100754 val = MAX_CAS;
Patrick Rudolph55409eb2016-06-15 20:28:32 +0200755 /* Find highest supported CAS latency */
Patrick Rudolph2966c992016-11-19 15:46:42 +0100756 while (!((ctrl->cas_supported >> (val - MIN_CAS)) & 1))
Patrick Rudolph55409eb2016-06-15 20:28:32 +0200757 val--;
758
759 printk(BIOS_ERR, "Using CAS %uT instead.\n", val);
760 }
761
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700762 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
763 ctrl->CAS = val;
Patrick Rudolphbec66962016-11-11 19:17:56 +0100764 ctrl->CWL = get_CWL(ctrl->tCK);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700765 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
766
767 /* Find tRCD */
768 ctrl->tRCD = (ctrl->tRCD + ctrl->tCK - 1) / ctrl->tCK;
769 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
770
771 ctrl->tRP = (ctrl->tRP + ctrl->tCK - 1) / ctrl->tCK;
772 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
773
774 /* Find tRAS */
775 ctrl->tRAS = (ctrl->tRAS + ctrl->tCK - 1) / ctrl->tCK;
776 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
777
778 /* Find tWR */
779 ctrl->tWR = (ctrl->tWR + ctrl->tCK - 1) / ctrl->tCK;
780 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
781
782 /* Find tFAW */
783 ctrl->tFAW = (ctrl->tFAW + ctrl->tCK - 1) / ctrl->tCK;
784 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
785
786 /* Find tRRD */
787 ctrl->tRRD = (ctrl->tRRD + ctrl->tCK - 1) / ctrl->tCK;
788 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
789
790 /* Find tRTP */
791 ctrl->tRTP = (ctrl->tRTP + ctrl->tCK - 1) / ctrl->tCK;
792 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
793
794 /* Find tWTR */
795 ctrl->tWTR = (ctrl->tWTR + ctrl->tCK - 1) / ctrl->tCK;
796 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
797
798 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
799 ctrl->tRFC = (ctrl->tRFC + ctrl->tCK - 1) / ctrl->tCK;
800 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
801
802 ctrl->tREFI = get_REFI(ctrl->tCK);
803 ctrl->tMOD = get_MOD(ctrl->tCK);
804 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
805 ctrl->tWLO = get_WLO(ctrl->tCK);
806 ctrl->tCKE = get_CKE(ctrl->tCK);
807 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
808 ctrl->tXP = get_XP(ctrl->tCK);
809 ctrl->tAONPD = get_AONPD(ctrl->tCK);
810}
811
812static void dram_freq(ramctr_timing * ctrl)
813{
814 if (ctrl->tCK > TCK_400MHZ) {
815 printk (BIOS_ERR, "DRAM frequency is under lowest supported frequency (400 MHz). Increasing to 400 MHz as last resort");
816 ctrl->tCK = TCK_400MHZ;
817 }
818 while (1) {
819 u8 val2;
820 u32 reg1 = 0;
821
822 /* Step 1 - Set target PCU frequency */
823
824 if (ctrl->tCK <= TCK_1066MHZ) {
825 ctrl->tCK = TCK_1066MHZ;
826 } else if (ctrl->tCK <= TCK_933MHZ) {
827 ctrl->tCK = TCK_933MHZ;
828 } else if (ctrl->tCK <= TCK_800MHZ) {
829 ctrl->tCK = TCK_800MHZ;
830 } else if (ctrl->tCK <= TCK_666MHZ) {
831 ctrl->tCK = TCK_666MHZ;
832 } else if (ctrl->tCK <= TCK_533MHZ) {
833 ctrl->tCK = TCK_533MHZ;
834 } else if (ctrl->tCK <= TCK_400MHZ) {
835 ctrl->tCK = TCK_400MHZ;
836 } else {
837 die ("No lock frequency found");
838 }
839
Martin Roth128c1042016-11-18 09:29:03 -0700840 /* Frequency multiplier. */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700841 u32 FRQ = get_FRQ(ctrl->tCK);
842
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100843 /* The PLL will never lock if the required frequency is
844 * already set. Exit early to prevent a system hang.
845 */
Patrick Rudolph069018d2016-11-12 11:43:59 +0100846 reg1 = MCHBAR32(MC_BIOS_DATA);
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100847 val2 = (u8) reg1;
Patrick Rudolphf7047542016-11-12 11:39:57 +0100848 if (val2)
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100849 return;
Patrick Rudolph9c9bde32016-03-26 17:20:02 +0100850
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700851 /* Step 2 - Select frequency in the MCU */
852 reg1 = FRQ;
853 reg1 |= 0x80000000; // set running bit
Patrick Rudolph069018d2016-11-12 11:43:59 +0100854 MCHBAR32(MC_BIOS_REQ) = reg1;
Kyösti Mälkki809b5882016-11-19 17:12:39 +0200855 int i=0;
856 printk(BIOS_DEBUG, "PLL busy... ");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700857 while (reg1 & 0x80000000) {
Kyösti Mälkki809b5882016-11-19 17:12:39 +0200858 udelay(10);
859 i++;
Patrick Rudolph069018d2016-11-12 11:43:59 +0100860 reg1 = MCHBAR32(MC_BIOS_REQ);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700861 }
Kyösti Mälkki809b5882016-11-19 17:12:39 +0200862 printk(BIOS_DEBUG, "done in %d us\n", i * 10);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700863
864 /* Step 3 - Verify lock frequency */
Patrick Rudolph069018d2016-11-12 11:43:59 +0100865 reg1 = MCHBAR32(MC_BIOS_DATA);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700866 val2 = (u8) reg1;
867 if (val2 >= FRQ) {
868 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
869 (1000 << 8) / ctrl->tCK);
870 return;
871 }
872 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
873 ctrl->tCK++;
874 }
875}
876
877static void dram_xover(ramctr_timing * ctrl)
878{
879 u32 reg;
880 int channel;
881
882 FOR_ALL_CHANNELS {
883 // enable xover clk
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100884 reg = get_XOVER_CLK(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100885 printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
886 reg);
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100887 MCHBAR32(channel * 0x100 + 0xc14) = reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700888
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +0100889 // enable xover ctl & xover cmd
890 reg = get_XOVER_CMD(ctrl->rankmap[channel]);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100891 printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
892 reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700893 MCHBAR32(0x100 * channel + 0x320c) = reg;
894 }
895}
896
897static void dram_timing_regs(ramctr_timing * ctrl)
898{
899 u32 reg, addr, val32, cpu, stretch;
900 struct cpuid_result cpures;
901 int channel;
902
903 FOR_ALL_CHANNELS {
904 // DBP
905 reg = 0;
906 reg |= ctrl->tRCD;
907 reg |= (ctrl->tRP << 4);
908 reg |= (ctrl->CAS << 8);
909 reg |= (ctrl->CWL << 12);
910 reg |= (ctrl->tRAS << 16);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100911 printram("DBP [%x] = %x\n", 0x400 * channel + 0x4000, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700912 MCHBAR32(0x400 * channel + 0x4000) = reg;
913
914 // RAP
915 reg = 0;
916 reg |= ctrl->tRRD;
917 reg |= (ctrl->tRTP << 4);
918 reg |= (ctrl->tCKE << 8);
919 reg |= (ctrl->tWTR << 12);
920 reg |= (ctrl->tFAW << 16);
921 reg |= (ctrl->tWR << 24);
922 reg |= (3 << 30);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100923 printram("RAP [%x] = %x\n", 0x400 * channel + 0x4004, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700924 MCHBAR32(0x400 * channel + 0x4004) = reg;
925
926 // OTHP
927 addr = 0x400 * channel + 0x400c;
928 reg = 0;
929 reg |= ctrl->tXPDLL;
930 reg |= (ctrl->tXP << 5);
931 reg |= (ctrl->tAONPD << 8);
932 reg |= 0xa0000;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100933 printram("OTHP [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700934 MCHBAR32(addr) = reg;
935
936 MCHBAR32(0x400 * channel + 0x4014) = 0;
937
938 MCHBAR32(addr) |= 0x00020000;
939
940 // ODT stretch
941 reg = 0;
942
Ryan Salsamendie4da9aa2016-06-24 12:01:11 -0700943 cpures = cpuid(1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700944 cpu = cpures.eax;
945 if (IS_IVY_CPU(cpu)
946 || (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_D2(cpu))) {
947 stretch = 2;
948 addr = 0x400 * channel + 0x400c;
Patrick Rudolpha649a542016-01-17 18:32:06 +0100949 printram("ODT stretch [%x] = %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700950 0x400 * channel + 0x400c, reg);
951 reg = MCHBAR32(addr);
952
953 if (((ctrl->rankmap[channel] & 3) == 0)
954 || (ctrl->rankmap[channel] & 0xc) == 0) {
955
956 // Rank 0 - operate on rank 2
957 reg = (reg & ~0xc0000) | (stretch << 18);
958
959 // Rank 2 - operate on rank 0
960 reg = (reg & ~0x30000) | (stretch << 16);
961
Patrick Rudolpha649a542016-01-17 18:32:06 +0100962 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700963 MCHBAR32(addr) = reg;
964 }
965
966 } else if (IS_SANDY_CPU(cpu) && IS_SANDY_CPU_C(cpu)) {
967 stretch = 3;
968 addr = 0x400 * channel + 0x401c;
969 reg = MCHBAR32(addr);
970
971 if (((ctrl->rankmap[channel] & 3) == 0)
972 || (ctrl->rankmap[channel] & 0xc) == 0) {
973
974 // Rank 0 - operate on rank 2
975 reg = (reg & ~0x3000) | (stretch << 12);
976
977 // Rank 2 - operate on rank 0
978 reg = (reg & ~0xc00) | (stretch << 10);
979
Patrick Rudolpha649a542016-01-17 18:32:06 +0100980 printram("ODT stretch [%x] = %x\n", addr, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700981 MCHBAR32(addr) = reg;
982 }
983 } else {
984 stretch = 0;
985 }
986
987 // REFI
988 reg = 0;
989 val32 = ctrl->tREFI;
990 reg = (reg & ~0xffff) | val32;
991 val32 = ctrl->tRFC;
992 reg = (reg & ~0x1ff0000) | (val32 << 16);
993 val32 = (u32) (ctrl->tREFI * 9) / 1024;
994 reg = (reg & ~0xfe000000) | (val32 << 25);
Patrick Rudolpha649a542016-01-17 18:32:06 +0100995 printram("REFI [%x] = %x\n", 0x400 * channel + 0x4298,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700996 reg);
997 MCHBAR32(0x400 * channel + 0x4298) = reg;
998
999 MCHBAR32(0x400 * channel + 0x4294) |= 0xff;
1000
1001 // SRFTP
1002 reg = 0;
1003 val32 = tDLLK;
1004 reg = (reg & ~0xfff) | val32;
1005 val32 = ctrl->tXSOffset;
1006 reg = (reg & ~0xf000) | (val32 << 12);
1007 val32 = tDLLK - ctrl->tXSOffset;
1008 reg = (reg & ~0x3ff0000) | (val32 << 16);
1009 val32 = ctrl->tMOD - 8;
1010 reg = (reg & ~0xf0000000) | (val32 << 28);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001011 printram("SRFTP [%x] = %x\n", 0x400 * channel + 0x42a4,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001012 reg);
1013 MCHBAR32(0x400 * channel + 0x42a4) = reg;
1014 }
1015}
1016
Patrick Rudolph735ecce2016-03-26 10:42:27 +01001017static void dram_dimm_mapping(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001018{
1019 u32 reg, val32;
1020 int channel;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01001021 dimm_info *info = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001022
1023 FOR_ALL_CHANNELS {
1024 dimm_attr *dimmA = 0;
1025 dimm_attr *dimmB = 0;
1026 reg = 0;
1027 val32 = 0;
1028 if (info->dimm[channel][0].size_mb >=
1029 info->dimm[channel][1].size_mb) {
1030 // dimm 0 is bigger, set it to dimmA
1031 dimmA = &info->dimm[channel][0];
1032 dimmB = &info->dimm[channel][1];
1033 reg |= (0 << 16);
1034 } else {
1035 // dimm 1 is bigger, set it to dimmA
1036 dimmA = &info->dimm[channel][1];
1037 dimmB = &info->dimm[channel][0];
1038 reg |= (1 << 16);
1039 }
1040 // dimmA
1041 if (dimmA && (dimmA->ranks > 0)) {
1042 val32 = dimmA->size_mb / 256;
1043 reg = (reg & ~0xff) | val32;
1044 val32 = dimmA->ranks - 1;
1045 reg = (reg & ~0x20000) | (val32 << 17);
1046 val32 = (dimmA->width / 8) - 1;
1047 reg = (reg & ~0x80000) | (val32 << 19);
1048 }
1049 // dimmB
1050 if (dimmB && (dimmB->ranks > 0)) {
1051 val32 = dimmB->size_mb / 256;
1052 reg = (reg & ~0xff00) | (val32 << 8);
1053 val32 = dimmB->ranks - 1;
1054 reg = (reg & ~0x40000) | (val32 << 18);
1055 val32 = (dimmB->width / 8) - 1;
1056 reg = (reg & ~0x100000) | (val32 << 20);
1057 }
1058 reg = (reg & ~0x200000) | (1 << 21); // rank interleave
1059 reg = (reg & ~0x400000) | (1 << 22); // enhanced interleave
1060
1061 // Save MAD-DIMM register
1062 if ((dimmA && (dimmA->ranks > 0))
1063 || (dimmB && (dimmB->ranks > 0))) {
1064 ctrl->mad_dimm[channel] = reg;
1065 } else {
1066 ctrl->mad_dimm[channel] = 0;
1067 }
1068 }
1069}
1070
1071static void dram_dimm_set_mapping(ramctr_timing * ctrl)
1072{
1073 int channel;
1074 FOR_ALL_CHANNELS {
1075 MCHBAR32(0x5004 + channel * 4) = ctrl->mad_dimm[channel];
1076 }
1077}
1078
1079static void dram_zones(ramctr_timing * ctrl, int training)
1080{
1081 u32 reg, ch0size, ch1size;
1082 u8 val;
1083 reg = 0;
1084 val = 0;
1085 if (training) {
1086 ch0size = ctrl->channel_size_mb[0] ? 256 : 0;
1087 ch1size = ctrl->channel_size_mb[1] ? 256 : 0;
1088 } else {
1089 ch0size = ctrl->channel_size_mb[0];
1090 ch1size = ctrl->channel_size_mb[1];
1091 }
1092
1093 if (ch0size >= ch1size) {
1094 reg = MCHBAR32(0x5014);
1095 val = ch1size / 256;
1096 reg = (reg & ~0xff000000) | val << 24;
1097 reg = (reg & ~0xff0000) | (2 * val) << 16;
1098 MCHBAR32(0x5014) = reg;
1099 MCHBAR32(0x5000) = 0x24;
1100 } else {
1101 reg = MCHBAR32(0x5014);
1102 val = ch0size / 256;
1103 reg = (reg & ~0xff000000) | val << 24;
1104 reg = (reg & ~0xff0000) | (2 * val) << 16;
1105 MCHBAR32(0x5014) = reg;
1106 MCHBAR32(0x5000) = 0x21;
1107 }
1108}
1109
1110static void dram_memorymap(ramctr_timing * ctrl, int me_uma_size)
1111{
1112 u32 reg, val, reclaim;
1113 u32 tom, gfxstolen, gttsize;
1114 size_t tsegsize, mmiosize, toludbase, touudbase, gfxstolenbase, gttbase,
1115 tsegbase, mestolenbase;
1116 size_t tsegbasedelta, remapbase, remaplimit;
1117 uint16_t ggc;
1118
Patrick Rudolph266a1f72016-06-09 18:13:34 +02001119 mmiosize = get_mmio_size();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001120
1121 ggc = pci_read_config16(NORTHBRIDGE, GGC);
1122 if (!(ggc & 2)) {
1123 gfxstolen = ((ggc >> 3) & 0x1f) * 32;
1124 gttsize = ((ggc >> 8) & 0x3);
1125 } else {
1126 gfxstolen = 0;
1127 gttsize = 0;
1128 }
1129
1130 tsegsize = CONFIG_SMM_TSEG_SIZE >> 20;
1131
1132 tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1];
1133
1134 mestolenbase = tom - me_uma_size;
1135
1136 toludbase = MIN(4096 - mmiosize + gfxstolen + gttsize + tsegsize,
1137 tom - me_uma_size);
1138 gfxstolenbase = toludbase - gfxstolen;
1139 gttbase = gfxstolenbase - gttsize;
1140
1141 tsegbase = gttbase - tsegsize;
1142
1143 // Round tsegbase down to nearest address aligned to tsegsize
1144 tsegbasedelta = tsegbase & (tsegsize - 1);
1145 tsegbase &= ~(tsegsize - 1);
1146
1147 gttbase -= tsegbasedelta;
1148 gfxstolenbase -= tsegbasedelta;
1149 toludbase -= tsegbasedelta;
1150
Elyes HAOUAS15279a92016-07-28 21:05:26 +02001151 // Test if it is possible to reclaim a hole in the RAM addressing
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001152 if (tom - me_uma_size > toludbase) {
1153 // Reclaim is possible
1154 reclaim = 1;
1155 remapbase = MAX(4096, tom - me_uma_size);
1156 remaplimit =
1157 remapbase + MIN(4096, tom - me_uma_size) - toludbase - 1;
1158 touudbase = remaplimit + 1;
1159 } else {
1160 // Reclaim not possible
1161 reclaim = 0;
1162 touudbase = tom - me_uma_size;
1163 }
1164
1165 // Update memory map in pci-e configuration space
Patrick Rudolpha649a542016-01-17 18:32:06 +01001166 printk(BIOS_DEBUG, "Update PCI-E configuration space:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001167
1168 // TOM (top of memory)
1169 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa0);
1170 val = tom & 0xfff;
1171 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001172 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001173 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa0, reg);
1174
1175 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa4);
1176 val = tom & 0xfffff000;
1177 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001178 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001179 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa4, reg);
1180
1181 // TOLUD (top of low used dram)
1182 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xbc);
1183 val = toludbase & 0xfff;
1184 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001185 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xbc, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001186 pcie_write_config32(PCI_DEV(0, 0, 0), 0xbc, reg);
1187
1188 // TOUUD LSB (top of upper usable dram)
1189 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xa8);
1190 val = touudbase & 0xfff;
1191 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001192 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xa8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001193 pcie_write_config32(PCI_DEV(0, 0, 0), 0xa8, reg);
1194
1195 // TOUUD MSB
1196 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xac);
1197 val = touudbase & 0xfffff000;
1198 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001199 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xac, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001200 pcie_write_config32(PCI_DEV(0, 0, 0), 0xac, reg);
1201
1202 if (reclaim) {
1203 // REMAP BASE
1204 pcie_write_config32(PCI_DEV(0, 0, 0), 0x90, remapbase << 20);
1205 pcie_write_config32(PCI_DEV(0, 0, 0), 0x94, remapbase >> 12);
1206
1207 // REMAP LIMIT
1208 pcie_write_config32(PCI_DEV(0, 0, 0), 0x98, remaplimit << 20);
1209 pcie_write_config32(PCI_DEV(0, 0, 0), 0x9c, remaplimit >> 12);
1210 }
1211 // TSEG
1212 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb8);
1213 val = tsegbase & 0xfff;
1214 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001215 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb8, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001216 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb8, reg);
1217
1218 // GFX stolen memory
1219 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb0);
1220 val = gfxstolenbase & 0xfff;
1221 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001222 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb0, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001223 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb0, reg);
1224
1225 // GTT stolen memory
1226 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0xb4);
1227 val = gttbase & 0xfff;
1228 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001229 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0xb4, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001230 pcie_write_config32(PCI_DEV(0, 0, 0), 0xb4, reg);
1231
1232 if (me_uma_size) {
1233 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x7c);
1234 val = (0x80000 - me_uma_size) & 0xfffff000;
1235 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001236 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x7c, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001237 pcie_write_config32(PCI_DEV(0, 0, 0), 0x7c, reg);
1238
1239 // ME base
1240 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x70);
1241 val = mestolenbase & 0xfff;
1242 reg = (reg & ~0xfff00000) | (val << 20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001243 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x70, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001244 pcie_write_config32(PCI_DEV(0, 0, 0), 0x70, reg);
1245
1246 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x74);
1247 val = mestolenbase & 0xfffff000;
1248 reg = (reg & ~0x000fffff) | (val >> 12);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001249 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x74, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001250 pcie_write_config32(PCI_DEV(0, 0, 0), 0x74, reg);
1251
1252 // ME mask
1253 reg = pcie_read_config32(PCI_DEV(0, 0, 0), 0x78);
1254 val = (0x80000 - me_uma_size) & 0xfff;
1255 reg = (reg & ~0xfff00000) | (val << 20);
1256 reg = (reg & ~0x400) | (1 << 10); // set lockbit on ME mem
1257
1258 reg = (reg & ~0x800) | (1 << 11); // set ME memory enable
Patrick Rudolpha649a542016-01-17 18:32:06 +01001259 printk(BIOS_DEBUG, "PCI(0, 0, 0)[%x] = %x\n", 0x78, reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001260 pcie_write_config32(PCI_DEV(0, 0, 0), 0x78, reg);
1261 }
1262}
1263
1264static void dram_ioregs(ramctr_timing * ctrl)
1265{
1266 u32 reg, comp2;
1267
1268 int channel;
1269
1270 // IO clock
1271 FOR_ALL_CHANNELS {
1272 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
1273 }
1274
1275 // IO command
1276 FOR_ALL_CHANNELS {
1277 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
1278 }
1279
1280 // IO control
1281 FOR_ALL_POPULATED_CHANNELS {
1282 program_timings(ctrl, channel);
1283 }
1284
1285 // Rcomp
Patrick Rudolpha649a542016-01-17 18:32:06 +01001286 printram("RCOMP...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001287 reg = 0;
1288 while (reg == 0) {
1289 reg = MCHBAR32(0x5084) & 0x10000;
1290 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001291 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001292
1293 // Set comp2
1294 comp2 = get_COMP2(ctrl->tCK);
1295 MCHBAR32(0x3714) = comp2;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001296 printram("COMP2 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001297
1298 // Set comp1
1299 FOR_ALL_POPULATED_CHANNELS {
1300 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
1301 reg = (reg & ~0xe00) | (1 << 9); //odt
1302 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
1303 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
1304 MCHBAR32(0x1810 + channel * 0x100) = reg;
1305 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01001306 printram("COMP1 done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001307
Patrick Rudolpha649a542016-01-17 18:32:06 +01001308 printram("FORCE RCOMP and wait 20us...");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001309 MCHBAR32(0x5f08) |= 0x100;
1310 udelay(20);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001311 printram("done\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001312}
1313
1314static void wait_428c(int channel)
1315{
1316 while (1) {
1317 if (read32(DEFAULT_MCHBAR + 0x428c + (channel << 10)) & 0x50)
1318 return;
1319 }
1320}
1321
1322static void write_reset(ramctr_timing * ctrl)
1323{
1324 int channel, slotrank;
1325
1326 /* choose a populated channel. */
1327 channel = (ctrl->rankmap[0]) ? 0 : 1;
1328
1329 wait_428c(channel);
1330
1331 /* choose a populated rank. */
1332 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
1333
Patrick Rudolph371d2912015-10-09 13:33:25 +02001334 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001335 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1336 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x80c01);
1337
1338 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1339 (slotrank << 24) | 0x60000);
1340
1341 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1342
1343 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x400001);
1344 wait_428c(channel);
1345}
1346
1347static void dram_jedecreset(ramctr_timing * ctrl)
1348{
1349 u32 reg, addr;
1350 int channel;
1351
Elyes HAOUAS7db506c2016-10-02 11:56:39 +02001352 while (!(MCHBAR32(0x5084) & 0x10000));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001353 do {
1354 reg = MCHBAR32(0x428c);
1355 } while ((reg & 0x14) == 0);
1356
1357 // Set state of memory controller
1358 reg = 0x112;
1359 MCHBAR32(0x5030) = reg;
1360 MCHBAR32(0x4ea0) = 0;
1361 reg |= 2; //ddr reset
1362 MCHBAR32(0x5030) = reg;
1363
1364 // Assert dimm reset signal
1365 reg = MCHBAR32(0x5030);
1366 reg &= ~0x2;
1367 MCHBAR32(0x5030) = reg;
1368
1369 // Wait 200us
1370 udelay(200);
1371
1372 // Deassert dimm reset signal
1373 MCHBAR32(0x5030) |= 2;
1374
1375 // Wait 500us
1376 udelay(500);
1377
1378 // Enable DCLK
1379 MCHBAR32(0x5030) |= 4;
1380
1381 // XXX Wait 20ns
1382 udelay(1);
1383
1384 FOR_ALL_CHANNELS {
1385 // Set valid rank CKE
1386 reg = 0;
1387 reg = (reg & ~0xf) | ctrl->rankmap[channel];
1388 addr = 0x400 * channel + 0x42a0;
1389 MCHBAR32(addr) = reg;
1390
1391 // Wait 10ns for ranks to settle
1392 //udelay(0.01);
1393
1394 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
1395 MCHBAR32(addr) = reg;
1396
1397 // Write reset using a NOP
1398 write_reset(ctrl);
1399 }
1400}
1401
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001402static odtmap get_ODT(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001403{
1404 /* Get ODT based on rankmap: */
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001405 int dimms_per_ch = (ctrl->rankmap[channel] & 1)
1406 + ((ctrl->rankmap[channel] >> 2) & 1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001407
1408 if (dimms_per_ch == 1) {
1409 return (const odtmap){60, 60};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001410 } else {
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001411 return (const odtmap){120, 30};
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001412 }
1413}
1414
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001415static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001416 int reg, u32 val)
1417{
1418 wait_428c(channel);
1419
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001420 if (ctrl->rank_mirror[channel][slotrank]) {
1421 /* DDR3 Rank1 Address mirror
1422 * swap the following pins:
1423 * A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 */
1424 reg = ((reg >> 1) & 1) | ((reg << 1) & 2);
1425 val = (val & ~0x1f8) | ((val >> 1) & 0xa8)
1426 | ((val & 0xa8) << 1);
1427 }
1428
Patrick Rudolph371d2912015-10-09 13:33:25 +02001429 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001430 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f000);
1431 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
1432 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1433 (slotrank << 24) | (reg << 20) | val | 0x60000);
1434 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1435
Patrick Rudolph371d2912015-10-09 13:33:25 +02001436 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001437 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f000);
1438 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x41001);
1439 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
1440 (slotrank << 24) | (reg << 20) | val | 0x60000);
1441 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1442
Patrick Rudolph371d2912015-10-09 13:33:25 +02001443 /* DRAM command MRS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001444 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x0f000);
1445 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1446 0x1001 | (ctrl->tMOD << 16));
1447 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1448 (slotrank << 24) | (reg << 20) | val | 0x60000);
1449 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1450 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
1451}
1452
1453static u32 make_mr0(ramctr_timing * ctrl, u8 rank)
1454{
1455 u16 mr0reg, mch_cas, mch_wr;
1456 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 +02001457
1458 /* DLL Reset - self clearing - set after CLK frequency has been changed */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001459 mr0reg = 0x100;
1460
1461 // Convert CAS to MCH register friendly
1462 if (ctrl->CAS < 12) {
1463 mch_cas = (u16) ((ctrl->CAS - 4) << 1);
1464 } else {
1465 mch_cas = (u16) (ctrl->CAS - 12);
1466 mch_cas = ((mch_cas << 1) | 0x1);
1467 }
1468
1469 // Convert tWR to MCH register friendly
1470 mch_wr = mch_wr_t[ctrl->tWR - 5];
1471
Patrick Rudolph2966c992016-11-19 15:46:42 +01001472 mr0reg = (mr0reg & ~0x4) | ((mch_cas & 0x1) << 2);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001473 mr0reg = (mr0reg & ~0x70) | ((mch_cas & 0xe) << 3);
1474 mr0reg = (mr0reg & ~0xe00) | (mch_wr << 9);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001475
1476 // Precharge PD - Fast (desktop) 0x1 or slow (mobile) 0x0 - mostly power-saving feature
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001477 mr0reg = (mr0reg & ~0x1000) | (!ctrl->mobile << 12);
1478 return mr0reg;
1479}
1480
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001481static void dram_mr0(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001482{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001483 write_mrreg(ctrl, channel, rank, 0,
1484 make_mr0(ctrl, rank));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001485}
1486
1487static u32 encode_odt(u32 odt)
1488{
1489 switch (odt) {
1490 case 30:
1491 return (1 << 9) | (1 << 2); // RZQ/8, RZQ/4
1492 case 60:
1493 return (1 << 2); // RZQ/4
1494 case 120:
1495 return (1 << 6); // RZQ/2
1496 default:
1497 case 0:
1498 return 0;
1499 }
1500}
1501
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001502static u32 make_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001503{
1504 odtmap odt;
1505 u32 mr1reg;
1506
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001507 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001508 mr1reg = 0x2;
1509
1510 mr1reg |= encode_odt(odt.rttnom);
1511
1512 return mr1reg;
1513}
1514
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001515static void dram_mr1(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001516{
1517 u16 mr1reg;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001518
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001519 mr1reg = make_mr1(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001520
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001521 write_mrreg(ctrl, channel, rank, 1, mr1reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001522}
1523
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001524static void dram_mr2(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001525{
1526 u16 pasr, cwl, mr2reg;
1527 odtmap odt;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001528 int srt;
1529
1530 pasr = 0;
1531 cwl = ctrl->CWL - 5;
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001532 odt = get_ODT(ctrl, rank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001533
1534 srt = ctrl->extended_temperature_range && !ctrl->auto_self_refresh;
1535
1536 mr2reg = 0;
1537 mr2reg = (mr2reg & ~0x7) | pasr;
1538 mr2reg = (mr2reg & ~0x38) | (cwl << 3);
1539 mr2reg = (mr2reg & ~0x40) | (ctrl->auto_self_refresh << 6);
1540 mr2reg = (mr2reg & ~0x80) | (srt << 7);
1541 mr2reg |= (odt.rttwr / 60) << 9;
1542
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001543 write_mrreg(ctrl, channel, rank, 2, mr2reg);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001544}
1545
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001546static void dram_mr3(ramctr_timing *ctrl, u8 rank, int channel)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001547{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001548 write_mrreg(ctrl, channel, rank, 3, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001549}
1550
1551static void dram_mrscommands(ramctr_timing * ctrl)
1552{
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001553 u8 slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001554 u32 reg, addr;
1555 int channel;
1556
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001557 FOR_ALL_POPULATED_CHANNELS {
1558 FOR_ALL_POPULATED_RANKS {
1559 // MR2
1560 dram_mr2(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001561
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001562 // MR3
1563 dram_mr3(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001564
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001565 // MR1
1566 dram_mr1(ctrl, slotrank, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001567
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001568 // MR0
1569 dram_mr0(ctrl, slotrank, channel);
1570 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001571 }
1572
Patrick Rudolph371d2912015-10-09 13:33:25 +02001573 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001574 write32(DEFAULT_MCHBAR + 0x4e20, 0x7);
1575 write32(DEFAULT_MCHBAR + 0x4e30, 0xf1001);
1576 write32(DEFAULT_MCHBAR + 0x4e00, 0x60002);
1577 write32(DEFAULT_MCHBAR + 0x4e10, 0);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001578
1579 /* DRAM command ZQCL */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001580 write32(DEFAULT_MCHBAR + 0x4e24, 0x1f003);
1581 write32(DEFAULT_MCHBAR + 0x4e34, 0x1901001);
1582 write32(DEFAULT_MCHBAR + 0x4e04, 0x60400);
1583 write32(DEFAULT_MCHBAR + 0x4e14, 0x288);
Patrick Rudolph371d2912015-10-09 13:33:25 +02001584
1585 /* execute command queue on all channels ? */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001586 write32(DEFAULT_MCHBAR + 0x4e84, 0x40004);
1587
1588 // Drain
1589 FOR_ALL_CHANNELS {
1590 // Wait for ref drained
1591 wait_428c(channel);
1592 }
1593
1594 // Refresh enable
1595 MCHBAR32(0x5030) |= 8;
1596
1597 FOR_ALL_POPULATED_CHANNELS {
1598 addr = 0x400 * channel + 0x4020;
1599 reg = MCHBAR32(addr);
1600 reg &= ~0x200000;
1601 MCHBAR32(addr) = reg;
1602
1603 wait_428c(channel);
1604
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001605 slotrank = (ctrl->rankmap[channel] & 1) ? 0 : 2;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001606
1607 // Drain
1608 wait_428c(channel);
1609
Patrick Rudolph371d2912015-10-09 13:33:25 +02001610 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001611 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
1612 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
1613 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01001614 (slotrank << 24) | 0x60000);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001615 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
1616 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x1);
1617
1618 // Drain
1619 wait_428c(channel);
1620 }
1621}
1622
1623const u32 lane_registers[] = {
1624 0x0000, 0x0200, 0x0400, 0x0600,
1625 0x1000, 0x1200, 0x1400, 0x1600,
1626 0x0800
1627};
1628
1629static void program_timings(ramctr_timing * ctrl, int channel)
1630{
1631 u32 reg32, reg_4024, reg_c14, reg_c18, reg_4028;
1632 int lane;
1633 int slotrank, slot;
1634 int full_shift = 0;
1635 u16 slot320c[NUM_SLOTS];
1636
1637 FOR_ALL_POPULATED_RANKS {
1638 if (full_shift < -ctrl->timings[channel][slotrank].val_320c)
1639 full_shift = -ctrl->timings[channel][slotrank].val_320c;
1640 }
1641
1642 for (slot = 0; slot < NUM_SLOTS; slot++)
1643 switch ((ctrl->rankmap[channel] >> (2 * slot)) & 3) {
1644 case 0:
1645 default:
1646 slot320c[slot] = 0x7f;
1647 break;
1648 case 1:
1649 slot320c[slot] =
1650 ctrl->timings[channel][2 * slot + 0].val_320c +
1651 full_shift;
1652 break;
1653 case 2:
1654 slot320c[slot] =
1655 ctrl->timings[channel][2 * slot + 1].val_320c +
1656 full_shift;
1657 break;
1658 case 3:
1659 slot320c[slot] =
1660 (ctrl->timings[channel][2 * slot].val_320c +
1661 ctrl->timings[channel][2 * slot +
1662 1].val_320c) / 2 +
1663 full_shift;
1664 break;
1665 }
1666
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001667 /* enable CMD XOVER */
1668 reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001669 reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
1670 reg32 |= (slot320c[1] & 0x7f) << 18;
1671 reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
1672
1673 MCHBAR32(0x320c + 0x100 * channel) = reg32;
1674
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001675 /* enable CLK XOVER */
1676 reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001677 reg_c18 = 0;
1678
1679 FOR_ALL_POPULATED_RANKS {
1680 int shift =
1681 ctrl->timings[channel][slotrank].val_320c + full_shift;
1682 int offset_val_c14;
1683 if (shift < 0)
1684 shift = 0;
1685 offset_val_c14 = ctrl->reg_c14_offset + shift;
Patrick Rudolpha1c3bed2016-01-24 14:07:15 +01001686 /* set CLK phase shift */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001687 reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
1688 reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
1689 }
1690
1691 MCHBAR32(0xc14 + channel * 0x100) = reg_c14;
1692 MCHBAR32(0xc18 + channel * 0x100) = reg_c18;
1693
1694 reg_4028 = MCHBAR32(0x4028 + 0x400 * channel);
1695 reg_4028 &= 0xffff0000;
1696
1697 reg_4024 = 0;
1698
1699 FOR_ALL_POPULATED_RANKS {
1700 int post_timA_min_high = 7, post_timA_max_high = 0;
1701 int pre_timA_min_high = 7, pre_timA_max_high = 0;
1702 int shift_402x = 0;
1703 int shift =
1704 ctrl->timings[channel][slotrank].val_320c + full_shift;
1705
1706 if (shift < 0)
1707 shift = 0;
1708
1709 FOR_ALL_LANES {
1710 if (post_timA_min_high >
1711 ((ctrl->timings[channel][slotrank].lanes[lane].
1712 timA + shift) >> 6))
1713 post_timA_min_high =
1714 ((ctrl->timings[channel][slotrank].
1715 lanes[lane].timA + shift) >> 6);
1716 if (pre_timA_min_high >
1717 (ctrl->timings[channel][slotrank].lanes[lane].
1718 timA >> 6))
1719 pre_timA_min_high =
1720 (ctrl->timings[channel][slotrank].
1721 lanes[lane].timA >> 6);
1722 if (post_timA_max_high <
1723 ((ctrl->timings[channel][slotrank].lanes[lane].
1724 timA + shift) >> 6))
1725 post_timA_max_high =
1726 ((ctrl->timings[channel][slotrank].
1727 lanes[lane].timA + shift) >> 6);
1728 if (pre_timA_max_high <
1729 (ctrl->timings[channel][slotrank].lanes[lane].
1730 timA >> 6))
1731 pre_timA_max_high =
1732 (ctrl->timings[channel][slotrank].
1733 lanes[lane].timA >> 6);
1734 }
1735
1736 if (pre_timA_max_high - pre_timA_min_high <
1737 post_timA_max_high - post_timA_min_high)
1738 shift_402x = +1;
1739 else if (pre_timA_max_high - pre_timA_min_high >
1740 post_timA_max_high - post_timA_min_high)
1741 shift_402x = -1;
1742
1743 reg_4028 |=
1744 (ctrl->timings[channel][slotrank].val_4028 + shift_402x -
1745 post_timA_min_high) << (4 * slotrank);
1746 reg_4024 |=
1747 (ctrl->timings[channel][slotrank].val_4024 +
1748 shift_402x) << (8 * slotrank);
1749
1750 FOR_ALL_LANES {
1751 MCHBAR32(lane_registers[lane] + 0x10 + 0x100 * channel +
1752 4 * slotrank)
1753 =
1754 (((ctrl->timings[channel][slotrank].lanes[lane].
1755 timA + shift) & 0x3f)
1756 |
1757 ((ctrl->timings[channel][slotrank].lanes[lane].
1758 rising + shift) << 8)
1759 |
1760 (((ctrl->timings[channel][slotrank].lanes[lane].
1761 timA + shift -
1762 (post_timA_min_high << 6)) & 0x1c0) << 10)
Patrick Rudolph0188b132016-02-10 19:16:34 +01001763 | ((ctrl->timings[channel][slotrank].lanes[lane].
1764 falling + shift) << 20));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001765
1766 MCHBAR32(lane_registers[lane] + 0x20 + 0x100 * channel +
1767 4 * slotrank)
1768 =
1769 (((ctrl->timings[channel][slotrank].lanes[lane].
1770 timC + shift) & 0x3f)
1771 |
1772 (((ctrl->timings[channel][slotrank].lanes[lane].
1773 timB + shift) & 0x3f) << 8)
1774 |
1775 (((ctrl->timings[channel][slotrank].lanes[lane].
1776 timB + shift) & 0x1c0) << 9)
1777 |
1778 (((ctrl->timings[channel][slotrank].lanes[lane].
1779 timC + shift) & 0x40) << 13));
1780 }
1781 }
1782 MCHBAR32(0x4024 + 0x400 * channel) = reg_4024;
1783 MCHBAR32(0x4028 + 0x400 * channel) = reg_4028;
1784}
1785
1786static void test_timA(ramctr_timing * ctrl, int channel, int slotrank)
1787{
1788 wait_428c(channel);
1789
Patrick Rudolph371d2912015-10-09 13:33:25 +02001790 /* DRAM command MRS
1791 * write MR3 MPR enable
1792 * in this mode only RD and RDA are allowed
1793 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001794 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
1795 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
1796 (0xc01 | (ctrl->tMOD << 16)));
1797 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
1798 (slotrank << 24) | 0x360004);
1799 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
1800
Patrick Rudolph371d2912015-10-09 13:33:25 +02001801 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001802 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
1803 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x4040c01);
1804 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel, (slotrank << 24));
1805 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
1806
Patrick Rudolph371d2912015-10-09 13:33:25 +02001807 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001808 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
1809 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
1810 0x100f | ((ctrl->CAS + 36) << 16));
1811 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
1812 (slotrank << 24) | 0x60000);
1813 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
1814
Patrick Rudolph371d2912015-10-09 13:33:25 +02001815 /* DRAM command MRS
1816 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001817 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
1818 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
1819 (0xc01 | (ctrl->tMOD << 16)));
1820 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
1821 (slotrank << 24) | 0x360000);
1822 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
1823
1824 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
1825
1826 wait_428c(channel);
1827}
1828
1829static int does_lane_work(ramctr_timing * ctrl, int channel, int slotrank,
1830 int lane)
1831{
1832 u32 timA = ctrl->timings[channel][slotrank].lanes[lane].timA;
1833 return ((read32
1834 (DEFAULT_MCHBAR + lane_registers[lane] + channel * 0x100 + 4 +
1835 ((timA / 32) & 1) * 4)
1836 >> (timA % 32)) & 1);
1837}
1838
1839struct run {
1840 int middle;
1841 int end;
1842 int start;
1843 int all;
1844 int length;
1845};
1846
1847static struct run get_longest_zero_run(int *seq, int sz)
1848{
1849 int i, ls;
1850 int bl = 0, bs = 0;
1851 struct run ret;
1852
1853 ls = 0;
1854 for (i = 0; i < 2 * sz; i++)
1855 if (seq[i % sz]) {
1856 if (i - ls > bl) {
1857 bl = i - ls;
1858 bs = ls;
1859 }
1860 ls = i + 1;
1861 }
1862 if (bl == 0) {
1863 ret.middle = sz / 2;
1864 ret.start = 0;
1865 ret.end = sz;
1866 ret.all = 1;
1867 return ret;
1868 }
1869
1870 ret.start = bs % sz;
1871 ret.end = (bs + bl - 1) % sz;
1872 ret.middle = (bs + (bl - 1) / 2) % sz;
1873 ret.length = bl;
1874 ret.all = 0;
1875
1876 return ret;
1877}
1878
1879static void discover_timA_coarse(ramctr_timing * ctrl, int channel,
1880 int slotrank, int *upperA)
1881{
1882 int timA;
1883 int statistics[NUM_LANES][128];
1884 int lane;
1885
1886 for (timA = 0; timA < 128; timA++) {
1887 FOR_ALL_LANES {
1888 ctrl->timings[channel][slotrank].lanes[lane].timA = timA;
1889 }
1890 program_timings(ctrl, channel);
1891
1892 test_timA(ctrl, channel, slotrank);
1893
1894 FOR_ALL_LANES {
1895 statistics[lane][timA] =
1896 !does_lane_work(ctrl, channel, slotrank, lane);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001897 printram("Astat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001898 channel, slotrank, lane, timA,
1899 statistics[lane][timA]);
1900 }
1901 }
1902 FOR_ALL_LANES {
1903 struct run rn = get_longest_zero_run(statistics[lane], 128);
1904 ctrl->timings[channel][slotrank].lanes[lane].timA = rn.middle;
1905 upperA[lane] = rn.end;
1906 if (upperA[lane] < rn.middle)
1907 upperA[lane] += 128;
Patrick Rudolpha649a542016-01-17 18:32:06 +01001908 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001909 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
Patrick Rudolpha649a542016-01-17 18:32:06 +01001910 printram("Aend: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001911 lane, upperA[lane]);
1912 }
1913}
1914
1915static void discover_timA_fine(ramctr_timing * ctrl, int channel, int slotrank,
1916 int *upperA)
1917{
1918 int timA_delta;
1919 int statistics[NUM_LANES][51];
1920 int lane, i;
1921
1922 memset(statistics, 0, sizeof(statistics));
1923
1924 for (timA_delta = -25; timA_delta <= 25; timA_delta++) {
1925 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
1926 timA = upperA[lane] + timA_delta + 0x40;
1927 program_timings(ctrl, channel);
1928
1929 for (i = 0; i < 100; i++) {
1930 test_timA(ctrl, channel, slotrank);
1931 FOR_ALL_LANES {
1932 statistics[lane][timA_delta + 25] +=
1933 does_lane_work(ctrl, channel, slotrank,
1934 lane);
1935 }
1936 }
1937 }
1938 FOR_ALL_LANES {
1939 int last_zero, first_all;
1940
1941 for (last_zero = -25; last_zero <= 25; last_zero++)
1942 if (statistics[lane][last_zero + 25])
1943 break;
1944 last_zero--;
1945 for (first_all = -25; first_all <= 25; first_all++)
1946 if (statistics[lane][first_all + 25] == 100)
1947 break;
1948
1949 printram("lane %d: %d, %d\n", lane, last_zero,
1950 first_all);
1951
1952 ctrl->timings[channel][slotrank].lanes[lane].timA =
1953 (last_zero + first_all) / 2 + upperA[lane];
Patrick Rudolpha649a542016-01-17 18:32:06 +01001954 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001955 lane, ctrl->timings[channel][slotrank].lanes[lane].timA);
1956 }
1957}
1958
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001959static int discover_402x(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001960 int *upperA)
1961{
1962 int works[NUM_LANES];
1963 int lane;
1964 while (1) {
1965 int all_works = 1, some_works = 0;
1966 program_timings(ctrl, channel);
1967 test_timA(ctrl, channel, slotrank);
1968 FOR_ALL_LANES {
1969 works[lane] =
1970 !does_lane_work(ctrl, channel, slotrank, lane);
1971 if (works[lane])
1972 some_works = 1;
1973 else
1974 all_works = 0;
1975 }
1976 if (all_works)
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001977 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001978 if (!some_works) {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001979 if (ctrl->timings[channel][slotrank].val_4024 < 2) {
1980 printk(BIOS_EMERG, "402x discovery failed (1): %d, %d\n",
1981 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001982 return MAKE_ERR;
1983 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001984 ctrl->timings[channel][slotrank].val_4024 -= 2;
1985 printram("4024 -= 2;\n");
1986 continue;
1987 }
1988 ctrl->timings[channel][slotrank].val_4028 += 2;
1989 printram("4028 += 2;\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001990 if (ctrl->timings[channel][slotrank].val_4028 >= 0x10) {
1991 printk(BIOS_EMERG, "402x discovery failed (2): %d, %d\n",
1992 channel, slotrank);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01001993 return MAKE_ERR;
1994 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07001995 FOR_ALL_LANES if (works[lane]) {
1996 ctrl->timings[channel][slotrank].lanes[lane].timA +=
1997 128;
1998 upperA[lane] += 128;
1999 printram("increment %d, %d, %d\n", channel,
2000 slotrank, lane);
2001 }
2002 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002003 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002004}
2005
2006struct timA_minmax {
2007 int timA_min_high, timA_max_high;
2008};
2009
2010static void pre_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
2011 struct timA_minmax *mnmx)
2012{
2013 int lane;
2014 mnmx->timA_min_high = 7;
2015 mnmx->timA_max_high = 0;
2016
2017 FOR_ALL_LANES {
2018 if (mnmx->timA_min_high >
2019 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
2020 mnmx->timA_min_high =
2021 (ctrl->timings[channel][slotrank].lanes[lane].
2022 timA >> 6);
2023 if (mnmx->timA_max_high <
2024 (ctrl->timings[channel][slotrank].lanes[lane].timA >> 6))
2025 mnmx->timA_max_high =
2026 (ctrl->timings[channel][slotrank].lanes[lane].
2027 timA >> 6);
2028 }
2029}
2030
2031static void post_timA_change(ramctr_timing * ctrl, int channel, int slotrank,
2032 struct timA_minmax *mnmx)
2033{
2034 struct timA_minmax post;
2035 int shift_402x = 0;
2036
2037 /* Get changed maxima. */
2038 pre_timA_change(ctrl, channel, slotrank, &post);
2039
2040 if (mnmx->timA_max_high - mnmx->timA_min_high <
2041 post.timA_max_high - post.timA_min_high)
2042 shift_402x = +1;
2043 else if (mnmx->timA_max_high - mnmx->timA_min_high >
2044 post.timA_max_high - post.timA_min_high)
2045 shift_402x = -1;
2046 else
2047 shift_402x = 0;
2048
2049 ctrl->timings[channel][slotrank].val_4028 += shift_402x;
2050 ctrl->timings[channel][slotrank].val_4024 += shift_402x;
2051 printram("4024 += %d;\n", shift_402x);
2052 printram("4028 += %d;\n", shift_402x);
2053}
2054
Patrick Rudolph371d2912015-10-09 13:33:25 +02002055/* Compensate the skew between DQS and DQs.
2056 * To ease PCB design a small skew between Data Strobe signals and
2057 * Data Signals is allowed.
2058 * The controller has to measure and compensate this skew for every byte-lane.
2059 * By delaying either all DQs signals or DQS signal, a full phase
2060 * shift can be introduced.
2061 * It is assumed that one byte-lane's DQs signals have the same routing delay.
2062 *
2063 * To measure the actual skew, the DRAM is placed in "read leveling" mode.
2064 * In read leveling mode the DRAM-chip outputs an alternating periodic pattern.
2065 * The memory controller iterates over all possible values to do a full phase shift
2066 * and issues read commands.
2067 * With DQS and DQs in phase the data read is expected to alternate on every byte:
2068 * 0xFF 0x00 0xFF ...
2069 * Once the controller has detected this pattern a bit in the result register is
2070 * set for the current phase shift.
2071 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002072static int read_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002073{
2074 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002075 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002076
2077 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002078 int all_high, some_high;
2079 int upperA[NUM_LANES];
2080 struct timA_minmax mnmx;
2081
2082 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002083
2084 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002085 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2086 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2087 0xc01 | (ctrl->tRP << 16));
2088 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2089 (slotrank << 24) | 0x60400);
2090 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2091 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2092
2093 write32(DEFAULT_MCHBAR + 0x3400, (slotrank << 2) | 0x8001);
2094
2095 ctrl->timings[channel][slotrank].val_4028 = 4;
2096 ctrl->timings[channel][slotrank].val_4024 = 55;
2097 program_timings(ctrl, channel);
2098
2099 discover_timA_coarse(ctrl, channel, slotrank, upperA);
2100
2101 all_high = 1;
2102 some_high = 0;
2103 FOR_ALL_LANES {
2104 if (ctrl->timings[channel][slotrank].lanes[lane].
2105 timA >= 0x40)
2106 some_high = 1;
2107 else
2108 all_high = 0;
2109 }
2110
2111 if (all_high) {
2112 ctrl->timings[channel][slotrank].val_4028--;
2113 printram("4028--;\n");
2114 FOR_ALL_LANES {
2115 ctrl->timings[channel][slotrank].lanes[lane].
2116 timA -= 0x40;
2117 upperA[lane] -= 0x40;
2118
2119 }
2120 } else if (some_high) {
2121 ctrl->timings[channel][slotrank].val_4024++;
2122 ctrl->timings[channel][slotrank].val_4028++;
2123 printram("4024++;\n");
2124 printram("4028++;\n");
2125 }
2126
2127 program_timings(ctrl, channel);
2128
2129 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2130
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002131 err = discover_402x(ctrl, channel, slotrank, upperA);
2132 if (err)
2133 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002134
2135 post_timA_change(ctrl, channel, slotrank, &mnmx);
2136 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2137
2138 discover_timA_fine(ctrl, channel, slotrank, upperA);
2139
2140 post_timA_change(ctrl, channel, slotrank, &mnmx);
2141 pre_timA_change(ctrl, channel, slotrank, &mnmx);
2142
2143 FOR_ALL_LANES {
2144 ctrl->timings[channel][slotrank].lanes[lane].timA -= mnmx.timA_min_high * 0x40;
2145 }
2146 ctrl->timings[channel][slotrank].val_4028 -= mnmx.timA_min_high;
2147 printram("4028 -= %d;\n", mnmx.timA_min_high);
2148
2149 post_timA_change(ctrl, channel, slotrank, &mnmx);
2150
2151 printram("4/8: %d, %d, %x, %x\n", channel, slotrank,
2152 ctrl->timings[channel][slotrank].val_4024,
2153 ctrl->timings[channel][slotrank].val_4028);
2154
Patrick Rudolpha649a542016-01-17 18:32:06 +01002155 printram("final results:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002156 FOR_ALL_LANES
Patrick Rudolpha649a542016-01-17 18:32:06 +01002157 printram("Aval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002158 lane,
2159 ctrl->timings[channel][slotrank].lanes[lane].timA);
2160
2161 write32(DEFAULT_MCHBAR + 0x3400, 0);
2162
Patrick Rudolph9b515682015-10-09 13:43:51 +02002163 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002164 }
2165
2166 FOR_ALL_POPULATED_CHANNELS {
2167 program_timings(ctrl, channel);
2168 }
2169 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2170 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
2171 + 4 * lane, 0);
2172 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002173 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002174}
2175
2176static void test_timC(ramctr_timing * ctrl, int channel, int slotrank)
2177{
2178 int lane;
2179
2180 FOR_ALL_LANES {
2181 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel + 4 * lane, 0);
2182 read32(DEFAULT_MCHBAR + 0x4140 + 0x400 * channel + 4 * lane);
2183 }
2184
2185 wait_428c(channel);
2186
Patrick Rudolph371d2912015-10-09 13:33:25 +02002187 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002188 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2189 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2190 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD) << 10)
2191 | 4 | (ctrl->tRCD << 16));
2192
2193 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2194 (slotrank << 24) | (6 << 16));
2195
2196 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
2197
Patrick Rudolph371d2912015-10-09 13:33:25 +02002198 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002199 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2200 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8041001);
2201 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2202 (slotrank << 24) | 8);
2203 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2204
Patrick Rudolph371d2912015-10-09 13:33:25 +02002205 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002206 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2207 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x80411f4);
2208 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2209 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2210
Patrick Rudolph371d2912015-10-09 13:33:25 +02002211 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002212 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2213 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2214 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2215 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2216 (slotrank << 24) | 8);
2217 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2218
2219 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2220
2221 wait_428c(channel);
2222
Patrick Rudolph371d2912015-10-09 13:33:25 +02002223 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002224 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2225 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2226 0xc01 | (ctrl->tRP << 16));
2227 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2228 (slotrank << 24) | 0x60400);
2229 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2230
Patrick Rudolph371d2912015-10-09 13:33:25 +02002231 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002232 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2233 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2234 (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) << 10)
2235 | 8 | (ctrl->CAS << 16));
2236
2237 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2238 (slotrank << 24) | 0x60000);
2239
2240 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x244);
2241
Patrick Rudolph371d2912015-10-09 13:33:25 +02002242 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002243 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2244 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2245 0x40011f4 | (max(ctrl->tRTP, 8) << 16));
2246 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel, (slotrank << 24));
2247 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x242);
2248
Patrick Rudolph371d2912015-10-09 13:33:25 +02002249 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002250 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2251 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2252 0xc01 | (ctrl->tRP << 16));
2253 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2254 (slotrank << 24) | 0x60400);
2255 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2256 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2257 wait_428c(channel);
2258}
2259
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002260static int discover_timC(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002261{
2262 int timC;
2263 int statistics[NUM_LANES][MAX_TIMC + 1];
2264 int lane;
2265
2266 wait_428c(channel);
2267
Patrick Rudolph371d2912015-10-09 13:33:25 +02002268 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002269 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2270 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2271 0xc01 | (ctrl->tRP << 16));
2272 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2273 (slotrank << 24) | 0x60400);
2274 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2275 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2276
2277 for (timC = 0; timC <= MAX_TIMC; timC++) {
2278 FOR_ALL_LANES ctrl->timings[channel][slotrank].lanes[lane].
2279 timC = timC;
2280 program_timings(ctrl, channel);
2281
2282 test_timC(ctrl, channel, slotrank);
2283
2284 FOR_ALL_LANES {
2285 statistics[lane][timC] =
2286 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2287 0x400 * channel);
2288 printram("Cstat: %d, %d, %d, %x, %x\n",
2289 channel, slotrank, lane, timC,
2290 statistics[lane][timC]);
2291 }
2292 }
2293 FOR_ALL_LANES {
2294 struct run rn =
2295 get_longest_zero_run(statistics[lane], MAX_TIMC + 1);
2296 ctrl->timings[channel][slotrank].lanes[lane].timC = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002297 if (rn.all) {
2298 printk(BIOS_EMERG, "timC discovery failed: %d, %d, %d\n",
2299 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002300 return MAKE_ERR;
2301 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002302 printram("Cval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002303 lane, ctrl->timings[channel][slotrank].lanes[lane].timC);
2304 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002305 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002306}
2307
2308static int get_precedening_channels(ramctr_timing * ctrl, int target_channel)
2309{
2310 int channel, ret = 0;
2311 FOR_ALL_POPULATED_CHANNELS if (channel < target_channel)
2312 ret++;
2313 return ret;
2314}
2315
2316static void fill_pattern0(ramctr_timing * ctrl, int channel, u32 a, u32 b)
2317{
2318 unsigned j;
2319 unsigned channel_offset =
2320 get_precedening_channels(ctrl, channel) * 0x40;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002321 for (j = 0; j < 16; j++)
2322 write32((void *)(0x04000000 + channel_offset + 4 * j), j & 2 ? b : a);
2323 sfence();
2324}
2325
2326static int num_of_channels(const ramctr_timing * ctrl)
2327{
2328 int ret = 0;
2329 int channel;
2330 FOR_ALL_POPULATED_CHANNELS ret++;
2331 return ret;
2332}
2333
2334static void fill_pattern1(ramctr_timing * ctrl, int channel)
2335{
2336 unsigned j;
2337 unsigned channel_offset =
2338 get_precedening_channels(ctrl, channel) * 0x40;
2339 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2340 for (j = 0; j < 16; j++)
2341 write32((void *)(0x04000000 + channel_offset + j * 4), 0xffffffff);
2342 for (j = 0; j < 16; j++)
2343 write32((void *)(0x04000000 + channel_offset + channel_step + j * 4), 0);
2344 sfence();
2345}
2346
2347static void precharge(ramctr_timing * ctrl)
2348{
2349 int channel, slotrank, lane;
2350
2351 FOR_ALL_POPULATED_CHANNELS {
2352 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2353 ctrl->timings[channel][slotrank].lanes[lane].falling =
2354 16;
2355 ctrl->timings[channel][slotrank].lanes[lane].rising =
2356 16;
Patrick Rudolpha649a542016-01-17 18:32:06 +01002357 }
2358
2359 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002360
2361 FOR_ALL_POPULATED_RANKS {
2362 wait_428c(channel);
2363
Patrick Rudolph371d2912015-10-09 13:33:25 +02002364 /* DRAM command MRS
2365 * write MR3 MPR enable
2366 * in this mode only RD and RDA are allowed
2367 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002368 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2369 0x1f000);
2370 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2371 0xc01 | (ctrl->tMOD << 16));
2372 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2373 (slotrank << 24) | 0x360004);
2374 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2375
Patrick Rudolph371d2912015-10-09 13:33:25 +02002376 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002377 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2378 0x1f105);
2379 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2380 0x4041003);
2381 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2382 (slotrank << 24) | 0);
2383 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2384
Patrick Rudolph371d2912015-10-09 13:33:25 +02002385 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002386 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2387 0x1f105);
2388 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2389 0x1001 | ((ctrl->CAS + 8) << 16));
2390 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2391 (slotrank << 24) | 0x60000);
2392 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2393
Patrick Rudolph371d2912015-10-09 13:33:25 +02002394 /* DRAM command MRS
2395 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002396 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2397 0x1f000);
2398 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2399 0xc01 | (ctrl->tMOD << 16));
2400 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2401 (slotrank << 24) | 0x360000);
2402 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2403 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2404 0xc0001);
2405
2406 wait_428c(channel);
2407 }
2408
2409 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2410 ctrl->timings[channel][slotrank].lanes[lane].falling =
2411 48;
2412 ctrl->timings[channel][slotrank].lanes[lane].rising =
2413 48;
2414 }
2415
2416 program_timings(ctrl, channel);
2417
2418 FOR_ALL_POPULATED_RANKS {
2419 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002420 /* DRAM command MRS
2421 * write MR3 MPR enable
2422 * in this mode only RD and RDA are allowed
2423 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002424 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
2425 0x1f000);
2426 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2427 0xc01 | (ctrl->tMOD << 16));
2428 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2429 (slotrank << 24) | 0x360004);
2430 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2431
Patrick Rudolph371d2912015-10-09 13:33:25 +02002432 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002433 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
2434 0x1f105);
2435 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2436 0x4041003);
2437 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2438 (slotrank << 24) | 0);
2439 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2440
Patrick Rudolph371d2912015-10-09 13:33:25 +02002441 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002442 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
2443 0x1f105);
2444 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2445 0x1001 | ((ctrl->CAS + 8) << 16));
2446 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2447 (slotrank << 24) | 0x60000);
2448 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2449
Patrick Rudolph371d2912015-10-09 13:33:25 +02002450 /* DRAM command MRS
2451 * write MR3 MPR disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002452 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
2453 0x1f000);
2454 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2455 0xc01 | (ctrl->tMOD << 16));
2456
2457 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2458 (slotrank << 24) | 0x360000);
2459 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
2460
2461 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
2462 0xc0001);
2463 wait_428c(channel);
2464 }
2465 }
2466}
2467
2468static void test_timB(ramctr_timing * ctrl, int channel, int slotrank)
2469{
Patrick Rudolph371d2912015-10-09 13:33:25 +02002470 /* enable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002471 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002472 0x80 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002473
2474 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002475 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002476 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f207);
2477 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2478 0x8000c01 | ((ctrl->CWL + ctrl->tWLO) << 16));
2479 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2480 8 | (slotrank << 24));
2481 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2482
Patrick Rudolph371d2912015-10-09 13:33:25 +02002483 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002484 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f107);
2485 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2486 0x4000c01 | ((ctrl->CAS + 38) << 16));
2487 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2488 (slotrank << 24) | 4);
2489 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2490
2491 write32(DEFAULT_MCHBAR + 0x400 * channel + 0x4284, 0x40001);
2492 wait_428c(channel);
2493
Patrick Rudolph371d2912015-10-09 13:33:25 +02002494 /* disable DQs on this slotrank */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002495 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002496 0x1080 | make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002497}
2498
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002499static int discover_timB(ramctr_timing *ctrl, int channel, int slotrank)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002500{
2501 int timB;
2502 int statistics[NUM_LANES][128];
2503 int lane;
2504
2505 write32(DEFAULT_MCHBAR + 0x3400, 0x108052 | (slotrank << 2));
2506
2507 for (timB = 0; timB < 128; timB++) {
2508 FOR_ALL_LANES {
2509 ctrl->timings[channel][slotrank].lanes[lane].timB = timB;
2510 }
2511 program_timings(ctrl, channel);
2512
2513 test_timB(ctrl, channel, slotrank);
2514
2515 FOR_ALL_LANES {
2516 statistics[lane][timB] =
2517 !((read32
2518 (DEFAULT_MCHBAR + lane_registers[lane] +
2519 channel * 0x100 + 4 + ((timB / 32) & 1) * 4)
2520 >> (timB % 32)) & 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01002521 printram("Bstat: %d, %d, %d: %x, %x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002522 channel, slotrank, lane, timB,
2523 statistics[lane][timB]);
2524 }
2525 }
2526 FOR_ALL_LANES {
2527 struct run rn = get_longest_zero_run(statistics[lane], 128);
Patrick Rudolphd912f1d2016-02-15 20:07:42 +01002528 /* timC is a direct function of timB's 6 LSBs.
2529 * Some tests increments the value of timB by a small value,
2530 * which might cause the 6bit value to overflow, if it's close
2531 * to 0x3F. Increment the value by a small offset if it's likely
2532 * to overflow, to make sure it won't overflow while running
2533 * tests and bricks the system due to a non matching timC.
2534 *
2535 * TODO: find out why some tests (edge write discovery)
2536 * increment timB. */
2537 if ((rn.start & 0x3F) == 0x3E)
2538 rn.start += 2;
2539 else if ((rn.start & 0x3F) == 0x3F)
2540 rn.start += 1;
Vladimir Serbinenko3141eac2016-01-29 19:42:02 +01002541 ctrl->timings[channel][slotrank].lanes[lane].timB = rn.start;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002542 if (rn.all) {
2543 printk(BIOS_EMERG, "timB discovery failed: %d, %d, %d\n",
2544 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002545 return MAKE_ERR;
2546 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01002547 printram("Bval: %d, %d, %d: %x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002548 lane, ctrl->timings[channel][slotrank].lanes[lane].timB);
2549 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002550 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002551}
2552
2553static int get_timB_high_adjust(u64 val)
2554{
2555 int i;
2556
2557 /* good */
2558 if (val == 0xffffffffffffffffLL)
2559 return 0;
2560
2561 if (val >= 0xf000000000000000LL) {
2562 /* needs negative adjustment */
2563 for (i = 0; i < 8; i++)
2564 if (val << (8 * (7 - i) + 4))
2565 return -i;
2566 } else {
2567 /* needs positive adjustment */
2568 for (i = 0; i < 8; i++)
2569 if (val >> (8 * (7 - i) + 4))
2570 return i;
2571 }
2572 return 8;
2573}
2574
2575static void adjust_high_timB(ramctr_timing * ctrl)
2576{
2577 int channel, slotrank, lane, old;
2578 write32(DEFAULT_MCHBAR + 0x3400, 0x200);
2579 FOR_ALL_POPULATED_CHANNELS {
2580 fill_pattern1(ctrl, channel);
2581 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 1);
2582 }
2583 FOR_ALL_POPULATED_CHANNELS FOR_ALL_POPULATED_RANKS {
2584
2585 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x10001);
2586
2587 wait_428c(channel);
2588
Patrick Rudolph371d2912015-10-09 13:33:25 +02002589 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002590 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2591 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2592 0xc01 | (ctrl->tRCD << 16));
2593 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2594 (slotrank << 24) | 0x60000);
2595 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
2596
Patrick Rudolph371d2912015-10-09 13:33:25 +02002597 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002598 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f207);
2599 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x8040c01);
2600 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2601 (slotrank << 24) | 0x8);
2602 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x3e0);
2603
Patrick Rudolph371d2912015-10-09 13:33:25 +02002604 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002605 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f201);
2606 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel, 0x8041003);
2607 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2608 (slotrank << 24));
2609 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x3e2);
2610
Patrick Rudolph371d2912015-10-09 13:33:25 +02002611 /* DRAM command NOP */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002612 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f207);
2613 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
2614 0x8000c01 | ((ctrl->CWL + ctrl->tWTR + 5) << 16));
2615 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2616 (slotrank << 24) | 0x8);
2617 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x3e0);
2618
2619 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2620
2621 wait_428c(channel);
2622
Patrick Rudolph371d2912015-10-09 13:33:25 +02002623 /* DRAM command PREA */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002624 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f002);
2625 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2626 0xc01 | ((ctrl->tRP) << 16));
2627 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2628 (slotrank << 24) | 0x60400);
2629 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x240);
2630
Patrick Rudolph371d2912015-10-09 13:33:25 +02002631 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002632 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f006);
2633 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2634 0xc01 | ((ctrl->tRCD) << 16));
2635 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2636 (slotrank << 24) | 0x60000);
2637 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
2638
Patrick Rudolph371d2912015-10-09 13:33:25 +02002639 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002640 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x3f105);
2641 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2642 0x4000c01 |
2643 ((ctrl->tRP +
2644 ctrl->timings[channel][slotrank].val_4024 +
2645 ctrl->timings[channel][slotrank].val_4028) << 16));
2646 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2647 (slotrank << 24) | 0x60008);
2648 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
2649
2650 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0x80001);
2651 wait_428c(channel);
2652 FOR_ALL_LANES {
2653 u64 res =
2654 read32(DEFAULT_MCHBAR + lane_registers[lane] +
2655 0x100 * channel + 4);
2656 res |=
2657 ((u64) read32(DEFAULT_MCHBAR + lane_registers[lane] +
2658 0x100 * channel + 8)) << 32;
2659 old = ctrl->timings[channel][slotrank].lanes[lane].timB;
2660 ctrl->timings[channel][slotrank].lanes[lane].timB +=
2661 get_timB_high_adjust(res) * 64;
2662
Patrick Rudolpha649a542016-01-17 18:32:06 +01002663 printram("High adjust %d:%016llx\n", lane, res);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002664 printram("Bval+: %d, %d, %d, %x -> %x\n", channel,
2665 slotrank, lane, old,
2666 ctrl->timings[channel][slotrank].lanes[lane].
2667 timB);
2668 }
2669 }
2670 write32(DEFAULT_MCHBAR + 0x3400, 0);
2671}
2672
2673static void write_op(ramctr_timing * ctrl, int channel)
2674{
2675 int slotrank;
2676
2677 wait_428c(channel);
2678
2679 /* choose an existing rank. */
2680 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2681
Patrick Rudolph371d2912015-10-09 13:33:25 +02002682 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002683 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2684 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2685
2686 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2687 (slotrank << 24) | 0x60000);
2688
2689 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2690
2691 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2692 wait_428c(channel);
2693}
2694
Patrick Rudolph371d2912015-10-09 13:33:25 +02002695/* Compensate the skew between CMD/ADDR/CLK and DQ/DQS lanes.
2696 * DDR3 adopted the fly-by topology. The data and strobes signals reach
2697 * the chips at different times with respect to command, address and
2698 * clock signals.
2699 * By delaying either all DQ/DQs or all CMD/ADDR/CLK signals, a full phase
2700 * shift can be introduced.
2701 * It is assumed that the CLK/ADDR/CMD signals have the same routing delay.
2702 *
2703 * To find the required phase shift the DRAM is placed in "write leveling" mode.
2704 * In this mode the DRAM-chip samples the CLK on every DQS edge and feeds back the
2705 * sampled value on the data lanes (DQs).
2706 */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002707static int write_training(ramctr_timing * ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002708{
2709 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002710 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002711
2712 FOR_ALL_POPULATED_CHANNELS
2713 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
2714 read32(DEFAULT_MCHBAR + 0x4008 +
2715 0x400 * channel) | 0x8000000);
2716
2717 FOR_ALL_POPULATED_CHANNELS {
2718 write_op(ctrl, channel);
2719 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2720 read32(DEFAULT_MCHBAR + 0x4020 +
2721 0x400 * channel) | 0x200000);
2722 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002723
2724 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002725 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2726 FOR_ALL_POPULATED_CHANNELS {
2727 write_op(ctrl, channel);
2728 }
2729
Patrick Rudolph371d2912015-10-09 13:33:25 +02002730 /* enable write leveling on all ranks
2731 * disable all DQ outputs
2732 * only NOP is allowed in this mode */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002733 FOR_ALL_CHANNELS
2734 FOR_ALL_POPULATED_RANKS
2735 write_mrreg(ctrl, channel, slotrank, 1,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002736 make_mr1(ctrl, slotrank, channel) | 0x1080);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002737
2738 write32(DEFAULT_MCHBAR + 0x3400, 0x108052);
2739
Patrick Rudolph9b515682015-10-09 13:43:51 +02002740 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002741
Patrick Rudolph371d2912015-10-09 13:33:25 +02002742 /* set any valid value for timB, it gets corrected later */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002743 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2744 err = discover_timB(ctrl, channel, slotrank);
2745 if (err)
2746 return err;
2747 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002748
Patrick Rudolph371d2912015-10-09 13:33:25 +02002749 /* disable write leveling on all ranks */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002750 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS
2751 write_mrreg(ctrl, channel,
Patrick Rudolph7e513d12016-01-10 14:22:34 +01002752 slotrank, 1, make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002753
2754 write32(DEFAULT_MCHBAR + 0x3400, 0);
2755
2756 FOR_ALL_POPULATED_CHANNELS
2757 wait_428c(channel);
2758
Patrick Rudolph371d2912015-10-09 13:33:25 +02002759 /* refresh enable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002760 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) | 8);
2761
2762 FOR_ALL_POPULATED_CHANNELS {
2763 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2764 ~0x00200000 & read32(DEFAULT_MCHBAR + 0x4020 +
2765 0x400 * channel));
2766 read32(DEFAULT_MCHBAR + 0x428c + 0x400 * channel);
2767 wait_428c(channel);
2768
Patrick Rudolph371d2912015-10-09 13:33:25 +02002769 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002770 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2771 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x659001);
2772 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel, 0x60000);
2773 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2774
2775 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2776 wait_428c(channel);
2777 }
2778
Patrick Rudolph9b515682015-10-09 13:43:51 +02002779 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002780
2781 printram("CPE\n");
2782 precharge(ctrl);
2783 printram("CPF\n");
2784
2785 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2786 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2787 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2788 0);
2789 }
2790
2791 FOR_ALL_POPULATED_CHANNELS {
2792 fill_pattern0(ctrl, channel, 0xaaaaaaaa, 0x55555555);
2793 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
2794 }
2795
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002796 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
2797 err = discover_timC(ctrl, channel, slotrank);
2798 if (err)
2799 return err;
2800 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002801
2802 FOR_ALL_POPULATED_CHANNELS
2803 program_timings(ctrl, channel);
2804
Patrick Rudolph371d2912015-10-09 13:33:25 +02002805 /* measure and adjust timB timings */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002806 adjust_high_timB(ctrl);
2807
2808 FOR_ALL_POPULATED_CHANNELS
2809 program_timings(ctrl, channel);
2810
2811 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
2812 read32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane);
2813 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
2814 0);
2815 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01002816 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002817}
2818
2819static int test_320c(ramctr_timing * ctrl, int channel, int slotrank)
2820{
2821 struct ram_rank_timings saved_rt = ctrl->timings[channel][slotrank];
2822 int timC_delta;
2823 int lanes_ok = 0;
2824 int ctr = 0;
2825 int lane;
2826
2827 for (timC_delta = -5; timC_delta <= 5; timC_delta++) {
2828 FOR_ALL_LANES {
2829 ctrl->timings[channel][slotrank].lanes[lane].timC =
2830 saved_rt.lanes[lane].timC + timC_delta;
2831 }
2832 program_timings(ctrl, channel);
2833 FOR_ALL_LANES {
2834 write32(DEFAULT_MCHBAR + 4 * lane + 0x4f40, 0);
2835 }
2836
2837 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
2838
2839 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002840 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002841 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
2842 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
2843 ((max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1)) << 10)
2844 | 8 | (ctrl->tRCD << 16));
2845
2846 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2847 (slotrank << 24) | ctr | 0x60000);
2848
2849 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02002850 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002851 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
2852 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
2853 0x8001020 | ((ctrl->CWL + ctrl->tWTR + 8) << 16));
2854 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
2855 (slotrank << 24));
2856 write32(DEFAULT_MCHBAR + 0x4244 + 0x400 * channel, 0x389abcd);
2857 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0x20e42);
2858
Patrick Rudolph371d2912015-10-09 13:33:25 +02002859 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002860 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
2861 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
2862 0x4001020 | (max(ctrl->tRTP, 8) << 16));
2863 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
2864 (slotrank << 24));
2865 write32(DEFAULT_MCHBAR + 0x4248 + 0x400 * channel, 0x389abcd);
2866 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0x20e42);
2867
Patrick Rudolph371d2912015-10-09 13:33:25 +02002868 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002869 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f002);
2870 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel, 0xf1001);
2871 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
2872 (slotrank << 24) | 0x60400);
2873 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0x240);
2874
2875 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
2876 wait_428c(channel);
2877 FOR_ALL_LANES {
2878 u32 r32 =
2879 read32(DEFAULT_MCHBAR + 0x4340 + 4 * lane +
2880 0x400 * channel);
2881
2882 if (r32 == 0)
2883 lanes_ok |= 1 << lane;
2884 }
2885 ctr++;
2886 if (lanes_ok == ((1 << NUM_LANES) - 1))
2887 break;
2888 }
2889
2890 ctrl->timings[channel][slotrank] = saved_rt;
2891
2892 printram("3lanes: %x\n", lanes_ok);
2893 return lanes_ok != ((1 << NUM_LANES) - 1);
2894}
2895
2896#include "raminit_patterns.h"
2897
2898static void fill_pattern5(ramctr_timing * ctrl, int channel, int patno)
2899{
2900 unsigned i, j;
2901 unsigned channel_offset =
2902 get_precedening_channels(ctrl, channel) * 0x40;
2903 unsigned channel_step = 0x40 * num_of_channels(ctrl);
2904
2905 if (patno) {
2906 u8 base8 = 0x80 >> ((patno - 1) % 8);
2907 u32 base = base8 | (base8 << 8) | (base8 << 16) | (base8 << 24);
2908 for (i = 0; i < 32; i++) {
2909 for (j = 0; j < 16; j++) {
2910 u32 val = use_base[patno - 1][i] & (1 << (j / 2)) ? base : 0;
2911 if (invert[patno - 1][i] & (1 << (j / 2)))
2912 val = ~val;
2913 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2914 j * 4), val);
2915 }
2916 }
2917
2918 } else {
2919 for (i = 0; i < sizeof(pattern) / sizeof(pattern[0]); i++) {
2920 for (j = 0; j < 16; j++)
2921 write32((void *)(0x04000000 + channel_offset + i * channel_step +
2922 j * 4), pattern[i][j]);
2923 }
2924 sfence();
2925 }
2926}
2927
2928static void reprogram_320c(ramctr_timing * ctrl)
2929{
2930 int channel, slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002931
2932 FOR_ALL_POPULATED_CHANNELS {
2933 wait_428c(channel);
2934
2935 /* choose an existing rank. */
2936 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2937
Patrick Rudolph371d2912015-10-09 13:33:25 +02002938 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002939 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2940 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2941
2942 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2943 (slotrank << 24) | 0x60000);
2944
2945 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2946
2947 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2948 wait_428c(channel);
2949 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
2950 read32(DEFAULT_MCHBAR + 0x4020 +
2951 0x400 * channel) | 0x200000);
2952 }
Patrick Rudolph371d2912015-10-09 13:33:25 +02002953
2954 /* refresh disable */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002955 write32(DEFAULT_MCHBAR + 0x5030, read32(DEFAULT_MCHBAR + 0x5030) & ~8);
2956 FOR_ALL_POPULATED_CHANNELS {
2957 wait_428c(channel);
2958
2959 /* choose an existing rank. */
2960 slotrank = !(ctrl->rankmap[channel] & 1) ? 2 : 0;
2961
Patrick Rudolph371d2912015-10-09 13:33:25 +02002962 /* DRAM command ZQCS */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002963 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x0f003);
2964 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel, 0x41001);
2965
2966 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
2967 (slotrank << 24) | 0x60000);
2968
2969 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x3e0);
2970
2971 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 1);
2972 wait_428c(channel);
2973 }
2974
2975 /* jedec reset */
2976 dram_jedecreset(ctrl);
2977 /* mrs commands. */
2978 dram_mrscommands(ctrl);
2979
Patrick Rudolph9b515682015-10-09 13:43:51 +02002980 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002981}
2982
2983#define MIN_C320C_LEN 13
2984
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002985static int try_cmd_stretch(ramctr_timing *ctrl, int channel, int cmd_stretch)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002986{
2987 struct ram_rank_timings saved_timings[NUM_CHANNELS][NUM_SLOTRANKS];
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002988 int slotrank;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002989 int c320c;
2990 int stat[NUM_SLOTRANKS][256];
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002991 int delta = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002992
Patrick Rudolph45d6a552016-11-16 19:21:31 +01002993 printram("Trying cmd_stretch %d on channel %d\n", cmd_stretch, channel);
2994
2995 FOR_ALL_POPULATED_RANKS {
2996 saved_timings[channel][slotrank] =
2997 ctrl->timings[channel][slotrank];
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002998 }
2999
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003000 ctrl->cmd_stretch[channel] = cmd_stretch;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003001
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003002 MCHBAR32(0x4004 + 0x400 * channel) =
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003003 ctrl->tRRD
3004 | (ctrl->tRTP << 4)
3005 | (ctrl->tCKE << 8)
3006 | (ctrl->tWTR << 12)
3007 | (ctrl->tFAW << 16)
3008 | (ctrl->tWR << 24)
3009 | (ctrl->cmd_stretch[channel] << 30);
3010
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003011 if (ctrl->cmd_stretch[channel] == 2)
3012 delta = 2;
3013 else if (ctrl->cmd_stretch[channel] == 0)
3014 delta = 4;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003015
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003016 FOR_ALL_POPULATED_RANKS {
3017 ctrl->timings[channel][slotrank].val_4024 -= delta;
3018 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003019
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003020 for (c320c = -127; c320c <= 127; c320c++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003021 FOR_ALL_POPULATED_RANKS {
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003022 ctrl->timings[channel][slotrank].val_320c = c320c;
3023 }
3024 program_timings(ctrl, channel);
3025 reprogram_320c(ctrl);
3026 FOR_ALL_POPULATED_RANKS {
3027 stat[slotrank][c320c + 127] =
3028 test_320c(ctrl, channel, slotrank);
3029 printram("3stat: %d, %d, %d: %x\n",
3030 channel, slotrank, c320c,
3031 stat[slotrank][c320c + 127]);
3032 }
3033 }
3034 FOR_ALL_POPULATED_RANKS {
3035 struct run rn =
3036 get_longest_zero_run(stat[slotrank], 255);
3037 ctrl->timings[channel][slotrank].val_320c =
3038 rn.middle - 127;
3039 printram("3val: %d, %d: %d\n", channel,
3040 slotrank,
3041 ctrl->timings[channel][slotrank].val_320c);
3042 if (rn.all || rn.length < MIN_C320C_LEN) {
3043 FOR_ALL_POPULATED_RANKS {
3044 ctrl->timings[channel][slotrank] =
3045 saved_timings[channel][slotrank];
3046 }
3047 return MAKE_ERR;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003048 }
3049 }
3050
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003051 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003052}
3053
Patrick Rudolph371d2912015-10-09 13:33:25 +02003054/* Adjust CMD phase shift and try multiple command rates.
3055 * A command rate of 2T doubles the time needed for address and
3056 * command decode. */
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003057static int command_training(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003058{
3059 int channel;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003060 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003061
3062 FOR_ALL_POPULATED_CHANNELS {
3063 fill_pattern5(ctrl, channel, 0);
3064 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
3065 }
3066
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003067 FOR_ALL_POPULATED_CHANNELS {
3068 /* try command rate 1T and 2T */
3069 err = try_cmd_stretch(ctrl, channel, 0);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003070 if (err) {
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003071 err = try_cmd_stretch(ctrl, channel, 2);
3072 if (err) {
3073 printk(BIOS_EMERG, "c320c discovery failed\n");
3074 return err;
3075 }
3076 printram("Using CMD rate 2T on channel %u\n", channel);
3077 } else
3078 printram("Using CMD rate 1T on channel %u\n", channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003079 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003080
Patrick Rudolph45d6a552016-11-16 19:21:31 +01003081 FOR_ALL_POPULATED_CHANNELS
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003082 program_timings(ctrl, channel);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003083
3084 reprogram_320c(ctrl);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003085 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003086}
3087
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003088static int discover_edges_real(ramctr_timing *ctrl, int channel, int slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003089 int *edges)
3090{
3091 int edge;
3092 int statistics[NUM_LANES][MAX_EDGE_TIMING + 1];
3093 int lane;
3094
3095 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3096 FOR_ALL_LANES {
3097 ctrl->timings[channel][slotrank].lanes[lane].rising =
3098 edge;
3099 ctrl->timings[channel][slotrank].lanes[lane].falling =
3100 edge;
3101 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003102 program_timings(ctrl, channel);
3103
3104 FOR_ALL_LANES {
3105 write32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3106 4 * lane, 0);
3107 read32(DEFAULT_MCHBAR + 0x400 * channel + 4 * lane +
3108 0x4140);
3109 }
3110
3111 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003112 /* DRAM command MRS
3113 * write MR3 MPR enable
3114 * in this mode only RD and RDA are allowed
3115 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003116 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f000);
3117 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3118 (0xc01 | (ctrl->tMOD << 16)));
3119 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3120 (slotrank << 24) | 0x360004);
3121 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3122
Patrick Rudolph371d2912015-10-09 13:33:25 +02003123 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003124 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f105);
3125 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel, 0x40411f4);
3126 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3127 (slotrank << 24));
3128 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3129
Patrick Rudolph371d2912015-10-09 13:33:25 +02003130 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003131 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel, 0x1f105);
3132 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3133 0x1001 | ((ctrl->CAS + 8) << 16));
3134 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3135 (slotrank << 24) | 0x60000);
3136 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3137
Patrick Rudolph371d2912015-10-09 13:33:25 +02003138 /* DRAM command MRS
3139 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003140 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel, 0x1f000);
3141 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3142 (0xc01 | (ctrl->tMOD << 16)));
3143 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3144 (slotrank << 24) | 0x360000);
3145 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3146
3147 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel, 0xc0001);
3148
3149 wait_428c(channel);
3150
3151 FOR_ALL_LANES {
3152 statistics[lane][edge] =
3153 read32(DEFAULT_MCHBAR + 0x4340 + 0x400 * channel +
3154 lane * 4);
3155 }
3156 }
3157 FOR_ALL_LANES {
3158 struct run rn =
3159 get_longest_zero_run(statistics[lane], MAX_EDGE_TIMING + 1);
3160 edges[lane] = rn.middle;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003161 if (rn.all) {
3162 printk(BIOS_EMERG, "edge discovery failed: %d, %d, %d\n",
3163 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003164 return MAKE_ERR;
3165 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003166 printram("eval %d, %d, %d: %02x\n", channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003167 lane, edges[lane]);
3168 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003169 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003170}
3171
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003172static int discover_edges(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003173{
3174 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3175 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3176 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003177 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003178
3179 write32(DEFAULT_MCHBAR + 0x3400, 0);
3180
Patrick Rudolph9b515682015-10-09 13:43:51 +02003181 toggle_io_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003182
3183 FOR_ALL_POPULATED_CHANNELS FOR_ALL_LANES {
3184 write32(DEFAULT_MCHBAR + 4 * lane +
3185 0x400 * channel + 0x4080, 0);
3186 }
3187
3188 FOR_ALL_POPULATED_CHANNELS {
3189 fill_pattern0(ctrl, channel, 0, 0);
3190 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3191 FOR_ALL_LANES {
3192 read32(DEFAULT_MCHBAR + 0x400 * channel +
3193 lane * 4 + 0x4140);
3194 }
3195
3196 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3197 ctrl->timings[channel][slotrank].lanes[lane].falling =
3198 16;
3199 ctrl->timings[channel][slotrank].lanes[lane].rising =
3200 16;
3201 }
3202
3203 program_timings(ctrl, channel);
3204
3205 FOR_ALL_POPULATED_RANKS {
3206 wait_428c(channel);
3207
Patrick Rudolph371d2912015-10-09 13:33:25 +02003208 /* DRAM command MRS
3209 * MR3 enable MPR
3210 * write MR3 MPR enable
3211 * in this mode only RD and RDA are allowed
3212 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003213 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3214 0x1f000);
3215 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3216 0xc01 | (ctrl->tMOD << 16));
3217 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3218 (slotrank << 24) | 0x360004);
3219 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3220
Patrick Rudolph371d2912015-10-09 13:33:25 +02003221 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003222 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3223 0x1f105);
3224 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3225 0x4041003);
3226 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3227 (slotrank << 24) | 0);
3228 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3229
Patrick Rudolph371d2912015-10-09 13:33:25 +02003230 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003231 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3232 0x1f105);
3233 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3234 0x1001 | ((ctrl->CAS + 8) << 16));
3235 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3236 (slotrank << 24) | 0x60000);
3237 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3238
Patrick Rudolph371d2912015-10-09 13:33:25 +02003239 /* DRAM command MRS
3240 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003241 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3242 0x1f000);
3243 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3244 0xc01 | (ctrl->tMOD << 16));
3245 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3246 (slotrank << 24) | 0x360000);
3247 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3248 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3249 0xc0001);
3250
3251 wait_428c(channel);
3252 }
3253
Patrick Rudolph371d2912015-10-09 13:33:25 +02003254 /* XXX: check any measured value ? */
3255
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003256 FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3257 ctrl->timings[channel][slotrank].lanes[lane].falling =
3258 48;
3259 ctrl->timings[channel][slotrank].lanes[lane].rising =
3260 48;
3261 }
3262
3263 program_timings(ctrl, channel);
3264
3265 FOR_ALL_POPULATED_RANKS {
3266 wait_428c(channel);
3267
Patrick Rudolph371d2912015-10-09 13:33:25 +02003268 /* DRAM command MRS
3269 * MR3 enable MPR
3270 * write MR3 MPR enable
3271 * in this mode only RD and RDA are allowed
3272 * all reads return a predefined pattern */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003273 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3274 0x1f000);
3275 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3276 0xc01 | (ctrl->tMOD << 16));
3277 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3278 (slotrank << 24) | 0x360004);
3279 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0);
3280
Patrick Rudolph371d2912015-10-09 13:33:25 +02003281 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003282 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3283 0x1f105);
3284 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3285 0x4041003);
3286 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3287 (slotrank << 24) | 0);
3288 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel, 0);
3289
Patrick Rudolph371d2912015-10-09 13:33:25 +02003290 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003291 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3292 0x1f105);
3293 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3294 0x1001 | ((ctrl->CAS + 8) << 16));
3295 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3296 (slotrank << 24) | 0x60000);
3297 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel, 0);
3298
Patrick Rudolph371d2912015-10-09 13:33:25 +02003299 /* DRAM command MRS
3300 * MR3 disable MPR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003301 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3302 0x1f000);
3303 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3304 0xc01 | (ctrl->tMOD << 16));
3305 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3306 (slotrank << 24) | 0x360000);
3307 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3308
3309 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3310 0xc0001);
3311 wait_428c(channel);
3312 }
3313
Patrick Rudolph371d2912015-10-09 13:33:25 +02003314 /* XXX: check any measured value ? */
3315
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003316 FOR_ALL_LANES {
3317 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel +
3318 lane * 4,
3319 ~read32(DEFAULT_MCHBAR + 0x4040 +
3320 0x400 * channel + lane * 4) & 0xff);
3321 }
3322
3323 fill_pattern0(ctrl, channel, 0, 0xffffffff);
3324 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3325 }
3326
3327 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3328 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003329 printram("discover falling edges:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003330
3331 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003332 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003333 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003334 if (err)
3335 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003336 }
3337
3338 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003339 printram("discover rising edges:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003340
3341 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003342 err = discover_edges_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003343 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003344 if (err)
3345 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003346 }
3347
3348 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3349
3350 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3351 ctrl->timings[channel][slotrank].lanes[lane].falling =
3352 falling_edges[channel][slotrank][lane];
3353 ctrl->timings[channel][slotrank].lanes[lane].rising =
3354 rising_edges[channel][slotrank][lane];
3355 }
3356
3357 FOR_ALL_POPULATED_CHANNELS {
3358 program_timings(ctrl, channel);
3359 }
3360
3361 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3362 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3363 0);
3364 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003365 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003366}
3367
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003368static int discover_edges_write_real(ramctr_timing *ctrl, int channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003369 int slotrank, int *edges)
3370{
3371 int edge;
3372 u32 raw_statistics[MAX_EDGE_TIMING + 1];
3373 int statistics[MAX_EDGE_TIMING + 1];
3374 const int reg3000b24[] = { 0, 0xc, 0x2c };
3375 int lane, i;
3376 int lower[NUM_LANES];
3377 int upper[NUM_LANES];
3378 int pat;
3379
3380 FOR_ALL_LANES {
3381 lower[lane] = 0;
3382 upper[lane] = MAX_EDGE_TIMING;
3383 }
3384
3385 for (i = 0; i < 3; i++) {
3386 write32(DEFAULT_MCHBAR + 0x3000 + 0x100 * channel,
3387 reg3000b24[i] << 24);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003388 printram("[%x] = 0x%08x\n",
3389 0x3000 + 0x100 * channel, reg3000b24[i] << 24);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003390 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3391 fill_pattern5(ctrl, channel, pat);
3392 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003393 printram("using pattern %d\n", pat);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003394 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++) {
3395 FOR_ALL_LANES {
3396 ctrl->timings[channel][slotrank].lanes[lane].
3397 rising = edge;
3398 ctrl->timings[channel][slotrank].lanes[lane].
3399 falling = edge;
3400 }
3401 program_timings(ctrl, channel);
3402
3403 FOR_ALL_LANES {
3404 write32(DEFAULT_MCHBAR + 0x4340 +
3405 0x400 * channel + 4 * lane, 0);
3406 read32(DEFAULT_MCHBAR + 0x400 * channel +
3407 4 * lane + 0x4140);
3408 }
3409 wait_428c(channel);
3410
Patrick Rudolph371d2912015-10-09 13:33:25 +02003411 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003412 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel,
3413 0x1f006);
3414 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3415 0x4 | (ctrl->tRCD << 16)
3416 | (max(ctrl->tRRD, (ctrl->tFAW >> 2) + 1) <<
3417 10));
3418 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3419 (slotrank << 24) | 0x60000);
3420 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel,
3421 0x240);
3422
Patrick Rudolph371d2912015-10-09 13:33:25 +02003423 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003424 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel,
3425 0x1f201);
3426 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3427 0x8005020 | ((ctrl->tWTR + ctrl->CWL + 8) <<
3428 16));
3429 write32(DEFAULT_MCHBAR + 0x4204 + 0x400 * channel,
3430 (slotrank << 24));
3431 write32(DEFAULT_MCHBAR + 0x4214 + 0x400 * channel,
3432 0x242);
3433
Patrick Rudolph371d2912015-10-09 13:33:25 +02003434 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003435 write32(DEFAULT_MCHBAR + 0x4228 + 0x400 * channel,
3436 0x1f105);
3437 write32(DEFAULT_MCHBAR + 0x4238 + 0x400 * channel,
3438 0x4005020 | (max(ctrl->tRTP, 8) << 16));
3439 write32(DEFAULT_MCHBAR + 0x4208 + 0x400 * channel,
3440 (slotrank << 24));
3441 write32(DEFAULT_MCHBAR + 0x4218 + 0x400 * channel,
3442 0x242);
3443
Patrick Rudolph371d2912015-10-09 13:33:25 +02003444 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003445 write32(DEFAULT_MCHBAR + 0x422c + 0x400 * channel,
3446 0x1f002);
3447 write32(DEFAULT_MCHBAR + 0x423c + 0x400 * channel,
3448 0xc01 | (ctrl->tRP << 16));
3449 write32(DEFAULT_MCHBAR + 0x420c + 0x400 * channel,
3450 (slotrank << 24) | 0x60400);
3451 write32(DEFAULT_MCHBAR + 0x421c + 0x400 * channel, 0);
3452
3453 write32(DEFAULT_MCHBAR + 0x4284 + 0x400 * channel,
3454 0xc0001);
3455 wait_428c(channel);
3456 FOR_ALL_LANES {
3457 read32(DEFAULT_MCHBAR + 0x4340 +
3458 0x400 * channel + lane * 4);
3459 }
3460
3461 raw_statistics[edge] =
3462 MCHBAR32(0x436c + 0x400 * channel);
3463 }
3464 FOR_ALL_LANES {
3465 struct run rn;
3466 for (edge = 0; edge <= MAX_EDGE_TIMING; edge++)
3467 statistics[edge] =
3468 ! !(raw_statistics[edge] & (1 << lane));
3469 rn = get_longest_zero_run(statistics,
3470 MAX_EDGE_TIMING + 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003471 printram("edges: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003472 channel, slotrank, i, rn.start, rn.middle,
3473 rn.end, rn.start + ctrl->edge_offset[i],
3474 rn.end - ctrl->edge_offset[i]);
3475 lower[lane] =
3476 max(rn.start + ctrl->edge_offset[i], lower[lane]);
3477 upper[lane] =
3478 min(rn.end - ctrl->edge_offset[i], upper[lane]);
3479 edges[lane] = (lower[lane] + upper[lane]) / 2;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003480 if (rn.all || (lower[lane] > upper[lane])) {
3481 printk(BIOS_EMERG, "edge write discovery failed: %d, %d, %d\n",
3482 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003483 return MAKE_ERR;
3484 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003485 }
3486 }
3487 }
3488
3489 write32(DEFAULT_MCHBAR + 0x3000, 0);
3490 printram("CPA\n");
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003491 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003492}
3493
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003494static int discover_edges_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003495{
3496 int falling_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3497 int rising_edges[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3498 int channel, slotrank, lane;
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003499 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003500
3501 /* FIXME: under some conditions (older chipsets?) vendor BIOS sets both edges to the same value. */
3502 write32(DEFAULT_MCHBAR + 0x4eb0, 0x300);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003503 printram("discover falling edges write:\n[%x] = %x\n", 0x4eb0, 0x300);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003504
3505 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003506 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003507 falling_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003508 if (err)
3509 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003510 }
3511
3512 write32(DEFAULT_MCHBAR + 0x4eb0, 0x200);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003513 printram("discover rising edges write:\n[%x] = %x\n", 0x4eb0, 0x200);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003514
3515 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003516 err = discover_edges_write_real(ctrl, channel, slotrank,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003517 rising_edges[channel][slotrank]);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003518 if (err)
3519 return err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003520 }
3521
3522 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
3523
3524 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3525 ctrl->timings[channel][slotrank].lanes[lane].falling =
3526 falling_edges[channel][slotrank][lane];
3527 ctrl->timings[channel][slotrank].lanes[lane].rising =
3528 rising_edges[channel][slotrank][lane];
3529 }
3530
3531 FOR_ALL_POPULATED_CHANNELS
3532 program_timings(ctrl, channel);
3533
3534 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3535 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel + 4 * lane,
3536 0);
3537 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003538 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003539}
3540
3541static void test_timC_write(ramctr_timing *ctrl, int channel, int slotrank)
3542{
3543 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003544 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003545 write32(DEFAULT_MCHBAR + 0x4220 + 0x400 * channel, 0x1f006);
3546 write32(DEFAULT_MCHBAR + 0x4230 + 0x400 * channel,
3547 (max((ctrl->tFAW >> 2) + 1, ctrl->tRRD)
3548 << 10) | (ctrl->tRCD << 16) | 4);
3549 write32(DEFAULT_MCHBAR + 0x4200 + 0x400 * channel,
3550 (slotrank << 24) | 0x60000);
3551 write32(DEFAULT_MCHBAR + 0x4210 + 0x400 * channel, 0x244);
3552
Patrick Rudolph371d2912015-10-09 13:33:25 +02003553 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003554 write32(DEFAULT_MCHBAR + 0x4224 + 0x400 * channel, 0x1f201);
3555 write32(DEFAULT_MCHBAR + 0x4234 + 0x400 * channel,
3556 0x80011e0 |
3557 ((ctrl->tWTR + ctrl->CWL + 8) << 16));
3558 write32(DEFAULT_MCHBAR + 0x4204 +
3559 0x400 * channel, (slotrank << 24));
3560 write32(DEFAULT_MCHBAR + 0x4214 +
3561 0x400 * channel, 0x242);
3562
Patrick Rudolph371d2912015-10-09 13:33:25 +02003563 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003564 write32(DEFAULT_MCHBAR + 0x4228 +
3565 0x400 * channel, 0x1f105);
3566 write32(DEFAULT_MCHBAR + 0x4238 +
3567 0x400 * channel,
3568 0x40011e0 | (max(ctrl->tRTP, 8) << 16));
3569 write32(DEFAULT_MCHBAR + 0x4208 +
3570 0x400 * channel, (slotrank << 24));
3571 write32(DEFAULT_MCHBAR + 0x4218 +
3572 0x400 * channel, 0x242);
3573
Patrick Rudolph371d2912015-10-09 13:33:25 +02003574 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003575 write32(DEFAULT_MCHBAR + 0x422c +
3576 0x400 * channel, 0x1f002);
3577 write32(DEFAULT_MCHBAR + 0x423c +
3578 0x400 * channel,
3579 0x1001 | (ctrl->tRP << 16));
3580 write32(DEFAULT_MCHBAR + 0x420c +
3581 0x400 * channel,
3582 (slotrank << 24) | 0x60400);
3583 write32(DEFAULT_MCHBAR + 0x421c +
3584 0x400 * channel, 0);
3585
3586 write32(DEFAULT_MCHBAR + 0x4284 +
3587 0x400 * channel, 0xc0001);
3588 wait_428c(channel);
3589}
3590
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003591static int discover_timC_write(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003592{
3593 const u8 rege3c_b24[3] = { 0, 0xf, 0x2f };
3594 int i, pat;
3595
3596 int lower[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3597 int upper[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
3598 int channel, slotrank, lane;
3599
3600 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3601 lower[channel][slotrank][lane] = 0;
3602 upper[channel][slotrank][lane] = MAX_TIMC;
3603 }
3604
3605 write32(DEFAULT_MCHBAR + 0x4ea8, 1);
Patrick Rudolpha649a542016-01-17 18:32:06 +01003606 printram("discover timC write:\n");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003607
3608 for (i = 0; i < 3; i++)
3609 FOR_ALL_POPULATED_CHANNELS {
3610 write32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100),
3611 (rege3c_b24[i] << 24)
3612 | (read32(DEFAULT_MCHBAR + 0xe3c + (channel * 0x100))
3613 & ~0x3f000000));
3614 udelay(2);
3615 for (pat = 0; pat < NUM_PATTERNS; pat++) {
3616 FOR_ALL_POPULATED_RANKS {
3617 int timC;
3618 u32 raw_statistics[MAX_TIMC + 1];
3619 int statistics[MAX_TIMC + 1];
3620
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003621 /* Make sure rn.start < rn.end */
3622 statistics[MAX_TIMC] = 1;
3623
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003624 fill_pattern5(ctrl, channel, pat);
3625 write32(DEFAULT_MCHBAR + 0x4288 + 0x400 * channel, 0x1f);
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003626 for (timC = 0; timC < MAX_TIMC; timC++) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003627 FOR_ALL_LANES
3628 ctrl->timings[channel][slotrank].lanes[lane].timC = timC;
3629 program_timings(ctrl, channel);
3630
3631 test_timC_write (ctrl, channel, slotrank);
3632
3633 raw_statistics[timC] =
3634 MCHBAR32(0x436c + 0x400 * channel);
3635 }
3636 FOR_ALL_LANES {
3637 struct run rn;
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003638 for (timC = 0; timC < MAX_TIMC; timC++)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003639 statistics[timC] =
3640 !!(raw_statistics[timC] &
3641 (1 << lane));
Patrick Rudolph77e45d32016-02-28 16:14:45 +01003642
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003643 rn = get_longest_zero_run(statistics,
3644 MAX_TIMC + 1);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003645 if (rn.all) {
3646 printk(BIOS_EMERG, "timC write discovery failed: %d, %d, %d\n",
3647 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003648 return MAKE_ERR;
3649 }
Patrick Rudolpha649a542016-01-17 18:32:06 +01003650 printram("timC: %d, %d, %d: 0x%02x-0x%02x-0x%02x, 0x%02x-0x%02x\n",
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003651 channel, slotrank, i, rn.start,
3652 rn.middle, rn.end,
3653 rn.start + ctrl->timC_offset[i],
3654 rn.end - ctrl->timC_offset[i]);
3655 lower[channel][slotrank][lane] =
3656 max(rn.start + ctrl->timC_offset[i],
3657 lower[channel][slotrank][lane]);
3658 upper[channel][slotrank][lane] =
3659 min(rn.end - ctrl->timC_offset[i],
3660 upper[channel][slotrank][lane]);
3661
3662 }
3663 }
3664 }
3665 }
3666
3667 FOR_ALL_CHANNELS {
3668 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
3669 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
3670 ~0x3f000000));
3671 udelay(2);
3672 }
3673
3674 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
3675
3676 printram("CPB\n");
3677
3678 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
Patrick Rudolpha649a542016-01-17 18:32:06 +01003679 printram("timC %d, %d, %d: %x\n", channel,
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003680 slotrank, lane,
3681 (lower[channel][slotrank][lane] +
3682 upper[channel][slotrank][lane]) / 2);
3683 ctrl->timings[channel][slotrank].lanes[lane].timC =
3684 (lower[channel][slotrank][lane] +
3685 upper[channel][slotrank][lane]) / 2;
3686 }
3687 FOR_ALL_POPULATED_CHANNELS {
3688 program_timings(ctrl, channel);
3689 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003690 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003691}
3692
3693static void normalize_training(ramctr_timing * ctrl)
3694{
3695 int channel, slotrank, lane;
3696 int mat = 0;
3697
3698 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3699 int delta;
3700 FOR_ALL_LANES mat =
3701 max(ctrl->timings[channel][slotrank].lanes[lane].timA, mat);
3702 delta = (mat >> 6) - ctrl->timings[channel][slotrank].val_4028;
3703 ctrl->timings[channel][slotrank].val_4024 += delta;
3704 ctrl->timings[channel][slotrank].val_4028 += delta;
3705 }
3706
3707 FOR_ALL_POPULATED_CHANNELS {
3708 program_timings(ctrl, channel);
3709 }
3710}
3711
3712static void write_controller_mr(ramctr_timing * ctrl)
3713{
3714 int channel, slotrank;
3715
3716 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS {
3717 write32(DEFAULT_MCHBAR + 0x0004 + (channel << 8) +
3718 lane_registers[slotrank], make_mr0(ctrl, slotrank));
3719 write32(DEFAULT_MCHBAR + 0x0008 + (channel << 8) +
Patrick Rudolph7e513d12016-01-10 14:22:34 +01003720 lane_registers[slotrank],
3721 make_mr1(ctrl, slotrank, channel));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003722 }
3723}
3724
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003725static int channel_test(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003726{
3727 int channel, slotrank, lane;
3728
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003729 slotrank = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003730 FOR_ALL_POPULATED_CHANNELS
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003731 if (read32(DEFAULT_MCHBAR + 0x42a0 + (channel << 10)) & 0xa000) {
3732 printk(BIOS_EMERG, "Mini channel test failed (1): %d\n",
3733 channel);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003734 return MAKE_ERR;
3735 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003736 FOR_ALL_POPULATED_CHANNELS {
3737 fill_pattern0(ctrl, channel, 0x12345678, 0x98765432);
3738
3739 write32(DEFAULT_MCHBAR + 0x4288 + (channel << 10), 0);
3740 }
3741
3742 for (slotrank = 0; slotrank < 4; slotrank++)
3743 FOR_ALL_CHANNELS
3744 if (ctrl->rankmap[channel] & (1 << slotrank)) {
3745 FOR_ALL_LANES {
3746 write32(DEFAULT_MCHBAR + (0x4f40 + 4 * lane), 0);
3747 write32(DEFAULT_MCHBAR + (0x4d40 + 4 * lane), 0);
3748 }
3749 wait_428c(channel);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003750 /* DRAM command ACT */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003751 write32(DEFAULT_MCHBAR + 0x4220 + (channel << 10), 0x0001f006);
3752 write32(DEFAULT_MCHBAR + 0x4230 + (channel << 10), 0x0028a004);
3753 write32(DEFAULT_MCHBAR + 0x4200 + (channel << 10),
3754 0x00060000 | (slotrank << 24));
3755 write32(DEFAULT_MCHBAR + 0x4210 + (channel << 10), 0x00000244);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003756 /* DRAM command WR */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003757 write32(DEFAULT_MCHBAR + 0x4224 + (channel << 10), 0x0001f201);
3758 write32(DEFAULT_MCHBAR + 0x4234 + (channel << 10), 0x08281064);
3759 write32(DEFAULT_MCHBAR + 0x4204 + (channel << 10),
3760 0x00000000 | (slotrank << 24));
3761 write32(DEFAULT_MCHBAR + 0x4214 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003762 /* DRAM command RD */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003763 write32(DEFAULT_MCHBAR + 0x4228 + (channel << 10), 0x0001f105);
3764 write32(DEFAULT_MCHBAR + 0x4238 + (channel << 10), 0x04281064);
3765 write32(DEFAULT_MCHBAR + 0x4208 + (channel << 10),
3766 0x00000000 | (slotrank << 24));
3767 write32(DEFAULT_MCHBAR + 0x4218 + (channel << 10), 0x00000242);
Patrick Rudolph371d2912015-10-09 13:33:25 +02003768 /* DRAM command PRE */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003769 write32(DEFAULT_MCHBAR + 0x422c + (channel << 10), 0x0001f002);
3770 write32(DEFAULT_MCHBAR + 0x423c + (channel << 10), 0x00280c01);
3771 write32(DEFAULT_MCHBAR + 0x420c + (channel << 10),
3772 0x00060400 | (slotrank << 24));
3773 write32(DEFAULT_MCHBAR + 0x421c + (channel << 10), 0x00000240);
3774 write32(DEFAULT_MCHBAR + 0x4284 + (channel << 10), 0x000c0001);
3775 wait_428c(channel);
3776 FOR_ALL_LANES
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003777 if (read32(DEFAULT_MCHBAR + 0x4340 + (channel << 10) + 4 * lane)) {
3778 printk(BIOS_EMERG, "Mini channel test failed (2): %d, %d, %d\n",
3779 channel, slotrank, lane);
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003780 return MAKE_ERR;
3781 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003782 }
Patrick Rudolph24a845b2016-03-25 18:19:47 +01003783 return 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003784}
3785
3786static void set_scrambling_seed(ramctr_timing * ctrl)
3787{
3788 int channel;
3789
3790 /* FIXME: we hardcode seeds. Do we need to use some PRNG for them?
3791 I don't think so. */
3792 static u32 seeds[NUM_CHANNELS][3] = {
3793 {0x00009a36, 0xbafcfdcf, 0x46d1ab68},
3794 {0x00028bfa, 0x53fe4b49, 0x19ed5483}
3795 };
3796 FOR_ALL_POPULATED_CHANNELS {
3797 MCHBAR32(0x4020 + 0x400 * channel) &= ~0x10000000;
3798 write32(DEFAULT_MCHBAR + 0x4034, seeds[channel][0]);
3799 write32(DEFAULT_MCHBAR + 0x403c, seeds[channel][1]);
3800 write32(DEFAULT_MCHBAR + 0x4038, seeds[channel][2]);
3801 }
3802}
3803
3804static void set_4f8c(void)
3805{
3806 struct cpuid_result cpures;
3807 u32 cpu;
3808
Ryan Salsamendie4da9aa2016-06-24 12:01:11 -07003809 cpures = cpuid(1);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003810 cpu = (cpures.eax);
3811 if (IS_SANDY_CPU(cpu) && (IS_SANDY_CPU_D0(cpu) || IS_SANDY_CPU_D1(cpu))) {
3812 MCHBAR32(0x4f8c) = 0x141D1519;
3813 } else {
3814 MCHBAR32(0x4f8c) = 0x551D1519;
3815 }
3816}
3817
3818static void prepare_training(ramctr_timing * ctrl)
3819{
3820 int channel;
3821
3822 FOR_ALL_POPULATED_CHANNELS {
3823 // Always drive command bus
3824 MCHBAR32(0x4004 + 0x400 * channel) |= 0x20000000;
3825 }
3826
3827 udelay(1);
3828
3829 FOR_ALL_POPULATED_CHANNELS {
3830 wait_428c(channel);
3831 }
3832}
3833
3834static void set_4008c(ramctr_timing * ctrl)
3835{
3836 int channel, slotrank;
3837 u32 reg;
3838 FOR_ALL_POPULATED_CHANNELS {
3839 u32 b20, b4_8_12;
3840 int min_320c = 10000;
3841 int max_320c = -10000;
3842
3843 FOR_ALL_POPULATED_RANKS {
3844 max_320c = max(ctrl->timings[channel][slotrank].val_320c, max_320c);
3845 min_320c = min(ctrl->timings[channel][slotrank].val_320c, min_320c);
3846 }
3847
3848 if (max_320c - min_320c > 51)
3849 b20 = 0;
3850 else
3851 b20 = ctrl->ref_card_offset[channel];
3852
3853 if (ctrl->reg_320c_range_threshold < max_320c - min_320c)
3854 b4_8_12 = 0x3330;
3855 else
3856 b4_8_12 = 0x2220;
3857
3858 reg = read32(DEFAULT_MCHBAR + 0x400c + (channel << 10));
3859 write32(DEFAULT_MCHBAR + 0x400c + (channel << 10),
3860 (reg & 0xFFF0FFFF)
3861 | (ctrl->ref_card_offset[channel] << 16)
3862 | (ctrl->ref_card_offset[channel] << 18));
3863 write32(DEFAULT_MCHBAR + 0x4008 + (channel << 10),
3864 0x0a000000
3865 | (b20 << 20)
3866 | ((ctrl->ref_card_offset[channel] + 2) << 16)
3867 | b4_8_12);
3868 }
3869}
3870
3871static void set_42a0(ramctr_timing * ctrl)
3872{
3873 int channel;
3874 FOR_ALL_POPULATED_CHANNELS {
3875 write32(DEFAULT_MCHBAR + (0x42a0 + 0x400 * channel),
3876 0x00001000 | ctrl->rankmap[channel]);
3877 MCHBAR32(0x4004 + 0x400 * channel) &= ~0x20000000; // OK
3878 }
3879}
3880
3881static int encode_5d10(int ns)
3882{
3883 return (ns + 499) / 500;
3884}
3885
3886/* FIXME: values in this function should be hardware revision-dependent. */
3887static void final_registers(ramctr_timing * ctrl)
3888{
3889 int channel;
3890 int t1_cycles = 0, t1_ns = 0, t2_ns;
3891 int t3_ns;
3892 u32 r32;
3893
3894 write32(DEFAULT_MCHBAR + 0x4cd4, 0x00000046);
3895
3896 write32(DEFAULT_MCHBAR + 0x400c, (read32(DEFAULT_MCHBAR + 0x400c) & 0xFFFFCFFF) | 0x1000); // OK
3897 write32(DEFAULT_MCHBAR + 0x440c, (read32(DEFAULT_MCHBAR + 0x440c) & 0xFFFFCFFF) | 0x1000); // OK
3898 write32(DEFAULT_MCHBAR + 0x4cb0, 0x00000740);
3899 write32(DEFAULT_MCHBAR + 0x4380, 0x00000aaa); // OK
3900 write32(DEFAULT_MCHBAR + 0x4780, 0x00000aaa); // OK
3901 write32(DEFAULT_MCHBAR + 0x4f88, 0x5f7003ff); // OK
3902 write32(DEFAULT_MCHBAR + 0x5064, 0x00073000 | ctrl->reg_5064b0); // OK
3903
3904 FOR_ALL_CHANNELS {
3905 switch (ctrl->rankmap[channel]) {
3906 /* Unpopulated channel. */
3907 case 0:
3908 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0);
3909 break;
3910 /* Only single-ranked dimms. */
3911 case 1:
3912 case 4:
3913 case 5:
3914 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x373131);
3915 break;
3916 /* Dual-ranked dimms present. */
3917 default:
3918 write32(DEFAULT_MCHBAR + 0x4384 + channel * 0x400, 0x9b6ea1);
3919 break;
3920 }
3921 }
3922
3923 write32 (DEFAULT_MCHBAR + 0x5880, 0xca9171e5);
3924 write32 (DEFAULT_MCHBAR + 0x5888,
3925 (read32 (DEFAULT_MCHBAR + 0x5888) & ~0xffffff) | 0xe4d5d0);
3926 write32 (DEFAULT_MCHBAR + 0x58a8, read32 (DEFAULT_MCHBAR + 0x58a8) & ~0x1f);
3927 write32 (DEFAULT_MCHBAR + 0x4294,
3928 (read32 (DEFAULT_MCHBAR + 0x4294) & ~0x30000)
3929 | (1 << 16));
3930 write32 (DEFAULT_MCHBAR + 0x4694,
3931 (read32 (DEFAULT_MCHBAR + 0x4694) & ~0x30000)
3932 | (1 << 16));
3933
3934 MCHBAR32(0x5030) |= 1; // OK
3935 MCHBAR32(0x5030) |= 0x80; // OK
3936 MCHBAR32(0x5f18) = 0xfa; // OK
3937
3938 /* Find a populated channel. */
3939 FOR_ALL_POPULATED_CHANNELS
3940 break;
3941
3942 t1_cycles = ((read32(DEFAULT_MCHBAR + 0x4290 + channel * 0x400) >> 8) & 0xff);
3943 r32 = read32(DEFAULT_MCHBAR + 0x5064);
3944 if (r32 & 0x20000)
3945 t1_cycles += (r32 & 0xfff);
3946 t1_cycles += (read32(DEFAULT_MCHBAR + channel * 0x400 + 0x42a4) & 0xfff);
3947 t1_ns = t1_cycles * ctrl->tCK / 256 + 544;
3948 if (!(r32 & 0x20000))
3949 t1_ns += 500;
3950
3951 t2_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f10) >> 8) & 0xfff);
3952 if ( read32(DEFAULT_MCHBAR + 0x5f00) & 8 )
3953 {
3954 t3_ns = 10 * ((read32(DEFAULT_MCHBAR + 0x5f20) >> 8) & 0xfff);
3955 t3_ns += 10 * (read32(DEFAULT_MCHBAR + 0x5f18) & 0xff);
3956 }
3957 else
3958 {
3959 t3_ns = 500;
3960 }
3961 printk(BIOS_DEBUG, "t123: %d, %d, %d\n",
3962 t1_ns, t2_ns, t3_ns);
3963 write32 (DEFAULT_MCHBAR + 0x5d10,
3964 ((encode_5d10(t1_ns) + encode_5d10(t2_ns)) << 16)
3965 | (encode_5d10(t1_ns) << 8)
3966 | ((encode_5d10(t3_ns) + encode_5d10(t2_ns) + encode_5d10(t1_ns)) << 24)
3967 | (read32(DEFAULT_MCHBAR + 0x5d10) & 0xC0C0C0C0)
3968 | 0xc);
3969}
3970
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003971static void save_timings(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003972{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003973 /* Save the MRC S3 restore data to cbmem */
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +02003974 store_current_mrc_cache(ctrl, sizeof(*ctrl));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07003975}
3976
3977static void restore_timings(ramctr_timing * ctrl)
3978{
3979 int channel, slotrank, lane;
3980
3981 FOR_ALL_POPULATED_CHANNELS
3982 MCHBAR32(0x4004 + 0x400 * channel) =
3983 ctrl->tRRD
3984 | (ctrl->tRTP << 4)
3985 | (ctrl->tCKE << 8)
3986 | (ctrl->tWTR << 12)
3987 | (ctrl->tFAW << 16)
3988 | (ctrl->tWR << 24)
3989 | (ctrl->cmd_stretch[channel] << 30);
3990
3991 udelay(1);
3992
3993 FOR_ALL_POPULATED_CHANNELS {
3994 wait_428c(channel);
3995 }
3996
3997 FOR_ALL_CHANNELS FOR_ALL_POPULATED_RANKS FOR_ALL_LANES {
3998 write32(DEFAULT_MCHBAR + 0x4080 + 0x400 * channel
3999 + 4 * lane, 0);
4000 }
4001
4002 FOR_ALL_POPULATED_CHANNELS
4003 write32(DEFAULT_MCHBAR + 0x4008 + 0x400 * channel,
4004 read32(DEFAULT_MCHBAR + 0x4008 +
4005 0x400 * channel) | 0x8000000);
4006
4007 FOR_ALL_POPULATED_CHANNELS {
4008 udelay (1);
4009 write32(DEFAULT_MCHBAR + 0x4020 + 0x400 * channel,
4010 read32(DEFAULT_MCHBAR + 0x4020 +
4011 0x400 * channel) | 0x200000);
4012 }
4013
4014 printram("CPE\n");
4015
4016 write32(DEFAULT_MCHBAR + 0x3400, 0);
4017 write32(DEFAULT_MCHBAR + 0x4eb0, 0);
4018
4019 printram("CP5b\n");
4020
4021 FOR_ALL_POPULATED_CHANNELS {
4022 program_timings(ctrl, channel);
4023 }
4024
4025 u32 reg, addr;
4026
Elyes HAOUAS7db506c2016-10-02 11:56:39 +02004027 while (!(MCHBAR32(0x5084) & 0x10000));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004028 do {
4029 reg = MCHBAR32(0x428c);
4030 } while ((reg & 0x14) == 0);
4031
4032 // Set state of memory controller
4033 MCHBAR32(0x5030) = 0x116;
4034 MCHBAR32(0x4ea0) = 0;
4035
4036 // Wait 500us
4037 udelay(500);
4038
4039 FOR_ALL_CHANNELS {
4040 // Set valid rank CKE
4041 reg = 0;
4042 reg = (reg & ~0xf) | ctrl->rankmap[channel];
4043 addr = 0x400 * channel + 0x42a0;
4044 MCHBAR32(addr) = reg;
4045
4046 // Wait 10ns for ranks to settle
4047 //udelay(0.01);
4048
4049 reg = (reg & ~0xf0) | (ctrl->rankmap[channel] << 4);
4050 MCHBAR32(addr) = reg;
4051
4052 // Write reset using a NOP
4053 write_reset(ctrl);
4054 }
4055
4056 /* mrs commands. */
4057 dram_mrscommands(ctrl);
4058
4059 printram("CP5c\n");
4060
4061 write32(DEFAULT_MCHBAR + 0x3000, 0);
4062
4063 FOR_ALL_CHANNELS {
4064 write32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c,
4065 0 | (read32(DEFAULT_MCHBAR + (channel * 0x100) + 0xe3c) &
4066 ~0x3f000000));
4067 udelay(2);
4068 }
4069
4070 write32(DEFAULT_MCHBAR + 0x4ea8, 0);
4071}
4072
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004073static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot,
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004074 int s3_resume, int me_uma_size)
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004075{
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004076 int err;
4077
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004078 printk(BIOS_DEBUG, "Starting RAM training (%d).\n", fast_boot);
4079
4080 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004081 /* Find fastest common supported parameters */
4082 dram_find_common_params(ctrl);
4083
4084 dram_dimm_mapping(ctrl);
4085 }
4086
4087 /* Set MCU frequency */
4088 dram_freq(ctrl);
4089
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004090 if (!fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004091 /* Calculate timings */
4092 dram_timing(ctrl);
4093 }
4094
4095 /* Set version register */
4096 MCHBAR32(0x5034) = 0xC04EB002;
4097
4098 /* Enable crossover */
4099 dram_xover(ctrl);
4100
4101 /* Set timing and refresh registers */
4102 dram_timing_regs(ctrl);
4103
4104 /* Power mode preset */
4105 MCHBAR32(0x4e80) = 0x5500;
4106
4107 /* Set scheduler parameters */
4108 MCHBAR32(0x4c20) = 0x10100005;
4109
Elyes HAOUAS15279a92016-07-28 21:05:26 +02004110 /* Set CPU specific register */
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004111 set_4f8c();
4112
4113 /* Clear IO reset bit */
4114 MCHBAR32(0x5030) &= ~0x20;
4115
4116 /* Set MAD-DIMM registers */
4117 dram_dimm_set_mapping(ctrl);
4118 printk(BIOS_DEBUG, "Done dimm mapping\n");
4119
4120 /* Zone config */
4121 dram_zones(ctrl, 1);
4122
4123 /* Set memory map */
4124 dram_memorymap(ctrl, me_uma_size);
4125 printk(BIOS_DEBUG, "Done memory map\n");
4126
4127 /* Set IO registers */
4128 dram_ioregs(ctrl);
4129 printk(BIOS_DEBUG, "Done io registers\n");
4130
4131 udelay(1);
4132
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004133 if (fast_boot) {
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004134 restore_timings(ctrl);
4135 } else {
4136 /* Do jedec ddr3 reset sequence */
4137 dram_jedecreset(ctrl);
4138 printk(BIOS_DEBUG, "Done jedec reset\n");
4139
4140 /* MRS commands */
4141 dram_mrscommands(ctrl);
4142 printk(BIOS_DEBUG, "Done MRS commands\n");
4143
4144 /* Prepare for memory training */
4145 prepare_training(ctrl);
4146
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004147 err = read_training(ctrl);
4148 if (err)
4149 return err;
4150
4151 err = write_training(ctrl);
4152 if (err)
4153 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004154
4155 printram("CP5a\n");
4156
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004157 err = discover_edges(ctrl);
4158 if (err)
4159 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004160
4161 printram("CP5b\n");
4162
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004163 err = command_training(ctrl);
4164 if (err)
4165 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004166
4167 printram("CP5c\n");
4168
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004169 err = discover_edges_write(ctrl);
4170 if (err)
4171 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004172
Patrick Rudolph24a845b2016-03-25 18:19:47 +01004173 err = discover_timC_write(ctrl);
4174 if (err)
4175 return err;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004176
4177 normalize_training(ctrl);
4178 }
4179
4180 set_4008c(ctrl);
4181
4182 write_controller_mr(ctrl);
4183
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004184 if (!s3_resume) {
4185 err = channel_test(ctrl);
4186 if (err)
4187 return err;
4188 }
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004189
4190 return 0;
4191}
4192
Kyösti Mälkki4cb44e52016-11-18 19:11:24 +02004193static void init_dram_ddr3(int mobile, int min_tck, int s3resume)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004194{
4195 int me_uma_size;
4196 int cbmem_was_inited;
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004197 ramctr_timing ctrl;
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004198 int fast_boot;
Kyösti Mälkki4cb44e52016-11-18 19:11:24 +02004199 spd_raw_data spds[4];
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004200 struct mrc_data_container *mrc_cache;
4201 ramctr_timing *ctrl_cached;
Patrick Rudolph31d19592016-03-26 12:22:34 +01004202 int err;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004203
4204 MCHBAR32(0x5f00) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004205
Vadim Bendebury7a3f36a2012-04-18 15:47:32 -07004206 report_platform_info();
4207
Stefan Reinauer00636b02012-04-04 00:08:51 +02004208 /* Wait for ME to be ready */
4209 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004210 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004211
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004212 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +02004213
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004214 u32 reg_5d10;
Stefan Reinauer00636b02012-04-04 00:08:51 +02004215
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004216 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004217
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004218 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +02004219
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004220 reg_5d10 = read32(DEFAULT_MCHBAR + 0x5d10); // !!! = 0x00000000
4221 if ((pcie_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 /* 0x0004 */
4222 && reg_5d10 && !s3resume) {
4223 write32(DEFAULT_MCHBAR + 0x5d10, 0);
4224 /* Need reset. */
Stefan Reinauer00636b02012-04-04 00:08:51 +02004225 outb(0x6, 0xcf9);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004226
Patrick Georgi546953c2014-11-29 10:38:17 +01004227 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004228 }
Stefan Reinauer00636b02012-04-04 00:08:51 +02004229
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004230 early_pch_init_native();
4231 early_thermal_init();
4232
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004233 /* try to find timings in MRC cache */
4234 mrc_cache = find_current_mrc_cache();
4235 if (!mrc_cache || (mrc_cache->mrc_data_size < sizeof(ctrl))) {
4236 if (s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004237 /* Failed S3 resume, reset to come up cleanly */
4238 outb(0x6, 0xcf9);
4239 halt();
Stefan Reinauer00636b02012-04-04 00:08:51 +02004240 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004241 ctrl_cached = NULL;
Patrick Rudolph27e085a2016-03-26 10:59:02 +01004242 } else {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004243 ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004244 }
4245
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004246 /* verify MRC cache for fast boot */
Kyösti Mälkki38cb8222016-11-18 19:25:52 +02004247 if (!s3resume && ctrl_cached) {
Kyösti Mälkkie258b9a2016-11-18 19:59:23 +02004248 /* Load SPD unique information data. */
4249 memset(spds, 0, sizeof(spds));
4250 mainboard_get_spd(spds, 1);
4251
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004252 /* check SPD CRC16 to make sure the DIMMs haven't been replaced */
4253 fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
4254 if (!fast_boot)
4255 printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
Kyösti Mälkki38cb8222016-11-18 19:25:52 +02004256 } else {
4257 fast_boot = s3resume;
4258 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004259
4260 if (fast_boot) {
4261 printk(BIOS_DEBUG, "Trying stored timings.\n");
4262 memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
4263
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004264 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004265 if (err) {
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004266 if (s3resume) {
4267 /* Failed S3 resume, reset to come up cleanly */
4268 outb(0x6, 0xcf9);
4269 halt();
4270 }
4271 /* no need to erase bad mrc cache here, it gets overwritten on
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004272 * successful boot. */
4273 printk(BIOS_ERR, "Stored timings are invalid !\n");
4274 fast_boot = 0;
4275 }
4276 }
4277 if (!fast_boot) {
Patrick Rudolphe74ad212016-11-16 18:06:50 +01004278 /* Reset internal state */
4279 memset(&ctrl, 0, sizeof(ctrl));
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004280 ctrl.mobile = mobile;
4281 ctrl.tCK = min_tck;
4282
4283 /* Get DDR3 SPD data */
Kyösti Mälkkie258b9a2016-11-18 19:59:23 +02004284 memset(spds, 0, sizeof(spds));
4285 mainboard_get_spd(spds, 0);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004286 dram_find_spds_ddr3(spds, &ctrl);
4287
Patrick Rudolph588ccaa2016-04-20 18:00:27 +02004288 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004289 }
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004290
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004291 if (err) {
4292 /* fallback: disable failing channel */
4293 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
4294 printram("Disable failing channel.\n");
4295
Patrick Rudolphe74ad212016-11-16 18:06:50 +01004296 /* Reset internal state */
4297 memset(&ctrl, 0, sizeof(ctrl));
4298 ctrl.mobile = mobile;
4299 ctrl.tCK = min_tck;
4300
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +01004301 /* Reset DDR3 frequency */
4302 dram_find_spds_ddr3(spds, &ctrl);
4303
4304 /* disable failing channel */
4305 disable_channel(&ctrl, GET_ERR_CHANNEL(err));
4306
4307 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
4308 }
4309
Patrick Rudolph31d19592016-03-26 12:22:34 +01004310 if (err)
4311 die("raminit failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004312
4313 /* FIXME: should be hardware revision-dependent. */
4314 write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);
4315
4316 set_scrambling_seed(&ctrl);
4317
4318 set_42a0(&ctrl);
4319
4320 final_registers(&ctrl);
4321
4322 /* Zone config */
4323 dram_zones(&ctrl, 0);
4324
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004325 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004326 quick_ram_check();
4327
4328 intel_early_me_status();
4329 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
4330 intel_early_me_status();
4331
Stefan Reinauer00636b02012-04-04 00:08:51 +02004332 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004333
4334 cbmem_was_inited = !cbmem_recovery(s3resume);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +01004335 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07004336 save_timings(&ctrl);
4337 if (s3resume && !cbmem_was_inited) {
4338 /* Failed S3 resume, reset to come up cleanly */
4339 outb(0x6, 0xcf9);
4340 halt();
4341 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +01004342
Patrick Rudolph735ecce2016-03-26 10:42:27 +01004343 fill_smbios17(&ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +02004344}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004345
4346#define HOST_BRIDGE PCI_DEVFN(0, 0)
4347#define DEFAULT_TCK TCK_800MHZ
4348
4349static unsigned int get_mem_min_tck(void)
4350{
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004351 u32 reg32;
4352 u8 rev;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004353 const struct device *dev;
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004354 const struct northbridge_intel_sandybridge_config *cfg = NULL;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004355
4356 dev = dev_find_slot(0, HOST_BRIDGE);
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004357 if (dev)
4358 cfg = dev->chip_info;
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004359
4360 /* If this is zero, it just means devicetree.cb didn't set it */
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004361 if (!cfg || cfg->max_mem_clock_mhz == 0) {
4362 rev = pci_read_config8(PCI_DEV(0, 0, 0), PCI_DEVICE_ID);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004363
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004364 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
4365 /* read Capabilities A Register DMFC bits */
4366 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A);
4367 reg32 &= 0x7;
4368
4369 switch (reg32) {
4370 case 7: return TCK_533MHZ;
4371 case 6: return TCK_666MHZ;
4372 case 5: return TCK_800MHZ;
4373 /* reserved: */
4374 default:
4375 break;
4376 }
4377 } else {
4378 /* read Capabilities B Register DMFC bits */
4379 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
4380 reg32 = (reg32 >> 4) & 0x7;
4381
4382 switch (reg32) {
4383 case 7: return TCK_533MHZ;
4384 case 6: return TCK_666MHZ;
4385 case 5: return TCK_800MHZ;
4386 case 4: return TCK_933MHZ;
4387 case 3: return TCK_1066MHZ;
4388 case 2: return TCK_1200MHZ;
4389 case 1: return TCK_1333MHZ;
4390 /* reserved: */
4391 default:
4392 break;
4393 }
4394 }
4395 return DEFAULT_TCK;
4396 } else {
Patrick Rudolph7bddd302016-06-11 18:39:35 +02004397 if (cfg->max_mem_clock_mhz >= 1066)
4398 return TCK_1066MHZ;
4399 else if (cfg->max_mem_clock_mhz >= 933)
4400 return TCK_933MHZ;
4401 else if (cfg->max_mem_clock_mhz >= 800)
Patrick Rudolph9f3f9152016-01-26 20:02:14 +01004402 return TCK_800MHZ;
4403 else if (cfg->max_mem_clock_mhz >= 666)
4404 return TCK_666MHZ;
4405 else if (cfg->max_mem_clock_mhz >= 533)
4406 return TCK_533MHZ;
4407 else
4408 return TCK_400MHZ;
4409 }
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004410}
4411
Patrick Rudolph266a1f72016-06-09 18:13:34 +02004412#define DEFAULT_PCI_MMIO_SIZE 2048
4413
4414static unsigned int get_mmio_size(void)
4415{
4416 const struct device *dev;
4417 const struct northbridge_intel_sandybridge_config *cfg = NULL;
4418
4419 dev = dev_find_slot(0, HOST_BRIDGE);
4420 if (dev)
4421 cfg = dev->chip_info;
4422
4423 /* If this is zero, it just means devicetree.cb didn't set it */
4424 if (!cfg || cfg->pci_mmio_size == 0)
4425 return DEFAULT_PCI_MMIO_SIZE;
4426 else
4427 return cfg->pci_mmio_size;
4428}
4429
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004430void perform_raminit(int s3resume)
4431{
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004432 post_code(0x3a);
4433
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004434 timestamp_add_now(TS_BEFORE_INITRAM);
4435
Kyösti Mälkki4cb44e52016-11-18 19:11:24 +02004436 init_dram_ddr3(1, get_mem_min_tck(), s3resume);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +01004437}