blob: 2f13b8fd9316df048f8b1cc6ad8c067a1f6e25fe [file] [log] [blame]
Kumar Gala124b0822008-08-26 15:01:29 -05001/*
York Sune8dc17b2012-08-17 08:22:39 +00002 * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc.
Kumar Gala124b0822008-08-26 15:01:29 -05003 *
Dave Liu707aa5c2010-03-05 12:22:00 +08004 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
Kumar Gala124b0822008-08-26 15:01:29 -05008 */
9
10#include <common.h>
Kumar Gala64042092010-07-14 10:04:21 -050011#include <hwconfig.h>
Kumar Gala124b0822008-08-26 15:01:29 -050012#include <asm/fsl_ddr_sdram.h>
13
14#include "ddr.h"
15
Kumar Gala72301602011-01-09 11:37:00 -060016/*
17 * Use our own stack based buffer before relocation to allow accessing longer
18 * hwconfig strings that might be in the environment before we've relocated.
19 * This is pretty fragile on both the use of stack and if the buffer is big
20 * enough. However we will get a warning from getenv_f for the later.
21 */
Kumar Gala72301602011-01-09 11:37:00 -060022
Kumar Gala124b0822008-08-26 15:01:29 -050023/* Board-specific functions defined in each board's ddr.c */
24extern void fsl_ddr_board_options(memctl_options_t *popts,
Haiying Wangfa440362008-10-03 12:36:55 -040025 dimm_params_t *pdimm,
Kumar Gala124b0822008-08-26 15:01:29 -050026 unsigned int ctrl_num);
27
York Sun454f5072011-08-26 11:32:43 -070028struct dynamic_odt {
York Sunba0c2eb2011-01-10 12:03:00 +000029 unsigned int odt_rd_cfg;
30 unsigned int odt_wr_cfg;
31 unsigned int odt_rtt_norm;
32 unsigned int odt_rtt_wr;
York Sun454f5072011-08-26 11:32:43 -070033};
York Sunba0c2eb2011-01-10 12:03:00 +000034
York Sun454f5072011-08-26 11:32:43 -070035#ifdef CONFIG_FSL_DDR3
36static const struct dynamic_odt single_Q[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +000037 { /* cs0 */
38 FSL_DDR_ODT_NEVER,
39 FSL_DDR_ODT_CS_AND_OTHER_DIMM,
40 DDR3_RTT_20_OHM,
41 DDR3_RTT_120_OHM
42 },
43 { /* cs1 */
44 FSL_DDR_ODT_NEVER,
45 FSL_DDR_ODT_NEVER, /* tied high */
46 DDR3_RTT_OFF,
47 DDR3_RTT_120_OHM
48 },
49 { /* cs2 */
50 FSL_DDR_ODT_NEVER,
51 FSL_DDR_ODT_CS_AND_OTHER_DIMM,
52 DDR3_RTT_20_OHM,
53 DDR3_RTT_120_OHM
54 },
55 { /* cs3 */
56 FSL_DDR_ODT_NEVER,
57 FSL_DDR_ODT_NEVER, /* tied high */
58 DDR3_RTT_OFF,
59 DDR3_RTT_120_OHM
60 }
61};
62
York Sun454f5072011-08-26 11:32:43 -070063static const struct dynamic_odt single_D[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +000064 { /* cs0 */
65 FSL_DDR_ODT_NEVER,
66 FSL_DDR_ODT_ALL,
67 DDR3_RTT_40_OHM,
68 DDR3_RTT_OFF
69 },
70 { /* cs1 */
71 FSL_DDR_ODT_NEVER,
72 FSL_DDR_ODT_NEVER,
73 DDR3_RTT_OFF,
74 DDR3_RTT_OFF
75 },
76 {0, 0, 0, 0},
77 {0, 0, 0, 0}
78};
79
York Sun454f5072011-08-26 11:32:43 -070080static const struct dynamic_odt single_S[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +000081 { /* cs0 */
82 FSL_DDR_ODT_NEVER,
83 FSL_DDR_ODT_ALL,
84 DDR3_RTT_40_OHM,
85 DDR3_RTT_OFF
86 },
87 {0, 0, 0, 0},
88 {0, 0, 0, 0},
89 {0, 0, 0, 0},
90};
91
York Sun454f5072011-08-26 11:32:43 -070092static const struct dynamic_odt dual_DD[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +000093 { /* cs0 */
94 FSL_DDR_ODT_NEVER,
95 FSL_DDR_ODT_SAME_DIMM,
96 DDR3_RTT_120_OHM,
97 DDR3_RTT_OFF
98 },
99 { /* cs1 */
100 FSL_DDR_ODT_OTHER_DIMM,
101 FSL_DDR_ODT_OTHER_DIMM,
102 DDR3_RTT_30_OHM,
103 DDR3_RTT_OFF
104 },
105 { /* cs2 */
106 FSL_DDR_ODT_NEVER,
107 FSL_DDR_ODT_SAME_DIMM,
108 DDR3_RTT_120_OHM,
109 DDR3_RTT_OFF
110 },
111 { /* cs3 */
112 FSL_DDR_ODT_OTHER_DIMM,
113 FSL_DDR_ODT_OTHER_DIMM,
114 DDR3_RTT_30_OHM,
115 DDR3_RTT_OFF
116 }
117};
118
York Sun454f5072011-08-26 11:32:43 -0700119static const struct dynamic_odt dual_DS[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +0000120 { /* cs0 */
121 FSL_DDR_ODT_NEVER,
122 FSL_DDR_ODT_SAME_DIMM,
123 DDR3_RTT_120_OHM,
124 DDR3_RTT_OFF
125 },
126 { /* cs1 */
127 FSL_DDR_ODT_OTHER_DIMM,
128 FSL_DDR_ODT_OTHER_DIMM,
129 DDR3_RTT_30_OHM,
130 DDR3_RTT_OFF
131 },
132 { /* cs2 */
133 FSL_DDR_ODT_OTHER_DIMM,
134 FSL_DDR_ODT_ALL,
135 DDR3_RTT_20_OHM,
136 DDR3_RTT_120_OHM
137 },
138 {0, 0, 0, 0}
139};
York Sun454f5072011-08-26 11:32:43 -0700140static const struct dynamic_odt dual_SD[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +0000141 { /* cs0 */
142 FSL_DDR_ODT_OTHER_DIMM,
143 FSL_DDR_ODT_ALL,
144 DDR3_RTT_20_OHM,
145 DDR3_RTT_120_OHM
146 },
147 {0, 0, 0, 0},
148 { /* cs2 */
149 FSL_DDR_ODT_NEVER,
150 FSL_DDR_ODT_SAME_DIMM,
151 DDR3_RTT_120_OHM,
152 DDR3_RTT_OFF
153 },
154 { /* cs3 */
155 FSL_DDR_ODT_OTHER_DIMM,
156 FSL_DDR_ODT_OTHER_DIMM,
157 DDR3_RTT_20_OHM,
158 DDR3_RTT_OFF
159 }
160};
161
York Sun454f5072011-08-26 11:32:43 -0700162static const struct dynamic_odt dual_SS[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +0000163 { /* cs0 */
164 FSL_DDR_ODT_OTHER_DIMM,
165 FSL_DDR_ODT_ALL,
166 DDR3_RTT_30_OHM,
167 DDR3_RTT_120_OHM
168 },
169 {0, 0, 0, 0},
170 { /* cs2 */
171 FSL_DDR_ODT_OTHER_DIMM,
172 FSL_DDR_ODT_ALL,
173 DDR3_RTT_30_OHM,
174 DDR3_RTT_120_OHM
175 },
176 {0, 0, 0, 0}
177};
178
York Sun454f5072011-08-26 11:32:43 -0700179static const struct dynamic_odt dual_D0[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +0000180 { /* cs0 */
181 FSL_DDR_ODT_NEVER,
182 FSL_DDR_ODT_SAME_DIMM,
183 DDR3_RTT_40_OHM,
184 DDR3_RTT_OFF
185 },
186 { /* cs1 */
187 FSL_DDR_ODT_NEVER,
188 FSL_DDR_ODT_NEVER,
189 DDR3_RTT_OFF,
190 DDR3_RTT_OFF
191 },
192 {0, 0, 0, 0},
193 {0, 0, 0, 0}
194};
195
York Sun454f5072011-08-26 11:32:43 -0700196static const struct dynamic_odt dual_0D[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +0000197 {0, 0, 0, 0},
198 {0, 0, 0, 0},
199 { /* cs2 */
200 FSL_DDR_ODT_NEVER,
201 FSL_DDR_ODT_SAME_DIMM,
202 DDR3_RTT_40_OHM,
203 DDR3_RTT_OFF
204 },
205 { /* cs3 */
206 FSL_DDR_ODT_NEVER,
207 FSL_DDR_ODT_NEVER,
208 DDR3_RTT_OFF,
209 DDR3_RTT_OFF
210 }
211};
212
York Sun454f5072011-08-26 11:32:43 -0700213static const struct dynamic_odt dual_S0[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +0000214 { /* cs0 */
215 FSL_DDR_ODT_NEVER,
216 FSL_DDR_ODT_CS,
217 DDR3_RTT_40_OHM,
218 DDR3_RTT_OFF
219 },
220 {0, 0, 0, 0},
221 {0, 0, 0, 0},
222 {0, 0, 0, 0}
223
224};
225
York Sun454f5072011-08-26 11:32:43 -0700226static const struct dynamic_odt dual_0S[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +0000227 {0, 0, 0, 0},
228 {0, 0, 0, 0},
229 { /* cs2 */
230 FSL_DDR_ODT_NEVER,
231 FSL_DDR_ODT_CS,
232 DDR3_RTT_40_OHM,
233 DDR3_RTT_OFF
234 },
235 {0, 0, 0, 0}
236
237};
238
York Sun454f5072011-08-26 11:32:43 -0700239static const struct dynamic_odt odt_unknown[4] = {
York Sunba0c2eb2011-01-10 12:03:00 +0000240 { /* cs0 */
241 FSL_DDR_ODT_NEVER,
242 FSL_DDR_ODT_CS,
243 DDR3_RTT_120_OHM,
244 DDR3_RTT_OFF
245 },
246 { /* cs1 */
247 FSL_DDR_ODT_NEVER,
248 FSL_DDR_ODT_CS,
249 DDR3_RTT_120_OHM,
250 DDR3_RTT_OFF
251 },
252 { /* cs2 */
253 FSL_DDR_ODT_NEVER,
254 FSL_DDR_ODT_CS,
255 DDR3_RTT_120_OHM,
256 DDR3_RTT_OFF
257 },
258 { /* cs3 */
259 FSL_DDR_ODT_NEVER,
260 FSL_DDR_ODT_CS,
261 DDR3_RTT_120_OHM,
262 DDR3_RTT_OFF
263 }
264};
York Sun454f5072011-08-26 11:32:43 -0700265#else /* CONFIG_FSL_DDR3 */
266static const struct dynamic_odt single_Q[4] = {
267 {0, 0, 0, 0},
268 {0, 0, 0, 0},
269 {0, 0, 0, 0},
270 {0, 0, 0, 0}
271};
272
273static const struct dynamic_odt single_D[4] = {
274 { /* cs0 */
275 FSL_DDR_ODT_NEVER,
276 FSL_DDR_ODT_ALL,
277 DDR2_RTT_150_OHM,
278 DDR2_RTT_OFF
279 },
280 { /* cs1 */
281 FSL_DDR_ODT_NEVER,
282 FSL_DDR_ODT_NEVER,
283 DDR2_RTT_OFF,
284 DDR2_RTT_OFF
285 },
286 {0, 0, 0, 0},
287 {0, 0, 0, 0}
288};
289
290static const struct dynamic_odt single_S[4] = {
291 { /* cs0 */
292 FSL_DDR_ODT_NEVER,
293 FSL_DDR_ODT_ALL,
294 DDR2_RTT_150_OHM,
295 DDR2_RTT_OFF
296 },
297 {0, 0, 0, 0},
298 {0, 0, 0, 0},
299 {0, 0, 0, 0},
300};
301
302static const struct dynamic_odt dual_DD[4] = {
303 { /* cs0 */
304 FSL_DDR_ODT_OTHER_DIMM,
305 FSL_DDR_ODT_OTHER_DIMM,
306 DDR2_RTT_75_OHM,
307 DDR2_RTT_OFF
308 },
309 { /* cs1 */
310 FSL_DDR_ODT_NEVER,
311 FSL_DDR_ODT_NEVER,
312 DDR2_RTT_OFF,
313 DDR2_RTT_OFF
314 },
315 { /* cs2 */
316 FSL_DDR_ODT_OTHER_DIMM,
317 FSL_DDR_ODT_OTHER_DIMM,
318 DDR2_RTT_75_OHM,
319 DDR2_RTT_OFF
320 },
321 { /* cs3 */
322 FSL_DDR_ODT_NEVER,
323 FSL_DDR_ODT_NEVER,
324 DDR2_RTT_OFF,
325 DDR2_RTT_OFF
326 }
327};
328
329static const struct dynamic_odt dual_DS[4] = {
330 { /* cs0 */
331 FSL_DDR_ODT_OTHER_DIMM,
332 FSL_DDR_ODT_OTHER_DIMM,
333 DDR2_RTT_75_OHM,
334 DDR2_RTT_OFF
335 },
336 { /* cs1 */
337 FSL_DDR_ODT_NEVER,
338 FSL_DDR_ODT_NEVER,
339 DDR2_RTT_OFF,
340 DDR2_RTT_OFF
341 },
342 { /* cs2 */
343 FSL_DDR_ODT_OTHER_DIMM,
344 FSL_DDR_ODT_OTHER_DIMM,
345 DDR2_RTT_75_OHM,
346 DDR2_RTT_OFF
347 },
348 {0, 0, 0, 0}
349};
350
351static const struct dynamic_odt dual_SD[4] = {
352 { /* cs0 */
353 FSL_DDR_ODT_OTHER_DIMM,
354 FSL_DDR_ODT_OTHER_DIMM,
355 DDR2_RTT_75_OHM,
356 DDR2_RTT_OFF
357 },
358 {0, 0, 0, 0},
359 { /* cs2 */
360 FSL_DDR_ODT_OTHER_DIMM,
361 FSL_DDR_ODT_OTHER_DIMM,
362 DDR2_RTT_75_OHM,
363 DDR2_RTT_OFF
364 },
365 { /* cs3 */
366 FSL_DDR_ODT_NEVER,
367 FSL_DDR_ODT_NEVER,
368 DDR2_RTT_OFF,
369 DDR2_RTT_OFF
370 }
371};
372
373static const struct dynamic_odt dual_SS[4] = {
374 { /* cs0 */
375 FSL_DDR_ODT_OTHER_DIMM,
376 FSL_DDR_ODT_OTHER_DIMM,
377 DDR2_RTT_75_OHM,
378 DDR2_RTT_OFF
379 },
380 {0, 0, 0, 0},
381 { /* cs2 */
382 FSL_DDR_ODT_OTHER_DIMM,
383 FSL_DDR_ODT_OTHER_DIMM,
384 DDR2_RTT_75_OHM,
385 DDR2_RTT_OFF
386 },
387 {0, 0, 0, 0}
388};
389
390static const struct dynamic_odt dual_D0[4] = {
391 { /* cs0 */
392 FSL_DDR_ODT_NEVER,
393 FSL_DDR_ODT_ALL,
394 DDR2_RTT_150_OHM,
395 DDR2_RTT_OFF
396 },
397 { /* cs1 */
398 FSL_DDR_ODT_NEVER,
399 FSL_DDR_ODT_NEVER,
400 DDR2_RTT_OFF,
401 DDR2_RTT_OFF
402 },
403 {0, 0, 0, 0},
404 {0, 0, 0, 0}
405};
406
407static const struct dynamic_odt dual_0D[4] = {
408 {0, 0, 0, 0},
409 {0, 0, 0, 0},
410 { /* cs2 */
411 FSL_DDR_ODT_NEVER,
412 FSL_DDR_ODT_ALL,
413 DDR2_RTT_150_OHM,
414 DDR2_RTT_OFF
415 },
416 { /* cs3 */
417 FSL_DDR_ODT_NEVER,
418 FSL_DDR_ODT_NEVER,
419 DDR2_RTT_OFF,
420 DDR2_RTT_OFF
421 }
422};
York Sunba0c2eb2011-01-10 12:03:00 +0000423
York Sun454f5072011-08-26 11:32:43 -0700424static const struct dynamic_odt dual_S0[4] = {
425 { /* cs0 */
426 FSL_DDR_ODT_NEVER,
427 FSL_DDR_ODT_CS,
428 DDR2_RTT_150_OHM,
429 DDR2_RTT_OFF
430 },
431 {0, 0, 0, 0},
432 {0, 0, 0, 0},
433 {0, 0, 0, 0}
434
435};
436
437static const struct dynamic_odt dual_0S[4] = {
438 {0, 0, 0, 0},
439 {0, 0, 0, 0},
440 { /* cs2 */
441 FSL_DDR_ODT_NEVER,
442 FSL_DDR_ODT_CS,
443 DDR2_RTT_150_OHM,
444 DDR2_RTT_OFF
445 },
446 {0, 0, 0, 0}
447
448};
449
450static const struct dynamic_odt odt_unknown[4] = {
451 { /* cs0 */
452 FSL_DDR_ODT_NEVER,
453 FSL_DDR_ODT_CS,
454 DDR2_RTT_75_OHM,
455 DDR2_RTT_OFF
456 },
457 { /* cs1 */
458 FSL_DDR_ODT_NEVER,
459 FSL_DDR_ODT_NEVER,
460 DDR2_RTT_OFF,
461 DDR2_RTT_OFF
462 },
463 { /* cs2 */
464 FSL_DDR_ODT_NEVER,
465 FSL_DDR_ODT_CS,
466 DDR2_RTT_75_OHM,
467 DDR2_RTT_OFF
468 },
469 { /* cs3 */
470 FSL_DDR_ODT_NEVER,
471 FSL_DDR_ODT_NEVER,
472 DDR2_RTT_OFF,
473 DDR2_RTT_OFF
474 }
475};
476#endif
York Sund01babd2012-10-08 07:44:27 +0000477
478/*
479 * Automatically seleect bank interleaving mode based on DIMMs
480 * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null.
481 * This function only deal with one or two slots per controller.
482 */
483static inline unsigned int auto_bank_intlv(dimm_params_t *pdimm)
484{
485#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
486 if (pdimm[0].n_ranks == 4)
487 return FSL_DDR_CS0_CS1_CS2_CS3;
488 else if (pdimm[0].n_ranks == 2)
489 return FSL_DDR_CS0_CS1;
490#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
491#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
492 if (pdimm[0].n_ranks == 4)
493 return FSL_DDR_CS0_CS1_CS2_CS3;
494#endif
495 if (pdimm[0].n_ranks == 2) {
496 if (pdimm[1].n_ranks == 2)
497 return FSL_DDR_CS0_CS1_CS2_CS3;
498 else
499 return FSL_DDR_CS0_CS1;
500 }
501#endif
502 return 0;
503}
504
Kumar Gala124b0822008-08-26 15:01:29 -0500505unsigned int populate_memctl_options(int all_DIMMs_registered,
506 memctl_options_t *popts,
Haiying Wangfa440362008-10-03 12:36:55 -0400507 dimm_params_t *pdimm,
Kumar Gala124b0822008-08-26 15:01:29 -0500508 unsigned int ctrl_num)
509{
510 unsigned int i;
Kumar Gala72301602011-01-09 11:37:00 -0600511 char buffer[HWCONFIG_BUFFER_SIZE];
512 char *buf = NULL;
Kumar Gala59cb44c2011-11-09 10:05:21 -0600513#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2)
York Sun454f5072011-08-26 11:32:43 -0700514 const struct dynamic_odt *pdodt = odt_unknown;
Kumar Gala59cb44c2011-11-09 10:05:21 -0600515#endif
York Sunf0345e22011-08-24 09:40:26 -0700516 ulong ddr_freq;
Kumar Gala72301602011-01-09 11:37:00 -0600517
518 /*
519 * Extract hwconfig from environment since we have not properly setup
520 * the environment but need it for ddr config params
521 */
522 if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
523 buf = buffer;
Kumar Gala124b0822008-08-26 15:01:29 -0500524
Kumar Gala59cb44c2011-11-09 10:05:21 -0600525#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2)
Kumar Gala124b0822008-08-26 15:01:29 -0500526 /* Chip select options. */
York Sunba0c2eb2011-01-10 12:03:00 +0000527 if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
528 switch (pdimm[0].n_ranks) {
529 case 1:
530 pdodt = single_S;
531 break;
532 case 2:
533 pdodt = single_D;
534 break;
535 case 4:
536 pdodt = single_Q;
537 break;
538 }
539 } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
540 switch (pdimm[0].n_ranks) {
York Sun98df4d12012-10-08 07:44:23 +0000541#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
542 case 4:
543 pdodt = single_Q;
544 if (pdimm[1].n_ranks)
545 printf("Error: Quad- and Dual-rank DIMMs "
546 "cannot be used together\n");
547 break;
548#endif
York Sunba0c2eb2011-01-10 12:03:00 +0000549 case 2:
550 switch (pdimm[1].n_ranks) {
551 case 2:
552 pdodt = dual_DD;
553 break;
554 case 1:
555 pdodt = dual_DS;
556 break;
557 case 0:
558 pdodt = dual_D0;
559 break;
560 }
561 break;
562 case 1:
563 switch (pdimm[1].n_ranks) {
564 case 2:
565 pdodt = dual_SD;
566 break;
567 case 1:
568 pdodt = dual_SS;
569 break;
570 case 0:
571 pdodt = dual_S0;
572 break;
573 }
574 break;
575 case 0:
576 switch (pdimm[1].n_ranks) {
577 case 2:
578 pdodt = dual_0D;
579 break;
580 case 1:
581 pdodt = dual_0S;
582 break;
583 }
584 break;
585 }
586 }
Kumar Gala59cb44c2011-11-09 10:05:21 -0600587#endif
Kumar Gala124b0822008-08-26 15:01:29 -0500588
589 /* Pick chip-select local options. */
590 for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
York Sun454f5072011-08-26 11:32:43 -0700591#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2)
York Sunba0c2eb2011-01-10 12:03:00 +0000592 popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg;
593 popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg;
594 popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm;
595 popts->cs_local_opts[i].odt_rtt_wr = pdodt[i].odt_rtt_wr;
596#else
597 popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
598 popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
599#endif
Kumar Gala124b0822008-08-26 15:01:29 -0500600 popts->cs_local_opts[i].auto_precharge = 0;
601 }
602
603 /* Pick interleaving mode. */
604
605 /*
606 * 0 = no interleaving
607 * 1 = interleaving between 2 controllers
608 */
609 popts->memctl_interleaving = 0;
610
611 /*
612 * 0 = cacheline
613 * 1 = page
614 * 2 = (logical) bank
615 * 3 = superbank (only if CS interleaving is enabled)
616 */
617 popts->memctl_interleaving_mode = 0;
618
619 /*
620 * 0: cacheline: bit 30 of the 36-bit physical addr selects the memctl
621 * 1: page: bit to the left of the column bits selects the memctl
622 * 2: bank: bit to the left of the bank bits selects the memctl
623 * 3: superbank: bit to the left of the chip select selects the memctl
624 *
625 * NOTE: ba_intlv (rank interleaving) is independent of memory
626 * controller interleaving; it is only within a memory controller.
627 * Must use superbank interleaving if rank interleaving is used and
628 * memory controller interleaving is enabled.
629 */
630
631 /*
632 * 0 = no
633 * 0x40 = CS0,CS1
634 * 0x20 = CS2,CS3
635 * 0x60 = CS0,CS1 + CS2,CS3
636 * 0x04 = CS0,CS1,CS2,CS3
637 */
638 popts->ba_intlv_ctl = 0;
639
640 /* Memory Organization Parameters */
641 popts->registered_dimm_en = all_DIMMs_registered;
642
643 /* Operational Mode Paramters */
644
645 /* Pick ECC modes */
Kumar Gala124b0822008-08-26 15:01:29 -0500646 popts->ECC_mode = 0; /* 0 = disabled, 1 = enabled */
York Sun0ac71ea2011-01-10 12:02:57 +0000647#ifdef CONFIG_DDR_ECC
648 if (hwconfig_sub_f("fsl_ddr", "ecc", buf)) {
649 if (hwconfig_subarg_cmp_f("fsl_ddr", "ecc", "on", buf))
650 popts->ECC_mode = 1;
651 } else
652 popts->ECC_mode = 1;
Kumar Gala124b0822008-08-26 15:01:29 -0500653#endif
654 popts->ECC_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */
655
656 /*
657 * Choose DQS config
658 * 0 for DDR1
659 * 1 for DDR2
660 */
661#if defined(CONFIG_FSL_DDR1)
662 popts->DQS_config = 0;
Dave Liu4be87b22009-03-14 12:48:30 +0800663#elif defined(CONFIG_FSL_DDR2) || defined(CONFIG_FSL_DDR3)
Kumar Gala124b0822008-08-26 15:01:29 -0500664 popts->DQS_config = 1;
Kumar Gala124b0822008-08-26 15:01:29 -0500665#endif
666
667 /* Choose self-refresh during sleep. */
668 popts->self_refresh_in_sleep = 1;
669
670 /* Choose dynamic power management mode. */
671 popts->dynamic_power = 0;
672
York Sun5fb9f6f2011-05-27 07:25:48 +0800673 /*
674 * check first dimm for primary sdram width
675 * presuming all dimms are similar
676 * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
677 */
York Sun3c5ffd42011-06-27 13:35:25 -0700678#if defined(CONFIG_FSL_DDR1) || defined(CONFIG_FSL_DDR2)
679 if (pdimm[0].n_ranks != 0) {
680 if ((pdimm[0].data_width >= 64) && \
681 (pdimm[0].data_width <= 72))
682 popts->data_bus_width = 0;
683 else if ((pdimm[0].data_width >= 32) || \
684 (pdimm[0].data_width <= 40))
685 popts->data_bus_width = 1;
686 else {
687 panic("Error: data width %u is invalid!\n",
688 pdimm[0].data_width);
689 }
690 }
691#else
692 if (pdimm[0].n_ranks != 0) {
693 if (pdimm[0].primary_sdram_width == 64)
694 popts->data_bus_width = 0;
695 else if (pdimm[0].primary_sdram_width == 32)
696 popts->data_bus_width = 1;
697 else if (pdimm[0].primary_sdram_width == 16)
698 popts->data_bus_width = 2;
699 else {
700 panic("Error: primary sdram width %u is invalid!\n",
701 pdimm[0].primary_sdram_width);
702 }
703 }
704#endif
Kumar Gala124b0822008-08-26 15:01:29 -0500705
706 /* Choose burst length. */
Dave Liu4be87b22009-03-14 12:48:30 +0800707#if defined(CONFIG_FSL_DDR3)
Dave Liu707aa5c2010-03-05 12:22:00 +0800708#if defined(CONFIG_E500MC)
709 popts->OTF_burst_chop_en = 0; /* on-the-fly burst chop disable */
710 popts->burst_length = DDR_BL8; /* Fixed 8-beat burst len */
711#else
York Sundd803dd2011-05-27 07:25:51 +0800712 if ((popts->data_bus_width == 1) || (popts->data_bus_width == 2)) {
713 /* 32-bit or 16-bit bus */
York Sun5fb9f6f2011-05-27 07:25:48 +0800714 popts->OTF_burst_chop_en = 0;
715 popts->burst_length = DDR_BL8;
716 } else {
717 popts->OTF_burst_chop_en = 1; /* on-the-fly burst chop */
718 popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */
719 }
Dave Liu707aa5c2010-03-05 12:22:00 +0800720#endif
Dave Liu4be87b22009-03-14 12:48:30 +0800721#else
722 popts->burst_length = DDR_BL4; /* has to be 4 for DDR2 */
723#endif
724
725 /* Choose ddr controller address mirror mode */
726#if defined(CONFIG_FSL_DDR3)
727 popts->mirrored_dimm = pdimm[0].mirrored_dimm;
728#endif
Kumar Gala124b0822008-08-26 15:01:29 -0500729
730 /* Global Timing Parameters. */
731 debug("mclk_ps = %u ps\n", get_memory_clk_period_ps());
732
733 /* Pick a caslat override. */
734 popts->cas_latency_override = 0;
735 popts->cas_latency_override_value = 3;
736 if (popts->cas_latency_override) {
737 debug("using caslat override value = %u\n",
738 popts->cas_latency_override_value);
739 }
740
741 /* Decide whether to use the computed derated latency */
742 popts->use_derated_caslat = 0;
743
744 /* Choose an additive latency. */
745 popts->additive_latency_override = 0;
746 popts->additive_latency_override_value = 3;
747 if (popts->additive_latency_override) {
748 debug("using additive latency override value = %u\n",
749 popts->additive_latency_override_value);
750 }
751
752 /*
753 * 2T_EN setting
754 *
755 * Factors to consider for 2T_EN:
756 * - number of DIMMs installed
757 * - number of components, number of active ranks
758 * - how much time you want to spend playing around
759 */
Dave Liua06d74c2008-11-21 16:31:43 +0800760 popts->twoT_en = 0;
Kumar Gala124b0822008-08-26 15:01:29 -0500761 popts->threeT_en = 0;
762
York Sunba0c2eb2011-01-10 12:03:00 +0000763 /* for RDIMM, address parity enable */
764 popts->ap_en = 1;
765
Kumar Gala124b0822008-08-26 15:01:29 -0500766 /*
767 * BSTTOPRE precharge interval
768 *
769 * Set this to 0 for global auto precharge
770 *
771 * FIXME: Should this be configured in picoseconds?
772 * Why it should be in ps: better understanding of this
773 * relative to actual DRAM timing parameters such as tRAS.
774 * e.g. tRAS(min) = 40 ns
775 */
776 popts->bstopre = 0x100;
777
778 /* Minimum CKE pulse width -- tCKE(MIN) */
779 popts->tCKE_clock_pulse_width_ps
780 = mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR);
781
782 /*
783 * Window for four activates -- tFAW
784 *
785 * FIXME: UM: applies only to DDR2/DDR3 with eight logical banks only
786 * FIXME: varies depending upon number of column addresses or data
787 * FIXME: width, was considering looking at pdimm->primary_sdram_width
788 */
789#if defined(CONFIG_FSL_DDR1)
790 popts->tFAW_window_four_activates_ps = mclk_to_picos(1);
791
792#elif defined(CONFIG_FSL_DDR2)
793 /*
794 * x4/x8; some datasheets have 35000
795 * x16 wide columns only? Use 50000?
796 */
797 popts->tFAW_window_four_activates_ps = 37500;
798
799#elif defined(CONFIG_FSL_DDR3)
Dave Liu4be87b22009-03-14 12:48:30 +0800800 popts->tFAW_window_four_activates_ps = pdimm[0].tFAW_ps;
801#endif
802 popts->zq_en = 0;
803 popts->wrlvl_en = 0;
804#if defined(CONFIG_FSL_DDR3)
805 /*
806 * due to ddr3 dimm is fly-by topology
807 * we suggest to enable write leveling to
808 * meet the tQDSS under different loading.
809 */
810 popts->wrlvl_en = 1;
york1714e492010-07-02 22:25:56 +0000811 popts->zq_en = 1;
Dave Liu64ee7df2009-12-16 10:24:37 -0600812 popts->wrlvl_override = 0;
Kumar Gala124b0822008-08-26 15:01:29 -0500813#endif
814
Kumar Gala124b0822008-08-26 15:01:29 -0500815 /*
Haiying Wangb834f922008-10-03 12:37:10 -0400816 * Check interleaving configuration from environment.
817 * Please refer to doc/README.fsl-ddr for the detail.
Kumar Gala124b0822008-08-26 15:01:29 -0500818 *
819 * If memory controller interleaving is enabled, then the data
york93799ca2010-07-02 22:25:52 +0000820 * bus widths must be programmed identically for all memory controllers.
Haiying Wangb834f922008-10-03 12:37:10 -0400821 *
york93799ca2010-07-02 22:25:52 +0000822 * XXX: Attempt to set all controllers to the same chip select
Haiying Wangb834f922008-10-03 12:37:10 -0400823 * interleaving mode. It will do a best effort to get the
824 * requested ranks interleaved together such that the result
825 * should be a subset of the requested configuration.
Kumar Gala124b0822008-08-26 15:01:29 -0500826 */
Kumar Galac0f3b3c2009-02-06 09:56:34 -0600827#if (CONFIG_NUM_DDR_CONTROLLERS > 1)
York Sune8dc17b2012-08-17 08:22:39 +0000828 if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf))
829 goto done;
830
831 if (pdimm[0].n_ranks == 0) {
832 printf("There is no rank on CS0 for controller %d.\n", ctrl_num);
833 popts->memctl_interleaving = 0;
834 goto done;
835 }
836 popts->memctl_interleaving = 1;
837 /*
838 * test null first. if CONFIG_HWCONFIG is not defined
839 * hwconfig_arg_cmp returns non-zero
840 */
841 if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv",
842 "null", buf)) {
843 popts->memctl_interleaving = 0;
844 debug("memory controller interleaving disabled.\n");
845 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
846 "ctlr_intlv",
847 "cacheline", buf)) {
848 popts->memctl_interleaving_mode =
849 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
850 0 : FSL_DDR_CACHE_LINE_INTERLEAVING;
851 popts->memctl_interleaving =
852 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
853 0 : 1;
854 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
855 "ctlr_intlv",
856 "page", buf)) {
857 popts->memctl_interleaving_mode =
858 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
859 0 : FSL_DDR_PAGE_INTERLEAVING;
860 popts->memctl_interleaving =
861 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
862 0 : 1;
863 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
864 "ctlr_intlv",
865 "bank", buf)) {
866 popts->memctl_interleaving_mode =
867 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
868 0 : FSL_DDR_BANK_INTERLEAVING;
869 popts->memctl_interleaving =
870 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
871 0 : 1;
872 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
873 "ctlr_intlv",
874 "superbank", buf)) {
875 popts->memctl_interleaving_mode =
876 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
877 0 : FSL_DDR_SUPERBANK_INTERLEAVING;
878 popts->memctl_interleaving =
879 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
880 0 : 1;
881#if (CONFIG_NUM_DDR_CONTROLLERS == 3)
882 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
883 "ctlr_intlv",
884 "3way_1KB", buf)) {
885 popts->memctl_interleaving_mode =
886 FSL_DDR_3WAY_1KB_INTERLEAVING;
887 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
888 "ctlr_intlv",
889 "3way_4KB", buf)) {
890 popts->memctl_interleaving_mode =
891 FSL_DDR_3WAY_4KB_INTERLEAVING;
892 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
893 "ctlr_intlv",
894 "3way_8KB", buf)) {
895 popts->memctl_interleaving_mode =
896 FSL_DDR_3WAY_8KB_INTERLEAVING;
897#elif (CONFIG_NUM_DDR_CONTROLLERS == 4)
898 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
899 "ctlr_intlv",
900 "4way_1KB", buf)) {
901 popts->memctl_interleaving_mode =
902 FSL_DDR_4WAY_1KB_INTERLEAVING;
903 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
904 "ctlr_intlv",
905 "4way_4KB", buf)) {
906 popts->memctl_interleaving_mode =
907 FSL_DDR_4WAY_4KB_INTERLEAVING;
908 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
909 "ctlr_intlv",
910 "4way_8KB", buf)) {
911 popts->memctl_interleaving_mode =
912 FSL_DDR_4WAY_8KB_INTERLEAVING;
913#endif
914 } else {
915 popts->memctl_interleaving = 0;
916 printf("hwconfig has unrecognized parameter for ctlr_intlv.\n");
Haiying Wangb834f922008-10-03 12:37:10 -0400917 }
York Sune8dc17b2012-08-17 08:22:39 +0000918done:
Dave Liu0f9318f2009-11-12 07:26:37 +0800919#endif
Kumar Gala72301602011-01-09 11:37:00 -0600920 if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) &&
Dave Liu0f9318f2009-11-12 07:26:37 +0800921 (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
Kumar Gala64042092010-07-14 10:04:21 -0500922 /* test null first. if CONFIG_HWCONFIG is not defined,
Kumar Gala72301602011-01-09 11:37:00 -0600923 * hwconfig_subarg_cmp_f returns non-zero */
924 if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
925 "null", buf))
york93799ca2010-07-02 22:25:52 +0000926 debug("bank interleaving disabled.\n");
Kumar Gala72301602011-01-09 11:37:00 -0600927 else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
928 "cs0_cs1", buf))
Haiying Wangb834f922008-10-03 12:37:10 -0400929 popts->ba_intlv_ctl = FSL_DDR_CS0_CS1;
Kumar Gala72301602011-01-09 11:37:00 -0600930 else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
931 "cs2_cs3", buf))
Haiying Wangb834f922008-10-03 12:37:10 -0400932 popts->ba_intlv_ctl = FSL_DDR_CS2_CS3;
Kumar Gala72301602011-01-09 11:37:00 -0600933 else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
934 "cs0_cs1_and_cs2_cs3", buf))
Haiying Wangb834f922008-10-03 12:37:10 -0400935 popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3;
Kumar Gala72301602011-01-09 11:37:00 -0600936 else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
937 "cs0_cs1_cs2_cs3", buf))
Haiying Wangb834f922008-10-03 12:37:10 -0400938 popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3;
York Sund01babd2012-10-08 07:44:27 +0000939 else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
940 "auto", buf))
941 popts->ba_intlv_ctl = auto_bank_intlv(pdimm);
Haiying Wangb834f922008-10-03 12:37:10 -0400942 else
york93799ca2010-07-02 22:25:52 +0000943 printf("hwconfig has unrecognized parameter for bank_intlv.\n");
Haiying Wangb834f922008-10-03 12:37:10 -0400944 switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
945 case FSL_DDR_CS0_CS1_CS2_CS3:
york93799ca2010-07-02 22:25:52 +0000946#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
yorkf4f93c62010-07-02 22:25:53 +0000947 if (pdimm[0].n_ranks < 4) {
york93799ca2010-07-02 22:25:52 +0000948 popts->ba_intlv_ctl = 0;
949 printf("Not enough bank(chip-select) for "
950 "CS0+CS1+CS2+CS3 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +0000951 "interleaving disabled!\n", ctrl_num);
york93799ca2010-07-02 22:25:52 +0000952 }
953#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
York Sun98df4d12012-10-08 07:44:23 +0000954#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
955 if (pdimm[0].n_ranks == 4)
956 break;
957#endif
yorkf4f93c62010-07-02 22:25:53 +0000958 if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) {
york93799ca2010-07-02 22:25:52 +0000959 popts->ba_intlv_ctl = 0;
960 printf("Not enough bank(chip-select) for "
961 "CS0+CS1+CS2+CS3 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +0000962 "interleaving disabled!\n", ctrl_num);
york93799ca2010-07-02 22:25:52 +0000963 }
964 if (pdimm[0].capacity != pdimm[1].capacity) {
965 popts->ba_intlv_ctl = 0;
966 printf("Not identical DIMM size for "
967 "CS0+CS1+CS2+CS3 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +0000968 "interleaving disabled!\n", ctrl_num);
york93799ca2010-07-02 22:25:52 +0000969 }
970#endif
971 break;
Haiying Wangb834f922008-10-03 12:37:10 -0400972 case FSL_DDR_CS0_CS1:
yorkf4f93c62010-07-02 22:25:53 +0000973 if (pdimm[0].n_ranks < 2) {
Haiying Wangb834f922008-10-03 12:37:10 -0400974 popts->ba_intlv_ctl = 0;
Ed Swarthoutb135d932008-10-29 09:21:44 -0500975 printf("Not enough bank(chip-select) for "
york93799ca2010-07-02 22:25:52 +0000976 "CS0+CS1 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +0000977 "interleaving disabled!\n", ctrl_num);
Haiying Wangb834f922008-10-03 12:37:10 -0400978 }
979 break;
980 case FSL_DDR_CS2_CS3:
york93799ca2010-07-02 22:25:52 +0000981#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
yorkf4f93c62010-07-02 22:25:53 +0000982 if (pdimm[0].n_ranks < 4) {
Haiying Wangb834f922008-10-03 12:37:10 -0400983 popts->ba_intlv_ctl = 0;
york93799ca2010-07-02 22:25:52 +0000984 printf("Not enough bank(chip-select) for CS2+CS3 "
York Sune8dc17b2012-08-17 08:22:39 +0000985 "on controller %d, interleaving disabled!\n", ctrl_num);
Haiying Wangb834f922008-10-03 12:37:10 -0400986 }
york93799ca2010-07-02 22:25:52 +0000987#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
yorkf4f93c62010-07-02 22:25:53 +0000988 if (pdimm[1].n_ranks < 2) {
york93799ca2010-07-02 22:25:52 +0000989 popts->ba_intlv_ctl = 0;
990 printf("Not enough bank(chip-select) for CS2+CS3 "
York Sune8dc17b2012-08-17 08:22:39 +0000991 "on controller %d, interleaving disabled!\n", ctrl_num);
york93799ca2010-07-02 22:25:52 +0000992 }
993#endif
Haiying Wangb834f922008-10-03 12:37:10 -0400994 break;
995 case FSL_DDR_CS0_CS1_AND_CS2_CS3:
york93799ca2010-07-02 22:25:52 +0000996#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
yorkf4f93c62010-07-02 22:25:53 +0000997 if (pdimm[0].n_ranks < 4) {
york93799ca2010-07-02 22:25:52 +0000998 popts->ba_intlv_ctl = 0;
999 printf("Not enough bank(CS) for CS0+CS1 and "
1000 "CS2+CS3 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +00001001 "interleaving disabled!\n", ctrl_num);
york93799ca2010-07-02 22:25:52 +00001002 }
1003#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
yorkf4f93c62010-07-02 22:25:53 +00001004 if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) {
Haiying Wangb834f922008-10-03 12:37:10 -04001005 popts->ba_intlv_ctl = 0;
york93799ca2010-07-02 22:25:52 +00001006 printf("Not enough bank(CS) for CS0+CS1 and "
1007 "CS2+CS3 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +00001008 "interleaving disabled!\n", ctrl_num);
Haiying Wangb834f922008-10-03 12:37:10 -04001009 }
york93799ca2010-07-02 22:25:52 +00001010#endif
Haiying Wangb834f922008-10-03 12:37:10 -04001011 break;
1012 default:
1013 popts->ba_intlv_ctl = 0;
1014 break;
1015 }
1016 }
Kumar Gala124b0822008-08-26 15:01:29 -05001017
Kumar Gala72301602011-01-09 11:37:00 -06001018 if (hwconfig_sub_f("fsl_ddr", "addr_hash", buf)) {
1019 if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", "null", buf))
york42603722010-07-02 22:25:54 +00001020 popts->addr_hash = 0;
Kumar Gala72301602011-01-09 11:37:00 -06001021 else if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash",
1022 "true", buf))
york42603722010-07-02 22:25:54 +00001023 popts->addr_hash = 1;
1024 }
1025
yorkf4f93c62010-07-02 22:25:53 +00001026 if (pdimm[0].n_ranks == 4)
1027 popts->quad_rank_present = 1;
1028
York Sunf0345e22011-08-24 09:40:26 -07001029 ddr_freq = get_ddr_freq(0) / 1000000;
1030 if (popts->registered_dimm_en) {
1031 popts->rcw_override = 1;
1032 popts->rcw_1 = 0x000a5a00;
1033 if (ddr_freq <= 800)
1034 popts->rcw_2 = 0x00000000;
1035 else if (ddr_freq <= 1066)
1036 popts->rcw_2 = 0x00100000;
1037 else if (ddr_freq <= 1333)
1038 popts->rcw_2 = 0x00200000;
1039 else
1040 popts->rcw_2 = 0x00300000;
1041 }
1042
Haiying Wangfa440362008-10-03 12:36:55 -04001043 fsl_ddr_board_options(popts, pdimm, ctrl_num);
Kumar Gala124b0822008-08-26 15:01:29 -05001044
1045 return 0;
1046}
york93799ca2010-07-02 22:25:52 +00001047
1048void check_interleaving_options(fsl_ddr_info_t *pinfo)
1049{
York Sune8dc17b2012-08-17 08:22:39 +00001050 int i, j, k, check_n_ranks, intlv_invalid = 0;
1051 unsigned int check_intlv, check_n_row_addr, check_n_col_addr;
york93799ca2010-07-02 22:25:52 +00001052 unsigned long long check_rank_density;
York Sune8dc17b2012-08-17 08:22:39 +00001053 struct dimm_params_s *dimm;
york93799ca2010-07-02 22:25:52 +00001054 /*
1055 * Check if all controllers are configured for memory
1056 * controller interleaving. Identical dimms are recommended. At least
York Sune8dc17b2012-08-17 08:22:39 +00001057 * the size, row and col address should be checked.
york93799ca2010-07-02 22:25:52 +00001058 */
1059 j = 0;
1060 check_n_ranks = pinfo->dimm_params[0][0].n_ranks;
1061 check_rank_density = pinfo->dimm_params[0][0].rank_density;
York Sune8dc17b2012-08-17 08:22:39 +00001062 check_n_row_addr = pinfo->dimm_params[0][0].n_row_addr;
1063 check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr;
1064 check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode;
york93799ca2010-07-02 22:25:52 +00001065 for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
York Sune8dc17b2012-08-17 08:22:39 +00001066 dimm = &pinfo->dimm_params[i][0];
1067 if (!pinfo->memctl_opts[i].memctl_interleaving) {
1068 continue;
1069 } else if (((check_rank_density != dimm->rank_density) ||
1070 (check_n_ranks != dimm->n_ranks) ||
1071 (check_n_row_addr != dimm->n_row_addr) ||
1072 (check_n_col_addr != dimm->n_col_addr) ||
1073 (check_intlv !=
1074 pinfo->memctl_opts[i].memctl_interleaving_mode))){
1075 intlv_invalid = 1;
1076 break;
1077 } else {
york93799ca2010-07-02 22:25:52 +00001078 j++;
1079 }
York Sune8dc17b2012-08-17 08:22:39 +00001080
york93799ca2010-07-02 22:25:52 +00001081 }
York Sune8dc17b2012-08-17 08:22:39 +00001082 if (intlv_invalid) {
york93799ca2010-07-02 22:25:52 +00001083 for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
York Sune8dc17b2012-08-17 08:22:39 +00001084 pinfo->memctl_opts[i].memctl_interleaving = 0;
1085 printf("Not all DIMMs are identical. "
1086 "Memory controller interleaving disabled.\n");
1087 } else {
1088 switch (check_intlv) {
1089 case FSL_DDR_CACHE_LINE_INTERLEAVING:
1090 case FSL_DDR_PAGE_INTERLEAVING:
1091 case FSL_DDR_BANK_INTERLEAVING:
1092 case FSL_DDR_SUPERBANK_INTERLEAVING:
1093 if (3 == CONFIG_NUM_DDR_CONTROLLERS)
1094 k = 2;
1095 else
1096 k = CONFIG_NUM_DDR_CONTROLLERS;
1097 break;
1098 case FSL_DDR_3WAY_1KB_INTERLEAVING:
1099 case FSL_DDR_3WAY_4KB_INTERLEAVING:
1100 case FSL_DDR_3WAY_8KB_INTERLEAVING:
1101 case FSL_DDR_4WAY_1KB_INTERLEAVING:
1102 case FSL_DDR_4WAY_4KB_INTERLEAVING:
1103 case FSL_DDR_4WAY_8KB_INTERLEAVING:
1104 default:
1105 k = CONFIG_NUM_DDR_CONTROLLERS;
1106 break;
1107 }
1108 debug("%d of %d controllers are interleaving.\n", j, k);
York Sund01babd2012-10-08 07:44:27 +00001109 if (j && (j != k)) {
York Sune8dc17b2012-08-17 08:22:39 +00001110 for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
york93799ca2010-07-02 22:25:52 +00001111 pinfo->memctl_opts[i].memctl_interleaving = 0;
York Sune8dc17b2012-08-17 08:22:39 +00001112 printf("Not all controllers have compatible "
1113 "interleaving mode. All disabled.\n");
1114 }
york93799ca2010-07-02 22:25:52 +00001115 }
York Sune8dc17b2012-08-17 08:22:39 +00001116 debug("Checking interleaving options completed\n");
york93799ca2010-07-02 22:25:52 +00001117}
Kumar Galaf582d982011-01-09 14:06:28 -06001118
1119int fsl_use_spd(void)
1120{
1121 int use_spd = 0;
1122
1123#ifdef CONFIG_DDR_SPD
Kumar Gala72301602011-01-09 11:37:00 -06001124 char buffer[HWCONFIG_BUFFER_SIZE];
1125 char *buf = NULL;
1126
1127 /*
1128 * Extract hwconfig from environment since we have not properly setup
1129 * the environment but need it for ddr config params
1130 */
1131 if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
1132 buf = buffer;
1133
Kumar Galaf582d982011-01-09 14:06:28 -06001134 /* if hwconfig is not enabled, or "sdram" is not defined, use spd */
Kumar Gala72301602011-01-09 11:37:00 -06001135 if (hwconfig_sub_f("fsl_ddr", "sdram", buf)) {
1136 if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", "spd", buf))
Kumar Galaf582d982011-01-09 14:06:28 -06001137 use_spd = 1;
Kumar Gala72301602011-01-09 11:37:00 -06001138 else if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram",
1139 "fixed", buf))
Kumar Galaf582d982011-01-09 14:06:28 -06001140 use_spd = 0;
1141 else
1142 use_spd = 1;
1143 } else
1144 use_spd = 1;
1145#endif
1146
1147 return use_spd;
1148}