|
@@ -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 */
|