ddr: altera: Clean up rw_mgr_mem_calibrate_writes_center() part 2
authorMarek Vasut <marex@denx.de>
Tue, 21 Jul 2015 03:26:58 +0000 (05:26 +0200)
committerMarek Vasut <marex@denx.de>
Sat, 8 Aug 2015 12:14:22 +0000 (14:14 +0200)
Factor out common code for searching best DM/DQS window.

Signed-off-by: Marek Vasut <marex@denx.de>
drivers/ddr/altera/sequencer.c

index e99ecb4..cc5db16 100644 (file)
@@ -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;