blob: 13e48252742d50a5a782ff9123d325612bc01b43 [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
Kumar Gala124b0822008-08-26 15:01:29 -0500477unsigned int populate_memctl_options(int all_DIMMs_registered,
478 memctl_options_t *popts,
Haiying Wangfa440362008-10-03 12:36:55 -0400479 dimm_params_t *pdimm,
Kumar Gala124b0822008-08-26 15:01:29 -0500480 unsigned int ctrl_num)
481{
482 unsigned int i;
Kumar Gala72301602011-01-09 11:37:00 -0600483 char buffer[HWCONFIG_BUFFER_SIZE];
484 char *buf = NULL;
Kumar Gala59cb44c2011-11-09 10:05:21 -0600485#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2)
York Sun454f5072011-08-26 11:32:43 -0700486 const struct dynamic_odt *pdodt = odt_unknown;
Kumar Gala59cb44c2011-11-09 10:05:21 -0600487#endif
York Sunf0345e22011-08-24 09:40:26 -0700488 ulong ddr_freq;
Kumar Gala72301602011-01-09 11:37:00 -0600489
490 /*
491 * Extract hwconfig from environment since we have not properly setup
492 * the environment but need it for ddr config params
493 */
494 if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
495 buf = buffer;
Kumar Gala124b0822008-08-26 15:01:29 -0500496
Kumar Gala59cb44c2011-11-09 10:05:21 -0600497#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2)
Kumar Gala124b0822008-08-26 15:01:29 -0500498 /* Chip select options. */
York Sunba0c2eb2011-01-10 12:03:00 +0000499 if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
500 switch (pdimm[0].n_ranks) {
501 case 1:
502 pdodt = single_S;
503 break;
504 case 2:
505 pdodt = single_D;
506 break;
507 case 4:
508 pdodt = single_Q;
509 break;
510 }
511 } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
512 switch (pdimm[0].n_ranks) {
513 case 2:
514 switch (pdimm[1].n_ranks) {
515 case 2:
516 pdodt = dual_DD;
517 break;
518 case 1:
519 pdodt = dual_DS;
520 break;
521 case 0:
522 pdodt = dual_D0;
523 break;
524 }
525 break;
526 case 1:
527 switch (pdimm[1].n_ranks) {
528 case 2:
529 pdodt = dual_SD;
530 break;
531 case 1:
532 pdodt = dual_SS;
533 break;
534 case 0:
535 pdodt = dual_S0;
536 break;
537 }
538 break;
539 case 0:
540 switch (pdimm[1].n_ranks) {
541 case 2:
542 pdodt = dual_0D;
543 break;
544 case 1:
545 pdodt = dual_0S;
546 break;
547 }
548 break;
549 }
550 }
Kumar Gala59cb44c2011-11-09 10:05:21 -0600551#endif
Kumar Gala124b0822008-08-26 15:01:29 -0500552
553 /* Pick chip-select local options. */
554 for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
York Sun454f5072011-08-26 11:32:43 -0700555#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2)
York Sunba0c2eb2011-01-10 12:03:00 +0000556 popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg;
557 popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg;
558 popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm;
559 popts->cs_local_opts[i].odt_rtt_wr = pdodt[i].odt_rtt_wr;
560#else
561 popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
562 popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
563#endif
Kumar Gala124b0822008-08-26 15:01:29 -0500564 popts->cs_local_opts[i].auto_precharge = 0;
565 }
566
567 /* Pick interleaving mode. */
568
569 /*
570 * 0 = no interleaving
571 * 1 = interleaving between 2 controllers
572 */
573 popts->memctl_interleaving = 0;
574
575 /*
576 * 0 = cacheline
577 * 1 = page
578 * 2 = (logical) bank
579 * 3 = superbank (only if CS interleaving is enabled)
580 */
581 popts->memctl_interleaving_mode = 0;
582
583 /*
584 * 0: cacheline: bit 30 of the 36-bit physical addr selects the memctl
585 * 1: page: bit to the left of the column bits selects the memctl
586 * 2: bank: bit to the left of the bank bits selects the memctl
587 * 3: superbank: bit to the left of the chip select selects the memctl
588 *
589 * NOTE: ba_intlv (rank interleaving) is independent of memory
590 * controller interleaving; it is only within a memory controller.
591 * Must use superbank interleaving if rank interleaving is used and
592 * memory controller interleaving is enabled.
593 */
594
595 /*
596 * 0 = no
597 * 0x40 = CS0,CS1
598 * 0x20 = CS2,CS3
599 * 0x60 = CS0,CS1 + CS2,CS3
600 * 0x04 = CS0,CS1,CS2,CS3
601 */
602 popts->ba_intlv_ctl = 0;
603
604 /* Memory Organization Parameters */
605 popts->registered_dimm_en = all_DIMMs_registered;
606
607 /* Operational Mode Paramters */
608
609 /* Pick ECC modes */
Kumar Gala124b0822008-08-26 15:01:29 -0500610 popts->ECC_mode = 0; /* 0 = disabled, 1 = enabled */
York Sun0ac71ea2011-01-10 12:02:57 +0000611#ifdef CONFIG_DDR_ECC
612 if (hwconfig_sub_f("fsl_ddr", "ecc", buf)) {
613 if (hwconfig_subarg_cmp_f("fsl_ddr", "ecc", "on", buf))
614 popts->ECC_mode = 1;
615 } else
616 popts->ECC_mode = 1;
Kumar Gala124b0822008-08-26 15:01:29 -0500617#endif
618 popts->ECC_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */
619
620 /*
621 * Choose DQS config
622 * 0 for DDR1
623 * 1 for DDR2
624 */
625#if defined(CONFIG_FSL_DDR1)
626 popts->DQS_config = 0;
Dave Liu4be87b22009-03-14 12:48:30 +0800627#elif defined(CONFIG_FSL_DDR2) || defined(CONFIG_FSL_DDR3)
Kumar Gala124b0822008-08-26 15:01:29 -0500628 popts->DQS_config = 1;
Kumar Gala124b0822008-08-26 15:01:29 -0500629#endif
630
631 /* Choose self-refresh during sleep. */
632 popts->self_refresh_in_sleep = 1;
633
634 /* Choose dynamic power management mode. */
635 popts->dynamic_power = 0;
636
York Sun5fb9f6f2011-05-27 07:25:48 +0800637 /*
638 * check first dimm for primary sdram width
639 * presuming all dimms are similar
640 * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
641 */
York Sun3c5ffd42011-06-27 13:35:25 -0700642#if defined(CONFIG_FSL_DDR1) || defined(CONFIG_FSL_DDR2)
643 if (pdimm[0].n_ranks != 0) {
644 if ((pdimm[0].data_width >= 64) && \
645 (pdimm[0].data_width <= 72))
646 popts->data_bus_width = 0;
647 else if ((pdimm[0].data_width >= 32) || \
648 (pdimm[0].data_width <= 40))
649 popts->data_bus_width = 1;
650 else {
651 panic("Error: data width %u is invalid!\n",
652 pdimm[0].data_width);
653 }
654 }
655#else
656 if (pdimm[0].n_ranks != 0) {
657 if (pdimm[0].primary_sdram_width == 64)
658 popts->data_bus_width = 0;
659 else if (pdimm[0].primary_sdram_width == 32)
660 popts->data_bus_width = 1;
661 else if (pdimm[0].primary_sdram_width == 16)
662 popts->data_bus_width = 2;
663 else {
664 panic("Error: primary sdram width %u is invalid!\n",
665 pdimm[0].primary_sdram_width);
666 }
667 }
668#endif
Kumar Gala124b0822008-08-26 15:01:29 -0500669
670 /* Choose burst length. */
Dave Liu4be87b22009-03-14 12:48:30 +0800671#if defined(CONFIG_FSL_DDR3)
Dave Liu707aa5c2010-03-05 12:22:00 +0800672#if defined(CONFIG_E500MC)
673 popts->OTF_burst_chop_en = 0; /* on-the-fly burst chop disable */
674 popts->burst_length = DDR_BL8; /* Fixed 8-beat burst len */
675#else
York Sundd803dd2011-05-27 07:25:51 +0800676 if ((popts->data_bus_width == 1) || (popts->data_bus_width == 2)) {
677 /* 32-bit or 16-bit bus */
York Sun5fb9f6f2011-05-27 07:25:48 +0800678 popts->OTF_burst_chop_en = 0;
679 popts->burst_length = DDR_BL8;
680 } else {
681 popts->OTF_burst_chop_en = 1; /* on-the-fly burst chop */
682 popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */
683 }
Dave Liu707aa5c2010-03-05 12:22:00 +0800684#endif
Dave Liu4be87b22009-03-14 12:48:30 +0800685#else
686 popts->burst_length = DDR_BL4; /* has to be 4 for DDR2 */
687#endif
688
689 /* Choose ddr controller address mirror mode */
690#if defined(CONFIG_FSL_DDR3)
691 popts->mirrored_dimm = pdimm[0].mirrored_dimm;
692#endif
Kumar Gala124b0822008-08-26 15:01:29 -0500693
694 /* Global Timing Parameters. */
695 debug("mclk_ps = %u ps\n", get_memory_clk_period_ps());
696
697 /* Pick a caslat override. */
698 popts->cas_latency_override = 0;
699 popts->cas_latency_override_value = 3;
700 if (popts->cas_latency_override) {
701 debug("using caslat override value = %u\n",
702 popts->cas_latency_override_value);
703 }
704
705 /* Decide whether to use the computed derated latency */
706 popts->use_derated_caslat = 0;
707
708 /* Choose an additive latency. */
709 popts->additive_latency_override = 0;
710 popts->additive_latency_override_value = 3;
711 if (popts->additive_latency_override) {
712 debug("using additive latency override value = %u\n",
713 popts->additive_latency_override_value);
714 }
715
716 /*
717 * 2T_EN setting
718 *
719 * Factors to consider for 2T_EN:
720 * - number of DIMMs installed
721 * - number of components, number of active ranks
722 * - how much time you want to spend playing around
723 */
Dave Liua06d74c2008-11-21 16:31:43 +0800724 popts->twoT_en = 0;
Kumar Gala124b0822008-08-26 15:01:29 -0500725 popts->threeT_en = 0;
726
York Sunba0c2eb2011-01-10 12:03:00 +0000727 /* for RDIMM, address parity enable */
728 popts->ap_en = 1;
729
Kumar Gala124b0822008-08-26 15:01:29 -0500730 /*
731 * BSTTOPRE precharge interval
732 *
733 * Set this to 0 for global auto precharge
734 *
735 * FIXME: Should this be configured in picoseconds?
736 * Why it should be in ps: better understanding of this
737 * relative to actual DRAM timing parameters such as tRAS.
738 * e.g. tRAS(min) = 40 ns
739 */
740 popts->bstopre = 0x100;
741
742 /* Minimum CKE pulse width -- tCKE(MIN) */
743 popts->tCKE_clock_pulse_width_ps
744 = mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR);
745
746 /*
747 * Window for four activates -- tFAW
748 *
749 * FIXME: UM: applies only to DDR2/DDR3 with eight logical banks only
750 * FIXME: varies depending upon number of column addresses or data
751 * FIXME: width, was considering looking at pdimm->primary_sdram_width
752 */
753#if defined(CONFIG_FSL_DDR1)
754 popts->tFAW_window_four_activates_ps = mclk_to_picos(1);
755
756#elif defined(CONFIG_FSL_DDR2)
757 /*
758 * x4/x8; some datasheets have 35000
759 * x16 wide columns only? Use 50000?
760 */
761 popts->tFAW_window_four_activates_ps = 37500;
762
763#elif defined(CONFIG_FSL_DDR3)
Dave Liu4be87b22009-03-14 12:48:30 +0800764 popts->tFAW_window_four_activates_ps = pdimm[0].tFAW_ps;
765#endif
766 popts->zq_en = 0;
767 popts->wrlvl_en = 0;
768#if defined(CONFIG_FSL_DDR3)
769 /*
770 * due to ddr3 dimm is fly-by topology
771 * we suggest to enable write leveling to
772 * meet the tQDSS under different loading.
773 */
774 popts->wrlvl_en = 1;
york1714e492010-07-02 22:25:56 +0000775 popts->zq_en = 1;
Dave Liu64ee7df2009-12-16 10:24:37 -0600776 popts->wrlvl_override = 0;
Kumar Gala124b0822008-08-26 15:01:29 -0500777#endif
778
Kumar Gala124b0822008-08-26 15:01:29 -0500779 /*
Haiying Wangb834f922008-10-03 12:37:10 -0400780 * Check interleaving configuration from environment.
781 * Please refer to doc/README.fsl-ddr for the detail.
Kumar Gala124b0822008-08-26 15:01:29 -0500782 *
783 * If memory controller interleaving is enabled, then the data
york93799ca2010-07-02 22:25:52 +0000784 * bus widths must be programmed identically for all memory controllers.
Haiying Wangb834f922008-10-03 12:37:10 -0400785 *
york93799ca2010-07-02 22:25:52 +0000786 * XXX: Attempt to set all controllers to the same chip select
Haiying Wangb834f922008-10-03 12:37:10 -0400787 * interleaving mode. It will do a best effort to get the
788 * requested ranks interleaved together such that the result
789 * should be a subset of the requested configuration.
Kumar Gala124b0822008-08-26 15:01:29 -0500790 */
Kumar Galac0f3b3c2009-02-06 09:56:34 -0600791#if (CONFIG_NUM_DDR_CONTROLLERS > 1)
York Sune8dc17b2012-08-17 08:22:39 +0000792 if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf))
793 goto done;
794
795 if (pdimm[0].n_ranks == 0) {
796 printf("There is no rank on CS0 for controller %d.\n", ctrl_num);
797 popts->memctl_interleaving = 0;
798 goto done;
799 }
800 popts->memctl_interleaving = 1;
801 /*
802 * test null first. if CONFIG_HWCONFIG is not defined
803 * hwconfig_arg_cmp returns non-zero
804 */
805 if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv",
806 "null", buf)) {
807 popts->memctl_interleaving = 0;
808 debug("memory controller interleaving disabled.\n");
809 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
810 "ctlr_intlv",
811 "cacheline", buf)) {
812 popts->memctl_interleaving_mode =
813 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
814 0 : FSL_DDR_CACHE_LINE_INTERLEAVING;
815 popts->memctl_interleaving =
816 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
817 0 : 1;
818 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
819 "ctlr_intlv",
820 "page", buf)) {
821 popts->memctl_interleaving_mode =
822 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
823 0 : FSL_DDR_PAGE_INTERLEAVING;
824 popts->memctl_interleaving =
825 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
826 0 : 1;
827 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
828 "ctlr_intlv",
829 "bank", buf)) {
830 popts->memctl_interleaving_mode =
831 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
832 0 : FSL_DDR_BANK_INTERLEAVING;
833 popts->memctl_interleaving =
834 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
835 0 : 1;
836 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
837 "ctlr_intlv",
838 "superbank", buf)) {
839 popts->memctl_interleaving_mode =
840 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
841 0 : FSL_DDR_SUPERBANK_INTERLEAVING;
842 popts->memctl_interleaving =
843 ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
844 0 : 1;
845#if (CONFIG_NUM_DDR_CONTROLLERS == 3)
846 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
847 "ctlr_intlv",
848 "3way_1KB", buf)) {
849 popts->memctl_interleaving_mode =
850 FSL_DDR_3WAY_1KB_INTERLEAVING;
851 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
852 "ctlr_intlv",
853 "3way_4KB", buf)) {
854 popts->memctl_interleaving_mode =
855 FSL_DDR_3WAY_4KB_INTERLEAVING;
856 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
857 "ctlr_intlv",
858 "3way_8KB", buf)) {
859 popts->memctl_interleaving_mode =
860 FSL_DDR_3WAY_8KB_INTERLEAVING;
861#elif (CONFIG_NUM_DDR_CONTROLLERS == 4)
862 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
863 "ctlr_intlv",
864 "4way_1KB", buf)) {
865 popts->memctl_interleaving_mode =
866 FSL_DDR_4WAY_1KB_INTERLEAVING;
867 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
868 "ctlr_intlv",
869 "4way_4KB", buf)) {
870 popts->memctl_interleaving_mode =
871 FSL_DDR_4WAY_4KB_INTERLEAVING;
872 } else if (hwconfig_subarg_cmp_f("fsl_ddr",
873 "ctlr_intlv",
874 "4way_8KB", buf)) {
875 popts->memctl_interleaving_mode =
876 FSL_DDR_4WAY_8KB_INTERLEAVING;
877#endif
878 } else {
879 popts->memctl_interleaving = 0;
880 printf("hwconfig has unrecognized parameter for ctlr_intlv.\n");
Haiying Wangb834f922008-10-03 12:37:10 -0400881 }
York Sune8dc17b2012-08-17 08:22:39 +0000882done:
Dave Liu0f9318f2009-11-12 07:26:37 +0800883#endif
Kumar Gala72301602011-01-09 11:37:00 -0600884 if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) &&
Dave Liu0f9318f2009-11-12 07:26:37 +0800885 (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
Kumar Gala64042092010-07-14 10:04:21 -0500886 /* test null first. if CONFIG_HWCONFIG is not defined,
Kumar Gala72301602011-01-09 11:37:00 -0600887 * hwconfig_subarg_cmp_f returns non-zero */
888 if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
889 "null", buf))
york93799ca2010-07-02 22:25:52 +0000890 debug("bank interleaving disabled.\n");
Kumar Gala72301602011-01-09 11:37:00 -0600891 else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
892 "cs0_cs1", buf))
Haiying Wangb834f922008-10-03 12:37:10 -0400893 popts->ba_intlv_ctl = FSL_DDR_CS0_CS1;
Kumar Gala72301602011-01-09 11:37:00 -0600894 else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
895 "cs2_cs3", buf))
Haiying Wangb834f922008-10-03 12:37:10 -0400896 popts->ba_intlv_ctl = FSL_DDR_CS2_CS3;
Kumar Gala72301602011-01-09 11:37:00 -0600897 else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
898 "cs0_cs1_and_cs2_cs3", buf))
Haiying Wangb834f922008-10-03 12:37:10 -0400899 popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3;
Kumar Gala72301602011-01-09 11:37:00 -0600900 else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
901 "cs0_cs1_cs2_cs3", buf))
Haiying Wangb834f922008-10-03 12:37:10 -0400902 popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3;
903 else
york93799ca2010-07-02 22:25:52 +0000904 printf("hwconfig has unrecognized parameter for bank_intlv.\n");
Haiying Wangb834f922008-10-03 12:37:10 -0400905 switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
906 case FSL_DDR_CS0_CS1_CS2_CS3:
york93799ca2010-07-02 22:25:52 +0000907#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
yorkf4f93c62010-07-02 22:25:53 +0000908 if (pdimm[0].n_ranks < 4) {
york93799ca2010-07-02 22:25:52 +0000909 popts->ba_intlv_ctl = 0;
910 printf("Not enough bank(chip-select) for "
911 "CS0+CS1+CS2+CS3 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +0000912 "interleaving disabled!\n", ctrl_num);
york93799ca2010-07-02 22:25:52 +0000913 }
914#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
yorkf4f93c62010-07-02 22:25:53 +0000915 if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) {
york93799ca2010-07-02 22:25:52 +0000916 popts->ba_intlv_ctl = 0;
917 printf("Not enough bank(chip-select) for "
918 "CS0+CS1+CS2+CS3 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +0000919 "interleaving disabled!\n", ctrl_num);
york93799ca2010-07-02 22:25:52 +0000920 }
921 if (pdimm[0].capacity != pdimm[1].capacity) {
922 popts->ba_intlv_ctl = 0;
923 printf("Not identical DIMM size for "
924 "CS0+CS1+CS2+CS3 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +0000925 "interleaving disabled!\n", ctrl_num);
york93799ca2010-07-02 22:25:52 +0000926 }
927#endif
928 break;
Haiying Wangb834f922008-10-03 12:37:10 -0400929 case FSL_DDR_CS0_CS1:
yorkf4f93c62010-07-02 22:25:53 +0000930 if (pdimm[0].n_ranks < 2) {
Haiying Wangb834f922008-10-03 12:37:10 -0400931 popts->ba_intlv_ctl = 0;
Ed Swarthoutb135d932008-10-29 09:21:44 -0500932 printf("Not enough bank(chip-select) for "
york93799ca2010-07-02 22:25:52 +0000933 "CS0+CS1 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +0000934 "interleaving disabled!\n", ctrl_num);
Haiying Wangb834f922008-10-03 12:37:10 -0400935 }
936 break;
937 case FSL_DDR_CS2_CS3:
york93799ca2010-07-02 22:25:52 +0000938#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
yorkf4f93c62010-07-02 22:25:53 +0000939 if (pdimm[0].n_ranks < 4) {
Haiying Wangb834f922008-10-03 12:37:10 -0400940 popts->ba_intlv_ctl = 0;
york93799ca2010-07-02 22:25:52 +0000941 printf("Not enough bank(chip-select) for CS2+CS3 "
York Sune8dc17b2012-08-17 08:22:39 +0000942 "on controller %d, interleaving disabled!\n", ctrl_num);
Haiying Wangb834f922008-10-03 12:37:10 -0400943 }
york93799ca2010-07-02 22:25:52 +0000944#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
yorkf4f93c62010-07-02 22:25:53 +0000945 if (pdimm[1].n_ranks < 2) {
york93799ca2010-07-02 22:25:52 +0000946 popts->ba_intlv_ctl = 0;
947 printf("Not enough bank(chip-select) for CS2+CS3 "
York Sune8dc17b2012-08-17 08:22:39 +0000948 "on controller %d, interleaving disabled!\n", ctrl_num);
york93799ca2010-07-02 22:25:52 +0000949 }
950#endif
Haiying Wangb834f922008-10-03 12:37:10 -0400951 break;
952 case FSL_DDR_CS0_CS1_AND_CS2_CS3:
york93799ca2010-07-02 22:25:52 +0000953#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
yorkf4f93c62010-07-02 22:25:53 +0000954 if (pdimm[0].n_ranks < 4) {
york93799ca2010-07-02 22:25:52 +0000955 popts->ba_intlv_ctl = 0;
956 printf("Not enough bank(CS) for CS0+CS1 and "
957 "CS2+CS3 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +0000958 "interleaving disabled!\n", ctrl_num);
york93799ca2010-07-02 22:25:52 +0000959 }
960#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
yorkf4f93c62010-07-02 22:25:53 +0000961 if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) {
Haiying Wangb834f922008-10-03 12:37:10 -0400962 popts->ba_intlv_ctl = 0;
york93799ca2010-07-02 22:25:52 +0000963 printf("Not enough bank(CS) for CS0+CS1 and "
964 "CS2+CS3 on controller %d, "
York Sune8dc17b2012-08-17 08:22:39 +0000965 "interleaving disabled!\n", ctrl_num);
Haiying Wangb834f922008-10-03 12:37:10 -0400966 }
york93799ca2010-07-02 22:25:52 +0000967#endif
Haiying Wangb834f922008-10-03 12:37:10 -0400968 break;
969 default:
970 popts->ba_intlv_ctl = 0;
971 break;
972 }
973 }
Kumar Gala124b0822008-08-26 15:01:29 -0500974
Kumar Gala72301602011-01-09 11:37:00 -0600975 if (hwconfig_sub_f("fsl_ddr", "addr_hash", buf)) {
976 if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", "null", buf))
york42603722010-07-02 22:25:54 +0000977 popts->addr_hash = 0;
Kumar Gala72301602011-01-09 11:37:00 -0600978 else if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash",
979 "true", buf))
york42603722010-07-02 22:25:54 +0000980 popts->addr_hash = 1;
981 }
982
yorkf4f93c62010-07-02 22:25:53 +0000983 if (pdimm[0].n_ranks == 4)
984 popts->quad_rank_present = 1;
985
York Sunf0345e22011-08-24 09:40:26 -0700986 ddr_freq = get_ddr_freq(0) / 1000000;
987 if (popts->registered_dimm_en) {
988 popts->rcw_override = 1;
989 popts->rcw_1 = 0x000a5a00;
990 if (ddr_freq <= 800)
991 popts->rcw_2 = 0x00000000;
992 else if (ddr_freq <= 1066)
993 popts->rcw_2 = 0x00100000;
994 else if (ddr_freq <= 1333)
995 popts->rcw_2 = 0x00200000;
996 else
997 popts->rcw_2 = 0x00300000;
998 }
999
Haiying Wangfa440362008-10-03 12:36:55 -04001000 fsl_ddr_board_options(popts, pdimm, ctrl_num);
Kumar Gala124b0822008-08-26 15:01:29 -05001001
1002 return 0;
1003}
york93799ca2010-07-02 22:25:52 +00001004
1005void check_interleaving_options(fsl_ddr_info_t *pinfo)
1006{
York Sune8dc17b2012-08-17 08:22:39 +00001007 int i, j, k, check_n_ranks, intlv_invalid = 0;
1008 unsigned int check_intlv, check_n_row_addr, check_n_col_addr;
york93799ca2010-07-02 22:25:52 +00001009 unsigned long long check_rank_density;
York Sune8dc17b2012-08-17 08:22:39 +00001010 struct dimm_params_s *dimm;
york93799ca2010-07-02 22:25:52 +00001011 /*
1012 * Check if all controllers are configured for memory
1013 * controller interleaving. Identical dimms are recommended. At least
York Sune8dc17b2012-08-17 08:22:39 +00001014 * the size, row and col address should be checked.
york93799ca2010-07-02 22:25:52 +00001015 */
1016 j = 0;
1017 check_n_ranks = pinfo->dimm_params[0][0].n_ranks;
1018 check_rank_density = pinfo->dimm_params[0][0].rank_density;
York Sune8dc17b2012-08-17 08:22:39 +00001019 check_n_row_addr = pinfo->dimm_params[0][0].n_row_addr;
1020 check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr;
1021 check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode;
york93799ca2010-07-02 22:25:52 +00001022 for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
York Sune8dc17b2012-08-17 08:22:39 +00001023 dimm = &pinfo->dimm_params[i][0];
1024 if (!pinfo->memctl_opts[i].memctl_interleaving) {
1025 continue;
1026 } else if (((check_rank_density != dimm->rank_density) ||
1027 (check_n_ranks != dimm->n_ranks) ||
1028 (check_n_row_addr != dimm->n_row_addr) ||
1029 (check_n_col_addr != dimm->n_col_addr) ||
1030 (check_intlv !=
1031 pinfo->memctl_opts[i].memctl_interleaving_mode))){
1032 intlv_invalid = 1;
1033 break;
1034 } else {
york93799ca2010-07-02 22:25:52 +00001035 j++;
1036 }
York Sune8dc17b2012-08-17 08:22:39 +00001037
york93799ca2010-07-02 22:25:52 +00001038 }
York Sune8dc17b2012-08-17 08:22:39 +00001039 if (intlv_invalid) {
york93799ca2010-07-02 22:25:52 +00001040 for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
York Sune8dc17b2012-08-17 08:22:39 +00001041 pinfo->memctl_opts[i].memctl_interleaving = 0;
1042 printf("Not all DIMMs are identical. "
1043 "Memory controller interleaving disabled.\n");
1044 } else {
1045 switch (check_intlv) {
1046 case FSL_DDR_CACHE_LINE_INTERLEAVING:
1047 case FSL_DDR_PAGE_INTERLEAVING:
1048 case FSL_DDR_BANK_INTERLEAVING:
1049 case FSL_DDR_SUPERBANK_INTERLEAVING:
1050 if (3 == CONFIG_NUM_DDR_CONTROLLERS)
1051 k = 2;
1052 else
1053 k = CONFIG_NUM_DDR_CONTROLLERS;
1054 break;
1055 case FSL_DDR_3WAY_1KB_INTERLEAVING:
1056 case FSL_DDR_3WAY_4KB_INTERLEAVING:
1057 case FSL_DDR_3WAY_8KB_INTERLEAVING:
1058 case FSL_DDR_4WAY_1KB_INTERLEAVING:
1059 case FSL_DDR_4WAY_4KB_INTERLEAVING:
1060 case FSL_DDR_4WAY_8KB_INTERLEAVING:
1061 default:
1062 k = CONFIG_NUM_DDR_CONTROLLERS;
1063 break;
1064 }
1065 debug("%d of %d controllers are interleaving.\n", j, k);
1066 if (j != k) {
1067 for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
york93799ca2010-07-02 22:25:52 +00001068 pinfo->memctl_opts[i].memctl_interleaving = 0;
York Sune8dc17b2012-08-17 08:22:39 +00001069 printf("Not all controllers have compatible "
1070 "interleaving mode. All disabled.\n");
1071 }
york93799ca2010-07-02 22:25:52 +00001072 }
York Sune8dc17b2012-08-17 08:22:39 +00001073 debug("Checking interleaving options completed\n");
york93799ca2010-07-02 22:25:52 +00001074}
Kumar Galaf582d982011-01-09 14:06:28 -06001075
1076int fsl_use_spd(void)
1077{
1078 int use_spd = 0;
1079
1080#ifdef CONFIG_DDR_SPD
Kumar Gala72301602011-01-09 11:37:00 -06001081 char buffer[HWCONFIG_BUFFER_SIZE];
1082 char *buf = NULL;
1083
1084 /*
1085 * Extract hwconfig from environment since we have not properly setup
1086 * the environment but need it for ddr config params
1087 */
1088 if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
1089 buf = buffer;
1090
Kumar Galaf582d982011-01-09 14:06:28 -06001091 /* if hwconfig is not enabled, or "sdram" is not defined, use spd */
Kumar Gala72301602011-01-09 11:37:00 -06001092 if (hwconfig_sub_f("fsl_ddr", "sdram", buf)) {
1093 if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", "spd", buf))
Kumar Galaf582d982011-01-09 14:06:28 -06001094 use_spd = 1;
Kumar Gala72301602011-01-09 11:37:00 -06001095 else if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram",
1096 "fixed", buf))
Kumar Galaf582d982011-01-09 14:06:28 -06001097 use_spd = 0;
1098 else
1099 use_spd = 1;
1100 } else
1101 use_spd = 1;
1102#endif
1103
1104 return use_spd;
1105}