• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) Marvell International Ltd. and its affiliates
4  */
5 
6 #include "ddr3_init.h"
7 
8 #define VREF_INITIAL_STEP		3
9 #define VREF_SECOND_STEP		1
10 #define VREF_MAX_INDEX			7
11 #define MAX_VALUE			(1024 - 1)
12 #define MIN_VALUE			(-MAX_VALUE)
13 #define GET_RD_SAMPLE_DELAY(data, cs)	((data >> rd_sample_mask[cs]) & 0xf)
14 
15 u32 ca_delay;
16 int ddr3_tip_centr_skip_min_win_check = 0;
17 u8 current_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
18 u8 last_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
19 u16 current_valid_window[MAX_BUS_NUM][MAX_INTERFACE_NUM];
20 u16 last_valid_window[MAX_BUS_NUM][MAX_INTERFACE_NUM];
21 u8 lim_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
22 u8 interface_state[MAX_INTERFACE_NUM];
23 u8 vref_window_size[MAX_INTERFACE_NUM][MAX_BUS_NUM];
24 u8 vref_window_size_th = 12;
25 
26 static u8 pup_st[MAX_BUS_NUM][MAX_INTERFACE_NUM];
27 
28 static u32 rd_sample_mask[] = {
29 	0,
30 	8,
31 	16,
32 	24
33 };
34 
35 #define	VREF_STEP_1		0
36 #define	VREF_STEP_2		1
37 #define	VREF_CONVERGE		2
38 
39 /*
40  * ODT additional timing
41  */
ddr3_tip_write_additional_odt_setting(u32 dev_num,u32 if_id)42 int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id)
43 {
44 	u32 cs_num = 0, max_read_sample = 0, min_read_sample = 0x1f;
45 	u32 data_read[MAX_INTERFACE_NUM] = { 0 };
46 	u32 read_sample[MAX_CS_NUM];
47 	u32 val;
48 	u32 pup_index;
49 	int max_phase = MIN_VALUE, current_phase;
50 	enum hws_access_type access_type = ACCESS_TYPE_UNICAST;
51 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
52 
53 	CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
54 				       DUNIT_ODT_CTRL_REG,
55 				       0 << 8, 0x3 << 8));
56 	CHECK_STATUS(ddr3_tip_if_read(dev_num, access_type, if_id,
57 				      RD_DATA_SMPL_DLYS_REG,
58 				      data_read, MASK_ALL_BITS));
59 	val = data_read[if_id];
60 
61 	for (cs_num = 0; cs_num < MAX_CS_NUM; cs_num++) {
62 		read_sample[cs_num] = GET_RD_SAMPLE_DELAY(val, cs_num);
63 
64 		/* find maximum of read_samples */
65 		if (read_sample[cs_num] >= max_read_sample) {
66 			if (read_sample[cs_num] == max_read_sample)
67 				max_phase = MIN_VALUE;
68 			else
69 				max_read_sample = read_sample[cs_num];
70 
71 			for (pup_index = 0;
72 			     pup_index < octets_per_if_num;
73 			     pup_index++) {
74 				CHECK_STATUS(ddr3_tip_bus_read
75 					     (dev_num, if_id,
76 					      ACCESS_TYPE_UNICAST, pup_index,
77 					      DDR_PHY_DATA,
78 					      RL_PHY_REG(cs_num),
79 					      &val));
80 
81 				current_phase = ((int)val & 0xe0) >> 6;
82 				if (current_phase >= max_phase)
83 					max_phase = current_phase;
84 			}
85 		}
86 
87 		/* find minimum */
88 		if (read_sample[cs_num] < min_read_sample)
89 			min_read_sample = read_sample[cs_num];
90 	}
91 
92 	min_read_sample = min_read_sample - 1;
93 	max_read_sample = max_read_sample + 4 + (max_phase + 1) / 2 + 1;
94 	if (min_read_sample >= 0xf)
95 		min_read_sample = 0xf;
96 	if (max_read_sample >= 0x1f)
97 		max_read_sample = 0x1f;
98 
99 	CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
100 				       DDR_ODT_TIMING_LOW_REG,
101 				       ((min_read_sample - 1) << 12),
102 				       0xf << 12));
103 	CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
104 				       DDR_ODT_TIMING_LOW_REG,
105 				       (max_read_sample << 16),
106 				       0x1f << 16));
107 
108 	return MV_OK;
109 }
110 
get_valid_win_rx(u32 dev_num,u32 if_id,u8 res[4])111 int get_valid_win_rx(u32 dev_num, u32 if_id, u8 res[4])
112 {
113 	u32 reg_pup = RESULT_PHY_REG;
114 	u32 reg_data;
115 	u32 cs_num;
116 	int i;
117 
118 	cs_num = 0;
119 
120 	/* TBD */
121 	reg_pup += cs_num;
122 
123 	for (i = 0; i < 4; i++) {
124 		CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id,
125 					       ACCESS_TYPE_UNICAST, i,
126 					       DDR_PHY_DATA, reg_pup,
127 					       &reg_data));
128 		res[i] = (reg_data >> RESULT_PHY_RX_OFFS) & 0x1f;
129 	}
130 
131 	return 0;
132 }
133 
134 /*
135  * This algorithm deals with the vertical optimum from Voltage point of view
136  * of the sample signal.
137  * Voltage sample point can improve the Eye / window size of the bit and the
138  * pup.
139  * The problem is that it is tune for all DQ the same so there isn't any
140  * PBS like code.
141  * It is more like centralization.
142  * But because we don't have The training SM support we do it a bit more
143  * smart search to save time.
144  */
ddr3_tip_vref(u32 dev_num)145 int ddr3_tip_vref(u32 dev_num)
146 {
147 	/*
148 	 * The Vref register have non linear order. Need to check what will be
149 	 * in future projects.
150 	 */
151 	u32 vref_map[8] = {
152 		1, 2, 3, 4, 5, 6, 7, 0
153 	};
154 	/* State and parameter definitions */
155 	u32 initial_step = VREF_INITIAL_STEP;
156 	/* need to be assign with minus ????? */
157 	u32 second_step = VREF_SECOND_STEP;
158 	u32 algo_run_flag = 0, currrent_vref = 0;
159 	u32 while_count = 0;
160 	u32 pup = 0, if_id = 0, num_pup = 0, rep = 0;
161 	u32 val = 0;
162 	u32 reg_addr = 0xa8;
163 	u32 copy_start_pattern, copy_end_pattern;
164 	enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage);
165 	u8 res[4];
166 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
167 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
168 
169 	CHECK_STATUS(ddr3_tip_special_rx(dev_num));
170 
171 	/* save start/end pattern */
172 	copy_start_pattern = start_pattern;
173 	copy_end_pattern = end_pattern;
174 
175 	/* set vref as centralization pattern */
176 	start_pattern = PATTERN_VREF;
177 	end_pattern = PATTERN_VREF;
178 
179 	/* init params */
180 	for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
181 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
182 		for (pup = 0;
183 		     pup < octets_per_if_num; pup++) {
184 			current_vref[pup][if_id] = 0;
185 			last_vref[pup][if_id] = 0;
186 			lim_vref[pup][if_id] = 0;
187 			current_valid_window[pup][if_id] = 0;
188 			last_valid_window[pup][if_id] = 0;
189 			if (vref_window_size[if_id][pup] >
190 			    vref_window_size_th) {
191 				pup_st[pup][if_id] = VREF_CONVERGE;
192 				DEBUG_TRAINING_HW_ALG(
193 					DEBUG_LEVEL_INFO,
194 					("VREF config, IF[ %d ]pup[ %d ] - Vref tune not requered (%d)\n",
195 					 if_id, pup, __LINE__));
196 			} else {
197 				pup_st[pup][if_id] = VREF_STEP_1;
198 				CHECK_STATUS(ddr3_tip_bus_read
199 					     (dev_num, if_id,
200 					      ACCESS_TYPE_UNICAST, pup,
201 					      DDR_PHY_DATA, reg_addr, &val));
202 				CHECK_STATUS(ddr3_tip_bus_write
203 					     (dev_num, ACCESS_TYPE_UNICAST,
204 					      if_id, ACCESS_TYPE_UNICAST,
205 					      pup, DDR_PHY_DATA, reg_addr,
206 					      (val & (~0xf)) | vref_map[0]));
207 				DEBUG_TRAINING_HW_ALG(
208 					DEBUG_LEVEL_INFO,
209 					("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
210 					 if_id, pup,
211 					 (val & (~0xf)) | vref_map[0],
212 					 __LINE__));
213 			}
214 		}
215 		interface_state[if_id] = 0;
216 	}
217 
218 	/* TODO: Set number of active interfaces */
219 	num_pup = octets_per_if_num * MAX_INTERFACE_NUM;
220 
221 	while ((algo_run_flag <= num_pup) & (while_count < 10)) {
222 		while_count++;
223 		for (rep = 1; rep < 4; rep++) {
224 			ddr3_tip_centr_skip_min_win_check = 1;
225 			ddr3_tip_centralization_rx(dev_num);
226 			ddr3_tip_centr_skip_min_win_check = 0;
227 
228 			/* Read Valid window results only for non converge pups */
229 			for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
230 				VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
231 				if (interface_state[if_id] != 4) {
232 					get_valid_win_rx(dev_num, if_id, res);
233 					for (pup = 0;
234 					     pup < octets_per_if_num;
235 					     pup++) {
236 						VALIDATE_BUS_ACTIVE
237 							(tm->bus_act_mask, pup);
238 						if (pup_st[pup]
239 						    [if_id] ==
240 						    VREF_CONVERGE)
241 							continue;
242 
243 						current_valid_window[pup]
244 							[if_id] =
245 							(current_valid_window[pup]
246 							 [if_id] * (rep - 1) +
247 							 1000 * res[pup]) / rep;
248 					}
249 				}
250 			}
251 		}
252 
253 		for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
254 			VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
255 			DEBUG_TRAINING_HW_ALG(
256 				DEBUG_LEVEL_TRACE,
257 				("current_valid_window: IF[ %d ] - ", if_id));
258 
259 			for (pup = 0;
260 			     pup < octets_per_if_num; pup++) {
261 				VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
262 				DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
263 						      ("%d ",
264 						       current_valid_window
265 						       [pup][if_id]));
266 			}
267 			DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE, ("\n"));
268 		}
269 
270 		/* Compare results and respond as function of state */
271 		for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
272 			VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
273 			for (pup = 0;
274 			     pup < octets_per_if_num; pup++) {
275 				VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
276 				DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
277 						      ("I/F[ %d ], pup[ %d ] STATE #%d (%d)\n",
278 						       if_id, pup,
279 						       pup_st[pup]
280 						       [if_id], __LINE__));
281 
282 				if (pup_st[pup][if_id] == VREF_CONVERGE)
283 					continue;
284 
285 				DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
286 						      ("I/F[ %d ], pup[ %d ] CHECK progress - Current %d Last %d, limit VREF %d (%d)\n",
287 						       if_id, pup,
288 						       current_valid_window[pup]
289 						       [if_id],
290 						       last_valid_window[pup]
291 						       [if_id], lim_vref[pup]
292 						       [if_id], __LINE__));
293 
294 				/*
295 				 * The -1 is for solution resolution +/- 1 tap
296 				 * of ADLL
297 				 */
298 				if (current_valid_window[pup][if_id] + 200 >=
299 				    (last_valid_window[pup][if_id])) {
300 					if (pup_st[pup][if_id] == VREF_STEP_1) {
301 						/*
302 						 * We stay in the same state and
303 						 * step just update the window
304 						 * size (take the max) and Vref
305 						 */
306 						if (current_vref[pup]
307 						    [if_id] == VREF_MAX_INDEX) {
308 							/*
309 							 * If we step to the end
310 							 * and didn't converge
311 							 * to some particular
312 							 * better Vref value
313 							 * define the pup as
314 							 * converge and step
315 							 * back to nominal
316 							 * Vref.
317 							 */
318 							pup_st[pup]
319 								[if_id] =
320 								VREF_CONVERGE;
321 							algo_run_flag++;
322 							interface_state
323 								[if_id]++;
324 							DEBUG_TRAINING_HW_ALG
325 								(DEBUG_LEVEL_TRACE,
326 								 ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
327 								  if_id, pup,
328 								  current_vref[pup]
329 								  [if_id],
330 								  __LINE__));
331 						} else {
332 							/* continue to update the Vref index */
333 							current_vref[pup]
334 								[if_id] =
335 								((current_vref[pup]
336 								  [if_id] +
337 								  initial_step) >
338 								 VREF_MAX_INDEX) ?
339 								VREF_MAX_INDEX
340 								: (current_vref[pup]
341 								   [if_id] +
342 								   initial_step);
343 							if (current_vref[pup]
344 							    [if_id] ==
345 							    VREF_MAX_INDEX) {
346 								pup_st[pup]
347 									[if_id]
348 									=
349 									VREF_STEP_2;
350 							}
351 							lim_vref[pup]
352 								[if_id] =
353 								last_vref[pup]
354 								[if_id] =
355 								current_vref[pup]
356 								[if_id];
357 						}
358 
359 						last_valid_window[pup]
360 							[if_id] =
361 							GET_MAX(current_valid_window
362 								[pup][if_id],
363 								last_valid_window
364 								[pup]
365 								[if_id]);
366 
367 						/* update the Vref for next stage */
368 						currrent_vref =
369 							current_vref[pup]
370 							[if_id];
371 						CHECK_STATUS
372 							(ddr3_tip_bus_read
373 							 (dev_num, if_id,
374 							  ACCESS_TYPE_UNICAST, pup,
375 							  DDR_PHY_DATA, reg_addr,
376 							  &val));
377 						CHECK_STATUS
378 							(ddr3_tip_bus_write
379 							 (dev_num,
380 							  ACCESS_TYPE_UNICAST,
381 							  if_id,
382 							  ACCESS_TYPE_UNICAST, pup,
383 							  DDR_PHY_DATA, reg_addr,
384 							  (val & (~0xf)) |
385 							  vref_map[currrent_vref]));
386 						DEBUG_TRAINING_HW_ALG
387 							(DEBUG_LEVEL_TRACE,
388 							 ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
389 							  if_id, pup,
390 							  (val & (~0xf)) |
391 							  vref_map[currrent_vref],
392 							  __LINE__));
393 					} else if (pup_st[pup][if_id]
394 						   == VREF_STEP_2) {
395 						/*
396 						 * We keep on search back with
397 						 * the same step size.
398 						 */
399 						last_valid_window[pup]
400 							[if_id] =
401 							GET_MAX(current_valid_window
402 								[pup][if_id],
403 								last_valid_window
404 								[pup]
405 								[if_id]);
406 						last_vref[pup][if_id] =
407 							current_vref[pup]
408 							[if_id];
409 
410 						/* we finish all search space */
411 						if ((current_vref[pup]
412 						     [if_id] - second_step) == lim_vref[pup][if_id]) {
413 							/*
414 							 * If we step to the end
415 							 * and didn't converge
416 							 * to some particular
417 							 * better Vref value
418 							 * define the pup as
419 							 * converge and step
420 							 * back to nominal
421 							 * Vref.
422 							 */
423 							pup_st[pup]
424 								[if_id] =
425 								VREF_CONVERGE;
426 							algo_run_flag++;
427 
428 							interface_state
429 								[if_id]++;
430 
431 							current_vref[pup]
432 								[if_id] =
433 								(current_vref[pup]
434 								 [if_id] -
435 								 second_step);
436 
437 							DEBUG_TRAINING_HW_ALG
438 								(DEBUG_LEVEL_TRACE,
439 								 ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
440 								  if_id, pup,
441 								  current_vref[pup]
442 								  [if_id],
443 								  __LINE__));
444 						} else
445 							/* we finish all search space */
446 							if (current_vref[pup]
447 							    [if_id] ==
448 							    lim_vref[pup]
449 							    [if_id]) {
450 								/*
451 								 * If we step to the end
452 								 * and didn't converge
453 								 * to some particular
454 								 * better Vref value
455 								 * define the pup as
456 								 * converge and step
457 								 * back to nominal
458 								 * Vref.
459 								 */
460 								pup_st[pup]
461 									[if_id] =
462 									VREF_CONVERGE;
463 
464 								algo_run_flag++;
465 								interface_state
466 									[if_id]++;
467 								DEBUG_TRAINING_HW_ALG
468 									(DEBUG_LEVEL_TRACE,
469 									 ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
470 									  if_id, pup,
471 									  current_vref[pup]
472 									  [if_id],
473 									  __LINE__));
474 							} else {
475 								current_vref[pup]
476 									[if_id] =
477 									current_vref[pup]
478 									[if_id] -
479 									second_step;
480 							}
481 
482 						/* Update the Vref for next stage */
483 						currrent_vref =
484 							current_vref[pup]
485 							[if_id];
486 						CHECK_STATUS
487 							(ddr3_tip_bus_read
488 							 (dev_num, if_id,
489 							  ACCESS_TYPE_UNICAST, pup,
490 							  DDR_PHY_DATA, reg_addr,
491 							  &val));
492 						CHECK_STATUS
493 							(ddr3_tip_bus_write
494 							 (dev_num,
495 							  ACCESS_TYPE_UNICAST,
496 							  if_id,
497 							  ACCESS_TYPE_UNICAST, pup,
498 							  DDR_PHY_DATA, reg_addr,
499 							  (val & (~0xf)) |
500 							  vref_map[currrent_vref]));
501 						DEBUG_TRAINING_HW_ALG
502 							(DEBUG_LEVEL_TRACE,
503 							 ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
504 							  if_id, pup,
505 							  (val & (~0xf)) |
506 							  vref_map[currrent_vref],
507 							  __LINE__));
508 					}
509 				} else {
510 					/* we change state and change step */
511 					if (pup_st[pup][if_id] == VREF_STEP_1) {
512 						pup_st[pup][if_id] =
513 							VREF_STEP_2;
514 						lim_vref[pup][if_id] =
515 							current_vref[pup]
516 							[if_id] - initial_step;
517 						last_valid_window[pup]
518 							[if_id] =
519 							current_valid_window[pup]
520 							[if_id];
521 						last_vref[pup][if_id] =
522 							current_vref[pup]
523 							[if_id];
524 						current_vref[pup][if_id] =
525 							last_vref[pup][if_id] -
526 							second_step;
527 
528 						/* Update the Vref for next stage */
529 						CHECK_STATUS
530 							(ddr3_tip_bus_read
531 							 (dev_num, if_id,
532 							  ACCESS_TYPE_UNICAST, pup,
533 							  DDR_PHY_DATA, reg_addr,
534 							  &val));
535 						CHECK_STATUS
536 							(ddr3_tip_bus_write
537 							 (dev_num,
538 							  ACCESS_TYPE_UNICAST,
539 							  if_id,
540 							  ACCESS_TYPE_UNICAST, pup,
541 							  DDR_PHY_DATA, reg_addr,
542 							  (val & (~0xf)) |
543 							  vref_map[current_vref[pup]
544 								   [if_id]]));
545 						DEBUG_TRAINING_HW_ALG
546 							(DEBUG_LEVEL_TRACE,
547 							 ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
548 							  if_id, pup,
549 							  (val & (~0xf)) |
550 							  vref_map[current_vref[pup]
551 								   [if_id]],
552 							  __LINE__));
553 
554 					} else if (pup_st[pup][if_id] == VREF_STEP_2) {
555 						/*
556 						 * The last search was the max
557 						 * point set value and exit
558 						 */
559 						CHECK_STATUS
560 							(ddr3_tip_bus_read
561 							 (dev_num, if_id,
562 							  ACCESS_TYPE_UNICAST, pup,
563 							  DDR_PHY_DATA, reg_addr,
564 							  &val));
565 						CHECK_STATUS
566 							(ddr3_tip_bus_write
567 							 (dev_num,
568 							  ACCESS_TYPE_UNICAST,
569 							  if_id,
570 							  ACCESS_TYPE_UNICAST, pup,
571 							  DDR_PHY_DATA, reg_addr,
572 							  (val & (~0xf)) |
573 							  vref_map[last_vref[pup]
574 								   [if_id]]));
575 						DEBUG_TRAINING_HW_ALG
576 							(DEBUG_LEVEL_TRACE,
577 							 ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
578 							  if_id, pup,
579 							  (val & (~0xf)) |
580 							  vref_map[last_vref[pup]
581 								   [if_id]],
582 							  __LINE__));
583 						pup_st[pup][if_id] =
584 							VREF_CONVERGE;
585 						algo_run_flag++;
586 						interface_state[if_id]++;
587 						DEBUG_TRAINING_HW_ALG
588 							(DEBUG_LEVEL_TRACE,
589 							 ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
590 							  if_id, pup,
591 							  current_vref[pup]
592 							  [if_id], __LINE__));
593 					}
594 				}
595 			}
596 		}
597 	}
598 
599 	for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
600 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
601 		for (pup = 0;
602 		     pup < octets_per_if_num; pup++) {
603 			VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
604 			CHECK_STATUS(ddr3_tip_bus_read
605 				     (dev_num, if_id,
606 				      ACCESS_TYPE_UNICAST, pup,
607 				      DDR_PHY_DATA, reg_addr, &val));
608 			DEBUG_TRAINING_HW_ALG(
609 				DEBUG_LEVEL_INFO,
610 				("FINAL values: I/F[ %d ], pup[ %d ] - Vref = %X (%d)\n",
611 				 if_id, pup, val, __LINE__));
612 		}
613 	}
614 
615 	flow_result[if_id] = TEST_SUCCESS;
616 
617 	/* restore start/end pattern */
618 	start_pattern = copy_start_pattern;
619 	end_pattern = copy_end_pattern;
620 
621 	return 0;
622 }
623 
624 /*
625  * CK/CA Delay
626  */
ddr3_tip_cmd_addr_init_delay(u32 dev_num,u32 adll_tap)627 int ddr3_tip_cmd_addr_init_delay(u32 dev_num, u32 adll_tap)
628 {
629 	u32 if_id = 0;
630 	u32 ck_num_adll_tap = 0, ca_num_adll_tap = 0, data = 0;
631 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
632 
633 	/*
634 	 * ck_delay_table is delaying the of the clock signal only.
635 	 * (to overcome timing issues between_c_k & command/address signals)
636 	 */
637 	/*
638 	 * ca_delay is delaying the of the entire command & Address signals
639 	 * (include Clock signal to overcome DGL error on the Clock versus
640 	 * the DQS).
641 	 */
642 
643 	/* Calc ADLL Tap */
644 	if (ck_delay == PARAM_UNDEFINED)
645 		DEBUG_TRAINING_HW_ALG(
646 			DEBUG_LEVEL_ERROR,
647 			("ERROR: ck_delay is not initialized!\n"));
648 
649 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
650 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
651 
652 		/* Calc delay ps in ADLL tap */
653 		ck_num_adll_tap = ck_delay / adll_tap;
654 		ca_num_adll_tap = ca_delay / adll_tap;
655 
656 		data = (ck_num_adll_tap & 0x3f) +
657 			((ca_num_adll_tap & 0x3f) << 10);
658 
659 		/*
660 		 * Set the ADLL number to the CK ADLL for Interfaces for
661 		 * all Pup
662 		 */
663 		DEBUG_TRAINING_HW_ALG(
664 			DEBUG_LEVEL_TRACE,
665 			("ck_num_adll_tap %d ca_num_adll_tap %d adll_tap %d\n",
666 			 ck_num_adll_tap, ca_num_adll_tap, adll_tap));
667 
668 		CHECK_STATUS(ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST,
669 						if_id, ACCESS_TYPE_MULTICAST,
670 						PARAM_NOT_CARE, DDR_PHY_CONTROL,
671 						0x0, data));
672 	}
673 
674 	return MV_OK;
675 }
676