blob: e75e45c169a0e3a597adae5258dea22682956ae2 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Stefan Roese5ffceb82015-03-26 15:36:56 +01002/*
3 * Copyright (C) Marvell International Ltd. and its affiliates
Stefan Roese5ffceb82015-03-26 15:36:56 +01004 */
5
Stefan Roese5ffceb82015-03-26 15:36:56 +01006#include "ddr3_init.h"
Chris Packham4bf81db2018-12-03 14:26:49 +13007#include "mv_ddr_regs.h"
Stefan Roese5ffceb82015-03-26 15:36:56 +01008
9#define VALIDATE_WIN_LENGTH(e1, e2, maxsize) \
10 (((e2) + 1 > (e1) + (u8)MIN_WINDOW_SIZE) && \
11 ((e2) + 1 < (e1) + (u8)maxsize))
12#define IS_WINDOW_OUT_BOUNDARY(e1, e2, maxsize) \
13 (((e1) == 0 && (e2) != 0) || \
14 ((e1) != (maxsize - 1) && (e2) == (maxsize - 1)))
15#define CENTRAL_TX 0
16#define CENTRAL_RX 1
17#define NUM_OF_CENTRAL_TYPES 2
18
Tony Dinhe2c524b2023-01-18 19:03:04 -080019#if defined(CONFIG_DDR4) /* DDR4 16/32-bit */
20u32 start_pattern = PATTERN_KILLER_DQ0, end_pattern = PATTERN_KILLER_DQ7_INV;
21#else /* DDR3 16/32-bit */
Stefan Roese5ffceb82015-03-26 15:36:56 +010022u32 start_pattern = PATTERN_KILLER_DQ0, end_pattern = PATTERN_KILLER_DQ7;
Tony Dinhe2c524b2023-01-18 19:03:04 -080023#endif /* CONFIG_64BIT */
Chris Packham1a07d212018-05-10 13:28:29 +120024
Stefan Roese5ffceb82015-03-26 15:36:56 +010025u32 start_if = 0, end_if = (MAX_INTERFACE_NUM - 1);
26u8 bus_end_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM];
27u8 bus_start_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM];
28u8 centralization_state[MAX_INTERFACE_NUM][MAX_BUS_NUM];
29static u8 ddr3_tip_special_rx_run_once_flag;
30
31static int ddr3_tip_centralization(u32 dev_num, u32 mode);
32
33/*
34 * Centralization RX Flow
35 */
36int ddr3_tip_centralization_rx(u32 dev_num)
37{
38 CHECK_STATUS(ddr3_tip_special_rx(dev_num));
39 CHECK_STATUS(ddr3_tip_centralization(dev_num, CENTRAL_RX));
40
41 return MV_OK;
42}
43
44/*
45 * Centralization TX Flow
46 */
47int ddr3_tip_centralization_tx(u32 dev_num)
48{
49 CHECK_STATUS(ddr3_tip_centralization(dev_num, CENTRAL_TX));
50
51 return MV_OK;
52}
53
54/*
55 * Centralization Flow
56 */
57static int ddr3_tip_centralization(u32 dev_num, u32 mode)
58{
59 enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM];
60 u32 if_id, pattern_id, bit_id;
61 u8 bus_id;
Marek BehĂșn9e2a9472022-01-12 17:06:59 +010062 u8 current_byte_status;
Stefan Roese5ffceb82015-03-26 15:36:56 +010063 u8 cur_start_win[BUS_WIDTH_IN_BITS];
64 u8 centralization_result[MAX_INTERFACE_NUM][BUS_WIDTH_IN_BITS];
65 u8 cur_end_win[BUS_WIDTH_IN_BITS];
66 u8 current_window[BUS_WIDTH_IN_BITS];
67 u8 opt_window, waste_window, start_window_skew, end_window_skew;
68 u8 final_pup_window[MAX_INTERFACE_NUM][BUS_WIDTH_IN_BITS];
Chris Packham1a07d212018-05-10 13:28:29 +120069 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
70 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
Stefan Roese5ffceb82015-03-26 15:36:56 +010071 enum hws_training_result result_type = RESULT_PER_BIT;
72 enum hws_dir direction;
73 u32 *result[HWS_SEARCH_DIR_LIMIT];
74 u32 reg_phy_off, reg;
75 u8 max_win_size;
76 int lock_success = 1;
77 u8 cur_end_win_min, cur_start_win_max;
78 u32 cs_enable_reg_val[MAX_INTERFACE_NUM];
79 int is_if_fail = 0;
80 enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage);
81 u32 pup_win_length = 0;
82 enum hws_search_dir search_dir_id;
83 u8 cons_tap = (mode == CENTRAL_TX) ? (64) : (0);
84
85 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +120086 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +010087 /* save current cs enable reg val */
88 CHECK_STATUS(ddr3_tip_if_read
89 (dev_num, ACCESS_TYPE_UNICAST, if_id,
Chris Packham1a07d212018-05-10 13:28:29 +120090 DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS));
Stefan Roese5ffceb82015-03-26 15:36:56 +010091 /* enable single cs */
92 CHECK_STATUS(ddr3_tip_if_write
93 (dev_num, ACCESS_TYPE_UNICAST, if_id,
Chris Packham1a07d212018-05-10 13:28:29 +120094 DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3)));
Stefan Roese5ffceb82015-03-26 15:36:56 +010095 }
96
97 if (mode == CENTRAL_TX) {
98 max_win_size = MAX_WINDOW_SIZE_TX;
Chris Packham1a07d212018-05-10 13:28:29 +120099 reg_phy_off = CTX_PHY_REG(effective_cs);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100100 direction = OPER_WRITE;
101 } else {
102 max_win_size = MAX_WINDOW_SIZE_RX;
Chris Packham1a07d212018-05-10 13:28:29 +1200103 reg_phy_off = CRX_PHY_REG(effective_cs);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100104 direction = OPER_READ;
105 }
106
107 /* DB initialization */
108 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200109 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100110 for (bus_id = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200111 bus_id < octets_per_if_num; bus_id++) {
112 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100113 centralization_state[if_id][bus_id] = 0;
114 bus_end_window[mode][if_id][bus_id] =
115 (max_win_size - 1) + cons_tap;
116 bus_start_window[mode][if_id][bus_id] = 0;
117 centralization_result[if_id][bus_id] = 0;
118 }
119 }
120
121 /* start flow */
122 for (pattern_id = start_pattern; pattern_id <= end_pattern;
123 pattern_id++) {
124 ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST,
125 PARAM_NOT_CARE,
126 ACCESS_TYPE_MULTICAST,
127 PARAM_NOT_CARE, result_type,
128 HWS_CONTROL_ELEMENT_ADLL,
129 PARAM_NOT_CARE, direction,
130 tm->
131 if_act_mask, 0x0,
132 max_win_size - 1,
133 max_win_size - 1,
134 pattern_id, EDGE_FPF, CS_SINGLE,
135 PARAM_NOT_CARE, training_result);
136
137 for (if_id = start_if; if_id <= end_if; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200138 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100139 for (bus_id = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200140 bus_id <= octets_per_if_num - 1;
Stefan Roese5ffceb82015-03-26 15:36:56 +0100141 bus_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200142 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100143
144 for (search_dir_id = HWS_LOW2HIGH;
145 search_dir_id <= HWS_HIGH2LOW;
146 search_dir_id++) {
147 CHECK_STATUS
148 (ddr3_tip_read_training_result
149 (dev_num, if_id,
150 ACCESS_TYPE_UNICAST, bus_id,
151 ALL_BITS_PER_PUP,
152 search_dir_id,
153 direction, result_type,
154 TRAINING_LOAD_OPERATION_UNLOAD,
155 CS_SINGLE,
156 &result[search_dir_id],
157 1, 0, 0));
158 DEBUG_CENTRALIZATION_ENGINE
159 (DEBUG_LEVEL_INFO,
160 ("%s pat %d IF %d pup %d Regs: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
161 ((mode ==
162 CENTRAL_TX) ? "TX" : "RX"),
163 pattern_id, if_id, bus_id,
164 result[search_dir_id][0],
165 result[search_dir_id][1],
166 result[search_dir_id][2],
167 result[search_dir_id][3],
168 result[search_dir_id][4],
169 result[search_dir_id][5],
170 result[search_dir_id][6],
171 result[search_dir_id][7]));
172 }
173
Marek BehĂșn9e2a9472022-01-12 17:06:59 +0100174 current_byte_status =
175 mv_ddr_tip_sub_phy_byte_status_get(if_id,
176 bus_id);
177
Stefan Roese5ffceb82015-03-26 15:36:56 +0100178 for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS;
179 bit_id++) {
180 /* check if this code is valid for 2 edge, probably not :( */
181 cur_start_win[bit_id] =
182 GET_TAP_RESULT(result
183 [HWS_LOW2HIGH]
184 [bit_id],
185 EDGE_1);
Marek BehĂșn9e2a9472022-01-12 17:06:59 +0100186 if (current_byte_status &
Marek BehĂșn532b7192022-02-17 01:08:37 +0100187 (BYTE_SPLIT_OUT_MIX |
188 BYTE_HOMOGENEOUS_SPLIT_OUT)) {
Marek BehĂșn9e2a9472022-01-12 17:06:59 +0100189 if (cur_start_win[bit_id] >= 64)
190 cur_start_win[bit_id] -= 64;
191 else
192 cur_start_win[bit_id] = 0;
193 DEBUG_CENTRALIZATION_ENGINE
194 (DEBUG_LEVEL_INFO,
195 ("pattern %d IF %d pup %d bit %d subtract 64 adll from start\n",
196 pattern_id, if_id, bus_id, bit_id));
197 }
Stefan Roese5ffceb82015-03-26 15:36:56 +0100198 cur_end_win[bit_id] =
199 GET_TAP_RESULT(result
200 [HWS_HIGH2LOW]
201 [bit_id],
202 EDGE_1);
Marek BehĂșn9e2a9472022-01-12 17:06:59 +0100203 if (cur_end_win[bit_id] >= 64 &&
204 (current_byte_status &
Marek BehĂșn532b7192022-02-17 01:08:37 +0100205 (BYTE_SPLIT_OUT_MIX |
206 BYTE_HOMOGENEOUS_SPLIT_OUT))) {
Marek BehĂșn9e2a9472022-01-12 17:06:59 +0100207 cur_end_win[bit_id] -= 64;
208 DEBUG_CENTRALIZATION_ENGINE
209 (DEBUG_LEVEL_INFO,
210 ("pattern %d IF %d pup %d bit %d subtract 64 adll from end\n",
211 pattern_id, if_id, bus_id, bit_id));
212 }
213
Stefan Roese5ffceb82015-03-26 15:36:56 +0100214 /* window length */
215 current_window[bit_id] =
216 cur_end_win[bit_id] -
217 cur_start_win[bit_id] + 1;
218 DEBUG_CENTRALIZATION_ENGINE
219 (DEBUG_LEVEL_TRACE,
220 ("cs %x patern %d IF %d pup %d cur_start_win %d cur_end_win %d current_window %d\n",
221 effective_cs, pattern_id,
222 if_id, bus_id,
223 cur_start_win[bit_id],
224 cur_end_win[bit_id],
225 current_window[bit_id]));
226 }
227
228 if ((ddr3_tip_is_pup_lock
229 (result[HWS_LOW2HIGH], result_type)) &&
230 (ddr3_tip_is_pup_lock
231 (result[HWS_HIGH2LOW], result_type))) {
232 /* read result success */
233 DEBUG_CENTRALIZATION_ENGINE
234 (DEBUG_LEVEL_INFO,
235 ("Pup locked, pat %d IF %d pup %d\n",
236 pattern_id, if_id, bus_id));
237 } else {
238 /* read result failure */
239 DEBUG_CENTRALIZATION_ENGINE
240 (DEBUG_LEVEL_INFO,
241 ("fail Lock, pat %d IF %d pup %d\n",
242 pattern_id, if_id, bus_id));
243 if (centralization_state[if_id][bus_id]
244 == 1) {
245 /* continue with next pup */
246 DEBUG_CENTRALIZATION_ENGINE
247 (DEBUG_LEVEL_TRACE,
248 ("continue to next pup %d %d\n",
249 if_id, bus_id));
250 continue;
251 }
252
253 for (bit_id = 0;
254 bit_id < BUS_WIDTH_IN_BITS;
255 bit_id++) {
256 /*
257 * the next check is relevant
258 * only when using search
259 * machine 2 edges
260 */
261 if (cur_start_win[bit_id] > 0 &&
262 cur_end_win[bit_id] == 0) {
263 cur_end_win
264 [bit_id] =
265 max_win_size - 1;
266 DEBUG_CENTRALIZATION_ENGINE
267 (DEBUG_LEVEL_TRACE,
268 ("fail, IF %d pup %d bit %d fail #1\n",
269 if_id, bus_id,
270 bit_id));
271 /* the next bit */
272 continue;
273 } else {
274 centralization_state
275 [if_id][bus_id] = 1;
276 DEBUG_CENTRALIZATION_ENGINE
277 (DEBUG_LEVEL_TRACE,
278 ("fail, IF %d pup %d bit %d fail #2\n",
279 if_id, bus_id,
280 bit_id));
281 }
282 }
283
284 if (centralization_state[if_id][bus_id]
285 == 1) {
286 /* going to next pup */
287 continue;
288 }
289 } /*bit */
290
291 opt_window =
292 ddr3_tip_get_buf_min(current_window);
293 /* final pup window length */
294 final_pup_window[if_id][bus_id] =
295 ddr3_tip_get_buf_min(cur_end_win) -
296 ddr3_tip_get_buf_max(cur_start_win) +
297 1;
298 waste_window =
299 opt_window -
300 final_pup_window[if_id][bus_id];
301 start_window_skew =
302 ddr3_tip_get_buf_max(cur_start_win) -
303 ddr3_tip_get_buf_min(
304 cur_start_win);
305 end_window_skew =
306 ddr3_tip_get_buf_max(
307 cur_end_win) -
308 ddr3_tip_get_buf_min(
309 cur_end_win);
310 /* min/max updated with pattern change */
311 cur_end_win_min =
312 ddr3_tip_get_buf_min(
313 cur_end_win);
314 cur_start_win_max =
315 ddr3_tip_get_buf_max(
316 cur_start_win);
317 bus_end_window[mode][if_id][bus_id] =
318 GET_MIN(bus_end_window[mode][if_id]
319 [bus_id],
320 cur_end_win_min);
321 bus_start_window[mode][if_id][bus_id] =
322 GET_MAX(bus_start_window[mode][if_id]
323 [bus_id],
324 cur_start_win_max);
325 DEBUG_CENTRALIZATION_ENGINE(
326 DEBUG_LEVEL_INFO,
327 ("pat %d IF %d pup %d opt_win %d final_win %d waste_win %d st_win_skew %d end_win_skew %d cur_st_win_max %d cur_end_win_min %d bus_st_win %d bus_end_win %d\n",
328 pattern_id, if_id, bus_id, opt_window,
329 final_pup_window[if_id][bus_id],
330 waste_window, start_window_skew,
331 end_window_skew,
332 cur_start_win_max,
333 cur_end_win_min,
334 bus_start_window[mode][if_id][bus_id],
335 bus_end_window[mode][if_id][bus_id]));
336
337 /* check if window is valid */
338 if (ddr3_tip_centr_skip_min_win_check == 0) {
339 if ((VALIDATE_WIN_LENGTH
340 (bus_start_window[mode][if_id]
341 [bus_id],
342 bus_end_window[mode][if_id]
343 [bus_id],
344 max_win_size) == 1) ||
345 (IS_WINDOW_OUT_BOUNDARY
346 (bus_start_window[mode][if_id]
347 [bus_id],
348 bus_end_window[mode][if_id]
349 [bus_id],
350 max_win_size) == 1)) {
351 DEBUG_CENTRALIZATION_ENGINE
352 (DEBUG_LEVEL_INFO,
353 ("win valid, pat %d IF %d pup %d\n",
354 pattern_id, if_id,
355 bus_id));
356 /* window is valid */
357 } else {
358 DEBUG_CENTRALIZATION_ENGINE
359 (DEBUG_LEVEL_INFO,
360 ("fail win, pat %d IF %d pup %d bus_st_win %d bus_end_win %d\n",
361 pattern_id, if_id, bus_id,
362 bus_start_window[mode]
363 [if_id][bus_id],
364 bus_end_window[mode]
365 [if_id][bus_id]));
366 centralization_state[if_id]
367 [bus_id] = 1;
Chris Packham1a07d212018-05-10 13:28:29 +1200368 if (debug_mode == 0) {
369 flow_result[if_id] = TEST_FAILED;
Stefan Roese5ffceb82015-03-26 15:36:56 +0100370 return MV_FAIL;
Chris Packham1a07d212018-05-10 13:28:29 +1200371 }
Stefan Roese5ffceb82015-03-26 15:36:56 +0100372 }
373 } /* ddr3_tip_centr_skip_min_win_check */
374 } /* pup */
375 } /* interface */
376 } /* pattern */
377
378 for (if_id = start_if; if_id <= end_if; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200379 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100380
381 is_if_fail = 0;
382 flow_result[if_id] = TEST_SUCCESS;
383
384 for (bus_id = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200385 bus_id <= (octets_per_if_num - 1); bus_id++) {
386 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100387
388 /* continue only if lock */
389 if (centralization_state[if_id][bus_id] != 1) {
390 if (ddr3_tip_centr_skip_min_win_check == 0) {
391 if ((bus_end_window
392 [mode][if_id][bus_id] ==
393 (max_win_size - 1)) &&
394 ((bus_end_window
395 [mode][if_id][bus_id] -
396 bus_start_window[mode][if_id]
397 [bus_id]) < MIN_WINDOW_SIZE) &&
398 ((bus_end_window[mode][if_id]
399 [bus_id] - bus_start_window
400 [mode][if_id][bus_id]) > 2)) {
401 /* prevent false lock */
402 /* TBD change to enum */
403 centralization_state
404 [if_id][bus_id] = 2;
405 }
406
407 if ((bus_end_window[mode][if_id][bus_id]
408 == 0) &&
409 ((bus_end_window[mode][if_id]
410 [bus_id] -
411 bus_start_window[mode][if_id]
412 [bus_id]) < MIN_WINDOW_SIZE) &&
413 ((bus_end_window[mode][if_id]
414 [bus_id] -
415 bus_start_window[mode][if_id]
416 [bus_id]) > 2))
417 /*prevent false lock */
418 centralization_state[if_id]
419 [bus_id] = 3;
420 }
421
422 if ((bus_end_window[mode][if_id][bus_id] >
423 (max_win_size - 1)) && direction ==
424 OPER_WRITE) {
425 DEBUG_CENTRALIZATION_ENGINE
426 (DEBUG_LEVEL_INFO,
427 ("Tx special pattern\n"));
428 cons_tap = 64;
429 }
430 }
431
432 /* check states */
433 if (centralization_state[if_id][bus_id] == 3) {
434 DEBUG_CENTRALIZATION_ENGINE(
435 DEBUG_LEVEL_INFO,
436 ("SSW - TBD IF %d pup %d\n",
437 if_id, bus_id));
438 lock_success = 1;
439 } else if (centralization_state[if_id][bus_id] == 2) {
440 DEBUG_CENTRALIZATION_ENGINE(
441 DEBUG_LEVEL_INFO,
442 ("SEW - TBD IF %d pup %d\n",
443 if_id, bus_id));
444 lock_success = 1;
445 } else if (centralization_state[if_id][bus_id] == 0) {
446 lock_success = 1;
447 } else {
448 DEBUG_CENTRALIZATION_ENGINE(
449 DEBUG_LEVEL_ERROR,
450 ("fail, IF %d pup %d\n",
451 if_id, bus_id));
452 lock_success = 0;
453 }
454
455 if (lock_success == 1) {
456 centralization_result[if_id][bus_id] =
457 (bus_end_window[mode][if_id][bus_id] +
458 bus_start_window[mode][if_id][bus_id])
459 / 2 - cons_tap;
460 DEBUG_CENTRALIZATION_ENGINE(
461 DEBUG_LEVEL_TRACE,
462 (" bus_id %d Res= %d\n", bus_id,
463 centralization_result[if_id][bus_id]));
464 /* copy results to registers */
465 pup_win_length =
466 bus_end_window[mode][if_id][bus_id] -
467 bus_start_window[mode][if_id][bus_id] +
468 1;
469
470 ddr3_tip_bus_read(dev_num, if_id,
471 ACCESS_TYPE_UNICAST, bus_id,
472 DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200473 RESULT_PHY_REG +
Stefan Roese5ffceb82015-03-26 15:36:56 +0100474 effective_cs, &reg);
475 reg = (reg & (~0x1f <<
476 ((mode == CENTRAL_TX) ?
Chris Packham1a07d212018-05-10 13:28:29 +1200477 (RESULT_PHY_TX_OFFS) :
478 (RESULT_PHY_RX_OFFS))))
Stefan Roese5ffceb82015-03-26 15:36:56 +0100479 | pup_win_length <<
480 ((mode == CENTRAL_TX) ?
Chris Packham1a07d212018-05-10 13:28:29 +1200481 (RESULT_PHY_TX_OFFS) :
482 (RESULT_PHY_RX_OFFS));
Stefan Roese5ffceb82015-03-26 15:36:56 +0100483 CHECK_STATUS(ddr3_tip_bus_write
484 (dev_num, ACCESS_TYPE_UNICAST,
485 if_id, ACCESS_TYPE_UNICAST,
486 bus_id, DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200487 RESULT_PHY_REG +
Stefan Roese5ffceb82015-03-26 15:36:56 +0100488 effective_cs, reg));
489
490 /* offset per CS is calculated earlier */
491 CHECK_STATUS(
492 ddr3_tip_bus_write(dev_num,
493 ACCESS_TYPE_UNICAST,
494 if_id,
495 ACCESS_TYPE_UNICAST,
496 bus_id,
497 DDR_PHY_DATA,
498 reg_phy_off,
499 centralization_result
500 [if_id]
501 [bus_id]));
502 } else {
503 is_if_fail = 1;
504 }
505 }
506
507 if (is_if_fail == 1)
508 flow_result[if_id] = TEST_FAILED;
509 }
510
511 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
512 /* restore cs enable value */
Chris Packham1a07d212018-05-10 13:28:29 +1200513 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100514 CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST,
Chris Packham1a07d212018-05-10 13:28:29 +1200515 if_id, DUAL_DUNIT_CFG_REG,
Stefan Roese5ffceb82015-03-26 15:36:56 +0100516 cs_enable_reg_val[if_id],
517 MASK_ALL_BITS));
518 }
519
520 return is_if_fail;
521}
522
523/*
524 * Centralization Flow
525 */
526int ddr3_tip_special_rx(u32 dev_num)
527{
528 enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM];
529 u32 if_id, pup_id, pattern_id, bit_id;
530 u8 cur_start_win[BUS_WIDTH_IN_BITS];
531 u8 cur_end_win[BUS_WIDTH_IN_BITS];
532 enum hws_training_result result_type = RESULT_PER_BIT;
533 enum hws_dir direction;
534 enum hws_search_dir search_dir_id;
535 u32 *result[HWS_SEARCH_DIR_LIMIT];
536 u32 max_win_size;
537 u8 cur_end_win_min, cur_start_win_max;
538 u32 cs_enable_reg_val[MAX_INTERFACE_NUM];
539 u32 temp = 0;
540 int pad_num = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200541 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
542 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
Stefan Roese5ffceb82015-03-26 15:36:56 +0100543
Chris Packham1a07d212018-05-10 13:28:29 +1200544 if ((ddr3_tip_special_rx_run_once_flag & (1 << effective_cs)) == (1 << effective_cs))
Stefan Roese5ffceb82015-03-26 15:36:56 +0100545 return MV_OK;
546
Chris Packham1a07d212018-05-10 13:28:29 +1200547 ddr3_tip_special_rx_run_once_flag |= (1 << effective_cs);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100548
549 for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200550 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100551 /* save current cs enable reg val */
552 CHECK_STATUS(ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST,
Chris Packham1a07d212018-05-10 13:28:29 +1200553 if_id, DUAL_DUNIT_CFG_REG,
Stefan Roese5ffceb82015-03-26 15:36:56 +0100554 cs_enable_reg_val,
555 MASK_ALL_BITS));
556 /* enable single cs */
557 CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST,
Chris Packham1a07d212018-05-10 13:28:29 +1200558 if_id, DUAL_DUNIT_CFG_REG,
Stefan Roese5ffceb82015-03-26 15:36:56 +0100559 (1 << 3), (1 << 3)));
560 }
561
562 max_win_size = MAX_WINDOW_SIZE_RX;
563 direction = OPER_READ;
Chris Packham1a07d212018-05-10 13:28:29 +1200564 pattern_id = PATTERN_FULL_SSO1;
Stefan Roese5ffceb82015-03-26 15:36:56 +0100565
566 /* start flow */
567 ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST,
568 PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
569 PARAM_NOT_CARE, result_type,
570 HWS_CONTROL_ELEMENT_ADLL,
571 PARAM_NOT_CARE, direction,
572 tm->if_act_mask, 0x0,
573 max_win_size - 1, max_win_size - 1,
574 pattern_id, EDGE_FPF, CS_SINGLE,
575 PARAM_NOT_CARE, training_result);
576
577 for (if_id = start_if; if_id <= end_if; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200578 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100579 for (pup_id = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200580 pup_id <= octets_per_if_num; pup_id++) {
581 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100582
583 for (search_dir_id = HWS_LOW2HIGH;
584 search_dir_id <= HWS_HIGH2LOW;
585 search_dir_id++) {
586 CHECK_STATUS(ddr3_tip_read_training_result
587 (dev_num, if_id,
588 ACCESS_TYPE_UNICAST, pup_id,
589 ALL_BITS_PER_PUP, search_dir_id,
590 direction, result_type,
591 TRAINING_LOAD_OPERATION_UNLOAD,
592 CS_SINGLE, &result[search_dir_id],
593 1, 0, 0));
594 DEBUG_CENTRALIZATION_ENGINE(DEBUG_LEVEL_INFO,
595 ("Special: pat %d IF %d pup %d Regs: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
596 pattern_id, if_id,
597 pup_id,
598 result
599 [search_dir_id][0],
600 result
601 [search_dir_id][1],
602 result
603 [search_dir_id][2],
604 result
605 [search_dir_id][3],
606 result
607 [search_dir_id][4],
608 result
609 [search_dir_id][5],
610 result
611 [search_dir_id][6],
612 result
613 [search_dir_id]
614 [7]));
615 }
616
617 for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS; bit_id++) {
618 /*
619 * check if this code is valid for 2 edge,
620 * probably not :(
621 */
622 cur_start_win[bit_id] =
623 GET_TAP_RESULT(result[HWS_LOW2HIGH]
624 [bit_id], EDGE_1);
625 cur_end_win[bit_id] =
626 GET_TAP_RESULT(result[HWS_HIGH2LOW]
627 [bit_id], EDGE_1);
628 }
629 if (!((ddr3_tip_is_pup_lock
630 (result[HWS_LOW2HIGH], result_type)) &&
631 (ddr3_tip_is_pup_lock
632 (result[HWS_HIGH2LOW], result_type)))) {
633 DEBUG_CENTRALIZATION_ENGINE(
634 DEBUG_LEVEL_ERROR,
635 ("Special: Pup lock fail, pat %d IF %d pup %d\n",
636 pattern_id, if_id, pup_id));
637 return MV_FAIL;
638 }
639
640 cur_end_win_min =
641 ddr3_tip_get_buf_min(cur_end_win);
642 cur_start_win_max =
643 ddr3_tip_get_buf_max(cur_start_win);
644
645 if (cur_start_win_max <= 1) { /* Align left */
646 for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS;
647 bit_id++) {
648 pad_num =
649 dq_map_table[bit_id +
650 pup_id *
651 BUS_WIDTH_IN_BITS +
652 if_id *
653 BUS_WIDTH_IN_BITS *
Chris Packham1a07d212018-05-10 13:28:29 +1200654 MAX_BUS_NUM];
Stefan Roese5ffceb82015-03-26 15:36:56 +0100655 CHECK_STATUS(ddr3_tip_bus_read
656 (dev_num, if_id,
657 ACCESS_TYPE_UNICAST,
658 pup_id, DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200659 PBS_RX_PHY_REG(effective_cs, pad_num),
Stefan Roese5ffceb82015-03-26 15:36:56 +0100660 &temp));
661 temp = (temp + 0xa > 31) ?
662 (31) : (temp + 0xa);
663 CHECK_STATUS(ddr3_tip_bus_write
664 (dev_num,
665 ACCESS_TYPE_UNICAST,
666 if_id,
667 ACCESS_TYPE_UNICAST,
668 pup_id, DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200669 PBS_RX_PHY_REG(effective_cs, pad_num),
Stefan Roese5ffceb82015-03-26 15:36:56 +0100670 temp));
671 }
672 DEBUG_CENTRALIZATION_ENGINE(
673 DEBUG_LEVEL_INFO,
674 ("Special: PBS:: I/F# %d , Bus# %d fix align to the Left\n",
675 if_id, pup_id));
676 }
677
678 if (cur_end_win_min > 30) { /* Align right */
679 CHECK_STATUS(ddr3_tip_bus_read
680 (dev_num, if_id,
681 ACCESS_TYPE_UNICAST, pup_id,
Chris Packham1a07d212018-05-10 13:28:29 +1200682 DDR_PHY_DATA,
683 PBS_RX_PHY_REG(effective_cs, 4),
Stefan Roese5ffceb82015-03-26 15:36:56 +0100684 &temp));
685 temp += 0xa;
686 CHECK_STATUS(ddr3_tip_bus_write
687 (dev_num, ACCESS_TYPE_UNICAST,
688 if_id, ACCESS_TYPE_UNICAST,
689 pup_id, DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200690 PBS_RX_PHY_REG(effective_cs, 4),
691 temp));
Stefan Roese5ffceb82015-03-26 15:36:56 +0100692 CHECK_STATUS(ddr3_tip_bus_read
693 (dev_num, if_id,
694 ACCESS_TYPE_UNICAST, pup_id,
Chris Packham1a07d212018-05-10 13:28:29 +1200695 DDR_PHY_DATA,
696 PBS_RX_PHY_REG(effective_cs, 5),
Stefan Roese5ffceb82015-03-26 15:36:56 +0100697 &temp));
698 temp += 0xa;
699 CHECK_STATUS(ddr3_tip_bus_write
700 (dev_num, ACCESS_TYPE_UNICAST,
701 if_id, ACCESS_TYPE_UNICAST,
702 pup_id, DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200703 PBS_RX_PHY_REG(effective_cs, 5),
704 temp));
Stefan Roese5ffceb82015-03-26 15:36:56 +0100705 DEBUG_CENTRALIZATION_ENGINE(
706 DEBUG_LEVEL_INFO,
707 ("Special: PBS:: I/F# %d , Bus# %d fix align to the right\n",
708 if_id, pup_id));
709 }
710
711 vref_window_size[if_id][pup_id] =
712 cur_end_win_min -
713 cur_start_win_max + 1;
714 DEBUG_CENTRALIZATION_ENGINE(
715 DEBUG_LEVEL_INFO,
716 ("Special: Winsize I/F# %d , Bus# %d is %d\n",
717 if_id, pup_id, vref_window_size
718 [if_id][pup_id]));
719 } /* pup */
720 } /* end of interface */
721
722 return MV_OK;
723}
724
725/*
726 * Print Centralization Result
727 */
728int ddr3_tip_print_centralization_result(u32 dev_num)
729{
730 u32 if_id = 0, bus_id = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200731 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
732 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
Stefan Roese5ffceb82015-03-26 15:36:56 +0100733
Chris Packham4bf81db2018-12-03 14:26:49 +1300734 dev_num = dev_num;
735
Stefan Roese5ffceb82015-03-26 15:36:56 +0100736 printf("Centralization Results\n");
737 printf("I/F0 Result[0 - success 1-fail 2 - state_2 3 - state_3] ...\n");
738 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200739 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
740 for (bus_id = 0; bus_id < octets_per_if_num;
Stefan Roese5ffceb82015-03-26 15:36:56 +0100741 bus_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200742 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100743 printf("%d ,\n", centralization_state[if_id][bus_id]);
744 }
745 }
746
747 return MV_OK;
748}