2 * Copyright (C) Marvell International Ltd. and its affiliates
4 * SPDX-License-Identifier: GPL-2.0
11 #include <asm/arch/cpu.h>
12 #include <asm/arch/soc.h>
14 #include "ddr3_hw_training.h"
19 #define DEBUG_DQS_C(s, d, l) \
20 DEBUG_DQS_S(s); DEBUG_DQS_D(d, l); DEBUG_DQS_S("\n")
21 #define DEBUG_DQS_FULL_C(s, d, l) \
22 DEBUG_DQS_FULL_S(s); DEBUG_DQS_FULL_D(d, l); DEBUG_DQS_FULL_S("\n")
23 #define DEBUG_DQS_RESULTS_C(s, d, l) \
24 DEBUG_DQS_RESULTS_S(s); DEBUG_DQS_RESULTS_D(d, l); DEBUG_DQS_RESULTS_S("\n")
25 #define DEBUG_PER_DQ_C(s, d, l) \
26 puts(s); printf("%x", d); puts("\n")
28 #define DEBUG_DQS_RESULTS_S(s) \
29 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
30 #define DEBUG_DQS_RESULTS_D(d, l) \
31 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
33 #define DEBUG_PER_DQ_S(s) \
34 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%s", s)
35 #define DEBUG_PER_DQ_D(d, l) \
36 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%x", d)
37 #define DEBUG_PER_DQ_DD(d, l) \
38 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%d", d)
41 #define DEBUG_DQS_S(s) puts(s)
42 #define DEBUG_DQS_D(d, l) printf("%x", d)
44 #define DEBUG_DQS_S(s)
45 #define DEBUG_DQS_D(d, l)
48 #ifdef MV_DEBUG_DQS_FULL
49 #define DEBUG_DQS_FULL_S(s) puts(s)
50 #define DEBUG_DQS_FULL_D(d, l) printf("%x", d)
52 #define DEBUG_DQS_FULL_S(s)
53 #define DEBUG_DQS_FULL_D(d, l)
56 /* State machine for centralization - find low & high limit */
58 PUP_ADLL_LIMITS_STATE_FAIL
,
59 PUP_ADLL_LIMITS_STATE_PASS
,
60 PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS
,
63 /* Hold centralization low results */
64 static int centralization_low_limit
[MAX_PUP_NUM
] = { 0 };
65 /* Hold centralization high results */
66 static int centralization_high_limit
[MAX_PUP_NUM
] = { 0 };
68 int ddr3_find_adll_limits(MV_DRAM_INFO
*dram_info
, u32 cs
, u32 ecc
, int is_tx
);
69 int ddr3_check_window_limits(u32 pup
, int high_limit
, int low_limit
, int is_tx
,
71 static int ddr3_center_calc(MV_DRAM_INFO
*dram_info
, u32 cs
, u32 ecc
,
73 int ddr3_special_pattern_i_search(MV_DRAM_INFO
*dram_info
, u32 cs
, u32 ecc
,
74 int is_tx
, u32 special_pattern_pup
);
75 int ddr3_special_pattern_ii_search(MV_DRAM_INFO
*dram_info
, u32 cs
, u32 ecc
,
76 int is_tx
, u32 special_pattern_pup
);
77 int ddr3_set_dqs_centralization_results(MV_DRAM_INFO
*dram_info
, u32 cs
, u32 ecc
,
81 extern u32 killer_pattern_32b
[DQ_NUM
][LEN_SPECIAL_PATTERN
];
82 extern u32 killer_pattern_64b
[DQ_NUM
][LEN_SPECIAL_PATTERN
];
83 extern int per_bit_data
[MAX_PUP_NUM
][DQ_NUM
];
85 extern u32 killer_pattern
[DQ_NUM
][LEN_16BIT_KILLER_PATTERN
];
86 extern u32 killer_pattern_32b
[DQ_NUM
][LEN_SPECIAL_PATTERN
];
87 #if defined(MV88F672X)
88 extern int per_bit_data
[MAX_PUP_NUM
][DQ_NUM
];
91 extern u32 special_pattern
[DQ_NUM
][LEN_SPECIAL_PATTERN
];
93 static u32
*ddr3_dqs_choose_pattern(MV_DRAM_INFO
*dram_info
, u32 victim_dq
)
98 switch (dram_info
->ddr_width
) {
99 #if defined(MV88F672X)
101 pattern_ptr
= (u32
*)&killer_pattern
[victim_dq
];
105 pattern_ptr
= (u32
*)&killer_pattern_32b
[victim_dq
];
107 #if defined(MV88F78X60)
109 pattern_ptr
= (u32
*)&killer_pattern_64b
[victim_dq
];
113 #if defined(MV88F78X60)
114 pattern_ptr
= (u32
*)&killer_pattern_32b
[victim_dq
];
116 pattern_ptr
= (u32
*)&killer_pattern
[victim_dq
];
125 * Name: ddr3_dqs_centralization_rx
126 * Desc: Execute the DQS centralization RX phase.
129 * Returns: MV_OK if success, other error code if fail.
131 int ddr3_dqs_centralization_rx(MV_DRAM_INFO
*dram_info
)
136 DEBUG_DQS_S("DDR3 - DQS Centralization RX - Starting procedure\n");
138 /* Enable SW override */
139 reg
= reg_read(REG_DRAM_TRAINING_2_ADDR
) |
140 (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS
);
142 /* [0] = 1 - Enable SW override */
143 /* 0x15B8 - Training SW 2 Register */
144 reg_write(REG_DRAM_TRAINING_2_ADDR
, reg
);
145 DEBUG_DQS_S("DDR3 - DQS Centralization RX - SW Override Enabled\n");
147 reg
= (1 << REG_DRAM_TRAINING_AUTO_OFFS
);
148 reg_write(REG_DRAM_TRAINING_ADDR
, reg
); /* 0x15B0 - Training Register */
150 /* Loop for each CS */
151 for (cs
= 0; cs
< MAX_CS
; cs
++) {
152 if (dram_info
->cs_ena
& (1 << cs
)) {
153 DEBUG_DQS_FULL_C("DDR3 - DQS Centralization RX - CS - ",
156 for (ecc
= 0; ecc
< (dram_info
->ecc_ena
+ 1); ecc
++) {
158 /* ECC Support - Switch ECC Mux on ecc=1 */
159 reg
= reg_read(REG_DRAM_TRAINING_2_ADDR
) &
160 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS
);
161 reg
|= (dram_info
->ecc_ena
*
162 ecc
<< REG_DRAM_TRAINING_2_ECC_MUX_OFFS
);
163 reg_write(REG_DRAM_TRAINING_2_ADDR
, reg
);
166 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Enabled\n");
168 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Disabled\n");
170 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Find all limits\n");
172 status
= ddr3_find_adll_limits(dram_info
, cs
,
177 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Start calculating center\n");
179 status
= ddr3_center_calc(dram_info
, cs
, ecc
,
187 /* ECC Support - Disable ECC MUX */
188 reg
= reg_read(REG_DRAM_TRAINING_2_ADDR
) &
189 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS
);
190 reg_write(REG_DRAM_TRAINING_2_ADDR
, reg
);
192 /* Disable SW override - Must be in a different stage */
193 /* [0]=0 - Enable SW override */
194 reg
= reg_read(REG_DRAM_TRAINING_2_ADDR
);
195 reg
&= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS
);
196 /* 0x15B8 - Training SW 2 Register */
197 reg_write(REG_DRAM_TRAINING_2_ADDR
, reg
);
199 reg
= reg_read(REG_DRAM_TRAINING_1_ADDR
) |
200 (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS
);
201 reg_write(REG_DRAM_TRAINING_1_ADDR
, reg
);
207 * Name: ddr3_dqs_centralization_tx
208 * Desc: Execute the DQS centralization TX phase.
211 * Returns: MV_OK if success, other error code if fail.
213 int ddr3_dqs_centralization_tx(MV_DRAM_INFO
*dram_info
)
218 DEBUG_DQS_S("DDR3 - DQS Centralization TX - Starting procedure\n");
220 /* Enable SW override */
221 reg
= reg_read(REG_DRAM_TRAINING_2_ADDR
) |
222 (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS
);
224 /* [0] = 1 - Enable SW override */
225 /* 0x15B8 - Training SW 2 Register */
226 reg_write(REG_DRAM_TRAINING_2_ADDR
, reg
);
227 DEBUG_DQS_S("DDR3 - DQS Centralization TX - SW Override Enabled\n");
229 reg
= (1 << REG_DRAM_TRAINING_AUTO_OFFS
);
230 reg_write(REG_DRAM_TRAINING_ADDR
, reg
); /* 0x15B0 - Training Register */
232 /* Loop for each CS */
233 for (cs
= 0; cs
< MAX_CS
; cs
++) {
234 if (dram_info
->cs_ena
& (1 << cs
)) {
235 DEBUG_DQS_FULL_C("DDR3 - DQS Centralization TX - CS - ",
237 for (ecc
= 0; ecc
< (dram_info
->ecc_ena
+ 1); ecc
++) {
238 /* ECC Support - Switch ECC Mux on ecc=1 */
239 reg
= reg_read(REG_DRAM_TRAINING_2_ADDR
) &
240 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS
);
241 reg
|= (dram_info
->ecc_ena
*
242 ecc
<< REG_DRAM_TRAINING_2_ECC_MUX_OFFS
);
243 reg_write(REG_DRAM_TRAINING_2_ADDR
, reg
);
246 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Enabled\n");
248 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Disabled\n");
250 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Find all limits\n");
252 status
= ddr3_find_adll_limits(dram_info
, cs
,
257 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Start calculating center\n");
259 status
= ddr3_center_calc(dram_info
, cs
, ecc
,
267 /* ECC Support - Disable ECC MUX */
268 reg
= reg_read(REG_DRAM_TRAINING_2_ADDR
) &
269 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS
);
270 reg_write(REG_DRAM_TRAINING_2_ADDR
, reg
);
272 /* Disable SW override - Must be in a different stage */
273 /* [0]=0 - Enable SW override */
274 reg
= reg_read(REG_DRAM_TRAINING_2_ADDR
);
275 reg
&= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS
);
276 /* 0x15B8 - Training SW 2 Register */
277 reg_write(REG_DRAM_TRAINING_2_ADDR
, reg
);
279 reg
= reg_read(REG_DRAM_TRAINING_1_ADDR
) |
280 (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS
);
281 reg_write(REG_DRAM_TRAINING_1_ADDR
, reg
);
287 * Name: ddr3_find_adll_limits
288 * Desc: Execute the Find ADLL limits phase.
292 * is_tx Indicate whether Rx or Tx
294 * Returns: MV_OK if success, other error code if fail.
296 int ddr3_find_adll_limits(MV_DRAM_INFO
*dram_info
, u32 cs
, u32 ecc
, int is_tx
)
298 u32 victim_dq
, pup
, tmp
;
300 u32 max_pup
; /* maximal pup index */
302 u32 unlock_pup
; /* bit array of un locked pups */
303 u32 new_unlock_pup
; /* bit array of compare failed pups */
305 u32 adll_start_val
; /* adll start loop value - for rx or tx limit */
306 u32 high_limit
; /* holds found High Limit */
307 u32 low_limit
; /* holds found Low Limit */
311 u32 uj
, cs_count
, cs_tmp
, ii
;
314 u32 adll_end_val
; /* adll end of loop val - for rx or tx limit */
315 u8 analog_pbs
[DQ_NUM
][MAX_PUP_NUM
][DQ_NUM
][2];
316 u8 analog_pbs_sum
[MAX_PUP_NUM
][DQ_NUM
][2];
317 int pup_adll_limit_state
[MAX_PUP_NUM
]; /* hold state of each pup */
319 adll_addr
= ((is_tx
== 1) ? PUP_DQS_WR
: PUP_DQS_RD
);
320 adll_end_val
= ((is_tx
== 1) ? ADLL_MIN
: ADLL_MAX
);
321 adll_start_val
= ((is_tx
== 1) ? ADLL_MAX
: ADLL_MIN
);
322 max_pup
= (ecc
+ (1 - ecc
) * dram_info
->num_of_std_pups
);
324 DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - Starting Find ADLL Limits\n");
327 for (pup
= 0; pup
< max_pup
; pup
++) {
328 centralization_low_limit
[pup
] = ADLL_MIN
;
329 centralization_high_limit
[pup
] = ADLL_MAX
;
334 for (cs_tmp
= 0; cs_tmp
< cs
; cs_tmp
++) {
335 if (dram_info
->cs_ena
& (1 << cs_tmp
))
338 sdram_offset
= cs_count
* (SDRAM_CS_SIZE
+ 1);
339 sdram_offset
+= ((is_tx
== 1) ?
340 SDRAM_DQS_TX_OFFS
: SDRAM_DQS_RX_OFFS
);
342 /* Prepare pup masks */
343 for (pup
= 0; pup
< max_pup
; pup
++)
344 pup_mask
|= (1 << pup
);
346 for (pup
= 0; pup
< max_pup
; pup
++) {
347 for (dq
= 0; dq
< DQ_NUM
; dq
++) {
348 analog_pbs_sum
[pup
][dq
][0] = adll_start_val
;
349 analog_pbs_sum
[pup
][dq
][1] = adll_end_val
;
353 /* Loop - use different pattern for each victim_dq */
354 for (victim_dq
= 0; victim_dq
< DQ_NUM
; victim_dq
++) {
355 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Victim DQ - ",
358 * The pups 3 bit arrays represent state machine. with
359 * 3 stages for each pup.
360 * 1. fail and didn't get pass in earlier compares.
362 * 3. fail after pass - end state.
363 * The window limits are the adll values where the adll
364 * was in the pass stage.
367 /* Set all states to Fail (1st state) */
368 for (pup
= 0; pup
< max_pup
; pup
++)
369 pup_adll_limit_state
[pup
] = PUP_ADLL_LIMITS_STATE_FAIL
;
371 /* Set current valid pups */
372 unlock_pup
= pup_mask
;
374 /* Set ADLL to start value */
375 curr_adll
= adll_start_val
;
377 #if defined(MV88F78X60)
378 for (pup
= 0; pup
< max_pup
; pup
++) {
379 for (dq
= 0; dq
< DQ_NUM
; dq
++) {
380 analog_pbs
[victim_dq
][pup
][dq
][0] =
382 analog_pbs
[victim_dq
][pup
][dq
][1] =
384 per_bit_data
[pup
][dq
] = 0;
389 for (uj
= 0; uj
< ADLL_MAX
; uj
++) {
390 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Setting ADLL to ",
392 for (pup
= 0; pup
< max_pup
; pup
++) {
393 if (IS_PUP_ACTIVE(unlock_pup
, pup
) == 1) {
394 tmp
= ((is_tx
== 1) ? curr_adll
+
395 dram_info
->wl_val
[cs
]
396 [pup
* (1 - ecc
) + ecc
* ECC_PUP
]
398 ddr3_write_pup_reg(adll_addr
, cs
, pup
+
399 (ecc
* ECC_PUP
), 0, tmp
);
404 pattern_ptr
= ddr3_dqs_choose_pattern(dram_info
,
407 /* '1' - means pup failed, '0' - means pup pass */
410 /* Read and compare results for Victim_DQ# */
411 for (ii
= 0; ii
< 3; ii
++) {
413 if (MV_OK
!= ddr3_sdram_dqs_compare(dram_info
,
422 return MV_DDR3_TRAINING_ERR_DRAM_COMPARE
;
424 new_unlock_pup
|= tmp
;
428 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - UnlockPup: ",
430 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - NewUnlockPup: ",
433 /* Update pup state */
434 for (pup
= 0; pup
< max_pup
; pup
++) {
435 if (IS_PUP_ACTIVE(unlock_pup
, pup
) == 0) {
436 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Skipping pup ",
442 * Still didn't find the window limit of the pup
444 if (IS_PUP_ACTIVE(new_unlock_pup
, pup
) == 1) {
445 /* Current compare result == fail */
446 if (pup_adll_limit_state
[pup
] ==
447 PUP_ADLL_LIMITS_STATE_PASS
) {
449 * If now it failed but passed
452 DEBUG_DQS_S("DDR3 - DQS Find Limits - PASS to FAIL: CS - ");
454 DEBUG_DQS_S(", DQ - ");
455 DEBUG_DQS_D(victim_dq
, 1);
456 DEBUG_DQS_S(", Pup - ");
458 DEBUG_DQS_S(", ADLL - ");
459 DEBUG_DQS_D(curr_adll
, 2);
462 #if defined(MV88F78X60)
463 for (dq
= 0; dq
< DQ_NUM
; dq
++) {
464 if ((analog_pbs
[victim_dq
][pup
][dq
][0] != adll_start_val
)
465 && (analog_pbs
[victim_dq
][pup
]
466 [dq
][1] == adll_end_val
))
477 /* Keep min / max limit value */
479 /* RX - found upper limit */
480 if (centralization_high_limit
[pup
] >
485 centralization_low_limit
[pup
];
489 /* TX - found lower limit */
490 if (centralization_low_limit
[pup
] < (curr_adll
+ 1)) {
492 centralization_high_limit
501 if (update_win
== 1) {
504 * window limits we need
509 ddr3_check_window_limits
513 return MV_DDR3_TRAINING_ERR_WIN_LIMITS
;
515 if (win_valid
== 1) {
521 centralization_low_limit
524 centralization_high_limit
530 if (win_valid
== 1) {
531 /* Found end of window - lock the pup */
532 pup_adll_limit_state
[pup
] =
533 PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS
;
534 unlock_pup
&= ~(1 << pup
);
536 /* Probably false pass - reset status */
537 pup_adll_limit_state
[pup
] =
538 PUP_ADLL_LIMITS_STATE_FAIL
;
540 #if defined(MV88F78X60)
541 /* Clear logging array of win size (per Dq) */
563 /* Current compare result == pass */
564 if (pup_adll_limit_state
[pup
] ==
565 PUP_ADLL_LIMITS_STATE_FAIL
) {
566 /* If now it passed but failed earlier */
567 DEBUG_DQS_S("DDR3 - DQS Find Limits - FAIL to PASS: CS - ");
569 DEBUG_DQS_S(", DQ - ");
570 DEBUG_DQS_D(victim_dq
, 1);
571 DEBUG_DQS_S(", Pup - ");
573 DEBUG_DQS_S(", ADLL - ");
574 DEBUG_DQS_D(curr_adll
, 2);
577 #if defined(MV88F78X60)
578 for (dq
= 0; dq
< DQ_NUM
;
580 if (analog_pbs
[victim_dq
][pup
][dq
][0] == adll_start_val
)
588 /* Found start of window */
589 pup_adll_limit_state
[pup
] =
590 PUP_ADLL_LIMITS_STATE_PASS
;
592 /* Keep min / max limit value */
594 /* RX - found low limit */
595 if (centralization_low_limit
[pup
] <= curr_adll
)
596 centralization_low_limit
600 /* TX - found high limit */
601 if (centralization_high_limit
[pup
] >= curr_adll
)
602 centralization_high_limit
610 if (unlock_pup
== 0) {
611 /* Found limit to all pups */
612 DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - found PUP limit\n");
617 * Increment / decrement (Move to right / left
618 * one phase - ADLL) dqs RX / TX delay (for all un
627 if (unlock_pup
!= 0) {
629 * Found pups that didn't reach to the end of the
632 DEBUG_DQS_C("DDR3 - DQS Find Limits - Pups that didn't reached end of the state machine: ",
635 for (pup
= 0; pup
< max_pup
; pup
++) {
636 if (IS_PUP_ACTIVE(unlock_pup
, pup
) == 1) {
637 if (pup_adll_limit_state
[pup
] ==
638 PUP_ADLL_LIMITS_STATE_FAIL
) {
639 /* ERROR - found fail for all window size */
640 DEBUG_DQS_S("DDR3 - DQS Find Limits - Got FAIL for the complete range on pup - ");
642 DEBUG_DQS_C(" victim DQ ",
645 /* For debug - set min limit to illegal limit */
646 centralization_low_limit
[pup
]
649 * In case the pup is in mode
650 * PASS - the limit is the min
651 * / max adll, no need to
652 * update because of the results
653 * array default value
655 return MV_DDR3_TRAINING_ERR_PUP_RANGE
;
662 DEBUG_DQS_S("DDR3 - DQS Find Limits - DQ values per victim results:\n");
663 for (victim_dq
= 0; victim_dq
< DQ_NUM
; victim_dq
++) {
664 for (pup
= 0; pup
< max_pup
; pup
++) {
665 DEBUG_DQS_S("Victim DQ-");
666 DEBUG_DQS_D(victim_dq
, 1);
667 DEBUG_DQS_S(", PUP-");
669 for (dq
= 0; dq
< DQ_NUM
; dq
++) {
670 DEBUG_DQS_S(", DQ-");
673 DEBUG_DQS_D(analog_pbs
[victim_dq
][pup
][dq
]
676 DEBUG_DQS_D(analog_pbs
[victim_dq
][pup
][dq
]
680 if (analog_pbs
[victim_dq
][pup
][dq
][0]
681 > analog_pbs_sum
[pup
][dq
][0])
682 analog_pbs_sum
[pup
][dq
][0] =
683 analog_pbs
[victim_dq
][pup
]
685 if (analog_pbs
[victim_dq
][pup
][dq
][1]
686 < analog_pbs_sum
[pup
][dq
][1])
687 analog_pbs_sum
[pup
][dq
][1] =
688 analog_pbs
[victim_dq
][pup
]
691 if (analog_pbs
[victim_dq
][pup
][dq
][0]
692 < analog_pbs_sum
[pup
][dq
][0])
693 analog_pbs_sum
[pup
][dq
][0] =
694 analog_pbs
[victim_dq
][pup
]
696 if (analog_pbs
[victim_dq
][pup
][dq
][1]
697 > analog_pbs_sum
[pup
][dq
][1])
698 analog_pbs_sum
[pup
][dq
][1] =
699 analog_pbs
[victim_dq
][pup
]
707 if (ddr3_get_log_level() >= MV_LOG_LEVEL_3
) {
710 DEBUG_PER_DQ_S("\n########## LOG LEVEL 3(Windows margins per-DQ) ##########\n");
712 DEBUG_PER_DQ_C("DDR3 - TX CS: ", cs
, 1);
714 DEBUG_PER_DQ_C("DDR3 - RX CS: ", cs
, 1);
718 DEBUG_PER_DQ_S("\n DATA RESULTS:\n");
720 DEBUG_PER_DQ_S("\n ECC RESULTS:\n");
723 /* Since all dq has the same value we take 0 as representive */
725 for (pup
= 0; pup
< max_pup
; pup
++) {
727 DEBUG_PER_DQ_S("\nBYTE:");
728 DEBUG_PER_DQ_D(pup
, 1);
729 DEBUG_PER_DQ_S("\n");
731 DEBUG_PER_DQ_S("\nECC BYTE:\n");
733 DEBUG_PER_DQ_S(" DQ's LOW HIGH WIN-SIZE\n");
734 DEBUG_PER_DQ_S("============================================\n");
735 for (victim_dq
= 0; victim_dq
< DQ_NUM
; victim_dq
++) {
737 DEBUG_PER_DQ_S("DQ[");
738 DEBUG_PER_DQ_DD((victim_dq
+
742 DEBUG_PER_DQ_S("CB[");
743 DEBUG_PER_DQ_DD(victim_dq
, 2);
747 DEBUG_PER_DQ_S(" 0x");
748 DEBUG_PER_DQ_D(analog_pbs
[victim_dq
][pup
][dq
][1], 2); /* low value */
749 DEBUG_PER_DQ_S(" 0x");
750 DEBUG_PER_DQ_D(analog_pbs
[victim_dq
][pup
][dq
][0], 2); /* high value */
751 DEBUG_PER_DQ_S(" 0x");
752 DEBUG_PER_DQ_D(analog_pbs
[victim_dq
][pup
][dq
][0] - analog_pbs
[victim_dq
][pup
][dq
][1], 2); /* win-size */
754 DEBUG_PER_DQ_S(" 0x");
755 DEBUG_PER_DQ_D(analog_pbs
[victim_dq
][pup
][dq
][0], 2); /* low value */
756 DEBUG_PER_DQ_S(" 0x");
757 DEBUG_PER_DQ_D((analog_pbs
[victim_dq
][pup
][dq
][1] - 1), 2); /* high value */
758 DEBUG_PER_DQ_S(" 0x");
759 DEBUG_PER_DQ_D(analog_pbs
[victim_dq
][pup
][dq
][1] - analog_pbs
[victim_dq
][pup
][dq
][0], 2); /* win-size */
761 DEBUG_PER_DQ_S("\n");
764 DEBUG_PER_DQ_S("\n");
768 DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
770 DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
773 for (pup
= 0; pup
< max_pup
; pup
++) {
776 for (dq
= 0; dq
< DQ_NUM
; dq
++) {
777 DEBUG_DQS_S(", DQ-");
780 DEBUG_DQS_D(analog_pbs_sum
[pup
][dq
][0], 2);
782 DEBUG_DQS_D(analog_pbs_sum
[pup
][dq
][1], 2);
788 DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
790 DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
793 for (pup
= 0; pup
< max_pup
; pup
++) {
796 DEBUG_DQS_S("DDR3 - DQS8");
798 DEBUG_DQS_S("DDR3 - DQS");
802 for (dq
= 0; dq
< DQ_NUM
; dq
++) {
803 DEBUG_DQS_S(", DQ-");
806 DEBUG_DQS_D(analog_pbs_sum
[pup
][dq
][0], 2);
808 DEBUG_DQS_D(analog_pbs_sum
[pup
][dq
][1], 2);
813 DEBUG_DQS_S("DDR3 - DQS Find Limits - Ended\n");
819 * Name: ddr3_check_window_limits
820 * Desc: Check window High & Low limits.
821 * Args: pup pup index
822 * high_limit window high limit
823 * low_limit window low limit
824 * is_tx Indicate whether Rx or Tx
825 * size_valid Indicate whether window size is valid
827 * Returns: MV_OK if success, other error code if fail.
829 int ddr3_check_window_limits(u32 pup
, int high_limit
, int low_limit
, int is_tx
,
832 DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Starting\n");
834 if (low_limit
> high_limit
) {
835 DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
837 DEBUG_DQS_S(" Low Limit grater than High Limit\n");
843 * Check that window size is valid, if not it was probably false pass
846 if ((high_limit
- low_limit
) < MIN_WIN_SIZE
) {
848 * Since window size is too small probably there was false
853 DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
855 DEBUG_DQS_S(" Window size is smaller than MIN_WIN_SIZE\n");
857 } else if ((high_limit
- low_limit
) > ADLL_MAX
) {
860 DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
863 (" Window size is bigger than max ADLL taps (31) Exiting.\n");
870 DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Pup ");
871 DEBUG_DQS_FULL_D(pup
, 1);
872 DEBUG_DQS_FULL_C(" window size is ", (high_limit
- low_limit
),
880 * Name: ddr3_center_calc
881 * Desc: Execute the calculate the center of windows phase.
883 * is_tx Indicate whether Rx or Tx
885 * Returns: MV_OK if success, other error code if fail.
887 static int ddr3_center_calc(MV_DRAM_INFO
*dram_info
, u32 cs
, u32 ecc
,
890 /* bit array of pups that need specail search */
891 u32 special_pattern_i_pup
= 0;
892 u32 special_pattern_ii_pup
= 0;
896 max_pup
= (ecc
+ (1 - ecc
) * dram_info
->num_of_std_pups
);
898 for (pup
= 0; pup
< max_pup
; pup
++) {
900 /* Check special pattern I */
902 * Special pattern Low limit search - relevant only
903 * for Rx, win size < threshold and low limit = 0
905 if (((centralization_high_limit
[pup
] -
906 centralization_low_limit
[pup
]) < VALID_WIN_THRS
)
907 && (centralization_low_limit
[pup
] == MIN_DELAY
))
908 special_pattern_i_pup
|= (1 << pup
);
910 /* Check special pattern II */
912 * Special pattern High limit search - relevant only
913 * for Rx, win size < threshold and high limit = 31
915 if (((centralization_high_limit
[pup
] -
916 centralization_low_limit
[pup
]) < VALID_WIN_THRS
)
917 && (centralization_high_limit
[pup
] == MAX_DELAY
))
918 special_pattern_ii_pup
|= (1 << pup
);
922 /* Run special pattern Low limit search - for relevant pup */
923 if (special_pattern_i_pup
!= 0) {
924 DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern I for Low limit search\n");
926 ddr3_special_pattern_i_search(dram_info
, cs
, ecc
, is_tx
,
927 special_pattern_i_pup
))
928 return MV_DDR3_TRAINING_ERR_DQS_LOW_LIMIT_SEARCH
;
931 /* Run special pattern High limit search - for relevant pup */
932 if (special_pattern_ii_pup
!= 0) {
933 DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern II for High limit search\n");
935 ddr3_special_pattern_ii_search(dram_info
, cs
, ecc
, is_tx
,
936 special_pattern_ii_pup
))
937 return MV_DDR3_TRAINING_ERR_DQS_HIGH_LIMIT_SEARCH
;
940 /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
941 return ddr3_set_dqs_centralization_results(dram_info
, cs
, ecc
, is_tx
);
945 * Name: ddr3_special_pattern_i_search
946 * Desc: Execute special pattern low limit search.
948 * special_pattern_pup The pups that need the special search
950 * Returns: MV_OK if success, other error code if fail.
952 int ddr3_special_pattern_i_search(MV_DRAM_INFO
*dram_info
, u32 cs
, u32 ecc
,
953 int is_tx
, u32 special_pattern_pup
)
955 u32 victim_dq
; /* loop index - victim DQ */
958 u32 unlock_pup
; /* bit array of the unlock pups */
959 u32 first_fail
; /* bit array - of pups that get first fail */
960 u32 new_lockup_pup
; /* bit array of compare failed pups */
961 u32 pass_pup
; /* bit array of compare pass pup */
965 u32 special_res
[MAX_PUP_NUM
]; /* hold tmp results */
967 DEBUG_DQS_S("DDR3 - DQS - Special Pattern I Search - Starting\n");
969 max_pup
= ecc
+ (1 - ecc
) * dram_info
->num_of_std_pups
;
971 /* Init the temporary results to max ADLL value */
972 for (pup
= 0; pup
< max_pup
; pup
++)
973 special_res
[pup
] = ADLL_MAX
;
975 /* Run special pattern for all DQ - use the same pattern */
976 for (victim_dq
= 0; victim_dq
< DQ_NUM
; victim_dq
++) {
977 unlock_pup
= special_pattern_pup
;
980 sdram_offset
= cs
* SDRAM_CS_SIZE
+ SDRAM_DQS_RX_OFFS
+
981 LEN_KILLER_PATTERN
* 4 * victim_dq
;
983 for (pup
= 0; pup
< max_pup
; pup
++) {
984 /* Set adll value per PUP. adll = high limit per pup */
985 if (IS_PUP_ACTIVE(unlock_pup
, pup
)) {
986 /* only for pups that need special search */
987 ddr3_write_pup_reg(PUP_DQS_RD
, cs
,
988 pup
+ (ecc
* ECC_PUP
), 0,
989 centralization_high_limit
997 * Perform read and compare simultaneously for all
998 * un-locked MC use the special pattern mask
1003 ddr3_sdram_dqs_compare(dram_info
, unlock_pup
,
1007 LEN_SPECIAL_PATTERN
,
1012 DEBUG_DQS_S("DDR3 - DQS - Special I - ADLL value is: ");
1013 DEBUG_DQS_D(adll_idx
, 2);
1014 DEBUG_DQS_S(", UnlockPup: ");
1015 DEBUG_DQS_D(unlock_pup
, 2);
1016 DEBUG_DQS_S(", NewLockPup: ");
1017 DEBUG_DQS_D(new_lockup_pup
, 2);
1020 if (unlock_pup
!= new_lockup_pup
)
1021 DEBUG_DQS_S("DDR3 - DQS - Special I - Some Pup passed!\n");
1023 /* Search for pups with passed compare & already fail */
1024 pass_pup
= first_fail
& ~new_lockup_pup
& unlock_pup
;
1025 first_fail
|= new_lockup_pup
;
1026 unlock_pup
&= ~pass_pup
;
1029 if (pass_pup
!= 0) {
1030 for (pup
= 0; pup
< max_pup
; pup
++) {
1031 if (IS_PUP_ACTIVE(pass_pup
, pup
) ==
1033 /* If pup passed and has first fail = 1 */
1034 /* keep min value of ADLL max value - current adll */
1035 /* (centralization_high_limit[pup] + adll_idx) = current adll !!! */
1038 (centralization_high_limit
1042 ("DDR3 - DQS - Special I - Pup - ",
1052 centralization_low_limit
1058 ("DDR3 - DQS - Special I - Pup - ",
1061 (" Changed Low limit to ",
1062 centralization_low_limit
1070 * Did all PUP found missing window?
1071 * Check for each pup if adll (different for each pup)
1072 * reach maximum if reach max value - lock the pup
1073 * if not - increment (Move to right one phase - ADLL)
1077 for (pup
= 0; pup
< max_pup
; pup
++) {
1078 if (IS_PUP_ACTIVE(unlock_pup
, pup
) == 1) {
1079 /* Check only unlocked pups */
1080 if ((centralization_high_limit
[pup
] +
1081 adll_idx
) >= ADLL_MAX
) {
1082 /* reach maximum - lock the pup */
1083 DEBUG_DQS_C("DDR3 - DQS - Special I - reach maximum - lock pup ",
1085 unlock_pup
&= ~(1 << pup
);
1087 /* Didn't reach maximum - increment ADLL */
1088 ddr3_write_pup_reg(PUP_DQS_RD
,
1093 (centralization_high_limit
1099 } while (unlock_pup
!= 0);
1106 * Name: ddr3_special_pattern_ii_search
1107 * Desc: Execute special pattern high limit search.
1109 * special_pattern_pup The pups that need the special search
1111 * Returns: MV_OK if success, other error code if fail.
1113 int ddr3_special_pattern_ii_search(MV_DRAM_INFO
*dram_info
, u32 cs
, u32 ecc
,
1114 int is_tx
, u32 special_pattern_pup
)
1116 u32 victim_dq
; /* loop index - victim DQ */
1119 u32 unlock_pup
; /* bit array of the unlock pups */
1120 u32 first_fail
; /* bit array - of pups that get first fail */
1121 u32 new_lockup_pup
; /* bit array of compare failed pups */
1122 u32 pass_pup
; /* bit array of compare pass pup */
1126 u32 special_res
[MAX_PUP_NUM
]; /* hold tmp results */
1128 DEBUG_DQS_S("DDR3 - DQS - Special Pattern II Search - Starting\n");
1130 max_pup
= (ecc
+ (1 - ecc
) * dram_info
->num_of_std_pups
);
1132 /* init the tmporary results to max ADLL value */
1133 for (pup
= 0; pup
< max_pup
; pup
++)
1134 special_res
[pup
] = ADLL_MAX
;
1136 sdram_offset
= cs
* SDRAM_CS_SIZE
+ SDRAM_DQS_RX_OFFS
;
1138 /* run special pattern for all DQ - use the same pattern */
1139 for (victim_dq
= 0; victim_dq
< DQ_NUM
; victim_dq
++) {
1140 unlock_pup
= special_pattern_pup
;
1143 for (pup
= 0; pup
< max_pup
; pup
++) {
1144 /* Set adll value per PUP. adll = 0 */
1145 if (IS_PUP_ACTIVE(unlock_pup
, pup
)) {
1146 /* Only for pups that need special search */
1147 ddr3_write_pup_reg(PUP_DQS_RD
, cs
,
1148 pup
+ (ecc
* ECC_PUP
), 0,
1156 * Perform read and compare simultaneously for all
1157 * un-locked MC use the special pattern mask
1161 if (MV_OK
!= ddr3_sdram_dqs_compare(
1162 dram_info
, unlock_pup
, &new_lockup_pup
,
1163 special_pattern
[victim_dq
],
1164 LEN_SPECIAL_PATTERN
,
1165 sdram_offset
, 0, 0, NULL
, 0))
1168 DEBUG_DQS_S("DDR3 - DQS - Special II - ADLL value is ");
1169 DEBUG_DQS_D(adll_idx
, 2);
1170 DEBUG_DQS_S("unlock_pup ");
1171 DEBUG_DQS_D(unlock_pup
, 1);
1172 DEBUG_DQS_S("new_lockup_pup ");
1173 DEBUG_DQS_D(new_lockup_pup
, 1);
1176 if (unlock_pup
!= new_lockup_pup
) {
1177 DEBUG_DQS_S("DDR3 - DQS - Special II - Some Pup passed!\n");
1180 /* Search for pups with passed compare & already fail */
1181 pass_pup
= first_fail
& ~new_lockup_pup
& unlock_pup
;
1182 first_fail
|= new_lockup_pup
;
1183 unlock_pup
&= ~pass_pup
;
1186 if (pass_pup
!= 0) {
1187 for (pup
= 0; pup
< max_pup
; pup
++) {
1188 if (IS_PUP_ACTIVE(pass_pup
, pup
) ==
1190 /* If pup passed and has first fail = 1 */
1191 /* keep min value of ADLL max value - current adll */
1192 /* (adll_idx) = current adll !!! */
1193 comp_val
= adll_idx
;
1195 DEBUG_DQS_C("DDR3 - DQS - Special II - Pup - ",
1197 DEBUG_DQS_C(" comp_val = ",
1204 centralization_high_limit
1210 ("DDR3 - DQS - Special II - Pup - ",
1213 (" Changed High limit to ",
1214 centralization_high_limit
1222 * Did all PUP found missing window?
1223 * Check for each pup if adll (different for each pup)
1224 * reach maximum if reach max value - lock the pup
1225 * if not - increment (Move to right one phase - ADLL)
1229 for (pup
= 0; pup
< max_pup
; pup
++) {
1230 if (IS_PUP_ACTIVE(unlock_pup
, pup
) == 1) {
1231 /* Check only unlocked pups */
1232 if ((adll_idx
) >= ADLL_MAX
) {
1233 /* Reach maximum - lock the pup */
1234 DEBUG_DQS_C("DDR3 - DQS - Special II - reach maximum - lock pup ",
1236 unlock_pup
&= ~(1 << pup
);
1238 /* Didn't reach maximum - increment ADLL */
1239 ddr3_write_pup_reg(PUP_DQS_RD
,
1248 } while (unlock_pup
!= 0);
1255 * Name: ddr3_set_dqs_centralization_results
1256 * Desc: Set to HW the DQS centralization phase results.
1258 * is_tx Indicates whether to set Tx or RX results
1260 * Returns: MV_OK if success, other error code if fail.
1262 int ddr3_set_dqs_centralization_results(MV_DRAM_INFO
*dram_info
, u32 cs
,
1269 max_pup
= (ecc
+ (1 - ecc
) * dram_info
->num_of_std_pups
);
1271 DEBUG_DQS_RESULTS_S("\n############ LOG LEVEL 2(Windows margins) ############\n");
1274 DEBUG_DQS_RESULTS_C("DDR3 - DQS TX - Set Dqs Centralization Results - CS: ",
1277 DEBUG_DQS_RESULTS_C("DDR3 - DQS RX - Set Dqs Centralization Results - CS: ",
1281 /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
1282 DEBUG_DQS_RESULTS_S("\nDQS LOW HIGH WIN-SIZE Set\n");
1283 DEBUG_DQS_RESULTS_S("==============================================\n");
1284 for (pup
= 0; pup
< max_pup
; pup
++) {
1285 addl_val
= (centralization_high_limit
[pup
] +
1286 centralization_low_limit
[pup
]) / 2;
1288 pup_num
= pup
* (1 - ecc
) + ecc
* ECC_PUP
;
1290 DEBUG_DQS_RESULTS_D(pup_num
, 1);
1291 DEBUG_DQS_RESULTS_S(" 0x");
1292 DEBUG_DQS_RESULTS_D(centralization_low_limit
[pup
], 2);
1293 DEBUG_DQS_RESULTS_S(" 0x");
1294 DEBUG_DQS_RESULTS_D(centralization_high_limit
[pup
], 2);
1295 DEBUG_DQS_RESULTS_S(" 0x");
1296 DEBUG_DQS_RESULTS_D(centralization_high_limit
[pup
] -
1297 centralization_low_limit
[pup
], 2);
1298 DEBUG_DQS_RESULTS_S(" 0x");
1299 DEBUG_DQS_RESULTS_D(addl_val
, 2);
1300 DEBUG_DQS_RESULTS_S("\n");
1302 if (addl_val
< ADLL_MIN
) {
1303 addl_val
= ADLL_MIN
;
1304 DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MIN (since it was lower than 0)\n");
1307 if (addl_val
> ADLL_MAX
) {
1308 addl_val
= ADLL_MAX
;
1309 DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MAX (since it was higher than 31)\n");
1313 ddr3_write_pup_reg(PUP_DQS_WR
, cs
, pup_num
, 0,
1315 dram_info
->wl_val
[cs
][pup_num
][D
]);
1317 ddr3_write_pup_reg(PUP_DQS_RD
, cs
, pup_num
, 0,
1326 * Set training patterns
1328 int ddr3_load_dqs_patterns(MV_DRAM_INFO
*dram_info
)
1330 u32 cs
, cs_count
, cs_tmp
, victim_dq
;
1334 /* Loop for each CS */
1335 for (cs
= 0; cs
< MAX_CS
; cs
++) {
1336 if (dram_info
->cs_ena
& (1 << cs
)) {
1338 for (cs_tmp
= 0; cs_tmp
< cs
; cs_tmp
++) {
1339 if (dram_info
->cs_ena
& (1 << cs_tmp
))
1343 /* Init killer pattern */
1344 sdram_addr
= (cs_count
* (SDRAM_CS_SIZE
+ 1) +
1346 for (victim_dq
= 0; victim_dq
< DQ_NUM
; victim_dq
++) {
1347 pattern_ptr
= ddr3_dqs_choose_pattern(dram_info
,
1349 if (MV_OK
!= ddr3_sdram_dqs_compare(
1350 dram_info
, (u32
)NULL
, NULL
,
1351 pattern_ptr
, LEN_KILLER_PATTERN
,
1352 sdram_addr
+ LEN_KILLER_PATTERN
*
1353 4 * victim_dq
, 1, 0, NULL
,
1355 return MV_DDR3_TRAINING_ERR_DQS_PATTERN
;
1358 /* Init special-killer pattern */
1359 sdram_addr
= (cs_count
* (SDRAM_CS_SIZE
+ 1) +
1360 SDRAM_DQS_RX_SPECIAL_OFFS
);
1361 for (victim_dq
= 0; victim_dq
< DQ_NUM
; victim_dq
++) {
1362 if (MV_OK
!= ddr3_sdram_dqs_compare(
1363 dram_info
, (u32
)NULL
, NULL
,
1364 special_pattern
[victim_dq
],
1365 LEN_KILLER_PATTERN
, sdram_addr
+
1366 LEN_KILLER_PATTERN
* 4 * victim_dq
,
1368 return MV_DDR3_TRAINING_ERR_DQS_PATTERN
;