]> git.sur5r.net Git - u-boot/blobdiff - drivers/ddr/altera/sequencer.c
ddr: altera: Internal mem_calibrate() cleanup part 2
[u-boot] / drivers / ddr / altera / sequencer.c
index a215c20d0d139dac5c480a864926dd8511e1a0cd..e2e7184ffffcbd060967125dd7ac14a26839e3b4 100644 (file)
@@ -154,32 +154,40 @@ static void phy_mgr_initialize(void)
        param->dm_correct_mask = (1 << ratio) - 1;
 }
 
-static void set_rank_and_odt_mask(uint32_t rank, uint32_t odt_mode)
+/**
+ * set_rank_and_odt_mask() - Set Rank and ODT mask
+ * @rank:      Rank mask
+ * @odt_mode:  ODT mode, OFF or READ_WRITE
+ *
+ * Set Rank and ODT mask (On-Die Termination).
+ */
+static void set_rank_and_odt_mask(const u32 rank, const u32 odt_mode)
 {
-       uint32_t odt_mask_0 = 0;
-       uint32_t odt_mask_1 = 0;
-       uint32_t cs_and_odt_mask;
+       u32 odt_mask_0 = 0;
+       u32 odt_mask_1 = 0;
+       u32 cs_and_odt_mask;
 
-       if (odt_mode == RW_MGR_ODT_MODE_READ_WRITE) {
-               if (RW_MGR_MEM_NUMBER_OF_RANKS == 1) {
-                       /*
-                        * 1 Rank
-                        * Read: ODT = 0
-                        * Write: ODT = 1
-                        */
+       if (odt_mode == RW_MGR_ODT_MODE_OFF) {
+               odt_mask_0 = 0x0;
+               odt_mask_1 = 0x0;
+       } else {        /* RW_MGR_ODT_MODE_READ_WRITE */
+               switch (RW_MGR_MEM_NUMBER_OF_RANKS) {
+               case 1: /* 1 Rank */
+                       /* Read: ODT = 0 ; Write: ODT = 1 */
                        odt_mask_0 = 0x0;
                        odt_mask_1 = 0x1;
-               } else if (RW_MGR_MEM_NUMBER_OF_RANKS == 2) {
-                       /* 2 Ranks */
+                       break;
+               case 2: /* 2 Ranks */
                        if (RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM == 1) {
-                               /* - Dual-Slot , Single-Rank
-                                * (1 chip-select per DIMM)
-                                * OR
-                                * - RDIMM, 4 total CS (2 CS per DIMM)
-                                * means 2 DIMM
-                                * Since MEM_NUMBER_OF_RANKS is 2 they are
-                                * both single rank
-                                * with 2 CS each (special for RDIMM)
+                               /*
+                                * - Dual-Slot , Single-Rank (1 CS per DIMM)
+                                *   OR
+                                * - RDIMM, 4 total CS (2 CS per DIMM, 2 DIMM)
+                                *
+                                * Since MEM_NUMBER_OF_RANKS is 2, they
+                                * are both single rank with 2 CS each
+                                * (special for RDIMM).
+                                *
                                 * Read: Turn on ODT on the opposite rank
                                 * Write: Turn on ODT on all ranks
                                 */
@@ -187,19 +195,18 @@ static void set_rank_and_odt_mask(uint32_t rank, uint32_t odt_mode)
                                odt_mask_1 = 0x3;
                        } else {
                                /*
-                                * USER - Single-Slot , Dual-rank DIMMs
-                                * (2 chip-selects per DIMM)
-                                * USER Read: Turn on ODT off on all ranks
-                                * USER Write: Turn on ODT on active rank
+                                * - Single-Slot , Dual-Rank (2 CS per DIMM)
+                                *
+                                * Read: Turn on ODT off on all ranks
+                                * Write: Turn on ODT on active rank
                                 */
                                odt_mask_0 = 0x0;
                                odt_mask_1 = 0x3 & (1 << rank);
                        }
-               } else {
-                       /* 4 Ranks
-                        * Read:
+                       break;
+               case 4: /* 4 Ranks */
+                       /* Read:
                         * ----------+-----------------------+
-                        *           |                       |
                         *           |         ODT           |
                         * Read From +-----------------------+
                         *   Rank    |  3  |  2  |  1  |  0  |
@@ -212,7 +219,6 @@ static void set_rank_and_odt_mask(uint32_t rank, uint32_t odt_mode)
                         *
                         * Write:
                         * ----------+-----------------------+
-                        *           |                       |
                         *           |         ODT           |
                         * Write To  +-----------------------+
                         *   Rank    |  3  |  2  |  1  |  0  |
@@ -241,16 +247,13 @@ static void set_rank_and_odt_mask(uint32_t rank, uint32_t odt_mode)
                                odt_mask_1 = 0xA;
                                break;
                        }
+                       break;
                }
-       } else {
-               odt_mask_0 = 0x0;
-               odt_mask_1 = 0x0;
        }
 
-       cs_and_odt_mask =
-               (0xFF & ~(1 << rank)) |
-               ((0xFF & odt_mask_0) << 8) |
-               ((0xFF & odt_mask_1) << 16);
+       cs_and_odt_mask = (0xFF & ~(1 << rank)) |
+                         ((0xFF & odt_mask_0) << 8) |
+                         ((0xFF & odt_mask_1) << 16);
        writel(cs_and_odt_mask, SDR_PHYGRP_RWMGRGRP_ADDRESS |
                                RW_MGR_SET_CS_AND_ODT_MASK_OFFSET);
 }
@@ -3091,21 +3094,24 @@ static uint32_t rw_mgr_mem_calibrate_writes(uint32_t rank_bgn, uint32_t g,
        return 1;
 }
 
-/* precharge all banks and activate row 0 in bank "000..." and bank "111..." */
+/**
+ * mem_precharge_and_activate() - Precharge all banks and activate
+ *
+ * Precharge all banks and activate row 0 in bank "000..." and bank "111...".
+ */
 static void mem_precharge_and_activate(void)
 {
-       uint32_t r;
+       int r;
 
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
-               if (param->skip_ranks[r]) {
-                       /* request to skip the rank */
+               /* Test if the rank should be skipped. */
+               if (param->skip_ranks[r])
                        continue;
-               }
 
-               /* set rank */
+               /* Set rank. */
                set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
 
-               /* precharge all banks ... */
+               /* Precharge all banks. */
                writel(RW_MGR_PRECHARGE_ALL, SDR_PHYGRP_RWMGRGRP_ADDRESS |
                                             RW_MGR_RUN_SINGLE_GROUP_OFFSET);
 
@@ -3117,7 +3123,7 @@ static void mem_precharge_and_activate(void)
                writel(RW_MGR_ACTIVATE_0_AND_1_WAIT2,
                        &sdr_rw_load_jump_mgr_regs->load_jump_add1);
 
-               /* activate rows */
+               /* Activate rows. */
                writel(RW_MGR_ACTIVATE_0_AND_1, SDR_PHYGRP_RWMGRGRP_ADDRESS |
                                                RW_MGR_RUN_SINGLE_GROUP_OFFSET);
        }
@@ -3163,7 +3169,11 @@ static void mem_init_latency(void)
        writel(wlat, &phy_mgr_cfg->afi_wlat);
 }
 
-/* Set VFIFO and LFIFO to instant-on settings in skip calibration mode */
+/**
+ * @mem_skip_calibrate() - Set VFIFO and LFIFO to instant-on settings
+ *
+ * Set VFIFO and LFIFO to instant-on settings in skip calibration mode.
+ */
 static void mem_skip_calibrate(void)
 {
        uint32_t vfifo_offset;
@@ -3172,7 +3182,7 @@ static void mem_skip_calibrate(void)
        debug("%s:%d\n", __func__, __LINE__);
        /* Need to update every shadow register set used by the interface */
        for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS;
-               r += NUM_RANKS_PER_SHADOW_REG) {
+            r += NUM_RANKS_PER_SHADOW_REG) {
                /*
                 * Set output phase alignment settings appropriate for
                 * skip calibration.
@@ -3209,8 +3219,8 @@ static void mem_skip_calibrate(void)
                         *
                         *    (1.25 * IO_DLL_CHAIN_LENGTH - 2)
                         */
-                       scc_mgr_set_dqdqs_output_phase(i, (1.25 *
-                               IO_DLL_CHAIN_LENGTH - 2));
+                       scc_mgr_set_dqdqs_output_phase(i,
+                                       1.25 * IO_DLL_CHAIN_LENGTH - 2);
                }
                writel(0xff, &sdr_scc_mgr->dqs_ena);
                writel(0xff, &sdr_scc_mgr->dqs_io_ena);
@@ -3236,14 +3246,13 @@ static void mem_skip_calibrate(void)
         * in sequencer.
         */
        vfifo_offset = CALIB_VFIFO_OFFSET;
-       for (j = 0; j < vfifo_offset; j++) {
+       for (j = 0; j < vfifo_offset; j++)
                writel(0xff, &phy_mgr_cmd->inc_vfifo_hard_phy);
-       }
        writel(0, &phy_mgr_cmd->fifo_reset);
 
        /*
-        * For ACV with hard lfifo, we get the skip-cal setting from
-        * generation-time constant.
+        * For Arria V and Cyclone V with hard LFIFO, we get the skip-cal
+        * setting from generation-time constant.
         */
        gbl->curr_read_lat = CALIB_LFIFO_OFFSET;
        writel(gbl->curr_read_lat, &phy_mgr_cfg->phy_rlat);
@@ -3259,7 +3268,9 @@ static uint32_t mem_calibrate(void)
        uint32_t run_groups, current_run;
        uint32_t failing_groups = 0;
        uint32_t group_failed = 0;
-       uint32_t sr_failed = 0;
+
+       const u32 rwdqs_ratio = RW_MGR_MEM_IF_READ_DQS_WIDTH /
+                               RW_MGR_MEM_IF_WRITE_DQS_WIDTH;
 
        debug("%s:%d\n", __func__, __LINE__);
 
@@ -3286,152 +3297,144 @@ static uint32_t mem_calibrate(void)
                scc_set_bypass_mode(i);
        }
 
+       /* Calibration is skipped. */
        if ((dyn_calib_steps & CALIB_SKIP_ALL) == CALIB_SKIP_ALL) {
                /*
                 * Set VFIFO and LFIFO to instant-on settings in skip
                 * calibration mode.
                 */
                mem_skip_calibrate();
-       } else {
-               for (i = 0; i < NUM_CALIB_REPEAT; i++) {
-                       /*
-                        * Zero all delay chain/phase settings for all
-                        * groups and all shadow register sets.
-                        */
-                       scc_mgr_zero_all();
-
-                       run_groups = ~param->skip_groups;
 
-                       for (write_group = 0, write_test_bgn = 0; write_group
-                               < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; write_group++,
-                               write_test_bgn += RW_MGR_MEM_DQ_PER_WRITE_DQS) {
-                               /* Initialized the group failure */
-                               group_failed = 0;
+               /*
+                * Do not remove this line as it makes sure all of our
+                * decisions have been applied.
+                */
+               writel(0, &sdr_scc_mgr->update);
+               return 1;
+       }
 
-                               current_run = run_groups & ((1 <<
-                                       RW_MGR_NUM_DQS_PER_WRITE_GROUP) - 1);
-                               run_groups = run_groups >>
-                                       RW_MGR_NUM_DQS_PER_WRITE_GROUP;
+       /* Calibration is not skipped. */
+       for (i = 0; i < NUM_CALIB_REPEAT; i++) {
+               /*
+                * Zero all delay chain/phase settings for all
+                * groups and all shadow register sets.
+                */
+               scc_mgr_zero_all();
+
+               run_groups = ~param->skip_groups;
+
+               for (write_group = 0, write_test_bgn = 0; write_group
+                       < RW_MGR_MEM_IF_WRITE_DQS_WIDTH; write_group++,
+                       write_test_bgn += RW_MGR_MEM_DQ_PER_WRITE_DQS) {
+                       /* Initialized the group failure */
+                       group_failed = 0;
+
+                       current_run = run_groups & ((1 <<
+                               RW_MGR_NUM_DQS_PER_WRITE_GROUP) - 1);
+                       run_groups = run_groups >>
+                               RW_MGR_NUM_DQS_PER_WRITE_GROUP;
+
+                       if (current_run == 0)
+                               continue;
+
+                       writel(write_group, SDR_PHYGRP_SCCGRP_ADDRESS |
+                                           SCC_MGR_GROUP_COUNTER_OFFSET);
+                       scc_mgr_zero_group(write_group, 0);
+
+                       for (read_group = write_group * rwdqs_ratio,
+                            read_test_bgn = 0;
+                            read_group < (write_group + 1) * rwdqs_ratio && group_failed == 0;
+                            read_group++,
+                            read_test_bgn += RW_MGR_MEM_DQ_PER_READ_DQS) {
+                               if (STATIC_CALIB_STEPS & CALIB_SKIP_VFIFO)
+                                       continue;
 
-                               if (current_run == 0)
+                               /* Calibrate the VFIFO */
+                               if (rw_mgr_mem_calibrate_vfifo(read_group,
+                                                              read_test_bgn))
                                        continue;
 
-                               writel(write_group, SDR_PHYGRP_SCCGRP_ADDRESS |
-                                                   SCC_MGR_GROUP_COUNTER_OFFSET);
-                               scc_mgr_zero_group(write_group, 0);
+                               group_failed = 1;
+                               if (!(gbl->phy_debug_mode_flags & PHY_DEBUG_SWEEP_ALL_GROUPS))
+                                       return 0;
+                       }
+
+                       /* Calibrate the output side */
+                       if (group_failed == 0) {
+                               for (rank_bgn = 0, sr = 0;
+                                    rank_bgn < RW_MGR_MEM_NUMBER_OF_RANKS;
+                                    rank_bgn += NUM_RANKS_PER_SHADOW_REG, sr++) {
+                                       if (STATIC_CALIB_STEPS & CALIB_SKIP_WRITES)
+                                               continue;
+
+                                       /* Not needed in quick mode! */
+                                       if (STATIC_CALIB_STEPS & CALIB_SKIP_DELAY_SWEEPS)
+                                               continue;
+
+                                       /*
+                                        * Determine if this set of ranks
+                                        * should be skipped entirely.
+                                        */
+                                       if (param->skip_shadow_regs[sr])
+                                               continue;
+
+                                       /* Calibrate WRITEs */
+                                       if (rw_mgr_mem_calibrate_writes(rank_bgn,
+                                                       write_group, write_test_bgn))
+                                               continue;
 
+                                       group_failed = 1;
+                                       if (!(gbl->phy_debug_mode_flags & PHY_DEBUG_SWEEP_ALL_GROUPS))
+                                               return 0;
+                               }
+                       }
+
+                       if (group_failed == 0) {
                                for (read_group = write_group *
-                                       RW_MGR_MEM_IF_READ_DQS_WIDTH /
-                                       RW_MGR_MEM_IF_WRITE_DQS_WIDTH,
-                                       read_test_bgn = 0;
-                                       read_group < (write_group + 1) *
-                                       RW_MGR_MEM_IF_READ_DQS_WIDTH /
-                                       RW_MGR_MEM_IF_WRITE_DQS_WIDTH &&
+                               RW_MGR_MEM_IF_READ_DQS_WIDTH /
+                               RW_MGR_MEM_IF_WRITE_DQS_WIDTH,
+                               read_test_bgn = 0;
+                                       read_group < (write_group + 1)
+                                       * RW_MGR_MEM_IF_READ_DQS_WIDTH
+                                       RW_MGR_MEM_IF_WRITE_DQS_WIDTH &&
                                        group_failed == 0;
                                        read_group++, read_test_bgn +=
                                        RW_MGR_MEM_DQ_PER_READ_DQS) {
-                                       /* Calibrate the VFIFO */
                                        if (!((STATIC_CALIB_STEPS) &
-                                               CALIB_SKIP_VFIFO)) {
-                                               if (!rw_mgr_mem_calibrate_vfifo
-                                                       (read_group,
-                                                       read_test_bgn)) {
-                                                       group_failed = 1;
-
-                                                       if (!(gbl->
-                                                       phy_debug_mode_flags &
-                                               PHY_DEBUG_SWEEP_ALL_GROUPS)) {
-                                                               return 0;
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               /* Calibrate the output side */
-                               if (group_failed == 0)  {
-                                       for (rank_bgn = 0, sr = 0; rank_bgn
-                                               < RW_MGR_MEM_NUMBER_OF_RANKS;
-                                               rank_bgn +=
-                                               NUM_RANKS_PER_SHADOW_REG,
-                                               ++sr) {
-                                               sr_failed = 0;
-                                               if (!((STATIC_CALIB_STEPS) &
                                                CALIB_SKIP_WRITES)) {
-                                                       if ((STATIC_CALIB_STEPS)
-                                               & CALIB_SKIP_DELAY_SWEEPS) {
-                                               /* not needed in quick mode! */
-                                                       } else {
-                                               /*
-                                                * Determine if this set of
-                                                * ranks should be skipped
-                                                * entirely.
-                                                */
-                                       if (!param->skip_shadow_regs[sr]) {
-                                               if (!rw_mgr_mem_calibrate_writes
-                                               (rank_bgn, write_group,
-                                               write_test_bgn)) {
-                                                       sr_failed = 1;
-                                                       if (!(gbl->
-                                                       phy_debug_mode_flags &
-                                               PHY_DEBUG_SWEEP_ALL_GROUPS)) {
-                                                               return 0;
-                                                                       }
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                               if (sr_failed != 0)
-                                                       group_failed = 1;
-                                       }
-                               }
+                               if (!rw_mgr_mem_calibrate_vfifo_end
+                                       (read_group, read_test_bgn)) {
+                                               group_failed = 1;
 
-                               if (group_failed == 0) {
-                                       for (read_group = write_group *
-                                       RW_MGR_MEM_IF_READ_DQS_WIDTH /
-                                       RW_MGR_MEM_IF_WRITE_DQS_WIDTH,
-                                       read_test_bgn = 0;
-                                               read_group < (write_group + 1)
-                                               * RW_MGR_MEM_IF_READ_DQS_WIDTH
-                                               / RW_MGR_MEM_IF_WRITE_DQS_WIDTH &&
-                                               group_failed == 0;
-                                               read_group++, read_test_bgn +=
-                                               RW_MGR_MEM_DQ_PER_READ_DQS) {
-                                               if (!((STATIC_CALIB_STEPS) &
-                                                       CALIB_SKIP_WRITES)) {
-                                       if (!rw_mgr_mem_calibrate_vfifo_end
-                                               (read_group, read_test_bgn)) {
-                                                       group_failed = 1;
-
-                                               if (!(gbl->phy_debug_mode_flags
-                                               & PHY_DEBUG_SWEEP_ALL_GROUPS)) {
-                                                               return 0;
-                                                               }
+                                       if (!(gbl->phy_debug_mode_flags
+                                       & PHY_DEBUG_SWEEP_ALL_GROUPS)) {
+                                                       return 0;
                                                        }
                                                }
                                        }
                                }
-
-                               if (group_failed != 0)
-                                       failing_groups++;
                        }
 
+                       if (group_failed != 0)
+                               failing_groups++;
+               }
+
+               /*
+                * USER If there are any failing groups then report
+                * the failure.
+                */
+               if (failing_groups != 0)
+                       return 0;
+
+               /* Calibrate the LFIFO */
+               if (!((STATIC_CALIB_STEPS) & CALIB_SKIP_LFIFO)) {
                        /*
-                        * USER If there are any failing groups then report
-                        * the failure.
+                        * If we're skipping groups as part of debug,
+                        * don't calibrate LFIFO.
                         */
-                       if (failing_groups != 0)
-                               return 0;
-
-                       /* Calibrate the LFIFO */
-                       if (!((STATIC_CALIB_STEPS) & CALIB_SKIP_LFIFO)) {
-                               /*
-                                * If we're skipping groups as part of debug,
-                                * don't calibrate LFIFO.
-                                */
-                               if (param->skip_groups == 0) {
-                                       if (!rw_mgr_mem_calibrate_lfifo())
-                                               return 0;
-                               }
+                       if (param->skip_groups == 0) {
+                               if (!rw_mgr_mem_calibrate_lfifo())
+                                       return 0;
                        }
                }
        }