]>
Commit | Line | Data |
---|---|---|
d1712369 | 1 | /* |
3dbd5d7d | 2 | * Copyright 2009-2011 Freescale Semiconductor, Inc. |
d1712369 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 | #include <common.h> | |
10 | #include <i2c.h> | |
28a96671 YS |
11 | #include <hwconfig.h> |
12 | #include <asm/mmu.h> | |
d1712369 KG |
13 | #include <asm/fsl_ddr_sdram.h> |
14 | #include <asm/fsl_ddr_dimm_params.h> | |
28a96671 YS |
15 | #include <asm/fsl_law.h> |
16 | ||
17 | DECLARE_GLOBAL_DATA_PTR; | |
18 | ||
28a96671 YS |
19 | |
20 | /* | |
21 | * Fixed sdram init -- doesn't use serial presence detect. | |
22 | */ | |
23 | extern fixed_ddr_parm_t fixed_ddr_parm_0[]; | |
24 | #if (CONFIG_NUM_DDR_CONTROLLERS == 2) | |
25 | extern fixed_ddr_parm_t fixed_ddr_parm_1[]; | |
26 | #endif | |
27 | ||
28 | phys_size_t fixed_sdram(void) | |
29 | { | |
30 | int i; | |
28a96671 YS |
31 | char buf[32]; |
32 | fsl_ddr_cfg_regs_t ddr_cfg_regs; | |
33 | phys_size_t ddr_size; | |
34 | unsigned int lawbar1_target_id; | |
5cfbc458 KG |
35 | ulong ddr_freq, ddr_freq_mhz; |
36 | ||
37 | ddr_freq = get_ddr_freq(0); | |
38 | ddr_freq_mhz = ddr_freq / 1000000; | |
28a96671 | 39 | |
28a96671 | 40 | printf("Configuring DDR for %s MT/s data rate\n", |
5cfbc458 | 41 | strmhz(buf, ddr_freq)); |
28a96671 YS |
42 | |
43 | for (i = 0; fixed_ddr_parm_0[i].max_freq > 0; i++) { | |
5cfbc458 KG |
44 | if ((ddr_freq_mhz > fixed_ddr_parm_0[i].min_freq) && |
45 | (ddr_freq_mhz <= fixed_ddr_parm_0[i].max_freq)) { | |
28a96671 YS |
46 | memcpy(&ddr_cfg_regs, |
47 | fixed_ddr_parm_0[i].ddr_settings, | |
48 | sizeof(ddr_cfg_regs)); | |
49 | break; | |
50 | } | |
51 | } | |
52 | ||
53 | if (fixed_ddr_parm_0[i].max_freq == 0) | |
54 | panic("Unsupported DDR data rate %s MT/s data rate\n", | |
5cfbc458 | 55 | strmhz(buf, ddr_freq)); |
28a96671 YS |
56 | |
57 | ddr_size = (phys_size_t) CONFIG_SYS_SDRAM_SIZE * 1024 * 1024; | |
6b06d7dc | 58 | ddr_cfg_regs.ddr_cdr1 = DDR_CDR1_DHC_EN; |
28a96671 YS |
59 | fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0); |
60 | ||
61 | #if (CONFIG_NUM_DDR_CONTROLLERS == 2) | |
62 | memcpy(&ddr_cfg_regs, | |
63 | fixed_ddr_parm_1[i].ddr_settings, | |
64 | sizeof(ddr_cfg_regs)); | |
6b06d7dc | 65 | ddr_cfg_regs.ddr_cdr1 = DDR_CDR1_DHC_EN; |
28a96671 YS |
66 | fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 1); |
67 | #endif | |
68 | ||
69 | /* | |
70 | * setup laws for DDR. If not interleaving, presuming half memory on | |
71 | * DDR1 and the other half on DDR2 | |
72 | */ | |
73 | if (fixed_ddr_parm_0[i].ddr_settings->cs[0].config & 0x20000000) { | |
74 | if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE, | |
75 | ddr_size, | |
76 | LAW_TRGT_IF_DDR_INTRLV) < 0) { | |
77 | printf("ERROR setting Local Access Windows for DDR\n"); | |
78 | return 0; | |
79 | } | |
80 | } else { | |
81 | #if (CONFIG_NUM_DDR_CONTROLLERS == 2) | |
82 | /* We require both controllers have identical DIMMs */ | |
83 | lawbar1_target_id = LAW_TRGT_IF_DDR_1; | |
84 | if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE, | |
85 | ddr_size / 2, | |
86 | lawbar1_target_id) < 0) { | |
87 | printf("ERROR setting Local Access Windows for DDR\n"); | |
88 | return 0; | |
89 | } | |
90 | lawbar1_target_id = LAW_TRGT_IF_DDR_2; | |
91 | if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE + ddr_size / 2, | |
92 | ddr_size / 2, | |
93 | lawbar1_target_id) < 0) { | |
94 | printf("ERROR setting Local Access Windows for DDR\n"); | |
95 | return 0; | |
96 | } | |
97 | #else | |
98 | lawbar1_target_id = LAW_TRGT_IF_DDR_1; | |
99 | if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE, | |
100 | ddr_size, | |
101 | lawbar1_target_id) < 0) { | |
102 | printf("ERROR setting Local Access Windows for DDR\n"); | |
103 | return 0; | |
104 | } | |
105 | #endif | |
106 | } | |
107 | return ddr_size; | |
108 | } | |
d1712369 | 109 | |
d1712369 KG |
110 | typedef struct { |
111 | u32 datarate_mhz_low; | |
112 | u32 datarate_mhz_high; | |
113 | u32 n_ranks; | |
114 | u32 clk_adjust; | |
6b06d7dc | 115 | u32 wrlvl_start; |
d1712369 KG |
116 | u32 cpo; |
117 | u32 write_data_delay; | |
118 | u32 force_2T; | |
119 | } board_specific_parameters_t; | |
120 | ||
9ec8dec5 | 121 | const board_specific_parameters_t board_specific_parameters_udimm[][30] = { |
d1712369 | 122 | { |
6b06d7dc YS |
123 | /* |
124 | * memory controller 0 | |
125 | * lo| hi| num| clk| wrlvl | cpo |wrdata|2T | |
9ec8dec5 | 126 | * mhz| mhz|ranks|adjst| start | |delay | |
6b06d7dc | 127 | */ |
d89a976c YS |
128 | { 0, 850, 4, 4, 6, 0xff, 2, 0}, |
129 | {851, 950, 4, 5, 7, 0xff, 2, 0}, | |
59a4089f YS |
130 | {951, 1050, 4, 5, 8, 0xff, 2, 0}, |
131 | {1051, 1250, 4, 5, 10, 0xff, 2, 0}, | |
132 | {1251, 1350, 4, 5, 11, 0xff, 2, 0}, | |
9ec8dec5 | 133 | {1351, 1666, 4, 5, 12, 0xff, 2, 0}, |
59a4089f YS |
134 | { 0, 850, 2, 5, 6, 0xff, 2, 0}, |
135 | {851, 950, 2, 5, 7, 0xff, 2, 0}, | |
136 | {951, 1050, 2, 5, 7, 0xff, 2, 0}, | |
137 | {1051, 1250, 2, 4, 6, 0xff, 2, 0}, | |
6b06d7dc | 138 | {1251, 1350, 2, 5, 7, 0xff, 2, 0}, |
9ec8dec5 YS |
139 | {1351, 1666, 2, 5, 8, 0xff, 2, 0}, |
140 | { 0, 850, 1, 4, 5, 0xff, 2, 0}, | |
141 | {851, 950, 1, 4, 7, 0xff, 2, 0}, | |
142 | {951, 1050, 1, 4, 8, 0xff, 2, 0}, | |
143 | {1051, 1250, 1, 4, 8, 0xff, 2, 0}, | |
144 | {1251, 1350, 1, 4, 8, 0xff, 2, 0}, | |
145 | {1351, 1666, 1, 4, 8, 0xff, 2, 0}, | |
d1712369 KG |
146 | }, |
147 | ||
148 | { | |
6b06d7dc YS |
149 | /* |
150 | * memory controller 1 | |
151 | * lo| hi| num| clk| wrlvl | cpo |wrdata|2T | |
9ec8dec5 | 152 | * mhz| mhz|ranks|adjst| start | |delay | |
6b06d7dc | 153 | */ |
d89a976c YS |
154 | { 0, 850, 4, 4, 6, 0xff, 2, 0}, |
155 | {851, 950, 4, 5, 7, 0xff, 2, 0}, | |
59a4089f YS |
156 | {951, 1050, 4, 5, 8, 0xff, 2, 0}, |
157 | {1051, 1250, 4, 5, 10, 0xff, 2, 0}, | |
158 | {1251, 1350, 4, 5, 11, 0xff, 2, 0}, | |
9ec8dec5 | 159 | {1351, 1666, 4, 5, 12, 0xff, 2, 0}, |
59a4089f YS |
160 | { 0, 850, 2, 5, 6, 0xff, 2, 0}, |
161 | {851, 950, 2, 5, 7, 0xff, 2, 0}, | |
162 | {951, 1050, 2, 5, 7, 0xff, 2, 0}, | |
163 | {1051, 1250, 2, 4, 6, 0xff, 2, 0}, | |
6b06d7dc | 164 | {1251, 1350, 2, 5, 7, 0xff, 2, 0}, |
9ec8dec5 YS |
165 | {1351, 1666, 2, 5, 8, 0xff, 2, 0}, |
166 | { 0, 850, 1, 4, 5, 0xff, 2, 0}, | |
167 | {851, 950, 1, 4, 7, 0xff, 2, 0}, | |
168 | {951, 1050, 1, 4, 8, 0xff, 2, 0}, | |
169 | {1051, 1250, 1, 4, 8, 0xff, 2, 0}, | |
170 | {1251, 1350, 1, 4, 8, 0xff, 2, 0}, | |
171 | {1351, 1666, 1, 4, 8, 0xff, 2, 0}, | |
172 | } | |
173 | }; | |
174 | ||
175 | const board_specific_parameters_t board_specific_parameters_rdimm[][30] = { | |
176 | { | |
177 | /* | |
178 | * memory controller 0 | |
179 | * lo| hi| num| clk| wrlvl | cpo |wrdata|2T | |
180 | * mhz| mhz|ranks|adjst| start | |delay | | |
181 | */ | |
182 | { 0, 850, 4, 4, 6, 0xff, 2, 0}, | |
183 | {851, 950, 4, 5, 7, 0xff, 2, 0}, | |
184 | {951, 1050, 4, 5, 8, 0xff, 2, 0}, | |
185 | {1051, 1250, 4, 5, 10, 0xff, 2, 0}, | |
186 | {1251, 1350, 4, 5, 11, 0xff, 2, 0}, | |
187 | {1351, 1666, 4, 5, 12, 0xff, 2, 0}, | |
188 | { 0, 850, 2, 4, 6, 0xff, 2, 0}, | |
189 | {851, 950, 2, 4, 7, 0xff, 2, 0}, | |
190 | {951, 1050, 2, 4, 7, 0xff, 2, 0}, | |
191 | {1051, 1250, 2, 4, 8, 0xff, 2, 0}, | |
192 | {1251, 1350, 2, 4, 8, 0xff, 2, 0}, | |
193 | {1351, 1666, 2, 4, 8, 0xff, 2, 0}, | |
194 | { 0, 850, 1, 4, 5, 0xff, 2, 0}, | |
195 | {851, 950, 1, 4, 7, 0xff, 2, 0}, | |
196 | {951, 1050, 1, 4, 8, 0xff, 2, 0}, | |
197 | {1051, 1250, 1, 4, 8, 0xff, 2, 0}, | |
198 | {1251, 1350, 1, 4, 8, 0xff, 2, 0}, | |
199 | {1351, 1666, 1, 4, 8, 0xff, 2, 0}, | |
200 | }, | |
201 | ||
202 | { | |
203 | /* | |
204 | * memory controller 1 | |
205 | * lo| hi| num| clk| wrlvl | cpo |wrdata|2T | |
206 | * mhz| mhz|ranks|adjst| start | |delay | | |
207 | */ | |
208 | { 0, 850, 4, 4, 6, 0xff, 2, 0}, | |
209 | {851, 950, 4, 5, 7, 0xff, 2, 0}, | |
210 | {951, 1050, 4, 5, 8, 0xff, 2, 0}, | |
211 | {1051, 1250, 4, 5, 10, 0xff, 2, 0}, | |
212 | {1251, 1350, 4, 5, 11, 0xff, 2, 0}, | |
213 | {1351, 1666, 4, 5, 12, 0xff, 2, 0}, | |
214 | { 0, 850, 2, 4, 6, 0xff, 2, 0}, | |
215 | {851, 950, 2, 4, 7, 0xff, 2, 0}, | |
216 | {951, 1050, 2, 4, 7, 0xff, 2, 0}, | |
217 | {1051, 1250, 2, 4, 8, 0xff, 2, 0}, | |
218 | {1251, 1350, 2, 4, 8, 0xff, 2, 0}, | |
219 | {1351, 1666, 2, 4, 8, 0xff, 2, 0}, | |
220 | { 0, 850, 1, 4, 5, 0xff, 2, 0}, | |
221 | {851, 950, 1, 4, 7, 0xff, 2, 0}, | |
222 | {951, 1050, 1, 4, 8, 0xff, 2, 0}, | |
223 | {1051, 1250, 1, 4, 8, 0xff, 2, 0}, | |
224 | {1251, 1350, 1, 4, 8, 0xff, 2, 0}, | |
225 | {1351, 1666, 1, 4, 8, 0xff, 2, 0}, | |
d1712369 KG |
226 | } |
227 | }; | |
228 | ||
229 | void fsl_ddr_board_options(memctl_options_t *popts, | |
230 | dimm_params_t *pdimm, | |
231 | unsigned int ctrl_num) | |
232 | { | |
9ec8dec5 YS |
233 | const board_specific_parameters_t *pbsp; |
234 | u32 num_params; | |
d1712369 KG |
235 | u32 i; |
236 | ulong ddr_freq; | |
237 | ||
9ec8dec5 YS |
238 | if (popts->registered_dimm_en) { |
239 | pbsp = &(board_specific_parameters_rdimm[ctrl_num][0]); | |
240 | num_params = sizeof(board_specific_parameters_rdimm[ctrl_num]) / | |
241 | sizeof(board_specific_parameters_rdimm[0][0]); | |
242 | } else { | |
243 | pbsp = &(board_specific_parameters_udimm[ctrl_num][0]); | |
244 | num_params = sizeof(board_specific_parameters_udimm[ctrl_num]) / | |
245 | sizeof(board_specific_parameters_udimm[0][0]); | |
246 | } | |
d1712369 KG |
247 | /* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr |
248 | * freqency and n_banks specified in board_specific_parameters table. | |
249 | */ | |
250 | ddr_freq = get_ddr_freq(0) / 1000000; | |
251 | for (i = 0; i < num_params; i++) { | |
252 | if (ddr_freq >= pbsp->datarate_mhz_low && | |
6b06d7dc YS |
253 | ddr_freq <= pbsp->datarate_mhz_high && |
254 | pdimm[0].n_ranks == pbsp->n_ranks) { | |
255 | popts->cpo_override = pbsp->cpo; | |
256 | popts->write_data_delay = pbsp->write_data_delay; | |
257 | popts->clk_adjust = pbsp->clk_adjust; | |
258 | popts->wrlvl_start = pbsp->wrlvl_start; | |
d1712369 | 259 | popts->twoT_en = pbsp->force_2T; |
939e5bf9 | 260 | break; |
d1712369 KG |
261 | } |
262 | pbsp++; | |
263 | } | |
264 | ||
939e5bf9 YS |
265 | if (i == num_params) { |
266 | printf("Warning: board specific timing not found " | |
267 | "for data rate %lu MT/s!\n", ddr_freq); | |
268 | } | |
269 | ||
d1712369 KG |
270 | /* |
271 | * Factors to consider for half-strength driver enable: | |
272 | * - number of DIMMs installed | |
273 | */ | |
274 | popts->half_strength_driver_enable = 0; | |
275 | /* | |
276 | * Write leveling override | |
277 | */ | |
278 | popts->wrlvl_override = 1; | |
6b06d7dc YS |
279 | popts->wrlvl_sample = 0xf; |
280 | ||
d1712369 KG |
281 | /* |
282 | * Rtt and Rtt_WR override | |
283 | */ | |
6b06d7dc | 284 | popts->rtt_override = 0; |
d1712369 KG |
285 | |
286 | /* Enable ZQ calibration */ | |
287 | popts->zq_en = 1; | |
6b06d7dc YS |
288 | |
289 | /* DHC_EN =1, ODT = 60 Ohm */ | |
290 | popts->ddr_cdr1 = DDR_CDR1_DHC_EN; | |
d1712369 | 291 | } |
28a96671 YS |
292 | |
293 | phys_size_t initdram(int board_type) | |
294 | { | |
295 | phys_size_t dram_size; | |
28a96671 YS |
296 | |
297 | puts("Initializing...."); | |
298 | ||
3dbd5d7d | 299 | if (fsl_use_spd()) { |
28a96671 YS |
300 | puts("using SPD\n"); |
301 | dram_size = fsl_ddr_sdram(); | |
302 | } else { | |
303 | puts("using fixed parameters\n"); | |
304 | dram_size = fixed_sdram(); | |
305 | } | |
306 | ||
307 | dram_size = setup_ddr_tlbs(dram_size / 0x100000); | |
308 | dram_size *= 0x100000; | |
309 | ||
21cd5815 | 310 | debug(" DDR: "); |
28a96671 YS |
311 | return dram_size; |
312 | } |