]>
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 KG |
109 | |
110 | static void get_spd(ddr3_spd_eeprom_t *spd, unsigned char i2c_address) | |
111 | { | |
112 | int ret; | |
113 | ||
114 | ret = i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr3_spd_eeprom_t)); | |
115 | if (ret) { | |
116 | debug("DDR: failed to read SPD from address %u\n", i2c_address); | |
117 | memset(spd, 0, sizeof(ddr3_spd_eeprom_t)); | |
118 | } | |
119 | } | |
120 | ||
d1712369 KG |
121 | void fsl_ddr_get_spd(ddr3_spd_eeprom_t *ctrl_dimms_spd, |
122 | unsigned int ctrl_num) | |
123 | { | |
124 | unsigned int i; | |
125 | unsigned int i2c_address = 0; | |
126 | ||
127 | for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { | |
128 | if (ctrl_num == 0 && i == 0) | |
129 | i2c_address = SPD_EEPROM_ADDRESS1; | |
130 | else if (ctrl_num == 1 && i == 0) | |
131 | i2c_address = SPD_EEPROM_ADDRESS2; | |
132 | ||
133 | get_spd(&(ctrl_dimms_spd[i]), i2c_address); | |
134 | } | |
135 | } | |
136 | ||
137 | typedef struct { | |
138 | u32 datarate_mhz_low; | |
139 | u32 datarate_mhz_high; | |
140 | u32 n_ranks; | |
141 | u32 clk_adjust; | |
6b06d7dc | 142 | u32 wrlvl_start; |
d1712369 KG |
143 | u32 cpo; |
144 | u32 write_data_delay; | |
145 | u32 force_2T; | |
146 | } board_specific_parameters_t; | |
147 | ||
148 | /* ranges for parameters: | |
149 | * wr_data_delay = 0-6 | |
150 | * clk adjust = 0-8 | |
151 | * cpo 2-0x1E (30) | |
152 | */ | |
153 | ||
154 | ||
155 | /* XXX: these values need to be checked for all interleaving modes. */ | |
156 | /* XXX: No reliable dual-rank 800 MHz setting has been found. It may | |
157 | * seem reliable, but errors will appear when memory intensive | |
158 | * program is run. */ | |
159 | /* XXX: Single rank at 800 MHz is OK. */ | |
90870d98 | 160 | const board_specific_parameters_t board_specific_parameters[][30] = { |
d1712369 | 161 | { |
6b06d7dc YS |
162 | /* |
163 | * memory controller 0 | |
164 | * lo| hi| num| clk| wrlvl | cpo |wrdata|2T | |
165 | * mhz| mhz|ranks|adjst| start | delay| | |
166 | */ | |
d89a976c YS |
167 | { 0, 850, 4, 4, 6, 0xff, 2, 0}, |
168 | {851, 950, 4, 5, 7, 0xff, 2, 0}, | |
59a4089f YS |
169 | {951, 1050, 4, 5, 8, 0xff, 2, 0}, |
170 | {1051, 1250, 4, 5, 10, 0xff, 2, 0}, | |
171 | {1251, 1350, 4, 5, 11, 0xff, 2, 0}, | |
172 | { 0, 850, 2, 5, 6, 0xff, 2, 0}, | |
173 | {851, 950, 2, 5, 7, 0xff, 2, 0}, | |
174 | {951, 1050, 2, 5, 7, 0xff, 2, 0}, | |
175 | {1051, 1250, 2, 4, 6, 0xff, 2, 0}, | |
6b06d7dc | 176 | {1251, 1350, 2, 5, 7, 0xff, 2, 0}, |
d1712369 KG |
177 | }, |
178 | ||
179 | { | |
6b06d7dc YS |
180 | /* |
181 | * memory controller 1 | |
182 | * lo| hi| num| clk| wrlvl | cpo |wrdata|2T | |
183 | * mhz| mhz|ranks|adjst| start | delay| | |
184 | */ | |
d89a976c YS |
185 | { 0, 850, 4, 4, 6, 0xff, 2, 0}, |
186 | {851, 950, 4, 5, 7, 0xff, 2, 0}, | |
59a4089f YS |
187 | {951, 1050, 4, 5, 8, 0xff, 2, 0}, |
188 | {1051, 1250, 4, 5, 10, 0xff, 2, 0}, | |
189 | {1251, 1350, 4, 5, 11, 0xff, 2, 0}, | |
190 | { 0, 850, 2, 5, 6, 0xff, 2, 0}, | |
191 | {851, 950, 2, 5, 7, 0xff, 2, 0}, | |
192 | {951, 1050, 2, 5, 7, 0xff, 2, 0}, | |
193 | {1051, 1250, 2, 4, 6, 0xff, 2, 0}, | |
6b06d7dc | 194 | {1251, 1350, 2, 5, 7, 0xff, 2, 0}, |
d1712369 KG |
195 | } |
196 | }; | |
197 | ||
198 | void fsl_ddr_board_options(memctl_options_t *popts, | |
199 | dimm_params_t *pdimm, | |
200 | unsigned int ctrl_num) | |
201 | { | |
202 | const board_specific_parameters_t *pbsp = | |
203 | &(board_specific_parameters[ctrl_num][0]); | |
204 | u32 num_params = sizeof(board_specific_parameters[ctrl_num]) / | |
205 | sizeof(board_specific_parameters[0][0]); | |
206 | u32 i; | |
207 | ulong ddr_freq; | |
208 | ||
d1712369 KG |
209 | /* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr |
210 | * freqency and n_banks specified in board_specific_parameters table. | |
211 | */ | |
212 | ddr_freq = get_ddr_freq(0) / 1000000; | |
213 | for (i = 0; i < num_params; i++) { | |
214 | if (ddr_freq >= pbsp->datarate_mhz_low && | |
6b06d7dc YS |
215 | ddr_freq <= pbsp->datarate_mhz_high && |
216 | pdimm[0].n_ranks == pbsp->n_ranks) { | |
217 | popts->cpo_override = pbsp->cpo; | |
218 | popts->write_data_delay = pbsp->write_data_delay; | |
219 | popts->clk_adjust = pbsp->clk_adjust; | |
220 | popts->wrlvl_start = pbsp->wrlvl_start; | |
d1712369 KG |
221 | popts->twoT_en = pbsp->force_2T; |
222 | } | |
223 | pbsp++; | |
224 | } | |
225 | ||
226 | /* | |
227 | * Factors to consider for half-strength driver enable: | |
228 | * - number of DIMMs installed | |
229 | */ | |
230 | popts->half_strength_driver_enable = 0; | |
231 | /* | |
232 | * Write leveling override | |
233 | */ | |
234 | popts->wrlvl_override = 1; | |
6b06d7dc YS |
235 | popts->wrlvl_sample = 0xf; |
236 | ||
d1712369 KG |
237 | /* |
238 | * Rtt and Rtt_WR override | |
239 | */ | |
6b06d7dc | 240 | popts->rtt_override = 0; |
d1712369 KG |
241 | |
242 | /* Enable ZQ calibration */ | |
243 | popts->zq_en = 1; | |
6b06d7dc YS |
244 | |
245 | /* DHC_EN =1, ODT = 60 Ohm */ | |
246 | popts->ddr_cdr1 = DDR_CDR1_DHC_EN; | |
247 | ||
248 | /* override SPD values. rcw_2 should vary at differnt speed */ | |
249 | if (pdimm[0].n_ranks == 4) { | |
250 | popts->rcw_override = 1; | |
251 | popts->rcw_1 = 0x000a5a00; | |
252 | if (ddr_freq <= 800) | |
253 | popts->rcw_2 = 0x00000000; | |
254 | else if (ddr_freq <= 1066) | |
255 | popts->rcw_2 = 0x00100000; | |
256 | else if (ddr_freq <= 1333) | |
257 | popts->rcw_2 = 0x00200000; | |
258 | else | |
259 | popts->rcw_2 = 0x00300000; | |
260 | } | |
d1712369 | 261 | } |
28a96671 YS |
262 | |
263 | phys_size_t initdram(int board_type) | |
264 | { | |
265 | phys_size_t dram_size; | |
28a96671 YS |
266 | |
267 | puts("Initializing...."); | |
268 | ||
3dbd5d7d | 269 | if (fsl_use_spd()) { |
28a96671 YS |
270 | puts("using SPD\n"); |
271 | dram_size = fsl_ddr_sdram(); | |
272 | } else { | |
273 | puts("using fixed parameters\n"); | |
274 | dram_size = fixed_sdram(); | |
275 | } | |
276 | ||
277 | dram_size = setup_ddr_tlbs(dram_size / 0x100000); | |
278 | dram_size *= 0x100000; | |
279 | ||
280 | puts(" DDR: "); | |
281 | return dram_size; | |
282 | } |