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