odroid: remove CONFIG_DM_I2C_COMPAT config
[platform/kernel/u-boot.git] / drivers / ddr / marvell / axp / ddr3_dqs.c
1 /*
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 */
57 enum {
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 */
64 static int centralization_low_limit[MAX_PUP_NUM] = { 0 };
65 /* Hold centralization high results */
66 static int centralization_high_limit[MAX_PUP_NUM] = { 0 };
67
68 int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx);
69 int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
70                           int *size_valid);
71 static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
72                             int is_tx);
73 int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
74                               int is_tx, u32 special_pattern_pup);
75 int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
76                                    int is_tx, u32 special_pattern_pup);
77 int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
78                                     int is_tx);
79
80 #ifdef MV88F78X60
81 extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
82 extern u32 killer_pattern_64b[DQ_NUM][LEN_SPECIAL_PATTERN];
83 extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
84 #else
85 extern u32 killer_pattern[DQ_NUM][LEN_16BIT_KILLER_PATTERN];
86 extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
87 #if defined(MV88F672X)
88 extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
89 #endif
90 #endif
91 extern u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN];
92
93 static 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  */
131 int 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  */
213 int 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  */
296 int 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  */
829 int 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  */
887 static 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  */
952 int 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  */
1113 int 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  */
1262 int 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  */
1328 int 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 }