1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) Marvell International Ltd. and its affiliates
4 */
5
6#include <common.h>
7#include <i2c.h>
8#include <log.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}
1375