From c8570afa04b6d5db236b2426922f78fc26f647b5 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 21 Jul 2015 05:26:58 +0200 Subject: [PATCH] ddr: altera: Clean up rw_mgr_mem_calibrate_writes_center() part 2 Factor out common code for searching best DM/DQS window. Signed-off-by: Marek Vasut --- drivers/ddr/altera/sequencer.c | 167 +++++++++++++++++---------------- 1 file changed, 88 insertions(+), 79 deletions(-) diff --git a/drivers/ddr/altera/sequencer.c b/drivers/ddr/altera/sequencer.c index e99ecb4a87..cc5db16e36 100644 --- a/drivers/ddr/altera/sequencer.c +++ b/drivers/ddr/altera/sequencer.c @@ -2883,6 +2883,89 @@ static uint32_t rw_mgr_mem_calibrate_write_test(uint32_t rank_bgn, } } +/** + * search_window() - Search for the/part of the window with DM/DQS shift + * @search_dm: If 1, search for the DM shift, if 0, search for DQS shift + * @rank_bgn: Rank number + * @write_group: Write Group + * @bgn_curr: Current window begin + * @end_curr: Current window end + * @bgn_best: Current best window begin + * @end_best: Current best window end + * @win_best: Size of the best window + * @new_dqs: New DQS value (only applicable if search_dm = 0). + * + * Search for the/part of the window with DM/DQS shift. + */ +static void search_window(const int search_dm, + const u32 rank_bgn, const u32 write_group, + int *bgn_curr, int *end_curr, int *bgn_best, + int *end_best, int *win_best, int new_dqs) +{ + u32 bit_chk; + const int max = IO_IO_OUT1_DELAY_MAX - new_dqs; + int d, di; + + /* Search for the/part of the window with DM/DQS shift. */ + for (di = max; di >= 0; di -= DELTA_D) { + if (search_dm) { + d = di; + scc_mgr_apply_group_dm_out1_delay(d); + } else { + /* For DQS, we go from 0...max */ + d = max - di; + /* + * Note: This only shifts DQS, so are we limiting ourselve to + * width of DQ unnecessarily. + */ + scc_mgr_apply_group_dqs_io_and_oct_out1(write_group, + d + new_dqs); + } + + writel(0, &sdr_scc_mgr->update); + + if (rw_mgr_mem_calibrate_write_test(rank_bgn, write_group, 1, + PASS_ALL_BITS, &bit_chk, + 0)) { + /* Set current end of the window. */ + *end_curr = search_dm ? -d : d; + + /* + * If a starting edge of our window has not been seen + * this is our current start of the DM window. + */ + if (*bgn_curr == IO_IO_OUT1_DELAY_MAX + 1) + *bgn_curr = search_dm ? -d : d; + + /* + * If current window is bigger than best seen. + * Set best seen to be current window. + */ + if ((*end_curr - *bgn_curr + 1) > *win_best) { + *win_best = *end_curr - *bgn_curr + 1; + *bgn_best = *bgn_curr; + *end_best = *end_curr; + } + } else { + /* We just saw a failing test. Reset temp edge. */ + *bgn_curr = IO_IO_OUT1_DELAY_MAX + 1; + *end_curr = IO_IO_OUT1_DELAY_MAX + 1; + + /* Early exit is only applicable to DQS. */ + if (search_dm) + continue; + + /* + * Early exit optimization: if the remaining delay + * chain space is less than already seen largest + * window we can exit. + */ + if (*win_best - 1 > IO_IO_OUT1_DELAY_MAX - new_dqs - d) + break; + } + } +} + /* * center all windows. do per-bit-deskew to possibly increase size of * certain windows. @@ -2891,8 +2974,7 @@ static int rw_mgr_mem_calibrate_writes_center(const u32 rank_bgn, const u32 write_group, const u32 test_bgn) { - int i, d; - u32 bit_chk; + int i; u32 sticky_bit_chk; u32 min_index; u32 addr; @@ -2975,37 +3057,8 @@ rw_mgr_mem_calibrate_writes_center(const u32 rank_bgn, const u32 write_group, right_edge[0] = IO_IO_OUT1_DELAY_MAX + 1; /* Search for the/part of the window with DM shift. */ - for (d = IO_IO_OUT1_DELAY_MAX; d >= 0; d -= DELTA_D) { - scc_mgr_apply_group_dm_out1_delay(d); - writel(0, &sdr_scc_mgr->update); - - if (rw_mgr_mem_calibrate_write_test(rank_bgn, write_group, 1, - PASS_ALL_BITS, &bit_chk, - 0)) { - /* Set current end of the window. */ - end_curr = -d; - /* - * If a starting edge of our window has not been seen - * this is our current start of the DM window. - */ - if (bgn_curr == IO_IO_OUT1_DELAY_MAX + 1) - bgn_curr = -d; - - /* - * If current window is bigger than best seen. - * Set best seen to be current window. - */ - if ((end_curr-bgn_curr+1) > win_best) { - win_best = end_curr-bgn_curr+1; - bgn_best = bgn_curr; - end_best = end_curr; - } - } else { - /* We just saw a failing test. Reset temp edge. */ - bgn_curr = IO_IO_OUT1_DELAY_MAX + 1; - end_curr = IO_IO_OUT1_DELAY_MAX + 1; - } - } + search_window(1, rank_bgn, write_group, &bgn_curr, &end_curr, + &bgn_best, &end_best, &win_best, 0); /* Reset DM delay chains to 0. */ scc_mgr_apply_group_dm_out1_delay(0); @@ -3021,52 +3074,8 @@ rw_mgr_mem_calibrate_writes_center(const u32 rank_bgn, const u32 write_group, } /* Search for the/part of the window with DQS shifts. */ - for (d = 0; d <= IO_IO_OUT1_DELAY_MAX - new_dqs; d += DELTA_D) { - /* - * Note: This only shifts DQS, so are we limiting ourselve to - * width of DQ unnecessarily. - */ - scc_mgr_apply_group_dqs_io_and_oct_out1(write_group, - d + new_dqs); - - writel(0, &sdr_scc_mgr->update); - if (rw_mgr_mem_calibrate_write_test(rank_bgn, write_group, 1, - PASS_ALL_BITS, &bit_chk, - 0)) { - /* Set current end of the window. */ - end_curr = d; - /* - * If a beginning edge of our window has not been seen - * this is our current begin of the DM window. - */ - if (bgn_curr == IO_IO_OUT1_DELAY_MAX + 1) - bgn_curr = d; - - /* - * If current window is bigger than best seen. Set best - * seen to be current window. - */ - if ((end_curr-bgn_curr+1) > win_best) { - win_best = end_curr-bgn_curr+1; - bgn_best = bgn_curr; - end_best = end_curr; - } - } else { - /* We just saw a failing test. Reset temp edge. */ - bgn_curr = IO_IO_OUT1_DELAY_MAX + 1; - end_curr = IO_IO_OUT1_DELAY_MAX + 1; - - /* - * Early exit optimization: if the remaining delay - * chain space is less than already seen largest - * window we can exit. - */ - if ((win_best-1) > - (IO_IO_OUT1_DELAY_MAX - new_dqs - d)) { - break; - } - } - } + search_window(0, rank_bgn, write_group, &bgn_curr, &end_curr, + &bgn_best, &end_best, &win_best, new_dqs); /* Assign left and right edge for cal and reporting. */ left_edge[0] = -1 * bgn_best; -- 2.25.1