ddr: altera: Clean up rw_mgr_mem_calibrate_vfifo_center() part 1
authorMarek Vasut <marex@denx.de>
Mon, 13 Jul 2015 00:11:02 +0000 (02:11 +0200)
committerMarek Vasut <marex@denx.de>
Sat, 8 Aug 2015 12:14:21 +0000 (14:14 +0200)
Factor out common code from rw_mgr_mem_calibrate_writes_center()
and rw_mgr_mem_calibrate_vfifo_center() for searching for the
right edge of the window. The code is almost identical, so pull
it into separate function and cater for the minor differences.

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

index 714fdf081b2d191455055a00de60c3cff9f81922..b175313db06f76b47cc8a7ea94c0dd5a736a4a4c 100644 (file)
@@ -1780,6 +1780,166 @@ static int rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(const u32 grp)
        return ret;
 }
 
+/**
+ * search_right_edge() - Find right edge of DQ/DQS working phase
+ * @write:             Perform read (Stage 2) or write (Stage 3) calibration
+ * @rank_bgn:          Rank number
+ * @write_group:       Write Group
+ * @read_group:                Read Group
+ * @start_dqs:         DQS start phase
+ * @start_dqs_en:      DQS enable start phase
+ * @bit_chk:           Resulting bit mask after the test
+ * @sticky_bit_chk:    Resulting sticky bit mask after the test
+ * @left_edge:         Left edge of the DQ/DQS phase
+ * @right_edge:                Right edge of the DQ/DQS phase
+ * @use_read_test:     Perform read test
+ *
+ * Find right edge of DQ/DQS working phase.
+ */
+static int search_right_edge(const int write, const int rank_bgn,
+       const u32 write_group, const u32 read_group,
+       const int start_dqs, const int start_dqs_en,
+       u32 *bit_chk, u32 *sticky_bit_chk,
+       int *left_edge, int *right_edge, const u32 use_read_test)
+{
+       const u32 correct_mask = write ? param->write_correct_mask :
+                                        param->read_correct_mask;
+       const u32 delay_max = write ? IO_IO_OUT1_DELAY_MAX : IO_IO_IN_DELAY_MAX;
+       const u32 dqs_max = write ? IO_IO_OUT1_DELAY_MAX : IO_DQS_IN_DELAY_MAX;
+       const u32 per_dqs = write ? RW_MGR_MEM_DQ_PER_WRITE_DQS :
+                                   RW_MGR_MEM_DQ_PER_READ_DQS;
+       u32 stop;
+       int i, d;
+
+       for (d = 0; d <= dqs_max - start_dqs; d++) {
+               if (write) {    /* WRITE-ONLY */
+                       scc_mgr_apply_group_dqs_io_and_oct_out1(write_group,
+                                                               d + start_dqs);
+               } else {        /* READ-ONLY */
+                       scc_mgr_set_dqs_bus_in_delay(read_group, d + start_dqs);
+                       if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
+                               uint32_t delay = d + start_dqs_en;
+                               if (delay > IO_DQS_EN_DELAY_MAX)
+                                       delay = IO_DQS_EN_DELAY_MAX;
+                               scc_mgr_set_dqs_en_delay(read_group, delay);
+                       }
+                       scc_mgr_load_dqs(read_group);
+               }
+
+               writel(0, &sdr_scc_mgr->update);
+
+               /*
+                * Stop searching when the read test doesn't pass AND when
+                * we've seen a passing read on every bit.
+                */
+               if (write) {    /* WRITE-ONLY */
+                       stop = !rw_mgr_mem_calibrate_write_test(rank_bgn,
+                                                       write_group,
+                                                       0, PASS_ONE_BIT,
+                                                       bit_chk, 0);
+
+               } else if (use_read_test) {     /* READ-ONLY */
+                       stop = !rw_mgr_mem_calibrate_read_test(rank_bgn,
+                               read_group, NUM_READ_PB_TESTS, PASS_ONE_BIT,
+                               bit_chk, 0, 0);
+               } else {                        /* READ-ONLY */
+                       rw_mgr_mem_calibrate_write_test(rank_bgn,
+                                                       write_group,
+                                                       0, PASS_ONE_BIT,
+                                                       bit_chk, 0);
+                       *bit_chk = *bit_chk >> (per_dqs *
+                               (read_group - (write_group *
+                                       RW_MGR_MEM_IF_READ_DQS_WIDTH /
+                                       RW_MGR_MEM_IF_WRITE_DQS_WIDTH)));
+                       stop = (*bit_chk == 0);
+               }
+               *sticky_bit_chk = *sticky_bit_chk | *bit_chk;
+               stop = stop && (*sticky_bit_chk == correct_mask);
+
+               debug_cond(DLEVEL == 2,
+                          "%s:%d center(right): dtap=%u => %u == %u && %u", __func__, __LINE__, d,
+                          *sticky_bit_chk, correct_mask, stop);
+
+               if (stop == 1) {
+                       if (write && (d == 0)) {        /* WRITE-ONLY */
+                               for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
+                                       /*
+                                        * d = 0 failed, but it passed when
+                                        * testing the left edge, so it must be
+                                        * marginal, set it to -1
+                                        */
+                                       if (right_edge[i] == delay_max + 1 &&
+                                           left_edge[i] != delay_max + 1)
+                                               right_edge[i] = -1;
+                               }
+                       }
+                       break;
+               }
+
+               /* stop != 1 */
+               for (i = 0; i < per_dqs; i++) {
+                       if (*bit_chk & 1) {
+                               /*
+                                * Remember a passing test as
+                                * the right_edge.
+                                */
+                               right_edge[i] = d;
+                       } else {
+                               if (d != 0) {
+                                       /*
+                                        * If a right edge has not
+                                        * been seen yet, then a future
+                                        * passing test will mark this
+                                        * edge as the left edge.
+                                        */
+                                       if (right_edge[i] == delay_max + 1)
+                                               left_edge[i] = -(d + 1);
+                               } else {
+                                       /*
+                                        * d = 0 failed, but it passed
+                                        * when testing the left edge,
+                                        * so it must be marginal, set
+                                        * it to -1
+                                        */
+                                       if (right_edge[i] == delay_max + 1 &&
+                                           left_edge[i] != delay_max + 1)
+                                               right_edge[i] = -1;
+                                       /*
+                                        * If a right edge has not been
+                                        * seen yet, then a future
+                                        * passing test will mark this
+                                        * edge as the left edge.
+                                        */
+                                       else if (right_edge[i] == delay_max + 1)
+                                               left_edge[i] = -(d + 1);
+                               }
+                       }
+
+                       debug_cond(DLEVEL == 2, "%s:%d center[r,d=%u]: ",
+                                  __func__, __LINE__, d);
+                       debug_cond(DLEVEL == 2,
+                                  "bit_chk_test=%i left_edge[%u]: %d ",
+                                  *bit_chk & 1, i, left_edge[i]);
+                       debug_cond(DLEVEL == 2, "right_edge[%u]: %d\n", i,
+                                  right_edge[i]);
+                       *bit_chk = *bit_chk >> 1;
+               }
+       }
+
+       /* Check that all bits have a window */
+       for (i = 0; i < per_dqs; i++) {
+               debug_cond(DLEVEL == 2,
+                          "%s:%d write_center: left_edge[%u]: %d right_edge[%u]: %d",
+                          __func__, __LINE__, i, left_edge[i],
+                          i, right_edge[i]);
+               if ((left_edge[i] == dqs_max + 1) ||
+                   (right_edge[i] == dqs_max + 1))
+                       return i + 1;   /* FIXME: If we fail, retval > 0 */
+       }
+
+       return 0;
+}
+
 /* per-bit deskew DQ and center */
 static uint32_t rw_mgr_mem_calibrate_vfifo_center(uint32_t rank_bgn,
        uint32_t write_group, uint32_t read_group, uint32_t test_bgn,
@@ -1803,6 +1963,7 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_center(uint32_t rank_bgn,
        uint32_t stop;
        uint32_t temp_dq_in_delay1, temp_dq_in_delay2;
        uint32_t addr;
+       int ret;
 
        debug("%s:%d: %u %u", __func__, __LINE__, read_group, test_bgn);
 
@@ -1909,132 +2070,38 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_center(uint32_t rank_bgn,
        }
 
        /* Search for the right edge of the window for each bit */
-       for (d = 0; d <= IO_DQS_IN_DELAY_MAX - start_dqs; d++) {
-               scc_mgr_set_dqs_bus_in_delay(read_group, d + start_dqs);
-               if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
-                       uint32_t delay = d + start_dqs_en;
-                       if (delay > IO_DQS_EN_DELAY_MAX)
-                               delay = IO_DQS_EN_DELAY_MAX;
-                       scc_mgr_set_dqs_en_delay(read_group, delay);
-               }
-               scc_mgr_load_dqs(read_group);
-
-               writel(0, &sdr_scc_mgr->update);
-
+       ret = search_right_edge(0, rank_bgn, write_group, read_group,
+                               start_dqs, start_dqs_en,
+                               &bit_chk, &sticky_bit_chk,
+                               left_edge, right_edge, use_read_test);
+       if (ret) {
                /*
-                * Stop searching when the read test doesn't pass AND when
-                * we've seen a passing read on every bit.
+                * Restore delay chain settings before letting the loop
+                * in rw_mgr_mem_calibrate_vfifo to retry different
+                * dqs/ck relationships.
                 */
-               if (use_read_test) {
-                       stop = !rw_mgr_mem_calibrate_read_test(rank_bgn,
-                               read_group, NUM_READ_PB_TESTS, PASS_ONE_BIT,
-                               &bit_chk, 0, 0);
-               } else {
-                       rw_mgr_mem_calibrate_write_test(rank_bgn, write_group,
-                                                       0, PASS_ONE_BIT,
-                                                       &bit_chk, 0);
-                       bit_chk = bit_chk >> (RW_MGR_MEM_DQ_PER_READ_DQS *
-                               (read_group - (write_group *
-                                       RW_MGR_MEM_IF_READ_DQS_WIDTH /
-                                       RW_MGR_MEM_IF_WRITE_DQS_WIDTH)));
-                       stop = (bit_chk == 0);
-               }
-               sticky_bit_chk = sticky_bit_chk | bit_chk;
-               stop = stop && (sticky_bit_chk == param->read_correct_mask);
+               scc_mgr_set_dqs_bus_in_delay(read_group, start_dqs);
+               if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS)
+                       scc_mgr_set_dqs_en_delay(read_group, start_dqs_en);
 
-               debug_cond(DLEVEL == 2, "%s:%d vfifo_center(right): dtap=%u => %u == \
-                          %u && %u", __func__, __LINE__, d,
-                          sticky_bit_chk, param->read_correct_mask, stop);
+               scc_mgr_load_dqs(read_group);
+               writel(0, &sdr_scc_mgr->update);
 
-               if (stop == 1) {
-                       break;
+               debug_cond(DLEVEL == 1,
+                          "%s:%d vfifo_center: failed to find edge [%u]: %d %d",
+                          __func__, __LINE__, i, left_edge[i], right_edge[i]);
+               if (use_read_test) {
+                       set_failing_group_stage(read_group *
+                               RW_MGR_MEM_DQ_PER_READ_DQS + i,
+                               CAL_STAGE_VFIFO,
+                               CAL_SUBSTAGE_VFIFO_CENTER);
                } else {
-                       for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
-                               if (bit_chk & 1) {
-                                       /* Remember a passing test as
-                                       the right_edge */
-                                       right_edge[i] = d;
-                               } else {
-                                       if (d != 0) {
-                                               /* If a right edge has not been
-                                               seen yet, then a future passing
-                                               test will mark this edge as the
-                                               left edge */
-                                               if (right_edge[i] ==
-                                               IO_IO_IN_DELAY_MAX + 1) {
-                                                       left_edge[i] = -(d + 1);
-                                               }
-                                       } else {
-                                               /* d = 0 failed, but it passed
-                                               when testing the left edge,
-                                               so it must be marginal,
-                                               set it to -1 */
-                                               if (right_edge[i] ==
-                                                       IO_IO_IN_DELAY_MAX + 1 &&
-                                                       left_edge[i] !=
-                                                       IO_IO_IN_DELAY_MAX
-                                                       + 1) {
-                                                       right_edge[i] = -1;
-                                               }
-                                               /* If a right edge has not been
-                                               seen yet, then a future passing
-                                               test will mark this edge as the
-                                               left edge */
-                                               else if (right_edge[i] ==
-                                                       IO_IO_IN_DELAY_MAX +
-                                                       1) {
-                                                       left_edge[i] = -(d + 1);
-                                               }
-                                       }
-                               }
-
-                               debug_cond(DLEVEL == 2, "%s:%d vfifo_center[r,\
-                                          d=%u]: ", __func__, __LINE__, d);
-                               debug_cond(DLEVEL == 2, "bit_chk_test=%d left_edge[%u]: %d ",
-                                          (int)(bit_chk & 1), i, left_edge[i]);
-                               debug_cond(DLEVEL == 2, "right_edge[%u]: %d\n", i,
-                                          right_edge[i]);
-                               bit_chk = bit_chk >> 1;
-                       }
-               }
-       }
-
-       /* Check that all bits have a window */
-       for (i = 0; i < RW_MGR_MEM_DQ_PER_READ_DQS; i++) {
-               debug_cond(DLEVEL == 2, "%s:%d vfifo_center: left_edge[%u]: \
-                          %d right_edge[%u]: %d", __func__, __LINE__,
-                          i, left_edge[i], i, right_edge[i]);
-               if ((left_edge[i] == IO_IO_IN_DELAY_MAX + 1) || (right_edge[i]
-                       == IO_IO_IN_DELAY_MAX + 1)) {
-                       /*
-                        * Restore delay chain settings before letting the loop
-                        * in rw_mgr_mem_calibrate_vfifo to retry different
-                        * dqs/ck relationships.
-                        */
-                       scc_mgr_set_dqs_bus_in_delay(read_group, start_dqs);
-                       if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
-                               scc_mgr_set_dqs_en_delay(read_group,
-                                                        start_dqs_en);
-                       }
-                       scc_mgr_load_dqs(read_group);
-                       writel(0, &sdr_scc_mgr->update);
-
-                       debug_cond(DLEVEL == 1, "%s:%d vfifo_center: failed to \
-                                  find edge [%u]: %d %d", __func__, __LINE__,
-                                  i, left_edge[i], right_edge[i]);
-                       if (use_read_test) {
-                               set_failing_group_stage(read_group *
-                                       RW_MGR_MEM_DQ_PER_READ_DQS + i,
-                                       CAL_STAGE_VFIFO,
-                                       CAL_SUBSTAGE_VFIFO_CENTER);
-                       } else {
-                               set_failing_group_stage(read_group *
-                                       RW_MGR_MEM_DQ_PER_READ_DQS + i,
-                                       CAL_STAGE_VFIFO_AFTER_WRITES,
-                                       CAL_SUBSTAGE_VFIFO_CENTER);
-                       }
-                       return 0;
+                       set_failing_group_stage(read_group *
+                               RW_MGR_MEM_DQ_PER_READ_DQS + i,
+                               CAL_STAGE_VFIFO_AFTER_WRITES,
+                               CAL_SUBSTAGE_VFIFO_CENTER);
                }
+               return 0;
        }
 
        /* Find middle of window for each DQ bit */
@@ -2729,6 +2796,8 @@ static uint32_t rw_mgr_mem_calibrate_writes_center(uint32_t rank_bgn,
        uint32_t temp_dq_out1_delay;
        uint32_t addr;
 
+       int ret;
+
        debug("%s:%d %u %u", __func__, __LINE__, write_group, test_bgn);
 
        dm_margin = 0;
@@ -2833,107 +2902,14 @@ static uint32_t rw_mgr_mem_calibrate_writes_center(uint32_t rank_bgn,
        }
 
        /* Search for the right edge of the window for each bit */
-       for (d = 0; d <= IO_IO_OUT1_DELAY_MAX - start_dqs; d++) {
-               scc_mgr_apply_group_dqs_io_and_oct_out1(write_group,
-                                                       d + start_dqs);
-
-               writel(0, &sdr_scc_mgr->update);
-
-               /*
-                * Stop searching when the read test doesn't pass AND when
-                * we've seen a passing read on every bit.
-                */
-               stop = !rw_mgr_mem_calibrate_write_test(rank_bgn, write_group,
-                       0, PASS_ONE_BIT, &bit_chk, 0);
-
-               sticky_bit_chk = sticky_bit_chk | bit_chk;
-               stop = stop && (sticky_bit_chk == param->write_correct_mask);
-
-               debug_cond(DLEVEL == 2, "write_center (right): dtap=%u => %u == \
-                          %u && %u\n", d, sticky_bit_chk,
-                          param->write_correct_mask, stop);
-
-               if (stop == 1) {
-                       if (d == 0) {
-                               for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS;
-                                       i++) {
-                                       /* d = 0 failed, but it passed when
-                                       testing the left edge, so it must be
-                                       marginal, set it to -1 */
-                                       if (right_edge[i] ==
-                                               IO_IO_OUT1_DELAY_MAX + 1 &&
-                                               left_edge[i] !=
-                                               IO_IO_OUT1_DELAY_MAX + 1) {
-                                               right_edge[i] = -1;
-                                       }
-                               }
-                       }
-                       break;
-               } else {
-                       for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
-                               if (bit_chk & 1) {
-                                       /*
-                                        * Remember a passing test as
-                                        * the right_edge.
-                                        */
-                                       right_edge[i] = d;
-                               } else {
-                                       if (d != 0) {
-                                               /*
-                                                * If a right edge has not
-                                                * been seen yet, then a future
-                                                * passing test will mark this
-                                                * edge as the left edge.
-                                                */
-                                               if (right_edge[i] ==
-                                                   IO_IO_OUT1_DELAY_MAX + 1)
-                                                       left_edge[i] = -(d + 1);
-                                       } else {
-                                               /*
-                                                * d = 0 failed, but it passed
-                                                * when testing the left edge,
-                                                * so it must be marginal, set
-                                                * it to -1.
-                                                */
-                                               if (right_edge[i] ==
-                                                   IO_IO_OUT1_DELAY_MAX + 1 &&
-                                                   left_edge[i] !=
-                                                   IO_IO_OUT1_DELAY_MAX + 1)
-                                                       right_edge[i] = -1;
-                                               /*
-                                                * If a right edge has not been
-                                                * seen yet, then a future
-                                                * passing test will mark this
-                                                * edge as the left edge.
-                                                */
-                                               else if (right_edge[i] ==
-                                                       IO_IO_OUT1_DELAY_MAX +
-                                                       1)
-                                                       left_edge[i] = -(d + 1);
-                                       }
-                               }
-                               debug_cond(DLEVEL == 2, "write_center[r,d=%d):", d);
-                               debug_cond(DLEVEL == 2, "bit_chk_test=%d left_edge[%u]: %d",
-                                          (int)(bit_chk & 1), i, left_edge[i]);
-                               debug_cond(DLEVEL == 2, "right_edge[%u]: %d\n", i,
-                                          right_edge[i]);
-                               bit_chk = bit_chk >> 1;
-                       }
-               }
-       }
-
-       /* Check that all bits have a window */
-       for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
-               debug_cond(DLEVEL == 2, "%s:%d write_center: left_edge[%u]: \
-                          %d right_edge[%u]: %d", __func__, __LINE__,
-                          i, left_edge[i], i, right_edge[i]);
-               if ((left_edge[i] == IO_IO_OUT1_DELAY_MAX + 1) ||
-                   (right_edge[i] == IO_IO_OUT1_DELAY_MAX + 1)) {
-                       set_failing_group_stage(test_bgn + i,
-                                               CAL_STAGE_WRITES,
-                                               CAL_SUBSTAGE_WRITES_CENTER);
-                       return 0;
-               }
+       ret = search_right_edge(1, rank_bgn, write_group, 0,
+                               start_dqs, 0,
+                               &bit_chk, &sticky_bit_chk,
+                               left_edge, right_edge, 0);
+       if (ret) {
+               set_failing_group_stage(test_bgn + ret - 1, CAL_STAGE_WRITES,
+                                       CAL_SUBSTAGE_WRITES_CENTER);
+               return 0;
        }
 
        /* Find middle of window for each DQ bit */