]>
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 | |
ef002275 | 189 | static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo, |
a4c66509 | 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 | ||
ef002275 YS |
357 | /* Use weak function to allow board file to override the address assignment */ |
358 | __attribute__((weak, alias("__step_assign_addresses"))) | |
359 | unsigned long long step_assign_addresses(fsl_ddr_info_t *pinfo, | |
360 | unsigned int dbw_cap_adj[]); | |
361 | ||
e7563aff | 362 | unsigned long long |
fc0c2b6f HW |
363 | fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step, |
364 | unsigned int size_only) | |
58e5e9af KG |
365 | { |
366 | unsigned int i, j; | |
e7563aff | 367 | unsigned long long total_mem = 0; |
58e5e9af KG |
368 | |
369 | fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg; | |
370 | common_timing_params_t *timing_params = pinfo->common_timing_params; | |
371 | ||
372 | /* data bus width capacity adjust shift amount */ | |
373 | unsigned int dbw_capacity_adjust[CONFIG_NUM_DDR_CONTROLLERS]; | |
374 | ||
375 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
376 | dbw_capacity_adjust[i] = 0; | |
377 | } | |
378 | ||
379 | debug("starting at step %u (%s)\n", | |
380 | start_step, step_to_string(start_step)); | |
381 | ||
382 | switch (start_step) { | |
383 | case STEP_GET_SPD: | |
1b3e3c4f | 384 | #if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM) |
58e5e9af KG |
385 | /* STEP 1: Gather all DIMM SPD data */ |
386 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
387 | fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i); | |
388 | } | |
389 | ||
390 | case STEP_COMPUTE_DIMM_PARMS: | |
391 | /* STEP 2: Compute DIMM parameters from SPD data */ | |
392 | ||
393 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
394 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { | |
395 | unsigned int retval; | |
396 | generic_spd_eeprom_t *spd = | |
397 | &(pinfo->spd_installed_dimms[i][j]); | |
398 | dimm_params_t *pdimm = | |
f12e4549 | 399 | &(pinfo->dimm_params[i][j]); |
58e5e9af KG |
400 | |
401 | retval = compute_dimm_parameters(spd, pdimm, i); | |
f2d264b6 | 402 | #ifdef CONFIG_SYS_DDR_RAW_TIMING |
62f739fe | 403 | if (!i && !j && retval) { |
a4c66509 YS |
404 | printf("SPD error on controller %d! " |
405 | "Trying fallback to raw timing " | |
406 | "calculation\n", i); | |
f2d264b6 YS |
407 | fsl_ddr_get_dimm_params(pdimm, i, j); |
408 | } | |
409 | #else | |
58e5e9af KG |
410 | if (retval == 2) { |
411 | printf("Error: compute_dimm_parameters" | |
412 | " non-zero returned FATAL value " | |
413 | "for memctl=%u dimm=%u\n", i, j); | |
414 | return 0; | |
415 | } | |
f2d264b6 | 416 | #endif |
58e5e9af KG |
417 | if (retval) { |
418 | debug("Warning: compute_dimm_parameters" | |
419 | " non-zero return value for memctl=%u " | |
420 | "dimm=%u\n", i, j); | |
421 | } | |
422 | } | |
423 | } | |
424 | ||
98de369b | 425 | #elif defined(CONFIG_SYS_DDR_RAW_TIMING) |
1b3e3c4f YS |
426 | case STEP_COMPUTE_DIMM_PARMS: |
427 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
428 | for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) { | |
429 | dimm_params_t *pdimm = | |
430 | &(pinfo->dimm_params[i][j]); | |
431 | fsl_ddr_get_dimm_params(pdimm, i, j); | |
432 | } | |
433 | } | |
434 | debug("Filling dimm parameters from board specific file\n"); | |
435 | #endif | |
58e5e9af KG |
436 | case STEP_COMPUTE_COMMON_PARMS: |
437 | /* | |
438 | * STEP 3: Compute a common set of timing parameters | |
439 | * suitable for all of the DIMMs on each memory controller | |
440 | */ | |
441 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
442 | debug("Computing lowest common DIMM" | |
443 | " parameters for memctl=%u\n", i); | |
444 | compute_lowest_common_dimm_parameters( | |
445 | pinfo->dimm_params[i], | |
446 | &timing_params[i], | |
447 | CONFIG_DIMM_SLOTS_PER_CTLR); | |
448 | } | |
449 | ||
450 | case STEP_GATHER_OPTS: | |
451 | /* STEP 4: Gather configuration requirements from user */ | |
452 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
453 | debug("Reloading memory controller " | |
454 | "configuration options for memctl=%u\n", i); | |
455 | /* | |
456 | * This "reloads" the memory controller options | |
457 | * to defaults. If the user "edits" an option, | |
458 | * next_step points to the step after this, | |
459 | * which is currently STEP_ASSIGN_ADDRESSES. | |
460 | */ | |
461 | populate_memctl_options( | |
462 | timing_params[i].all_DIMMs_registered, | |
dfb49108 HW |
463 | &pinfo->memctl_opts[i], |
464 | pinfo->dimm_params[i], i); | |
58e5e9af | 465 | } |
58e5e9af KG |
466 | case STEP_ASSIGN_ADDRESSES: |
467 | /* STEP 5: Assign addresses to chip selects */ | |
a4c66509 YS |
468 | check_interleaving_options(pinfo); |
469 | total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust); | |
58e5e9af KG |
470 | |
471 | case STEP_COMPUTE_REGS: | |
472 | /* STEP 6: compute controller register values */ | |
a4c66509 | 473 | debug("FSL Memory ctrl register computation\n"); |
58e5e9af KG |
474 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { |
475 | if (timing_params[i].ndimms_present == 0) { | |
476 | memset(&ddr_reg[i], 0, | |
477 | sizeof(fsl_ddr_cfg_regs_t)); | |
478 | continue; | |
479 | } | |
480 | ||
481 | compute_fsl_memctl_config_regs( | |
482 | &pinfo->memctl_opts[i], | |
483 | &ddr_reg[i], &timing_params[i], | |
484 | pinfo->dimm_params[i], | |
fc0c2b6f HW |
485 | dbw_capacity_adjust[i], |
486 | size_only); | |
58e5e9af KG |
487 | } |
488 | ||
489 | default: | |
490 | break; | |
491 | } | |
492 | ||
a4c66509 | 493 | { |
58e5e9af KG |
494 | /* |
495 | * Compute the amount of memory available just by | |
496 | * looking for the highest valid CSn_BNDS value. | |
497 | * This allows us to also experiment with using | |
498 | * only CS0 when using dual-rank DIMMs. | |
499 | */ | |
500 | unsigned int max_end = 0; | |
501 | ||
502 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
503 | for (j = 0; j < CONFIG_CHIP_SELECTS_PER_CTRL; j++) { | |
504 | fsl_ddr_cfg_regs_t *reg = &ddr_reg[i]; | |
505 | if (reg->cs[j].config & 0x80000000) { | |
506 | unsigned int end; | |
d8556db1 YS |
507 | /* |
508 | * 0xfffffff is a special value we put | |
509 | * for unused bnds | |
510 | */ | |
511 | if (reg->cs[j].bnds == 0xffffffff) | |
512 | continue; | |
513 | end = reg->cs[j].bnds & 0xffff; | |
58e5e9af KG |
514 | if (end > max_end) { |
515 | max_end = end; | |
516 | } | |
517 | } | |
518 | } | |
519 | } | |
520 | ||
58e5e9af KG |
521 | total_mem = 1 + (((unsigned long long)max_end << 24ULL) |
522 | | 0xFFFFFFULL); | |
523 | } | |
524 | ||
525 | return total_mem; | |
526 | } | |
527 | ||
528 | /* | |
529 | * fsl_ddr_sdram() -- this is the main function to be called by | |
530 | * initdram() in the board file. | |
531 | * | |
532 | * It returns amount of memory configured in bytes. | |
533 | */ | |
534 | phys_size_t fsl_ddr_sdram(void) | |
535 | { | |
536 | unsigned int i; | |
a4c66509 | 537 | unsigned int law_memctl = LAW_TRGT_IF_DDR_1; |
e7563aff | 538 | unsigned long long total_memory; |
58e5e9af KG |
539 | fsl_ddr_info_t info; |
540 | ||
541 | /* Reset info structure. */ | |
542 | memset(&info, 0, sizeof(fsl_ddr_info_t)); | |
543 | ||
544 | /* Compute it once normally. */ | |
6f5e1dc5 | 545 | #ifdef CONFIG_FSL_DDR_INTERACTIVE |
e8ba6c50 JY |
546 | if (tstc() && (getc() == 'd')) { /* we got a key press of 'd' */ |
547 | total_memory = fsl_ddr_interactive(&info, 0); | |
548 | } else if (fsl_ddr_interactive_env_var_exists()) { | |
549 | total_memory = fsl_ddr_interactive(&info, 1); | |
e750cfaa | 550 | } else |
6f5e1dc5 YS |
551 | #endif |
552 | total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0); | |
58e5e9af | 553 | |
f31cfd19 | 554 | /* setup 3-way interleaving before enabling DDRC */ |
0a7c5353 YS |
555 | if (info.memctl_opts[0].memctl_interleaving) { |
556 | switch (info.memctl_opts[0].memctl_interleaving_mode) { | |
557 | case FSL_DDR_3WAY_1KB_INTERLEAVING: | |
558 | case FSL_DDR_3WAY_4KB_INTERLEAVING: | |
559 | case FSL_DDR_3WAY_8KB_INTERLEAVING: | |
560 | fsl_ddr_set_intl3r( | |
561 | info.memctl_opts[0].memctl_interleaving_mode); | |
562 | break; | |
563 | default: | |
564 | break; | |
565 | } | |
f31cfd19 YS |
566 | } |
567 | ||
58e5e9af KG |
568 | /* Program configuration registers. */ |
569 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
570 | debug("Programming controller %u\n", i); | |
571 | if (info.common_timing_params[i].ndimms_present == 0) { | |
572 | debug("No dimms present on controller %u; " | |
573 | "skipping programming\n", i); | |
574 | continue; | |
575 | } | |
576 | ||
577 | fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i); | |
578 | } | |
579 | ||
a4c66509 YS |
580 | /* program LAWs */ |
581 | for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) { | |
582 | if (info.memctl_opts[i].memctl_interleaving) { | |
583 | switch (info.memctl_opts[i].memctl_interleaving_mode) { | |
584 | case FSL_DDR_CACHE_LINE_INTERLEAVING: | |
585 | case FSL_DDR_PAGE_INTERLEAVING: | |
586 | case FSL_DDR_BANK_INTERLEAVING: | |
587 | case FSL_DDR_SUPERBANK_INTERLEAVING: | |
588 | if (i == 0) { | |
589 | law_memctl = LAW_TRGT_IF_DDR_INTRLV; | |
590 | fsl_ddr_set_lawbar(&info.common_timing_params[i], | |
591 | law_memctl, i); | |
592 | } else if (i == 2) { | |
593 | law_memctl = LAW_TRGT_IF_DDR_INTLV_34; | |
594 | fsl_ddr_set_lawbar(&info.common_timing_params[i], | |
595 | law_memctl, i); | |
596 | } | |
597 | break; | |
598 | case FSL_DDR_3WAY_1KB_INTERLEAVING: | |
599 | case FSL_DDR_3WAY_4KB_INTERLEAVING: | |
600 | case FSL_DDR_3WAY_8KB_INTERLEAVING: | |
601 | law_memctl = LAW_TRGT_IF_DDR_INTLV_123; | |
602 | if (i == 0) { | |
a4c66509 YS |
603 | fsl_ddr_set_lawbar(&info.common_timing_params[i], |
604 | law_memctl, i); | |
605 | } | |
606 | break; | |
607 | case FSL_DDR_4WAY_1KB_INTERLEAVING: | |
608 | case FSL_DDR_4WAY_4KB_INTERLEAVING: | |
609 | case FSL_DDR_4WAY_8KB_INTERLEAVING: | |
610 | law_memctl = LAW_TRGT_IF_DDR_INTLV_1234; | |
611 | if (i == 0) | |
612 | fsl_ddr_set_lawbar(&info.common_timing_params[i], | |
613 | law_memctl, i); | |
614 | /* place holder for future 4-way interleaving */ | |
615 | break; | |
616 | default: | |
617 | break; | |
618 | } | |
619 | } else { | |
620 | switch (i) { | |
621 | case 0: | |
622 | law_memctl = LAW_TRGT_IF_DDR_1; | |
623 | break; | |
624 | case 1: | |
625 | law_memctl = LAW_TRGT_IF_DDR_2; | |
626 | break; | |
627 | case 2: | |
628 | law_memctl = LAW_TRGT_IF_DDR_3; | |
629 | break; | |
630 | case 3: | |
631 | law_memctl = LAW_TRGT_IF_DDR_4; | |
632 | break; | |
633 | default: | |
634 | break; | |
635 | } | |
58e5e9af | 636 | fsl_ddr_set_lawbar(&info.common_timing_params[i], |
a4c66509 | 637 | law_memctl, i); |
58e5e9af KG |
638 | } |
639 | } | |
640 | ||
a4c66509 | 641 | debug("total_memory by %s = %llu\n", __func__, total_memory); |
e7563aff KG |
642 | |
643 | #if !defined(CONFIG_PHYS_64BIT) | |
644 | /* Check for 4G or more. Bad. */ | |
645 | if (total_memory >= (1ull << 32)) { | |
646 | printf("Detected %lld MB of memory\n", total_memory >> 20); | |
7ea3871e BB |
647 | printf(" This U-Boot only supports < 4G of DDR\n"); |
648 | printf(" You could rebuild it with CONFIG_PHYS_64BIT\n"); | |
649 | printf(" "); /* re-align to match init_func_ram print */ | |
e7563aff KG |
650 | total_memory = CONFIG_MAX_MEM_MAPPED; |
651 | } | |
652 | #endif | |
58e5e9af KG |
653 | |
654 | return total_memory; | |
655 | } | |
fc0c2b6f HW |
656 | |
657 | /* | |
658 | * fsl_ddr_sdram_size() - This function only returns the size of the total | |
659 | * memory without setting ddr control registers. | |
660 | */ | |
661 | phys_size_t | |
662 | fsl_ddr_sdram_size(void) | |
663 | { | |
664 | fsl_ddr_info_t info; | |
665 | unsigned long long total_memory = 0; | |
666 | ||
667 | memset(&info, 0 , sizeof(fsl_ddr_info_t)); | |
668 | ||
669 | /* Compute it once normally. */ | |
670 | total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 1); | |
671 | ||
672 | return total_memory; | |
673 | } |