blob: 97bf50b52d1fd9f43b6b55c1d57319c450dc65a0 [file] [log] [blame]
Patrick Rudolph305035c2016-11-11 18:38:50 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 Damien Zammit <damien@zamaudio.com>
5 * Copyright (C) 2014 Vladimir Serbinenko <phcoder@gmail.com>
6 * Copyright (C) 2016 Patrick Rudolph <siro@das-labor.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <console/console.h>
19#include <console/usb.h>
20#include <cpu/x86/msr.h>
21#include <delay.h>
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +010022#include <arch/io.h>
23#include <device/pci_ops.h>
Patrick Rudolph305035c2016-11-11 18:38:50 +010024#include "raminit_native.h"
25#include "raminit_common.h"
26
27/* Frequency multiplier. */
Patrick Rudolph77eaba32016-11-11 18:55:54 +010028static u32 get_FRQ(u32 tCK, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +010029{
30 u32 FRQ;
Patrick Rudolph77eaba32016-11-11 18:55:54 +010031
32 FRQ = 256000 / (tCK * base_freq);
33
34 if (base_freq == 100) {
35 if (FRQ > 12)
36 return 12;
37 if (FRQ < 7)
38 return 7;
39 } else {
40 if (FRQ > 10)
41 return 10;
42 if (FRQ < 3)
43 return 3;
44 }
45
Patrick Rudolph305035c2016-11-11 18:38:50 +010046 return FRQ;
47}
48
Patrick Rudolph77eaba32016-11-11 18:55:54 +010049static u32 get_REFI(u32 tCK, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +010050{
Patrick Rudolph77eaba32016-11-11 18:55:54 +010051 u32 refi;
52
53 if (base_freq == 100) {
54 /* Get REFI based on MCU frequency using the following rule:
55 * tREFI = 7.8usec
56 * _________________________________________
57 * FRQ : | 7 | 8 | 9 | 10 | 11 | 12 |
58 * REFI : | 5460 | 6240 | 7020 | 7800 | 8580 | 9360 |
59 */
60 static const u32 frq_xs_map[] =
61 { 5460, 6240, 7020, 7800, 8580, 9360 };
62 refi = frq_xs_map[get_FRQ(tCK, 100) - 7];
63 } else {
64 /* Get REFI based on MCU frequency using the following rule:
65 * tREFI = 7.8usec
66 * ________________________________________________________
67 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
68 * REFI: | 3120 | 4160 | 5200 | 6240 | 7280 | 8320 | 9360 | 10400 |
69 */
70 static const u32 frq_refi_map[] =
71 { 3120, 4160, 5200, 6240, 7280, 8320, 9360, 10400 };
72 refi = frq_refi_map[get_FRQ(tCK, 133) - 3];
73 }
74
75 return refi;
Patrick Rudolph305035c2016-11-11 18:38:50 +010076}
77
Patrick Rudolph77eaba32016-11-11 18:55:54 +010078static u8 get_XSOffset(u32 tCK, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +010079{
Patrick Rudolph77eaba32016-11-11 18:55:54 +010080 u8 xsoffset;
81
82 if (base_freq == 100) {
83 /* Get XSOffset based on MCU frequency using the following rule:
84 * tXS-offset: tXS = tRFC+10ns.
85 * _____________________________
86 * FRQ : | 7 | 8 | 9 | 10 | 11 | 12 |
87 * XSOffset : | 7 | 8 | 9 | 10 | 11 | 12 |
88 */
89 static const u8 frq_xs_map[] = { 7, 8, 9, 10, 11, 12 };
90 xsoffset = frq_xs_map[get_FRQ(tCK, 100) - 7];
91 } else {
92 /* Get XSOffset based on MCU frequency using the following rule:
93 * ___________________________________
94 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
95 * XSOffset : | 4 | 6 | 7 | 8 | 10 | 11 | 12 | 14 |
96 */
97 static const u8 frq_xs_map[] = { 4, 6, 7, 8, 10, 11, 12, 14 };
98 xsoffset = frq_xs_map[get_FRQ(tCK, 133) - 3];
99 }
100
101 return xsoffset;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100102}
103
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100104static u8 get_MOD(u32 tCK, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100105{
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100106 u8 mod;
107
108 if (base_freq == 100) {
109 /* Get MOD based on MCU frequency using the following rule:
110 * _____________________________
111 * FRQ : | 7 | 8 | 9 | 10 | 11 | 12 |
112 * MOD : | 12 | 12 | 14 | 15 | 17 | 18 |
113 */
114
115 static const u8 frq_mod_map[] = { 12, 12, 14, 15, 17, 18 };
116 mod = frq_mod_map[get_FRQ(tCK, 100) - 7];
117 } else {
118 /* Get MOD based on MCU frequency using the following rule:
119 * _______________________________________
120 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
121 * MOD : | 12 | 12 | 12 | 12 | 15 | 16 | 18 | 20 |
122 */
123
124 static const u8 frq_mod_map[] = { 12, 12, 12, 12, 15, 16, 18, 20 };
125 mod = frq_mod_map[get_FRQ(tCK, 133) - 3];
126 }
127 return mod;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100128}
129
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100130static u8 get_WLO(u32 tCK, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100131{
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100132 u8 wlo;
133
134 if (base_freq == 100) {
135 /* Get WLO based on MCU frequency using the following rule:
136 * Write leveling output delay
137 * _____________________________
138 * FRQ : | 7 | 8 | 9 | 10 | 11 | 12 |
139 * MOD : | 6 | 6 | 7 | 8 | 9 | 9 |
140 */
141
142 static const u8 frq_wlo_map[] = { 6, 6, 7, 8, 9, 9 };
143 wlo = frq_wlo_map[get_FRQ(tCK, 100) - 7];
144 } else {
145 /* Get WLO based on MCU frequency using the following rule:
146 * Write leveling output delay
147 * ________________________________
148 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
149 * WLO : | 4 | 5 | 6 | 6 | 8 | 8 | 9 | 10 |
150 */
151 static const u8 frq_wlo_map[] = { 4, 5, 6, 6, 8, 8, 9, 10 };
152 wlo = frq_wlo_map[get_FRQ(tCK, 133) - 3];
153 }
154
155 return wlo;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100156}
157
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100158static u8 get_CKE(u32 tCK, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100159{
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100160 u8 cke;
161
162 if (base_freq == 100) {
163 /* Get CKE based on MCU frequency using the following rule:
164 * _____________________________
165 * FRQ : | 7 | 8 | 9 | 10 | 11 | 12 |
166 * MOD : | 4 | 4 | 5 | 5 | 6 | 6 |
167 */
168
169 static const u8 frq_cke_map[] = { 4, 4, 5, 5, 6, 6 };
170 cke = frq_cke_map[get_FRQ(tCK, 100) - 7];
171 } else {
172 /* Get CKE based on MCU frequency using the following rule:
173 * ________________________________
174 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
175 * WLO : | 3 | 3 | 4 | 4 | 5 | 6 | 6 | 7 |
176 */
177 static const u8 frq_cke_map[] = { 3, 3, 4, 4, 5, 6, 6, 7 };
178 cke = frq_cke_map[get_FRQ(tCK, 133) - 3];
179 }
180
181 return cke;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100182}
183
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100184static u8 get_XPDLL(u32 tCK, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100185{
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100186 u8 xpdll;
187
188 if (base_freq == 100) {
189 /* Get XPDLL based on MCU frequency using the following rule:
190 * _____________________________
191 * FRQ : | 7 | 8 | 9 | 10 | 11 | 12 |
192 * XPDLL : | 17 | 20 | 22 | 24 | 27 | 32 |
193 */
194
195 static const u8 frq_xpdll_map[] = { 17, 20, 22, 24, 27, 32 };
196 xpdll = frq_xpdll_map[get_FRQ(tCK, 100) - 7];
197 } else {
198 /* Get XPDLL based on MCU frequency using the following rule:
199 * _______________________________________
200 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
201 * XPDLL : | 10 | 13 | 16 | 20 | 23 | 26 | 29 | 32 |
202 */
203 static const u8 frq_xpdll_map[] = { 10, 13, 16, 20, 23, 26, 29, 32 };
204 xpdll = frq_xpdll_map[get_FRQ(tCK, 133) - 3];
205 }
206
207 return xpdll;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100208}
209
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100210static u8 get_XP(u32 tCK, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100211{
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100212 u8 xp;
213
214 if (base_freq == 100) {
215 /* Get XP based on MCU frequency using the following rule:
216 * _____________________________
217 * FRQ : | 7 | 8 | 9 | 10 | 11 | 12 |
218 * XP : | 5 | 5 | 6 | 6 | 7 | 8 |
219 */
220
221 static const u8 frq_xp_map[] = { 5, 5, 6, 6, 7, 8 };
222 xp = frq_xp_map[get_FRQ(tCK, 100) - 7];
223 } else {
224 /* Get XP based on MCU frequency using the following rule:
225 * _______________________________________
226 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
227 * XP : | 3 | 4 | 4 | 5 | 6 | 7 | 8 | 8 |
228 */
229 static const u8 frq_xp_map[] = { 3, 4, 4, 5, 6, 7 , 8, 8 };
230 xp = frq_xp_map[get_FRQ(tCK, 133) - 3];
231 }
232
233 return xp;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100234}
235
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100236static u8 get_AONPD(u32 tCK, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100237{
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100238 u8 aonpd;
239
240 if (base_freq == 100) {
241 /* Get AONPD based on MCU frequency using the following rule:
242 * _____________________________
243 * FRQ : | 7 | 8 | 9 | 10 | 11 | 12 |
244 * AONPD : | 6 | 8 | 8 | 9 | 10 | 11 |
245 */
246
247 static const u8 frq_aonpd_map[] = { 6, 8, 8, 9, 10, 11 };
248 aonpd = frq_aonpd_map[get_FRQ(tCK, 100) - 7];
249 } else {
250 /* Get AONPD based on MCU frequency using the following rule:
251 * _______________________________________
252 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
253 * AONPD : | 4 | 5 | 6 | 8 | 8 | 10 | 11 | 12 |
254 */
255 static const u8 frq_aonpd_map[] = { 4, 5, 6, 8, 8, 10, 11, 12 };
256 aonpd = frq_aonpd_map[get_FRQ(tCK, 133) - 3];
257 }
258
259 return aonpd;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100260}
261
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100262static u32 get_COMP2(u32 tCK, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100263{
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100264 u32 comp2;
265
266 if (base_freq == 100) {
267 /* Get COMP2 based on MCU frequency using the following rule:
268 * ______________________________________________________________
269 * FRQ : | 7 | 8 | 9 | 10 | 11 | 12 |
270 * COMP : | CA8C264 | C6671E4 | C6671E4 | C446964 | C235924 | C235924 |
271 */
272
273 static const u32 frq_comp2_map[] = { 0xCA8C264, 0xC6671E4, 0xC6671E4, 0xC446964, 0xC235924, 0xC235924 };
274 comp2 = frq_comp2_map[get_FRQ(tCK, 100) - 7];
275 } else {
276 /* Get COMP2 based on MCU frequency using the following rule:
277 * ________________________________________________________________________________
278 * FRQ : | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
279 * COMP : | D6FF5E4 | CEBDB64 | CA8C264 | C6671E4 | C446964 | C235924 | C235924 | C235924 |
280 */
281 static const u32 frq_comp2_map[] = { 0xD6FF5E4, 0xCEBDB64, 0xCA8C264,
282 0xC6671E4, 0xC446964, 0xC235924, 0xC235924, 0xC235924
283 };
284 comp2 = frq_comp2_map[get_FRQ(tCK, 133) - 3];
285 }
286
287 return comp2;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100288}
289
290static void dram_timing(ramctr_timing * ctrl)
291{
292 u8 val;
293 u32 val32;
294
Patrick Rudolphcb7d6a12016-11-25 15:40:49 +0100295 /* Maximum supported DDR3 frequency is 1400MHz (DDR3 2800).
296 * We cap it at 1200Mhz (DDR3 2400).
Patrick Rudolph305035c2016-11-11 18:38:50 +0100297 * Then, align it to the closest JEDEC standard frequency */
Patrick Rudolphcb7d6a12016-11-25 15:40:49 +0100298 if (ctrl->tCK <= TCK_1200MHZ) {
299 ctrl->tCK = TCK_1200MHZ;
300 ctrl->edge_offset[0] = 18; //XXX: guessed
301 ctrl->edge_offset[1] = 8;
302 ctrl->edge_offset[2] = 8;
303 ctrl->timC_offset[0] = 20; //XXX: guessed
304 ctrl->timC_offset[1] = 8;
305 ctrl->timC_offset[2] = 8;
306 ctrl->reg_320c_range_threshold = 10;
307 } else if (ctrl->tCK <= TCK_1100MHZ) {
308 ctrl->tCK = TCK_1100MHZ;
309 ctrl->edge_offset[0] = 17; //XXX: guessed
310 ctrl->edge_offset[1] = 7;
311 ctrl->edge_offset[2] = 7;
312 ctrl->timC_offset[0] = 19; //XXX: guessed
313 ctrl->timC_offset[1] = 7;
314 ctrl->timC_offset[2] = 7;
315 ctrl->reg_320c_range_threshold = 13;
316 } else if (ctrl->tCK <= TCK_1066MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100317 ctrl->tCK = TCK_1066MHZ;
318 ctrl->edge_offset[0] = 16;
319 ctrl->edge_offset[1] = 7;
320 ctrl->edge_offset[2] = 7;
321 ctrl->timC_offset[0] = 18;
322 ctrl->timC_offset[1] = 7;
323 ctrl->timC_offset[2] = 7;
324 ctrl->reg_320c_range_threshold = 13;
Patrick Rudolphcb7d6a12016-11-25 15:40:49 +0100325 } else if (ctrl->tCK <= TCK_1000MHZ) {
326 ctrl->tCK = TCK_1000MHZ;
327 ctrl->edge_offset[0] = 15; //XXX: guessed
328 ctrl->edge_offset[1] = 6;
329 ctrl->edge_offset[2] = 6;
330 ctrl->timC_offset[0] = 17; //XXX: guessed
331 ctrl->timC_offset[1] = 6;
332 ctrl->timC_offset[2] = 6;
333 ctrl->reg_320c_range_threshold = 13;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100334 } else if (ctrl->tCK <= TCK_933MHZ) {
335 ctrl->tCK = TCK_933MHZ;
336 ctrl->edge_offset[0] = 14;
337 ctrl->edge_offset[1] = 6;
338 ctrl->edge_offset[2] = 6;
339 ctrl->timC_offset[0] = 15;
340 ctrl->timC_offset[1] = 6;
341 ctrl->timC_offset[2] = 6;
342 ctrl->reg_320c_range_threshold = 15;
Patrick Rudolphcb7d6a12016-11-25 15:40:49 +0100343 } else if (ctrl->tCK <= TCK_900MHZ) {
344 ctrl->tCK = TCK_900MHZ;
345 ctrl->edge_offset[0] = 14; //XXX: guessed
346 ctrl->edge_offset[1] = 6;
347 ctrl->edge_offset[2] = 6;
348 ctrl->timC_offset[0] = 15; //XXX: guessed
349 ctrl->timC_offset[1] = 6;
350 ctrl->timC_offset[2] = 6;
351 ctrl->reg_320c_range_threshold = 12;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100352 } else if (ctrl->tCK <= TCK_800MHZ) {
353 ctrl->tCK = TCK_800MHZ;
354 ctrl->edge_offset[0] = 13;
355 ctrl->edge_offset[1] = 5;
356 ctrl->edge_offset[2] = 5;
357 ctrl->timC_offset[0] = 14;
358 ctrl->timC_offset[1] = 5;
359 ctrl->timC_offset[2] = 5;
360 ctrl->reg_320c_range_threshold = 15;
Patrick Rudolphcb7d6a12016-11-25 15:40:49 +0100361 } else if (ctrl->tCK <= TCK_700MHZ) {
362 ctrl->tCK = TCK_700MHZ;
363 ctrl->edge_offset[0] = 13; //XXX: guessed
364 ctrl->edge_offset[1] = 5;
365 ctrl->edge_offset[2] = 5;
366 ctrl->timC_offset[0] = 14; //XXX: guessed
367 ctrl->timC_offset[1] = 5;
368 ctrl->timC_offset[2] = 5;
369 ctrl->reg_320c_range_threshold = 16;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100370 } else if (ctrl->tCK <= TCK_666MHZ) {
371 ctrl->tCK = TCK_666MHZ;
372 ctrl->edge_offset[0] = 10;
373 ctrl->edge_offset[1] = 4;
374 ctrl->edge_offset[2] = 4;
375 ctrl->timC_offset[0] = 11;
376 ctrl->timC_offset[1] = 4;
377 ctrl->timC_offset[2] = 4;
378 ctrl->reg_320c_range_threshold = 16;
379 } else if (ctrl->tCK <= TCK_533MHZ) {
380 ctrl->tCK = TCK_533MHZ;
381 ctrl->edge_offset[0] = 8;
382 ctrl->edge_offset[1] = 3;
383 ctrl->edge_offset[2] = 3;
384 ctrl->timC_offset[0] = 9;
385 ctrl->timC_offset[1] = 3;
386 ctrl->timC_offset[2] = 3;
387 ctrl->reg_320c_range_threshold = 17;
388 } else {
389 ctrl->tCK = TCK_400MHZ;
390 ctrl->edge_offset[0] = 6;
391 ctrl->edge_offset[1] = 2;
392 ctrl->edge_offset[2] = 2;
393 ctrl->timC_offset[0] = 6;
394 ctrl->timC_offset[1] = 2;
395 ctrl->timC_offset[2] = 2;
396 ctrl->reg_320c_range_threshold = 17;
397 }
398
399 /* Initial phase between CLK/CMD pins */
400 ctrl->reg_c14_offset = (256000 / ctrl->tCK) / 66;
401
402 /* DLL_CONFIG_MDLL_W_TIMER */
403 ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3;
404
405 val32 = (1000 << 8) / ctrl->tCK;
406 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
407
408 /* Find CAS latency */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100409 val = DIV_ROUND_UP(ctrl->tAA, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100410 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
411 /* Find lowest supported CAS latency that satisfies the minimum value */
412 while (!((ctrl->cas_supported >> (val - MIN_CAS)) & 1)
413 && (ctrl->cas_supported >> (val - MIN_CAS))) {
414 val++;
415 }
416 /* Is CAS supported */
417 if (!(ctrl->cas_supported & (1 << (val - MIN_CAS)))) {
418 printk(BIOS_ERR, "CAS %uT not supported. ", val);
419 val = MAX_CAS;
420 /* Find highest supported CAS latency */
421 while (!((ctrl->cas_supported >> (val - MIN_CAS)) & 1))
422 val--;
423
424 printk(BIOS_ERR, "Using CAS %uT instead.\n", val);
425 }
426
427 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
428 ctrl->CAS = val;
429 ctrl->CWL = get_CWL(ctrl->tCK);
430 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
431
432 /* Find tRCD */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100433 ctrl->tRCD = DIV_ROUND_UP(ctrl->tRCD, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100434 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
435
Arthur Heymans50db9c92017-03-23 18:53:38 +0100436 ctrl->tRP = DIV_ROUND_UP(ctrl->tRP, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100437 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
438
439 /* Find tRAS */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100440 ctrl->tRAS = DIV_ROUND_UP(ctrl->tRAS, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100441 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
442
443 /* Find tWR */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100444 ctrl->tWR = DIV_ROUND_UP(ctrl->tWR, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100445 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
446
447 /* Find tFAW */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100448 ctrl->tFAW = DIV_ROUND_UP(ctrl->tFAW, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100449 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
450
451 /* Find tRRD */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100452 ctrl->tRRD = DIV_ROUND_UP(ctrl->tRRD, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100453 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
454
455 /* Find tRTP */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100456 ctrl->tRTP = DIV_ROUND_UP(ctrl->tRTP, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100457 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
458
459 /* Find tWTR */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100460 ctrl->tWTR = DIV_ROUND_UP(ctrl->tWTR, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100461 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
462
463 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100464 ctrl->tRFC = DIV_ROUND_UP(ctrl->tRFC, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100465 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
466
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100467 ctrl->tREFI = get_REFI(ctrl->tCK, ctrl->base_freq);
468 ctrl->tMOD = get_MOD(ctrl->tCK, ctrl->base_freq);
469 ctrl->tXSOffset = get_XSOffset(ctrl->tCK, ctrl->base_freq);
470 ctrl->tWLO = get_WLO(ctrl->tCK, ctrl->base_freq);
471 ctrl->tCKE = get_CKE(ctrl->tCK, ctrl->base_freq);
472 ctrl->tXPDLL = get_XPDLL(ctrl->tCK, ctrl->base_freq);
473 ctrl->tXP = get_XP(ctrl->tCK, ctrl->base_freq);
474 ctrl->tAONPD = get_AONPD(ctrl->tCK, ctrl->base_freq);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100475}
476
477static void dram_freq(ramctr_timing * ctrl)
478{
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100479 bool ref_100mhz_support;
480 u32 reg32;
481
Patrick Rudolph305035c2016-11-11 18:38:50 +0100482 if (ctrl->tCK > TCK_400MHZ) {
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100483 printk (BIOS_ERR, "DRAM frequency is under lowest supported "
484 "frequency (400 MHz). Increasing to 400 MHz as last resort");
Patrick Rudolph305035c2016-11-11 18:38:50 +0100485 ctrl->tCK = TCK_400MHZ;
486 }
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100487
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100488 /* 100 Mhz reference clock supported */
489 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
490 ref_100mhz_support = !!((reg32 >> 21) & 0x7);
491 printk(BIOS_DEBUG, "100MHz reference clock support: %s\n",
492 ref_100mhz_support ? "yes" : "no");
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100493
Patrick Rudolph305035c2016-11-11 18:38:50 +0100494 while (1) {
495 u8 val2;
496 u32 reg1 = 0;
497
498 /* Step 1 - Set target PCU frequency */
499
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100500 if (ctrl->tCK <= TCK_1200MHZ) {
501 ctrl->tCK = TCK_1200MHZ;
502 ctrl->base_freq = 100;
503 } else if (ctrl->tCK <= TCK_1100MHZ) {
504 ctrl->tCK = TCK_1100MHZ;
505 ctrl->base_freq = 100;
506 } else if (ctrl->tCK <= TCK_1066MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100507 ctrl->tCK = TCK_1066MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100508 ctrl->base_freq = 133;
509 } else if (ctrl->tCK <= TCK_1000MHZ) {
510 ctrl->tCK = TCK_1000MHZ;
511 ctrl->base_freq = 100;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100512 } else if (ctrl->tCK <= TCK_933MHZ) {
513 ctrl->tCK = TCK_933MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100514 ctrl->base_freq = 133;
515 } else if (ctrl->tCK <= TCK_900MHZ) {
516 ctrl->tCK = TCK_900MHZ;
517 ctrl->base_freq = 100;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100518 } else if (ctrl->tCK <= TCK_800MHZ) {
519 ctrl->tCK = TCK_800MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100520 ctrl->base_freq = 133;
521 } else if (ctrl->tCK <= TCK_700MHZ) {
522 ctrl->tCK = TCK_700MHZ;
523 ctrl->base_freq = 100;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100524 } else if (ctrl->tCK <= TCK_666MHZ) {
525 ctrl->tCK = TCK_666MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100526 ctrl->base_freq = 133;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100527 } else if (ctrl->tCK <= TCK_533MHZ) {
528 ctrl->tCK = TCK_533MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100529 ctrl->base_freq = 133;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100530 } else if (ctrl->tCK <= TCK_400MHZ) {
531 ctrl->tCK = TCK_400MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100532 ctrl->base_freq = 133;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100533 } else {
534 die ("No lock frequency found");
535 }
536
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100537 if (!ref_100mhz_support && ctrl->base_freq == 100) {
538 /* Skip unsupported frequency. */
539 ctrl->tCK++;
540 continue;
541 }
542
Patrick Rudolph305035c2016-11-11 18:38:50 +0100543 /* Frequency multiplier. */
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100544 u32 FRQ = get_FRQ(ctrl->tCK, ctrl->base_freq);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100545
546 /* The PLL will never lock if the required frequency is
547 * already set. Exit early to prevent a system hang.
548 */
549 reg1 = MCHBAR32(MC_BIOS_DATA);
550 val2 = (u8) reg1;
551 if (val2)
552 return;
553
554 /* Step 2 - Select frequency in the MCU */
555 reg1 = FRQ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100556 if (ctrl->base_freq == 100)
557 reg1 |= 0x100; /* Enable 100Mhz REF clock */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100558 reg1 |= 0x80000000; // set running bit
559 MCHBAR32(MC_BIOS_REQ) = reg1;
560 int i=0;
561 printk(BIOS_DEBUG, "PLL busy... ");
562 while (reg1 & 0x80000000) {
563 udelay(10);
564 i++;
565 reg1 = MCHBAR32(MC_BIOS_REQ);
566 }
567 printk(BIOS_DEBUG, "done in %d us\n", i * 10);
568
569 /* Step 3 - Verify lock frequency */
570 reg1 = MCHBAR32(MC_BIOS_DATA);
571 val2 = (u8) reg1;
572 if (val2 >= FRQ) {
573 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
574 (1000 << 8) / ctrl->tCK);
575 return;
576 }
577 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
578 ctrl->tCK++;
579 }
580}
581
582static void dram_ioregs(ramctr_timing * ctrl)
583{
584 u32 reg, comp2;
585
586 int channel;
587
588 // IO clock
589 FOR_ALL_CHANNELS {
590 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
591 }
592
593 // IO command
594 FOR_ALL_CHANNELS {
595 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
596 }
597
598 // IO control
599 FOR_ALL_POPULATED_CHANNELS {
600 program_timings(ctrl, channel);
601 }
602
603 // Rcomp
604 printram("RCOMP...");
605 reg = 0;
606 while (reg == 0) {
607 reg = MCHBAR32(0x5084) & 0x10000;
608 }
609 printram("done\n");
610
611 // Set comp2
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100612 comp2 = get_COMP2(ctrl->tCK, ctrl->base_freq);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100613 MCHBAR32(0x3714) = comp2;
614 printram("COMP2 done\n");
615
616 // Set comp1
617 FOR_ALL_POPULATED_CHANNELS {
618 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
619 reg = (reg & ~0xe00) | (1 << 9); //odt
620 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
621 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
622 MCHBAR32(0x1810 + channel * 0x100) = reg;
623 }
624 printram("COMP1 done\n");
625
626 printram("FORCE RCOMP and wait 20us...");
627 MCHBAR32(0x5f08) |= 0x100;
628 udelay(20);
629 printram("done\n");
630}
631
632int try_init_dram_ddr3_ivy(ramctr_timing *ctrl, int fast_boot,
633 int s3_resume, int me_uma_size)
634{
635 int err;
636
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100637 printk(BIOS_DEBUG, "Starting Ivybridge RAM training (%d).\n",
638 fast_boot);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100639
640 if (!fast_boot) {
641 /* Find fastest common supported parameters */
642 dram_find_common_params(ctrl);
643
644 dram_dimm_mapping(ctrl);
645 }
646
647 /* Set MCU frequency */
648 dram_freq(ctrl);
649
650 if (!fast_boot) {
651 /* Calculate timings */
652 dram_timing(ctrl);
653 }
654
655 /* Set version register */
656 MCHBAR32(0x5034) = 0xC04EB002;
657
658 /* Enable crossover */
659 dram_xover(ctrl);
660
661 /* Set timing and refresh registers */
662 dram_timing_regs(ctrl);
663
664 /* Power mode preset */
665 MCHBAR32(0x4e80) = 0x5500;
666
667 /* Set scheduler parameters */
668 MCHBAR32(0x4c20) = 0x10100005;
669
670 /* Set CPU specific register */
671 set_4f8c();
672
673 /* Clear IO reset bit */
674 MCHBAR32(0x5030) &= ~0x20;
675
676 /* Set MAD-DIMM registers */
677 dram_dimm_set_mapping(ctrl);
678 printk(BIOS_DEBUG, "Done dimm mapping\n");
679
680 /* Zone config */
681 dram_zones(ctrl, 1);
682
683 /* Set memory map */
684 dram_memorymap(ctrl, me_uma_size);
685 printk(BIOS_DEBUG, "Done memory map\n");
686
687 /* Set IO registers */
688 dram_ioregs(ctrl);
689 printk(BIOS_DEBUG, "Done io registers\n");
690
691 udelay(1);
692
693 if (fast_boot) {
694 restore_timings(ctrl);
695 } else {
696 /* Do jedec ddr3 reset sequence */
697 dram_jedecreset(ctrl);
698 printk(BIOS_DEBUG, "Done jedec reset\n");
699
700 /* MRS commands */
701 dram_mrscommands(ctrl);
702 printk(BIOS_DEBUG, "Done MRS commands\n");
703
704 /* Prepare for memory training */
705 prepare_training(ctrl);
706
707 err = read_training(ctrl);
708 if (err)
709 return err;
710
711 err = write_training(ctrl);
712 if (err)
713 return err;
714
715 printram("CP5a\n");
716
717 err = discover_edges(ctrl);
718 if (err)
719 return err;
720
721 printram("CP5b\n");
722
723 err = command_training(ctrl);
724 if (err)
725 return err;
726
727 printram("CP5c\n");
728
729 err = discover_edges_write(ctrl);
730 if (err)
731 return err;
732
733 err = discover_timC_write(ctrl);
734 if (err)
735 return err;
736
737 normalize_training(ctrl);
738 }
739
740 set_4008c(ctrl);
741
742 write_controller_mr(ctrl);
743
744 if (!s3_resume) {
745 err = channel_test(ctrl);
746 if (err)
747 return err;
748 }
749
750 return 0;
751}