]>
Commit | Line | Data |
---|---|---|
f1df9364 SR |
1 | /* |
2 | * Copyright (C) Marvell International Ltd. and its affiliates | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0 | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <spl.h> | |
9 | #include <asm/io.h> | |
10 | #include <asm/arch/cpu.h> | |
11 | #include <asm/arch/soc.h> | |
12 | ||
13 | #include "ddr3_init.h" | |
14 | ||
15 | #define VALIDATE_WIN_LENGTH(e1, e2, maxsize) \ | |
16 | (((e2) + 1 > (e1) + (u8)MIN_WINDOW_SIZE) && \ | |
17 | ((e2) + 1 < (e1) + (u8)maxsize)) | |
18 | #define IS_WINDOW_OUT_BOUNDARY(e1, e2, maxsize) \ | |
19 | (((e1) == 0 && (e2) != 0) || \ | |
20 | ((e1) != (maxsize - 1) && (e2) == (maxsize - 1))) | |
21 | #define CENTRAL_TX 0 | |
22 | #define CENTRAL_RX 1 | |
23 | #define NUM_OF_CENTRAL_TYPES 2 | |
24 | ||
25 | u32 start_pattern = PATTERN_KILLER_DQ0, end_pattern = PATTERN_KILLER_DQ7; | |
26 | u32 start_if = 0, end_if = (MAX_INTERFACE_NUM - 1); | |
27 | u8 bus_end_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM]; | |
28 | u8 bus_start_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM]; | |
29 | u8 centralization_state[MAX_INTERFACE_NUM][MAX_BUS_NUM]; | |
30 | static u8 ddr3_tip_special_rx_run_once_flag; | |
31 | ||
32 | static int ddr3_tip_centralization(u32 dev_num, u32 mode); | |
33 | ||
34 | /* | |
35 | * Centralization RX Flow | |
36 | */ | |
37 | int ddr3_tip_centralization_rx(u32 dev_num) | |
38 | { | |
39 | CHECK_STATUS(ddr3_tip_special_rx(dev_num)); | |
40 | CHECK_STATUS(ddr3_tip_centralization(dev_num, CENTRAL_RX)); | |
41 | ||
42 | return MV_OK; | |
43 | } | |
44 | ||
45 | /* | |
46 | * Centralization TX Flow | |
47 | */ | |
48 | int ddr3_tip_centralization_tx(u32 dev_num) | |
49 | { | |
50 | CHECK_STATUS(ddr3_tip_centralization(dev_num, CENTRAL_TX)); | |
51 | ||
52 | return MV_OK; | |
53 | } | |
54 | ||
55 | /* | |
56 | * Centralization Flow | |
57 | */ | |
58 | static int ddr3_tip_centralization(u32 dev_num, u32 mode) | |
59 | { | |
60 | enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM]; | |
61 | u32 if_id, pattern_id, bit_id; | |
62 | u8 bus_id; | |
63 | 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]; | |
69 | struct hws_topology_map *tm = ddr3_get_topology_map(); | |
70 | enum hws_training_result result_type = RESULT_PER_BIT; | |
71 | enum hws_dir direction; | |
72 | u32 *result[HWS_SEARCH_DIR_LIMIT]; | |
73 | u32 reg_phy_off, reg; | |
74 | u8 max_win_size; | |
75 | int lock_success = 1; | |
76 | u8 cur_end_win_min, cur_start_win_max; | |
77 | u32 cs_enable_reg_val[MAX_INTERFACE_NUM]; | |
78 | int is_if_fail = 0; | |
79 | enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage); | |
80 | u32 pup_win_length = 0; | |
81 | enum hws_search_dir search_dir_id; | |
82 | u8 cons_tap = (mode == CENTRAL_TX) ? (64) : (0); | |
83 | ||
84 | for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { | |
85 | VALIDATE_ACTIVE(tm->if_act_mask, if_id); | |
86 | /* save current cs enable reg val */ | |
87 | CHECK_STATUS(ddr3_tip_if_read | |
88 | (dev_num, ACCESS_TYPE_UNICAST, if_id, | |
89 | CS_ENABLE_REG, cs_enable_reg_val, MASK_ALL_BITS)); | |
90 | /* enable single cs */ | |
91 | CHECK_STATUS(ddr3_tip_if_write | |
92 | (dev_num, ACCESS_TYPE_UNICAST, if_id, | |
93 | CS_ENABLE_REG, (1 << 3), (1 << 3))); | |
94 | } | |
95 | ||
96 | if (mode == CENTRAL_TX) { | |
97 | max_win_size = MAX_WINDOW_SIZE_TX; | |
98 | reg_phy_off = WRITE_CENTRALIZATION_PHY_REG + (effective_cs * 4); | |
99 | direction = OPER_WRITE; | |
100 | } else { | |
101 | max_win_size = MAX_WINDOW_SIZE_RX; | |
102 | reg_phy_off = READ_CENTRALIZATION_PHY_REG + (effective_cs * 4); | |
103 | direction = OPER_READ; | |
104 | } | |
105 | ||
106 | /* DB initialization */ | |
107 | for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { | |
108 | VALIDATE_ACTIVE(tm->if_act_mask, if_id); | |
109 | for (bus_id = 0; | |
110 | bus_id < tm->num_of_bus_per_interface; bus_id++) { | |
111 | VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); | |
112 | centralization_state[if_id][bus_id] = 0; | |
113 | bus_end_window[mode][if_id][bus_id] = | |
114 | (max_win_size - 1) + cons_tap; | |
115 | bus_start_window[mode][if_id][bus_id] = 0; | |
116 | centralization_result[if_id][bus_id] = 0; | |
117 | } | |
118 | } | |
119 | ||
120 | /* start flow */ | |
121 | for (pattern_id = start_pattern; pattern_id <= end_pattern; | |
122 | pattern_id++) { | |
123 | ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST, | |
124 | PARAM_NOT_CARE, | |
125 | ACCESS_TYPE_MULTICAST, | |
126 | PARAM_NOT_CARE, result_type, | |
127 | HWS_CONTROL_ELEMENT_ADLL, | |
128 | PARAM_NOT_CARE, direction, | |
129 | tm-> | |
130 | if_act_mask, 0x0, | |
131 | max_win_size - 1, | |
132 | max_win_size - 1, | |
133 | pattern_id, EDGE_FPF, CS_SINGLE, | |
134 | PARAM_NOT_CARE, training_result); | |
135 | ||
136 | for (if_id = start_if; if_id <= end_if; if_id++) { | |
137 | VALIDATE_ACTIVE(tm->if_act_mask, if_id); | |
138 | for (bus_id = 0; | |
139 | bus_id <= tm->num_of_bus_per_interface - 1; | |
140 | bus_id++) { | |
141 | VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); | |
142 | ||
143 | for (search_dir_id = HWS_LOW2HIGH; | |
144 | search_dir_id <= HWS_HIGH2LOW; | |
145 | search_dir_id++) { | |
146 | CHECK_STATUS | |
147 | (ddr3_tip_read_training_result | |
148 | (dev_num, if_id, | |
149 | ACCESS_TYPE_UNICAST, bus_id, | |
150 | ALL_BITS_PER_PUP, | |
151 | search_dir_id, | |
152 | direction, result_type, | |
153 | TRAINING_LOAD_OPERATION_UNLOAD, | |
154 | CS_SINGLE, | |
155 | &result[search_dir_id], | |
156 | 1, 0, 0)); | |
157 | DEBUG_CENTRALIZATION_ENGINE | |
158 | (DEBUG_LEVEL_INFO, | |
159 | ("%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", | |
160 | ((mode == | |
161 | CENTRAL_TX) ? "TX" : "RX"), | |
162 | pattern_id, if_id, bus_id, | |
163 | result[search_dir_id][0], | |
164 | result[search_dir_id][1], | |
165 | result[search_dir_id][2], | |
166 | result[search_dir_id][3], | |
167 | result[search_dir_id][4], | |
168 | result[search_dir_id][5], | |
169 | result[search_dir_id][6], | |
170 | result[search_dir_id][7])); | |
171 | } | |
172 | ||
173 | for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS; | |
174 | bit_id++) { | |
175 | /* check if this code is valid for 2 edge, probably not :( */ | |
176 | cur_start_win[bit_id] = | |
177 | GET_TAP_RESULT(result | |
178 | [HWS_LOW2HIGH] | |
179 | [bit_id], | |
180 | EDGE_1); | |
181 | cur_end_win[bit_id] = | |
182 | GET_TAP_RESULT(result | |
183 | [HWS_HIGH2LOW] | |
184 | [bit_id], | |
185 | EDGE_1); | |
186 | /* window length */ | |
187 | current_window[bit_id] = | |
188 | cur_end_win[bit_id] - | |
189 | cur_start_win[bit_id] + 1; | |
190 | DEBUG_CENTRALIZATION_ENGINE | |
191 | (DEBUG_LEVEL_TRACE, | |
192 | ("cs %x patern %d IF %d pup %d cur_start_win %d cur_end_win %d current_window %d\n", | |
193 | effective_cs, pattern_id, | |
194 | if_id, bus_id, | |
195 | cur_start_win[bit_id], | |
196 | cur_end_win[bit_id], | |
197 | current_window[bit_id])); | |
198 | } | |
199 | ||
200 | if ((ddr3_tip_is_pup_lock | |
201 | (result[HWS_LOW2HIGH], result_type)) && | |
202 | (ddr3_tip_is_pup_lock | |
203 | (result[HWS_HIGH2LOW], result_type))) { | |
204 | /* read result success */ | |
205 | DEBUG_CENTRALIZATION_ENGINE | |
206 | (DEBUG_LEVEL_INFO, | |
207 | ("Pup locked, pat %d IF %d pup %d\n", | |
208 | pattern_id, if_id, bus_id)); | |
209 | } else { | |
210 | /* read result failure */ | |
211 | DEBUG_CENTRALIZATION_ENGINE | |
212 | (DEBUG_LEVEL_INFO, | |
213 | ("fail Lock, pat %d IF %d pup %d\n", | |
214 | pattern_id, if_id, bus_id)); | |
215 | if (centralization_state[if_id][bus_id] | |
216 | == 1) { | |
217 | /* continue with next pup */ | |
218 | DEBUG_CENTRALIZATION_ENGINE | |
219 | (DEBUG_LEVEL_TRACE, | |
220 | ("continue to next pup %d %d\n", | |
221 | if_id, bus_id)); | |
222 | continue; | |
223 | } | |
224 | ||
225 | for (bit_id = 0; | |
226 | bit_id < BUS_WIDTH_IN_BITS; | |
227 | bit_id++) { | |
228 | /* | |
229 | * the next check is relevant | |
230 | * only when using search | |
231 | * machine 2 edges | |
232 | */ | |
233 | if (cur_start_win[bit_id] > 0 && | |
234 | cur_end_win[bit_id] == 0) { | |
235 | cur_end_win | |
236 | [bit_id] = | |
237 | max_win_size - 1; | |
238 | DEBUG_CENTRALIZATION_ENGINE | |
239 | (DEBUG_LEVEL_TRACE, | |
240 | ("fail, IF %d pup %d bit %d fail #1\n", | |
241 | if_id, bus_id, | |
242 | bit_id)); | |
243 | /* the next bit */ | |
244 | continue; | |
245 | } else { | |
246 | centralization_state | |
247 | [if_id][bus_id] = 1; | |
248 | DEBUG_CENTRALIZATION_ENGINE | |
249 | (DEBUG_LEVEL_TRACE, | |
250 | ("fail, IF %d pup %d bit %d fail #2\n", | |
251 | if_id, bus_id, | |
252 | bit_id)); | |
253 | } | |
254 | } | |
255 | ||
256 | if (centralization_state[if_id][bus_id] | |
257 | == 1) { | |
258 | /* going to next pup */ | |
259 | continue; | |
260 | } | |
261 | } /*bit */ | |
262 | ||
263 | opt_window = | |
264 | ddr3_tip_get_buf_min(current_window); | |
265 | /* final pup window length */ | |
266 | final_pup_window[if_id][bus_id] = | |
267 | ddr3_tip_get_buf_min(cur_end_win) - | |
268 | ddr3_tip_get_buf_max(cur_start_win) + | |
269 | 1; | |
270 | waste_window = | |
271 | opt_window - | |
272 | final_pup_window[if_id][bus_id]; | |
273 | start_window_skew = | |
274 | ddr3_tip_get_buf_max(cur_start_win) - | |
275 | ddr3_tip_get_buf_min( | |
276 | cur_start_win); | |
277 | end_window_skew = | |
278 | ddr3_tip_get_buf_max( | |
279 | cur_end_win) - | |
280 | ddr3_tip_get_buf_min( | |
281 | cur_end_win); | |
282 | /* min/max updated with pattern change */ | |
283 | cur_end_win_min = | |
284 | ddr3_tip_get_buf_min( | |
285 | cur_end_win); | |
286 | cur_start_win_max = | |
287 | ddr3_tip_get_buf_max( | |
288 | cur_start_win); | |
289 | bus_end_window[mode][if_id][bus_id] = | |
290 | GET_MIN(bus_end_window[mode][if_id] | |
291 | [bus_id], | |
292 | cur_end_win_min); | |
293 | bus_start_window[mode][if_id][bus_id] = | |
294 | GET_MAX(bus_start_window[mode][if_id] | |
295 | [bus_id], | |
296 | cur_start_win_max); | |
297 | DEBUG_CENTRALIZATION_ENGINE( | |
298 | DEBUG_LEVEL_INFO, | |
299 | ("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", | |
300 | pattern_id, if_id, bus_id, opt_window, | |
301 | final_pup_window[if_id][bus_id], | |
302 | waste_window, start_window_skew, | |
303 | end_window_skew, | |
304 | cur_start_win_max, | |
305 | cur_end_win_min, | |
306 | bus_start_window[mode][if_id][bus_id], | |
307 | bus_end_window[mode][if_id][bus_id])); | |
308 | ||
309 | /* check if window is valid */ | |
310 | if (ddr3_tip_centr_skip_min_win_check == 0) { | |
311 | if ((VALIDATE_WIN_LENGTH | |
312 | (bus_start_window[mode][if_id] | |
313 | [bus_id], | |
314 | bus_end_window[mode][if_id] | |
315 | [bus_id], | |
316 | max_win_size) == 1) || | |
317 | (IS_WINDOW_OUT_BOUNDARY | |
318 | (bus_start_window[mode][if_id] | |
319 | [bus_id], | |
320 | bus_end_window[mode][if_id] | |
321 | [bus_id], | |
322 | max_win_size) == 1)) { | |
323 | DEBUG_CENTRALIZATION_ENGINE | |
324 | (DEBUG_LEVEL_INFO, | |
325 | ("win valid, pat %d IF %d pup %d\n", | |
326 | pattern_id, if_id, | |
327 | bus_id)); | |
328 | /* window is valid */ | |
329 | } else { | |
330 | DEBUG_CENTRALIZATION_ENGINE | |
331 | (DEBUG_LEVEL_INFO, | |
332 | ("fail win, pat %d IF %d pup %d bus_st_win %d bus_end_win %d\n", | |
333 | pattern_id, if_id, bus_id, | |
334 | bus_start_window[mode] | |
335 | [if_id][bus_id], | |
336 | bus_end_window[mode] | |
337 | [if_id][bus_id])); | |
338 | centralization_state[if_id] | |
339 | [bus_id] = 1; | |
340 | if (debug_mode == 0) | |
341 | return MV_FAIL; | |
342 | } | |
343 | } /* ddr3_tip_centr_skip_min_win_check */ | |
344 | } /* pup */ | |
345 | } /* interface */ | |
346 | } /* pattern */ | |
347 | ||
348 | for (if_id = start_if; if_id <= end_if; if_id++) { | |
349 | if (IS_ACTIVE(tm->if_act_mask, if_id) == 0) | |
350 | continue; | |
351 | ||
352 | is_if_fail = 0; | |
353 | flow_result[if_id] = TEST_SUCCESS; | |
354 | ||
355 | for (bus_id = 0; | |
356 | bus_id <= (tm->num_of_bus_per_interface - 1); bus_id++) { | |
357 | VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); | |
358 | ||
359 | /* continue only if lock */ | |
360 | if (centralization_state[if_id][bus_id] != 1) { | |
361 | if (ddr3_tip_centr_skip_min_win_check == 0) { | |
362 | if ((bus_end_window | |
363 | [mode][if_id][bus_id] == | |
364 | (max_win_size - 1)) && | |
365 | ((bus_end_window | |
366 | [mode][if_id][bus_id] - | |
367 | bus_start_window[mode][if_id] | |
368 | [bus_id]) < MIN_WINDOW_SIZE) && | |
369 | ((bus_end_window[mode][if_id] | |
370 | [bus_id] - bus_start_window | |
371 | [mode][if_id][bus_id]) > 2)) { | |
372 | /* prevent false lock */ | |
373 | /* TBD change to enum */ | |
374 | centralization_state | |
375 | [if_id][bus_id] = 2; | |
376 | } | |
377 | ||
378 | if ((bus_end_window[mode][if_id][bus_id] | |
379 | == 0) && | |
380 | ((bus_end_window[mode][if_id] | |
381 | [bus_id] - | |
382 | bus_start_window[mode][if_id] | |
383 | [bus_id]) < MIN_WINDOW_SIZE) && | |
384 | ((bus_end_window[mode][if_id] | |
385 | [bus_id] - | |
386 | bus_start_window[mode][if_id] | |
387 | [bus_id]) > 2)) | |
388 | /*prevent false lock */ | |
389 | centralization_state[if_id] | |
390 | [bus_id] = 3; | |
391 | } | |
392 | ||
393 | if ((bus_end_window[mode][if_id][bus_id] > | |
394 | (max_win_size - 1)) && direction == | |
395 | OPER_WRITE) { | |
396 | DEBUG_CENTRALIZATION_ENGINE | |
397 | (DEBUG_LEVEL_INFO, | |
398 | ("Tx special pattern\n")); | |
399 | cons_tap = 64; | |
400 | } | |
401 | } | |
402 | ||
403 | /* check states */ | |
404 | if (centralization_state[if_id][bus_id] == 3) { | |
405 | DEBUG_CENTRALIZATION_ENGINE( | |
406 | DEBUG_LEVEL_INFO, | |
407 | ("SSW - TBD IF %d pup %d\n", | |
408 | if_id, bus_id)); | |
409 | lock_success = 1; | |
410 | } else if (centralization_state[if_id][bus_id] == 2) { | |
411 | DEBUG_CENTRALIZATION_ENGINE( | |
412 | DEBUG_LEVEL_INFO, | |
413 | ("SEW - TBD IF %d pup %d\n", | |
414 | if_id, bus_id)); | |
415 | lock_success = 1; | |
416 | } else if (centralization_state[if_id][bus_id] == 0) { | |
417 | lock_success = 1; | |
418 | } else { | |
419 | DEBUG_CENTRALIZATION_ENGINE( | |
420 | DEBUG_LEVEL_ERROR, | |
421 | ("fail, IF %d pup %d\n", | |
422 | if_id, bus_id)); | |
423 | lock_success = 0; | |
424 | } | |
425 | ||
426 | if (lock_success == 1) { | |
427 | centralization_result[if_id][bus_id] = | |
428 | (bus_end_window[mode][if_id][bus_id] + | |
429 | bus_start_window[mode][if_id][bus_id]) | |
430 | / 2 - cons_tap; | |
431 | DEBUG_CENTRALIZATION_ENGINE( | |
432 | DEBUG_LEVEL_TRACE, | |
433 | (" bus_id %d Res= %d\n", bus_id, | |
434 | centralization_result[if_id][bus_id])); | |
435 | /* copy results to registers */ | |
436 | pup_win_length = | |
437 | bus_end_window[mode][if_id][bus_id] - | |
438 | bus_start_window[mode][if_id][bus_id] + | |
439 | 1; | |
440 | ||
441 | ddr3_tip_bus_read(dev_num, if_id, | |
442 | ACCESS_TYPE_UNICAST, bus_id, | |
443 | DDR_PHY_DATA, | |
444 | RESULT_DB_PHY_REG_ADDR + | |
445 | effective_cs, ®); | |
446 | reg = (reg & (~0x1f << | |
447 | ((mode == CENTRAL_TX) ? | |
448 | (RESULT_DB_PHY_REG_TX_OFFSET) : | |
449 | (RESULT_DB_PHY_REG_RX_OFFSET)))) | |
450 | | pup_win_length << | |
451 | ((mode == CENTRAL_TX) ? | |
452 | (RESULT_DB_PHY_REG_TX_OFFSET) : | |
453 | (RESULT_DB_PHY_REG_RX_OFFSET)); | |
454 | CHECK_STATUS(ddr3_tip_bus_write | |
455 | (dev_num, ACCESS_TYPE_UNICAST, | |
456 | if_id, ACCESS_TYPE_UNICAST, | |
457 | bus_id, DDR_PHY_DATA, | |
458 | RESULT_DB_PHY_REG_ADDR + | |
459 | effective_cs, reg)); | |
460 | ||
461 | /* offset per CS is calculated earlier */ | |
462 | CHECK_STATUS( | |
463 | ddr3_tip_bus_write(dev_num, | |
464 | ACCESS_TYPE_UNICAST, | |
465 | if_id, | |
466 | ACCESS_TYPE_UNICAST, | |
467 | bus_id, | |
468 | DDR_PHY_DATA, | |
469 | reg_phy_off, | |
470 | centralization_result | |
471 | [if_id] | |
472 | [bus_id])); | |
473 | } else { | |
474 | is_if_fail = 1; | |
475 | } | |
476 | } | |
477 | ||
478 | if (is_if_fail == 1) | |
479 | flow_result[if_id] = TEST_FAILED; | |
480 | } | |
481 | ||
482 | for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { | |
483 | /* restore cs enable value */ | |
484 | VALIDATE_ACTIVE(tm->if_act_mask, if_id); | |
485 | CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, | |
486 | if_id, CS_ENABLE_REG, | |
487 | cs_enable_reg_val[if_id], | |
488 | MASK_ALL_BITS)); | |
489 | } | |
490 | ||
491 | return is_if_fail; | |
492 | } | |
493 | ||
494 | /* | |
495 | * Centralization Flow | |
496 | */ | |
497 | int ddr3_tip_special_rx(u32 dev_num) | |
498 | { | |
499 | enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM]; | |
500 | u32 if_id, pup_id, pattern_id, bit_id; | |
501 | u8 cur_start_win[BUS_WIDTH_IN_BITS]; | |
502 | u8 cur_end_win[BUS_WIDTH_IN_BITS]; | |
503 | enum hws_training_result result_type = RESULT_PER_BIT; | |
504 | enum hws_dir direction; | |
505 | enum hws_search_dir search_dir_id; | |
506 | u32 *result[HWS_SEARCH_DIR_LIMIT]; | |
507 | u32 max_win_size; | |
508 | u8 cur_end_win_min, cur_start_win_max; | |
509 | u32 cs_enable_reg_val[MAX_INTERFACE_NUM]; | |
510 | u32 temp = 0; | |
511 | int pad_num = 0; | |
512 | struct hws_topology_map *tm = ddr3_get_topology_map(); | |
513 | ||
514 | if (ddr3_tip_special_rx_run_once_flag != 0) | |
515 | return MV_OK; | |
516 | ||
517 | ddr3_tip_special_rx_run_once_flag = 1; | |
518 | ||
519 | for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { | |
520 | VALIDATE_ACTIVE(tm->if_act_mask, if_id); | |
521 | /* save current cs enable reg val */ | |
522 | CHECK_STATUS(ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, | |
523 | if_id, CS_ENABLE_REG, | |
524 | cs_enable_reg_val, | |
525 | MASK_ALL_BITS)); | |
526 | /* enable single cs */ | |
527 | CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, | |
528 | if_id, CS_ENABLE_REG, | |
529 | (1 << 3), (1 << 3))); | |
530 | } | |
531 | ||
532 | max_win_size = MAX_WINDOW_SIZE_RX; | |
533 | direction = OPER_READ; | |
534 | pattern_id = PATTERN_VREF; | |
535 | ||
536 | /* start flow */ | |
537 | ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST, | |
538 | PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST, | |
539 | PARAM_NOT_CARE, result_type, | |
540 | HWS_CONTROL_ELEMENT_ADLL, | |
541 | PARAM_NOT_CARE, direction, | |
542 | tm->if_act_mask, 0x0, | |
543 | max_win_size - 1, max_win_size - 1, | |
544 | pattern_id, EDGE_FPF, CS_SINGLE, | |
545 | PARAM_NOT_CARE, training_result); | |
546 | ||
547 | for (if_id = start_if; if_id <= end_if; if_id++) { | |
548 | VALIDATE_ACTIVE(tm->if_act_mask, if_id); | |
549 | for (pup_id = 0; | |
550 | pup_id <= tm->num_of_bus_per_interface; pup_id++) { | |
551 | VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); | |
552 | ||
553 | for (search_dir_id = HWS_LOW2HIGH; | |
554 | search_dir_id <= HWS_HIGH2LOW; | |
555 | search_dir_id++) { | |
556 | CHECK_STATUS(ddr3_tip_read_training_result | |
557 | (dev_num, if_id, | |
558 | ACCESS_TYPE_UNICAST, pup_id, | |
559 | ALL_BITS_PER_PUP, search_dir_id, | |
560 | direction, result_type, | |
561 | TRAINING_LOAD_OPERATION_UNLOAD, | |
562 | CS_SINGLE, &result[search_dir_id], | |
563 | 1, 0, 0)); | |
564 | DEBUG_CENTRALIZATION_ENGINE(DEBUG_LEVEL_INFO, | |
565 | ("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", | |
566 | pattern_id, if_id, | |
567 | pup_id, | |
568 | result | |
569 | [search_dir_id][0], | |
570 | result | |
571 | [search_dir_id][1], | |
572 | result | |
573 | [search_dir_id][2], | |
574 | result | |
575 | [search_dir_id][3], | |
576 | result | |
577 | [search_dir_id][4], | |
578 | result | |
579 | [search_dir_id][5], | |
580 | result | |
581 | [search_dir_id][6], | |
582 | result | |
583 | [search_dir_id] | |
584 | [7])); | |
585 | } | |
586 | ||
587 | for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS; bit_id++) { | |
588 | /* | |
589 | * check if this code is valid for 2 edge, | |
590 | * probably not :( | |
591 | */ | |
592 | cur_start_win[bit_id] = | |
593 | GET_TAP_RESULT(result[HWS_LOW2HIGH] | |
594 | [bit_id], EDGE_1); | |
595 | cur_end_win[bit_id] = | |
596 | GET_TAP_RESULT(result[HWS_HIGH2LOW] | |
597 | [bit_id], EDGE_1); | |
598 | } | |
599 | if (!((ddr3_tip_is_pup_lock | |
600 | (result[HWS_LOW2HIGH], result_type)) && | |
601 | (ddr3_tip_is_pup_lock | |
602 | (result[HWS_HIGH2LOW], result_type)))) { | |
603 | DEBUG_CENTRALIZATION_ENGINE( | |
604 | DEBUG_LEVEL_ERROR, | |
605 | ("Special: Pup lock fail, pat %d IF %d pup %d\n", | |
606 | pattern_id, if_id, pup_id)); | |
607 | return MV_FAIL; | |
608 | } | |
609 | ||
610 | cur_end_win_min = | |
611 | ddr3_tip_get_buf_min(cur_end_win); | |
612 | cur_start_win_max = | |
613 | ddr3_tip_get_buf_max(cur_start_win); | |
614 | ||
615 | if (cur_start_win_max <= 1) { /* Align left */ | |
616 | for (bit_id = 0; bit_id < BUS_WIDTH_IN_BITS; | |
617 | bit_id++) { | |
618 | pad_num = | |
619 | dq_map_table[bit_id + | |
620 | pup_id * | |
621 | BUS_WIDTH_IN_BITS + | |
622 | if_id * | |
623 | BUS_WIDTH_IN_BITS * | |
624 | tm-> | |
625 | num_of_bus_per_interface]; | |
626 | CHECK_STATUS(ddr3_tip_bus_read | |
627 | (dev_num, if_id, | |
628 | ACCESS_TYPE_UNICAST, | |
629 | pup_id, DDR_PHY_DATA, | |
630 | PBS_RX_PHY_REG + pad_num, | |
631 | &temp)); | |
632 | temp = (temp + 0xa > 31) ? | |
633 | (31) : (temp + 0xa); | |
634 | CHECK_STATUS(ddr3_tip_bus_write | |
635 | (dev_num, | |
636 | ACCESS_TYPE_UNICAST, | |
637 | if_id, | |
638 | ACCESS_TYPE_UNICAST, | |
639 | pup_id, DDR_PHY_DATA, | |
640 | PBS_RX_PHY_REG + pad_num, | |
641 | temp)); | |
642 | } | |
643 | DEBUG_CENTRALIZATION_ENGINE( | |
644 | DEBUG_LEVEL_INFO, | |
645 | ("Special: PBS:: I/F# %d , Bus# %d fix align to the Left\n", | |
646 | if_id, pup_id)); | |
647 | } | |
648 | ||
649 | if (cur_end_win_min > 30) { /* Align right */ | |
650 | CHECK_STATUS(ddr3_tip_bus_read | |
651 | (dev_num, if_id, | |
652 | ACCESS_TYPE_UNICAST, pup_id, | |
653 | DDR_PHY_DATA, PBS_RX_PHY_REG + 4, | |
654 | &temp)); | |
655 | temp += 0xa; | |
656 | CHECK_STATUS(ddr3_tip_bus_write | |
657 | (dev_num, ACCESS_TYPE_UNICAST, | |
658 | if_id, ACCESS_TYPE_UNICAST, | |
659 | pup_id, DDR_PHY_DATA, | |
660 | PBS_RX_PHY_REG + 4, temp)); | |
661 | CHECK_STATUS(ddr3_tip_bus_read | |
662 | (dev_num, if_id, | |
663 | ACCESS_TYPE_UNICAST, pup_id, | |
664 | DDR_PHY_DATA, PBS_RX_PHY_REG + 5, | |
665 | &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, | |
671 | PBS_RX_PHY_REG + 5, temp)); | |
672 | DEBUG_CENTRALIZATION_ENGINE( | |
673 | DEBUG_LEVEL_INFO, | |
674 | ("Special: PBS:: I/F# %d , Bus# %d fix align to the right\n", | |
675 | if_id, pup_id)); | |
676 | } | |
677 | ||
678 | vref_window_size[if_id][pup_id] = | |
679 | cur_end_win_min - | |
680 | cur_start_win_max + 1; | |
681 | DEBUG_CENTRALIZATION_ENGINE( | |
682 | DEBUG_LEVEL_INFO, | |
683 | ("Special: Winsize I/F# %d , Bus# %d is %d\n", | |
684 | if_id, pup_id, vref_window_size | |
685 | [if_id][pup_id])); | |
686 | } /* pup */ | |
687 | } /* end of interface */ | |
688 | ||
689 | return MV_OK; | |
690 | } | |
691 | ||
692 | /* | |
693 | * Print Centralization Result | |
694 | */ | |
695 | int ddr3_tip_print_centralization_result(u32 dev_num) | |
696 | { | |
697 | u32 if_id = 0, bus_id = 0; | |
698 | struct hws_topology_map *tm = ddr3_get_topology_map(); | |
699 | ||
f1df9364 SR |
700 | printf("Centralization Results\n"); |
701 | printf("I/F0 Result[0 - success 1-fail 2 - state_2 3 - state_3] ...\n"); | |
702 | for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { | |
703 | VALIDATE_ACTIVE(tm->if_act_mask, if_id); | |
704 | for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; | |
705 | bus_id++) { | |
706 | VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); | |
707 | printf("%d ,\n", centralization_state[if_id][bus_id]); | |
708 | } | |
709 | } | |
710 | ||
711 | return MV_OK; | |
712 | } |