blob: 648b37ef6f7922e7eb8eac16b655c0307694dd45 [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
19u32 start_pattern = PATTERN_KILLER_DQ0, end_pattern = PATTERN_KILLER_DQ7;
Chris Packham1a07d212018-05-10 13:28:29 +120020
Stefan Roese5ffceb82015-03-26 15:36:56 +010021u32 start_if = 0, end_if = (MAX_INTERFACE_NUM - 1);
22u8 bus_end_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM];
23u8 bus_start_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM];
24u8 centralization_state[MAX_INTERFACE_NUM][MAX_BUS_NUM];
25static u8 ddr3_tip_special_rx_run_once_flag;
26
27static int ddr3_tip_centralization(u32 dev_num, u32 mode);
28
29/*
30 * Centralization RX Flow
31 */
32int ddr3_tip_centralization_rx(u32 dev_num)
33{
34 CHECK_STATUS(ddr3_tip_special_rx(dev_num));
35 CHECK_STATUS(ddr3_tip_centralization(dev_num, CENTRAL_RX));
36
37 return MV_OK;
38}
39
40/*
41 * Centralization TX Flow
42 */
43int ddr3_tip_centralization_tx(u32 dev_num)
44{
45 CHECK_STATUS(ddr3_tip_centralization(dev_num, CENTRAL_TX));
46
47 return MV_OK;
48}
49
50/*
51 * Centralization Flow
52 */
53static int ddr3_tip_centralization(u32 dev_num, u32 mode)
54{
55 enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM];
56 u32 if_id, pattern_id, bit_id;
57 u8 bus_id;
58 u8 cur_start_win[BUS_WIDTH_IN_BITS];
59 u8 centralization_result[MAX_INTERFACE_NUM][BUS_WIDTH_IN_BITS];
60 u8 cur_end_win[BUS_WIDTH_IN_BITS];
61 u8 current_window[BUS_WIDTH_IN_BITS];
62 u8 opt_window, waste_window, start_window_skew, end_window_skew;
63 u8 final_pup_window[MAX_INTERFACE_NUM][BUS_WIDTH_IN_BITS];
Chris Packham1a07d212018-05-10 13:28:29 +120064 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
65 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
Stefan Roese5ffceb82015-03-26 15:36:56 +010066 enum hws_training_result result_type = RESULT_PER_BIT;
67 enum hws_dir direction;
68 u32 *result[HWS_SEARCH_DIR_LIMIT];
69 u32 reg_phy_off, reg;
70 u8 max_win_size;
71 int lock_success = 1;
72 u8 cur_end_win_min, cur_start_win_max;
73 u32 cs_enable_reg_val[MAX_INTERFACE_NUM];
74 int is_if_fail = 0;
75 enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage);
76 u32 pup_win_length = 0;
77 enum hws_search_dir search_dir_id;
78 u8 cons_tap = (mode == CENTRAL_TX) ? (64) : (0);
79
80 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +120081 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +010082 /* save current cs enable reg val */
83 CHECK_STATUS(ddr3_tip_if_read
84 (dev_num, ACCESS_TYPE_UNICAST, if_id,
Chris Packham1a07d212018-05-10 13:28:29 +120085 DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS));
Stefan Roese5ffceb82015-03-26 15:36:56 +010086 /* enable single cs */
87 CHECK_STATUS(ddr3_tip_if_write
88 (dev_num, ACCESS_TYPE_UNICAST, if_id,
Chris Packham1a07d212018-05-10 13:28:29 +120089 DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3)));
Stefan Roese5ffceb82015-03-26 15:36:56 +010090 }
91
92 if (mode == CENTRAL_TX) {
93 max_win_size = MAX_WINDOW_SIZE_TX;
Chris Packham1a07d212018-05-10 13:28:29 +120094 reg_phy_off = CTX_PHY_REG(effective_cs);
Stefan Roese5ffceb82015-03-26 15:36:56 +010095 direction = OPER_WRITE;
96 } else {
97 max_win_size = MAX_WINDOW_SIZE_RX;
Chris Packham1a07d212018-05-10 13:28:29 +120098 reg_phy_off = CRX_PHY_REG(effective_cs);
Stefan Roese5ffceb82015-03-26 15:36:56 +010099 direction = OPER_READ;
100 }
101
102 /* DB initialization */
103 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200104 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100105 for (bus_id = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200106 bus_id < octets_per_if_num; bus_id++) {
107 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100108 centralization_state[if_id][bus_id] = 0;
109 bus_end_window[mode][if_id][bus_id] =
110 (max_win_size - 1) + cons_tap;
111 bus_start_window[mode][if_id][bus_id] = 0;
112 centralization_result[if_id][bus_id] = 0;
113 }
114 }
115
116 /* start flow */
117 for (pattern_id = start_pattern; pattern_id <= end_pattern;
118 pattern_id++) {
119 ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST,
120 PARAM_NOT_CARE,
121 ACCESS_TYPE_MULTICAST,
122 PARAM_NOT_CARE, result_type,
123 HWS_CONTROL_ELEMENT_ADLL,
124 PARAM_NOT_CARE, direction,
125 tm->
126 if_act_mask, 0x0,
127 max_win_size - 1,
128 max_win_size - 1,
129 pattern_id, EDGE_FPF, CS_SINGLE,
130 PARAM_NOT_CARE, training_result);
131
132 for (if_id = start_if; if_id <= end_if; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200133 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100134 for (bus_id = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200135 bus_id <= octets_per_if_num - 1;
Stefan Roese5ffceb82015-03-26 15:36:56 +0100136 bus_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200137 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100138
139 for (search_dir_id = HWS_LOW2HIGH;
140 search_dir_id <= HWS_HIGH2LOW;
141 search_dir_id++) {
142 CHECK_STATUS
143 (ddr3_tip_read_training_result
144 (dev_num, if_id,
145 ACCESS_TYPE_UNICAST, bus_id,
146 ALL_BITS_PER_PUP,
147 search_dir_id,
148 direction, result_type,
149 TRAINING_LOAD_OPERATION_UNLOAD,
150 CS_SINGLE,
151 &result[search_dir_id],
152 1, 0, 0));
153 DEBUG_CENTRALIZATION_ENGINE
154 (DEBUG_LEVEL_INFO,
155 ("%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",
156 ((mode ==
157 CENTRAL_TX) ? "TX" : "RX"),
158 pattern_id, if_id, bus_id,
159 result[search_dir_id][0],
160 result[search_dir_id][1],
161 result[search_dir_id][2],
162 result[search_dir_id][3],
163 result[search_dir_id][4],
164 result[search_dir_id][5],
165 result[search_dir_id][6],
166 result[search_dir_id][7]));
167 }
168
169 for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS;
170 bit_id++) {
171 /* check if this code is valid for 2 edge, probably not :( */
172 cur_start_win[bit_id] =
173 GET_TAP_RESULT(result
174 [HWS_LOW2HIGH]
175 [bit_id],
176 EDGE_1);
177 cur_end_win[bit_id] =
178 GET_TAP_RESULT(result
179 [HWS_HIGH2LOW]
180 [bit_id],
181 EDGE_1);
182 /* window length */
183 current_window[bit_id] =
184 cur_end_win[bit_id] -
185 cur_start_win[bit_id] + 1;
186 DEBUG_CENTRALIZATION_ENGINE
187 (DEBUG_LEVEL_TRACE,
188 ("cs %x patern %d IF %d pup %d cur_start_win %d cur_end_win %d current_window %d\n",
189 effective_cs, pattern_id,
190 if_id, bus_id,
191 cur_start_win[bit_id],
192 cur_end_win[bit_id],
193 current_window[bit_id]));
194 }
195
196 if ((ddr3_tip_is_pup_lock
197 (result[HWS_LOW2HIGH], result_type)) &&
198 (ddr3_tip_is_pup_lock
199 (result[HWS_HIGH2LOW], result_type))) {
200 /* read result success */
201 DEBUG_CENTRALIZATION_ENGINE
202 (DEBUG_LEVEL_INFO,
203 ("Pup locked, pat %d IF %d pup %d\n",
204 pattern_id, if_id, bus_id));
205 } else {
206 /* read result failure */
207 DEBUG_CENTRALIZATION_ENGINE
208 (DEBUG_LEVEL_INFO,
209 ("fail Lock, pat %d IF %d pup %d\n",
210 pattern_id, if_id, bus_id));
211 if (centralization_state[if_id][bus_id]
212 == 1) {
213 /* continue with next pup */
214 DEBUG_CENTRALIZATION_ENGINE
215 (DEBUG_LEVEL_TRACE,
216 ("continue to next pup %d %d\n",
217 if_id, bus_id));
218 continue;
219 }
220
221 for (bit_id = 0;
222 bit_id < BUS_WIDTH_IN_BITS;
223 bit_id++) {
224 /*
225 * the next check is relevant
226 * only when using search
227 * machine 2 edges
228 */
229 if (cur_start_win[bit_id] > 0 &&
230 cur_end_win[bit_id] == 0) {
231 cur_end_win
232 [bit_id] =
233 max_win_size - 1;
234 DEBUG_CENTRALIZATION_ENGINE
235 (DEBUG_LEVEL_TRACE,
236 ("fail, IF %d pup %d bit %d fail #1\n",
237 if_id, bus_id,
238 bit_id));
239 /* the next bit */
240 continue;
241 } else {
242 centralization_state
243 [if_id][bus_id] = 1;
244 DEBUG_CENTRALIZATION_ENGINE
245 (DEBUG_LEVEL_TRACE,
246 ("fail, IF %d pup %d bit %d fail #2\n",
247 if_id, bus_id,
248 bit_id));
249 }
250 }
251
252 if (centralization_state[if_id][bus_id]
253 == 1) {
254 /* going to next pup */
255 continue;
256 }
257 } /*bit */
258
259 opt_window =
260 ddr3_tip_get_buf_min(current_window);
261 /* final pup window length */
262 final_pup_window[if_id][bus_id] =
263 ddr3_tip_get_buf_min(cur_end_win) -
264 ddr3_tip_get_buf_max(cur_start_win) +
265 1;
266 waste_window =
267 opt_window -
268 final_pup_window[if_id][bus_id];
269 start_window_skew =
270 ddr3_tip_get_buf_max(cur_start_win) -
271 ddr3_tip_get_buf_min(
272 cur_start_win);
273 end_window_skew =
274 ddr3_tip_get_buf_max(
275 cur_end_win) -
276 ddr3_tip_get_buf_min(
277 cur_end_win);
278 /* min/max updated with pattern change */
279 cur_end_win_min =
280 ddr3_tip_get_buf_min(
281 cur_end_win);
282 cur_start_win_max =
283 ddr3_tip_get_buf_max(
284 cur_start_win);
285 bus_end_window[mode][if_id][bus_id] =
286 GET_MIN(bus_end_window[mode][if_id]
287 [bus_id],
288 cur_end_win_min);
289 bus_start_window[mode][if_id][bus_id] =
290 GET_MAX(bus_start_window[mode][if_id]
291 [bus_id],
292 cur_start_win_max);
293 DEBUG_CENTRALIZATION_ENGINE(
294 DEBUG_LEVEL_INFO,
295 ("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",
296 pattern_id, if_id, bus_id, opt_window,
297 final_pup_window[if_id][bus_id],
298 waste_window, start_window_skew,
299 end_window_skew,
300 cur_start_win_max,
301 cur_end_win_min,
302 bus_start_window[mode][if_id][bus_id],
303 bus_end_window[mode][if_id][bus_id]));
304
305 /* check if window is valid */
306 if (ddr3_tip_centr_skip_min_win_check == 0) {
307 if ((VALIDATE_WIN_LENGTH
308 (bus_start_window[mode][if_id]
309 [bus_id],
310 bus_end_window[mode][if_id]
311 [bus_id],
312 max_win_size) == 1) ||
313 (IS_WINDOW_OUT_BOUNDARY
314 (bus_start_window[mode][if_id]
315 [bus_id],
316 bus_end_window[mode][if_id]
317 [bus_id],
318 max_win_size) == 1)) {
319 DEBUG_CENTRALIZATION_ENGINE
320 (DEBUG_LEVEL_INFO,
321 ("win valid, pat %d IF %d pup %d\n",
322 pattern_id, if_id,
323 bus_id));
324 /* window is valid */
325 } else {
326 DEBUG_CENTRALIZATION_ENGINE
327 (DEBUG_LEVEL_INFO,
328 ("fail win, pat %d IF %d pup %d bus_st_win %d bus_end_win %d\n",
329 pattern_id, if_id, bus_id,
330 bus_start_window[mode]
331 [if_id][bus_id],
332 bus_end_window[mode]
333 [if_id][bus_id]));
334 centralization_state[if_id]
335 [bus_id] = 1;
Chris Packham1a07d212018-05-10 13:28:29 +1200336 if (debug_mode == 0) {
337 flow_result[if_id] = TEST_FAILED;
Stefan Roese5ffceb82015-03-26 15:36:56 +0100338 return MV_FAIL;
Chris Packham1a07d212018-05-10 13:28:29 +1200339 }
Stefan Roese5ffceb82015-03-26 15:36:56 +0100340 }
341 } /* ddr3_tip_centr_skip_min_win_check */
342 } /* pup */
343 } /* interface */
344 } /* pattern */
345
346 for (if_id = start_if; if_id <= end_if; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200347 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100348
349 is_if_fail = 0;
350 flow_result[if_id] = TEST_SUCCESS;
351
352 for (bus_id = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200353 bus_id <= (octets_per_if_num - 1); bus_id++) {
354 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100355
356 /* continue only if lock */
357 if (centralization_state[if_id][bus_id] != 1) {
358 if (ddr3_tip_centr_skip_min_win_check == 0) {
359 if ((bus_end_window
360 [mode][if_id][bus_id] ==
361 (max_win_size - 1)) &&
362 ((bus_end_window
363 [mode][if_id][bus_id] -
364 bus_start_window[mode][if_id]
365 [bus_id]) < MIN_WINDOW_SIZE) &&
366 ((bus_end_window[mode][if_id]
367 [bus_id] - bus_start_window
368 [mode][if_id][bus_id]) > 2)) {
369 /* prevent false lock */
370 /* TBD change to enum */
371 centralization_state
372 [if_id][bus_id] = 2;
373 }
374
375 if ((bus_end_window[mode][if_id][bus_id]
376 == 0) &&
377 ((bus_end_window[mode][if_id]
378 [bus_id] -
379 bus_start_window[mode][if_id]
380 [bus_id]) < MIN_WINDOW_SIZE) &&
381 ((bus_end_window[mode][if_id]
382 [bus_id] -
383 bus_start_window[mode][if_id]
384 [bus_id]) > 2))
385 /*prevent false lock */
386 centralization_state[if_id]
387 [bus_id] = 3;
388 }
389
390 if ((bus_end_window[mode][if_id][bus_id] >
391 (max_win_size - 1)) && direction ==
392 OPER_WRITE) {
393 DEBUG_CENTRALIZATION_ENGINE
394 (DEBUG_LEVEL_INFO,
395 ("Tx special pattern\n"));
396 cons_tap = 64;
397 }
398 }
399
400 /* check states */
401 if (centralization_state[if_id][bus_id] == 3) {
402 DEBUG_CENTRALIZATION_ENGINE(
403 DEBUG_LEVEL_INFO,
404 ("SSW - TBD IF %d pup %d\n",
405 if_id, bus_id));
406 lock_success = 1;
407 } else if (centralization_state[if_id][bus_id] == 2) {
408 DEBUG_CENTRALIZATION_ENGINE(
409 DEBUG_LEVEL_INFO,
410 ("SEW - TBD IF %d pup %d\n",
411 if_id, bus_id));
412 lock_success = 1;
413 } else if (centralization_state[if_id][bus_id] == 0) {
414 lock_success = 1;
415 } else {
416 DEBUG_CENTRALIZATION_ENGINE(
417 DEBUG_LEVEL_ERROR,
418 ("fail, IF %d pup %d\n",
419 if_id, bus_id));
420 lock_success = 0;
421 }
422
423 if (lock_success == 1) {
424 centralization_result[if_id][bus_id] =
425 (bus_end_window[mode][if_id][bus_id] +
426 bus_start_window[mode][if_id][bus_id])
427 / 2 - cons_tap;
428 DEBUG_CENTRALIZATION_ENGINE(
429 DEBUG_LEVEL_TRACE,
430 (" bus_id %d Res= %d\n", bus_id,
431 centralization_result[if_id][bus_id]));
432 /* copy results to registers */
433 pup_win_length =
434 bus_end_window[mode][if_id][bus_id] -
435 bus_start_window[mode][if_id][bus_id] +
436 1;
437
438 ddr3_tip_bus_read(dev_num, if_id,
439 ACCESS_TYPE_UNICAST, bus_id,
440 DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200441 RESULT_PHY_REG +
Stefan Roese5ffceb82015-03-26 15:36:56 +0100442 effective_cs, &reg);
443 reg = (reg & (~0x1f <<
444 ((mode == CENTRAL_TX) ?
Chris Packham1a07d212018-05-10 13:28:29 +1200445 (RESULT_PHY_TX_OFFS) :
446 (RESULT_PHY_RX_OFFS))))
Stefan Roese5ffceb82015-03-26 15:36:56 +0100447 | pup_win_length <<
448 ((mode == CENTRAL_TX) ?
Chris Packham1a07d212018-05-10 13:28:29 +1200449 (RESULT_PHY_TX_OFFS) :
450 (RESULT_PHY_RX_OFFS));
Stefan Roese5ffceb82015-03-26 15:36:56 +0100451 CHECK_STATUS(ddr3_tip_bus_write
452 (dev_num, ACCESS_TYPE_UNICAST,
453 if_id, ACCESS_TYPE_UNICAST,
454 bus_id, DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200455 RESULT_PHY_REG +
Stefan Roese5ffceb82015-03-26 15:36:56 +0100456 effective_cs, reg));
457
458 /* offset per CS is calculated earlier */
459 CHECK_STATUS(
460 ddr3_tip_bus_write(dev_num,
461 ACCESS_TYPE_UNICAST,
462 if_id,
463 ACCESS_TYPE_UNICAST,
464 bus_id,
465 DDR_PHY_DATA,
466 reg_phy_off,
467 centralization_result
468 [if_id]
469 [bus_id]));
470 } else {
471 is_if_fail = 1;
472 }
473 }
474
475 if (is_if_fail == 1)
476 flow_result[if_id] = TEST_FAILED;
477 }
478
479 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
480 /* restore cs enable value */
Chris Packham1a07d212018-05-10 13:28:29 +1200481 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100482 CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST,
Chris Packham1a07d212018-05-10 13:28:29 +1200483 if_id, DUAL_DUNIT_CFG_REG,
Stefan Roese5ffceb82015-03-26 15:36:56 +0100484 cs_enable_reg_val[if_id],
485 MASK_ALL_BITS));
486 }
487
488 return is_if_fail;
489}
490
491/*
492 * Centralization Flow
493 */
494int ddr3_tip_special_rx(u32 dev_num)
495{
496 enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM];
497 u32 if_id, pup_id, pattern_id, bit_id;
498 u8 cur_start_win[BUS_WIDTH_IN_BITS];
499 u8 cur_end_win[BUS_WIDTH_IN_BITS];
500 enum hws_training_result result_type = RESULT_PER_BIT;
501 enum hws_dir direction;
502 enum hws_search_dir search_dir_id;
503 u32 *result[HWS_SEARCH_DIR_LIMIT];
504 u32 max_win_size;
505 u8 cur_end_win_min, cur_start_win_max;
506 u32 cs_enable_reg_val[MAX_INTERFACE_NUM];
507 u32 temp = 0;
508 int pad_num = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200509 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
510 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
Stefan Roese5ffceb82015-03-26 15:36:56 +0100511
Chris Packham1a07d212018-05-10 13:28:29 +1200512 if ((ddr3_tip_special_rx_run_once_flag & (1 << effective_cs)) == (1 << effective_cs))
Stefan Roese5ffceb82015-03-26 15:36:56 +0100513 return MV_OK;
514
Chris Packham1a07d212018-05-10 13:28:29 +1200515 ddr3_tip_special_rx_run_once_flag |= (1 << effective_cs);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100516
517 for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200518 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100519 /* save current cs enable reg val */
520 CHECK_STATUS(ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST,
Chris Packham1a07d212018-05-10 13:28:29 +1200521 if_id, DUAL_DUNIT_CFG_REG,
Stefan Roese5ffceb82015-03-26 15:36:56 +0100522 cs_enable_reg_val,
523 MASK_ALL_BITS));
524 /* enable single cs */
525 CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST,
Chris Packham1a07d212018-05-10 13:28:29 +1200526 if_id, DUAL_DUNIT_CFG_REG,
Stefan Roese5ffceb82015-03-26 15:36:56 +0100527 (1 << 3), (1 << 3)));
528 }
529
530 max_win_size = MAX_WINDOW_SIZE_RX;
531 direction = OPER_READ;
Chris Packham1a07d212018-05-10 13:28:29 +1200532 pattern_id = PATTERN_FULL_SSO1;
Stefan Roese5ffceb82015-03-26 15:36:56 +0100533
534 /* start flow */
535 ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST,
536 PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
537 PARAM_NOT_CARE, result_type,
538 HWS_CONTROL_ELEMENT_ADLL,
539 PARAM_NOT_CARE, direction,
540 tm->if_act_mask, 0x0,
541 max_win_size - 1, max_win_size - 1,
542 pattern_id, EDGE_FPF, CS_SINGLE,
543 PARAM_NOT_CARE, training_result);
544
545 for (if_id = start_if; if_id <= end_if; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200546 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100547 for (pup_id = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200548 pup_id <= octets_per_if_num; pup_id++) {
549 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100550
551 for (search_dir_id = HWS_LOW2HIGH;
552 search_dir_id <= HWS_HIGH2LOW;
553 search_dir_id++) {
554 CHECK_STATUS(ddr3_tip_read_training_result
555 (dev_num, if_id,
556 ACCESS_TYPE_UNICAST, pup_id,
557 ALL_BITS_PER_PUP, search_dir_id,
558 direction, result_type,
559 TRAINING_LOAD_OPERATION_UNLOAD,
560 CS_SINGLE, &result[search_dir_id],
561 1, 0, 0));
562 DEBUG_CENTRALIZATION_ENGINE(DEBUG_LEVEL_INFO,
563 ("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",
564 pattern_id, if_id,
565 pup_id,
566 result
567 [search_dir_id][0],
568 result
569 [search_dir_id][1],
570 result
571 [search_dir_id][2],
572 result
573 [search_dir_id][3],
574 result
575 [search_dir_id][4],
576 result
577 [search_dir_id][5],
578 result
579 [search_dir_id][6],
580 result
581 [search_dir_id]
582 [7]));
583 }
584
585 for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS; bit_id++) {
586 /*
587 * check if this code is valid for 2 edge,
588 * probably not :(
589 */
590 cur_start_win[bit_id] =
591 GET_TAP_RESULT(result[HWS_LOW2HIGH]
592 [bit_id], EDGE_1);
593 cur_end_win[bit_id] =
594 GET_TAP_RESULT(result[HWS_HIGH2LOW]
595 [bit_id], EDGE_1);
596 }
597 if (!((ddr3_tip_is_pup_lock
598 (result[HWS_LOW2HIGH], result_type)) &&
599 (ddr3_tip_is_pup_lock
600 (result[HWS_HIGH2LOW], result_type)))) {
601 DEBUG_CENTRALIZATION_ENGINE(
602 DEBUG_LEVEL_ERROR,
603 ("Special: Pup lock fail, pat %d IF %d pup %d\n",
604 pattern_id, if_id, pup_id));
605 return MV_FAIL;
606 }
607
608 cur_end_win_min =
609 ddr3_tip_get_buf_min(cur_end_win);
610 cur_start_win_max =
611 ddr3_tip_get_buf_max(cur_start_win);
612
613 if (cur_start_win_max <= 1) { /* Align left */
614 for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS;
615 bit_id++) {
616 pad_num =
617 dq_map_table[bit_id +
618 pup_id *
619 BUS_WIDTH_IN_BITS +
620 if_id *
621 BUS_WIDTH_IN_BITS *
Chris Packham1a07d212018-05-10 13:28:29 +1200622 MAX_BUS_NUM];
Stefan Roese5ffceb82015-03-26 15:36:56 +0100623 CHECK_STATUS(ddr3_tip_bus_read
624 (dev_num, if_id,
625 ACCESS_TYPE_UNICAST,
626 pup_id, DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200627 PBS_RX_PHY_REG(effective_cs, pad_num),
Stefan Roese5ffceb82015-03-26 15:36:56 +0100628 &temp));
629 temp = (temp + 0xa > 31) ?
630 (31) : (temp + 0xa);
631 CHECK_STATUS(ddr3_tip_bus_write
632 (dev_num,
633 ACCESS_TYPE_UNICAST,
634 if_id,
635 ACCESS_TYPE_UNICAST,
636 pup_id, DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200637 PBS_RX_PHY_REG(effective_cs, pad_num),
Stefan Roese5ffceb82015-03-26 15:36:56 +0100638 temp));
639 }
640 DEBUG_CENTRALIZATION_ENGINE(
641 DEBUG_LEVEL_INFO,
642 ("Special: PBS:: I/F# %d , Bus# %d fix align to the Left\n",
643 if_id, pup_id));
644 }
645
646 if (cur_end_win_min > 30) { /* Align right */
647 CHECK_STATUS(ddr3_tip_bus_read
648 (dev_num, if_id,
649 ACCESS_TYPE_UNICAST, pup_id,
Chris Packham1a07d212018-05-10 13:28:29 +1200650 DDR_PHY_DATA,
651 PBS_RX_PHY_REG(effective_cs, 4),
Stefan Roese5ffceb82015-03-26 15:36:56 +0100652 &temp));
653 temp += 0xa;
654 CHECK_STATUS(ddr3_tip_bus_write
655 (dev_num, ACCESS_TYPE_UNICAST,
656 if_id, ACCESS_TYPE_UNICAST,
657 pup_id, DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200658 PBS_RX_PHY_REG(effective_cs, 4),
659 temp));
Stefan Roese5ffceb82015-03-26 15:36:56 +0100660 CHECK_STATUS(ddr3_tip_bus_read
661 (dev_num, if_id,
662 ACCESS_TYPE_UNICAST, pup_id,
Chris Packham1a07d212018-05-10 13:28:29 +1200663 DDR_PHY_DATA,
664 PBS_RX_PHY_REG(effective_cs, 5),
Stefan Roese5ffceb82015-03-26 15:36:56 +0100665 &temp));
666 temp += 0xa;
667 CHECK_STATUS(ddr3_tip_bus_write
668 (dev_num, ACCESS_TYPE_UNICAST,
669 if_id, ACCESS_TYPE_UNICAST,
670 pup_id, DDR_PHY_DATA,
Chris Packham1a07d212018-05-10 13:28:29 +1200671 PBS_RX_PHY_REG(effective_cs, 5),
672 temp));
Stefan Roese5ffceb82015-03-26 15:36:56 +0100673 DEBUG_CENTRALIZATION_ENGINE(
674 DEBUG_LEVEL_INFO,
675 ("Special: PBS:: I/F# %d , Bus# %d fix align to the right\n",
676 if_id, pup_id));
677 }
678
679 vref_window_size[if_id][pup_id] =
680 cur_end_win_min -
681 cur_start_win_max + 1;
682 DEBUG_CENTRALIZATION_ENGINE(
683 DEBUG_LEVEL_INFO,
684 ("Special: Winsize I/F# %d , Bus# %d is %d\n",
685 if_id, pup_id, vref_window_size
686 [if_id][pup_id]));
687 } /* pup */
688 } /* end of interface */
689
690 return MV_OK;
691}
692
693/*
694 * Print Centralization Result
695 */
696int ddr3_tip_print_centralization_result(u32 dev_num)
697{
698 u32 if_id = 0, bus_id = 0;
Chris Packham1a07d212018-05-10 13:28:29 +1200699 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
700 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
Stefan Roese5ffceb82015-03-26 15:36:56 +0100701
Chris Packham4bf81db2018-12-03 14:26:49 +1300702 dev_num = dev_num;
703
Stefan Roese5ffceb82015-03-26 15:36:56 +0100704 printf("Centralization Results\n");
705 printf("I/F0 Result[0 - success 1-fail 2 - state_2 3 - state_3] ...\n");
706 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200707 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
708 for (bus_id = 0; bus_id < octets_per_if_num;
Stefan Roese5ffceb82015-03-26 15:36:56 +0100709 bus_id++) {
Chris Packham1a07d212018-05-10 13:28:29 +1200710 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
Stefan Roese5ffceb82015-03-26 15:36:56 +0100711 printf("%d ,\n", centralization_state[if_id][bus_id]);
712 }
713 }
714
715 return MV_OK;
716}