1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) Marvell International Ltd. and its affiliates
4 */
5
6 #include <common.h>
7 #include <i2c.h>
8 #include <spl.h>
9 #include <asm/io.h>
10 #include <asm/arch/cpu.h>
11 #include <asm/arch/soc.h>
12
13 #include "ddr3_hw_training.h"
14
15 /*
16 * Debug
17 */
18 #define DEBUG_DQS_C(s, d, l) \
19 DEBUG_DQS_S(s); DEBUG_DQS_D(d, l); DEBUG_DQS_S("\n")
20 #define DEBUG_DQS_FULL_C(s, d, l) \
21 DEBUG_DQS_FULL_S(s); DEBUG_DQS_FULL_D(d, l); DEBUG_DQS_FULL_S("\n")
22 #define DEBUG_DQS_RESULTS_C(s, d, l) \
23 DEBUG_DQS_RESULTS_S(s); DEBUG_DQS_RESULTS_D(d, l); DEBUG_DQS_RESULTS_S("\n")
24 #define DEBUG_PER_DQ_C(s, d, l) \
25 puts(s); printf("%x", d); puts("\n")
26
27 #define DEBUG_DQS_RESULTS_S(s) \
28 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
29 #define DEBUG_DQS_RESULTS_D(d, l) \
30 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
31
32 #define DEBUG_PER_DQ_S(s) \
33 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%s", s)
34 #define DEBUG_PER_DQ_D(d, l) \
35 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%x", d)
36 #define DEBUG_PER_DQ_DD(d, l) \
37 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%d", d)
38
39 #ifdef MV_DEBUG_DQS
40 #define DEBUG_DQS_S(s) puts(s)
41 #define DEBUG_DQS_D(d, l) printf("%x", d)
42 #else
43 #define DEBUG_DQS_S(s)
44 #define DEBUG_DQS_D(d, l)
45 #endif
46
47 #ifdef MV_DEBUG_DQS_FULL
48 #define DEBUG_DQS_FULL_S(s) puts(s)
49 #define DEBUG_DQS_FULL_D(d, l) printf("%x", d)
50 #else
51 #define DEBUG_DQS_FULL_S(s)
52 #define DEBUG_DQS_FULL_D(d, l)
53 #endif
54
55 /* State machine for centralization - find low & high limit */
56 enum {
57 PUP_ADLL_LIMITS_STATE_FAIL,
58 PUP_ADLL_LIMITS_STATE_PASS,
59 PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS,
60 };
61
62 /* Hold centralization low results */
63 static int centralization_low_limit[MAX_PUP_NUM] = { 0 };
64 /* Hold centralization high results */
65 static int centralization_high_limit[MAX_PUP_NUM] = { 0 };
66
67 int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx);
68 int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
69 int *size_valid);
70 static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
71 int is_tx);
72 int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
73 int is_tx, u32 special_pattern_pup);
74 int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
75 int is_tx, u32 special_pattern_pup);
76 int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
77 int is_tx);
78
79 #ifdef MV88F78X60
80 extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
81 extern u32 killer_pattern_64b[DQ_NUM][LEN_SPECIAL_PATTERN];
82 extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
83 #else
84 extern u32 killer_pattern[DQ_NUM][LEN_16BIT_KILLER_PATTERN];
85 extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
86 #if defined(MV88F672X)
87 extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
88 #endif
89 #endif
90 extern u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN];
91
ddr3_dqs_choose_pattern(MV_DRAM_INFO * dram_info,u32 victim_dq)92 static u32 *ddr3_dqs_choose_pattern(MV_DRAM_INFO *dram_info, u32 victim_dq)
93 {
94 u32 *pattern_ptr;
95
96 /* Choose pattern */
97 switch (dram_info->ddr_width) {
98 #if defined(MV88F672X)
99 case 16:
100 pattern_ptr = (u32 *)&killer_pattern[victim_dq];
101 break;
102 #endif
103 case 32:
104 pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
105 break;
106 #if defined(MV88F78X60)
107 case 64:
108 pattern_ptr = (u32 *)&killer_pattern_64b[victim_dq];
109 break;
110 #endif
111 default:
112 #if defined(MV88F78X60)
113 pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
114 #else
115 pattern_ptr = (u32 *)&killer_pattern[victim_dq];
116 #endif
117 break;
118 }
119
120 return pattern_ptr;
121 }
122
123 /*
124 * Name: ddr3_dqs_centralization_rx
125 * Desc: Execute the DQS centralization RX phase.
126 * Args: dram_info
127 * Notes:
128 * Returns: MV_OK if success, other error code if fail.
129 */
ddr3_dqs_centralization_rx(MV_DRAM_INFO * dram_info)130 int ddr3_dqs_centralization_rx(MV_DRAM_INFO *dram_info)
131 {
132 u32 cs, ecc, reg;
133 int status;
134
135 DEBUG_DQS_S("DDR3 - DQS Centralization RX - Starting procedure\n");
136
137 /* Enable SW override */
138 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
139 (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
140
141 /* [0] = 1 - Enable SW override */
142 /* 0x15B8 - Training SW 2 Register */
143 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
144 DEBUG_DQS_S("DDR3 - DQS Centralization RX - SW Override Enabled\n");
145
146 reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
147 reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
148
149 /* Loop for each CS */
150 for (cs = 0; cs < MAX_CS; cs++) {
151 if (dram_info->cs_ena & (1 << cs)) {
152 DEBUG_DQS_FULL_C("DDR3 - DQS Centralization RX - CS - ",
153 (u32) cs, 1);
154
155 for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
156
157 /* ECC Support - Switch ECC Mux on ecc=1 */
158 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
159 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
160 reg |= (dram_info->ecc_ena *
161 ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
162 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
163
164 if (ecc)
165 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Enabled\n");
166 else
167 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Disabled\n");
168
169 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Find all limits\n");
170
171 status = ddr3_find_adll_limits(dram_info, cs,
172 ecc, 0);
173 if (MV_OK != status)
174 return status;
175
176 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Start calculating center\n");
177
178 status = ddr3_center_calc(dram_info, cs, ecc,
179 0);
180 if (MV_OK != status)
181 return status;
182 }
183 }
184 }
185
186 /* ECC Support - Disable ECC MUX */
187 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
188 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
189 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
190
191 /* Disable SW override - Must be in a different stage */
192 /* [0]=0 - Enable SW override */
193 reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
194 reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
195 /* 0x15B8 - Training SW 2 Register */
196 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
197
198 reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
199 (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
200 reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
201
202 return MV_OK;
203 }
204
205 /*
206 * Name: ddr3_dqs_centralization_tx
207 * Desc: Execute the DQS centralization TX phase.
208 * Args: dram_info
209 * Notes:
210 * Returns: MV_OK if success, other error code if fail.
211 */
ddr3_dqs_centralization_tx(MV_DRAM_INFO * dram_info)212 int ddr3_dqs_centralization_tx(MV_DRAM_INFO *dram_info)
213 {
214 u32 cs, ecc, reg;
215 int status;
216
217 DEBUG_DQS_S("DDR3 - DQS Centralization TX - Starting procedure\n");
218
219 /* Enable SW override */
220 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
221 (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
222
223 /* [0] = 1 - Enable SW override */
224 /* 0x15B8 - Training SW 2 Register */
225 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
226 DEBUG_DQS_S("DDR3 - DQS Centralization TX - SW Override Enabled\n");
227
228 reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
229 reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
230
231 /* Loop for each CS */
232 for (cs = 0; cs < MAX_CS; cs++) {
233 if (dram_info->cs_ena & (1 << cs)) {
234 DEBUG_DQS_FULL_C("DDR3 - DQS Centralization TX - CS - ",
235 (u32) cs, 1);
236 for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
237 /* ECC Support - Switch ECC Mux on ecc=1 */
238 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
239 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
240 reg |= (dram_info->ecc_ena *
241 ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
242 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
243
244 if (ecc)
245 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Enabled\n");
246 else
247 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Disabled\n");
248
249 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Find all limits\n");
250
251 status = ddr3_find_adll_limits(dram_info, cs,
252 ecc, 1);
253 if (MV_OK != status)
254 return status;
255
256 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Start calculating center\n");
257
258 status = ddr3_center_calc(dram_info, cs, ecc,
259 1);
260 if (MV_OK != status)
261 return status;
262 }
263 }
264 }
265
266 /* ECC Support - Disable ECC MUX */
267 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
268 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
269 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
270
271 /* Disable SW override - Must be in a different stage */
272 /* [0]=0 - Enable SW override */
273 reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
274 reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
275 /* 0x15B8 - Training SW 2 Register */
276 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
277
278 reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
279 (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
280 reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
281
282 return MV_OK;
283 }
284
285 /*
286 * Name: ddr3_find_adll_limits
287 * Desc: Execute the Find ADLL limits phase.
288 * Args: dram_info
289 * cs
290 * ecc_ena
291 * is_tx Indicate whether Rx or Tx
292 * Notes:
293 * Returns: MV_OK if success, other error code if fail.
294 */
ddr3_find_adll_limits(MV_DRAM_INFO * dram_info,u32 cs,u32 ecc,int is_tx)295 int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx)
296 {
297 u32 victim_dq, pup, tmp;
298 u32 adll_addr;
299 u32 max_pup; /* maximal pup index */
300 u32 pup_mask = 0;
301 u32 unlock_pup; /* bit array of un locked pups */
302 u32 new_unlock_pup; /* bit array of compare failed pups */
303 u32 curr_adll;
304 u32 adll_start_val; /* adll start loop value - for rx or tx limit */
305 u32 high_limit; /* holds found High Limit */
306 u32 low_limit; /* holds found Low Limit */
307 int win_valid;
308 int update_win;
309 u32 sdram_offset;
310 u32 uj, cs_count, cs_tmp, ii;
311 u32 *pattern_ptr;
312 u32 dq;
313 u32 adll_end_val; /* adll end of loop val - for rx or tx limit */
314 u8 analog_pbs[DQ_NUM][MAX_PUP_NUM][DQ_NUM][2];
315 u8 analog_pbs_sum[MAX_PUP_NUM][DQ_NUM][2];
316 int pup_adll_limit_state[MAX_PUP_NUM]; /* hold state of each pup */
317
318 adll_addr = ((is_tx == 1) ? PUP_DQS_WR : PUP_DQS_RD);
319 adll_end_val = ((is_tx == 1) ? ADLL_MIN : ADLL_MAX);
320 adll_start_val = ((is_tx == 1) ? ADLL_MAX : ADLL_MIN);
321 max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
322
323 DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - Starting Find ADLL Limits\n");
324
325 /* init the array */
326 for (pup = 0; pup < max_pup; pup++) {
327 centralization_low_limit[pup] = ADLL_MIN;
328 centralization_high_limit[pup] = ADLL_MAX;
329 }
330
331 /* Killer Pattern */
332 cs_count = 0;
333 for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
334 if (dram_info->cs_ena & (1 << cs_tmp))
335 cs_count++;
336 }
337 sdram_offset = cs_count * (SDRAM_CS_SIZE + 1);
338 sdram_offset += ((is_tx == 1) ?
339 SDRAM_DQS_TX_OFFS : SDRAM_DQS_RX_OFFS);
340
341 /* Prepare pup masks */
342 for (pup = 0; pup < max_pup; pup++)
343 pup_mask |= (1 << pup);
344
345 for (pup = 0; pup < max_pup; pup++) {
346 for (dq = 0; dq < DQ_NUM; dq++) {
347 analog_pbs_sum[pup][dq][0] = adll_start_val;
348 analog_pbs_sum[pup][dq][1] = adll_end_val;
349 }
350 }
351
352 /* Loop - use different pattern for each victim_dq */
353 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
354 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Victim DQ - ",
355 (u32)victim_dq, 1);
356 /*
357 * The pups 3 bit arrays represent state machine. with
358 * 3 stages for each pup.
359 * 1. fail and didn't get pass in earlier compares.
360 * 2. pass compare
361 * 3. fail after pass - end state.
362 * The window limits are the adll values where the adll
363 * was in the pass stage.
364 */
365
366 /* Set all states to Fail (1st state) */
367 for (pup = 0; pup < max_pup; pup++)
368 pup_adll_limit_state[pup] = PUP_ADLL_LIMITS_STATE_FAIL;
369
370 /* Set current valid pups */
371 unlock_pup = pup_mask;
372
373 /* Set ADLL to start value */
374 curr_adll = adll_start_val;
375
376 #if defined(MV88F78X60)
377 for (pup = 0; pup < max_pup; pup++) {
378 for (dq = 0; dq < DQ_NUM; dq++) {
379 analog_pbs[victim_dq][pup][dq][0] =
380 adll_start_val;
381 analog_pbs[victim_dq][pup][dq][1] =
382 adll_end_val;
383 per_bit_data[pup][dq] = 0;
384 }
385 }
386 #endif
387
388 for (uj = 0; uj < ADLL_MAX; uj++) {
389 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Setting ADLL to ",
390 curr_adll, 2);
391 for (pup = 0; pup < max_pup; pup++) {
392 if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
393 tmp = ((is_tx == 1) ? curr_adll +
394 dram_info->wl_val[cs]
395 [pup * (1 - ecc) + ecc * ECC_PUP]
396 [D] : curr_adll);
397 ddr3_write_pup_reg(adll_addr, cs, pup +
398 (ecc * ECC_PUP), 0, tmp);
399 }
400 }
401
402 /* Choose pattern */
403 pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
404 victim_dq);
405
406 /* '1' - means pup failed, '0' - means pup pass */
407 new_unlock_pup = 0;
408
409 /* Read and compare results for Victim_DQ# */
410 for (ii = 0; ii < 3; ii++) {
411 u32 tmp = 0;
412 if (MV_OK != ddr3_sdram_dqs_compare(dram_info,
413 unlock_pup, &tmp,
414 pattern_ptr,
415 LEN_KILLER_PATTERN,
416 sdram_offset +
417 LEN_KILLER_PATTERN *
418 4 * victim_dq,
419 is_tx, 0, NULL,
420 0))
421 return MV_DDR3_TRAINING_ERR_DRAM_COMPARE;
422
423 new_unlock_pup |= tmp;
424 }
425
426 pup = 0;
427 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - UnlockPup: ",
428 unlock_pup, 2);
429 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - NewUnlockPup: ",
430 new_unlock_pup, 2);
431
432 /* Update pup state */
433 for (pup = 0; pup < max_pup; pup++) {
434 if (IS_PUP_ACTIVE(unlock_pup, pup) == 0) {
435 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Skipping pup ",
436 pup, 1);
437 continue;
438 }
439
440 /*
441 * Still didn't find the window limit of the pup
442 */
443 if (IS_PUP_ACTIVE(new_unlock_pup, pup) == 1) {
444 /* Current compare result == fail */
445 if (pup_adll_limit_state[pup] ==
446 PUP_ADLL_LIMITS_STATE_PASS) {
447 /*
448 * If now it failed but passed
449 * earlier
450 */
451 DEBUG_DQS_S("DDR3 - DQS Find Limits - PASS to FAIL: CS - ");
452 DEBUG_DQS_D(cs, 1);
453 DEBUG_DQS_S(", DQ - ");
454 DEBUG_DQS_D(victim_dq, 1);
455 DEBUG_DQS_S(", Pup - ");
456 DEBUG_DQS_D(pup, 1);
457 DEBUG_DQS_S(", ADLL - ");
458 DEBUG_DQS_D(curr_adll, 2);
459 DEBUG_DQS_S("\n");
460
461 #if defined(MV88F78X60)
462 for (dq = 0; dq < DQ_NUM; dq++) {
463 if ((analog_pbs[victim_dq][pup][dq][0] != adll_start_val)
464 && (analog_pbs[victim_dq][pup]
465 [dq][1] == adll_end_val))
466 analog_pbs
467 [victim_dq]
468 [pup][dq]
469 [1] =
470 curr_adll;
471 }
472 #endif
473 win_valid = 1;
474 update_win = 0;
475
476 /* Keep min / max limit value */
477 if (is_tx == 0) {
478 /* RX - found upper limit */
479 if (centralization_high_limit[pup] >
480 (curr_adll - 1)) {
481 high_limit =
482 curr_adll - 1;
483 low_limit =
484 centralization_low_limit[pup];
485 update_win = 1;
486 }
487 } else {
488 /* TX - found lower limit */
489 if (centralization_low_limit[pup] < (curr_adll + 1)) {
490 high_limit =
491 centralization_high_limit
492 [pup];
493 low_limit =
494 curr_adll + 1;
495 update_win =
496 1;
497 }
498 }
499
500 if (update_win == 1) {
501 /*
502 * Before updating
503 * window limits we need
504 * to check that the
505 * limits are valid
506 */
507 if (MV_OK !=
508 ddr3_check_window_limits
509 (pup, high_limit,
510 low_limit, is_tx,
511 &win_valid))
512 return MV_DDR3_TRAINING_ERR_WIN_LIMITS;
513
514 if (win_valid == 1) {
515 /*
516 * Window limits
517 * should be
518 * updated
519 */
520 centralization_low_limit
521 [pup] =
522 low_limit;
523 centralization_high_limit
524 [pup] =
525 high_limit;
526 }
527 }
528
529 if (win_valid == 1) {
530 /* Found end of window - lock the pup */
531 pup_adll_limit_state[pup] =
532 PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS;
533 unlock_pup &= ~(1 << pup);
534 } else {
535 /* Probably false pass - reset status */
536 pup_adll_limit_state[pup] =
537 PUP_ADLL_LIMITS_STATE_FAIL;
538
539 #if defined(MV88F78X60)
540 /* Clear logging array of win size (per Dq) */
541 for (dq = 0;
542 dq < DQ_NUM;
543 dq++) {
544 analog_pbs
545 [victim_dq]
546 [pup][dq]
547 [0] =
548 adll_start_val;
549 analog_pbs
550 [victim_dq]
551 [pup][dq]
552 [1] =
553 adll_end_val;
554 per_bit_data
555 [pup][dq]
556 = 0;
557 }
558 #endif
559 }
560 }
561 } else {
562 /* Current compare result == pass */
563 if (pup_adll_limit_state[pup] ==
564 PUP_ADLL_LIMITS_STATE_FAIL) {
565 /* If now it passed but failed earlier */
566 DEBUG_DQS_S("DDR3 - DQS Find Limits - FAIL to PASS: CS - ");
567 DEBUG_DQS_D(cs, 1);
568 DEBUG_DQS_S(", DQ - ");
569 DEBUG_DQS_D(victim_dq, 1);
570 DEBUG_DQS_S(", Pup - ");
571 DEBUG_DQS_D(pup, 1);
572 DEBUG_DQS_S(", ADLL - ");
573 DEBUG_DQS_D(curr_adll, 2);
574 DEBUG_DQS_S("\n");
575
576 #if defined(MV88F78X60)
577 for (dq = 0; dq < DQ_NUM;
578 dq++) {
579 if (analog_pbs[victim_dq][pup][dq][0] == adll_start_val)
580 analog_pbs
581 [victim_dq]
582 [pup][dq]
583 [0] =
584 curr_adll;
585 }
586 #endif
587 /* Found start of window */
588 pup_adll_limit_state[pup] =
589 PUP_ADLL_LIMITS_STATE_PASS;
590
591 /* Keep min / max limit value */
592 if (is_tx == 0) {
593 /* RX - found low limit */
594 if (centralization_low_limit[pup] <= curr_adll)
595 centralization_low_limit
596 [pup] =
597 curr_adll;
598 } else {
599 /* TX - found high limit */
600 if (centralization_high_limit[pup] >= curr_adll)
601 centralization_high_limit
602 [pup] =
603 curr_adll;
604 }
605 }
606 }
607 }
608
609 if (unlock_pup == 0) {
610 /* Found limit to all pups */
611 DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - found PUP limit\n");
612 break;
613 }
614
615 /*
616 * Increment / decrement (Move to right / left
617 * one phase - ADLL) dqs RX / TX delay (for all un
618 * lock pups
619 */
620 if (is_tx == 0)
621 curr_adll++;
622 else
623 curr_adll--;
624 }
625
626 if (unlock_pup != 0) {
627 /*
628 * Found pups that didn't reach to the end of the
629 * state machine
630 */
631 DEBUG_DQS_C("DDR3 - DQS Find Limits - Pups that didn't reached end of the state machine: ",
632 unlock_pup, 1);
633
634 for (pup = 0; pup < max_pup; pup++) {
635 if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
636 if (pup_adll_limit_state[pup] ==
637 PUP_ADLL_LIMITS_STATE_FAIL) {
638 /* ERROR - found fail for all window size */
639 DEBUG_DQS_S("DDR3 - DQS Find Limits - Got FAIL for the complete range on pup - ");
640 DEBUG_DQS_D(pup, 1);
641 DEBUG_DQS_C(" victim DQ ",
642 victim_dq, 1);
643
644 /* For debug - set min limit to illegal limit */
645 centralization_low_limit[pup]
646 = ADLL_ERROR;
647 /*
648 * In case the pup is in mode
649 * PASS - the limit is the min
650 * / max adll, no need to
651 * update because of the results
652 * array default value
653 */
654 return MV_DDR3_TRAINING_ERR_PUP_RANGE;
655 }
656 }
657 }
658 }
659 }
660
661 DEBUG_DQS_S("DDR3 - DQS Find Limits - DQ values per victim results:\n");
662 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
663 for (pup = 0; pup < max_pup; pup++) {
664 DEBUG_DQS_S("Victim DQ-");
665 DEBUG_DQS_D(victim_dq, 1);
666 DEBUG_DQS_S(", PUP-");
667 DEBUG_DQS_D(pup, 1);
668 for (dq = 0; dq < DQ_NUM; dq++) {
669 DEBUG_DQS_S(", DQ-");
670 DEBUG_DQS_D(dq, 1);
671 DEBUG_DQS_S(",S-");
672 DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
673 [0], 2);
674 DEBUG_DQS_S(",E-");
675 DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
676 [1], 2);
677
678 if (is_tx == 0) {
679 if (analog_pbs[victim_dq][pup][dq][0]
680 > analog_pbs_sum[pup][dq][0])
681 analog_pbs_sum[pup][dq][0] =
682 analog_pbs[victim_dq][pup]
683 [dq][0];
684 if (analog_pbs[victim_dq][pup][dq][1]
685 < analog_pbs_sum[pup][dq][1])
686 analog_pbs_sum[pup][dq][1] =
687 analog_pbs[victim_dq][pup]
688 [dq][1];
689 } else {
690 if (analog_pbs[victim_dq][pup][dq][0]
691 < analog_pbs_sum[pup][dq][0])
692 analog_pbs_sum[pup][dq][0] =
693 analog_pbs[victim_dq][pup]
694 [dq][0];
695 if (analog_pbs[victim_dq][pup][dq][1]
696 > analog_pbs_sum[pup][dq][1])
697 analog_pbs_sum[pup][dq][1] =
698 analog_pbs[victim_dq][pup]
699 [dq][1];
700 }
701 }
702 DEBUG_DQS_S("\n");
703 }
704 }
705
706 if (ddr3_get_log_level() >= MV_LOG_LEVEL_3) {
707 u32 dq;
708
709 DEBUG_PER_DQ_S("\n########## LOG LEVEL 3(Windows margins per-DQ) ##########\n");
710 if (is_tx) {
711 DEBUG_PER_DQ_C("DDR3 - TX CS: ", cs, 1);
712 } else {
713 DEBUG_PER_DQ_C("DDR3 - RX CS: ", cs, 1);
714 }
715
716 if (ecc == 0) {
717 DEBUG_PER_DQ_S("\n DATA RESULTS:\n");
718 } else {
719 DEBUG_PER_DQ_S("\n ECC RESULTS:\n");
720 }
721
722 /* Since all dq has the same value we take 0 as representive */
723 dq = 0;
724 for (pup = 0; pup < max_pup; pup++) {
725 if (ecc == 0) {
726 DEBUG_PER_DQ_S("\nBYTE:");
727 DEBUG_PER_DQ_D(pup, 1);
728 DEBUG_PER_DQ_S("\n");
729 } else {
730 DEBUG_PER_DQ_S("\nECC BYTE:\n");
731 }
732 DEBUG_PER_DQ_S(" DQ's LOW HIGH WIN-SIZE\n");
733 DEBUG_PER_DQ_S("============================================\n");
734 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
735 if (ecc == 0) {
736 DEBUG_PER_DQ_S("DQ[");
737 DEBUG_PER_DQ_DD((victim_dq +
738 DQ_NUM * pup), 2);
739 DEBUG_PER_DQ_S("]");
740 } else {
741 DEBUG_PER_DQ_S("CB[");
742 DEBUG_PER_DQ_DD(victim_dq, 2);
743 DEBUG_PER_DQ_S("]");
744 }
745 if (is_tx) {
746 DEBUG_PER_DQ_S(" 0x");
747 DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1], 2); /* low value */
748 DEBUG_PER_DQ_S(" 0x");
749 DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2); /* high value */
750 DEBUG_PER_DQ_S(" 0x");
751 DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0] - analog_pbs[victim_dq][pup][dq][1], 2); /* win-size */
752 } else {
753 DEBUG_PER_DQ_S(" 0x");
754 DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2); /* low value */
755 DEBUG_PER_DQ_S(" 0x");
756 DEBUG_PER_DQ_D((analog_pbs[victim_dq][pup][dq][1] - 1), 2); /* high value */
757 DEBUG_PER_DQ_S(" 0x");
758 DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1] - analog_pbs[victim_dq][pup][dq][0], 2); /* win-size */
759 }
760 DEBUG_PER_DQ_S("\n");
761 }
762 }
763 DEBUG_PER_DQ_S("\n");
764 }
765
766 if (is_tx) {
767 DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
768 } else {
769 DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
770 }
771
772 for (pup = 0; pup < max_pup; pup++) {
773 DEBUG_DQS_S("PUP-");
774 DEBUG_DQS_D(pup, 1);
775 for (dq = 0; dq < DQ_NUM; dq++) {
776 DEBUG_DQS_S(", DQ-");
777 DEBUG_DQS_D(dq, 1);
778 DEBUG_DQS_S(",S-");
779 DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
780 DEBUG_DQS_S(",E-");
781 DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
782 }
783 DEBUG_DQS_S("\n");
784 }
785
786 if (is_tx) {
787 DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
788 } else {
789 DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
790 }
791
792 for (pup = 0; pup < max_pup; pup++) {
793 if (max_pup == 1) {
794 /* For ECC PUP */
795 DEBUG_DQS_S("DDR3 - DQS8");
796 } else {
797 DEBUG_DQS_S("DDR3 - DQS");
798 DEBUG_DQS_D(pup, 1);
799 }
800
801 for (dq = 0; dq < DQ_NUM; dq++) {
802 DEBUG_DQS_S(", DQ-");
803 DEBUG_DQS_D(dq, 1);
804 DEBUG_DQS_S("::S-");
805 DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
806 DEBUG_DQS_S(",E-");
807 DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
808 }
809 DEBUG_DQS_S("\n");
810 }
811
812 DEBUG_DQS_S("DDR3 - DQS Find Limits - Ended\n");
813
814 return MV_OK;
815 }
816
817 /*
818 * Name: ddr3_check_window_limits
819 * Desc: Check window High & Low limits.
820 * Args: pup pup index
821 * high_limit window high limit
822 * low_limit window low limit
823 * is_tx Indicate whether Rx or Tx
824 * size_valid Indicate whether window size is valid
825 * Notes:
826 * Returns: MV_OK if success, other error code if fail.
827 */
ddr3_check_window_limits(u32 pup,int high_limit,int low_limit,int is_tx,int * size_valid)828 int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
829 int *size_valid)
830 {
831 DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Starting\n");
832
833 if (low_limit > high_limit) {
834 DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
835 DEBUG_DQS_D(pup, 1);
836 DEBUG_DQS_S(" Low Limit grater than High Limit\n");
837 *size_valid = 0;
838 return MV_OK;
839 }
840
841 /*
842 * Check that window size is valid, if not it was probably false pass
843 * before
844 */
845 if ((high_limit - low_limit) < MIN_WIN_SIZE) {
846 /*
847 * Since window size is too small probably there was false
848 * pass
849 */
850 *size_valid = 0;
851
852 DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
853 DEBUG_DQS_D(pup, 1);
854 DEBUG_DQS_S(" Window size is smaller than MIN_WIN_SIZE\n");
855
856 } else if ((high_limit - low_limit) > ADLL_MAX) {
857 *size_valid = 0;
858
859 DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
860 DEBUG_DQS_D(pup, 1);
861 DEBUG_DQS_S
862 (" Window size is bigger than max ADLL taps (31) Exiting.\n");
863
864 return MV_FAIL;
865
866 } else {
867 *size_valid = 1;
868
869 DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Pup ");
870 DEBUG_DQS_FULL_D(pup, 1);
871 DEBUG_DQS_FULL_C(" window size is ", (high_limit - low_limit),
872 2);
873 }
874
875 return MV_OK;
876 }
877
878 /*
879 * Name: ddr3_center_calc
880 * Desc: Execute the calculate the center of windows phase.
881 * Args: pDram Info
882 * is_tx Indicate whether Rx or Tx
883 * Notes:
884 * Returns: MV_OK if success, other error code if fail.
885 */
ddr3_center_calc(MV_DRAM_INFO * dram_info,u32 cs,u32 ecc,int is_tx)886 static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
887 int is_tx)
888 {
889 /* bit array of pups that need specail search */
890 u32 special_pattern_i_pup = 0;
891 u32 special_pattern_ii_pup = 0;
892 u32 pup;
893 u32 max_pup;
894
895 max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
896
897 for (pup = 0; pup < max_pup; pup++) {
898 if (is_tx == 0) {
899 /* Check special pattern I */
900 /*
901 * Special pattern Low limit search - relevant only
902 * for Rx, win size < threshold and low limit = 0
903 */
904 if (((centralization_high_limit[pup] -
905 centralization_low_limit[pup]) < VALID_WIN_THRS)
906 && (centralization_low_limit[pup] == MIN_DELAY))
907 special_pattern_i_pup |= (1 << pup);
908
909 /* Check special pattern II */
910 /*
911 * Special pattern High limit search - relevant only
912 * for Rx, win size < threshold and high limit = 31
913 */
914 if (((centralization_high_limit[pup] -
915 centralization_low_limit[pup]) < VALID_WIN_THRS)
916 && (centralization_high_limit[pup] == MAX_DELAY))
917 special_pattern_ii_pup |= (1 << pup);
918 }
919 }
920
921 /* Run special pattern Low limit search - for relevant pup */
922 if (special_pattern_i_pup != 0) {
923 DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern I for Low limit search\n");
924 if (MV_OK !=
925 ddr3_special_pattern_i_search(dram_info, cs, ecc, is_tx,
926 special_pattern_i_pup))
927 return MV_DDR3_TRAINING_ERR_DQS_LOW_LIMIT_SEARCH;
928 }
929
930 /* Run special pattern High limit search - for relevant pup */
931 if (special_pattern_ii_pup != 0) {
932 DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern II for High limit search\n");
933 if (MV_OK !=
934 ddr3_special_pattern_ii_search(dram_info, cs, ecc, is_tx,
935 special_pattern_ii_pup))
936 return MV_DDR3_TRAINING_ERR_DQS_HIGH_LIMIT_SEARCH;
937 }
938
939 /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
940 return ddr3_set_dqs_centralization_results(dram_info, cs, ecc, is_tx);
941 }
942
943 /*
944 * Name: ddr3_special_pattern_i_search
945 * Desc: Execute special pattern low limit search.
946 * Args:
947 * special_pattern_pup The pups that need the special search
948 * Notes:
949 * Returns: MV_OK if success, other error code if fail.
950 */
ddr3_special_pattern_i_search(MV_DRAM_INFO * dram_info,u32 cs,u32 ecc,int is_tx,u32 special_pattern_pup)951 int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
952 int is_tx, u32 special_pattern_pup)
953 {
954 u32 victim_dq; /* loop index - victim DQ */
955 u32 adll_idx;
956 u32 pup;
957 u32 unlock_pup; /* bit array of the unlock pups */
958 u32 first_fail; /* bit array - of pups that get first fail */
959 u32 new_lockup_pup; /* bit array of compare failed pups */
960 u32 pass_pup; /* bit array of compare pass pup */
961 u32 sdram_offset;
962 u32 max_pup;
963 u32 comp_val;
964 u32 special_res[MAX_PUP_NUM]; /* hold tmp results */
965
966 DEBUG_DQS_S("DDR3 - DQS - Special Pattern I Search - Starting\n");
967
968 max_pup = ecc + (1 - ecc) * dram_info->num_of_std_pups;
969
970 /* Init the temporary results to max ADLL value */
971 for (pup = 0; pup < max_pup; pup++)
972 special_res[pup] = ADLL_MAX;
973
974 /* Run special pattern for all DQ - use the same pattern */
975 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
976 unlock_pup = special_pattern_pup;
977 first_fail = 0;
978
979 sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS +
980 LEN_KILLER_PATTERN * 4 * victim_dq;
981
982 for (pup = 0; pup < max_pup; pup++) {
983 /* Set adll value per PUP. adll = high limit per pup */
984 if (IS_PUP_ACTIVE(unlock_pup, pup)) {
985 /* only for pups that need special search */
986 ddr3_write_pup_reg(PUP_DQS_RD, cs,
987 pup + (ecc * ECC_PUP), 0,
988 centralization_high_limit
989 [pup]);
990 }
991 }
992
993 adll_idx = 0;
994 do {
995 /*
996 * Perform read and compare simultaneously for all
997 * un-locked MC use the special pattern mask
998 */
999 new_lockup_pup = 0;
1000
1001 if (MV_OK !=
1002 ddr3_sdram_dqs_compare(dram_info, unlock_pup,
1003 &new_lockup_pup,
1004 special_pattern
1005 [victim_dq],
1006 LEN_SPECIAL_PATTERN,
1007 sdram_offset, 0,
1008 0, NULL, 1))
1009 return MV_FAIL;
1010
1011 DEBUG_DQS_S("DDR3 - DQS - Special I - ADLL value is: ");
1012 DEBUG_DQS_D(adll_idx, 2);
1013 DEBUG_DQS_S(", UnlockPup: ");
1014 DEBUG_DQS_D(unlock_pup, 2);
1015 DEBUG_DQS_S(", NewLockPup: ");
1016 DEBUG_DQS_D(new_lockup_pup, 2);
1017 DEBUG_DQS_S("\n");
1018
1019 if (unlock_pup != new_lockup_pup)
1020 DEBUG_DQS_S("DDR3 - DQS - Special I - Some Pup passed!\n");
1021
1022 /* Search for pups with passed compare & already fail */
1023 pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
1024 first_fail |= new_lockup_pup;
1025 unlock_pup &= ~pass_pup;
1026
1027 /* Get pass pups */
1028 if (pass_pup != 0) {
1029 for (pup = 0; pup < max_pup; pup++) {
1030 if (IS_PUP_ACTIVE(pass_pup, pup) ==
1031 1) {
1032 /* If pup passed and has first fail = 1 */
1033 /* keep min value of ADLL max value - current adll */
1034 /* (centralization_high_limit[pup] + adll_idx) = current adll !!! */
1035 comp_val =
1036 (ADLL_MAX -
1037 (centralization_high_limit
1038 [pup] + adll_idx));
1039
1040 DEBUG_DQS_C
1041 ("DDR3 - DQS - Special I - Pup - ",
1042 pup, 1);
1043 DEBUG_DQS_C
1044 (" comp_val = ",
1045 comp_val, 2);
1046
1047 if (comp_val <
1048 special_res[pup]) {
1049 special_res[pup] =
1050 comp_val;
1051 centralization_low_limit
1052 [pup] =
1053 (-1) *
1054 comp_val;
1055
1056 DEBUG_DQS_C
1057 ("DDR3 - DQS - Special I - Pup - ",
1058 pup, 1);
1059 DEBUG_DQS_C
1060 (" Changed Low limit to ",
1061 centralization_low_limit
1062 [pup], 2);
1063 }
1064 }
1065 }
1066 }
1067
1068 /*
1069 * Did all PUP found missing window?
1070 * Check for each pup if adll (different for each pup)
1071 * reach maximum if reach max value - lock the pup
1072 * if not - increment (Move to right one phase - ADLL)
1073 * dqs RX delay
1074 */
1075 adll_idx++;
1076 for (pup = 0; pup < max_pup; pup++) {
1077 if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
1078 /* Check only unlocked pups */
1079 if ((centralization_high_limit[pup] +
1080 adll_idx) >= ADLL_MAX) {
1081 /* reach maximum - lock the pup */
1082 DEBUG_DQS_C("DDR3 - DQS - Special I - reach maximum - lock pup ",
1083 pup, 1);
1084 unlock_pup &= ~(1 << pup);
1085 } else {
1086 /* Didn't reach maximum - increment ADLL */
1087 ddr3_write_pup_reg(PUP_DQS_RD,
1088 cs,
1089 pup +
1090 (ecc *
1091 ECC_PUP), 0,
1092 (centralization_high_limit
1093 [pup] +
1094 adll_idx));
1095 }
1096 }
1097 }
1098 } while (unlock_pup != 0);
1099 }
1100
1101 return MV_OK;
1102 }
1103
1104 /*
1105 * Name: ddr3_special_pattern_ii_search
1106 * Desc: Execute special pattern high limit search.
1107 * Args:
1108 * special_pattern_pup The pups that need the special search
1109 * Notes:
1110 * Returns: MV_OK if success, other error code if fail.
1111 */
ddr3_special_pattern_ii_search(MV_DRAM_INFO * dram_info,u32 cs,u32 ecc,int is_tx,u32 special_pattern_pup)1112 int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
1113 int is_tx, u32 special_pattern_pup)
1114 {
1115 u32 victim_dq; /* loop index - victim DQ */
1116 u32 adll_idx;
1117 u32 pup;
1118 u32 unlock_pup; /* bit array of the unlock pups */
1119 u32 first_fail; /* bit array - of pups that get first fail */
1120 u32 new_lockup_pup; /* bit array of compare failed pups */
1121 u32 pass_pup; /* bit array of compare pass pup */
1122 u32 sdram_offset;
1123 u32 max_pup;
1124 u32 comp_val;
1125 u32 special_res[MAX_PUP_NUM]; /* hold tmp results */
1126
1127 DEBUG_DQS_S("DDR3 - DQS - Special Pattern II Search - Starting\n");
1128
1129 max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
1130
1131 /* init the tmporary results to max ADLL value */
1132 for (pup = 0; pup < max_pup; pup++)
1133 special_res[pup] = ADLL_MAX;
1134
1135 sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS;
1136
1137 /* run special pattern for all DQ - use the same pattern */
1138 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1139 unlock_pup = special_pattern_pup;
1140 first_fail = 0;
1141
1142 for (pup = 0; pup < max_pup; pup++) {
1143 /* Set adll value per PUP. adll = 0 */
1144 if (IS_PUP_ACTIVE(unlock_pup, pup)) {
1145 /* Only for pups that need special search */
1146 ddr3_write_pup_reg(PUP_DQS_RD, cs,
1147 pup + (ecc * ECC_PUP), 0,
1148 ADLL_MIN);
1149 }
1150 }
1151
1152 adll_idx = 0;
1153 do {
1154 /*
1155 * Perform read and compare simultaneously for all
1156 * un-locked MC use the special pattern mask
1157 */
1158 new_lockup_pup = 0;
1159
1160 if (MV_OK != ddr3_sdram_dqs_compare(
1161 dram_info, unlock_pup, &new_lockup_pup,
1162 special_pattern[victim_dq],
1163 LEN_SPECIAL_PATTERN,
1164 sdram_offset, 0, 0, NULL, 0))
1165 return MV_FAIL;
1166
1167 DEBUG_DQS_S("DDR3 - DQS - Special II - ADLL value is ");
1168 DEBUG_DQS_D(adll_idx, 2);
1169 DEBUG_DQS_S("unlock_pup ");
1170 DEBUG_DQS_D(unlock_pup, 1);
1171 DEBUG_DQS_S("new_lockup_pup ");
1172 DEBUG_DQS_D(new_lockup_pup, 1);
1173 DEBUG_DQS_S("\n");
1174
1175 if (unlock_pup != new_lockup_pup) {
1176 DEBUG_DQS_S("DDR3 - DQS - Special II - Some Pup passed!\n");
1177 }
1178
1179 /* Search for pups with passed compare & already fail */
1180 pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
1181 first_fail |= new_lockup_pup;
1182 unlock_pup &= ~pass_pup;
1183
1184 /* Get pass pups */
1185 if (pass_pup != 0) {
1186 for (pup = 0; pup < max_pup; pup++) {
1187 if (IS_PUP_ACTIVE(pass_pup, pup) ==
1188 1) {
1189 /* If pup passed and has first fail = 1 */
1190 /* keep min value of ADLL max value - current adll */
1191 /* (adll_idx) = current adll !!! */
1192 comp_val = adll_idx;
1193
1194 DEBUG_DQS_C("DDR3 - DQS - Special II - Pup - ",
1195 pup, 1);
1196 DEBUG_DQS_C(" comp_val = ",
1197 comp_val, 1);
1198
1199 if (comp_val <
1200 special_res[pup]) {
1201 special_res[pup] =
1202 comp_val;
1203 centralization_high_limit
1204 [pup] =
1205 ADLL_MAX +
1206 comp_val;
1207
1208 DEBUG_DQS_C
1209 ("DDR3 - DQS - Special II - Pup - ",
1210 pup, 1);
1211 DEBUG_DQS_C
1212 (" Changed High limit to ",
1213 centralization_high_limit
1214 [pup], 2);
1215 }
1216 }
1217 }
1218 }
1219
1220 /*
1221 * Did all PUP found missing window?
1222 * Check for each pup if adll (different for each pup)
1223 * reach maximum if reach max value - lock the pup
1224 * if not - increment (Move to right one phase - ADLL)
1225 * dqs RX delay
1226 */
1227 adll_idx++;
1228 for (pup = 0; pup < max_pup; pup++) {
1229 if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
1230 /* Check only unlocked pups */
1231 if ((adll_idx) >= ADLL_MAX) {
1232 /* Reach maximum - lock the pup */
1233 DEBUG_DQS_C("DDR3 - DQS - Special II - reach maximum - lock pup ",
1234 pup, 1);
1235 unlock_pup &= ~(1 << pup);
1236 } else {
1237 /* Didn't reach maximum - increment ADLL */
1238 ddr3_write_pup_reg(PUP_DQS_RD,
1239 cs,
1240 pup +
1241 (ecc *
1242 ECC_PUP), 0,
1243 (adll_idx));
1244 }
1245 }
1246 }
1247 } while (unlock_pup != 0);
1248 }
1249
1250 return MV_OK;
1251 }
1252
1253 /*
1254 * Name: ddr3_set_dqs_centralization_results
1255 * Desc: Set to HW the DQS centralization phase results.
1256 * Args:
1257 * is_tx Indicates whether to set Tx or RX results
1258 * Notes:
1259 * Returns: MV_OK if success, other error code if fail.
1260 */
ddr3_set_dqs_centralization_results(MV_DRAM_INFO * dram_info,u32 cs,u32 ecc,int is_tx)1261 int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs,
1262 u32 ecc, int is_tx)
1263 {
1264 u32 pup, pup_num;
1265 int addl_val;
1266 u32 max_pup;
1267
1268 max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
1269
1270 DEBUG_DQS_RESULTS_S("\n############ LOG LEVEL 2(Windows margins) ############\n");
1271
1272 if (is_tx) {
1273 DEBUG_DQS_RESULTS_C("DDR3 - DQS TX - Set Dqs Centralization Results - CS: ",
1274 cs, 1);
1275 } else {
1276 DEBUG_DQS_RESULTS_C("DDR3 - DQS RX - Set Dqs Centralization Results - CS: ",
1277 cs, 1);
1278 }
1279
1280 /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
1281 DEBUG_DQS_RESULTS_S("\nDQS LOW HIGH WIN-SIZE Set\n");
1282 DEBUG_DQS_RESULTS_S("==============================================\n");
1283 for (pup = 0; pup < max_pup; pup++) {
1284 addl_val = (centralization_high_limit[pup] +
1285 centralization_low_limit[pup]) / 2;
1286
1287 pup_num = pup * (1 - ecc) + ecc * ECC_PUP;
1288
1289 DEBUG_DQS_RESULTS_D(pup_num, 1);
1290 DEBUG_DQS_RESULTS_S(" 0x");
1291 DEBUG_DQS_RESULTS_D(centralization_low_limit[pup], 2);
1292 DEBUG_DQS_RESULTS_S(" 0x");
1293 DEBUG_DQS_RESULTS_D(centralization_high_limit[pup], 2);
1294 DEBUG_DQS_RESULTS_S(" 0x");
1295 DEBUG_DQS_RESULTS_D(centralization_high_limit[pup] -
1296 centralization_low_limit[pup], 2);
1297 DEBUG_DQS_RESULTS_S(" 0x");
1298 DEBUG_DQS_RESULTS_D(addl_val, 2);
1299 DEBUG_DQS_RESULTS_S("\n");
1300
1301 if (addl_val < ADLL_MIN) {
1302 addl_val = ADLL_MIN;
1303 DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MIN (since it was lower than 0)\n");
1304 }
1305
1306 if (addl_val > ADLL_MAX) {
1307 addl_val = ADLL_MAX;
1308 DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MAX (since it was higher than 31)\n");
1309 }
1310
1311 if (is_tx) {
1312 ddr3_write_pup_reg(PUP_DQS_WR, cs, pup_num, 0,
1313 addl_val +
1314 dram_info->wl_val[cs][pup_num][D]);
1315 } else {
1316 ddr3_write_pup_reg(PUP_DQS_RD, cs, pup_num, 0,
1317 addl_val);
1318 }
1319 }
1320
1321 return MV_OK;
1322 }
1323
1324 /*
1325 * Set training patterns
1326 */
ddr3_load_dqs_patterns(MV_DRAM_INFO * dram_info)1327 int ddr3_load_dqs_patterns(MV_DRAM_INFO *dram_info)
1328 {
1329 u32 cs, cs_count, cs_tmp, victim_dq;
1330 u32 sdram_addr;
1331 u32 *pattern_ptr;
1332
1333 /* Loop for each CS */
1334 for (cs = 0; cs < MAX_CS; cs++) {
1335 if (dram_info->cs_ena & (1 << cs)) {
1336 cs_count = 0;
1337 for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
1338 if (dram_info->cs_ena & (1 << cs_tmp))
1339 cs_count++;
1340 }
1341
1342 /* Init killer pattern */
1343 sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
1344 SDRAM_DQS_RX_OFFS);
1345 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1346 pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
1347 victim_dq);
1348 if (MV_OK != ddr3_sdram_dqs_compare(
1349 dram_info, (u32)NULL, NULL,
1350 pattern_ptr, LEN_KILLER_PATTERN,
1351 sdram_addr + LEN_KILLER_PATTERN *
1352 4 * victim_dq, 1, 0, NULL,
1353 0))
1354 return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
1355 }
1356
1357 /* Init special-killer pattern */
1358 sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
1359 SDRAM_DQS_RX_SPECIAL_OFFS);
1360 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1361 if (MV_OK != ddr3_sdram_dqs_compare(
1362 dram_info, (u32)NULL, NULL,
1363 special_pattern[victim_dq],
1364 LEN_KILLER_PATTERN, sdram_addr +
1365 LEN_KILLER_PATTERN * 4 * victim_dq,
1366 1, 0, NULL, 0))
1367 return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
1368 }
1369 }
1370 }
1371
1372 return MV_OK;
1373 }
1374