]>
Commit | Line | Data |
---|---|---|
58e5e9af | 1 | /* |
a4c66509 | 2 | * Copyright 2008-2012 Freescale Semiconductor, Inc. |
58e5e9af KG |
3 | * |
4 | * This program is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU General Public License | |
6 | * Version 2 as published by the Free Software Foundation. | |
7 | */ | |
8 | ||
9 | /* | |
10 | * Generic driver for Freescale DDR/DDR2/DDR3 memory controller. | |
11 | * Based on code from spd_sdram.c | |
12 | * Author: James Yang [at freescale.com] | |
13 | */ | |
14 | ||
15 | #include <common.h> | |
c39f44dc | 16 | #include <i2c.h> |
58e5e9af | 17 | #include <asm/fsl_ddr_sdram.h> |
a4c66509 | 18 | #include <asm/fsl_law.h> |
58e5e9af KG |
19 | |
20 | #include "ddr.h" | |
21 | ||
a4c66509 | 22 | void fsl_ddr_set_lawbar( |
58e5e9af KG |
23 | const common_timing_params_t *memctl_common_params, |
24 | unsigned int memctl_interleaved, | |
25 | unsigned int ctrl_num); | |
a4c66509 | 26 | void fsl_ddr_set_intl3r(const unsigned int granule_size); |
58e5e9af KG |
27 | |
28 | /* processor specific function */ | |
29 | extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, | |
30 | unsigned int ctrl_num); | |
31 | ||
c39f44dc KG |
32 | #if defined(SPD_EEPROM_ADDRESS) || \ |
33 | defined(SPD_EEPROM_ADDRESS1) || defined(SPD_EEPROM_ADDRESS2) || \ | |
34 | defined(SPD_EEPROM_ADDRESS3) || defined(SPD_EEPROM_ADDRESS4) | |
35 | #if (CONFIG_NUM_DDR_CONTROLLERS == 1) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) | |
36 | u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { | |
37 | [0][0] = SPD_EEPROM_ADDRESS, | |
38 | }; | |
639f330f YS |
39 | #elif (CONFIG_NUM_DDR_CONTROLLERS == 1) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) |
40 | u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { | |
41 | [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ | |
42 | [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ | |
43 | }; | |
44 | #elif (CONFIG_NUM_DDR_CONTROLLERS == 2) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) | |
c39f44dc KG |
45 | u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { |
46 | [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ | |
47 | [1][0] = SPD_EEPROM_ADDRESS2, /* controller 2 */ | |
48 | }; | |
639f330f | 49 | #elif (CONFIG_NUM_DDR_CONTROLLERS == 2) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) |
c39f44dc KG |
50 | u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { |
51 | [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ | |
52 | [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ | |
53 | [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */ | |
54 | [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */ | |
55 | }; | |
a4c66509 YS |
56 | #elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1) |
57 | u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { | |
58 | [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ | |
59 | [1][0] = SPD_EEPROM_ADDRESS2, /* controller 2 */ | |
60 | [2][0] = SPD_EEPROM_ADDRESS3, /* controller 3 */ | |
61 | }; | |
62 | #elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2) | |
63 | u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = { | |
64 | [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */ | |
65 | [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */ | |
66 | [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */ | |
67 | [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */ | |
68 | [2][0] = SPD_EEPROM_ADDRESS5, /* controller 3 */ | |
69 | [2][1] = SPD_EEPROM_ADDRESS6, /* controller 3 */ | |
70 | }; | |
71 | ||
c39f44dc KG |
72 | #endif |
73 | ||
74 | static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address) | |
75 | { | |
76 | int ret = i2c_read(i2c_address, 0, 1, (uchar *)spd, | |
77 | sizeof(generic_spd_eeprom_t)); | |
78 | ||
79 | if (ret) { | |
82968a7a YS |
80 | if (i2c_address == |
81 | #ifdef SPD_EEPROM_ADDRESS | |
82 | SPD_EEPROM_ADDRESS | |
83 | #elif defined(SPD_EEPROM_ADDRESS1) | |
84 | SPD_EEPROM_ADDRESS1 | |
85 | #endif | |
86 | ) { | |
87 | printf("DDR: failed to read SPD from address %u\n", | |
88 | i2c_address); | |
89 | } else { | |
90 | debug("DDR: failed to read SPD from address %u\n", | |
91 | i2c_address); | |
92 | } | |
c39f44dc KG |
93 | memset(spd, 0, sizeof(generic_spd_eeprom_t)); |
94 | } | |
95 | } | |
96 | ||
97 | __attribute__((weak, alias("__get_spd"))) | |
98 | void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address); | |
99 | ||
100 | void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, | |
101 | unsigned int ctrl_num) | |
102 | { | |
103 | unsigned int i; | |
104 | unsigned int i2c_address = 0; | |
105 | ||
106 | if (ctrl_num >= CONFIG_NUM_DDR_CONTROLLERS) { | |
107 | printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); | |
108 | return; | |
109 | } | |
110 | ||
111 | for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { | |
112 | i2c_address = spd_i2c_addr[ctrl_num][i]; | |
113 | get_spd(&(ctrl_dimms_spd[i]), i2c_address); | |
114 | } | |
115 | } | |
116 | #else | |
117 | void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd, | |
118 | unsigned int ctrl_num) | |
119 | { | |
120 | } | |
121 | #endif /* SPD_EEPROM_ADDRESSx */ | |
58e5e9af KG |
122 | |
123 | /* | |
124 | * ASSUMPTIONS: | |
125 | * - Same number of CONFIG_DIMM_SLOTS_PER_CTLR on each controller | |
126 | * - Same memory data bus width on all controllers | |
127 | * | |
128 | * NOTES: | |
129 | * | |
130 | * The memory controller and associated documentation use confusing | |
131 | * terminology when referring to the orgranization of DRAM. | |
132 | * | |
133 | * Here is a terminology translation table: | |
134 | * | |
135 | * memory controller/documention |industry |this code |signals | |
136 | * -------------------------------|-----------|-----------|----------------- | |
f12e4549 WD |
137 | * physical bank/bank |rank |rank |chip select (CS) |
138 | * logical bank/sub-bank |bank |bank |bank address (BA) | |
139 | * page/row |row |page |row address | |
140 | * ??? |column |column |column address | |
58e5e9af KG |
141 | * |
142 | * The naming confusion is further exacerbated by the descriptions of the | |
143 | * memory controller interleaving feature, where accesses are interleaved | |
144 | * _BETWEEN_ two seperate memory controllers. This is configured only in | |
145 | * CS0_CONFIG[INTLV_CTL] of each memory controller. | |
146 | * | |
147 | * memory controller documentation | number of chip selects | |
f12e4549 | 148 | * | per memory controller supported |
58e5e9af | 149 | * --------------------------------|----------------------------------------- |
f12e4549 WD |
150 | * cache line interleaving | 1 (CS0 only) |
151 | * page interleaving | 1 (CS0 only) | |
152 | * bank interleaving | 1 (CS0 only) | |
153 | * superbank interleraving | depends on bank (chip select) | |
154 | * | interleraving [rank interleaving] | |
155 | * | mode used on every memory controller | |
58e5e9af KG |
156 | * |
157 | * Even further confusing is the existence of the interleaving feature | |
158 | * _WITHIN_ each memory controller. The feature is referred to in | |
159 | * documentation as chip select interleaving or bank interleaving, | |
160 | * although it is configured in the DDR_SDRAM_CFG field. | |
161 | * | |
f12e4549 | 162 | * Name of field | documentation name | this code |
58e5e9af | 163 | * -----------------------------|-----------------------|------------------ |
f12e4549 WD |
164 | * DDR_SDRAM_CFG[BA_INTLV_CTL] | Bank (chip select) | rank interleaving |
165 | * | interleaving | |
58e5e9af KG |
166 | */ |
167 | ||
58e5e9af KG |
168 | const char *step_string_tbl[] = { |
169 | "STEP_GET_SPD", | |
170 | "STEP_COMPUTE_DIMM_PARMS", | |
171 | "STEP_COMPUTE_COMMON_PARMS", | |
172 | "STEP_GATHER_OPTS", | |
173 | "STEP_ASSIGN_ADDRESSES", | |
174 | "STEP_COMPUTE_REGS", | |
175 | "STEP_PROGRAM_REGS", | |
176 | "STEP_ALL" | |
177 | }; | |
178 | ||
179 | const char * step_to_string(unsigned int step) { | |
180 | ||
181 | unsigned int s = __ilog2(step); | |
182 | ||
183 | if ((1 << s) != step) | |
184 | return step_string_tbl[7]; | |
185 | ||
186 | return step_string_tbl[s]; | |
187 | } | |
58e5e9af | 188 | |
a4c66509 YS |
189 | unsigned long long step_assign_addresses(fsl_ddr_info_t *pinfo, |
190 | unsigned int dbw_cap_adj[]) | |
58e5e9af KG |
191 | { |
192 | int i, j; | |
a4c66509 YS |
193 | unsigned long long total_mem, current_mem_base, total_ctlr_mem; |
194 | unsigned long long rank_density, ctlr_density = 0; | |
58e5e9af KG |
195 | |
196 | /* | |
197 | * If a reduced data width is requested, but the SPD | |
198 | * specifies a physically wider device, adjust the | |
199 | * computed dimm capacities accordingly before | |
200 | * assigning addresses. | |
201 | */ | |
202 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
203 | unsigned int found = 0; | |
204 | ||
205 | switch (pinfo->memctl_opts[i].data_bus_width) { | |
206 | case 2: | |
207 | /* 16-bit */ | |
51d498f1 YS |
208 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { |
209 | unsigned int dw; | |
210 | if (!pinfo->dimm_params[i][j].n_ranks) | |
211 | continue; | |
212 | dw = pinfo->dimm_params[i][j].primary_sdram_width; | |
213 | if ((dw == 72 || dw == 64)) { | |
214 | dbw_cap_adj[i] = 2; | |
215 | break; | |
216 | } else if ((dw == 40 || dw == 32)) { | |
217 | dbw_cap_adj[i] = 1; | |
218 | break; | |
219 | } | |
220 | } | |
58e5e9af KG |
221 | break; |
222 | ||
223 | case 1: | |
224 | /* 32-bit */ | |
225 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { | |
226 | unsigned int dw; | |
227 | dw = pinfo->dimm_params[i][j].data_width; | |
228 | if (pinfo->dimm_params[i][j].n_ranks | |
229 | && (dw == 72 || dw == 64)) { | |
230 | /* | |
231 | * FIXME: can't really do it | |
232 | * like this because this just | |
233 | * further reduces the memory | |
234 | */ | |
235 | found = 1; | |
236 | break; | |
237 | } | |
238 | } | |
239 | if (found) { | |
240 | dbw_cap_adj[i] = 1; | |
241 | } | |
242 | break; | |
243 | ||
244 | case 0: | |
245 | /* 64-bit */ | |
246 | break; | |
247 | ||
248 | default: | |
249 | printf("unexpected data bus width " | |
250 | "specified controller %u\n", i); | |
251 | return 1; | |
252 | } | |
a4c66509 | 253 | debug("dbw_cap_adj[%d]=%d\n", i, dbw_cap_adj[i]); |
58e5e9af KG |
254 | } |
255 | ||
a4c66509 YS |
256 | current_mem_base = 0ull; |
257 | total_mem = 0; | |
258 | if (pinfo->memctl_opts[0].memctl_interleaving) { | |
259 | rank_density = pinfo->dimm_params[0][0].rank_density >> | |
260 | dbw_cap_adj[0]; | |
261 | switch (pinfo->memctl_opts[0].ba_intlv_ctl & | |
262 | FSL_DDR_CS0_CS1_CS2_CS3) { | |
263 | case FSL_DDR_CS0_CS1_CS2_CS3: | |
264 | ctlr_density = 4 * rank_density; | |
265 | break; | |
266 | case FSL_DDR_CS0_CS1: | |
267 | case FSL_DDR_CS0_CS1_AND_CS2_CS3: | |
268 | ctlr_density = 2 * rank_density; | |
269 | break; | |
270 | case FSL_DDR_CS2_CS3: | |
271 | default: | |
272 | ctlr_density = rank_density; | |
273 | break; | |
274 | } | |
275 | debug("rank density is 0x%llx, ctlr density is 0x%llx\n", | |
276 | rank_density, ctlr_density); | |
58e5e9af | 277 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { |
a4c66509 YS |
278 | if (pinfo->memctl_opts[i].memctl_interleaving) { |
279 | switch (pinfo->memctl_opts[i].memctl_interleaving_mode) { | |
280 | case FSL_DDR_CACHE_LINE_INTERLEAVING: | |
281 | case FSL_DDR_PAGE_INTERLEAVING: | |
282 | case FSL_DDR_BANK_INTERLEAVING: | |
283 | case FSL_DDR_SUPERBANK_INTERLEAVING: | |
284 | total_ctlr_mem = 2 * ctlr_density; | |
285 | break; | |
286 | case FSL_DDR_3WAY_1KB_INTERLEAVING: | |
287 | case FSL_DDR_3WAY_4KB_INTERLEAVING: | |
288 | case FSL_DDR_3WAY_8KB_INTERLEAVING: | |
289 | total_ctlr_mem = 3 * ctlr_density; | |
290 | break; | |
291 | case FSL_DDR_4WAY_1KB_INTERLEAVING: | |
292 | case FSL_DDR_4WAY_4KB_INTERLEAVING: | |
293 | case FSL_DDR_4WAY_8KB_INTERLEAVING: | |
294 | total_ctlr_mem = 4 * ctlr_density; | |
295 | break; | |
296 | default: | |
297 | panic("Unknown interleaving mode"); | |
298 | } | |
299 | pinfo->common_timing_params[i].base_address = | |
300 | current_mem_base; | |
301 | pinfo->common_timing_params[i].total_mem = | |
302 | total_ctlr_mem; | |
303 | total_mem = current_mem_base + total_ctlr_mem; | |
304 | debug("ctrl %d base 0x%llx\n", i, current_mem_base); | |
305 | debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); | |
306 | } else { | |
307 | /* when 3rd controller not interleaved */ | |
308 | current_mem_base = total_mem; | |
309 | total_ctlr_mem = 0; | |
310 | pinfo->common_timing_params[i].base_address = | |
311 | current_mem_base; | |
312 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { | |
313 | unsigned long long cap = | |
314 | pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i]; | |
315 | pinfo->dimm_params[i][j].base_address = | |
316 | current_mem_base; | |
317 | debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base); | |
318 | current_mem_base += cap; | |
319 | total_ctlr_mem += cap; | |
320 | } | |
321 | debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); | |
322 | pinfo->common_timing_params[i].total_mem = | |
323 | total_ctlr_mem; | |
324 | total_mem += total_ctlr_mem; | |
58e5e9af KG |
325 | } |
326 | } | |
327 | } else { | |
328 | /* | |
329 | * Simple linear assignment if memory | |
330 | * controllers are not interleaved. | |
331 | */ | |
58e5e9af | 332 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { |
a4c66509 | 333 | total_ctlr_mem = 0; |
58e5e9af | 334 | pinfo->common_timing_params[i].base_address = |
a4c66509 | 335 | current_mem_base; |
58e5e9af KG |
336 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { |
337 | /* Compute DIMM base addresses. */ | |
338 | unsigned long long cap = | |
a4c66509 | 339 | pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i]; |
58e5e9af | 340 | pinfo->dimm_params[i][j].base_address = |
a4c66509 YS |
341 | current_mem_base; |
342 | debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base); | |
343 | current_mem_base += cap; | |
344 | total_ctlr_mem += cap; | |
58e5e9af | 345 | } |
a4c66509 | 346 | debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem); |
58e5e9af | 347 | pinfo->common_timing_params[i].total_mem = |
a4c66509 YS |
348 | total_ctlr_mem; |
349 | total_mem += total_ctlr_mem; | |
58e5e9af KG |
350 | } |
351 | } | |
a4c66509 | 352 | debug("Total mem by %s is 0x%llx\n", __func__, total_mem); |
58e5e9af | 353 | |
a4c66509 | 354 | return total_mem; |
58e5e9af KG |
355 | } |
356 | ||
e7563aff | 357 | unsigned long long |
fc0c2b6f HW |
358 | fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, |
359 | unsigned int size_only) | |
58e5e9af KG |
360 | { |
361 | unsigned int i, j; | |
e7563aff | 362 | unsigned long long total_mem = 0; |
58e5e9af KG |
363 | |
364 | fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg; | |
365 | common_timing_params_t *timing_params = pinfo->common_timing_params; | |
366 | ||
367 | /* data bus width capacity adjust shift amount */ | |
368 | unsigned int dbw_capacity_adjust[CONFIG_NUM_DDR_CONTROLLERS]; | |
369 | ||
370 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
371 | dbw_capacity_adjust[i] = 0; | |
372 | } | |
373 | ||
374 | debug("starting at step %u (%s)\n", | |
375 | start_step, step_to_string(start_step)); | |
376 | ||
377 | switch (start_step) { | |
378 | case STEP_GET_SPD: | |
1b3e3c4f | 379 | #if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM) |
58e5e9af KG |
380 | /* STEP 1: Gather all DIMM SPD data */ |
381 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
382 | fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i); | |
383 | } | |
384 | ||
385 | case STEP_COMPUTE_DIMM_PARMS: | |
386 | /* STEP 2: Compute DIMM parameters from SPD data */ | |
387 | ||
388 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
389 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { | |
390 | unsigned int retval; | |
391 | generic_spd_eeprom_t *spd = | |
392 | &(pinfo->spd_installed_dimms[i][j]); | |
393 | dimm_params_t *pdimm = | |
f12e4549 | 394 | &(pinfo->dimm_params[i][j]); |
58e5e9af KG |
395 | |
396 | retval = compute_dimm_parameters(spd, pdimm, i); | |
f2d264b6 | 397 | #ifdef CONFIG_SYS_DDR_RAW_TIMING |
62f739fe | 398 | if (!i && !j && retval) { |
a4c66509 YS |
399 | printf("SPD error on controller %d! " |
400 | "Trying fallback to raw timing " | |
401 | "calculation\n", i); | |
f2d264b6 YS |
402 | fsl_ddr_get_dimm_params(pdimm, i, j); |
403 | } | |
404 | #else | |
58e5e9af KG |
405 | if (retval == 2) { |
406 | printf("Error: compute_dimm_parameters" | |
407 | " non-zero returned FATAL value " | |
408 | "for memctl=%u dimm=%u\n", i, j); | |
409 | return 0; | |
410 | } | |
f2d264b6 | 411 | #endif |
58e5e9af KG |
412 | if (retval) { |
413 | debug("Warning: compute_dimm_parameters" | |
414 | " non-zero return value for memctl=%u " | |
415 | "dimm=%u\n", i, j); | |
416 | } | |
417 | } | |
418 | } | |
419 | ||
98de369b | 420 | #elif defined(CONFIG_SYS_DDR_RAW_TIMING) |
1b3e3c4f YS |
421 | case STEP_COMPUTE_DIMM_PARMS: |
422 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
423 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { | |
424 | dimm_params_t *pdimm = | |
425 | &(pinfo->dimm_params[i][j]); | |
426 | fsl_ddr_get_dimm_params(pdimm, i, j); | |
427 | } | |
428 | } | |
429 | debug("Filling dimm parameters from board specific file\n"); | |
430 | #endif | |
58e5e9af KG |
431 | case STEP_COMPUTE_COMMON_PARMS: |
432 | /* | |
433 | * STEP 3: Compute a common set of timing parameters | |
434 | * suitable for all of the DIMMs on each memory controller | |
435 | */ | |
436 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
437 | debug("Computing lowest common DIMM" | |
438 | " parameters for memctl=%u\n", i); | |
439 | compute_lowest_common_dimm_parameters( | |
440 | pinfo->dimm_params[i], | |
441 | &timing_params[i], | |
442 | CONFIG_DIMM_SLOTS_PER_CTLR); | |
443 | } | |
444 | ||
445 | case STEP_GATHER_OPTS: | |
446 | /* STEP 4: Gather configuration requirements from user */ | |
447 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
448 | debug("Reloading memory controller " | |
449 | "configuration options for memctl=%u\n", i); | |
450 | /* | |
451 | * This "reloads" the memory controller options | |
452 | * to defaults. If the user "edits" an option, | |
453 | * next_step points to the step after this, | |
454 | * which is currently STEP_ASSIGN_ADDRESSES. | |
455 | */ | |
456 | populate_memctl_options( | |
457 | timing_params[i].all_DIMMs_registered, | |
dfb49108 HW |
458 | &pinfo->memctl_opts[i], |
459 | pinfo->dimm_params[i], i); | |
58e5e9af | 460 | } |
58e5e9af KG |
461 | case STEP_ASSIGN_ADDRESSES: |
462 | /* STEP 5: Assign addresses to chip selects */ | |
a4c66509 YS |
463 | check_interleaving_options(pinfo); |
464 | total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust); | |
58e5e9af KG |
465 | |
466 | case STEP_COMPUTE_REGS: | |
467 | /* STEP 6: compute controller register values */ | |
a4c66509 | 468 | debug("FSL Memory ctrl register computation\n"); |
58e5e9af KG |
469 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { |
470 | if (timing_params[i].ndimms_present == 0) { | |
471 | memset(&ddr_reg[i], 0, | |
472 | sizeof(fsl_ddr_cfg_regs_t)); | |
473 | continue; | |
474 | } | |
475 | ||
476 | compute_fsl_memctl_config_regs( | |
477 | &pinfo->memctl_opts[i], | |
478 | &ddr_reg[i], &timing_params[i], | |
479 | pinfo->dimm_params[i], | |
fc0c2b6f HW |
480 | dbw_capacity_adjust[i], |
481 | size_only); | |
58e5e9af KG |
482 | } |
483 | ||
484 | default: | |
485 | break; | |
486 | } | |
487 | ||
a4c66509 | 488 | { |
58e5e9af KG |
489 | /* |
490 | * Compute the amount of memory available just by | |
491 | * looking for the highest valid CSn_BNDS value. | |
492 | * This allows us to also experiment with using | |
493 | * only CS0 when using dual-rank DIMMs. | |
494 | */ | |
495 | unsigned int max_end = 0; | |
496 | ||
497 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
498 | for (j = 0; j < CONFIG_CHIP_SELECTS_PER_CTRL; j++) { | |
499 | fsl_ddr_cfg_regs_t *reg = &ddr_reg[i]; | |
500 | if (reg->cs[j].config & 0x80000000) { | |
501 | unsigned int end; | |
502 | end = reg->cs[j].bnds & 0xFFF; | |
503 | if (end > max_end) { | |
504 | max_end = end; | |
505 | } | |
506 | } | |
507 | } | |
508 | } | |
509 | ||
58e5e9af KG |
510 | total_mem = 1 + (((unsigned long long)max_end << 24ULL) |
511 | | 0xFFFFFFULL); | |
512 | } | |
513 | ||
514 | return total_mem; | |
515 | } | |
516 | ||
517 | /* | |
518 | * fsl_ddr_sdram() -- this is the main function to be called by | |
519 | * initdram() in the board file. | |
520 | * | |
521 | * It returns amount of memory configured in bytes. | |
522 | */ | |
523 | phys_size_t fsl_ddr_sdram(void) | |
524 | { | |
525 | unsigned int i; | |
a4c66509 | 526 | unsigned int law_memctl = LAW_TRGT_IF_DDR_1; |
e7563aff | 527 | unsigned long long total_memory; |
58e5e9af KG |
528 | fsl_ddr_info_t info; |
529 | ||
530 | /* Reset info structure. */ | |
531 | memset(&info, 0, sizeof(fsl_ddr_info_t)); | |
532 | ||
533 | /* Compute it once normally. */ | |
6f5e1dc5 YS |
534 | #ifdef CONFIG_FSL_DDR_INTERACTIVE |
535 | if (getenv("ddr_interactive")) | |
536 | total_memory = fsl_ddr_interactive(&info); | |
537 | else | |
538 | #endif | |
539 | total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0); | |
58e5e9af | 540 | |
f31cfd19 YS |
541 | /* setup 3-way interleaving before enabling DDRC */ |
542 | switch (info.memctl_opts[0].memctl_interleaving_mode) { | |
543 | case FSL_DDR_3WAY_1KB_INTERLEAVING: | |
544 | case FSL_DDR_3WAY_4KB_INTERLEAVING: | |
545 | case FSL_DDR_3WAY_8KB_INTERLEAVING: | |
546 | fsl_ddr_set_intl3r(info.memctl_opts[0].memctl_interleaving_mode); | |
547 | break; | |
548 | default: | |
549 | break; | |
550 | } | |
551 | ||
58e5e9af KG |
552 | /* Program configuration registers. */ |
553 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
554 | debug("Programming controller %u\n", i); | |
555 | if (info.common_timing_params[i].ndimms_present == 0) { | |
556 | debug("No dimms present on controller %u; " | |
557 | "skipping programming\n", i); | |
558 | continue; | |
559 | } | |
560 | ||
561 | fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i); | |
562 | } | |
563 | ||
a4c66509 YS |
564 | /* program LAWs */ |
565 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
566 | if (info.memctl_opts[i].memctl_interleaving) { | |
567 | switch (info.memctl_opts[i].memctl_interleaving_mode) { | |
568 | case FSL_DDR_CACHE_LINE_INTERLEAVING: | |
569 | case FSL_DDR_PAGE_INTERLEAVING: | |
570 | case FSL_DDR_BANK_INTERLEAVING: | |
571 | case FSL_DDR_SUPERBANK_INTERLEAVING: | |
572 | if (i == 0) { | |
573 | law_memctl = LAW_TRGT_IF_DDR_INTRLV; | |
574 | fsl_ddr_set_lawbar(&info.common_timing_params[i], | |
575 | law_memctl, i); | |
576 | } else if (i == 2) { | |
577 | law_memctl = LAW_TRGT_IF_DDR_INTLV_34; | |
578 | fsl_ddr_set_lawbar(&info.common_timing_params[i], | |
579 | law_memctl, i); | |
580 | } | |
581 | break; | |
582 | case FSL_DDR_3WAY_1KB_INTERLEAVING: | |
583 | case FSL_DDR_3WAY_4KB_INTERLEAVING: | |
584 | case FSL_DDR_3WAY_8KB_INTERLEAVING: | |
585 | law_memctl = LAW_TRGT_IF_DDR_INTLV_123; | |
586 | if (i == 0) { | |
a4c66509 YS |
587 | fsl_ddr_set_lawbar(&info.common_timing_params[i], |
588 | law_memctl, i); | |
589 | } | |
590 | break; | |
591 | case FSL_DDR_4WAY_1KB_INTERLEAVING: | |
592 | case FSL_DDR_4WAY_4KB_INTERLEAVING: | |
593 | case FSL_DDR_4WAY_8KB_INTERLEAVING: | |
594 | law_memctl = LAW_TRGT_IF_DDR_INTLV_1234; | |
595 | if (i == 0) | |
596 | fsl_ddr_set_lawbar(&info.common_timing_params[i], | |
597 | law_memctl, i); | |
598 | /* place holder for future 4-way interleaving */ | |
599 | break; | |
600 | default: | |
601 | break; | |
602 | } | |
603 | } else { | |
604 | switch (i) { | |
605 | case 0: | |
606 | law_memctl = LAW_TRGT_IF_DDR_1; | |
607 | break; | |
608 | case 1: | |
609 | law_memctl = LAW_TRGT_IF_DDR_2; | |
610 | break; | |
611 | case 2: | |
612 | law_memctl = LAW_TRGT_IF_DDR_3; | |
613 | break; | |
614 | case 3: | |
615 | law_memctl = LAW_TRGT_IF_DDR_4; | |
616 | break; | |
617 | default: | |
618 | break; | |
619 | } | |
58e5e9af | 620 | fsl_ddr_set_lawbar(&info.common_timing_params[i], |
a4c66509 | 621 | law_memctl, i); |
58e5e9af KG |
622 | } |
623 | } | |
624 | ||
a4c66509 | 625 | debug("total_memory by %s = %llu\n", __func__, total_memory); |
e7563aff KG |
626 | |
627 | #if !defined(CONFIG_PHYS_64BIT) | |
628 | /* Check for 4G or more. Bad. */ | |
629 | if (total_memory >= (1ull << 32)) { | |
630 | printf("Detected %lld MB of memory\n", total_memory >> 20); | |
7ea3871e BB |
631 | printf(" This U-Boot only supports < 4G of DDR\n"); |
632 | printf(" You could rebuild it with CONFIG_PHYS_64BIT\n"); | |
633 | printf(" "); /* re-align to match init_func_ram print */ | |
e7563aff KG |
634 | total_memory = CONFIG_MAX_MEM_MAPPED; |
635 | } | |
636 | #endif | |
58e5e9af KG |
637 | |
638 | return total_memory; | |
639 | } | |
fc0c2b6f HW |
640 | |
641 | /* | |
642 | * fsl_ddr_sdram_size() - This function only returns the size of the total | |
643 | * memory without setting ddr control registers. | |
644 | */ | |
645 | phys_size_t | |
646 | fsl_ddr_sdram_size(void) | |
647 | { | |
648 | fsl_ddr_info_t info; | |
649 | unsigned long long total_memory = 0; | |
650 | ||
651 | memset(&info, 0 , sizeof(fsl_ddr_info_t)); | |
652 | ||
653 | /* Compute it once normally. */ | |
654 | total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 1); | |
655 | ||
656 | return total_memory; | |
657 | } |