blob: 5cdfe8971b5209e3e0dcd0cae0ae1e9c440baa4a [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
295 /* Maximum supported DDR3 frequency is 1066MHz (DDR3 2133) so make sure
296 * we cap it if we have faster DIMMs.
297 * Then, align it to the closest JEDEC standard frequency */
298 if (ctrl->tCK <= TCK_1066MHZ) {
299 ctrl->tCK = TCK_1066MHZ;
300 ctrl->edge_offset[0] = 16;
301 ctrl->edge_offset[1] = 7;
302 ctrl->edge_offset[2] = 7;
303 ctrl->timC_offset[0] = 18;
304 ctrl->timC_offset[1] = 7;
305 ctrl->timC_offset[2] = 7;
306 ctrl->reg_320c_range_threshold = 13;
307 } else if (ctrl->tCK <= TCK_933MHZ) {
308 ctrl->tCK = TCK_933MHZ;
309 ctrl->edge_offset[0] = 14;
310 ctrl->edge_offset[1] = 6;
311 ctrl->edge_offset[2] = 6;
312 ctrl->timC_offset[0] = 15;
313 ctrl->timC_offset[1] = 6;
314 ctrl->timC_offset[2] = 6;
315 ctrl->reg_320c_range_threshold = 15;
316 } else if (ctrl->tCK <= TCK_800MHZ) {
317 ctrl->tCK = TCK_800MHZ;
318 ctrl->edge_offset[0] = 13;
319 ctrl->edge_offset[1] = 5;
320 ctrl->edge_offset[2] = 5;
321 ctrl->timC_offset[0] = 14;
322 ctrl->timC_offset[1] = 5;
323 ctrl->timC_offset[2] = 5;
324 ctrl->reg_320c_range_threshold = 15;
325 } else if (ctrl->tCK <= TCK_666MHZ) {
326 ctrl->tCK = TCK_666MHZ;
327 ctrl->edge_offset[0] = 10;
328 ctrl->edge_offset[1] = 4;
329 ctrl->edge_offset[2] = 4;
330 ctrl->timC_offset[0] = 11;
331 ctrl->timC_offset[1] = 4;
332 ctrl->timC_offset[2] = 4;
333 ctrl->reg_320c_range_threshold = 16;
334 } else if (ctrl->tCK <= TCK_533MHZ) {
335 ctrl->tCK = TCK_533MHZ;
336 ctrl->edge_offset[0] = 8;
337 ctrl->edge_offset[1] = 3;
338 ctrl->edge_offset[2] = 3;
339 ctrl->timC_offset[0] = 9;
340 ctrl->timC_offset[1] = 3;
341 ctrl->timC_offset[2] = 3;
342 ctrl->reg_320c_range_threshold = 17;
343 } else {
344 ctrl->tCK = TCK_400MHZ;
345 ctrl->edge_offset[0] = 6;
346 ctrl->edge_offset[1] = 2;
347 ctrl->edge_offset[2] = 2;
348 ctrl->timC_offset[0] = 6;
349 ctrl->timC_offset[1] = 2;
350 ctrl->timC_offset[2] = 2;
351 ctrl->reg_320c_range_threshold = 17;
352 }
353
354 /* Initial phase between CLK/CMD pins */
355 ctrl->reg_c14_offset = (256000 / ctrl->tCK) / 66;
356
357 /* DLL_CONFIG_MDLL_W_TIMER */
358 ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3;
359
360 val32 = (1000 << 8) / ctrl->tCK;
361 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", val32);
362
363 /* Find CAS latency */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100364 val = DIV_ROUND_UP(ctrl->tAA, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100365 printk(BIOS_DEBUG, "Minimum CAS latency : %uT\n", val);
366 /* Find lowest supported CAS latency that satisfies the minimum value */
367 while (!((ctrl->cas_supported >> (val - MIN_CAS)) & 1)
368 && (ctrl->cas_supported >> (val - MIN_CAS))) {
369 val++;
370 }
371 /* Is CAS supported */
372 if (!(ctrl->cas_supported & (1 << (val - MIN_CAS)))) {
373 printk(BIOS_ERR, "CAS %uT not supported. ", val);
374 val = MAX_CAS;
375 /* Find highest supported CAS latency */
376 while (!((ctrl->cas_supported >> (val - MIN_CAS)) & 1))
377 val--;
378
379 printk(BIOS_ERR, "Using CAS %uT instead.\n", val);
380 }
381
382 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
383 ctrl->CAS = val;
384 ctrl->CWL = get_CWL(ctrl->tCK);
385 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
386
387 /* Find tRCD */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100388 ctrl->tRCD = DIV_ROUND_UP(ctrl->tRCD, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100389 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
390
Arthur Heymans50db9c92017-03-23 18:53:38 +0100391 ctrl->tRP = DIV_ROUND_UP(ctrl->tRP, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100392 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
393
394 /* Find tRAS */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100395 ctrl->tRAS = DIV_ROUND_UP(ctrl->tRAS, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100396 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
397
398 /* Find tWR */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100399 ctrl->tWR = DIV_ROUND_UP(ctrl->tWR, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100400 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
401
402 /* Find tFAW */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100403 ctrl->tFAW = DIV_ROUND_UP(ctrl->tFAW, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100404 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
405
406 /* Find tRRD */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100407 ctrl->tRRD = DIV_ROUND_UP(ctrl->tRRD, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100408 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
409
410 /* Find tRTP */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100411 ctrl->tRTP = DIV_ROUND_UP(ctrl->tRTP, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100412 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
413
414 /* Find tWTR */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100415 ctrl->tWTR = DIV_ROUND_UP(ctrl->tWTR, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100416 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
417
418 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100419 ctrl->tRFC = DIV_ROUND_UP(ctrl->tRFC, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100420 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
421
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100422 ctrl->tREFI = get_REFI(ctrl->tCK, ctrl->base_freq);
423 ctrl->tMOD = get_MOD(ctrl->tCK, ctrl->base_freq);
424 ctrl->tXSOffset = get_XSOffset(ctrl->tCK, ctrl->base_freq);
425 ctrl->tWLO = get_WLO(ctrl->tCK, ctrl->base_freq);
426 ctrl->tCKE = get_CKE(ctrl->tCK, ctrl->base_freq);
427 ctrl->tXPDLL = get_XPDLL(ctrl->tCK, ctrl->base_freq);
428 ctrl->tXP = get_XP(ctrl->tCK, ctrl->base_freq);
429 ctrl->tAONPD = get_AONPD(ctrl->tCK, ctrl->base_freq);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100430}
431
432static void dram_freq(ramctr_timing * ctrl)
433{
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100434 bool ref_100mhz_support;
435 u32 reg32;
436
Patrick Rudolph305035c2016-11-11 18:38:50 +0100437 if (ctrl->tCK > TCK_400MHZ) {
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100438 printk (BIOS_ERR, "DRAM frequency is under lowest supported "
439 "frequency (400 MHz). Increasing to 400 MHz as last resort");
Patrick Rudolph305035c2016-11-11 18:38:50 +0100440 ctrl->tCK = TCK_400MHZ;
441 }
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100442
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100443 /* 100 Mhz reference clock supported */
444 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_B);
445 ref_100mhz_support = !!((reg32 >> 21) & 0x7);
446 printk(BIOS_DEBUG, "100MHz reference clock support: %s\n",
447 ref_100mhz_support ? "yes" : "no");
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100448
Patrick Rudolph305035c2016-11-11 18:38:50 +0100449 while (1) {
450 u8 val2;
451 u32 reg1 = 0;
452
453 /* Step 1 - Set target PCU frequency */
454
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100455 if (ctrl->tCK <= TCK_1200MHZ) {
456 ctrl->tCK = TCK_1200MHZ;
457 ctrl->base_freq = 100;
458 } else if (ctrl->tCK <= TCK_1100MHZ) {
459 ctrl->tCK = TCK_1100MHZ;
460 ctrl->base_freq = 100;
461 } else if (ctrl->tCK <= TCK_1066MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100462 ctrl->tCK = TCK_1066MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100463 ctrl->base_freq = 133;
464 } else if (ctrl->tCK <= TCK_1000MHZ) {
465 ctrl->tCK = TCK_1000MHZ;
466 ctrl->base_freq = 100;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100467 } else if (ctrl->tCK <= TCK_933MHZ) {
468 ctrl->tCK = TCK_933MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100469 ctrl->base_freq = 133;
470 } else if (ctrl->tCK <= TCK_900MHZ) {
471 ctrl->tCK = TCK_900MHZ;
472 ctrl->base_freq = 100;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100473 } else if (ctrl->tCK <= TCK_800MHZ) {
474 ctrl->tCK = TCK_800MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100475 ctrl->base_freq = 133;
476 } else if (ctrl->tCK <= TCK_700MHZ) {
477 ctrl->tCK = TCK_700MHZ;
478 ctrl->base_freq = 100;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100479 } else if (ctrl->tCK <= TCK_666MHZ) {
480 ctrl->tCK = TCK_666MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100481 ctrl->base_freq = 133;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100482 } else if (ctrl->tCK <= TCK_533MHZ) {
483 ctrl->tCK = TCK_533MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100484 ctrl->base_freq = 133;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100485 } else if (ctrl->tCK <= TCK_400MHZ) {
486 ctrl->tCK = TCK_400MHZ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100487 ctrl->base_freq = 133;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100488 } else {
489 die ("No lock frequency found");
490 }
491
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100492 if (!ref_100mhz_support && ctrl->base_freq == 100) {
493 /* Skip unsupported frequency. */
494 ctrl->tCK++;
495 continue;
496 }
497
Patrick Rudolph305035c2016-11-11 18:38:50 +0100498 /* Frequency multiplier. */
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100499 u32 FRQ = get_FRQ(ctrl->tCK, ctrl->base_freq);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100500
501 /* The PLL will never lock if the required frequency is
502 * already set. Exit early to prevent a system hang.
503 */
504 reg1 = MCHBAR32(MC_BIOS_DATA);
505 val2 = (u8) reg1;
506 if (val2)
507 return;
508
509 /* Step 2 - Select frequency in the MCU */
510 reg1 = FRQ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100511 if (ctrl->base_freq == 100)
512 reg1 |= 0x100; /* Enable 100Mhz REF clock */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100513 reg1 |= 0x80000000; // set running bit
514 MCHBAR32(MC_BIOS_REQ) = reg1;
515 int i=0;
516 printk(BIOS_DEBUG, "PLL busy... ");
517 while (reg1 & 0x80000000) {
518 udelay(10);
519 i++;
520 reg1 = MCHBAR32(MC_BIOS_REQ);
521 }
522 printk(BIOS_DEBUG, "done in %d us\n", i * 10);
523
524 /* Step 3 - Verify lock frequency */
525 reg1 = MCHBAR32(MC_BIOS_DATA);
526 val2 = (u8) reg1;
527 if (val2 >= FRQ) {
528 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
529 (1000 << 8) / ctrl->tCK);
530 return;
531 }
532 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
533 ctrl->tCK++;
534 }
535}
536
537static void dram_ioregs(ramctr_timing * ctrl)
538{
539 u32 reg, comp2;
540
541 int channel;
542
543 // IO clock
544 FOR_ALL_CHANNELS {
545 MCHBAR32(0xc00 + 0x100 * channel) = ctrl->rankmap[channel];
546 }
547
548 // IO command
549 FOR_ALL_CHANNELS {
550 MCHBAR32(0x3200 + 0x100 * channel) = ctrl->rankmap[channel];
551 }
552
553 // IO control
554 FOR_ALL_POPULATED_CHANNELS {
555 program_timings(ctrl, channel);
556 }
557
558 // Rcomp
559 printram("RCOMP...");
560 reg = 0;
561 while (reg == 0) {
562 reg = MCHBAR32(0x5084) & 0x10000;
563 }
564 printram("done\n");
565
566 // Set comp2
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100567 comp2 = get_COMP2(ctrl->tCK, ctrl->base_freq);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100568 MCHBAR32(0x3714) = comp2;
569 printram("COMP2 done\n");
570
571 // Set comp1
572 FOR_ALL_POPULATED_CHANNELS {
573 reg = MCHBAR32(0x1810 + channel * 0x100); //ch0
574 reg = (reg & ~0xe00) | (1 << 9); //odt
575 reg = (reg & ~0xe00000) | (1 << 21); //clk drive up
576 reg = (reg & ~0x38000000) | (1 << 27); //ctl drive up
577 MCHBAR32(0x1810 + channel * 0x100) = reg;
578 }
579 printram("COMP1 done\n");
580
581 printram("FORCE RCOMP and wait 20us...");
582 MCHBAR32(0x5f08) |= 0x100;
583 udelay(20);
584 printram("done\n");
585}
586
587int try_init_dram_ddr3_ivy(ramctr_timing *ctrl, int fast_boot,
588 int s3_resume, int me_uma_size)
589{
590 int err;
591
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100592 printk(BIOS_DEBUG, "Starting Ivybridge RAM training (%d).\n",
593 fast_boot);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100594
595 if (!fast_boot) {
596 /* Find fastest common supported parameters */
597 dram_find_common_params(ctrl);
598
599 dram_dimm_mapping(ctrl);
600 }
601
602 /* Set MCU frequency */
603 dram_freq(ctrl);
604
605 if (!fast_boot) {
606 /* Calculate timings */
607 dram_timing(ctrl);
608 }
609
610 /* Set version register */
611 MCHBAR32(0x5034) = 0xC04EB002;
612
613 /* Enable crossover */
614 dram_xover(ctrl);
615
616 /* Set timing and refresh registers */
617 dram_timing_regs(ctrl);
618
619 /* Power mode preset */
620 MCHBAR32(0x4e80) = 0x5500;
621
622 /* Set scheduler parameters */
623 MCHBAR32(0x4c20) = 0x10100005;
624
625 /* Set CPU specific register */
626 set_4f8c();
627
628 /* Clear IO reset bit */
629 MCHBAR32(0x5030) &= ~0x20;
630
631 /* Set MAD-DIMM registers */
632 dram_dimm_set_mapping(ctrl);
633 printk(BIOS_DEBUG, "Done dimm mapping\n");
634
635 /* Zone config */
636 dram_zones(ctrl, 1);
637
638 /* Set memory map */
639 dram_memorymap(ctrl, me_uma_size);
640 printk(BIOS_DEBUG, "Done memory map\n");
641
642 /* Set IO registers */
643 dram_ioregs(ctrl);
644 printk(BIOS_DEBUG, "Done io registers\n");
645
646 udelay(1);
647
648 if (fast_boot) {
649 restore_timings(ctrl);
650 } else {
651 /* Do jedec ddr3 reset sequence */
652 dram_jedecreset(ctrl);
653 printk(BIOS_DEBUG, "Done jedec reset\n");
654
655 /* MRS commands */
656 dram_mrscommands(ctrl);
657 printk(BIOS_DEBUG, "Done MRS commands\n");
658
659 /* Prepare for memory training */
660 prepare_training(ctrl);
661
662 err = read_training(ctrl);
663 if (err)
664 return err;
665
666 err = write_training(ctrl);
667 if (err)
668 return err;
669
670 printram("CP5a\n");
671
672 err = discover_edges(ctrl);
673 if (err)
674 return err;
675
676 printram("CP5b\n");
677
678 err = command_training(ctrl);
679 if (err)
680 return err;
681
682 printram("CP5c\n");
683
684 err = discover_edges_write(ctrl);
685 if (err)
686 return err;
687
688 err = discover_timC_write(ctrl);
689 if (err)
690 return err;
691
692 normalize_training(ctrl);
693 }
694
695 set_4008c(ctrl);
696
697 write_controller_mr(ctrl);
698
699 if (!s3_resume) {
700 err = channel_test(ctrl);
701 if (err)
702 return err;
703 }
704
705 return 0;
706}