1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) Marvell International Ltd. and its affiliates
10 #include <asm/arch/cpu.h>
11 #include <asm/arch/soc.h>
13 #include "ddr3_hw_training.h"
18 #define DEBUG_DQS_C(s, d, l) \
19 DEBUG_DQS_S(s); DEBUG_DQS_D(d, l); DEBUG_DQS_S("\n")
20 #define DEBUG_DQS_FULL_C(s, d, l) \
21 DEBUG_DQS_FULL_S(s); DEBUG_DQS_FULL_D(d, l); DEBUG_DQS_FULL_S("\n")
22 #define DEBUG_DQS_RESULTS_C(s, d, l) \
23 DEBUG_DQS_RESULTS_S(s); DEBUG_DQS_RESULTS_D(d, l); DEBUG_DQS_RESULTS_S("\n")
24 #define DEBUG_PER_DQ_C(s, d, l) \
25 puts(s); printf("%x", d); puts("\n")
27 #define DEBUG_DQS_RESULTS_S(s) \
28 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
29 #define DEBUG_DQS_RESULTS_D(d, l) \
30 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
32 #define DEBUG_PER_DQ_S(s) \
33 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%s", s)
34 #define DEBUG_PER_DQ_D(d, l) \
35 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%x", d)
36 #define DEBUG_PER_DQ_DD(d, l) \
37 debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%d", d)
40 #define DEBUG_DQS_S(s) puts(s)
41 #define DEBUG_DQS_D(d, l) printf("%x", d)
43 #define DEBUG_DQS_S(s)
44 #define DEBUG_DQS_D(d, l)
47 #ifdef MV_DEBUG_DQS_FULL
48 #define DEBUG_DQS_FULL_S(s) puts(s)
49 #define DEBUG_DQS_FULL_D(d, l) printf("%x", d)
51 #define DEBUG_DQS_FULL_S(s)
52 #define DEBUG_DQS_FULL_D(d, l)
55 /* State machine for centralization - find low & high limit */
57 PUP_ADLL_LIMITS_STATE_FAIL,
58 PUP_ADLL_LIMITS_STATE_PASS,
59 PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS,
62 /* Hold centralization low results */
63 static int centralization_low_limit[MAX_PUP_NUM] = { 0 };
64 /* Hold centralization high results */
65 static int centralization_high_limit[MAX_PUP_NUM] = { 0 };
67 int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx);
68 int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
70 static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
72 int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
73 int is_tx, u32 special_pattern_pup);
74 int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
75 int is_tx, u32 special_pattern_pup);
76 int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
80 extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
81 extern u32 killer_pattern_64b[DQ_NUM][LEN_SPECIAL_PATTERN];
82 extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
84 extern u32 killer_pattern[DQ_NUM][LEN_16BIT_KILLER_PATTERN];
85 extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
86 #if defined(MV88F672X)
87 extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
90 extern u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN];
92 static u32 *ddr3_dqs_choose_pattern(MV_DRAM_INFO *dram_info, u32 victim_dq)
97 switch (dram_info->ddr_width) {
98 #if defined(MV88F672X)
100 pattern_ptr = (u32 *)&killer_pattern[victim_dq];
104 pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
106 #if defined(MV88F78X60)
108 pattern_ptr = (u32 *)&killer_pattern_64b[victim_dq];
112 #if defined(MV88F78X60)
113 pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
115 pattern_ptr = (u32 *)&killer_pattern[victim_dq];
124 * Name: ddr3_dqs_centralization_rx
125 * Desc: Execute the DQS centralization RX phase.
128 * Returns: MV_OK if success, other error code if fail.
130 int ddr3_dqs_centralization_rx(MV_DRAM_INFO *dram_info)
135 DEBUG_DQS_S("DDR3 - DQS Centralization RX - Starting procedure\n");
137 /* Enable SW override */
138 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
139 (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
141 /* [0] = 1 - Enable SW override */
142 /* 0x15B8 - Training SW 2 Register */
143 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
144 DEBUG_DQS_S("DDR3 - DQS Centralization RX - SW Override Enabled\n");
146 reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
147 reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
149 /* Loop for each CS */
150 for (cs = 0; cs < MAX_CS; cs++) {
151 if (dram_info->cs_ena & (1 << cs)) {
152 DEBUG_DQS_FULL_C("DDR3 - DQS Centralization RX - CS - ",
155 for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
157 /* ECC Support - Switch ECC Mux on ecc=1 */
158 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
159 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
160 reg |= (dram_info->ecc_ena *
161 ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
162 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
165 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Enabled\n");
167 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Disabled\n");
169 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Find all limits\n");
171 status = ddr3_find_adll_limits(dram_info, cs,
176 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Start calculating center\n");
178 status = ddr3_center_calc(dram_info, cs, ecc,
186 /* ECC Support - Disable ECC MUX */
187 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
188 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
189 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
191 /* Disable SW override - Must be in a different stage */
192 /* [0]=0 - Enable SW override */
193 reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
194 reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
195 /* 0x15B8 - Training SW 2 Register */
196 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
198 reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
199 (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
200 reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
206 * Name: ddr3_dqs_centralization_tx
207 * Desc: Execute the DQS centralization TX phase.
210 * Returns: MV_OK if success, other error code if fail.
212 int ddr3_dqs_centralization_tx(MV_DRAM_INFO *dram_info)
217 DEBUG_DQS_S("DDR3 - DQS Centralization TX - Starting procedure\n");
219 /* Enable SW override */
220 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
221 (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
223 /* [0] = 1 - Enable SW override */
224 /* 0x15B8 - Training SW 2 Register */
225 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
226 DEBUG_DQS_S("DDR3 - DQS Centralization TX - SW Override Enabled\n");
228 reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
229 reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
231 /* Loop for each CS */
232 for (cs = 0; cs < MAX_CS; cs++) {
233 if (dram_info->cs_ena & (1 << cs)) {
234 DEBUG_DQS_FULL_C("DDR3 - DQS Centralization TX - CS - ",
236 for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
237 /* ECC Support - Switch ECC Mux on ecc=1 */
238 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
239 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
240 reg |= (dram_info->ecc_ena *
241 ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
242 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
245 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Enabled\n");
247 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Disabled\n");
249 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Find all limits\n");
251 status = ddr3_find_adll_limits(dram_info, cs,
256 DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Start calculating center\n");
258 status = ddr3_center_calc(dram_info, cs, ecc,
266 /* ECC Support - Disable ECC MUX */
267 reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
268 ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
269 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
271 /* Disable SW override - Must be in a different stage */
272 /* [0]=0 - Enable SW override */
273 reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
274 reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
275 /* 0x15B8 - Training SW 2 Register */
276 reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
278 reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
279 (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
280 reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
286 * Name: ddr3_find_adll_limits
287 * Desc: Execute the Find ADLL limits phase.
291 * is_tx Indicate whether Rx or Tx
293 * Returns: MV_OK if success, other error code if fail.
295 int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx)
297 u32 victim_dq, pup, tmp;
299 u32 max_pup; /* maximal pup index */
301 u32 unlock_pup; /* bit array of un locked pups */
302 u32 new_unlock_pup; /* bit array of compare failed pups */
304 u32 adll_start_val; /* adll start loop value - for rx or tx limit */
305 u32 high_limit; /* holds found High Limit */
306 u32 low_limit; /* holds found Low Limit */
310 u32 uj, cs_count, cs_tmp, ii;
313 u32 adll_end_val; /* adll end of loop val - for rx or tx limit */
314 u8 analog_pbs[DQ_NUM][MAX_PUP_NUM][DQ_NUM][2];
315 u8 analog_pbs_sum[MAX_PUP_NUM][DQ_NUM][2];
316 int pup_adll_limit_state[MAX_PUP_NUM]; /* hold state of each pup */
318 adll_addr = ((is_tx == 1) ? PUP_DQS_WR : PUP_DQS_RD);
319 adll_end_val = ((is_tx == 1) ? ADLL_MIN : ADLL_MAX);
320 adll_start_val = ((is_tx == 1) ? ADLL_MAX : ADLL_MIN);
321 max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
323 DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - Starting Find ADLL Limits\n");
326 for (pup = 0; pup < max_pup; pup++) {
327 centralization_low_limit[pup] = ADLL_MIN;
328 centralization_high_limit[pup] = ADLL_MAX;
333 for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
334 if (dram_info->cs_ena & (1 << cs_tmp))
337 sdram_offset = cs_count * (SDRAM_CS_SIZE + 1);
338 sdram_offset += ((is_tx == 1) ?
339 SDRAM_DQS_TX_OFFS : SDRAM_DQS_RX_OFFS);
341 /* Prepare pup masks */
342 for (pup = 0; pup < max_pup; pup++)
343 pup_mask |= (1 << pup);
345 for (pup = 0; pup < max_pup; pup++) {
346 for (dq = 0; dq < DQ_NUM; dq++) {
347 analog_pbs_sum[pup][dq][0] = adll_start_val;
348 analog_pbs_sum[pup][dq][1] = adll_end_val;
352 /* Loop - use different pattern for each victim_dq */
353 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
354 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Victim DQ - ",
357 * The pups 3 bit arrays represent state machine. with
358 * 3 stages for each pup.
359 * 1. fail and didn't get pass in earlier compares.
361 * 3. fail after pass - end state.
362 * The window limits are the adll values where the adll
363 * was in the pass stage.
366 /* Set all states to Fail (1st state) */
367 for (pup = 0; pup < max_pup; pup++)
368 pup_adll_limit_state[pup] = PUP_ADLL_LIMITS_STATE_FAIL;
370 /* Set current valid pups */
371 unlock_pup = pup_mask;
373 /* Set ADLL to start value */
374 curr_adll = adll_start_val;
376 #if defined(MV88F78X60)
377 for (pup = 0; pup < max_pup; pup++) {
378 for (dq = 0; dq < DQ_NUM; dq++) {
379 analog_pbs[victim_dq][pup][dq][0] =
381 analog_pbs[victim_dq][pup][dq][1] =
383 per_bit_data[pup][dq] = 0;
388 for (uj = 0; uj < ADLL_MAX; uj++) {
389 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Setting ADLL to ",
391 for (pup = 0; pup < max_pup; pup++) {
392 if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
393 tmp = ((is_tx == 1) ? curr_adll +
394 dram_info->wl_val[cs]
395 [pup * (1 - ecc) + ecc * ECC_PUP]
397 ddr3_write_pup_reg(adll_addr, cs, pup +
398 (ecc * ECC_PUP), 0, tmp);
403 pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
406 /* '1' - means pup failed, '0' - means pup pass */
409 /* Read and compare results for Victim_DQ# */
410 for (ii = 0; ii < 3; ii++) {
412 if (MV_OK != ddr3_sdram_dqs_compare(dram_info,
421 return MV_DDR3_TRAINING_ERR_DRAM_COMPARE;
423 new_unlock_pup |= tmp;
427 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - UnlockPup: ",
429 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - NewUnlockPup: ",
432 /* Update pup state */
433 for (pup = 0; pup < max_pup; pup++) {
434 if (IS_PUP_ACTIVE(unlock_pup, pup) == 0) {
435 DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Skipping pup ",
441 * Still didn't find the window limit of the pup
443 if (IS_PUP_ACTIVE(new_unlock_pup, pup) == 1) {
444 /* Current compare result == fail */
445 if (pup_adll_limit_state[pup] ==
446 PUP_ADLL_LIMITS_STATE_PASS) {
448 * If now it failed but passed
451 DEBUG_DQS_S("DDR3 - DQS Find Limits - PASS to FAIL: CS - ");
453 DEBUG_DQS_S(", DQ - ");
454 DEBUG_DQS_D(victim_dq, 1);
455 DEBUG_DQS_S(", Pup - ");
457 DEBUG_DQS_S(", ADLL - ");
458 DEBUG_DQS_D(curr_adll, 2);
461 #if defined(MV88F78X60)
462 for (dq = 0; dq < DQ_NUM; dq++) {
463 if ((analog_pbs[victim_dq][pup][dq][0] != adll_start_val)
464 && (analog_pbs[victim_dq][pup]
465 [dq][1] == adll_end_val))
476 /* Keep min / max limit value */
478 /* RX - found upper limit */
479 if (centralization_high_limit[pup] >
484 centralization_low_limit[pup];
488 /* TX - found lower limit */
489 if (centralization_low_limit[pup] < (curr_adll + 1)) {
491 centralization_high_limit
500 if (update_win == 1) {
503 * window limits we need
508 ddr3_check_window_limits
512 return MV_DDR3_TRAINING_ERR_WIN_LIMITS;
514 if (win_valid == 1) {
520 centralization_low_limit
523 centralization_high_limit
529 if (win_valid == 1) {
530 /* Found end of window - lock the pup */
531 pup_adll_limit_state[pup] =
532 PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS;
533 unlock_pup &= ~(1 << pup);
535 /* Probably false pass - reset status */
536 pup_adll_limit_state[pup] =
537 PUP_ADLL_LIMITS_STATE_FAIL;
539 #if defined(MV88F78X60)
540 /* Clear logging array of win size (per Dq) */
562 /* Current compare result == pass */
563 if (pup_adll_limit_state[pup] ==
564 PUP_ADLL_LIMITS_STATE_FAIL) {
565 /* If now it passed but failed earlier */
566 DEBUG_DQS_S("DDR3 - DQS Find Limits - FAIL to PASS: CS - ");
568 DEBUG_DQS_S(", DQ - ");
569 DEBUG_DQS_D(victim_dq, 1);
570 DEBUG_DQS_S(", Pup - ");
572 DEBUG_DQS_S(", ADLL - ");
573 DEBUG_DQS_D(curr_adll, 2);
576 #if defined(MV88F78X60)
577 for (dq = 0; dq < DQ_NUM;
579 if (analog_pbs[victim_dq][pup][dq][0] == adll_start_val)
587 /* Found start of window */
588 pup_adll_limit_state[pup] =
589 PUP_ADLL_LIMITS_STATE_PASS;
591 /* Keep min / max limit value */
593 /* RX - found low limit */
594 if (centralization_low_limit[pup] <= curr_adll)
595 centralization_low_limit
599 /* TX - found high limit */
600 if (centralization_high_limit[pup] >= curr_adll)
601 centralization_high_limit
609 if (unlock_pup == 0) {
610 /* Found limit to all pups */
611 DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - found PUP limit\n");
616 * Increment / decrement (Move to right / left
617 * one phase - ADLL) dqs RX / TX delay (for all un
626 if (unlock_pup != 0) {
628 * Found pups that didn't reach to the end of the
631 DEBUG_DQS_C("DDR3 - DQS Find Limits - Pups that didn't reached end of the state machine: ",
634 for (pup = 0; pup < max_pup; pup++) {
635 if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
636 if (pup_adll_limit_state[pup] ==
637 PUP_ADLL_LIMITS_STATE_FAIL) {
638 /* ERROR - found fail for all window size */
639 DEBUG_DQS_S("DDR3 - DQS Find Limits - Got FAIL for the complete range on pup - ");
641 DEBUG_DQS_C(" victim DQ ",
644 /* For debug - set min limit to illegal limit */
645 centralization_low_limit[pup]
648 * In case the pup is in mode
649 * PASS - the limit is the min
650 * / max adll, no need to
651 * update because of the results
652 * array default value
654 return MV_DDR3_TRAINING_ERR_PUP_RANGE;
661 DEBUG_DQS_S("DDR3 - DQS Find Limits - DQ values per victim results:\n");
662 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
663 for (pup = 0; pup < max_pup; pup++) {
664 DEBUG_DQS_S("Victim DQ-");
665 DEBUG_DQS_D(victim_dq, 1);
666 DEBUG_DQS_S(", PUP-");
668 for (dq = 0; dq < DQ_NUM; dq++) {
669 DEBUG_DQS_S(", DQ-");
672 DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
675 DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
679 if (analog_pbs[victim_dq][pup][dq][0]
680 > analog_pbs_sum[pup][dq][0])
681 analog_pbs_sum[pup][dq][0] =
682 analog_pbs[victim_dq][pup]
684 if (analog_pbs[victim_dq][pup][dq][1]
685 < analog_pbs_sum[pup][dq][1])
686 analog_pbs_sum[pup][dq][1] =
687 analog_pbs[victim_dq][pup]
690 if (analog_pbs[victim_dq][pup][dq][0]
691 < analog_pbs_sum[pup][dq][0])
692 analog_pbs_sum[pup][dq][0] =
693 analog_pbs[victim_dq][pup]
695 if (analog_pbs[victim_dq][pup][dq][1]
696 > analog_pbs_sum[pup][dq][1])
697 analog_pbs_sum[pup][dq][1] =
698 analog_pbs[victim_dq][pup]
706 if (ddr3_get_log_level() >= MV_LOG_LEVEL_3) {
709 DEBUG_PER_DQ_S("\n########## LOG LEVEL 3(Windows margins per-DQ) ##########\n");
711 DEBUG_PER_DQ_C("DDR3 - TX CS: ", cs, 1);
713 DEBUG_PER_DQ_C("DDR3 - RX CS: ", cs, 1);
717 DEBUG_PER_DQ_S("\n DATA RESULTS:\n");
719 DEBUG_PER_DQ_S("\n ECC RESULTS:\n");
722 /* Since all dq has the same value we take 0 as representive */
724 for (pup = 0; pup < max_pup; pup++) {
726 DEBUG_PER_DQ_S("\nBYTE:");
727 DEBUG_PER_DQ_D(pup, 1);
728 DEBUG_PER_DQ_S("\n");
730 DEBUG_PER_DQ_S("\nECC BYTE:\n");
732 DEBUG_PER_DQ_S(" DQ's LOW HIGH WIN-SIZE\n");
733 DEBUG_PER_DQ_S("============================================\n");
734 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
736 DEBUG_PER_DQ_S("DQ[");
737 DEBUG_PER_DQ_DD((victim_dq +
741 DEBUG_PER_DQ_S("CB[");
742 DEBUG_PER_DQ_DD(victim_dq, 2);
746 DEBUG_PER_DQ_S(" 0x");
747 DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1], 2); /* low value */
748 DEBUG_PER_DQ_S(" 0x");
749 DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2); /* high value */
750 DEBUG_PER_DQ_S(" 0x");
751 DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0] - analog_pbs[victim_dq][pup][dq][1], 2); /* win-size */
753 DEBUG_PER_DQ_S(" 0x");
754 DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2); /* low value */
755 DEBUG_PER_DQ_S(" 0x");
756 DEBUG_PER_DQ_D((analog_pbs[victim_dq][pup][dq][1] - 1), 2); /* high value */
757 DEBUG_PER_DQ_S(" 0x");
758 DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1] - analog_pbs[victim_dq][pup][dq][0], 2); /* win-size */
760 DEBUG_PER_DQ_S("\n");
763 DEBUG_PER_DQ_S("\n");
767 DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
769 DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
772 for (pup = 0; pup < max_pup; pup++) {
775 for (dq = 0; dq < DQ_NUM; dq++) {
776 DEBUG_DQS_S(", DQ-");
779 DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
781 DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
787 DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
789 DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
792 for (pup = 0; pup < max_pup; pup++) {
795 DEBUG_DQS_S("DDR3 - DQS8");
797 DEBUG_DQS_S("DDR3 - DQS");
801 for (dq = 0; dq < DQ_NUM; dq++) {
802 DEBUG_DQS_S(", DQ-");
805 DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
807 DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
812 DEBUG_DQS_S("DDR3 - DQS Find Limits - Ended\n");
818 * Name: ddr3_check_window_limits
819 * Desc: Check window High & Low limits.
820 * Args: pup pup index
821 * high_limit window high limit
822 * low_limit window low limit
823 * is_tx Indicate whether Rx or Tx
824 * size_valid Indicate whether window size is valid
826 * Returns: MV_OK if success, other error code if fail.
828 int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
831 DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Starting\n");
833 if (low_limit > high_limit) {
834 DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
836 DEBUG_DQS_S(" Low Limit grater than High Limit\n");
842 * Check that window size is valid, if not it was probably false pass
845 if ((high_limit - low_limit) < MIN_WIN_SIZE) {
847 * Since window size is too small probably there was false
852 DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
854 DEBUG_DQS_S(" Window size is smaller than MIN_WIN_SIZE\n");
856 } else if ((high_limit - low_limit) > ADLL_MAX) {
859 DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
862 (" Window size is bigger than max ADLL taps (31) Exiting.\n");
869 DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Pup ");
870 DEBUG_DQS_FULL_D(pup, 1);
871 DEBUG_DQS_FULL_C(" window size is ", (high_limit - low_limit),
879 * Name: ddr3_center_calc
880 * Desc: Execute the calculate the center of windows phase.
882 * is_tx Indicate whether Rx or Tx
884 * Returns: MV_OK if success, other error code if fail.
886 static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
889 /* bit array of pups that need specail search */
890 u32 special_pattern_i_pup = 0;
891 u32 special_pattern_ii_pup = 0;
895 max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
897 for (pup = 0; pup < max_pup; pup++) {
899 /* Check special pattern I */
901 * Special pattern Low limit search - relevant only
902 * for Rx, win size < threshold and low limit = 0
904 if (((centralization_high_limit[pup] -
905 centralization_low_limit[pup]) < VALID_WIN_THRS)
906 && (centralization_low_limit[pup] == MIN_DELAY))
907 special_pattern_i_pup |= (1 << pup);
909 /* Check special pattern II */
911 * Special pattern High limit search - relevant only
912 * for Rx, win size < threshold and high limit = 31
914 if (((centralization_high_limit[pup] -
915 centralization_low_limit[pup]) < VALID_WIN_THRS)
916 && (centralization_high_limit[pup] == MAX_DELAY))
917 special_pattern_ii_pup |= (1 << pup);
921 /* Run special pattern Low limit search - for relevant pup */
922 if (special_pattern_i_pup != 0) {
923 DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern I for Low limit search\n");
925 ddr3_special_pattern_i_search(dram_info, cs, ecc, is_tx,
926 special_pattern_i_pup))
927 return MV_DDR3_TRAINING_ERR_DQS_LOW_LIMIT_SEARCH;
930 /* Run special pattern High limit search - for relevant pup */
931 if (special_pattern_ii_pup != 0) {
932 DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern II for High limit search\n");
934 ddr3_special_pattern_ii_search(dram_info, cs, ecc, is_tx,
935 special_pattern_ii_pup))
936 return MV_DDR3_TRAINING_ERR_DQS_HIGH_LIMIT_SEARCH;
939 /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
940 return ddr3_set_dqs_centralization_results(dram_info, cs, ecc, is_tx);
944 * Name: ddr3_special_pattern_i_search
945 * Desc: Execute special pattern low limit search.
947 * special_pattern_pup The pups that need the special search
949 * Returns: MV_OK if success, other error code if fail.
951 int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
952 int is_tx, u32 special_pattern_pup)
954 u32 victim_dq; /* loop index - victim DQ */
957 u32 unlock_pup; /* bit array of the unlock pups */
958 u32 first_fail; /* bit array - of pups that get first fail */
959 u32 new_lockup_pup; /* bit array of compare failed pups */
960 u32 pass_pup; /* bit array of compare pass pup */
964 u32 special_res[MAX_PUP_NUM]; /* hold tmp results */
966 DEBUG_DQS_S("DDR3 - DQS - Special Pattern I Search - Starting\n");
968 max_pup = ecc + (1 - ecc) * dram_info->num_of_std_pups;
970 /* Init the temporary results to max ADLL value */
971 for (pup = 0; pup < max_pup; pup++)
972 special_res[pup] = ADLL_MAX;
974 /* Run special pattern for all DQ - use the same pattern */
975 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
976 unlock_pup = special_pattern_pup;
979 sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS +
980 LEN_KILLER_PATTERN * 4 * victim_dq;
982 for (pup = 0; pup < max_pup; pup++) {
983 /* Set adll value per PUP. adll = high limit per pup */
984 if (IS_PUP_ACTIVE(unlock_pup, pup)) {
985 /* only for pups that need special search */
986 ddr3_write_pup_reg(PUP_DQS_RD, cs,
987 pup + (ecc * ECC_PUP), 0,
988 centralization_high_limit
996 * Perform read and compare simultaneously for all
997 * un-locked MC use the special pattern mask
1002 ddr3_sdram_dqs_compare(dram_info, unlock_pup,
1006 LEN_SPECIAL_PATTERN,
1011 DEBUG_DQS_S("DDR3 - DQS - Special I - ADLL value is: ");
1012 DEBUG_DQS_D(adll_idx, 2);
1013 DEBUG_DQS_S(", UnlockPup: ");
1014 DEBUG_DQS_D(unlock_pup, 2);
1015 DEBUG_DQS_S(", NewLockPup: ");
1016 DEBUG_DQS_D(new_lockup_pup, 2);
1019 if (unlock_pup != new_lockup_pup)
1020 DEBUG_DQS_S("DDR3 - DQS - Special I - Some Pup passed!\n");
1022 /* Search for pups with passed compare & already fail */
1023 pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
1024 first_fail |= new_lockup_pup;
1025 unlock_pup &= ~pass_pup;
1028 if (pass_pup != 0) {
1029 for (pup = 0; pup < max_pup; pup++) {
1030 if (IS_PUP_ACTIVE(pass_pup, pup) ==
1032 /* If pup passed and has first fail = 1 */
1033 /* keep min value of ADLL max value - current adll */
1034 /* (centralization_high_limit[pup] + adll_idx) = current adll !!! */
1037 (centralization_high_limit
1041 ("DDR3 - DQS - Special I - Pup - ",
1051 centralization_low_limit
1057 ("DDR3 - DQS - Special I - Pup - ",
1060 (" Changed Low limit to ",
1061 centralization_low_limit
1069 * Did all PUP found missing window?
1070 * Check for each pup if adll (different for each pup)
1071 * reach maximum if reach max value - lock the pup
1072 * if not - increment (Move to right one phase - ADLL)
1076 for (pup = 0; pup < max_pup; pup++) {
1077 if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
1078 /* Check only unlocked pups */
1079 if ((centralization_high_limit[pup] +
1080 adll_idx) >= ADLL_MAX) {
1081 /* reach maximum - lock the pup */
1082 DEBUG_DQS_C("DDR3 - DQS - Special I - reach maximum - lock pup ",
1084 unlock_pup &= ~(1 << pup);
1086 /* Didn't reach maximum - increment ADLL */
1087 ddr3_write_pup_reg(PUP_DQS_RD,
1092 (centralization_high_limit
1098 } while (unlock_pup != 0);
1105 * Name: ddr3_special_pattern_ii_search
1106 * Desc: Execute special pattern high limit search.
1108 * special_pattern_pup The pups that need the special search
1110 * Returns: MV_OK if success, other error code if fail.
1112 int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
1113 int is_tx, u32 special_pattern_pup)
1115 u32 victim_dq; /* loop index - victim DQ */
1118 u32 unlock_pup; /* bit array of the unlock pups */
1119 u32 first_fail; /* bit array - of pups that get first fail */
1120 u32 new_lockup_pup; /* bit array of compare failed pups */
1121 u32 pass_pup; /* bit array of compare pass pup */
1125 u32 special_res[MAX_PUP_NUM]; /* hold tmp results */
1127 DEBUG_DQS_S("DDR3 - DQS - Special Pattern II Search - Starting\n");
1129 max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
1131 /* init the tmporary results to max ADLL value */
1132 for (pup = 0; pup < max_pup; pup++)
1133 special_res[pup] = ADLL_MAX;
1135 sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS;
1137 /* run special pattern for all DQ - use the same pattern */
1138 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1139 unlock_pup = special_pattern_pup;
1142 for (pup = 0; pup < max_pup; pup++) {
1143 /* Set adll value per PUP. adll = 0 */
1144 if (IS_PUP_ACTIVE(unlock_pup, pup)) {
1145 /* Only for pups that need special search */
1146 ddr3_write_pup_reg(PUP_DQS_RD, cs,
1147 pup + (ecc * ECC_PUP), 0,
1155 * Perform read and compare simultaneously for all
1156 * un-locked MC use the special pattern mask
1160 if (MV_OK != ddr3_sdram_dqs_compare(
1161 dram_info, unlock_pup, &new_lockup_pup,
1162 special_pattern[victim_dq],
1163 LEN_SPECIAL_PATTERN,
1164 sdram_offset, 0, 0, NULL, 0))
1167 DEBUG_DQS_S("DDR3 - DQS - Special II - ADLL value is ");
1168 DEBUG_DQS_D(adll_idx, 2);
1169 DEBUG_DQS_S("unlock_pup ");
1170 DEBUG_DQS_D(unlock_pup, 1);
1171 DEBUG_DQS_S("new_lockup_pup ");
1172 DEBUG_DQS_D(new_lockup_pup, 1);
1175 if (unlock_pup != new_lockup_pup) {
1176 DEBUG_DQS_S("DDR3 - DQS - Special II - Some Pup passed!\n");
1179 /* Search for pups with passed compare & already fail */
1180 pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
1181 first_fail |= new_lockup_pup;
1182 unlock_pup &= ~pass_pup;
1185 if (pass_pup != 0) {
1186 for (pup = 0; pup < max_pup; pup++) {
1187 if (IS_PUP_ACTIVE(pass_pup, pup) ==
1189 /* If pup passed and has first fail = 1 */
1190 /* keep min value of ADLL max value - current adll */
1191 /* (adll_idx) = current adll !!! */
1192 comp_val = adll_idx;
1194 DEBUG_DQS_C("DDR3 - DQS - Special II - Pup - ",
1196 DEBUG_DQS_C(" comp_val = ",
1203 centralization_high_limit
1209 ("DDR3 - DQS - Special II - Pup - ",
1212 (" Changed High limit to ",
1213 centralization_high_limit
1221 * Did all PUP found missing window?
1222 * Check for each pup if adll (different for each pup)
1223 * reach maximum if reach max value - lock the pup
1224 * if not - increment (Move to right one phase - ADLL)
1228 for (pup = 0; pup < max_pup; pup++) {
1229 if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
1230 /* Check only unlocked pups */
1231 if ((adll_idx) >= ADLL_MAX) {
1232 /* Reach maximum - lock the pup */
1233 DEBUG_DQS_C("DDR3 - DQS - Special II - reach maximum - lock pup ",
1235 unlock_pup &= ~(1 << pup);
1237 /* Didn't reach maximum - increment ADLL */
1238 ddr3_write_pup_reg(PUP_DQS_RD,
1247 } while (unlock_pup != 0);
1254 * Name: ddr3_set_dqs_centralization_results
1255 * Desc: Set to HW the DQS centralization phase results.
1257 * is_tx Indicates whether to set Tx or RX results
1259 * Returns: MV_OK if success, other error code if fail.
1261 int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs,
1268 max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
1270 DEBUG_DQS_RESULTS_S("\n############ LOG LEVEL 2(Windows margins) ############\n");
1273 DEBUG_DQS_RESULTS_C("DDR3 - DQS TX - Set Dqs Centralization Results - CS: ",
1276 DEBUG_DQS_RESULTS_C("DDR3 - DQS RX - Set Dqs Centralization Results - CS: ",
1280 /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
1281 DEBUG_DQS_RESULTS_S("\nDQS LOW HIGH WIN-SIZE Set\n");
1282 DEBUG_DQS_RESULTS_S("==============================================\n");
1283 for (pup = 0; pup < max_pup; pup++) {
1284 addl_val = (centralization_high_limit[pup] +
1285 centralization_low_limit[pup]) / 2;
1287 pup_num = pup * (1 - ecc) + ecc * ECC_PUP;
1289 DEBUG_DQS_RESULTS_D(pup_num, 1);
1290 DEBUG_DQS_RESULTS_S(" 0x");
1291 DEBUG_DQS_RESULTS_D(centralization_low_limit[pup], 2);
1292 DEBUG_DQS_RESULTS_S(" 0x");
1293 DEBUG_DQS_RESULTS_D(centralization_high_limit[pup], 2);
1294 DEBUG_DQS_RESULTS_S(" 0x");
1295 DEBUG_DQS_RESULTS_D(centralization_high_limit[pup] -
1296 centralization_low_limit[pup], 2);
1297 DEBUG_DQS_RESULTS_S(" 0x");
1298 DEBUG_DQS_RESULTS_D(addl_val, 2);
1299 DEBUG_DQS_RESULTS_S("\n");
1301 if (addl_val < ADLL_MIN) {
1302 addl_val = ADLL_MIN;
1303 DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MIN (since it was lower than 0)\n");
1306 if (addl_val > ADLL_MAX) {
1307 addl_val = ADLL_MAX;
1308 DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MAX (since it was higher than 31)\n");
1312 ddr3_write_pup_reg(PUP_DQS_WR, cs, pup_num, 0,
1314 dram_info->wl_val[cs][pup_num][D]);
1316 ddr3_write_pup_reg(PUP_DQS_RD, cs, pup_num, 0,
1325 * Set training patterns
1327 int ddr3_load_dqs_patterns(MV_DRAM_INFO *dram_info)
1329 u32 cs, cs_count, cs_tmp, victim_dq;
1333 /* Loop for each CS */
1334 for (cs = 0; cs < MAX_CS; cs++) {
1335 if (dram_info->cs_ena & (1 << cs)) {
1337 for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
1338 if (dram_info->cs_ena & (1 << cs_tmp))
1342 /* Init killer pattern */
1343 sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
1345 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1346 pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
1348 if (MV_OK != ddr3_sdram_dqs_compare(
1349 dram_info, (u32)NULL, NULL,
1350 pattern_ptr, LEN_KILLER_PATTERN,
1351 sdram_addr + LEN_KILLER_PATTERN *
1352 4 * victim_dq, 1, 0, NULL,
1354 return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
1357 /* Init special-killer pattern */
1358 sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
1359 SDRAM_DQS_RX_SPECIAL_OFFS);
1360 for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1361 if (MV_OK != ddr3_sdram_dqs_compare(
1362 dram_info, (u32)NULL, NULL,
1363 special_pattern[victim_dq],
1364 LEN_KILLER_PATTERN, sdram_addr +
1365 LEN_KILLER_PATTERN * 4 * victim_dq,
1367 return MV_DDR3_TRAINING_ERR_DQS_PATTERN;