ddr: altera: Fix ad-hoc iterative division implementation
[oweals/u-boot.git] / drivers / ddr / altera / sequencer.c
index b2119a69a1ae35979a7d2d97fac7cf2cbcd1100d..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);
@@ -840,12 +844,107 @@ static void delay_for_n_mem_clocks(const uint32_t clocks)
        debug("%s:%d clocks=%u ... end\n", __func__, __LINE__, clocks);
 }
 
-static void rw_mgr_mem_initialize(void)
+/**
+ * rw_mgr_mem_init_load_regs() - Load instruction registers
+ * @cntr0:     Counter 0 value
+ * @cntr1:     Counter 1 value
+ * @cntr2:     Counter 2 value
+ * @jump:      Jump instruction value
+ *
+ * Load instruction registers.
+ */
+static void rw_mgr_mem_init_load_regs(u32 cntr0, u32 cntr1, u32 cntr2, u32 jump)
 {
-       uint32_t r;
        uint32_t grpaddr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
                           RW_MGR_RUN_SINGLE_GROUP_OFFSET;
 
+       /* Load counters */
+       writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(cntr0),
+              &sdr_rw_load_mgr_regs->load_cntr0);
+       writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(cntr1),
+              &sdr_rw_load_mgr_regs->load_cntr1);
+       writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(cntr2),
+              &sdr_rw_load_mgr_regs->load_cntr2);
+
+       /* Load jump address */
+       writel(jump, &sdr_rw_load_jump_mgr_regs->load_jump_add0);
+       writel(jump, &sdr_rw_load_jump_mgr_regs->load_jump_add1);
+       writel(jump, &sdr_rw_load_jump_mgr_regs->load_jump_add2);
+
+       /* Execute count instruction */
+       writel(jump, grpaddr);
+}
+
+/**
+ * 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)
+{
+       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 */
@@ -875,25 +974,9 @@ static void rw_mgr_mem_initialize(void)
         * One possible solution is n = 0 , a = 256 , b = 106 => a = FF,
         * b = 6A
         */
-
-       /* Load counters */
-       writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TINIT_CNTR0_VAL),
-              &sdr_rw_load_mgr_regs->load_cntr0);
-       writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TINIT_CNTR1_VAL),
-              &sdr_rw_load_mgr_regs->load_cntr1);
-       writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TINIT_CNTR2_VAL),
-              &sdr_rw_load_mgr_regs->load_cntr2);
-
-       /* Load jump address */
-       writel(RW_MGR_INIT_RESET_0_CKE_0,
-               &sdr_rw_load_jump_mgr_regs->load_jump_add0);
-       writel(RW_MGR_INIT_RESET_0_CKE_0,
-               &sdr_rw_load_jump_mgr_regs->load_jump_add1);
-       writel(RW_MGR_INIT_RESET_0_CKE_0,
-               &sdr_rw_load_jump_mgr_regs->load_jump_add2);
-
-       /* Execute count instruction */
-       writel(RW_MGR_INIT_RESET_0_CKE_0, grpaddr);
+       rw_mgr_mem_init_load_regs(SEQ_TINIT_CNTR0_VAL, SEQ_TINIT_CNTR1_VAL,
+                                 SEQ_TINIT_CNTR2_VAL,
+                                 RW_MGR_INIT_RESET_0_CKE_0);
 
        /* indicate that memory is stable */
        writel(1, &phy_mgr_cfg->reset_mem_stbl);
@@ -912,73 +995,17 @@ static void rw_mgr_mem_initialize(void)
         * One possible solution is n = 2 , a = 131 , b = 256 => a = 83,
         * b = FF
         */
-
-       /* Load counters */
-       writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TRESET_CNTR0_VAL),
-              &sdr_rw_load_mgr_regs->load_cntr0);
-       writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TRESET_CNTR1_VAL),
-              &sdr_rw_load_mgr_regs->load_cntr1);
-       writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(SEQ_TRESET_CNTR2_VAL),
-              &sdr_rw_load_mgr_regs->load_cntr2);
-
-       /* Load jump address */
-       writel(RW_MGR_INIT_RESET_1_CKE_0,
-               &sdr_rw_load_jump_mgr_regs->load_jump_add0);
-       writel(RW_MGR_INIT_RESET_1_CKE_0,
-               &sdr_rw_load_jump_mgr_regs->load_jump_add1);
-       writel(RW_MGR_INIT_RESET_1_CKE_0,
-               &sdr_rw_load_jump_mgr_regs->load_jump_add2);
-
-       writel(RW_MGR_INIT_RESET_1_CKE_0, grpaddr);
+       rw_mgr_mem_init_load_regs(SEQ_TRESET_CNTR0_VAL, SEQ_TRESET_CNTR1_VAL,
+                                 SEQ_TRESET_CNTR2_VAL,
+                                 RW_MGR_INIT_RESET_1_CKE_0);
 
        /* bring up clock enable */
 
        /* 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);