]>
Commit | Line | Data |
---|---|---|
58e5e9af | 1 | /* |
45064adc | 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 | #include <common.h> | |
10 | #include <asm/fsl_ddr_sdram.h> | |
11 | ||
12 | #include "ddr.h" | |
13 | ||
c360ceac DL |
14 | unsigned int |
15 | compute_cas_latency_ddr3(const dimm_params_t *dimm_params, | |
16 | common_timing_params_t *outpdimm, | |
17 | unsigned int number_of_dimms) | |
18 | { | |
19 | unsigned int i; | |
20 | unsigned int tAAmin_ps = 0; | |
21 | unsigned int tCKmin_X_ps = 0; | |
22 | unsigned int common_caslat; | |
23 | unsigned int caslat_actual; | |
24 | unsigned int retry = 16; | |
25 | unsigned int tmp; | |
26 | const unsigned int mclk_ps = get_memory_clk_period_ps(); | |
27 | ||
28 | /* compute the common CAS latency supported between slots */ | |
29 | tmp = dimm_params[0].caslat_X; | |
7e4db27f YS |
30 | for (i = 1; i < number_of_dimms; i++) { |
31 | if (dimm_params[i].n_ranks) | |
32 | tmp &= dimm_params[i].caslat_X; | |
33 | } | |
c360ceac DL |
34 | common_caslat = tmp; |
35 | ||
36 | /* compute the max tAAmin tCKmin between slots */ | |
37 | for (i = 0; i < number_of_dimms; i++) { | |
38 | tAAmin_ps = max(tAAmin_ps, dimm_params[i].tAA_ps); | |
39 | tCKmin_X_ps = max(tCKmin_X_ps, dimm_params[i].tCKmin_X_ps); | |
40 | } | |
41 | /* validate if the memory clk is in the range of dimms */ | |
42 | if (mclk_ps < tCKmin_X_ps) { | |
d49f8e04 YS |
43 | printf("DDR clock (MCLK cycle %u ps) is faster than " |
44 | "the slowest DIMM(s) (tCKmin %u ps) can support.\n", | |
45 | mclk_ps, tCKmin_X_ps); | |
c360ceac DL |
46 | return 1; |
47 | } | |
48 | /* determine the acutal cas latency */ | |
49 | caslat_actual = (tAAmin_ps + mclk_ps - 1) / mclk_ps; | |
50 | /* check if the dimms support the CAS latency */ | |
51 | while (!(common_caslat & (1 << caslat_actual)) && retry > 0) { | |
52 | caslat_actual++; | |
53 | retry--; | |
54 | } | |
55 | /* once the caculation of caslat_actual is completed | |
56 | * we must verify that this CAS latency value does not | |
57 | * exceed tAAmax, which is 20 ns for all DDR3 speed grades | |
58 | */ | |
59 | if (caslat_actual * mclk_ps > 20000) { | |
60 | printf("The choosen cas latency %d is too large\n", | |
61 | caslat_actual); | |
62 | return 1; | |
63 | } | |
64 | outpdimm->lowest_common_SPD_caslat = caslat_actual; | |
65 | ||
66 | return 0; | |
67 | } | |
68 | ||
58e5e9af KG |
69 | /* |
70 | * compute_lowest_common_dimm_parameters() | |
71 | * | |
72 | * Determine the worst-case DIMM timing parameters from the set of DIMMs | |
73 | * whose parameters have been computed into the array pointed to | |
74 | * by dimm_params. | |
75 | */ | |
76 | unsigned int | |
77 | compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params, | |
78 | common_timing_params_t *outpdimm, | |
123922b1 | 79 | const unsigned int number_of_dimms) |
58e5e9af | 80 | { |
9490ff48 | 81 | unsigned int i, j; |
58e5e9af KG |
82 | |
83 | unsigned int tCKmin_X_ps = 0; | |
84 | unsigned int tCKmax_ps = 0xFFFFFFFF; | |
85 | unsigned int tCKmax_max_ps = 0; | |
86 | unsigned int tRCD_ps = 0; | |
87 | unsigned int tRP_ps = 0; | |
88 | unsigned int tRAS_ps = 0; | |
89 | unsigned int tWR_ps = 0; | |
90 | unsigned int tWTR_ps = 0; | |
91 | unsigned int tRFC_ps = 0; | |
92 | unsigned int tRRD_ps = 0; | |
93 | unsigned int tRC_ps = 0; | |
94 | unsigned int refresh_rate_ps = 0; | |
95 | unsigned int tIS_ps = 0; | |
96 | unsigned int tIH_ps = 0; | |
97 | unsigned int tDS_ps = 0; | |
98 | unsigned int tDH_ps = 0; | |
99 | unsigned int tRTP_ps = 0; | |
100 | unsigned int tDQSQ_max_ps = 0; | |
101 | unsigned int tQHS_ps = 0; | |
102 | ||
dd127689 | 103 | unsigned int temp1, temp2; |
58e5e9af | 104 | unsigned int additive_latency = 0; |
c360ceac | 105 | #if !defined(CONFIG_FSL_DDR3) |
58e5e9af | 106 | const unsigned int mclk_ps = get_memory_clk_period_ps(); |
c360ceac | 107 | unsigned int lowest_good_caslat; |
58e5e9af KG |
108 | unsigned int not_ok; |
109 | ||
110 | debug("using mclk_ps = %u\n", mclk_ps); | |
c360ceac | 111 | #endif |
58e5e9af KG |
112 | |
113 | temp1 = 0; | |
114 | for (i = 0; i < number_of_dimms; i++) { | |
115 | /* | |
116 | * If there are no ranks on this DIMM, | |
117 | * it probably doesn't exist, so skip it. | |
118 | */ | |
119 | if (dimm_params[i].n_ranks == 0) { | |
120 | temp1++; | |
121 | continue; | |
122 | } | |
5800e7ab YS |
123 | if (dimm_params[i].n_ranks == 4 && i != 0) { |
124 | printf("Found Quad-rank DIMM in wrong bank, ignored." | |
125 | " Software may not run as expected.\n"); | |
126 | temp1++; | |
127 | continue; | |
128 | } | |
123922b1 YS |
129 | |
130 | /* | |
131 | * check if quad-rank DIMM is plugged if | |
132 | * CONFIG_CHIP_SELECT_QUAD_CAPABLE is not defined | |
133 | * Only the board with proper design is capable | |
134 | */ | |
135 | #ifndef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE | |
5800e7ab YS |
136 | if (dimm_params[i].n_ranks == 4 && \ |
137 | CONFIG_CHIP_SELECTS_PER_CTRL/CONFIG_DIMM_SLOTS_PER_CTLR < 4) { | |
138 | printf("Found Quad-rank DIMM, not able to support."); | |
139 | temp1++; | |
140 | continue; | |
141 | } | |
123922b1 | 142 | #endif |
58e5e9af KG |
143 | /* |
144 | * Find minimum tCKmax_ps to find fastest slow speed, | |
145 | * i.e., this is the slowest the whole system can go. | |
146 | */ | |
147 | tCKmax_ps = min(tCKmax_ps, dimm_params[i].tCKmax_ps); | |
148 | ||
149 | /* Either find maximum value to determine slowest | |
150 | * speed, delay, time, period, etc */ | |
151 | tCKmin_X_ps = max(tCKmin_X_ps, dimm_params[i].tCKmin_X_ps); | |
152 | tCKmax_max_ps = max(tCKmax_max_ps, dimm_params[i].tCKmax_ps); | |
153 | tRCD_ps = max(tRCD_ps, dimm_params[i].tRCD_ps); | |
154 | tRP_ps = max(tRP_ps, dimm_params[i].tRP_ps); | |
155 | tRAS_ps = max(tRAS_ps, dimm_params[i].tRAS_ps); | |
156 | tWR_ps = max(tWR_ps, dimm_params[i].tWR_ps); | |
157 | tWTR_ps = max(tWTR_ps, dimm_params[i].tWTR_ps); | |
158 | tRFC_ps = max(tRFC_ps, dimm_params[i].tRFC_ps); | |
159 | tRRD_ps = max(tRRD_ps, dimm_params[i].tRRD_ps); | |
160 | tRC_ps = max(tRC_ps, dimm_params[i].tRC_ps); | |
161 | tIS_ps = max(tIS_ps, dimm_params[i].tIS_ps); | |
162 | tIH_ps = max(tIH_ps, dimm_params[i].tIH_ps); | |
163 | tDS_ps = max(tDS_ps, dimm_params[i].tDS_ps); | |
164 | tDH_ps = max(tDH_ps, dimm_params[i].tDH_ps); | |
165 | tRTP_ps = max(tRTP_ps, dimm_params[i].tRTP_ps); | |
166 | tQHS_ps = max(tQHS_ps, dimm_params[i].tQHS_ps); | |
167 | refresh_rate_ps = max(refresh_rate_ps, | |
168 | dimm_params[i].refresh_rate_ps); | |
169 | ||
170 | /* | |
171 | * Find maximum tDQSQ_max_ps to find slowest. | |
172 | * | |
173 | * FIXME: is finding the slowest value the correct | |
174 | * strategy for this parameter? | |
175 | */ | |
176 | tDQSQ_max_ps = max(tDQSQ_max_ps, dimm_params[i].tDQSQ_max_ps); | |
177 | } | |
178 | ||
179 | outpdimm->ndimms_present = number_of_dimms - temp1; | |
180 | ||
181 | if (temp1 == number_of_dimms) { | |
182 | debug("no dimms this memory controller\n"); | |
183 | return 0; | |
184 | } | |
185 | ||
186 | outpdimm->tCKmin_X_ps = tCKmin_X_ps; | |
187 | outpdimm->tCKmax_ps = tCKmax_ps; | |
188 | outpdimm->tCKmax_max_ps = tCKmax_max_ps; | |
189 | outpdimm->tRCD_ps = tRCD_ps; | |
190 | outpdimm->tRP_ps = tRP_ps; | |
191 | outpdimm->tRAS_ps = tRAS_ps; | |
192 | outpdimm->tWR_ps = tWR_ps; | |
193 | outpdimm->tWTR_ps = tWTR_ps; | |
194 | outpdimm->tRFC_ps = tRFC_ps; | |
195 | outpdimm->tRRD_ps = tRRD_ps; | |
196 | outpdimm->tRC_ps = tRC_ps; | |
197 | outpdimm->refresh_rate_ps = refresh_rate_ps; | |
198 | outpdimm->tIS_ps = tIS_ps; | |
199 | outpdimm->tIH_ps = tIH_ps; | |
200 | outpdimm->tDS_ps = tDS_ps; | |
201 | outpdimm->tDH_ps = tDH_ps; | |
202 | outpdimm->tRTP_ps = tRTP_ps; | |
203 | outpdimm->tDQSQ_max_ps = tDQSQ_max_ps; | |
204 | outpdimm->tQHS_ps = tQHS_ps; | |
205 | ||
206 | /* Determine common burst length for all DIMMs. */ | |
207 | temp1 = 0xff; | |
208 | for (i = 0; i < number_of_dimms; i++) { | |
209 | if (dimm_params[i].n_ranks) { | |
210 | temp1 &= dimm_params[i].burst_lengths_bitmask; | |
211 | } | |
212 | } | |
213 | outpdimm->all_DIMMs_burst_lengths_bitmask = temp1; | |
214 | ||
215 | /* Determine if all DIMMs registered buffered. */ | |
216 | temp1 = temp2 = 0; | |
217 | for (i = 0; i < number_of_dimms; i++) { | |
218 | if (dimm_params[i].n_ranks) { | |
c399765d | 219 | if (dimm_params[i].registered_dimm) { |
58e5e9af | 220 | temp1 = 1; |
c399765d YS |
221 | printf("Detected RDIMM %s\n", |
222 | dimm_params[i].mpart); | |
223 | } else { | |
58e5e9af | 224 | temp2 = 1; |
c399765d YS |
225 | printf("Detected UDIMM %s\n", |
226 | dimm_params[i].mpart); | |
227 | } | |
58e5e9af KG |
228 | } |
229 | } | |
230 | ||
231 | outpdimm->all_DIMMs_registered = 0; | |
dd127689 | 232 | outpdimm->all_DIMMs_unbuffered = 0; |
58e5e9af KG |
233 | if (temp1 && !temp2) { |
234 | outpdimm->all_DIMMs_registered = 1; | |
dd127689 | 235 | } else if (!temp1 && temp2) { |
58e5e9af | 236 | outpdimm->all_DIMMs_unbuffered = 1; |
dd127689 | 237 | } else { |
58e5e9af KG |
238 | printf("ERROR: Mix of registered buffered and unbuffered " |
239 | "DIMMs detected!\n"); | |
240 | } | |
241 | ||
9490ff48 YS |
242 | temp1 = 0; |
243 | if (outpdimm->all_DIMMs_registered) | |
244 | for (j = 0; j < 16; j++) { | |
245 | outpdimm->rcw[j] = dimm_params[0].rcw[j]; | |
123922b1 YS |
246 | for (i = 1; i < number_of_dimms; i++) { |
247 | if (!dimm_params[i].n_ranks) | |
248 | continue; | |
9490ff48 | 249 | if (dimm_params[i].rcw[j] != dimm_params[0].rcw[j]) { |
dd127689 | 250 | temp1 = 1; |
9490ff48 YS |
251 | break; |
252 | } | |
123922b1 | 253 | } |
9490ff48 YS |
254 | } |
255 | ||
256 | if (temp1 != 0) | |
257 | printf("ERROR: Mix different RDIMM detected!\n"); | |
258 | ||
c360ceac DL |
259 | #if defined(CONFIG_FSL_DDR3) |
260 | if (compute_cas_latency_ddr3(dimm_params, outpdimm, number_of_dimms)) | |
261 | return 1; | |
262 | #else | |
58e5e9af KG |
263 | /* |
264 | * Compute a CAS latency suitable for all DIMMs | |
265 | * | |
266 | * Strategy for SPD-defined latencies: compute only | |
267 | * CAS latency defined by all DIMMs. | |
268 | */ | |
269 | ||
270 | /* | |
271 | * Step 1: find CAS latency common to all DIMMs using bitwise | |
272 | * operation. | |
273 | */ | |
274 | temp1 = 0xFF; | |
275 | for (i = 0; i < number_of_dimms; i++) { | |
276 | if (dimm_params[i].n_ranks) { | |
277 | temp2 = 0; | |
278 | temp2 |= 1 << dimm_params[i].caslat_X; | |
279 | temp2 |= 1 << dimm_params[i].caslat_X_minus_1; | |
280 | temp2 |= 1 << dimm_params[i].caslat_X_minus_2; | |
281 | /* | |
282 | * FIXME: If there was no entry for X-2 (X-1) in | |
283 | * the SPD, then caslat_X_minus_2 | |
284 | * (caslat_X_minus_1) contains either 255 or | |
285 | * 0xFFFFFFFF because that's what the glorious | |
286 | * __ilog2 function returns for an input of 0. | |
287 | * On 32-bit PowerPC, left shift counts with bit | |
288 | * 26 set (that the value of 255 or 0xFFFFFFFF | |
289 | * will have), cause the destination register to | |
290 | * be 0. That is why this works. | |
291 | */ | |
292 | temp1 &= temp2; | |
293 | } | |
294 | } | |
295 | ||
296 | /* | |
297 | * Step 2: check each common CAS latency against tCK of each | |
298 | * DIMM's SPD. | |
299 | */ | |
300 | lowest_good_caslat = 0; | |
301 | temp2 = 0; | |
302 | while (temp1) { | |
303 | not_ok = 0; | |
304 | temp2 = __ilog2(temp1); | |
305 | debug("checking common caslat = %u\n", temp2); | |
306 | ||
307 | /* Check if this CAS latency will work on all DIMMs at tCK. */ | |
308 | for (i = 0; i < number_of_dimms; i++) { | |
309 | if (!dimm_params[i].n_ranks) { | |
310 | continue; | |
311 | } | |
312 | if (dimm_params[i].caslat_X == temp2) { | |
313 | if (mclk_ps >= dimm_params[i].tCKmin_X_ps) { | |
314 | debug("CL = %u ok on DIMM %u at tCK=%u" | |
315 | " ps with its tCKmin_X_ps of %u\n", | |
316 | temp2, i, mclk_ps, | |
317 | dimm_params[i].tCKmin_X_ps); | |
318 | continue; | |
319 | } else { | |
320 | not_ok++; | |
321 | } | |
322 | } | |
323 | ||
324 | if (dimm_params[i].caslat_X_minus_1 == temp2) { | |
325 | unsigned int tCKmin_X_minus_1_ps | |
326 | = dimm_params[i].tCKmin_X_minus_1_ps; | |
327 | if (mclk_ps >= tCKmin_X_minus_1_ps) { | |
328 | debug("CL = %u ok on DIMM %u at " | |
329 | "tCK=%u ps with its " | |
330 | "tCKmin_X_minus_1_ps of %u\n", | |
331 | temp2, i, mclk_ps, | |
332 | tCKmin_X_minus_1_ps); | |
333 | continue; | |
334 | } else { | |
335 | not_ok++; | |
336 | } | |
337 | } | |
338 | ||
339 | if (dimm_params[i].caslat_X_minus_2 == temp2) { | |
340 | unsigned int tCKmin_X_minus_2_ps | |
341 | = dimm_params[i].tCKmin_X_minus_2_ps; | |
342 | if (mclk_ps >= tCKmin_X_minus_2_ps) { | |
343 | debug("CL = %u ok on DIMM %u at " | |
344 | "tCK=%u ps with its " | |
345 | "tCKmin_X_minus_2_ps of %u\n", | |
346 | temp2, i, mclk_ps, | |
347 | tCKmin_X_minus_2_ps); | |
348 | continue; | |
349 | } else { | |
350 | not_ok++; | |
351 | } | |
352 | } | |
353 | } | |
354 | ||
355 | if (!not_ok) { | |
356 | lowest_good_caslat = temp2; | |
357 | } | |
358 | ||
359 | temp1 &= ~(1 << temp2); | |
360 | } | |
361 | ||
362 | debug("lowest common SPD-defined CAS latency = %u\n", | |
363 | lowest_good_caslat); | |
364 | outpdimm->lowest_common_SPD_caslat = lowest_good_caslat; | |
365 | ||
366 | ||
367 | /* | |
368 | * Compute a common 'de-rated' CAS latency. | |
369 | * | |
370 | * The strategy here is to find the *highest* dereated cas latency | |
371 | * with the assumption that all of the DIMMs will support a dereated | |
372 | * CAS latency higher than or equal to their lowest dereated value. | |
373 | */ | |
374 | temp1 = 0; | |
375 | for (i = 0; i < number_of_dimms; i++) { | |
376 | temp1 = max(temp1, dimm_params[i].caslat_lowest_derated); | |
377 | } | |
378 | outpdimm->highest_common_derated_caslat = temp1; | |
379 | debug("highest common dereated CAS latency = %u\n", temp1); | |
c360ceac | 380 | #endif /* #if defined(CONFIG_FSL_DDR3) */ |
58e5e9af KG |
381 | |
382 | /* Determine if all DIMMs ECC capable. */ | |
383 | temp1 = 1; | |
384 | for (i = 0; i < number_of_dimms; i++) { | |
08b3f759 YS |
385 | if (dimm_params[i].n_ranks && |
386 | !(dimm_params[i].edc_config & EDC_ECC)) { | |
58e5e9af KG |
387 | temp1 = 0; |
388 | break; | |
389 | } | |
390 | } | |
391 | if (temp1) { | |
392 | debug("all DIMMs ECC capable\n"); | |
393 | } else { | |
394 | debug("Warning: not all DIMMs ECC capable, cant enable ECC\n"); | |
395 | } | |
396 | outpdimm->all_DIMMs_ECC_capable = temp1; | |
397 | ||
c360ceac | 398 | #ifndef CONFIG_FSL_DDR3 |
58e5e9af KG |
399 | /* FIXME: move to somewhere else to validate. */ |
400 | if (mclk_ps > tCKmax_max_ps) { | |
401 | printf("Warning: some of the installed DIMMs " | |
402 | "can not operate this slowly.\n"); | |
403 | return 1; | |
404 | } | |
c360ceac | 405 | #endif |
58e5e9af KG |
406 | /* |
407 | * Compute additive latency. | |
408 | * | |
409 | * For DDR1, additive latency should be 0. | |
410 | * | |
411 | * For DDR2, with ODT enabled, use "a value" less than ACTTORW, | |
412 | * which comes from Trcd, and also note that: | |
413 | * add_lat + caslat must be >= 4 | |
414 | * | |
c360ceac | 415 | * For DDR3, we use the AL=0 |
58e5e9af KG |
416 | * |
417 | * When to use additive latency for DDR2: | |
418 | * | |
419 | * I. Because you are using CL=3 and need to do ODT on writes and | |
420 | * want functionality. | |
421 | * 1. Are you going to use ODT? (Does your board not have | |
422 | * additional termination circuitry for DQ, DQS, DQS_, | |
423 | * DM, RDQS, RDQS_ for x4/x8 configs?) | |
424 | * 2. If so, is your lowest supported CL going to be 3? | |
425 | * 3. If so, then you must set AL=1 because | |
426 | * | |
427 | * WL >= 3 for ODT on writes | |
428 | * RL = AL + CL | |
429 | * WL = RL - 1 | |
430 | * -> | |
431 | * WL = AL + CL - 1 | |
432 | * AL + CL - 1 >= 3 | |
433 | * AL + CL >= 4 | |
434 | * QED | |
435 | * | |
436 | * RL >= 3 for ODT on reads | |
437 | * RL = AL + CL | |
438 | * | |
439 | * Since CL aren't usually less than 2, AL=0 is a minimum, | |
440 | * so the WL-derived AL should be the -- FIXME? | |
441 | * | |
442 | * II. Because you are using auto-precharge globally and want to | |
443 | * use additive latency (posted CAS) to get more bandwidth. | |
444 | * 1. Are you going to use auto-precharge mode globally? | |
445 | * | |
446 | * Use addtivie latency and compute AL to be 1 cycle less than | |
447 | * tRCD, i.e. the READ or WRITE command is in the cycle | |
448 | * immediately following the ACTIVATE command.. | |
449 | * | |
450 | * III. Because you feel like it or want to do some sort of | |
451 | * degraded-performance experiment. | |
452 | * 1. Do you just want to use additive latency because you feel | |
453 | * like it? | |
454 | * | |
455 | * Validation: AL is less than tRCD, and within the other | |
456 | * read-to-precharge constraints. | |
457 | */ | |
458 | ||
459 | additive_latency = 0; | |
460 | ||
461 | #if defined(CONFIG_FSL_DDR2) | |
462 | if (lowest_good_caslat < 4) { | |
4e57382f YS |
463 | additive_latency = (picos_to_mclk(tRCD_ps) > lowest_good_caslat) |
464 | ? picos_to_mclk(tRCD_ps) - lowest_good_caslat : 0; | |
58e5e9af KG |
465 | if (mclk_to_picos(additive_latency) > tRCD_ps) { |
466 | additive_latency = picos_to_mclk(tRCD_ps); | |
467 | debug("setting additive_latency to %u because it was " | |
468 | " greater than tRCD_ps\n", additive_latency); | |
469 | } | |
470 | } | |
471 | ||
472 | #elif defined(CONFIG_FSL_DDR3) | |
c360ceac DL |
473 | /* |
474 | * The system will not use the global auto-precharge mode. | |
475 | * However, it uses the page mode, so we set AL=0 | |
476 | */ | |
477 | additive_latency = 0; | |
58e5e9af KG |
478 | #endif |
479 | ||
480 | /* | |
481 | * Validate additive latency | |
482 | * FIXME: move to somewhere else to validate | |
483 | * | |
484 | * AL <= tRCD(min) | |
485 | */ | |
486 | if (mclk_to_picos(additive_latency) > tRCD_ps) { | |
487 | printf("Error: invalid additive latency exceeds tRCD(min).\n"); | |
488 | return 1; | |
489 | } | |
490 | ||
491 | /* | |
492 | * RL = CL + AL; RL >= 3 for ODT_RD_CFG to be enabled | |
493 | * WL = RL - 1; WL >= 3 for ODT_WL_CFG to be enabled | |
494 | * ADD_LAT (the register) must be set to a value less | |
495 | * than ACTTORW if WL = 1, then AL must be set to 1 | |
496 | * RD_TO_PRE (the register) must be set to a minimum | |
497 | * tRTP + AL if AL is nonzero | |
498 | */ | |
499 | ||
500 | /* | |
501 | * Additive latency will be applied only if the memctl option to | |
502 | * use it. | |
503 | */ | |
504 | outpdimm->additive_latency = additive_latency; | |
505 | ||
45064adc YS |
506 | debug("tCKmin_ps = %u\n", outpdimm->tCKmin_X_ps); |
507 | debug("tRCD_ps = %u\n", outpdimm->tRCD_ps); | |
508 | debug("tRP_ps = %u\n", outpdimm->tRP_ps); | |
509 | debug("tRAS_ps = %u\n", outpdimm->tRAS_ps); | |
510 | debug("tWR_ps = %u\n", outpdimm->tWR_ps); | |
511 | debug("tWTR_ps = %u\n", outpdimm->tWTR_ps); | |
512 | debug("tRFC_ps = %u\n", outpdimm->tRFC_ps); | |
513 | debug("tRRD_ps = %u\n", outpdimm->tRRD_ps); | |
514 | debug("tRC_ps = %u\n", outpdimm->tRC_ps); | |
515 | ||
58e5e9af KG |
516 | return 0; |
517 | } |