]>
Commit | Line | Data |
---|---|---|
58e5e9af | 1 | /* |
ec145e87 | 2 | * Copyright 2008-2010 Freescale Semiconductor, Inc. |
58e5e9af | 3 | * |
ec145e87 DL |
4 | * 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. | |
58e5e9af KG |
8 | */ |
9 | ||
10 | /* | |
11 | * Generic driver for Freescale DDR/DDR2/DDR3 memory controller. | |
12 | * Based on code from spd_sdram.c | |
13 | * Author: James Yang [at freescale.com] | |
14 | */ | |
15 | ||
16 | #include <common.h> | |
17 | #include <asm/fsl_ddr_sdram.h> | |
18 | ||
19 | #include "ddr.h" | |
20 | ||
21 | extern unsigned int picos_to_mclk(unsigned int picos); | |
22 | /* | |
23 | * Determine Rtt value. | |
24 | * | |
25 | * This should likely be either board or controller specific. | |
26 | * | |
c360ceac | 27 | * Rtt(nominal) - DDR2: |
58e5e9af KG |
28 | * 0 = Rtt disabled |
29 | * 1 = 75 ohm | |
30 | * 2 = 150 ohm | |
31 | * 3 = 50 ohm | |
c360ceac DL |
32 | * Rtt(nominal) - DDR3: |
33 | * 0 = Rtt disabled | |
34 | * 1 = 60 ohm | |
35 | * 2 = 120 ohm | |
36 | * 3 = 40 ohm | |
37 | * 4 = 20 ohm | |
38 | * 5 = 30 ohm | |
58e5e9af KG |
39 | * |
40 | * FIXME: Apparently 8641 needs a value of 2 | |
41 | * FIXME: Old code seys if 667 MHz or higher, use 3 on 8572 | |
42 | * | |
43 | * FIXME: There was some effort down this line earlier: | |
44 | * | |
45 | * unsigned int i; | |
46 | * for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL/2; i++) { | |
47 | * if (popts->dimmslot[i].num_valid_cs | |
48 | * && (popts->cs_local_opts[2*i].odt_rd_cfg | |
49 | * || popts->cs_local_opts[2*i].odt_wr_cfg)) { | |
50 | * rtt = 2; | |
51 | * break; | |
52 | * } | |
53 | * } | |
54 | */ | |
55 | static inline int fsl_ddr_get_rtt(void) | |
56 | { | |
57 | int rtt; | |
58 | ||
59 | #if defined(CONFIG_FSL_DDR1) | |
60 | rtt = 0; | |
61 | #elif defined(CONFIG_FSL_DDR2) | |
62 | rtt = 3; | |
63 | #else | |
c360ceac | 64 | rtt = 0; |
58e5e9af KG |
65 | #endif |
66 | ||
67 | return rtt; | |
68 | } | |
69 | ||
c360ceac DL |
70 | /* |
71 | * compute the CAS write latency according to DDR3 spec | |
72 | * CWL = 5 if tCK >= 2.5ns | |
73 | * 6 if 2.5ns > tCK >= 1.875ns | |
74 | * 7 if 1.875ns > tCK >= 1.5ns | |
75 | * 8 if 1.5ns > tCK >= 1.25ns | |
76 | */ | |
77 | static inline unsigned int compute_cas_write_latency(void) | |
78 | { | |
79 | unsigned int cwl; | |
80 | const unsigned int mclk_ps = get_memory_clk_period_ps(); | |
81 | ||
82 | if (mclk_ps >= 2500) | |
83 | cwl = 5; | |
84 | else if (mclk_ps >= 1875) | |
85 | cwl = 6; | |
86 | else if (mclk_ps >= 1500) | |
87 | cwl = 7; | |
88 | else if (mclk_ps >= 1250) | |
89 | cwl = 8; | |
90 | else | |
91 | cwl = 8; | |
92 | return cwl; | |
93 | } | |
94 | ||
58e5e9af KG |
95 | /* Chip Select Configuration (CSn_CONFIG) */ |
96 | static void set_csn_config(int i, fsl_ddr_cfg_regs_t *ddr, | |
97 | const memctl_options_t *popts, | |
98 | const dimm_params_t *dimm_params) | |
99 | { | |
100 | unsigned int cs_n_en = 0; /* Chip Select enable */ | |
101 | unsigned int intlv_en = 0; /* Memory controller interleave enable */ | |
102 | unsigned int intlv_ctl = 0; /* Interleaving control */ | |
103 | unsigned int ap_n_en = 0; /* Chip select n auto-precharge enable */ | |
104 | unsigned int odt_rd_cfg = 0; /* ODT for reads configuration */ | |
105 | unsigned int odt_wr_cfg = 0; /* ODT for writes configuration */ | |
106 | unsigned int ba_bits_cs_n = 0; /* Num of bank bits for SDRAM on CSn */ | |
107 | unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */ | |
108 | unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */ | |
109 | ||
110 | /* Compute CS_CONFIG only for existing ranks of each DIMM. */ | |
111 | if ((((i&1) == 0) | |
112 | && (dimm_params[i/2].n_ranks == 1)) | |
113 | || (dimm_params[i/2].n_ranks == 2)) { | |
114 | unsigned int n_banks_per_sdram_device; | |
115 | cs_n_en = 1; | |
116 | if (i == 0) { | |
117 | /* These fields only available in CS0_CONFIG */ | |
118 | intlv_en = popts->memctl_interleaving; | |
119 | intlv_ctl = popts->memctl_interleaving_mode; | |
120 | } | |
121 | ap_n_en = popts->cs_local_opts[i].auto_precharge; | |
122 | odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg; | |
123 | odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg; | |
124 | n_banks_per_sdram_device | |
125 | = dimm_params[i/2].n_banks_per_sdram_device; | |
126 | ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2; | |
127 | row_bits_cs_n = dimm_params[i/2].n_row_addr - 12; | |
128 | col_bits_cs_n = dimm_params[i/2].n_col_addr - 8; | |
129 | } | |
130 | ||
58e5e9af KG |
131 | ddr->cs[i].config = (0 |
132 | | ((cs_n_en & 0x1) << 31) | |
133 | | ((intlv_en & 0x3) << 29) | |
dbbbb3ab | 134 | | ((intlv_ctl & 0xf) << 24) |
58e5e9af KG |
135 | | ((ap_n_en & 0x1) << 23) |
136 | ||
137 | /* XXX: some implementation only have 1 bit starting at left */ | |
138 | | ((odt_rd_cfg & 0x7) << 20) | |
139 | ||
140 | /* XXX: Some implementation only have 1 bit starting at left */ | |
141 | | ((odt_wr_cfg & 0x7) << 16) | |
142 | ||
143 | | ((ba_bits_cs_n & 0x3) << 14) | |
144 | | ((row_bits_cs_n & 0x7) << 8) | |
145 | | ((col_bits_cs_n & 0x7) << 0) | |
146 | ); | |
1f293b41 | 147 | debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config); |
58e5e9af KG |
148 | } |
149 | ||
150 | /* Chip Select Configuration 2 (CSn_CONFIG_2) */ | |
151 | /* FIXME: 8572 */ | |
152 | static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr) | |
153 | { | |
154 | unsigned int pasr_cfg = 0; /* Partial array self refresh config */ | |
155 | ||
156 | ddr->cs[i].config_2 = ((pasr_cfg & 7) << 24); | |
1f293b41 | 157 | debug("FSLDDR: cs[%d]_config_2 = 0x%08x\n", i, ddr->cs[i].config_2); |
58e5e9af KG |
158 | } |
159 | ||
160 | /* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */ | |
161 | ||
c360ceac | 162 | #if !defined(CONFIG_FSL_DDR1) |
58e5e9af KG |
163 | /* |
164 | * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0) | |
165 | * | |
166 | * Avoid writing for DDR I. The new PQ38 DDR controller | |
167 | * dreams up non-zero default values to be backwards compatible. | |
168 | */ | |
169 | static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr) | |
170 | { | |
171 | unsigned char trwt_mclk = 0; /* Read-to-write turnaround */ | |
172 | unsigned char twrt_mclk = 0; /* Write-to-read turnaround */ | |
173 | /* 7.5 ns on -3E; 0 means WL - CL + BL/2 + 1 */ | |
174 | unsigned char trrt_mclk = 0; /* Read-to-read turnaround */ | |
175 | unsigned char twwt_mclk = 0; /* Write-to-write turnaround */ | |
176 | ||
177 | /* Active powerdown exit timing (tXARD and tXARDS). */ | |
178 | unsigned char act_pd_exit_mclk; | |
179 | /* Precharge powerdown exit timing (tXP). */ | |
180 | unsigned char pre_pd_exit_mclk; | |
181 | /* Precharge powerdown exit timing (tAXPD). */ | |
182 | unsigned char taxpd_mclk; | |
183 | /* Mode register set cycle time (tMRD). */ | |
184 | unsigned char tmrd_mclk; | |
185 | ||
c360ceac DL |
186 | #if defined(CONFIG_FSL_DDR3) |
187 | /* | |
188 | * (tXARD and tXARDS). Empirical? | |
189 | * The DDR3 spec has not tXARD, | |
190 | * we use the tXP instead of it. | |
191 | * tXP=max(3nCK, 7.5ns) for DDR3. | |
c360ceac DL |
192 | * spec has not the tAXPD, we use |
193 | * tAXPD=8, need design to confirm. | |
194 | */ | |
0a71c92c DL |
195 | int tXP = max((get_memory_clk_period_ps() * 3), 7500); /* unit=ps */ |
196 | act_pd_exit_mclk = picos_to_mclk(tXP); | |
197 | /* Mode register MR0[A12] is '1' - fast exit */ | |
198 | pre_pd_exit_mclk = act_pd_exit_mclk; | |
58e5e9af | 199 | taxpd_mclk = 8; |
c360ceac DL |
200 | tmrd_mclk = 4; |
201 | #else /* CONFIG_FSL_DDR2 */ | |
202 | /* | |
203 | * (tXARD and tXARDS). Empirical? | |
204 | * tXARD = 2 for DDR2 | |
205 | * tXP=2 | |
206 | * tAXPD=8 | |
207 | */ | |
208 | act_pd_exit_mclk = 2; | |
209 | pre_pd_exit_mclk = 2; | |
210 | taxpd_mclk = 8; | |
58e5e9af | 211 | tmrd_mclk = 2; |
c360ceac | 212 | #endif |
58e5e9af KG |
213 | |
214 | ddr->timing_cfg_0 = (0 | |
215 | | ((trwt_mclk & 0x3) << 30) /* RWT */ | |
216 | | ((twrt_mclk & 0x3) << 28) /* WRT */ | |
217 | | ((trrt_mclk & 0x3) << 26) /* RRT */ | |
218 | | ((twwt_mclk & 0x3) << 24) /* WWT */ | |
219 | | ((act_pd_exit_mclk & 0x7) << 20) /* ACT_PD_EXIT */ | |
22ff3d01 | 220 | | ((pre_pd_exit_mclk & 0xF) << 16) /* PRE_PD_EXIT */ |
58e5e9af KG |
221 | | ((taxpd_mclk & 0xf) << 8) /* ODT_PD_EXIT */ |
222 | | ((tmrd_mclk & 0xf) << 0) /* MRS_CYC */ | |
223 | ); | |
224 | debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0); | |
225 | } | |
226 | #endif /* defined(CONFIG_FSL_DDR2) */ | |
227 | ||
228 | /* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */ | |
229 | static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, | |
c360ceac DL |
230 | const common_timing_params_t *common_dimm, |
231 | unsigned int cas_latency) | |
58e5e9af KG |
232 | { |
233 | /* Extended Activate to precharge interval (tRAS) */ | |
234 | unsigned int ext_acttopre = 0; | |
235 | unsigned int ext_refrec; /* Extended refresh recovery time (tRFC) */ | |
236 | unsigned int ext_caslat = 0; /* Extended MCAS latency from READ cmd */ | |
237 | unsigned int cntl_adj = 0; /* Control Adjust */ | |
238 | ||
80ee3ce6 DL |
239 | /* If the tRAS > 19 MCLK, we use the ext mode */ |
240 | if (picos_to_mclk(common_dimm->tRAS_ps) > 0x13) | |
241 | ext_acttopre = 1; | |
242 | ||
58e5e9af | 243 | ext_refrec = (picos_to_mclk(common_dimm->tRFC_ps) - 8) >> 4; |
c360ceac DL |
244 | |
245 | /* If the CAS latency more than 8, use the ext mode */ | |
246 | if (cas_latency > 8) | |
247 | ext_caslat = 1; | |
248 | ||
58e5e9af KG |
249 | ddr->timing_cfg_3 = (0 |
250 | | ((ext_acttopre & 0x1) << 24) | |
80ee3ce6 | 251 | | ((ext_refrec & 0xF) << 16) |
58e5e9af KG |
252 | | ((ext_caslat & 0x1) << 12) |
253 | | ((cntl_adj & 0x7) << 0) | |
254 | ); | |
1f293b41 | 255 | debug("FSLDDR: timing_cfg_3 = 0x%08x\n", ddr->timing_cfg_3); |
58e5e9af KG |
256 | } |
257 | ||
258 | /* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */ | |
259 | static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, | |
c360ceac | 260 | const memctl_options_t *popts, |
58e5e9af KG |
261 | const common_timing_params_t *common_dimm, |
262 | unsigned int cas_latency) | |
263 | { | |
264 | /* Precharge-to-activate interval (tRP) */ | |
265 | unsigned char pretoact_mclk; | |
266 | /* Activate to precharge interval (tRAS) */ | |
267 | unsigned char acttopre_mclk; | |
268 | /* Activate to read/write interval (tRCD) */ | |
269 | unsigned char acttorw_mclk; | |
270 | /* CASLAT */ | |
271 | unsigned char caslat_ctrl; | |
272 | /* Refresh recovery time (tRFC) ; trfc_low */ | |
273 | unsigned char refrec_ctrl; | |
274 | /* Last data to precharge minimum interval (tWR) */ | |
275 | unsigned char wrrec_mclk; | |
276 | /* Activate-to-activate interval (tRRD) */ | |
277 | unsigned char acttoact_mclk; | |
278 | /* Last write data pair to read command issue interval (tWTR) */ | |
279 | unsigned char wrtord_mclk; | |
280 | ||
281 | pretoact_mclk = picos_to_mclk(common_dimm->tRP_ps); | |
282 | acttopre_mclk = picos_to_mclk(common_dimm->tRAS_ps); | |
283 | acttorw_mclk = picos_to_mclk(common_dimm->tRCD_ps); | |
284 | ||
285 | /* | |
286 | * Translate CAS Latency to a DDR controller field value: | |
287 | * | |
288 | * CAS Lat DDR I DDR II Ctrl | |
289 | * Clocks SPD Bit SPD Bit Value | |
290 | * ------- ------- ------- ----- | |
291 | * 1.0 0 0001 | |
292 | * 1.5 1 0010 | |
293 | * 2.0 2 2 0011 | |
294 | * 2.5 3 0100 | |
295 | * 3.0 4 3 0101 | |
296 | * 3.5 5 0110 | |
297 | * 4.0 4 0111 | |
298 | * 4.5 1000 | |
299 | * 5.0 5 1001 | |
300 | */ | |
301 | #if defined(CONFIG_FSL_DDR1) | |
302 | caslat_ctrl = (cas_latency + 1) & 0x07; | |
303 | #elif defined(CONFIG_FSL_DDR2) | |
304 | caslat_ctrl = 2 * cas_latency - 1; | |
305 | #else | |
c360ceac DL |
306 | /* |
307 | * if the CAS latency more than 8 cycle, | |
308 | * we need set extend bit for it at | |
309 | * TIMING_CFG_3[EXT_CASLAT] | |
310 | */ | |
311 | if (cas_latency > 8) | |
312 | cas_latency -= 8; | |
313 | caslat_ctrl = 2 * cas_latency - 1; | |
58e5e9af KG |
314 | #endif |
315 | ||
316 | refrec_ctrl = picos_to_mclk(common_dimm->tRFC_ps) - 8; | |
317 | wrrec_mclk = picos_to_mclk(common_dimm->tWR_ps); | |
c360ceac DL |
318 | if (popts->OTF_burst_chop_en) |
319 | wrrec_mclk += 2; | |
320 | ||
58e5e9af | 321 | acttoact_mclk = picos_to_mclk(common_dimm->tRRD_ps); |
c360ceac DL |
322 | /* |
323 | * JEDEC has min requirement for tRRD | |
324 | */ | |
325 | #if defined(CONFIG_FSL_DDR3) | |
326 | if (acttoact_mclk < 4) | |
327 | acttoact_mclk = 4; | |
328 | #endif | |
58e5e9af | 329 | wrtord_mclk = picos_to_mclk(common_dimm->tWTR_ps); |
c360ceac DL |
330 | /* |
331 | * JEDEC has some min requirements for tWTR | |
332 | */ | |
333 | #if defined(CONFIG_FSL_DDR2) | |
334 | if (wrtord_mclk < 2) | |
335 | wrtord_mclk = 2; | |
336 | #elif defined(CONFIG_FSL_DDR3) | |
337 | if (wrtord_mclk < 4) | |
338 | wrtord_mclk = 4; | |
339 | #endif | |
340 | if (popts->OTF_burst_chop_en) | |
341 | wrtord_mclk += 2; | |
58e5e9af KG |
342 | |
343 | ddr->timing_cfg_1 = (0 | |
80ee3ce6 | 344 | | ((pretoact_mclk & 0x0F) << 28) |
58e5e9af | 345 | | ((acttopre_mclk & 0x0F) << 24) |
80ee3ce6 | 346 | | ((acttorw_mclk & 0xF) << 20) |
58e5e9af KG |
347 | | ((caslat_ctrl & 0xF) << 16) |
348 | | ((refrec_ctrl & 0xF) << 12) | |
80ee3ce6 | 349 | | ((wrrec_mclk & 0x0F) << 8) |
58e5e9af KG |
350 | | ((acttoact_mclk & 0x07) << 4) |
351 | | ((wrtord_mclk & 0x07) << 0) | |
352 | ); | |
1f293b41 | 353 | debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1); |
58e5e9af KG |
354 | } |
355 | ||
356 | /* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */ | |
357 | static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr, | |
358 | const memctl_options_t *popts, | |
359 | const common_timing_params_t *common_dimm, | |
360 | unsigned int cas_latency, | |
361 | unsigned int additive_latency) | |
362 | { | |
363 | /* Additive latency */ | |
364 | unsigned char add_lat_mclk; | |
365 | /* CAS-to-preamble override */ | |
366 | unsigned short cpo; | |
367 | /* Write latency */ | |
368 | unsigned char wr_lat; | |
369 | /* Read to precharge (tRTP) */ | |
370 | unsigned char rd_to_pre; | |
371 | /* Write command to write data strobe timing adjustment */ | |
372 | unsigned char wr_data_delay; | |
373 | /* Minimum CKE pulse width (tCKE) */ | |
374 | unsigned char cke_pls; | |
375 | /* Window for four activates (tFAW) */ | |
376 | unsigned short four_act; | |
377 | ||
378 | /* FIXME add check that this must be less than acttorw_mclk */ | |
379 | add_lat_mclk = additive_latency; | |
380 | cpo = popts->cpo_override; | |
381 | ||
382 | #if defined(CONFIG_FSL_DDR1) | |
383 | /* | |
384 | * This is a lie. It should really be 1, but if it is | |
385 | * set to 1, bits overlap into the old controller's | |
386 | * otherwise unused ACSM field. If we leave it 0, then | |
387 | * the HW will magically treat it as 1 for DDR 1. Oh Yea. | |
388 | */ | |
389 | wr_lat = 0; | |
390 | #elif defined(CONFIG_FSL_DDR2) | |
6a819783 | 391 | wr_lat = cas_latency - 1; |
58e5e9af | 392 | #else |
c360ceac | 393 | wr_lat = compute_cas_write_latency(); |
58e5e9af KG |
394 | #endif |
395 | ||
396 | rd_to_pre = picos_to_mclk(common_dimm->tRTP_ps); | |
c360ceac DL |
397 | /* |
398 | * JEDEC has some min requirements for tRTP | |
399 | */ | |
6a819783 | 400 | #if defined(CONFIG_FSL_DDR2) |
c360ceac DL |
401 | if (rd_to_pre < 2) |
402 | rd_to_pre = 2; | |
403 | #elif defined(CONFIG_FSL_DDR3) | |
404 | if (rd_to_pre < 4) | |
405 | rd_to_pre = 4; | |
6a819783 | 406 | #endif |
c360ceac DL |
407 | if (additive_latency) |
408 | rd_to_pre += additive_latency; | |
409 | if (popts->OTF_burst_chop_en) | |
410 | rd_to_pre += 2; /* according to UM */ | |
411 | ||
58e5e9af KG |
412 | wr_data_delay = popts->write_data_delay; |
413 | cke_pls = picos_to_mclk(popts->tCKE_clock_pulse_width_ps); | |
414 | four_act = picos_to_mclk(popts->tFAW_window_four_activates_ps); | |
415 | ||
416 | ddr->timing_cfg_2 = (0 | |
22ff3d01 | 417 | | ((add_lat_mclk & 0xf) << 28) |
58e5e9af | 418 | | ((cpo & 0x1f) << 23) |
22ff3d01 | 419 | | ((wr_lat & 0xf) << 19) |
c360ceac DL |
420 | | ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT) |
421 | | ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT) | |
58e5e9af | 422 | | ((cke_pls & 0x7) << 6) |
22ff3d01 | 423 | | ((four_act & 0x3f) << 0) |
58e5e9af | 424 | ); |
1f293b41 | 425 | debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2); |
58e5e9af KG |
426 | } |
427 | ||
428 | /* DDR SDRAM control configuration (DDR_SDRAM_CFG) */ | |
429 | static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr, | |
430 | const memctl_options_t *popts, | |
431 | const common_timing_params_t *common_dimm) | |
432 | { | |
433 | unsigned int mem_en; /* DDR SDRAM interface logic enable */ | |
434 | unsigned int sren; /* Self refresh enable (during sleep) */ | |
435 | unsigned int ecc_en; /* ECC enable. */ | |
436 | unsigned int rd_en; /* Registered DIMM enable */ | |
437 | unsigned int sdram_type; /* Type of SDRAM */ | |
438 | unsigned int dyn_pwr; /* Dynamic power management mode */ | |
439 | unsigned int dbw; /* DRAM dta bus width */ | |
22ff3d01 | 440 | unsigned int eight_be = 0; /* 8-beat burst enable, DDR2 is zero */ |
58e5e9af KG |
441 | unsigned int ncap = 0; /* Non-concurrent auto-precharge */ |
442 | unsigned int threeT_en; /* Enable 3T timing */ | |
443 | unsigned int twoT_en; /* Enable 2T timing */ | |
444 | unsigned int ba_intlv_ctl; /* Bank (CS) interleaving control */ | |
445 | unsigned int x32_en = 0; /* x32 enable */ | |
446 | unsigned int pchb8 = 0; /* precharge bit 8 enable */ | |
447 | unsigned int hse; /* Global half strength override */ | |
448 | unsigned int mem_halt = 0; /* memory controller halt */ | |
449 | unsigned int bi = 0; /* Bypass initialization */ | |
450 | ||
451 | mem_en = 1; | |
452 | sren = popts->self_refresh_in_sleep; | |
453 | if (common_dimm->all_DIMMs_ECC_capable) { | |
454 | /* Allow setting of ECC only if all DIMMs are ECC. */ | |
455 | ecc_en = popts->ECC_mode; | |
456 | } else { | |
457 | ecc_en = 0; | |
458 | } | |
459 | ||
460 | rd_en = (common_dimm->all_DIMMs_registered | |
461 | && !common_dimm->all_DIMMs_unbuffered); | |
462 | ||
463 | sdram_type = CONFIG_FSL_SDRAM_TYPE; | |
464 | ||
465 | dyn_pwr = popts->dynamic_power; | |
466 | dbw = popts->data_bus_width; | |
c360ceac DL |
467 | /* 8-beat burst enable DDR-III case |
468 | * we must clear it when use the on-the-fly mode, | |
469 | * must set it when use the 32-bits bus mode. | |
470 | */ | |
471 | if (sdram_type == SDRAM_TYPE_DDR3) { | |
472 | if (popts->burst_length == DDR_BL8) | |
473 | eight_be = 1; | |
474 | if (popts->burst_length == DDR_OTF) | |
475 | eight_be = 0; | |
476 | if (dbw == 0x1) | |
477 | eight_be = 1; | |
478 | } | |
479 | ||
58e5e9af KG |
480 | threeT_en = popts->threeT_en; |
481 | twoT_en = popts->twoT_en; | |
482 | ba_intlv_ctl = popts->ba_intlv_ctl; | |
483 | hse = popts->half_strength_driver_enable; | |
484 | ||
485 | ddr->ddr_sdram_cfg = (0 | |
486 | | ((mem_en & 0x1) << 31) | |
487 | | ((sren & 0x1) << 30) | |
488 | | ((ecc_en & 0x1) << 29) | |
489 | | ((rd_en & 0x1) << 28) | |
490 | | ((sdram_type & 0x7) << 24) | |
491 | | ((dyn_pwr & 0x1) << 21) | |
492 | | ((dbw & 0x3) << 19) | |
493 | | ((eight_be & 0x1) << 18) | |
494 | | ((ncap & 0x1) << 17) | |
495 | | ((threeT_en & 0x1) << 16) | |
496 | | ((twoT_en & 0x1) << 15) | |
497 | | ((ba_intlv_ctl & 0x7F) << 8) | |
498 | | ((x32_en & 0x1) << 5) | |
499 | | ((pchb8 & 0x1) << 4) | |
500 | | ((hse & 0x1) << 3) | |
501 | | ((mem_halt & 0x1) << 1) | |
502 | | ((bi & 0x1) << 0) | |
503 | ); | |
1f293b41 | 504 | debug("FSLDDR: ddr_sdram_cfg = 0x%08x\n", ddr->ddr_sdram_cfg); |
58e5e9af KG |
505 | } |
506 | ||
507 | /* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */ | |
508 | static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr, | |
509 | const memctl_options_t *popts) | |
510 | { | |
511 | unsigned int frc_sr = 0; /* Force self refresh */ | |
512 | unsigned int sr_ie = 0; /* Self-refresh interrupt enable */ | |
513 | unsigned int dll_rst_dis; /* DLL reset disable */ | |
514 | unsigned int dqs_cfg; /* DQS configuration */ | |
515 | unsigned int odt_cfg; /* ODT configuration */ | |
516 | unsigned int num_pr; /* Number of posted refreshes */ | |
517 | unsigned int obc_cfg; /* On-The-Fly Burst Chop Cfg */ | |
518 | unsigned int ap_en; /* Address Parity Enable */ | |
519 | unsigned int d_init; /* DRAM data initialization */ | |
520 | unsigned int rcw_en = 0; /* Register Control Word Enable */ | |
521 | unsigned int md_en = 0; /* Mirrored DIMM Enable */ | |
522 | ||
523 | dll_rst_dis = 1; /* Make this configurable */ | |
524 | dqs_cfg = popts->DQS_config; | |
525 | if (popts->cs_local_opts[0].odt_rd_cfg | |
526 | || popts->cs_local_opts[0].odt_wr_cfg) { | |
527 | /* FIXME */ | |
528 | odt_cfg = 2; | |
529 | } else { | |
530 | odt_cfg = 0; | |
531 | } | |
532 | ||
533 | num_pr = 1; /* Make this configurable */ | |
534 | ||
535 | /* | |
536 | * 8572 manual says | |
537 | * {TIMING_CFG_1[PRETOACT] | |
538 | * + [DDR_SDRAM_CFG_2[NUM_PR] | |
539 | * * ({EXT_REFREC || REFREC} + 8 + 2)]} | |
540 | * << DDR_SDRAM_INTERVAL[REFINT] | |
541 | */ | |
c360ceac DL |
542 | #if defined(CONFIG_FSL_DDR3) |
543 | obc_cfg = popts->OTF_burst_chop_en; | |
544 | #else | |
545 | obc_cfg = 0; | |
546 | #endif | |
58e5e9af | 547 | |
58e5e9af KG |
548 | ap_en = 0; /* Make this configurable? */ |
549 | ||
550 | #if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) | |
551 | /* Use the DDR controller to auto initialize memory. */ | |
552 | d_init = 1; | |
553 | ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE; | |
554 | debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init); | |
555 | #else | |
556 | /* Memory will be initialized via DMA, or not at all. */ | |
557 | d_init = 0; | |
558 | #endif | |
559 | ||
c360ceac DL |
560 | #if defined(CONFIG_FSL_DDR3) |
561 | md_en = popts->mirrored_dimm; | |
562 | #endif | |
58e5e9af KG |
563 | ddr->ddr_sdram_cfg_2 = (0 |
564 | | ((frc_sr & 0x1) << 31) | |
565 | | ((sr_ie & 0x1) << 30) | |
566 | | ((dll_rst_dis & 0x1) << 29) | |
567 | | ((dqs_cfg & 0x3) << 26) | |
568 | | ((odt_cfg & 0x3) << 21) | |
569 | | ((num_pr & 0xf) << 12) | |
570 | | ((obc_cfg & 0x1) << 6) | |
571 | | ((ap_en & 0x1) << 5) | |
572 | | ((d_init & 0x1) << 4) | |
573 | | ((rcw_en & 0x1) << 2) | |
574 | | ((md_en & 0x1) << 0) | |
575 | ); | |
1f293b41 | 576 | debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2); |
58e5e9af KG |
577 | } |
578 | ||
579 | /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */ | |
1aa3d08a DL |
580 | static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr, |
581 | const memctl_options_t *popts) | |
58e5e9af KG |
582 | { |
583 | unsigned short esdmode2 = 0; /* Extended SDRAM mode 2 */ | |
584 | unsigned short esdmode3 = 0; /* Extended SDRAM mode 3 */ | |
585 | ||
c360ceac | 586 | #if defined(CONFIG_FSL_DDR3) |
1aa3d08a | 587 | unsigned int rtt_wr = 0; /* Rtt_WR - dynamic ODT off */ |
c360ceac DL |
588 | unsigned int srt = 0; /* self-refresh temerature, normal range */ |
589 | unsigned int asr = 0; /* auto self-refresh disable */ | |
590 | unsigned int cwl = compute_cas_write_latency() - 5; | |
591 | unsigned int pasr = 0; /* partial array self refresh disable */ | |
592 | ||
1aa3d08a DL |
593 | if (popts->rtt_override) |
594 | rtt_wr = popts->rtt_wr_override_value; | |
595 | ||
c360ceac DL |
596 | esdmode2 = (0 |
597 | | ((rtt_wr & 0x3) << 9) | |
598 | | ((srt & 0x1) << 7) | |
599 | | ((asr & 0x1) << 6) | |
600 | | ((cwl & 0x7) << 3) | |
601 | | ((pasr & 0x7) << 0)); | |
602 | #endif | |
58e5e9af KG |
603 | ddr->ddr_sdram_mode_2 = (0 |
604 | | ((esdmode2 & 0xFFFF) << 16) | |
605 | | ((esdmode3 & 0xFFFF) << 0) | |
606 | ); | |
1f293b41 | 607 | debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2); |
58e5e9af KG |
608 | } |
609 | ||
610 | /* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */ | |
611 | static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr, | |
612 | const memctl_options_t *popts, | |
613 | const common_timing_params_t *common_dimm) | |
614 | { | |
615 | unsigned int refint; /* Refresh interval */ | |
616 | unsigned int bstopre; /* Precharge interval */ | |
617 | ||
618 | refint = picos_to_mclk(common_dimm->refresh_rate_ps); | |
619 | ||
620 | bstopre = popts->bstopre; | |
621 | ||
622 | /* refint field used 0x3FFF in earlier controllers */ | |
623 | ddr->ddr_sdram_interval = (0 | |
624 | | ((refint & 0xFFFF) << 16) | |
625 | | ((bstopre & 0x3FFF) << 0) | |
626 | ); | |
1f293b41 | 627 | debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval); |
58e5e9af KG |
628 | } |
629 | ||
c360ceac DL |
630 | #if defined(CONFIG_FSL_DDR3) |
631 | /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */ | |
632 | static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, | |
633 | const memctl_options_t *popts, | |
634 | const common_timing_params_t *common_dimm, | |
635 | unsigned int cas_latency, | |
636 | unsigned int additive_latency) | |
637 | { | |
638 | unsigned short esdmode; /* Extended SDRAM mode */ | |
639 | unsigned short sdmode; /* SDRAM mode */ | |
640 | ||
641 | /* Mode Register - MR1 */ | |
642 | unsigned int qoff = 0; /* Output buffer enable 0=yes, 1=no */ | |
643 | unsigned int tdqs_en = 0; /* TDQS Enable: 0=no, 1=yes */ | |
644 | unsigned int rtt; | |
645 | unsigned int wrlvl_en = 0; /* Write level enable: 0=no, 1=yes */ | |
646 | unsigned int al = 0; /* Posted CAS# additive latency (AL) */ | |
647 | unsigned int dic = 1; /* Output driver impedance, 34ohm */ | |
648 | unsigned int dll_en = 0; /* DLL Enable 0=Enable (Normal), | |
649 | 1=Disable (Test/Debug) */ | |
650 | ||
651 | /* Mode Register - MR0 */ | |
652 | unsigned int dll_on; /* DLL control for precharge PD, 0=off, 1=on */ | |
653 | unsigned int wr; /* Write Recovery */ | |
654 | unsigned int dll_rst; /* DLL Reset */ | |
655 | unsigned int mode; /* Normal=0 or Test=1 */ | |
656 | unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */ | |
657 | /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */ | |
658 | unsigned int bt; | |
659 | unsigned int bl; /* BL: Burst Length */ | |
660 | ||
661 | unsigned int wr_mclk; | |
662 | ||
663 | const unsigned int mclk_ps = get_memory_clk_period_ps(); | |
664 | ||
665 | rtt = fsl_ddr_get_rtt(); | |
666 | if (popts->rtt_override) | |
667 | rtt = popts->rtt_override_value; | |
668 | ||
669 | if (additive_latency == (cas_latency - 1)) | |
670 | al = 1; | |
671 | if (additive_latency == (cas_latency - 2)) | |
672 | al = 2; | |
673 | ||
674 | /* | |
675 | * The esdmode value will also be used for writing | |
676 | * MR1 during write leveling for DDR3, although the | |
677 | * bits specifically related to the write leveling | |
678 | * scheme will be handled automatically by the DDR | |
679 | * controller. so we set the wrlvl_en = 0 here. | |
680 | */ | |
681 | esdmode = (0 | |
682 | | ((qoff & 0x1) << 12) | |
683 | | ((tdqs_en & 0x1) << 11) | |
6d8565a1 | 684 | | ((rtt & 0x4) << 7) /* rtt field is split */ |
c360ceac | 685 | | ((wrlvl_en & 0x1) << 7) |
6d8565a1 KG |
686 | | ((rtt & 0x2) << 5) /* rtt field is split */ |
687 | | ((dic & 0x2) << 4) /* DIC field is split */ | |
c360ceac | 688 | | ((al & 0x3) << 3) |
6d8565a1 | 689 | | ((rtt & 0x1) << 2) /* rtt field is split */ |
c360ceac DL |
690 | | ((dic & 0x1) << 1) /* DIC field is split */ |
691 | | ((dll_en & 0x1) << 0) | |
692 | ); | |
693 | ||
694 | /* | |
695 | * DLL control for precharge PD | |
696 | * 0=slow exit DLL off (tXPDLL) | |
697 | * 1=fast exit DLL on (tXP) | |
698 | */ | |
699 | dll_on = 1; | |
700 | wr_mclk = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps; | |
701 | if (wr_mclk >= 12) | |
702 | wr = 6; | |
703 | else if (wr_mclk >= 9) | |
704 | wr = 5; | |
705 | else | |
706 | wr = wr_mclk - 4; | |
707 | dll_rst = 0; /* dll no reset */ | |
708 | mode = 0; /* normal mode */ | |
709 | ||
710 | /* look up table to get the cas latency bits */ | |
711 | if (cas_latency >= 5 && cas_latency <= 11) { | |
712 | unsigned char cas_latency_table[7] = { | |
713 | 0x2, /* 5 clocks */ | |
714 | 0x4, /* 6 clocks */ | |
715 | 0x6, /* 7 clocks */ | |
716 | 0x8, /* 8 clocks */ | |
717 | 0xa, /* 9 clocks */ | |
718 | 0xc, /* 10 clocks */ | |
719 | 0xe /* 11 clocks */ | |
720 | }; | |
721 | caslat = cas_latency_table[cas_latency - 5]; | |
722 | } | |
723 | bt = 0; /* Nibble sequential */ | |
724 | ||
725 | switch (popts->burst_length) { | |
726 | case DDR_BL8: | |
727 | bl = 0; | |
728 | break; | |
729 | case DDR_OTF: | |
730 | bl = 1; | |
731 | break; | |
732 | case DDR_BC4: | |
733 | bl = 2; | |
734 | break; | |
735 | default: | |
736 | printf("Error: invalid burst length of %u specified. " | |
737 | " Defaulting to on-the-fly BC4 or BL8 beats.\n", | |
738 | popts->burst_length); | |
739 | bl = 1; | |
740 | break; | |
741 | } | |
742 | ||
743 | sdmode = (0 | |
744 | | ((dll_on & 0x1) << 12) | |
745 | | ((wr & 0x7) << 9) | |
746 | | ((dll_rst & 0x1) << 8) | |
747 | | ((mode & 0x1) << 7) | |
748 | | (((caslat >> 1) & 0x7) << 4) | |
749 | | ((bt & 0x1) << 3) | |
750 | | ((bl & 0x3) << 0) | |
751 | ); | |
752 | ||
753 | ddr->ddr_sdram_mode = (0 | |
754 | | ((esdmode & 0xFFFF) << 16) | |
755 | | ((sdmode & 0xFFFF) << 0) | |
756 | ); | |
757 | ||
758 | debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode); | |
759 | } | |
760 | ||
761 | #else /* !CONFIG_FSL_DDR3 */ | |
762 | ||
58e5e9af KG |
763 | /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */ |
764 | static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr, | |
765 | const memctl_options_t *popts, | |
766 | const common_timing_params_t *common_dimm, | |
767 | unsigned int cas_latency, | |
768 | unsigned int additive_latency) | |
769 | { | |
770 | unsigned short esdmode; /* Extended SDRAM mode */ | |
771 | unsigned short sdmode; /* SDRAM mode */ | |
772 | ||
773 | /* | |
774 | * FIXME: This ought to be pre-calculated in a | |
775 | * technology-specific routine, | |
776 | * e.g. compute_DDR2_mode_register(), and then the | |
777 | * sdmode and esdmode passed in as part of common_dimm. | |
778 | */ | |
779 | ||
780 | /* Extended Mode Register */ | |
781 | unsigned int mrs = 0; /* Mode Register Set */ | |
782 | unsigned int outputs = 0; /* 0=Enabled, 1=Disabled */ | |
783 | unsigned int rdqs_en = 0; /* RDQS Enable: 0=no, 1=yes */ | |
784 | unsigned int dqs_en = 0; /* DQS# Enable: 0=enable, 1=disable */ | |
785 | unsigned int ocd = 0; /* 0x0=OCD not supported, | |
786 | 0x7=OCD default state */ | |
787 | unsigned int rtt; | |
788 | unsigned int al; /* Posted CAS# additive latency (AL) */ | |
789 | unsigned int ods = 0; /* Output Drive Strength: | |
790 | 0 = Full strength (18ohm) | |
791 | 1 = Reduced strength (4ohm) */ | |
792 | unsigned int dll_en = 0; /* DLL Enable 0=Enable (Normal), | |
793 | 1=Disable (Test/Debug) */ | |
794 | ||
795 | /* Mode Register (MR) */ | |
796 | unsigned int mr; /* Mode Register Definition */ | |
797 | unsigned int pd; /* Power-Down Mode */ | |
798 | unsigned int wr; /* Write Recovery */ | |
799 | unsigned int dll_res; /* DLL Reset */ | |
800 | unsigned int mode; /* Normal=0 or Test=1 */ | |
302e52e0 | 801 | unsigned int caslat = 0;/* CAS# latency */ |
58e5e9af KG |
802 | /* BT: Burst Type (0=Sequential, 1=Interleaved) */ |
803 | unsigned int bt; | |
804 | unsigned int bl; /* BL: Burst Length */ | |
805 | ||
806 | #if defined(CONFIG_FSL_DDR2) | |
807 | const unsigned int mclk_ps = get_memory_clk_period_ps(); | |
808 | #endif | |
809 | ||
810 | rtt = fsl_ddr_get_rtt(); | |
811 | ||
812 | al = additive_latency; | |
813 | ||
814 | esdmode = (0 | |
815 | | ((mrs & 0x3) << 14) | |
816 | | ((outputs & 0x1) << 12) | |
817 | | ((rdqs_en & 0x1) << 11) | |
818 | | ((dqs_en & 0x1) << 10) | |
819 | | ((ocd & 0x7) << 7) | |
820 | | ((rtt & 0x2) << 5) /* rtt field is split */ | |
821 | | ((al & 0x7) << 3) | |
822 | | ((rtt & 0x1) << 2) /* rtt field is split */ | |
823 | | ((ods & 0x1) << 1) | |
824 | | ((dll_en & 0x1) << 0) | |
825 | ); | |
826 | ||
827 | mr = 0; /* FIXME: CHECKME */ | |
828 | ||
829 | /* | |
830 | * 0 = Fast Exit (Normal) | |
831 | * 1 = Slow Exit (Low Power) | |
832 | */ | |
833 | pd = 0; | |
834 | ||
835 | #if defined(CONFIG_FSL_DDR1) | |
836 | wr = 0; /* Historical */ | |
837 | #elif defined(CONFIG_FSL_DDR2) | |
838 | wr = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps - 1; | |
58e5e9af KG |
839 | #endif |
840 | dll_res = 0; | |
841 | mode = 0; | |
842 | ||
843 | #if defined(CONFIG_FSL_DDR1) | |
844 | if (1 <= cas_latency && cas_latency <= 4) { | |
845 | unsigned char mode_caslat_table[4] = { | |
846 | 0x5, /* 1.5 clocks */ | |
847 | 0x2, /* 2.0 clocks */ | |
848 | 0x6, /* 2.5 clocks */ | |
849 | 0x3 /* 3.0 clocks */ | |
850 | }; | |
302e52e0 KG |
851 | caslat = mode_caslat_table[cas_latency - 1]; |
852 | } else { | |
853 | printf("Warning: unknown cas_latency %d\n", cas_latency); | |
58e5e9af KG |
854 | } |
855 | #elif defined(CONFIG_FSL_DDR2) | |
856 | caslat = cas_latency; | |
58e5e9af KG |
857 | #endif |
858 | bt = 0; | |
859 | ||
860 | switch (popts->burst_length) { | |
c360ceac | 861 | case DDR_BL4: |
58e5e9af KG |
862 | bl = 2; |
863 | break; | |
c360ceac | 864 | case DDR_BL8: |
58e5e9af KG |
865 | bl = 3; |
866 | break; | |
867 | default: | |
868 | printf("Error: invalid burst length of %u specified. " | |
869 | " Defaulting to 4 beats.\n", | |
870 | popts->burst_length); | |
871 | bl = 2; | |
872 | break; | |
873 | } | |
874 | ||
875 | sdmode = (0 | |
876 | | ((mr & 0x3) << 14) | |
877 | | ((pd & 0x1) << 12) | |
878 | | ((wr & 0x7) << 9) | |
879 | | ((dll_res & 0x1) << 8) | |
880 | | ((mode & 0x1) << 7) | |
881 | | ((caslat & 0x7) << 4) | |
882 | | ((bt & 0x1) << 3) | |
883 | | ((bl & 0x7) << 0) | |
884 | ); | |
885 | ||
886 | ddr->ddr_sdram_mode = (0 | |
887 | | ((esdmode & 0xFFFF) << 16) | |
888 | | ((sdmode & 0xFFFF) << 0) | |
889 | ); | |
1f293b41 | 890 | debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode); |
58e5e9af | 891 | } |
c360ceac | 892 | #endif |
58e5e9af KG |
893 | |
894 | /* DDR SDRAM Data Initialization (DDR_DATA_INIT) */ | |
895 | static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr) | |
896 | { | |
897 | unsigned int init_value; /* Initialization value */ | |
898 | ||
899 | init_value = 0xDEADBEEF; | |
900 | ddr->ddr_data_init = init_value; | |
901 | } | |
902 | ||
903 | /* | |
904 | * DDR SDRAM Clock Control (DDR_SDRAM_CLK_CNTL) | |
905 | * The old controller on the 8540/60 doesn't have this register. | |
906 | * Hope it's OK to set it (to 0) anyway. | |
907 | */ | |
908 | static void set_ddr_sdram_clk_cntl(fsl_ddr_cfg_regs_t *ddr, | |
909 | const memctl_options_t *popts) | |
910 | { | |
911 | unsigned int clk_adjust; /* Clock adjust */ | |
912 | ||
913 | clk_adjust = popts->clk_adjust; | |
914 | ddr->ddr_sdram_clk_cntl = (clk_adjust & 0xF) << 23; | |
915 | } | |
916 | ||
917 | /* DDR Initialization Address (DDR_INIT_ADDR) */ | |
918 | static void set_ddr_init_addr(fsl_ddr_cfg_regs_t *ddr) | |
919 | { | |
920 | unsigned int init_addr = 0; /* Initialization address */ | |
921 | ||
922 | ddr->ddr_init_addr = init_addr; | |
923 | } | |
924 | ||
925 | /* DDR Initialization Address (DDR_INIT_EXT_ADDR) */ | |
926 | static void set_ddr_init_ext_addr(fsl_ddr_cfg_regs_t *ddr) | |
927 | { | |
928 | unsigned int uia = 0; /* Use initialization address */ | |
929 | unsigned int init_ext_addr = 0; /* Initialization address */ | |
930 | ||
931 | ddr->ddr_init_ext_addr = (0 | |
932 | | ((uia & 0x1) << 31) | |
933 | | (init_ext_addr & 0xF) | |
934 | ); | |
935 | } | |
936 | ||
937 | /* DDR SDRAM Timing Configuration 4 (TIMING_CFG_4) */ | |
ec145e87 DL |
938 | static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr, |
939 | const memctl_options_t *popts) | |
58e5e9af KG |
940 | { |
941 | unsigned int rwt = 0; /* Read-to-write turnaround for same CS */ | |
942 | unsigned int wrt = 0; /* Write-to-read turnaround for same CS */ | |
943 | unsigned int rrt = 0; /* Read-to-read turnaround for same CS */ | |
944 | unsigned int wwt = 0; /* Write-to-write turnaround for same CS */ | |
945 | unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */ | |
946 | ||
c360ceac | 947 | #if defined(CONFIG_FSL_DDR3) |
ec145e87 DL |
948 | if (popts->burst_length == DDR_BL8) { |
949 | /* We set BL/2 for fixed BL8 */ | |
950 | rrt = 0; /* BL/2 clocks */ | |
951 | wwt = 0; /* BL/2 clocks */ | |
952 | } else { | |
953 | /* We need to set BL/2 + 2 to BC4 and OTF */ | |
954 | rrt = 2; /* BL/2 + 2 clocks */ | |
955 | wwt = 2; /* BL/2 + 2 clocks */ | |
956 | } | |
c360ceac DL |
957 | dll_lock = 1; /* tDLLK = 512 clocks from spec */ |
958 | #endif | |
58e5e9af KG |
959 | ddr->timing_cfg_4 = (0 |
960 | | ((rwt & 0xf) << 28) | |
961 | | ((wrt & 0xf) << 24) | |
962 | | ((rrt & 0xf) << 20) | |
963 | | ((wwt & 0xf) << 16) | |
964 | | (dll_lock & 0x3) | |
965 | ); | |
1f293b41 | 966 | debug("FSLDDR: timing_cfg_4 = 0x%08x\n", ddr->timing_cfg_4); |
58e5e9af KG |
967 | } |
968 | ||
969 | /* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */ | |
970 | static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr) | |
971 | { | |
972 | unsigned int rodt_on = 0; /* Read to ODT on */ | |
973 | unsigned int rodt_off = 0; /* Read to ODT off */ | |
974 | unsigned int wodt_on = 0; /* Write to ODT on */ | |
975 | unsigned int wodt_off = 0; /* Write to ODT off */ | |
976 | ||
c360ceac DL |
977 | #if defined(CONFIG_FSL_DDR3) |
978 | rodt_on = 3; /* 2 clocks */ | |
979 | rodt_off = 4; /* 4 clocks */ | |
980 | wodt_on = 2; /* 1 clocks */ | |
981 | wodt_off = 4; /* 4 clocks */ | |
982 | #endif | |
983 | ||
58e5e9af | 984 | ddr->timing_cfg_5 = (0 |
22ff3d01 DL |
985 | | ((rodt_on & 0x1f) << 24) |
986 | | ((rodt_off & 0x7) << 20) | |
987 | | ((wodt_on & 0x1f) << 12) | |
988 | | ((wodt_off & 0x7) << 8) | |
58e5e9af | 989 | ); |
1f293b41 | 990 | debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5); |
58e5e9af KG |
991 | } |
992 | ||
993 | /* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */ | |
c360ceac | 994 | static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en) |
58e5e9af | 995 | { |
58e5e9af KG |
996 | unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */ |
997 | /* Normal Operation Full Calibration Time (tZQoper) */ | |
998 | unsigned int zqoper = 0; | |
999 | /* Normal Operation Short Calibration Time (tZQCS) */ | |
1000 | unsigned int zqcs = 0; | |
1001 | ||
c360ceac DL |
1002 | if (zq_en) { |
1003 | zqinit = 9; /* 512 clocks */ | |
1004 | zqoper = 8; /* 256 clocks */ | |
1005 | zqcs = 6; /* 64 clocks */ | |
1006 | } | |
1007 | ||
58e5e9af KG |
1008 | ddr->ddr_zq_cntl = (0 |
1009 | | ((zq_en & 0x1) << 31) | |
1010 | | ((zqinit & 0xF) << 24) | |
1011 | | ((zqoper & 0xF) << 16) | |
1012 | | ((zqcs & 0xF) << 8) | |
1013 | ); | |
1014 | } | |
1015 | ||
1016 | /* DDR Write Leveling Control (DDR_WRLVL_CNTL) */ | |
bdc9f7b5 DL |
1017 | static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en, |
1018 | const memctl_options_t *popts) | |
58e5e9af | 1019 | { |
58e5e9af KG |
1020 | /* |
1021 | * First DQS pulse rising edge after margining mode | |
1022 | * is programmed (tWL_MRD) | |
1023 | */ | |
1024 | unsigned int wrlvl_mrd = 0; | |
1025 | /* ODT delay after margining mode is programmed (tWL_ODTEN) */ | |
1026 | unsigned int wrlvl_odten = 0; | |
1027 | /* DQS/DQS_ delay after margining mode is programmed (tWL_DQSEN) */ | |
1028 | unsigned int wrlvl_dqsen = 0; | |
1029 | /* WRLVL_SMPL: Write leveling sample time */ | |
1030 | unsigned int wrlvl_smpl = 0; | |
1031 | /* WRLVL_WLR: Write leveling repeition time */ | |
1032 | unsigned int wrlvl_wlr = 0; | |
1033 | /* WRLVL_START: Write leveling start time */ | |
1034 | unsigned int wrlvl_start = 0; | |
1035 | ||
c360ceac DL |
1036 | /* suggest enable write leveling for DDR3 due to fly-by topology */ |
1037 | if (wrlvl_en) { | |
1038 | /* tWL_MRD min = 40 nCK, we set it 64 */ | |
1039 | wrlvl_mrd = 0x6; | |
1040 | /* tWL_ODTEN 128 */ | |
1041 | wrlvl_odten = 0x7; | |
1042 | /* tWL_DQSEN min = 25 nCK, we set it 32 */ | |
1043 | wrlvl_dqsen = 0x5; | |
1044 | /* | |
bdc9f7b5 DL |
1045 | * Write leveling sample time at least need 6 clocks |
1046 | * higher than tWLO to allow enough time for progagation | |
1047 | * delay and sampling the prime data bits. | |
c360ceac DL |
1048 | */ |
1049 | wrlvl_smpl = 0xf; | |
1050 | /* | |
1051 | * Write leveling repetition time | |
1052 | * at least tWLO + 6 clocks clocks | |
1053 | * we set it 32 | |
1054 | */ | |
1055 | wrlvl_wlr = 0x5; | |
1056 | /* | |
1057 | * Write leveling start time | |
1058 | * The value use for the DQS_ADJUST for the first sample | |
1059 | * when write leveling is enabled. | |
c360ceac DL |
1060 | */ |
1061 | wrlvl_start = 0x8; | |
bdc9f7b5 DL |
1062 | /* |
1063 | * Override the write leveling sample and start time | |
1064 | * according to specific board | |
1065 | */ | |
1066 | if (popts->wrlvl_override) { | |
1067 | wrlvl_smpl = popts->wrlvl_sample; | |
1068 | wrlvl_start = popts->wrlvl_start; | |
1069 | } | |
c360ceac DL |
1070 | } |
1071 | ||
58e5e9af KG |
1072 | ddr->ddr_wrlvl_cntl = (0 |
1073 | | ((wrlvl_en & 0x1) << 31) | |
1074 | | ((wrlvl_mrd & 0x7) << 24) | |
1075 | | ((wrlvl_odten & 0x7) << 20) | |
1076 | | ((wrlvl_dqsen & 0x7) << 16) | |
1077 | | ((wrlvl_smpl & 0xf) << 12) | |
1078 | | ((wrlvl_wlr & 0x7) << 8) | |
22ff3d01 | 1079 | | ((wrlvl_start & 0x1F) << 0) |
58e5e9af KG |
1080 | ); |
1081 | } | |
1082 | ||
1083 | /* DDR Self Refresh Counter (DDR_SR_CNTR) */ | |
22cca7e1 | 1084 | static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr, unsigned int sr_it) |
58e5e9af | 1085 | { |
22cca7e1 | 1086 | /* Self Refresh Idle Threshold */ |
58e5e9af KG |
1087 | ddr->ddr_sr_cntr = (sr_it & 0xF) << 16; |
1088 | } | |
1089 | ||
58e5e9af KG |
1090 | /* DDR SDRAM Register Control Word 1 (DDR_SDRAM_RCW_1) */ |
1091 | static void set_ddr_sdram_rcw_1(fsl_ddr_cfg_regs_t *ddr) | |
1092 | { | |
1093 | unsigned int rcw0 = 0; /* RCW0: Register Control Word 0 */ | |
1094 | unsigned int rcw1 = 0; /* RCW1: Register Control Word 1 */ | |
1095 | unsigned int rcw2 = 0; /* RCW2: Register Control Word 2 */ | |
1096 | unsigned int rcw3 = 0; /* RCW3: Register Control Word 3 */ | |
1097 | unsigned int rcw4 = 0; /* RCW4: Register Control Word 4 */ | |
1098 | unsigned int rcw5 = 0; /* RCW5: Register Control Word 5 */ | |
1099 | unsigned int rcw6 = 0; /* RCW6: Register Control Word 6 */ | |
1100 | unsigned int rcw7 = 0; /* RCW7: Register Control Word 7 */ | |
1101 | ||
1102 | ddr->ddr_sdram_rcw_1 = (0 | |
1103 | | ((rcw0 & 0xF) << 28) | |
1104 | | ((rcw1 & 0xF) << 24) | |
1105 | | ((rcw2 & 0xF) << 20) | |
1106 | | ((rcw3 & 0xF) << 16) | |
1107 | | ((rcw4 & 0xF) << 12) | |
1108 | | ((rcw5 & 0xF) << 8) | |
1109 | | ((rcw6 & 0xF) << 4) | |
1110 | | ((rcw7 & 0xF) << 0) | |
1111 | ); | |
1112 | } | |
1113 | ||
1114 | /* DDR SDRAM Register Control Word 2 (DDR_SDRAM_RCW_2) */ | |
1115 | static void set_ddr_sdram_rcw_2(fsl_ddr_cfg_regs_t *ddr) | |
1116 | { | |
1117 | unsigned int rcw8 = 0; /* RCW0: Register Control Word 8 */ | |
1118 | unsigned int rcw9 = 0; /* RCW1: Register Control Word 9 */ | |
1119 | unsigned int rcw10 = 0; /* RCW2: Register Control Word 10 */ | |
1120 | unsigned int rcw11 = 0; /* RCW3: Register Control Word 11 */ | |
1121 | unsigned int rcw12 = 0; /* RCW4: Register Control Word 12 */ | |
1122 | unsigned int rcw13 = 0; /* RCW5: Register Control Word 13 */ | |
1123 | unsigned int rcw14 = 0; /* RCW6: Register Control Word 14 */ | |
1124 | unsigned int rcw15 = 0; /* RCW7: Register Control Word 15 */ | |
1125 | ||
1126 | ddr->ddr_sdram_rcw_2 = (0 | |
1127 | | ((rcw8 & 0xF) << 28) | |
1128 | | ((rcw9 & 0xF) << 24) | |
1129 | | ((rcw10 & 0xF) << 20) | |
1130 | | ((rcw11 & 0xF) << 16) | |
1131 | | ((rcw12 & 0xF) << 12) | |
1132 | | ((rcw13 & 0xF) << 8) | |
1133 | | ((rcw14 & 0xF) << 4) | |
1134 | | ((rcw15 & 0xF) << 0) | |
1135 | ); | |
1136 | } | |
1137 | ||
1138 | unsigned int | |
1139 | check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr) | |
1140 | { | |
1141 | unsigned int res = 0; | |
1142 | ||
1143 | /* | |
1144 | * Check that DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] are | |
1145 | * not set at the same time. | |
1146 | */ | |
1147 | if (ddr->ddr_sdram_cfg & 0x10000000 | |
1148 | && ddr->ddr_sdram_cfg & 0x00008000) { | |
1149 | printf("Error: DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] " | |
1150 | " should not be set at the same time.\n"); | |
1151 | res++; | |
1152 | } | |
1153 | ||
1154 | return res; | |
1155 | } | |
1156 | ||
1157 | unsigned int | |
1158 | compute_fsl_memctl_config_regs(const memctl_options_t *popts, | |
1159 | fsl_ddr_cfg_regs_t *ddr, | |
1160 | const common_timing_params_t *common_dimm, | |
1161 | const dimm_params_t *dimm_params, | |
1162 | unsigned int dbw_cap_adj) | |
1163 | { | |
1164 | unsigned int i; | |
1165 | unsigned int cas_latency; | |
1166 | unsigned int additive_latency; | |
22cca7e1 | 1167 | unsigned int sr_it; |
c360ceac DL |
1168 | unsigned int zq_en; |
1169 | unsigned int wrlvl_en; | |
58e5e9af KG |
1170 | |
1171 | memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t)); | |
1172 | ||
1173 | if (common_dimm == NULL) { | |
1174 | printf("Error: subset DIMM params struct null pointer\n"); | |
1175 | return 1; | |
1176 | } | |
1177 | ||
1178 | /* | |
1179 | * Process overrides first. | |
1180 | * | |
1181 | * FIXME: somehow add dereated caslat to this | |
1182 | */ | |
1183 | cas_latency = (popts->cas_latency_override) | |
1184 | ? popts->cas_latency_override_value | |
1185 | : common_dimm->lowest_common_SPD_caslat; | |
1186 | ||
1187 | additive_latency = (popts->additive_latency_override) | |
1188 | ? popts->additive_latency_override_value | |
1189 | : common_dimm->additive_latency; | |
1190 | ||
22cca7e1 DL |
1191 | sr_it = (popts->auto_self_refresh_en) |
1192 | ? popts->sr_it | |
1193 | : 0; | |
c360ceac DL |
1194 | /* ZQ calibration */ |
1195 | zq_en = (popts->zq_en) ? 1 : 0; | |
1196 | /* write leveling */ | |
1197 | wrlvl_en = (popts->wrlvl_en) ? 1 : 0; | |
22cca7e1 | 1198 | |
58e5e9af KG |
1199 | /* Chip Select Memory Bounds (CSn_BNDS) */ |
1200 | for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { | |
e7563aff | 1201 | unsigned long long ea = 0, sa = 0; |
dbbbb3ab HW |
1202 | |
1203 | if (popts->ba_intlv_ctl && (i > 0) && | |
1204 | ((popts->ba_intlv_ctl & 0x60) != FSL_DDR_CS2_CS3 )) { | |
1205 | /* Don't set up boundaries for other CS | |
1206 | * other than CS0, if bank interleaving | |
1207 | * is enabled and not CS2+CS3 interleaved. | |
3e731aab DL |
1208 | * But we need to set the ODT_RD_CFG and |
1209 | * ODT_WR_CFG for CS1_CONFIG here. | |
dbbbb3ab | 1210 | */ |
3e731aab | 1211 | set_csn_config(i, ddr, popts, dimm_params); |
58e5e9af KG |
1212 | break; |
1213 | } | |
1214 | ||
1215 | if (dimm_params[i/2].n_ranks == 0) { | |
1216 | debug("Skipping setup of CS%u " | |
1217 | "because n_ranks on DIMM %u is 0\n", i, i/2); | |
1218 | continue; | |
1219 | } | |
1220 | if (popts->memctl_interleaving && popts->ba_intlv_ctl) { | |
1221 | /* | |
1222 | * This works superbank 2CS | |
1223 | * There are 2 memory controllers configured | |
1224 | * identically, memory is interleaved between them, | |
1225 | * and each controller uses rank interleaving within | |
1226 | * itself. Therefore the starting and ending address | |
1227 | * on each controller is twice the amount present on | |
1228 | * each controller. | |
1229 | */ | |
dbbbb3ab HW |
1230 | unsigned long long rank_density |
1231 | = dimm_params[0].capacity; | |
1232 | ea = (2 * (rank_density >> dbw_cap_adj)) - 1; | |
58e5e9af KG |
1233 | } |
1234 | else if (!popts->memctl_interleaving && popts->ba_intlv_ctl) { | |
1235 | /* | |
1236 | * If memory interleaving between controllers is NOT | |
1237 | * enabled, the starting address for each memory | |
1238 | * controller is distinct. However, because rank | |
1239 | * interleaving is enabled, the starting and ending | |
1240 | * addresses of the total memory on that memory | |
1241 | * controller needs to be programmed into its | |
1242 | * respective CS0_BNDS. | |
1243 | */ | |
dbbbb3ab HW |
1244 | unsigned long long rank_density |
1245 | = dimm_params[i/2].rank_density; | |
1246 | switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) { | |
1247 | case FSL_DDR_CS0_CS1_CS2_CS3: | |
1248 | /* CS0+CS1+CS2+CS3 interleaving, only CS0_CNDS | |
1249 | * needs to be set. | |
1250 | */ | |
1251 | sa = common_dimm->base_address; | |
1252 | ea = sa + (4 * (rank_density >> dbw_cap_adj))-1; | |
1253 | break; | |
1254 | case FSL_DDR_CS0_CS1_AND_CS2_CS3: | |
1255 | /* CS0+CS1 and CS2+CS3 interleaving, CS0_CNDS | |
1256 | * and CS2_CNDS need to be set. | |
1257 | */ | |
1258 | if (!(i&1)) { | |
1259 | sa = dimm_params[i/2].base_address; | |
1260 | ea = sa + (i * (rank_density >> | |
1261 | dbw_cap_adj)) - 1; | |
1262 | } | |
1263 | break; | |
1264 | case FSL_DDR_CS0_CS1: | |
1265 | /* CS0+CS1 interleaving, CS0_CNDS needs | |
1266 | * to be set | |
1267 | */ | |
1268 | sa = common_dimm->base_address; | |
1269 | ea = sa + (2 * (rank_density >> dbw_cap_adj))-1; | |
1270 | break; | |
1271 | case FSL_DDR_CS2_CS3: | |
1272 | /* CS2+CS3 interleaving*/ | |
1273 | if (i == 2) { | |
1274 | sa = dimm_params[i/2].base_address; | |
1275 | ea = sa + (2 * (rank_density >> | |
1276 | dbw_cap_adj)) - 1; | |
1277 | } | |
1278 | break; | |
1279 | default: /* No bank(chip-select) interleaving */ | |
1280 | break; | |
1281 | } | |
58e5e9af KG |
1282 | } |
1283 | else if (popts->memctl_interleaving && !popts->ba_intlv_ctl) { | |
1284 | /* | |
1285 | * Only the rank on CS0 of each memory controller may | |
1286 | * be used if memory controller interleaving is used | |
1287 | * without rank interleaving within each memory | |
1288 | * controller. However, the ending address programmed | |
1289 | * into each CS0 must be the sum of the amount of | |
1290 | * memory in the two CS0 ranks. | |
1291 | */ | |
1292 | if (i == 0) { | |
1293 | unsigned long long rank_density | |
1294 | = dimm_params[0].rank_density; | |
1295 | ea = (2 * (rank_density >> dbw_cap_adj)) - 1; | |
1296 | } | |
1297 | ||
1298 | } | |
1299 | else if (!popts->memctl_interleaving && !popts->ba_intlv_ctl) { | |
1300 | /* | |
1301 | * No rank interleaving and no memory controller | |
1302 | * interleaving. | |
1303 | */ | |
1304 | unsigned long long rank_density | |
1305 | = dimm_params[i/2].rank_density; | |
1306 | sa = dimm_params[i/2].base_address; | |
1307 | ea = sa + (rank_density >> dbw_cap_adj) - 1; | |
1308 | if (i&1) { | |
1309 | if ((dimm_params[i/2].n_ranks == 1)) { | |
1310 | /* Odd chip select, single-rank dimm */ | |
1311 | sa = 0; | |
1312 | ea = 0; | |
1313 | } else { | |
1314 | /* Odd chip select, dual-rank DIMM */ | |
1315 | sa += rank_density >> dbw_cap_adj; | |
1316 | ea += rank_density >> dbw_cap_adj; | |
1317 | } | |
1318 | } | |
1319 | } | |
1320 | ||
1321 | sa >>= 24; | |
1322 | ea >>= 24; | |
1323 | ||
1324 | ddr->cs[i].bnds = (0 | |
1325 | | ((sa & 0xFFF) << 16) /* starting address MSB */ | |
1326 | | ((ea & 0xFFF) << 0) /* ending address MSB */ | |
1327 | ); | |
1328 | ||
1f293b41 | 1329 | debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds); |
58e5e9af KG |
1330 | set_csn_config(i, ddr, popts, dimm_params); |
1331 | set_csn_config_2(i, ddr); | |
1332 | } | |
1333 | ||
c360ceac | 1334 | #if !defined(CONFIG_FSL_DDR1) |
58e5e9af KG |
1335 | set_timing_cfg_0(ddr); |
1336 | #endif | |
1337 | ||
c360ceac DL |
1338 | set_timing_cfg_3(ddr, common_dimm, cas_latency); |
1339 | set_timing_cfg_1(ddr, popts, common_dimm, cas_latency); | |
58e5e9af KG |
1340 | set_timing_cfg_2(ddr, popts, common_dimm, |
1341 | cas_latency, additive_latency); | |
1342 | ||
1343 | set_ddr_sdram_cfg(ddr, popts, common_dimm); | |
1344 | ||
1345 | set_ddr_sdram_cfg_2(ddr, popts); | |
1346 | set_ddr_sdram_mode(ddr, popts, common_dimm, | |
1347 | cas_latency, additive_latency); | |
1aa3d08a | 1348 | set_ddr_sdram_mode_2(ddr, popts); |
58e5e9af KG |
1349 | set_ddr_sdram_interval(ddr, popts, common_dimm); |
1350 | set_ddr_data_init(ddr); | |
1351 | set_ddr_sdram_clk_cntl(ddr, popts); | |
1352 | set_ddr_init_addr(ddr); | |
1353 | set_ddr_init_ext_addr(ddr); | |
ec145e87 | 1354 | set_timing_cfg_4(ddr, popts); |
58e5e9af KG |
1355 | set_timing_cfg_5(ddr); |
1356 | ||
c360ceac | 1357 | set_ddr_zq_cntl(ddr, zq_en); |
bdc9f7b5 | 1358 | set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts); |
58e5e9af | 1359 | |
22cca7e1 | 1360 | set_ddr_sr_cntr(ddr, sr_it); |
58e5e9af KG |
1361 | |
1362 | set_ddr_sdram_rcw_1(ddr); | |
1363 | set_ddr_sdram_rcw_2(ddr); | |
1364 | ||
1365 | return check_fsl_memctl_config_regs(ddr); | |
1366 | } |