diff options
Diffstat (limited to 'drivers/ddr/mvebu/ddr3_pbs.c')
-rw-r--r-- | drivers/ddr/mvebu/ddr3_pbs.c | 1592 |
1 files changed, 0 insertions, 1592 deletions
diff --git a/drivers/ddr/mvebu/ddr3_pbs.c b/drivers/ddr/mvebu/ddr3_pbs.c deleted file mode 100644 index 00ea3fdb912..00000000000 --- a/drivers/ddr/mvebu/ddr3_pbs.c +++ /dev/null @@ -1,1592 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include <common.h> -#include <i2c.h> -#include <spl.h> -#include <asm/io.h> -#include <asm/arch/cpu.h> -#include <asm/arch/soc.h> - -#include "ddr3_hw_training.h" - -/* - * Debug - */ -#define DEBUG_PBS_FULL_C(s, d, l) \ - DEBUG_PBS_FULL_S(s); DEBUG_PBS_FULL_D(d, l); DEBUG_PBS_FULL_S("\n") -#define DEBUG_PBS_C(s, d, l) \ - DEBUG_PBS_S(s); DEBUG_PBS_D(d, l); DEBUG_PBS_S("\n") - -#ifdef MV_DEBUG_PBS -#define DEBUG_PBS_S(s) puts(s) -#define DEBUG_PBS_D(d, l) printf("%x", d) -#else -#define DEBUG_PBS_S(s) -#define DEBUG_PBS_D(d, l) -#endif - -#ifdef MV_DEBUG_FULL_PBS -#define DEBUG_PBS_FULL_S(s) puts(s) -#define DEBUG_PBS_FULL_D(d, l) printf("%x", d) -#else -#define DEBUG_PBS_FULL_S(s) -#define DEBUG_PBS_FULL_D(d, l) -#endif - -#if defined(MV88F78X60) || defined(MV88F672X) - -/* Temp array for skew data storage */ -static u32 skew_array[(MAX_PUP_NUM) * DQ_NUM] = { 0 }; - -/* PBS locked dq (per pup) */ -extern u32 pbs_locked_dq[MAX_PUP_NUM][DQ_NUM]; -extern u32 pbs_locked_dm[MAX_PUP_NUM]; -extern u32 pbs_locked_value[MAX_PUP_NUM][DQ_NUM]; - -#if defined(MV88F672X) -extern u32 pbs_pattern[2][LEN_16BIT_PBS_PATTERN]; -extern u32 pbs_pattern_32b[2][LEN_PBS_PATTERN]; -#else -extern u32 pbs_pattern_32b[2][LEN_PBS_PATTERN]; -extern u32 pbs_pattern_64b[2][LEN_PBS_PATTERN]; -#endif - -extern u32 pbs_dq_mapping[PUP_NUM_64BIT + 1][DQ_NUM]; - -static int ddr3_tx_shift_dqs_adll_step_before_fail(MV_DRAM_INFO *dram_info, - u32 cur_pup, u32 pbs_pattern_idx, u32 ecc); -static int ddr3_rx_shift_dqs_to_first_fail(MV_DRAM_INFO *dram_info, u32 cur_pup, - u32 pbs_pattern_idx, u32 ecc); -static int ddr3_pbs_per_bit(MV_DRAM_INFO *dram_info, int *start_over, int is_tx, - u32 *pcur_pup, u32 pbs_pattern_idx, u32 ecc); -static int ddr3_set_pbs_results(MV_DRAM_INFO *dram_info, int is_tx); -static void ddr3_pbs_write_pup_dqs_reg(u32 cs, u32 pup, u32 dqs_delay); - -/* - * Name: ddr3_pbs_tx - * Desc: Execute the PBS TX phase. - * Args: dram_info ddr3 training information struct - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_pbs_tx(MV_DRAM_INFO *dram_info) -{ - /* Array of Deskew results */ - - /* - * Array to hold the total sum of skew from all iterations - * (for average purpose) - */ - u32 skew_sum_array[MAX_PUP_NUM][DQ_NUM] = { {0} }; - - /* - * Array to hold the total average skew from both patterns - * (for average purpose) - */ - u32 pattern_skew_array[MAX_PUP_NUM][DQ_NUM] = { {0} }; - - u32 pbs_rep_time = 0; /* counts number of loop in case of fail */ - /* bit array for unlock pups - used to repeat on the RX operation */ - u32 cur_pup; - u32 max_pup; - u32 pbs_retry; - u32 pup, dq, pups, cur_max_pup, valid_pup, reg; - u32 pattern_idx; - u32 ecc; - /* indicates whether we need to start the loop again */ - int start_over; - - DEBUG_PBS_S("DDR3 - PBS TX - Starting PBS TX procedure\n"); - - pups = dram_info->num_of_total_pups; - max_pup = dram_info->num_of_total_pups; - - /* Enable SW override */ - reg = reg_read(REG_DRAM_TRAINING_2_ADDR) | - (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS); - /* [0] = 1 - Enable SW override */ - /* 0x15B8 - Training SW 2 Register */ - reg_write(REG_DRAM_TRAINING_2_ADDR, reg); - DEBUG_PBS_S("DDR3 - PBS RX - SW Override Enabled\n"); - - reg = 1 << REG_DRAM_TRAINING_AUTO_OFFS; - reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */ - - /* Running twice for 2 different patterns. each patterns - 3 times */ - for (pattern_idx = 0; pattern_idx < COUNT_PBS_PATTERN; pattern_idx++) { - DEBUG_PBS_C("DDR3 - PBS TX - Working with pattern - ", - pattern_idx, 1); - - /* Reset sum array */ - for (pup = 0; pup < pups; pup++) { - for (dq = 0; dq < DQ_NUM; dq++) - skew_sum_array[pup][dq] = 0; - } - - /* - * Perform PBS several of times (3 for each pattern). - * At the end, we'll use the average - */ - /* If there is ECC, do each PBS again with mux change */ - for (pbs_retry = 0; pbs_retry < COUNT_PBS_REPEAT; pbs_retry++) { - for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) { - - /* - * This parameter stores the current PUP - * num - ecc mode dependent - 4-8 / 1 pups - */ - cur_max_pup = (1 - ecc) * - dram_info->num_of_std_pups + ecc; - - if (ecc) { - /* Only 1 pup in this case */ - valid_pup = 0x1; - } else if (cur_max_pup > 4) { - /* 64 bit - 8 pups */ - valid_pup = 0xFF; - } else if (cur_max_pup == 4) { - /* 32 bit - 4 pups */ - valid_pup = 0xF; - } else { - /* 16 bit - 2 pups */ - valid_pup = 0x3; - } - - /* ECC Support - Switch ECC Mux on ecc=1 */ - reg = reg_read(REG_DRAM_TRAINING_2_ADDR) & - ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS); - reg |= (dram_info->ecc_ena * ecc << - REG_DRAM_TRAINING_2_ECC_MUX_OFFS); - reg_write(REG_DRAM_TRAINING_2_ADDR, reg); - - if (ecc) - DEBUG_PBS_S("DDR3 - PBS Tx - ECC Mux Enabled\n"); - else - DEBUG_PBS_S("DDR3 - PBS Tx - ECC Mux Disabled\n"); - - /* Init iteration values */ - /* Clear the locked DQs */ - for (pup = 0; pup < cur_max_pup; pup++) { - for (dq = 0; dq < DQ_NUM; dq++) { - pbs_locked_dq[ - pup + ecc * - (max_pup - 1)][dq] = - 0; - } - } - - pbs_rep_time = 0; - cur_pup = valid_pup; - start_over = 0; - - /* - * Run loop On current Pattern and current - * pattern iteration (just to cover the false - * fail problem) - */ - do { - DEBUG_PBS_S("DDR3 - PBS Tx - Pbs Rep Loop is "); - DEBUG_PBS_D(pbs_rep_time, 1); - DEBUG_PBS_S(", for Retry No."); - DEBUG_PBS_D(pbs_retry, 1); - DEBUG_PBS_S("\n"); - - /* Set all PBS values to MIN (0) */ - DEBUG_PBS_S("DDR3 - PBS Tx - Set all PBS values to MIN\n"); - - for (dq = 0; dq < DQ_NUM; dq++) { - ddr3_write_pup_reg( - PUP_PBS_TX + - pbs_dq_mapping[pup * - (1 - ecc) + - ecc * ECC_PUP] - [dq], CS0, (1 - ecc) * - PUP_BC + ecc * ECC_PUP, 0, - 0); - } - - /* - * Shift DQ ADLL right, One step before - * fail - */ - DEBUG_PBS_S("DDR3 - PBS Tx - ADLL shift right one phase before fail\n"); - - if (MV_OK != ddr3_tx_shift_dqs_adll_step_before_fail - (dram_info, cur_pup, pattern_idx, - ecc)) - return MV_DDR3_TRAINING_ERR_PBS_ADLL_SHR_1PHASE; - - /* PBS For each bit */ - DEBUG_PBS_S("DDR3 - PBS Tx - perform PBS for each bit\n"); - - /* - * In this stage - start_over = 0 - */ - if (MV_OK != ddr3_pbs_per_bit( - dram_info, &start_over, 1, - &cur_pup, pattern_idx, ecc)) - return MV_DDR3_TRAINING_ERR_PBS_TX_PER_BIT; - - } while ((start_over == 1) && - (++pbs_rep_time < COUNT_PBS_STARTOVER)); - - if (pbs_rep_time == COUNT_PBS_STARTOVER && - start_over == 1) { - DEBUG_PBS_S("DDR3 - PBS Tx - FAIL - Adll reach max value\n"); - return MV_DDR3_TRAINING_ERR_PBS_TX_MAX_VAL; - } - - DEBUG_PBS_FULL_C("DDR3 - PBS TX - values for iteration - ", - pbs_retry, 1); - for (pup = 0; pup < cur_max_pup; pup++) { - /* - * To minimize delay elements, inc - * from pbs value the min pbs val - */ - DEBUG_PBS_S("DDR3 - PBS - PUP"); - DEBUG_PBS_D((pup + (ecc * ECC_PUP)), 1); - DEBUG_PBS_S(": "); - - for (dq = 0; dq < DQ_NUM; dq++) { - /* Set skew value for all dq */ - /* - * Bit# Deskew <- Bit# Deskew - - * last / first failing bit - * Deskew For all bits (per PUP) - * (minimize delay elements) - */ - DEBUG_PBS_S("DQ"); - DEBUG_PBS_D(dq, 1); - DEBUG_PBS_S("-"); - DEBUG_PBS_D(skew_array - [((pup) * DQ_NUM) + - dq], 2); - DEBUG_PBS_S(", "); - } - DEBUG_PBS_S("\n"); - } - - /* - * Collect the results we got on this trial - * of PBS - */ - for (pup = 0; pup < cur_max_pup; pup++) { - for (dq = 0; dq < DQ_NUM; dq++) { - skew_sum_array[pup + (ecc * (max_pup - 1))] - [dq] += skew_array - [((pup) * DQ_NUM) + dq]; - } - } - - /* ECC Support - Disable ECC MUX */ - reg = reg_read(REG_DRAM_TRAINING_2_ADDR) & - ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS); - reg_write(REG_DRAM_TRAINING_2_ADDR, reg); - } - } - - DEBUG_PBS_C("DDR3 - PBS TX - values for current pattern - ", - pattern_idx, 1); - for (pup = 0; pup < max_pup; pup++) { - /* - * To minimize delay elements, inc from pbs value the - * min pbs val - */ - DEBUG_PBS_S("DDR3 - PBS - PUP"); - DEBUG_PBS_D(pup, 1); - DEBUG_PBS_S(": "); - - for (dq = 0; dq < DQ_NUM; dq++) { - /* set skew value for all dq */ - /* Bit# Deskew <- Bit# Deskew - last / first failing bit Deskew For all bits (per PUP) (minimize delay elements) */ - DEBUG_PBS_S("DQ"); - DEBUG_PBS_D(dq, 1); - DEBUG_PBS_S("-"); - DEBUG_PBS_D(skew_sum_array[pup][dq] / - COUNT_PBS_REPEAT, 2); - DEBUG_PBS_S(", "); - } - DEBUG_PBS_S("\n"); - } - - /* - * Calculate the average skew for current pattern for each - * pup and each bit - */ - DEBUG_PBS_C("DDR3 - PBS TX - Average for pattern - ", - pattern_idx, 1); - - for (pup = 0; pup < max_pup; pup++) { - /* - * FOR ECC only :: found min and max value for current - * pattern skew array - */ - /* Loop for all dqs */ - for (dq = 0; dq < DQ_NUM; dq++) { - pattern_skew_array[pup][dq] += - (skew_sum_array[pup][dq] / - COUNT_PBS_REPEAT); - } - } - } - - /* Calculate the average skew */ - for (pup = 0; pup < max_pup; pup++) { - for (dq = 0; dq < DQ_NUM; dq++) - skew_array[((pup) * DQ_NUM) + dq] = - pattern_skew_array[pup][dq] / COUNT_PBS_PATTERN; - } - - DEBUG_PBS_S("DDR3 - PBS TX - Average for all patterns:\n"); - for (pup = 0; pup < max_pup; pup++) { - /* - * To minimize delay elements, inc from pbs value the min - * pbs val - */ - DEBUG_PBS_S("DDR3 - PBS - PUP"); - DEBUG_PBS_D(pup, 1); - DEBUG_PBS_S(": "); - - for (dq = 0; dq < DQ_NUM; dq++) { - /* Set skew value for all dq */ - /* - * Bit# Deskew <- Bit# Deskew - last / first - * failing bit Deskew For all bits (per PUP) - * (minimize delay elements) - */ - DEBUG_PBS_S("DQ"); - DEBUG_PBS_D(dq, 1); - DEBUG_PBS_S("-"); - DEBUG_PBS_D(skew_array[(pup * DQ_NUM) + dq], 2); - DEBUG_PBS_S(", "); - } - DEBUG_PBS_S("\n"); - } - - /* Return ADLL to default value */ - for (pup = 0; pup < max_pup; pup++) { - if (pup == (max_pup - 1) && dram_info->ecc_ena) - pup = ECC_PUP; - ddr3_pbs_write_pup_dqs_reg(CS0, pup, INIT_WL_DELAY); - } - - /* Set averaged PBS results */ - ddr3_set_pbs_results(dram_info, 1); - - /* Disable SW override - Must be in a different stage */ - /* [0]=0 - Enable SW override */ - reg = reg_read(REG_DRAM_TRAINING_2_ADDR); - reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS); - /* 0x15B8 - Training SW 2 Register */ - reg_write(REG_DRAM_TRAINING_2_ADDR, reg); - - reg = reg_read(REG_DRAM_TRAINING_1_ADDR) | - (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS); - reg_write(REG_DRAM_TRAINING_1_ADDR, reg); - - DEBUG_PBS_S("DDR3 - PBS Tx - PBS TX ended successfuly\n"); - - return MV_OK; -} - -/* - * Name: ddr3_tx_shift_dqs_adll_step_before_fail - * Desc: Execute the Tx shift DQ phase. - * Args: dram_info ddr3 training information struct - * cur_pup bit array of the function active pups. - * pbs_pattern_idx Index of PBS pattern - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -static int ddr3_tx_shift_dqs_adll_step_before_fail(MV_DRAM_INFO *dram_info, - u32 cur_pup, - u32 pbs_pattern_idx, u32 ecc) -{ - u32 unlock_pup; /* bit array of unlock pups */ - u32 new_lockup_pup; /* bit array of compare failed pups */ - u32 adll_val = 4; /* INIT_WL_DELAY */ - u32 cur_max_pup, pup; - u32 dqs_dly_set[MAX_PUP_NUM] = { 0 }; - u32 *pattern_ptr; - - /* Choose pattern */ - switch (dram_info->ddr_width) { -#if defined(MV88F672X) - case 16: - pattern_ptr = (u32 *)&pbs_pattern[pbs_pattern_idx]; - break; -#endif - case 32: - pattern_ptr = (u32 *)&pbs_pattern_32b[pbs_pattern_idx]; - break; -#if defined(MV88F78X60) - case 64: - pattern_ptr = (u32 *)&pbs_pattern_64b[pbs_pattern_idx]; - break; -#endif - default: - return MV_FAIL; - } - - /* Set current pup number */ - if (cur_pup == 0x1) /* Ecc mode */ - cur_max_pup = 1; - else - cur_max_pup = dram_info->num_of_std_pups; - - unlock_pup = cur_pup; /* '1' for each unlocked pup */ - - /* Loop on all ADLL Vaules */ - do { - /* Loop until found first fail */ - adll_val++; - - /* - * Increment (Move to right - ADLL) DQ TX delay - * (broadcast to all Data PUPs) - */ - for (pup = 0; pup < cur_max_pup; pup++) - ddr3_pbs_write_pup_dqs_reg(CS0, - pup * (1 - ecc) + - ECC_PUP * ecc, adll_val); - - /* - * Write and Read, compare results (read was already verified) - */ - /* 0 - all locked */ - new_lockup_pup = 0; - - if (MV_OK != ddr3_sdram_compare(dram_info, unlock_pup, - &new_lockup_pup, - pattern_ptr, LEN_PBS_PATTERN, - SDRAM_PBS_TX_OFFS, 1, 0, - NULL, - 0)) - return MV_FAIL; - - unlock_pup &= ~new_lockup_pup; - - DEBUG_PBS_FULL_S("Shift DQS by 2 steps for PUPs: "); - DEBUG_PBS_FULL_D(unlock_pup, 2); - DEBUG_PBS_FULL_C(", Set ADLL value = ", adll_val, 2); - - /* If any PUP failed there is '1' to mark the PUP */ - if (new_lockup_pup != 0) { - /* - * Decrement (Move Back to Left two steps - ADLL) - * DQ TX delay for current failed pups and save - */ - for (pup = 0; pup < cur_max_pup; pup++) { - if (((new_lockup_pup >> pup) & 0x1) && - dqs_dly_set[pup] == 0) - dqs_dly_set[pup] = adll_val - 1; - } - } - } while ((unlock_pup != 0) && (adll_val != ADLL_MAX)); - - if (unlock_pup != 0) { - DEBUG_PBS_FULL_S("DDR3 - PBS Tx - Shift DQ - Adll value reached maximum\n"); - - for (pup = 0; pup < cur_max_pup; pup++) { - if (((unlock_pup >> pup) & 0x1) && - dqs_dly_set[pup] == 0) - dqs_dly_set[pup] = adll_val - 1; - } - } - - DEBUG_PBS_FULL_C("PBS TX one step before fail last pups locked Adll ", - adll_val - 2, 2); - - /* Set the PUP DQS DLY Values */ - for (pup = 0; pup < cur_max_pup; pup++) - ddr3_pbs_write_pup_dqs_reg(CS0, pup * (1 - ecc) + ECC_PUP * ecc, - dqs_dly_set[pup]); - - /* Found one phase before fail */ - return MV_OK; -} - -/* - * Name: ddr3_pbs_rx - * Desc: Execute the PBS RX phase. - * Args: dram_info ddr3 training information struct - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_pbs_rx(MV_DRAM_INFO *dram_info) -{ - /* - * Array to hold the total sum of skew from all iterations - * (for average purpose) - */ - u32 skew_sum_array[MAX_PUP_NUM][DQ_NUM] = { {0} }; - - /* - * Array to hold the total average skew from both patterns - * (for average purpose) - */ - u32 pattern_skew_array[MAX_PUP_NUM][DQ_NUM] = { {0} }; - - u32 pbs_rep_time = 0; /* counts number of loop in case of fail */ - /* bit array for unlock pups - used to repeat on the RX operation */ - u32 cur_pup; - u32 max_pup; - u32 pbs_retry; - u32 pup, dq, pups, cur_max_pup, valid_pup, reg; - u32 pattern_idx; - u32 ecc; - /* indicates whether we need to start the loop again */ - int start_over; - int status; - - DEBUG_PBS_S("DDR3 - PBS RX - Starting PBS RX procedure\n"); - - pups = dram_info->num_of_total_pups; - max_pup = dram_info->num_of_total_pups; - - /* Enable SW override */ - reg = reg_read(REG_DRAM_TRAINING_2_ADDR) | - (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS); - /* [0] = 1 - Enable SW override */ - /* 0x15B8 - Training SW 2 Register */ - reg_write(REG_DRAM_TRAINING_2_ADDR, reg); - DEBUG_PBS_FULL_S("DDR3 - PBS RX - SW Override Enabled\n"); - - reg = 1 << REG_DRAM_TRAINING_AUTO_OFFS; - reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */ - - /* Running twice for 2 different patterns. each patterns - 3 times */ - for (pattern_idx = 0; pattern_idx < COUNT_PBS_PATTERN; pattern_idx++) { - DEBUG_PBS_FULL_C("DDR3 - PBS RX - Working with pattern - ", - pattern_idx, 1); - - /* Reset sum array */ - for (pup = 0; pup < pups; pup++) { - for (dq = 0; dq < DQ_NUM; dq++) - skew_sum_array[pup][dq] = 0; - } - - /* - * Perform PBS several of times (3 for each pattern). - * At the end, we'll use the average - */ - /* If there is ECC, do each PBS again with mux change */ - for (pbs_retry = 0; pbs_retry < COUNT_PBS_REPEAT; pbs_retry++) { - for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) { - /* - * This parameter stores the current PUP - * num - ecc mode dependent - 4-8 / 1 pups - */ - cur_max_pup = (1 - ecc) * - dram_info->num_of_std_pups + ecc; - - if (ecc) { - /* Only 1 pup in this case */ - valid_pup = 0x1; - } else if (cur_max_pup > 4) { - /* 64 bit - 8 pups */ - valid_pup = 0xFF; - } else if (cur_max_pup == 4) { - /* 32 bit - 4 pups */ - valid_pup = 0xF; - } else { - /* 16 bit - 2 pups */ - valid_pup = 0x3; - } - - /* ECC Support - Switch ECC Mux on ecc=1 */ - reg = reg_read(REG_DRAM_TRAINING_2_ADDR) & - ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS); - reg |= (dram_info->ecc_ena * ecc << - REG_DRAM_TRAINING_2_ECC_MUX_OFFS); - reg_write(REG_DRAM_TRAINING_2_ADDR, reg); - - if (ecc) - DEBUG_PBS_FULL_S("DDR3 - PBS Rx - ECC Mux Enabled\n"); - else - DEBUG_PBS_FULL_S("DDR3 - PBS Rx - ECC Mux Disabled\n"); - - /* Init iteration values */ - /* Clear the locked DQs */ - for (pup = 0; pup < cur_max_pup; pup++) { - for (dq = 0; dq < DQ_NUM; dq++) { - pbs_locked_dq[ - pup + ecc * (max_pup - 1)][dq] = - 0; - } - } - - pbs_rep_time = 0; - cur_pup = valid_pup; - start_over = 0; - - /* - * Run loop On current Pattern and current - * pattern iteration (just to cover the false - * fail problem - */ - do { - DEBUG_PBS_FULL_S("DDR3 - PBS Rx - Pbs Rep Loop is "); - DEBUG_PBS_FULL_D(pbs_rep_time, 1); - DEBUG_PBS_FULL_S(", for Retry No."); - DEBUG_PBS_FULL_D(pbs_retry, 1); - DEBUG_PBS_FULL_S("\n"); - - /* Set all PBS values to MAX (31) */ - for (pup = 0; pup < cur_max_pup; pup++) { - for (dq = 0; dq < DQ_NUM; dq++) - ddr3_write_pup_reg( - PUP_PBS_RX + - pbs_dq_mapping[ - pup * (1 - ecc) - + ecc * ECC_PUP] - [dq], CS0, - pup + ecc * ECC_PUP, - 0, MAX_PBS); - } - - /* Set all DQS PBS values to MIN (0) */ - for (pup = 0; pup < cur_max_pup; pup++) { - ddr3_write_pup_reg(PUP_PBS_RX + - DQ_NUM, CS0, - pup + - ecc * - ECC_PUP, 0, - 0); - } - - /* Shift DQS, To first Fail */ - DEBUG_PBS_FULL_S("DDR3 - PBS Rx - Shift RX DQS to first fail\n"); - - status = ddr3_rx_shift_dqs_to_first_fail - (dram_info, cur_pup, - pattern_idx, ecc); - if (MV_OK != status) { - DEBUG_PBS_S("DDR3 - PBS Rx - ddr3_rx_shift_dqs_to_first_fail failed.\n"); - DEBUG_PBS_D(status, 8); - DEBUG_PBS_S("\nDDR3 - PBS Rx - SKIP.\n"); - - /* Reset read FIFO */ - reg = reg_read(REG_DRAM_TRAINING_ADDR); - /* Start Auto Read Leveling procedure */ - reg |= (1 << REG_DRAM_TRAINING_RL_OFFS); - /* 0x15B0 - Training Register */ - reg_write(REG_DRAM_TRAINING_ADDR, reg); - - reg = reg_read(REG_DRAM_TRAINING_2_ADDR); - reg |= ((1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS) - + (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS)); - /* [0] = 1 - Enable SW override, [4] = 1 - FIFO reset */ - /* 0x15B8 - Training SW 2 Register */ - reg_write(REG_DRAM_TRAINING_2_ADDR, reg); - - do { - reg = (reg_read(REG_DRAM_TRAINING_2_ADDR)) - & (1 << REG_DRAM_TRAINING_2_FIFO_RST_OFFS); - } while (reg); /* Wait for '0' */ - - reg = reg_read(REG_DRAM_TRAINING_ADDR); - /* Clear Auto Read Leveling procedure */ - reg &= ~(1 << REG_DRAM_TRAINING_RL_OFFS); - /* 0x15B0 - Training Register */ - reg_write(REG_DRAM_TRAINING_ADDR, reg); - - /* Set ADLL to 15 */ - for (pup = 0; pup < max_pup; - pup++) { - ddr3_write_pup_reg - (PUP_DQS_RD, CS0, - pup + - (ecc * ECC_PUP), 0, - 15); - } - - /* Set all PBS values to MIN (0) */ - for (pup = 0; pup < cur_max_pup; - pup++) { - for (dq = 0; - dq < DQ_NUM; dq++) - ddr3_write_pup_reg - (PUP_PBS_RX + - pbs_dq_mapping - [pup * (1 - ecc) + - ecc * ECC_PUP] - [dq], CS0, - pup + ecc * ECC_PUP, - 0, MIN_PBS); - } - - return MV_OK; - } - - /* PBS For each bit */ - DEBUG_PBS_FULL_S("DDR3 - PBS Rx - perform PBS for each bit\n"); - /* in this stage - start_over = 0; */ - if (MV_OK != ddr3_pbs_per_bit( - dram_info, &start_over, - 0, &cur_pup, - pattern_idx, ecc)) { - DEBUG_PBS_S("DDR3 - PBS Rx - ddr3_pbs_per_bit failed."); - return MV_DDR3_TRAINING_ERR_PBS_RX_PER_BIT; - } - - } while ((start_over == 1) && - (++pbs_rep_time < COUNT_PBS_STARTOVER)); - - if (pbs_rep_time == COUNT_PBS_STARTOVER && - start_over == 1) { - DEBUG_PBS_FULL_S("DDR3 - PBS Rx - FAIL - Algorithm failed doing RX PBS\n"); - return MV_DDR3_TRAINING_ERR_PBS_RX_MAX_VAL; - } - - /* Return DQS ADLL to default value - 15 */ - /* Set all DQS PBS values to MIN (0) */ - for (pup = 0; pup < cur_max_pup; pup++) - ddr3_write_pup_reg(PUP_DQS_RD, CS0, - pup + ecc * ECC_PUP, - 0, INIT_RL_DELAY); - - DEBUG_PBS_FULL_C("DDR3 - PBS RX - values for iteration - ", - pbs_retry, 1); - for (pup = 0; pup < cur_max_pup; pup++) { - /* - * To minimize delay elements, inc from - * pbs value the min pbs val - */ - DEBUG_PBS_FULL_S("DDR3 - PBS - PUP"); - DEBUG_PBS_FULL_D((pup + - (ecc * ECC_PUP)), 1); - DEBUG_PBS_FULL_S(": "); - - for (dq = 0; dq < DQ_NUM; dq++) { - /* Set skew value for all dq */ - /* - * Bit# Deskew <- Bit# Deskew - - * last / first failing bit - * Deskew For all bits (per PUP) - * (minimize delay elements) - */ - DEBUG_PBS_FULL_S("DQ"); - DEBUG_PBS_FULL_D(dq, 1); - DEBUG_PBS_FULL_S("-"); - DEBUG_PBS_FULL_D(skew_array - [((pup) * - DQ_NUM) + - dq], 2); - DEBUG_PBS_FULL_S(", "); - } - DEBUG_PBS_FULL_S("\n"); - } - - /* - * Collect the results we got on this trial - * of PBS - */ - for (pup = 0; pup < cur_max_pup; pup++) { - for (dq = 0; dq < DQ_NUM; dq++) { - skew_sum_array - [pup + (ecc * (max_pup - 1))] - [dq] += - skew_array[((pup) * DQ_NUM) + dq]; - } - } - - /* ECC Support - Disable ECC MUX */ - reg = reg_read(REG_DRAM_TRAINING_2_ADDR) & - ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS); - reg_write(REG_DRAM_TRAINING_2_ADDR, reg); - } - } - - /* - * Calculate the average skew for current pattern for each - * pup and each bit - */ - DEBUG_PBS_FULL_C("DDR3 - PBS RX - Average for pattern - ", - pattern_idx, 1); - for (pup = 0; pup < max_pup; pup++) { - /* - * FOR ECC only :: found min and max value for - * current pattern skew array - */ - /* Loop for all dqs */ - for (dq = 0; dq < DQ_NUM; dq++) { - pattern_skew_array[pup][dq] += - (skew_sum_array[pup][dq] / - COUNT_PBS_REPEAT); - } - } - - DEBUG_PBS_C("DDR3 - PBS RX - values for current pattern - ", - pattern_idx, 1); - for (pup = 0; pup < max_pup; pup++) { - /* - * To minimize delay elements, inc from pbs value the - * min pbs val - */ - DEBUG_PBS_S("DDR3 - PBS RX - PUP"); - DEBUG_PBS_D(pup, 1); - DEBUG_PBS_S(": "); - - for (dq = 0; dq < DQ_NUM; dq++) { - /* Set skew value for all dq */ - /* - * Bit# Deskew <- Bit# Deskew - last / first - * failing bit Deskew For all bits (per PUP) - * (minimize delay elements) - */ - DEBUG_PBS_S("DQ"); - DEBUG_PBS_D(dq, 1); - DEBUG_PBS_S("-"); - DEBUG_PBS_D(skew_sum_array[pup][dq] / - COUNT_PBS_REPEAT, 2); - DEBUG_PBS_S(", "); - } - DEBUG_PBS_S("\n"); - } - } - - /* Calculate the average skew */ - for (pup = 0; pup < max_pup; pup++) { - for (dq = 0; dq < DQ_NUM; dq++) - skew_array[((pup) * DQ_NUM) + dq] = - pattern_skew_array[pup][dq] / COUNT_PBS_PATTERN; - } - - DEBUG_PBS_S("DDR3 - PBS RX - Average for all patterns:\n"); - for (pup = 0; pup < max_pup; pup++) { - /* - * To minimize delay elements, inc from pbs value the - * min pbs val - */ - DEBUG_PBS_S("DDR3 - PBS - PUP"); - DEBUG_PBS_D(pup, 1); - DEBUG_PBS_S(": "); - - for (dq = 0; dq < DQ_NUM; dq++) { - /* Set skew value for all dq */ - /* - * Bit# Deskew <- Bit# Deskew - last / first - * failing bit Deskew For all bits (per PUP) - * (minimize delay elements) - */ - DEBUG_PBS_S("DQ"); - DEBUG_PBS_D(dq, 1); - DEBUG_PBS_S("-"); - DEBUG_PBS_D(skew_array[(pup * DQ_NUM) + dq], 2); - DEBUG_PBS_S(", "); - } - DEBUG_PBS_S("\n"); - } - - /* Return ADLL to default value */ - ddr3_write_pup_reg(PUP_DQS_RD, CS0, PUP_BC, 0, INIT_RL_DELAY); - - /* Set averaged PBS results */ - ddr3_set_pbs_results(dram_info, 0); - - /* Disable SW override - Must be in a different stage */ - /* [0]=0 - Enable SW override */ - reg = reg_read(REG_DRAM_TRAINING_2_ADDR); - reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS); - /* 0x15B8 - Training SW 2 Register */ - reg_write(REG_DRAM_TRAINING_2_ADDR, reg); - - reg = reg_read(REG_DRAM_TRAINING_1_ADDR) | - (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS); - reg_write(REG_DRAM_TRAINING_1_ADDR, reg); - - DEBUG_PBS_FULL_S("DDR3 - PBS RX - ended successfuly\n"); - - return MV_OK; -} - -/* - * Name: ddr3_rx_shift_dqs_to_first_fail - * Desc: Execute the Rx shift DQ phase. - * Args: dram_info ddr3 training information struct - * cur_pup bit array of the function active pups. - * pbs_pattern_idx Index of PBS pattern - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -static int ddr3_rx_shift_dqs_to_first_fail(MV_DRAM_INFO *dram_info, u32 cur_pup, - u32 pbs_pattern_idx, u32 ecc) -{ - u32 unlock_pup; /* bit array of unlock pups */ - u32 new_lockup_pup; /* bit array of compare failed pups */ - u32 adll_val = MAX_DELAY; - u32 dqs_deskew_val = 0; /* current value of DQS PBS deskew */ - u32 cur_max_pup, pup, pass_pup; - u32 *pattern_ptr; - - /* Choose pattern */ - switch (dram_info->ddr_width) { -#if defined(MV88F672X) - case 16: - pattern_ptr = (u32 *)&pbs_pattern[pbs_pattern_idx]; - break; -#endif - case 32: - pattern_ptr = (u32 *)&pbs_pattern_32b[pbs_pattern_idx]; - break; -#if defined(MV88F78X60) - case 64: - pattern_ptr = (u32 *)&pbs_pattern_64b[pbs_pattern_idx]; - break; -#endif - default: - return MV_FAIL; - } - - /* Set current pup number */ - if (cur_pup == 0x1) /* Ecc mode */ - cur_max_pup = 1; - else - cur_max_pup = dram_info->num_of_std_pups; - - unlock_pup = cur_pup; /* '1' for each unlocked pup */ - - DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - Starting...\n"); - - /* Set DQS ADLL to MAX */ - DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - Set DQS ADLL to Max for all PUPs\n"); - for (pup = 0; pup < cur_max_pup; pup++) - ddr3_write_pup_reg(PUP_DQS_RD, CS0, pup + ecc * ECC_PUP, 0, - MAX_DELAY); - - /* Loop on all ADLL Vaules */ - do { - /* Loop until found fail for all pups */ - new_lockup_pup = 0; - if (MV_OK != ddr3_sdram_compare(dram_info, unlock_pup, - &new_lockup_pup, - pattern_ptr, LEN_PBS_PATTERN, - SDRAM_PBS_I_OFFS + - pbs_pattern_idx * SDRAM_PBS_NEXT_OFFS, - 0, 0, NULL, 0)) { - DEBUG_PBS_S("DDR3 - PBS Rx - Shift DQS - MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP(ddr3_sdram_compare)\n"); - return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP; - } - - if ((new_lockup_pup != 0) && (dqs_deskew_val <= 1)) { - /* Fail on start with first deskew value */ - /* Decrement DQS ADLL */ - --adll_val; - if (adll_val == ADLL_MIN) { - DEBUG_PBS_S("DDR3 - PBS Rx - Shift DQS - fail on start with first deskew value\n"); - return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP; - } - ddr3_write_pup_reg(PUP_DQS_RD, CS0, pup + ecc * ECC_PUP, - 0, adll_val); - continue; - } - - /* Update all new locked pups */ - unlock_pup &= ~new_lockup_pup; - - if ((unlock_pup == 0) || (dqs_deskew_val == MAX_PBS)) { - if (dqs_deskew_val == MAX_PBS) { - /* - * Reach max value of dqs deskew or get fail - * for all pups - */ - DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - DQS deskew reached maximum value\n"); - } - break; - } - - DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - Inc DQS deskew for PUPs: "); - DEBUG_PBS_FULL_D(unlock_pup, 2); - DEBUG_PBS_FULL_C(", deskew = ", dqs_deskew_val, 2); - - /* Increment DQS deskew elements - Only for unlocked pups */ - dqs_deskew_val++; - for (pup = 0; pup < cur_max_pup; pup++) { - if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) { - ddr3_write_pup_reg(PUP_PBS_RX + DQS_DQ_NUM, CS0, - pup + ecc * ECC_PUP, 0, - dqs_deskew_val); - } - } - } while (1); - - DEBUG_PBS_FULL_S("DDR3 - PBS RX - Shift DQS - ADLL shift one step before fail\n"); - /* Continue to ADLL shift one step before fail */ - unlock_pup = cur_pup; - do { - /* Loop until pass compare for all pups */ - new_lockup_pup = 0; - /* Read and compare results */ - if (MV_OK != ddr3_sdram_compare(dram_info, unlock_pup, &new_lockup_pup, - pattern_ptr, LEN_PBS_PATTERN, - SDRAM_PBS_I_OFFS + - pbs_pattern_idx * SDRAM_PBS_NEXT_OFFS, - 1, 0, NULL, 0)) { - DEBUG_PBS_S("DDR3 - PBS Rx - Shift DQS - MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP(ddr3_sdram_compare)\n"); - return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_SRAM_CMP; - } - - /* - * Get mask for pup which passed so their adll will be - * changed to 2 steps before fails - */ - pass_pup = unlock_pup & ~new_lockup_pup; - - DEBUG_PBS_FULL_S("Shift DQS by 2 steps for PUPs: "); - DEBUG_PBS_FULL_D(pass_pup, 2); - DEBUG_PBS_FULL_C(", Set ADLL value = ", (adll_val - 2), 2); - - /* Only for pass pups */ - for (pup = 0; pup < cur_max_pup; pup++) { - if (IS_PUP_ACTIVE(pass_pup, pup) == 1) { - ddr3_write_pup_reg(PUP_DQS_RD, CS0, - pup + ecc * ECC_PUP, 0, - (adll_val - 2)); - } - } - - /* Locked pups that compare success */ - unlock_pup &= new_lockup_pup; - - if (unlock_pup == 0) { - /* All pups locked */ - break; - } - - /* Found error */ - if (adll_val == 0) { - DEBUG_PBS_FULL_S("DDR3 - PBS Rx - Shift DQS - Adll reach min value\n"); - return MV_DDR3_TRAINING_ERR_PBS_SHIFT_QDS_MAX_VAL; - } - - /* - * Decrement (Move Back to Left one phase - ADLL) dqs RX delay - */ - adll_val--; - for (pup = 0; pup < cur_max_pup; pup++) { - if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) { - ddr3_write_pup_reg(PUP_DQS_RD, CS0, - pup + ecc * ECC_PUP, 0, - adll_val); - } - } - } while (1); - - return MV_OK; -} - -/* - * lock_pups() extracted from ddr3_pbs_per_bit(). This just got too - * much indented making it hard to read / edit. - */ -static void lock_pups(u32 pup, u32 *pup_locked, u8 *unlock_pup_dq_array, - u32 pbs_curr_val, u32 start_pbs, u32 ecc, int is_tx) -{ - u32 dq; - int idx; - - /* Lock PBS value for all remaining PUPs bits */ - DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Lock PBS value for all remaining PUPs bits, pup "); - DEBUG_PBS_FULL_D(pup, 1); - DEBUG_PBS_FULL_C(" pbs value ", pbs_curr_val, 2); - - idx = pup * (1 - ecc) + ecc * ECC_PUP; - *pup_locked &= ~(1 << pup); - - for (dq = 0; dq < DQ_NUM; dq++) { - if (IS_PUP_ACTIVE(unlock_pup_dq_array[dq], pup) == 1) { - int offs; - - /* Lock current dq */ - unlock_pup_dq_array[dq] &= ~(1 << pup); - skew_array[(pup * DQ_NUM) + dq] = pbs_curr_val; - - if (is_tx == 1) - offs = PUP_PBS_TX; - else - offs = PUP_PBS_RX; - - ddr3_write_pup_reg(offs + - pbs_dq_mapping[idx][dq], CS0, - idx, 0, start_pbs); - } - } -} - -/* - * Name: ddr3_pbs_per_bit - * Desc: Execute the Per Bit Skew phase. - * Args: start_over Return whether need to start over the algorithm - * is_tx Indicate whether Rx or Tx - * pcur_pup bit array of the function active pups. return the - * pups that need to repeat on the PBS - * pbs_pattern_idx Index of PBS pattern - * - * Notes: Current implementation supports double activation of this function. - * i.e. in order to activate this function (using start_over) more than - * twice, the implementation should change. - * imlementation limitation are marked using - * ' CHIP-ONLY! - Implementation Limitation ' - * Returns: MV_OK if success, other error code if fail. - */ -static int ddr3_pbs_per_bit(MV_DRAM_INFO *dram_info, int *start_over, int is_tx, - u32 *pcur_pup, u32 pbs_pattern_idx, u32 ecc) -{ - /* - * Bit array to indicate if we already get fail on bit per pup & dq bit - */ - u8 unlock_pup_dq_array[DQ_NUM] = { - *pcur_pup, *pcur_pup, *pcur_pup, *pcur_pup, *pcur_pup, - *pcur_pup, *pcur_pup, *pcur_pup - }; - - u8 cmp_unlock_pup_dq_array[COUNT_PBS_COMP_RETRY_NUM][DQ_NUM]; - u32 pup, dq; - /* value of pbs is according to RX or TX */ - u32 start_pbs, last_pbs; - u32 pbs_curr_val; - /* bit array that indicates all dq of the pup locked */ - u32 pup_locked; - u32 first_fail[MAX_PUP_NUM] = { 0 }; /* count first fail per pup */ - /* indicates whether we get first fail per pup */ - int first_failed[MAX_PUP_NUM] = { 0 }; - /* bit array that indicates pup already get fail */ - u32 sum_pup_fail; - /* use to calculate diff between curr pbs to first fail pbs */ - u32 calc_pbs_diff; - u32 pbs_cmp_retry; - u32 max_pup; - - /* Set init values for retry array - 8 retry */ - for (pbs_cmp_retry = 0; pbs_cmp_retry < COUNT_PBS_COMP_RETRY_NUM; - pbs_cmp_retry++) { - for (dq = 0; dq < DQ_NUM; dq++) - cmp_unlock_pup_dq_array[pbs_cmp_retry][dq] = *pcur_pup; - } - - memset(&skew_array, 0, MAX_PUP_NUM * DQ_NUM * sizeof(u32)); - - DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Started\n"); - - /* The pbs value depends if rx or tx */ - if (is_tx == 1) { - start_pbs = MIN_PBS; - last_pbs = MAX_PBS; - } else { - start_pbs = MAX_PBS; - last_pbs = MIN_PBS; - } - - pbs_curr_val = start_pbs; - pup_locked = *pcur_pup; - - /* Set current pup number */ - if (pup_locked == 0x1) /* Ecc mode */ - max_pup = 1; - else - max_pup = dram_info->num_of_std_pups; - - do { - /* Increment/ decrement PBS for un-lock bits only */ - if (is_tx == 1) - pbs_curr_val++; - else - pbs_curr_val--; - - /* Set Current PBS delay */ - for (dq = 0; dq < DQ_NUM; dq++) { - /* Check DQ bits to see if locked in all pups */ - if (unlock_pup_dq_array[dq] == 0) { - DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - All pups are locked for DQ "); - DEBUG_PBS_FULL_D(dq, 1); - DEBUG_PBS_FULL_S("\n"); - continue; - } - - for (pup = 0; pup < max_pup; pup++) { - int idx; - - idx = pup * (1 - ecc) + ecc * ECC_PUP; - - if (IS_PUP_ACTIVE(unlock_pup_dq_array[dq], pup) - == 0) - continue; - - if (is_tx == 1) - ddr3_write_pup_reg( - PUP_PBS_TX + pbs_dq_mapping[idx][dq], - CS0, idx, 0, pbs_curr_val); - else - ddr3_write_pup_reg( - PUP_PBS_RX + pbs_dq_mapping[idx][dq], - CS0, idx, 0, pbs_curr_val); - } - } - - /* - * Write Read and compare results - run the test - * DDR_PBS_COMP_RETRY_NUM times - */ - /* Run number of read and write to verify */ - for (pbs_cmp_retry = 0; - pbs_cmp_retry < COUNT_PBS_COMP_RETRY_NUM; - pbs_cmp_retry++) { - - if (MV_OK != - ddr3_sdram_pbs_compare(dram_info, pup_locked, is_tx, - pbs_pattern_idx, - pbs_curr_val, start_pbs, - skew_array, - cmp_unlock_pup_dq_array - [pbs_cmp_retry], ecc)) - return MV_FAIL; - - for (pup = 0; pup < max_pup; pup++) { - for (dq = 0; dq < DQ_NUM; dq++) { - if ((IS_PUP_ACTIVE(unlock_pup_dq_array[dq], - pup) == 1) - && (IS_PUP_ACTIVE(cmp_unlock_pup_dq_array - [pbs_cmp_retry][dq], - pup) == 0)) { - DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - PbsCurrVal: "); - DEBUG_PBS_FULL_D(pbs_curr_val, 2); - DEBUG_PBS_FULL_S(" PUP: "); - DEBUG_PBS_FULL_D(pup, 1); - DEBUG_PBS_FULL_S(" DQ: "); - DEBUG_PBS_FULL_D(dq, 1); - DEBUG_PBS_FULL_S(" - failed\n"); - } - } - } - - for (dq = 0; dq < DQ_NUM; dq++) { - unlock_pup_dq_array[dq] &= - cmp_unlock_pup_dq_array[pbs_cmp_retry][dq]; - } - } - - pup_locked = 0; - sum_pup_fail = *pcur_pup; - - /* Check which DQ is failed */ - for (dq = 0; dq < DQ_NUM; dq++) { - /* Summarize the locked pup */ - pup_locked |= unlock_pup_dq_array[dq]; - - /* Check if get fail */ - sum_pup_fail &= unlock_pup_dq_array[dq]; - } - - /* If all PUPS are locked in all DQ - Break */ - if (pup_locked == 0) { - /* All pups are locked */ - *start_over = 0; - DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - All bit in all pups are successfully locked\n"); - break; - } - - /* PBS deskew elements reach max ? */ - if (pbs_curr_val == last_pbs) { - DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - PBS deskew elements reach max\n"); - /* CHIP-ONLY! - Implementation Limitation */ - *start_over = (sum_pup_fail != 0) && (!(*start_over)); - *pcur_pup = pup_locked; - - DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - StartOver: "); - DEBUG_PBS_FULL_D(*start_over, 1); - DEBUG_PBS_FULL_S(" pup_locked: "); - DEBUG_PBS_FULL_D(pup_locked, 2); - DEBUG_PBS_FULL_S(" sum_pup_fail: "); - DEBUG_PBS_FULL_D(sum_pup_fail, 2); - DEBUG_PBS_FULL_S("\n"); - - /* Lock PBS value for all remaining bits */ - for (pup = 0; pup < max_pup; pup++) { - /* Check if current pup already received error */ - if (IS_PUP_ACTIVE(pup_locked, pup) == 1) { - /* Valid pup for current function */ - if (IS_PUP_ACTIVE(sum_pup_fail, pup) == - 1 && (*start_over == 1)) { - DEBUG_PBS_FULL_C("DDR3 - PBS Per bit - skipping lock of pup (first loop of pbs)", - pup, 1); - continue; - } else - if (IS_PUP_ACTIVE(sum_pup_fail, pup) - == 1) { - DEBUG_PBS_FULL_C("DDR3 - PBS Per bit - Locking pup %d (even though it wasn't supposed to be locked)", - pup, 1); - } - - /* Already got fail on the PUP */ - /* Lock PBS value for all remaining bits */ - DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Locking remaning DQs for pup - "); - DEBUG_PBS_FULL_D(pup, 1); - DEBUG_PBS_FULL_S(": "); - - for (dq = 0; dq < DQ_NUM; dq++) { - if (IS_PUP_ACTIVE - (unlock_pup_dq_array[dq], - pup) == 1) { - DEBUG_PBS_FULL_D(dq, 1); - DEBUG_PBS_FULL_S(","); - /* set current PBS */ - skew_array[((pup) * - DQ_NUM) + - dq] = - pbs_curr_val; - } - } - - if (*start_over == 1) { - /* - * Reset this pup bit - when - * restart the PBS, ignore this - * pup - */ - *pcur_pup &= ~(1 << pup); - } - DEBUG_PBS_FULL_S("\n"); - } else { - DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - Pup "); - DEBUG_PBS_FULL_D(pup, 1); - DEBUG_PBS_FULL_C(" is not set in puplocked - ", - pup_locked, 1); - } - } - - /* Need to start the PBS again */ - if (*start_over == 1) { - DEBUG_PBS_FULL_S("DDR3 - PBS Per bit - false fail - returning to start\n"); - return MV_OK; - } - break; - } - - /* Diff Check */ - for (pup = 0; pup < max_pup; pup++) { - if (IS_PUP_ACTIVE(pup_locked, pup) == 1) { - /* pup is not locked */ - if (first_failed[pup] == 0) { - /* No first fail until now */ - if (IS_PUP_ACTIVE(sum_pup_fail, pup) == - 0) { - /* Get first fail */ - DEBUG_PBS_FULL_C("DDR3 - PBS Per bit - First fail in pup ", - pup, 1); - first_failed[pup] = 1; - first_fail[pup] = pbs_curr_val; - } - } else { - /* Already got first fail */ - if (is_tx == 1) { - /* TX - inc pbs */ - calc_pbs_diff = pbs_curr_val - - first_fail[pup]; - } else { - /* RX - dec pbs */ - calc_pbs_diff = first_fail[pup] - - pbs_curr_val; - } - - if (calc_pbs_diff >= PBS_DIFF_LIMIT) { - lock_pups(pup, &pup_locked, - unlock_pup_dq_array, - pbs_curr_val, - start_pbs, ecc, is_tx); - } - } - } - } - } while (1); - - return MV_OK; -} - -/* - * Name: ddr3_set_pbs_results - * Desc: Set to HW the PBS phase results. - * Args: is_tx Indicates whether to set Tx or RX results - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -static int ddr3_set_pbs_results(MV_DRAM_INFO *dram_info, int is_tx) -{ - u32 pup, phys_pup, dq; - u32 max_pup; /* number of valid pups */ - u32 pbs_min; /* minimal pbs val per pup */ - u32 pbs_max; /* maximum pbs val per pup */ - u32 val[9]; - - max_pup = dram_info->num_of_total_pups; - DEBUG_PBS_FULL_S("DDR3 - PBS - ddr3_set_pbs_results:\n"); - - /* Loop for all dqs & pups */ - for (pup = 0; pup < max_pup; pup++) { - if (pup == (max_pup - 1) && dram_info->ecc_ena) - phys_pup = ECC_PUP; - else - phys_pup = pup; - - /* - * To minimize delay elements, inc from pbs value the min - * pbs val - */ - pbs_min = MAX_PBS; - pbs_max = 0; - for (dq = 0; dq < DQ_NUM; dq++) { - if (pbs_min > skew_array[(pup * DQ_NUM) + dq]) - pbs_min = skew_array[(pup * DQ_NUM) + dq]; - - if (pbs_max < skew_array[(pup * DQ_NUM) + dq]) - pbs_max = skew_array[(pup * DQ_NUM) + dq]; - } - - pbs_max -= pbs_min; - - DEBUG_PBS_FULL_S("DDR3 - PBS - PUP"); - DEBUG_PBS_FULL_D(phys_pup, 1); - DEBUG_PBS_FULL_S(": Min Val = "); - DEBUG_PBS_FULL_D(pbs_min, 2); - DEBUG_PBS_FULL_C(", Max Val = ", pbs_max, 2); - - val[pup] = 0; - - for (dq = 0; dq < DQ_NUM; dq++) { - int idx; - int offs; - - /* Set skew value for all dq */ - /* - * Bit# Deskew <- Bit# Deskew - last / first - * failing bit Deskew For all bits (per PUP) - * (minimize delay elements) - */ - - DEBUG_PBS_FULL_S("DQ"); - DEBUG_PBS_FULL_D(dq, 1); - DEBUG_PBS_FULL_S("-"); - DEBUG_PBS_FULL_D((skew_array[(pup * DQ_NUM) + dq] - - pbs_min), 2); - DEBUG_PBS_FULL_S(", "); - - idx = (pup * DQ_NUM) + dq; - - if (is_tx == 1) - offs = PUP_PBS_TX; - else - offs = PUP_PBS_RX; - - ddr3_write_pup_reg(offs + pbs_dq_mapping[phys_pup][dq], - CS0, phys_pup, 0, - skew_array[idx] - pbs_min); - - if (is_tx == 1) - val[pup] += skew_array[idx] - pbs_min; - } - - DEBUG_PBS_FULL_S("\n"); - - /* Set the DQS the half of the Max PBS of the DQs */ - if (is_tx == 1) { - ddr3_write_pup_reg(PUP_PBS_TX + 8, CS0, phys_pup, 0, - pbs_max / 2); - ddr3_write_pup_reg(PUP_PBS_TX + 0xa, CS0, phys_pup, 0, - val[pup] / 8); - } else - ddr3_write_pup_reg(PUP_PBS_RX + 8, CS0, phys_pup, 0, - pbs_max / 2); - } - - return MV_OK; -} - -static void ddr3_pbs_write_pup_dqs_reg(u32 cs, u32 pup, u32 dqs_delay) -{ - u32 reg, delay; - - reg = (ddr3_read_pup_reg(PUP_WL_MODE, cs, pup) & 0x3FF); - delay = reg & PUP_DELAY_MASK; - reg |= ((dqs_delay + delay) << REG_PHY_DQS_REF_DLY_OFFS); - reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR; - reg |= (pup << REG_PHY_PUP_OFFS); - reg |= ((0x4 * cs + PUP_WL_MODE) << REG_PHY_CS_OFFS); - - reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg); /* 0x16A0 */ - do { - reg = reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR) & - REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE; - } while (reg); /* Wait for '0' to mark the end of the transaction */ - - udelay(10); -} - -/* - * Set training patterns - */ -int ddr3_load_pbs_patterns(MV_DRAM_INFO *dram_info) -{ - u32 cs, cs_count, cs_tmp; - u32 sdram_addr; - u32 *pattern_ptr0, *pattern_ptr1; - - /* Choose pattern */ - switch (dram_info->ddr_width) { -#if defined(MV88F672X) - case 16: - pattern_ptr0 = (u32 *)&pbs_pattern[0]; - pattern_ptr1 = (u32 *)&pbs_pattern[1]; - break; -#endif - case 32: - pattern_ptr0 = (u32 *)&pbs_pattern_32b[0]; - pattern_ptr1 = (u32 *)&pbs_pattern_32b[1]; - break; -#if defined(MV88F78X60) - case 64: - pattern_ptr0 = (u32 *)&pbs_pattern_64b[0]; - pattern_ptr1 = (u32 *)&pbs_pattern_64b[1]; - break; -#endif - default: - return MV_FAIL; - } - - /* Loop for each CS */ - for (cs = 0; cs < MAX_CS; cs++) { - if (dram_info->cs_ena & (1 << cs)) { - cs_count = 0; - for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) { - if (dram_info->cs_ena & (1 << cs_tmp)) - cs_count++; - } - - /* Init PBS I pattern */ - sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) + - SDRAM_PBS_I_OFFS); - if (MV_OK != - ddr3_sdram_compare(dram_info, (u32) NULL, NULL, - pattern_ptr0, LEN_STD_PATTERN, - sdram_addr, 1, 0, NULL, - 0)) - return MV_FAIL; - - /* Init PBS II pattern */ - sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) + - SDRAM_PBS_II_OFFS); - if (MV_OK != - ddr3_sdram_compare(dram_info, (u32) NULL, NULL, - pattern_ptr1, LEN_STD_PATTERN, - sdram_addr, 1, 0, NULL, - 0)) - return MV_FAIL; - } - } - - return MV_OK; -} -#endif |