ddr: altera: Fix ad-hoc iterative division implementation
[oweals/u-boot.git] / drivers / ddr / altera / sequencer.c
index 2d3f44639aaf1c993cdd9aac4d2e5bae8c635156..28e32ff57501b797712d5fdfce159e832a401501 100644 (file)
@@ -732,14 +732,18 @@ scc_mgr_apply_group_all_out_delay_add_all_ranks(const u32 write_group,
        }
 }
 
-/* optimization used to recover some slots in ddr3 inst_rom */
-/* could be applied to other protocols if we wanted to */
+/**
+ * set_jump_as_return() - Return instruction optimization
+ *
+ * Optimization used to recover some slots in ddr3 inst_rom could be
+ * applied to other protocols if we wanted to
+ */
 static void set_jump_as_return(void)
 {
        /*
-        * to save space, we replace return with jump to special shared
+        * To save space, we replace return with jump to special shared
         * RETURN instruction so we set the counter to large value so that
-        * we always jump
+        * we always jump.
         */
        writel(0xff, &sdr_rw_load_mgr_regs->load_cntr0);
        writel(RW_MGR_RETURN, &sdr_rw_load_jump_mgr_regs->load_jump_add0);
@@ -871,12 +875,76 @@ static void rw_mgr_mem_init_load_regs(u32 cntr0, u32 cntr1, u32 cntr2, u32 jump)
        writel(jump, grpaddr);
 }
 
-static void rw_mgr_mem_initialize(void)
+/**
+ * rw_mgr_mem_load_user() - Load user calibration values
+ * @fin1:      Final instruction 1
+ * @fin2:      Final instruction 2
+ * @precharge: If 1, precharge the banks at the end
+ *
+ * Load user calibration values and optionally precharge the banks.
+ */
+static void rw_mgr_mem_load_user(const u32 fin1, const u32 fin2,
+                                const int precharge)
 {
-       uint32_t r;
-       uint32_t grpaddr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
-                          RW_MGR_RUN_SINGLE_GROUP_OFFSET;
+       u32 grpaddr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
+                     RW_MGR_RUN_SINGLE_GROUP_OFFSET;
+       u32 r;
+
+       for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
+               if (param->skip_ranks[r]) {
+                       /* request to skip the rank */
+                       continue;
+               }
+
+               /* set rank */
+               set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
+
+               /* precharge all banks ... */
+               if (precharge)
+                       writel(RW_MGR_PRECHARGE_ALL, grpaddr);
+
+               /*
+                * USER Use Mirror-ed commands for odd ranks if address
+                * mirrorring is on
+                */
+               if ((RW_MGR_MEM_ADDRESS_MIRRORING >> r) & 0x1) {
+                       set_jump_as_return();
+                       writel(RW_MGR_MRS2_MIRR, grpaddr);
+                       delay_for_n_mem_clocks(4);
+                       set_jump_as_return();
+                       writel(RW_MGR_MRS3_MIRR, grpaddr);
+                       delay_for_n_mem_clocks(4);
+                       set_jump_as_return();
+                       writel(RW_MGR_MRS1_MIRR, grpaddr);
+                       delay_for_n_mem_clocks(4);
+                       set_jump_as_return();
+                       writel(fin1, grpaddr);
+               } else {
+                       set_jump_as_return();
+                       writel(RW_MGR_MRS2, grpaddr);
+                       delay_for_n_mem_clocks(4);
+                       set_jump_as_return();
+                       writel(RW_MGR_MRS3, grpaddr);
+                       delay_for_n_mem_clocks(4);
+                       set_jump_as_return();
+                       writel(RW_MGR_MRS1, grpaddr);
+                       set_jump_as_return();
+                       writel(fin2, grpaddr);
+               }
+
+               if (precharge)
+                       continue;
+
+               set_jump_as_return();
+               writel(RW_MGR_ZQCL, grpaddr);
+
+               /* tZQinit = tDLLK = 512 ck cycles */
+               delay_for_n_mem_clocks(512);
+       }
+}
 
+static void rw_mgr_mem_initialize(void)
+{
        debug("%s:%d\n", __func__, __LINE__);
 
        /* The reset / cke part of initialization is broadcasted to all ranks */
@@ -936,49 +1004,8 @@ static void rw_mgr_mem_initialize(void)
        /* tXRP < 250 ck cycles */
        delay_for_n_mem_clocks(250);
 
-       for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
-               if (param->skip_ranks[r]) {
-                       /* request to skip the rank */
-                       continue;
-               }
-
-               /* set rank */
-               set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
-
-               /*
-                * USER Use Mirror-ed commands for odd ranks if address
-                * mirrorring is on
-                */
-               if ((RW_MGR_MEM_ADDRESS_MIRRORING >> r) & 0x1) {
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS2_MIRR, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS3_MIRR, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS1_MIRR, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS0_DLL_RESET_MIRR, grpaddr);
-               } else {
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS2, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS3, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS1, grpaddr);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS0_DLL_RESET, grpaddr);
-               }
-               set_jump_as_return();
-               writel(RW_MGR_ZQCL, grpaddr);
-
-               /* tZQinit = tDLLK = 512 ck cycles */
-               delay_for_n_mem_clocks(512);
-       }
+       rw_mgr_mem_load_user(RW_MGR_MRS0_DLL_RESET_MIRR, RW_MGR_MRS0_DLL_RESET,
+                            0);
 }
 
 /*
@@ -987,58 +1014,12 @@ static void rw_mgr_mem_initialize(void)
  */
 static void rw_mgr_mem_handoff(void)
 {
-       uint32_t r;
-       uint32_t grpaddr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
-                          RW_MGR_RUN_SINGLE_GROUP_OFFSET;
-
-       debug("%s:%d\n", __func__, __LINE__);
-       for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
-               if (param->skip_ranks[r])
-                       /* request to skip the rank */
-                       continue;
-               /* set rank */
-               set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
-
-               /* precharge all banks ... */
-               writel(RW_MGR_PRECHARGE_ALL, grpaddr);
-
-               /* load up MR settings specified by user */
-
-               /*
-                * Use Mirror-ed commands for odd ranks if address
-                * mirrorring is on
-                */
-               if ((RW_MGR_MEM_ADDRESS_MIRRORING >> r) & 0x1) {
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS2_MIRR, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS3_MIRR, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS1_MIRR, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS0_USER_MIRR, grpaddr);
-               } else {
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS2, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS3, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS1, grpaddr);
-                       delay_for_n_mem_clocks(4);
-                       set_jump_as_return();
-                       writel(RW_MGR_MRS0_USER, grpaddr);
-               }
-               /*
-                * USER  need to wait tMOD (12CK or 15ns) time before issuing
-                * other commands, but we will have plenty of NIOS cycles before
-                * actual handoff so its okay.
-                */
-       }
+       rw_mgr_mem_load_user(RW_MGR_MRS0_USER_MIRR, RW_MGR_MRS0_USER, 1);
+       /*
+        * USER  need to wait tMOD (12CK or 15ns) time before issuing
+        * other commands, but we will have plenty of NIOS cycles before
+        * actual handoff so its okay.
+        */
 }
 
 /*
@@ -2204,7 +2185,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo(uint32_t read_group,
 {
        uint32_t p, d, rank_bgn, sr;
        uint32_t dtaps_per_ptap;
-       uint32_t tmp_delay;
        uint32_t bit_chk;
        uint32_t grp_calibrated;
        uint32_t write_group, write_test_bgn;
@@ -2219,14 +2199,8 @@ static uint32_t rw_mgr_mem_calibrate_vfifo(uint32_t read_group,
        write_test_bgn = test_bgn;
 
        /* USER Determine number of delay taps for each phase tap */
-       dtaps_per_ptap = 0;
-       tmp_delay = 0;
-       while (tmp_delay < IO_DELAY_PER_OPA_TAP) {
-               dtaps_per_ptap++;
-               tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP;
-       }
-       dtaps_per_ptap--;
-       tmp_delay = 0;
+       dtaps_per_ptap = DIV_ROUND_UP(IO_DELAY_PER_OPA_TAP,
+                                     IO_DELAY_PER_DQS_EN_DCHAIN_TAP) - 1;
 
        /* update info for sims */
        reg_file_set_group(read_group);