<p>Tristan Hsieh has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/28842">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">mediatek/mt8183: Add DDR driver of tx rx window perbit cal part<br><br>BUG=b:80501386<br>BRANCH=none<br>TEST=Boots correctly on Kukui, and inits DRAM successfully with related<br>     patches.<br><br>Change-Id: I4434897864993e254e1362416316470083351493<br>Signed-off-by: Huayang Duan <huayang.duan@mediatek.com><br>---<br>M src/soc/mediatek/mt8183/dramc_pi_calibration_api.c<br>M src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h<br>M src/soc/mediatek/mt8183/include/soc/memlayout.ld<br>3 files changed, 844 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/42/28842/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c</span><br><span>index 159d72a..f6ab9a0 100644</span><br><span>--- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c</span><br><span>+++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c</span><br><span>@@ -20,6 +20,81 @@</span><br><span> #include <soc/dramc_register.h></span><br><span> #include <soc/dramc_pi_api.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+     RX_VREF_BEGIN = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+    RX_VREF_END = 12,</span><br><span style="color: hsl(120, 100%, 40%);">+     RX_VREF_STEP = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+     TX_VREF_BEGIN = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+    TX_VREF_END = 18,</span><br><span style="color: hsl(120, 100%, 40%);">+     TX_VREF_STEP = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+       FIRST_DQ_DELAY = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+   FIRST_DQS_DELAY = -27,</span><br><span style="color: hsl(120, 100%, 40%);">+        MAX_DQDLY_TAPS = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+  MAX_RX_DQDLY_TAPS = 63,</span><br><span style="color: hsl(120, 100%, 40%);">+       MAX_TX_DQDLY_TAPS = 200,</span><br><span style="color: hsl(120, 100%, 40%);">+      MAX_TX_DQSDLY_TAPS = 63,</span><br><span style="color: hsl(120, 100%, 40%);">+      MAX_RX_DQSDLY_TAPS = 26</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+ RX_WIN_RD_DQC = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+    RX_WIN_TEST_ENG,</span><br><span style="color: hsl(120, 100%, 40%);">+      TX_WIN_DQ_ONLY,</span><br><span style="color: hsl(120, 100%, 40%);">+       TX_WIN_DQ_DQM,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum {</span><br><span style="color: hsl(120, 100%, 40%);">+  RX_DQ = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+    RX_DQM,</span><br><span style="color: hsl(120, 100%, 40%);">+       RX_DQS,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct dqdqs_perbit_dly {</span><br><span style="color: hsl(120, 100%, 40%);">+      s16 first_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+      s16 last_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+       s16 first_dqsdly;</span><br><span style="color: hsl(120, 100%, 40%);">+     s16 last_dqsdly;</span><br><span style="color: hsl(120, 100%, 40%);">+      s16 best_first_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+ s16 best_last_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+  s16 best_first_dqsdly;</span><br><span style="color: hsl(120, 100%, 40%);">+        s16 best_last_dqsdly;</span><br><span style="color: hsl(120, 100%, 40%);">+ s16 best_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+       s16 best_dqsdly;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct vref_perbit_dly {</span><br><span style="color: hsl(120, 100%, 40%);">+      u8 vref;</span><br><span style="color: hsl(120, 100%, 40%);">+      u16 max_win;</span><br><span style="color: hsl(120, 100%, 40%);">+  u16 min_win;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct dqdqs_perbit_dly perbit_dly[DQ_DATA_WIDTH];</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct tx_dly_tune {</span><br><span style="color: hsl(120, 100%, 40%);">+        u8 fine_tune;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 coarse_tune_large;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 coarse_tune_small;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 coarse_tune_large_oen;</span><br><span style="color: hsl(120, 100%, 40%);">+     u8 coarse_tune_small_oen;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct per_byte_dly {</span><br><span style="color: hsl(120, 100%, 40%);">+        u16 max_center;</span><br><span style="color: hsl(120, 100%, 40%);">+       u16 min_center;</span><br><span style="color: hsl(120, 100%, 40%);">+       u16 final_dly;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct per_bit_dly {</span><br><span style="color: hsl(120, 100%, 40%);">+    s16 first_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+       s16 last_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+        s16 win_center;</span><br><span style="color: hsl(120, 100%, 40%);">+       u16 win_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ u16 best_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+extern const u8 phy_mapping[CHANNEL_MAX][16];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void auto_refresh_switch(u8 chn, u8 option)</span><br><span> {</span><br><span>      clrsetbits_le32(&ch[chn].ao.refctrl0, 1 << REFCTRL0_REFDIS_SHIFT,</span><br><span>@@ -863,6 +938,769 @@</span><br><span>  dram_phy_reset(chn);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_rd_dqc_init(u8 chn, u8 rank)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      u8 *lpddr_phy_mapping;</span><br><span style="color: hsl(120, 100%, 40%);">+        u16 temp_value = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   u8 mr15_golden_value = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     u8 mr20_golden_value = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (u8 b = 0; b < 2; b++)</span><br><span style="color: hsl(120, 100%, 40%);">+         clrbits_le32(&ch[chn].phy.shu[0].b[b].dq[7],</span><br><span style="color: hsl(120, 100%, 40%);">+                   0x1 << SHU1_BX_DQ7_R_DMDQMDBI_SHU_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        clrsetbits_le32(&ch[chn].ao.mrs,</span><br><span style="color: hsl(120, 100%, 40%);">+          MRS_MRSRK_MASK, rank << MRS_MRSRK_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+       setbits_le32(&ch[chn].ao.mpc_option,</span><br><span style="color: hsl(120, 100%, 40%);">+              0x1 << MPC_OPTION_MPCRKEN_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     lpddr_phy_mapping = (u8 *)phy_mapping[chn];</span><br><span style="color: hsl(120, 100%, 40%);">+   for (u8 i = 0; i < 16; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+                temp_value |= ((0x5555 >> i) & 0x1) << lpddr_phy_mapping[i];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        mr15_golden_value = (u8) temp_value & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+       mr20_golden_value = (u8) (temp_value >> 8) & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+  clrsetbits_le32(&ch[chn].ao.mr_golden,</span><br><span style="color: hsl(120, 100%, 40%);">+            MR_GOLDEN_MR15_GOLDEN_MASK | MR_GOLDEN_MR20_GOLDEN_MASK,</span><br><span style="color: hsl(120, 100%, 40%);">+              mr15_golden_value << 8 | mr20_golden_value);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static u32 dramc_rd_dqc_run(u8 chn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       u16 timeout_cnt = 100;</span><br><span style="color: hsl(120, 100%, 40%);">+        u8 response;</span><br><span style="color: hsl(120, 100%, 40%);">+  u32 result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ setbits_le32(&ch[chn].ao.spcmdctrl, 1 << SPCMDCTRL_RDDQCDIS_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+ setbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_RDDQCEN_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+  do {</span><br><span style="color: hsl(120, 100%, 40%);">+          response = read32(&ch[chn].nao.spcmdresp) &</span><br><span style="color: hsl(120, 100%, 40%);">+                   (0x1 << SPCMDRESP_RDDQC_RESPONSE_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+                timeout_cnt--;</span><br><span style="color: hsl(120, 100%, 40%);">+                udelay(1);</span><br><span style="color: hsl(120, 100%, 40%);">+    } while ((response == 0) && (timeout_cnt > 0));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (timeout_cnt == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+         dramc_dbg("[RxWinRDDQC] Resp fail (time out)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ result = read32(&ch[chn].nao.rdqc_cmp);</span><br><span style="color: hsl(120, 100%, 40%);">+   clrbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_RDDQCEN_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+  clrbits_le32(&ch[chn].ao.spcmdctrl, 1 << SPCMDCTRL_RDDQCDIS_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return result;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_rd_dqc_end(u8 chn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  clrsetbits_le32(&ch[chn].ao.mrs, MRS_MRSRK_MASK, 0 << MRS_MRSRK_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_rx_vref_enable(u8 chn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   setbits_le32(&ch[chn].phy.b[0].dq[5],</span><br><span style="color: hsl(120, 100%, 40%);">+             0x1 << B0_DQ5_RG_RX_ARDQ_VREF_EN_B0_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+     setbits_le32(&ch[chn].phy.b[1].dq[5],</span><br><span style="color: hsl(120, 100%, 40%);">+             0x1 << B1_DQ5_RG_RX_ARDQ_VREF_EN_B1_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_set_rx_vref(u8 chn, u8 value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    for (u8 b = 0; b < 2; b++)</span><br><span style="color: hsl(120, 100%, 40%);">+         clrsetbits_le32(&ch[chn].phy.shu[0].b[b].dq[5],</span><br><span style="color: hsl(120, 100%, 40%);">+                   SHU1_BX_DQ5_RG_RX_ARDQ_VREF_SEL_B0_MASK,</span><br><span style="color: hsl(120, 100%, 40%);">+                      value << SHU1_BX_DQ5_RG_RX_ARDQ_VREF_SEL_B0_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_set_tx_vref(u8 chn, u8 rank, u8 value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   dramc_mode_reg_write_by_rank(chn, rank, 14, value | 0 << 6);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_set_vref(u8 chn, u8 rank, u8 cal_type, u8 vref)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cal_type == RX_WIN_TEST_ENG)</span><br><span style="color: hsl(120, 100%, 40%);">+              dramc_set_rx_vref(chn, vref);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+          dramc_set_tx_vref(chn, rank, vref);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_transfer_dly_tune(u8 chn, u32 dly,</span><br><span style="color: hsl(120, 100%, 40%);">+                struct tx_dly_tune *dly_tune)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      u16 tmp_val;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        dly_tune->fine_tune = dly & (TX_DQ_COARSE_TUNE_TO_FINE_TUNE_TAP - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        tmp_val = (dly / TX_DQ_COARSE_TUNE_TO_FINE_TUNE_TAP) << 1;</span><br><span style="color: hsl(120, 100%, 40%);">+      dly_tune->coarse_tune_small = tmp_val - ((tmp_val >> 3) << 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ dly_tune->coarse_tune_large = tmp_val >> 3;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        tmp_val -= 4;</span><br><span style="color: hsl(120, 100%, 40%);">+ dly_tune->coarse_tune_small_oen = tmp_val - ((tmp_val >> 3) << 3);</span><br><span style="color: hsl(120, 100%, 40%);">+     dly_tune->coarse_tune_large_oen = tmp_val >> 3;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void set_rx_dly_factor(u8 chn, u8 rank, u8 type, u32 val)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    u8 i;</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 tmp, mask;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (type) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case RX_DQ:</span><br><span style="color: hsl(120, 100%, 40%);">+           tmp = (val << 24 | val << 16 | val << 8 | val);</span><br><span style="color: hsl(120, 100%, 40%);">+             for (i = 2; i < 6; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  write32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[i], tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+                    write32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[i], tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case RX_DQM:</span><br><span style="color: hsl(120, 100%, 40%);">+          tmp = (val << 8 | val);</span><br><span style="color: hsl(120, 100%, 40%);">+         mask = SHU1_B0_DQ6_RK_RX_ARDQM0_F_DLY_B0_MASK |</span><br><span style="color: hsl(120, 100%, 40%);">+                   SHU1_B0_DQ6_RK_RX_ARDQM0_R_DLY_B0_MASK;</span><br><span style="color: hsl(120, 100%, 40%);">+           clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[6],</span><br><span style="color: hsl(120, 100%, 40%);">+                  mask, tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+           clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[6],</span><br><span style="color: hsl(120, 100%, 40%);">+                  mask, tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case RX_DQS:</span><br><span style="color: hsl(120, 100%, 40%);">+          tmp = (val << 24 | val << 16);</span><br><span style="color: hsl(120, 100%, 40%);">+            mask = SHU1_B0_DQ6_RK_RX_ARDQS0_F_DLY_B0_MASK |</span><br><span style="color: hsl(120, 100%, 40%);">+                       SHU1_B0_DQ6_RK_RX_ARDQS0_R_DLY_B0_MASK;</span><br><span style="color: hsl(120, 100%, 40%);">+               clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[0].dq[6],</span><br><span style="color: hsl(120, 100%, 40%);">+                  mask, tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+           clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[1].dq[6],</span><br><span style="color: hsl(120, 100%, 40%);">+                  mask, tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void set_tx_dly_factor(u8 chn, u8 rank, u8 type, u32 curr_val)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct tx_dly_tune dly_tune = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+    u32 coarse_tune_large = 0, coarse_tune_large_oen = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 coarse_tune_small = 0, coarse_tune_small_oen = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       dramc_transfer_dly_tune(chn, curr_val, &dly_tune);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (u8 i = 0; i < 4; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+               coarse_tune_large += dly_tune.coarse_tune_large << (i * 4);</span><br><span style="color: hsl(120, 100%, 40%);">+             coarse_tune_large_oen +=</span><br><span style="color: hsl(120, 100%, 40%);">+                      dly_tune.coarse_tune_large_oen << (i * 4);</span><br><span style="color: hsl(120, 100%, 40%);">+              coarse_tune_small += dly_tune.coarse_tune_small << (i * 4);</span><br><span style="color: hsl(120, 100%, 40%);">+             coarse_tune_small_oen +=</span><br><span style="color: hsl(120, 100%, 40%);">+                      dly_tune.coarse_tune_small_oen << (i * 4);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (type == TX_WIN_DQ_DQM)</span><br><span style="color: hsl(120, 100%, 40%);">+            dramc_dbg("%3d |%d  %d  %2d | [0]", curr_val,</span><br><span style="color: hsl(120, 100%, 40%);">+               dly_tune.coarse_tune_large,</span><br><span style="color: hsl(120, 100%, 40%);">+           dly_tune.coarse_tune_small, dly_tune.fine_tune);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (type != TX_WIN_DQ_DQM && type != TX_WIN_DQ_ONLY)</span><br><span style="color: hsl(120, 100%, 40%);">+          return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[0],</span><br><span style="color: hsl(120, 100%, 40%);">+          (coarse_tune_large_oen << 16) | coarse_tune_large);</span><br><span style="color: hsl(120, 100%, 40%);">+     write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[2],</span><br><span style="color: hsl(120, 100%, 40%);">+          (coarse_tune_small_oen << 16) | coarse_tune_small);</span><br><span style="color: hsl(120, 100%, 40%);">+     for (u8 b = 0; b < 2; b++)</span><br><span style="color: hsl(120, 100%, 40%);">+         clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[b].dq[7],</span><br><span style="color: hsl(120, 100%, 40%);">+                  FINE_TUNE_DQ_MASK, dly_tune.fine_tune << 8);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (type == TX_WIN_DQ_DQM) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* large coarse_tune setting */</span><br><span style="color: hsl(120, 100%, 40%);">+               write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[1],</span><br><span style="color: hsl(120, 100%, 40%);">+                  (coarse_tune_large_oen << 16) | coarse_tune_large);</span><br><span style="color: hsl(120, 100%, 40%);">+             write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[3],</span><br><span style="color: hsl(120, 100%, 40%);">+                  (coarse_tune_small_oen << 16) | coarse_tune_small);</span><br><span style="color: hsl(120, 100%, 40%);">+             /* fine_tune delay setting */</span><br><span style="color: hsl(120, 100%, 40%);">+         for (u8 b = 0; b < 2; b++)</span><br><span style="color: hsl(120, 100%, 40%);">+                 clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[b].dq[7],</span><br><span style="color: hsl(120, 100%, 40%);">+                          FINE_TUNE_DQM_MASK, dly_tune.fine_tune << 16);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static u32 dramc_get_smallest_dqs_dly(u8 chn, u8 rank,</span><br><span style="color: hsl(120, 100%, 40%);">+                const struct sdram_params *params)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 min_dly = 0xffff;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       for (size_t i = 0; i < DQS_NUMBER; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+            min_dly = MIN(min_dly, params->wr_level[chn][rank][i]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return DQS_DELAY + min_dly;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_get_dly_range(u8 chn, u8 rank,  u8 cal_type, u16 *pre_cal,</span><br><span style="color: hsl(120, 100%, 40%);">+              s16 *begin, s16 *end, const struct sdram_params *params)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   u16 pre_dq_dly;</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (cal_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case RX_WIN_RD_DQC:</span><br><span style="color: hsl(120, 100%, 40%);">+   case RX_WIN_TEST_ENG:</span><br><span style="color: hsl(120, 100%, 40%);">+         *begin = FIRST_DQS_DELAY;</span><br><span style="color: hsl(120, 100%, 40%);">+             *end = MAX_RX_DQDLY_TAPS;</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case TX_WIN_DQ_DQM:</span><br><span style="color: hsl(120, 100%, 40%);">+           *begin = dramc_get_smallest_dqs_dly(chn, rank, params);</span><br><span style="color: hsl(120, 100%, 40%);">+               *end = *begin + 256;</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case TX_WIN_DQ_ONLY:</span><br><span style="color: hsl(120, 100%, 40%);">+          pre_dq_dly = MIN(pre_cal[0], pre_cal[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+             pre_dq_dly = (pre_dq_dly > 24) ? (pre_dq_dly - 24) : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            *begin = pre_dq_dly;</span><br><span style="color: hsl(120, 100%, 40%);">+          *end = *begin + 64;</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_check_dqdqs_win(struct dqdqs_perbit_dly *p,</span><br><span style="color: hsl(120, 100%, 40%);">+         u16 dly_step, u16 last_step, u32 fail_bit, u8 flag)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        s16 pass_win, best_pass_win;</span><br><span style="color: hsl(120, 100%, 40%);">+  s16 *first_dly_pass, *last_dly_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+  s16 *best_first_pass, *best_last_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (flag == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              first_dly_pass = &(p->first_dqsdly);</span><br><span style="color: hsl(120, 100%, 40%);">+           last_dly_pass = &(p->last_dqsdly);</span><br><span style="color: hsl(120, 100%, 40%);">+             best_first_pass = &(p->best_first_dqsdly);</span><br><span style="color: hsl(120, 100%, 40%);">+             best_last_pass = &(p->best_last_dqsdly);</span><br><span style="color: hsl(120, 100%, 40%);">+       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              first_dly_pass = &(p->first_dqdly);</span><br><span style="color: hsl(120, 100%, 40%);">+            last_dly_pass = &(p->last_dqdly);</span><br><span style="color: hsl(120, 100%, 40%);">+              best_first_pass = &(p->best_first_dqdly);</span><br><span style="color: hsl(120, 100%, 40%);">+              best_last_pass = &(p->best_last_dqdly);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (fail_bit == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (*first_dly_pass == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* first  pass delay tap */</span><br><span style="color: hsl(120, 100%, 40%);">+                   *first_dly_pass = dly_step;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+             if ((*last_dly_pass == -2) && (dly_step == last_step)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* pass to the last tap */</span><br><span style="color: hsl(120, 100%, 40%);">+                    *last_dly_pass = dly_step;</span><br><span style="color: hsl(120, 100%, 40%);">+                    pass_win = *last_dly_pass - *first_dly_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+                  best_pass_win = *best_last_pass - *best_first_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (pass_win > best_pass_win) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            *best_last_pass = *last_dly_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+                             *best_first_pass = *first_dly_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+                   }</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* clear to find the next pass range if it has */</span><br><span style="color: hsl(120, 100%, 40%);">+                     *first_dly_pass = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                 *last_dly_pass = -2;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              if ((*first_dly_pass != -1)</span><br><span style="color: hsl(120, 100%, 40%);">+                           && (*last_dly_pass == -2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  *last_dly_pass = dly_step - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                        pass_win = *last_dly_pass - *first_dly_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+                  best_pass_win = *best_last_pass - *best_first_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (pass_win > best_pass_win) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            *best_last_pass = *last_dly_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+                             *best_first_pass = *first_dly_pass;</span><br><span style="color: hsl(120, 100%, 40%);">+                   }</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* clear to find the next pass range if it has */</span><br><span style="color: hsl(120, 100%, 40%);">+                     *first_dly_pass = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                 *last_dly_pass = -2;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_set_vref_dly(struct vref_perbit_dly *vref_dly,</span><br><span style="color: hsl(120, 100%, 40%);">+              u8 vref, u32 win_size_sum, struct dqdqs_perbit_dly delay[])</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct dqdqs_perbit_dly *perbit_dly = vref_dly->perbit_dly;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      vref_dly->max_win = win_size_sum;</span><br><span style="color: hsl(120, 100%, 40%);">+  vref_dly->vref = vref;</span><br><span style="color: hsl(120, 100%, 40%);">+     for (u8 bit = 0; bit < DQ_DATA_WIDTH; bit++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             perbit_dly[bit].best_dqdly = delay[bit].best_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+           perbit_dly[bit].best_first_dqdly = delay[bit].best_first_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+               perbit_dly[bit].best_last_dqdly = delay[bit].best_last_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+         perbit_dly[bit].best_first_dqsdly =</span><br><span style="color: hsl(120, 100%, 40%);">+                   delay[bit].best_first_dqsdly;</span><br><span style="color: hsl(120, 100%, 40%);">+         perbit_dly[bit].best_last_dqsdly = delay[bit].best_last_dqsdly;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int dramk_calc_best_vref(u8 cal_type, u8 vref,</span><br><span style="color: hsl(120, 100%, 40%);">+         struct vref_perbit_dly *vref_dly,</span><br><span style="color: hsl(120, 100%, 40%);">+             struct dqdqs_perbit_dly delay[])</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   u8 bit;</span><br><span style="color: hsl(120, 100%, 40%);">+       u32 win_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 win_size_sum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ static u32 min_win_size_vref;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (cal_type == RX_WIN_TEST_ENG) {</span><br><span style="color: hsl(120, 100%, 40%);">+            for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        win_size_sum += (delay[bit].best_last_dqdly -</span><br><span style="color: hsl(120, 100%, 40%);">+                                  delay[bit].best_first_dqdly + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                    win_size_sum += (delay[bit].best_last_dqsdly -</span><br><span style="color: hsl(120, 100%, 40%);">+                                         delay[bit].best_first_dqsdly + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (win_size_sum > vref_dly->max_win)</span><br><span style="color: hsl(120, 100%, 40%);">+                   dramc_set_vref_dly(vref_dly, vref, win_size_sum, delay);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            if (win_size_sum < (vref_dly->max_win * 95 / 100))</span><br><span style="color: hsl(120, 100%, 40%);">+                      return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (cal_type == TX_DQ_DQS_MOVE_DQ_ONLY) {</span><br><span style="color: hsl(120, 100%, 40%);">+              for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        win_size = (delay[bit].best_last_dqdly -</span><br><span style="color: hsl(120, 100%, 40%);">+                                      delay[bit].best_first_dqdly + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                     vref_dly->min_win = MIN(vref_dly->min_win, win_size);</span><br><span style="color: hsl(120, 100%, 40%);">+                   win_size_sum += win_size;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if ((win_size_sum > vref_dly->max_win)</span><br><span style="color: hsl(120, 100%, 40%);">+              && (vref_dly->min_win >= min_win_size_vref)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      min_win_size_vref = vref_dly->min_win;</span><br><span style="color: hsl(120, 100%, 40%);">+                     dramc_set_vref_dly(vref_dly, vref, win_size_sum, delay);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else</span><br><span style="color: hsl(120, 100%, 40%);">+                dramc_set_vref_dly(vref_dly, vref, win_size_sum, delay);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_calc_tx_perbyte_dly(</span><br><span style="color: hsl(120, 100%, 40%);">+                struct dqdqs_perbit_dly *p, s16 *win,</span><br><span style="color: hsl(120, 100%, 40%);">+         struct per_byte_dly *byte_delay_prop)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      s16 win_center;</span><br><span style="color: hsl(120, 100%, 40%);">+       win_center = (p->best_first_dqdly + p->best_last_dqdly) >> 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     *win = win_center;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (win_center < byte_delay_prop->min_center)</span><br><span style="color: hsl(120, 100%, 40%);">+           byte_delay_prop->min_center = win_center;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (win_center > byte_delay_prop->max_center)</span><br><span style="color: hsl(120, 100%, 40%);">+           byte_delay_prop->max_center = win_center;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_set_rx_dly(u8 chn, u8 rank, s32 dly)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  if (dly <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Hold time calibration */</span><br><span style="color: hsl(120, 100%, 40%);">+           set_rx_dly_factor(chn, rank, RX_DQS, -dly);</span><br><span style="color: hsl(120, 100%, 40%);">+           dram_phy_reset(chn);</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Setup time calibration */</span><br><span style="color: hsl(120, 100%, 40%);">+          set_rx_dly_factor(chn, rank, RX_DQS, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+              set_rx_dly_factor(chn, rank, RX_DQM, dly);</span><br><span style="color: hsl(120, 100%, 40%);">+            dram_phy_reset(chn);</span><br><span style="color: hsl(120, 100%, 40%);">+          set_rx_dly_factor(chn, rank, RX_DQ, dly);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void set_tx_best_dly_factor(u8 chn, u8 rank_start,</span><br><span style="color: hsl(120, 100%, 40%);">+           struct per_byte_dly *tx_perbyte_dly, u16 dq_precal_result[])</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       u8 i, rank;</span><br><span style="color: hsl(120, 100%, 40%);">+   u32 coarse_tune_large = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    u32 coarse_tune_large_oen = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        u32 coarse_tune_small = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    u32 coarse_tune_small_oen = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        u16 dq_oen[DQS_NUMBER] = {0}, dqm_oen[DQS_NUMBER] = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+      struct tx_dly_tune dqdly_tune[DQS_NUMBER] = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+      struct tx_dly_tune dqmdly_tune[DQS_NUMBER] = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < DQS_NUMBER; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         dramc_transfer_dly_tune(chn, tx_perbyte_dly[i].final_dly,</span><br><span style="color: hsl(120, 100%, 40%);">+                     &dqdly_tune[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+          dramc_transfer_dly_tune(chn, dq_precal_result[i],</span><br><span style="color: hsl(120, 100%, 40%);">+                     &dqmdly_tune[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               coarse_tune_large += dqdly_tune[i].coarse_tune_large << (i * 4);</span><br><span style="color: hsl(120, 100%, 40%);">+                coarse_tune_large_oen +=</span><br><span style="color: hsl(120, 100%, 40%);">+                      dqdly_tune[i].coarse_tune_large_oen << (i * 4);</span><br><span style="color: hsl(120, 100%, 40%);">+         coarse_tune_small += dqdly_tune[i].coarse_tune_small << (i * 4);</span><br><span style="color: hsl(120, 100%, 40%);">+                coarse_tune_small_oen +=</span><br><span style="color: hsl(120, 100%, 40%);">+                      dqdly_tune[i].coarse_tune_small_oen << (i * 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               dq_oen[i] = (dqdly_tune[i].coarse_tune_large_oen << 3) +</span><br><span style="color: hsl(120, 100%, 40%);">+                                (dqdly_tune[i].coarse_tune_small_oen << 5) +</span><br><span style="color: hsl(120, 100%, 40%);">+                            dqdly_tune[i].fine_tune;</span><br><span style="color: hsl(120, 100%, 40%);">+              dqm_oen[i] = (dqmdly_tune[i].coarse_tune_large_oen << 3) +</span><br><span style="color: hsl(120, 100%, 40%);">+                              (dqmdly_tune[i].coarse_tune_small_oen << 5) +</span><br><span style="color: hsl(120, 100%, 40%);">+                           dqmdly_tune[i].fine_tune;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (rank = rank_start; rank < RANK_MAX; rank++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[0],</span><br><span style="color: hsl(120, 100%, 40%);">+                  (coarse_tune_large_oen << 16) | coarse_tune_large);</span><br><span style="color: hsl(120, 100%, 40%);">+             write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[2],</span><br><span style="color: hsl(120, 100%, 40%);">+                  (coarse_tune_small_oen << 16) | coarse_tune_small);</span><br><span style="color: hsl(120, 100%, 40%);">+             write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[1],</span><br><span style="color: hsl(120, 100%, 40%);">+                  (coarse_tune_large_oen << 16) | coarse_tune_large);</span><br><span style="color: hsl(120, 100%, 40%);">+             write32(&ch[chn].ao.shu[0].rk[rank].selph_dq[3],</span><br><span style="color: hsl(120, 100%, 40%);">+                  (coarse_tune_small_oen << 16) | coarse_tune_small);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (rank = rank_start; rank < RANK_MAX; rank++)</span><br><span style="color: hsl(120, 100%, 40%);">+           for (u8 b = 0; b < 2; b++)</span><br><span style="color: hsl(120, 100%, 40%);">+                 clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].b[b].dq[7],</span><br><span style="color: hsl(120, 100%, 40%);">+                          FINE_TUNE_DQ_MASK | FINE_TUNE_DQM_MASK,</span><br><span style="color: hsl(120, 100%, 40%);">+                               (dqdly_tune[b].fine_tune <<</span><br><span style="color: hsl(120, 100%, 40%);">+                             FINE_TUNE_DQ_SHIFT) |</span><br><span style="color: hsl(120, 100%, 40%);">+                         (dqmdly_tune[b].fine_tune <<</span><br><span style="color: hsl(120, 100%, 40%);">+                            FINE_TUNE_DQM_SHIFT));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void set_rx_best_dly_factor(u8 chn, u8 rank,</span><br><span style="color: hsl(120, 100%, 40%);">+              struct dqdqs_perbit_dly *dqdqs_perbit_dly,</span><br><span style="color: hsl(120, 100%, 40%);">+            u32 *max_dqsdly_byte, u32 *ave_dqm_dly)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    u32 i, value = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     u8 index, byte;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < DQS_NUMBER; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         value = (max_dqsdly_byte[i] << 24) |</span><br><span style="color: hsl(120, 100%, 40%);">+                    (max_dqsdly_byte[i] << 16) |</span><br><span style="color: hsl(120, 100%, 40%);">+                    (ave_dqm_dly[i] << 8) | (ave_dqm_dly[i] << 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          /* Delay dqs/dqm */</span><br><span style="color: hsl(120, 100%, 40%);">+           write32(&ch[chn].phy.shu[0].rk[rank].b[i].dq[6], value);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     dram_phy_reset(chn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        value = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < DQ_DATA_WIDTH; i += 2) {</span><br><span style="color: hsl(120, 100%, 40%);">+           byte = i / DQS_BIT_NUMBER;</span><br><span style="color: hsl(120, 100%, 40%);">+            index = 2 + ((i % 8) * 2) / 4;</span><br><span style="color: hsl(120, 100%, 40%);">+                value = dqdqs_perbit_dly[i + 1].best_dqdly << 24 |</span><br><span style="color: hsl(120, 100%, 40%);">+                      dqdqs_perbit_dly[i + 1].best_dqdly << 16 |</span><br><span style="color: hsl(120, 100%, 40%);">+                      dqdqs_perbit_dly[i].best_dqdly << 8 |</span><br><span style="color: hsl(120, 100%, 40%);">+                   dqdqs_perbit_dly[i].best_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+               write32(&ch[chn].phy.shu[0].rk[rank].b[byte].dq[index], value);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static u8 dramc_calc_best_dly(u8 bit,</span><br><span style="color: hsl(120, 100%, 40%);">+         struct dqdqs_perbit_dly *p, u32 *p_max_byte)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       u8 fail = 0, hold, setup;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   hold = p->best_last_dqsdly - p->best_first_dqsdly + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+  setup = p->best_last_dqdly - p->best_first_dqdly + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (hold > setup) {</span><br><span style="color: hsl(120, 100%, 40%);">+                p->best_dqdly = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+         p->best_dqsdly = (setup != 0) ? (hold - setup) / 2 :</span><br><span style="color: hsl(120, 100%, 40%);">+                   (hold - setup) / 2 + p->best_first_dqsdly;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (p->best_dqsdly > *p_max_byte)</span><br><span style="color: hsl(120, 100%, 40%);">+                       *p_max_byte = p->best_dqsdly;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (hold < setup) {</span><br><span style="color: hsl(120, 100%, 40%);">+         p->best_dqsdly = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                p->best_dqdly = (hold != 0) ? (setup - hold) / 2 :</span><br><span style="color: hsl(120, 100%, 40%);">+             (setup - hold) / 2 + p->best_first_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {                /* hold time == setup time */</span><br><span style="color: hsl(120, 100%, 40%);">+         p->best_dqsdly = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                p->best_dqdly = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               if (hold == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      dramc_dbg("ERROR, error bit %d, "</span><br><span style="color: hsl(120, 100%, 40%);">+                           "setup_time = hold_time = 0\n", bit);</span><br><span style="color: hsl(120, 100%, 40%);">+                       fail = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   dramc_dbg("bit#%d : dq =%d dqs=%d win=%d (%d, %d)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+               bit, setup, hold, setup + hold, p->best_dqdly, p->best_dqsdly);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return fail;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_set_dqdqs_dly(u8 chn, u8 rank, u8 cal_type, s32 dly)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  if ((cal_type == RX_WIN_RD_DQC) || (cal_type == RX_WIN_TEST_ENG))</span><br><span style="color: hsl(120, 100%, 40%);">+             dramc_set_rx_dly(chn, rank, dly);</span><br><span style="color: hsl(120, 100%, 40%);">+     else</span><br><span style="color: hsl(120, 100%, 40%);">+          set_tx_dly_factor(chn, rank, cal_type, dly);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_set_tx_best_dly(u8 chn, u8 rank,</span><br><span style="color: hsl(120, 100%, 40%);">+         struct dqdqs_perbit_dly *tx_dly, u16 *tx_dq_precal_result,</span><br><span style="color: hsl(120, 100%, 40%);">+            const struct sdram_params *params)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ s16 dq_win_center[DQ_DATA_WIDTH];</span><br><span style="color: hsl(120, 100%, 40%);">+     u16 pi_diff;</span><br><span style="color: hsl(120, 100%, 40%);">+  u32 byte_dly_cell[DQS_NUMBER] = {0, 0};</span><br><span style="color: hsl(120, 100%, 40%);">+       struct per_byte_dly tx_perbyte_dly[DQS_NUMBER];</span><br><span style="color: hsl(120, 100%, 40%);">+       u16 dly_cell_unit = params->delay_cell_unit;</span><br><span style="color: hsl(120, 100%, 40%);">+       int i, index, bit;</span><br><span style="color: hsl(120, 100%, 40%);">+    u16 dq_delay_cell[DQ_DATA_WIDTH];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < DQS_NUMBER; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         tx_perbyte_dly[i].min_center = 0xffff;</span><br><span style="color: hsl(120, 100%, 40%);">+                tx_perbyte_dly[i].max_center = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < DQ_DATA_WIDTH; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              index = i / DQS_BIT_NUMBER;</span><br><span style="color: hsl(120, 100%, 40%);">+           dramc_calc_tx_perbyte_dly(&tx_dly[i],</span><br><span style="color: hsl(120, 100%, 40%);">+                     &dq_win_center[i], &tx_perbyte_dly[index]);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < DQS_NUMBER; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         tx_perbyte_dly[i].final_dly = tx_perbyte_dly[i].min_center;</span><br><span style="color: hsl(120, 100%, 40%);">+           tx_dq_precal_result[i] = (tx_perbyte_dly[i].max_center</span><br><span style="color: hsl(120, 100%, 40%);">+                                        + tx_perbyte_dly[i].min_center) >> 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         for (bit = 0; bit < DQS_BIT_NUMBER; bit++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       pi_diff = dq_win_center[i * 8 + bit]</span><br><span style="color: hsl(120, 100%, 40%);">+                          - tx_perbyte_dly[i].min_center;</span><br><span style="color: hsl(120, 100%, 40%);">+                       dq_delay_cell[i * 8 + bit] =</span><br><span style="color: hsl(120, 100%, 40%);">+                          ((pi_diff * 1000000) / (16 * 64))</span><br><span style="color: hsl(120, 100%, 40%);">+                             / dly_cell_unit;</span><br><span style="color: hsl(120, 100%, 40%);">+                      byte_dly_cell[i] |=</span><br><span style="color: hsl(120, 100%, 40%);">+                           (dq_delay_cell[i * 8 + bit] << (bit * 4));</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           write32(&ch[chn].phy.shu[0].rk[rank].b[i].dq[0],</span><br><span style="color: hsl(120, 100%, 40%);">+                  byte_dly_cell[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   set_tx_best_dly_factor(chn, rank, tx_perbyte_dly, tx_dq_precal_result);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int dramc_set_rx_best_dly(u8 chn, u8 rank,</span><br><span style="color: hsl(120, 100%, 40%);">+               struct dqdqs_perbit_dly *rx_dly)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   s16 dly;</span><br><span style="color: hsl(120, 100%, 40%);">+      s8 fail = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  u8 i, index, max_limit;</span><br><span style="color: hsl(120, 100%, 40%);">+       static u32 max_dqsdly_byte[DQS_NUMBER];</span><br><span style="color: hsl(120, 100%, 40%);">+       static u32 ave_dqmdly_byte[DQS_NUMBER];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < DQS_NUMBER; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         max_dqsdly_byte[i] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+               ave_dqmdly_byte[i] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < DQ_DATA_WIDTH; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              index = i / DQS_BIT_NUMBER;</span><br><span style="color: hsl(120, 100%, 40%);">+           fail |= dramc_calc_best_dly(i, &rx_dly[i],</span><br><span style="color: hsl(120, 100%, 40%);">+                        &max_dqsdly_byte[index]);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < DQ_DATA_WIDTH; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              index = i / DQS_BIT_NUMBER;</span><br><span style="color: hsl(120, 100%, 40%);">+           /* set DQS to max for 8-bit */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (rx_dly[i].best_dqsdly < max_dqsdly_byte[index]) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* Delay DQ to compensate extra DQS delay */</span><br><span style="color: hsl(120, 100%, 40%);">+                  dly = max_dqsdly_byte[index] - rx_dly[i].best_dqsdly;</span><br><span style="color: hsl(120, 100%, 40%);">+                 rx_dly[i].best_dqdly += dly;</span><br><span style="color: hsl(120, 100%, 40%);">+                  max_limit = MAX_DQDLY_TAPS - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (rx_dly[i].best_dqdly > max_limit)</span><br><span style="color: hsl(120, 100%, 40%);">+                              rx_dly[i].best_dqdly = max_limit;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           ave_dqmdly_byte[index] += rx_dly[i].best_dqdly;</span><br><span style="color: hsl(120, 100%, 40%);">+               if ((i + 1) % DQS_BIT_NUMBER == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                    ave_dqmdly_byte[index] /= DQS_BIT_NUMBER;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (fail == 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+              dramc_dbg("FAIL on perbit_window_cal()\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   set_rx_best_dly_factor(chn, rank, rx_dly, max_dqsdly_byte,</span><br><span style="color: hsl(120, 100%, 40%);">+                           ave_dqmdly_byte);</span><br><span style="color: hsl(120, 100%, 40%);">+      return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_get_vref_prop(u8 rank, u8 cal_type,</span><br><span style="color: hsl(120, 100%, 40%);">+         u8 *vref_scan_en, u8 *vref_begin, u8 *vref_end)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((cal_type == RX_WIN_TEST_ENG) && (rank == RANK_0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              *vref_scan_en = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+            *vref_begin = RX_VREF_BEGIN;</span><br><span style="color: hsl(120, 100%, 40%);">+          *vref_end  = RX_VREF_END;</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (cal_type == TX_WIN_DQ_ONLY) {</span><br><span style="color: hsl(120, 100%, 40%);">+              *vref_scan_en = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+            *vref_begin = TX_VREF_BEGIN;</span><br><span style="color: hsl(120, 100%, 40%);">+          *vref_end = TX_VREF_END;</span><br><span style="color: hsl(120, 100%, 40%);">+      } else</span><br><span style="color: hsl(120, 100%, 40%);">+                *vref_scan_en = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dramc_engine2_setpat(u8 chn, u8 testaudpat)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   const u32 log2loopcount = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  const u32 len1 = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ clrbits_le32(&ch[chn].ao.test2_4,</span><br><span style="color: hsl(120, 100%, 40%);">+         0x1 << TEST2_4_TESTXTALKPAT_SHIFT |</span><br><span style="color: hsl(120, 100%, 40%);">+             0x1 << TEST2_4_TESTAUDMODE_SHIFT |</span><br><span style="color: hsl(120, 100%, 40%);">+              0x1 << TEST2_4_TESTAUDBITINV_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (testaudpat == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                setbits_le32(&ch[chn].ao.perfctl0, 1 << PERFCTL0_RWOFOEN_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          clrsetbits_le32(&ch[chn].ao.test2_4,</span><br><span style="color: hsl(120, 100%, 40%);">+                      0x1 << TEST2_4_TEST_REQ_LEN1_SHIFT |</span><br><span style="color: hsl(120, 100%, 40%);">+                    0x1 << TEST2_4_TESTSSOPAT_SHIFT |</span><br><span style="color: hsl(120, 100%, 40%);">+                       0x1 << TEST2_4_TESTSSOXTALKPAT_SHIFT |</span><br><span style="color: hsl(120, 100%, 40%);">+                  0x1 << TEST2_4_TESTXTALKPAT_SHIFT,</span><br><span style="color: hsl(120, 100%, 40%);">+                      len1 << TEST2_4_TEST_REQ_LEN1_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (testaudpat == 1)   {</span><br><span style="color: hsl(120, 100%, 40%);">+               clrsetbits_le32(&ch[chn].ao.test2_4,</span><br><span style="color: hsl(120, 100%, 40%);">+                      TEST2_4_TESTAUDINIT_MASK | TEST2_4_TESTAUDINC_MASK,</span><br><span style="color: hsl(120, 100%, 40%);">+                   (0x11 << 8) | (0xd << 0) | (0x1 << 14));</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     clrsetbits_le32(&ch[chn].ao.test2_3,</span><br><span style="color: hsl(120, 100%, 40%);">+              0x1 << TEST2_3_TESTAUDPAT_SHIFT | TEST2_3_TESTCNT_MASK,</span><br><span style="color: hsl(120, 100%, 40%);">+         (testaudpat ? 1 : 0) << TEST2_3_TESTAUDPAT_SHIFT |</span><br><span style="color: hsl(120, 100%, 40%);">+              log2loopcount << 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static u32 dram_k_perbit(u8 chn, u8 cal_type)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     u32 err_value = 0x0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (cal_type == RX_WIN_RD_DQC) {</span><br><span style="color: hsl(120, 100%, 40%);">+              err_value = dramc_rd_dqc_run(chn);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              dramc_engine2_setpat(chn, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+         err_value = dramc_engine2_run(chn, TE_OP_WRITE_READ_CHECK);</span><br><span style="color: hsl(120, 100%, 40%);">+           dramc_engine2_setpat(chn, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+         err_value |= dramc_engine2_run(chn, TE_OP_WRITE_READ_CHECK);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     return err_value;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static u8 dramc_window_perbit_cal(u8 chn, u8 rank,</span><br><span style="color: hsl(120, 100%, 40%);">+            u8 type, const struct sdram_params *params)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        u8 vref = 0, vref_begin = 0, vref_end = 1, vref_scan_enable = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      s16 dly, dly_begin = 0, dly_end = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  u8 i, bit, dly_step = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+      u32 dummy_rd_backup = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      static u16 dq_precal_result[DQS_NUMBER];</span><br><span style="color: hsl(120, 100%, 40%);">+      u32 err_value, fail_bit;</span><br><span style="color: hsl(120, 100%, 40%);">+      static struct vref_perbit_dly vref_dly;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct dqdqs_perbit_dly dq_perbit_dly[DQ_DATA_WIDTH];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       dramc_get_vref_prop(rank, type,</span><br><span style="color: hsl(120, 100%, 40%);">+                       &vref_scan_enable, &vref_begin, &vref_end);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (vref_scan_enable && (type == RX_WIN_RD_DQC))</span><br><span style="color: hsl(120, 100%, 40%);">+              dramc_rx_vref_enable(chn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  dramc_dbg("%s [Rank %d] [Channel %d] cal_type:%d,vref_enable:%d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+         __func__, rank, chn, type, vref_scan_enable);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if ((type == TX_WIN_DQ_ONLY) || (type == TX_WIN_DQ_DQM)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            for (i = 0; i < 2; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  write32(&ch[chn].phy.shu[0].rk[rank].b[i].dq[0], 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                      clrbits_le32(&ch[chn].phy.shu[0].rk[rank].b[i].dq[1],</span><br><span style="color: hsl(120, 100%, 40%);">+                             0xf);</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+             setbits_le32(&ch[chn].phy.misc_ctrl1,</span><br><span style="color: hsl(120, 100%, 40%);">+                     0x1 << MISC_CTRL1_R_DMAR_FINE_TUNE_DQ_SW_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+                setbits_le32(&ch[chn].ao.dqsoscr,</span><br><span style="color: hsl(120, 100%, 40%);">+                 0x1 << DQSOSCR_AR_COARSE_TUNE_DQ_SW_SHIFT);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (type == RX_WIN_RD_DQC) {</span><br><span style="color: hsl(120, 100%, 40%);">+          dramc_rd_dqc_init(chn, rank);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              dummy_rd_backup = read32(&ch[chn].ao.dummy_rd);</span><br><span style="color: hsl(120, 100%, 40%);">+           dramc_engine2_init(chn, rank, 0x400, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   vref_dly.max_win = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ vref_dly.min_win = 0xffff;</span><br><span style="color: hsl(120, 100%, 40%);">+    for (vref = vref_begin; vref < vref_end; vref += dly_step) {</span><br><span style="color: hsl(120, 100%, 40%);">+               vref_dly.vref = vref;</span><br><span style="color: hsl(120, 100%, 40%);">+         for (i = 0; i < DQ_DATA_WIDTH; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      dq_perbit_dly[i].first_dqdly = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                    dq_perbit_dly[i].last_dqdly = -2;</span><br><span style="color: hsl(120, 100%, 40%);">+                     dq_perbit_dly[i].first_dqsdly = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                   dq_perbit_dly[i].last_dqsdly = -2;</span><br><span style="color: hsl(120, 100%, 40%);">+                    dq_perbit_dly[i].best_first_dqdly = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                       dq_perbit_dly[i].best_last_dqdly = -2;</span><br><span style="color: hsl(120, 100%, 40%);">+                        dq_perbit_dly[i].best_first_dqsdly = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                      dq_perbit_dly[i].best_last_dqsdly = -2;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (vref_scan_enable)</span><br><span style="color: hsl(120, 100%, 40%);">+                 dramc_set_vref(chn, rank, type, vref_dly.vref);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             if ((type == RX_WIN_RD_DQC) || (type == RX_WIN_TEST_ENG)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   set_rx_dly_factor(chn, rank, RX_DQM, FIRST_DQ_DELAY);</span><br><span style="color: hsl(120, 100%, 40%);">+                 set_rx_dly_factor(chn, rank, RX_DQ, FIRST_DQ_DELAY);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           dramc_get_dly_range(chn, rank, type, dq_precal_result,</span><br><span style="color: hsl(120, 100%, 40%);">+                        &dly_begin, &dly_end, params);</span><br><span style="color: hsl(120, 100%, 40%);">+                for (dly = dly_begin; dly < dly_end; dly += dly_step) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    dramc_set_dqdqs_dly(chn, rank, type, dly);</span><br><span style="color: hsl(120, 100%, 40%);">+                    err_value = dram_k_perbit(chn, type);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (!vref_scan_enable)</span><br><span style="color: hsl(120, 100%, 40%);">+                                dramc_dbg("%d ", dly);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                    for (bit = 0; bit < DQ_DATA_WIDTH; bit++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                fail_bit = err_value & ((u32) 1 << bit);</span><br><span style="color: hsl(120, 100%, 40%);">+                            if (dly < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                                       dramc_check_dqdqs_win(</span><br><span style="color: hsl(120, 100%, 40%);">+                                                &(dq_perbit_dly[bit]),</span><br><span style="color: hsl(120, 100%, 40%);">+                                            -dly, -FIRST_DQS_DELAY,</span><br><span style="color: hsl(120, 100%, 40%);">+                                               fail_bit, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                         else</span><br><span style="color: hsl(120, 100%, 40%);">+                                  dramc_check_dqdqs_win(</span><br><span style="color: hsl(120, 100%, 40%);">+                                                &(dq_perbit_dly[bit]),</span><br><span style="color: hsl(120, 100%, 40%);">+                                            dly, dly_end, fail_bit, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                           if (!vref_scan_enable) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      if (fail_bit == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                                            dramc_dbg("o");</span><br><span style="color: hsl(120, 100%, 40%);">+                                     else</span><br><span style="color: hsl(120, 100%, 40%);">+                                          dramc_dbg("x");</span><br><span style="color: hsl(120, 100%, 40%);">+                             }</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (!vref_scan_enable)</span><br><span style="color: hsl(120, 100%, 40%);">+                                dramc_dbg(" [MSB]\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           for (bit = 0; bit < DQ_DATA_WIDTH; bit++)</span><br><span style="color: hsl(120, 100%, 40%);">+                  dramc_dbg("dq[%d] win(%d ~ %d)\n", bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                             dq_perbit_dly[bit].best_first_dqdly,</span><br><span style="color: hsl(120, 100%, 40%);">+                          dq_perbit_dly[bit].best_last_dqdly);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                if (dramk_calc_best_vref(type, vref, &vref_dly, dq_perbit_dly))</span><br><span style="color: hsl(120, 100%, 40%);">+                   break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (type == RX_WIN_RD_DQC) {</span><br><span style="color: hsl(120, 100%, 40%);">+          dramc_rd_dqc_end(chn);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              dramc_engine2_end(chn);</span><br><span style="color: hsl(120, 100%, 40%);">+               write32(&ch[chn].ao.dummy_rd, dummy_rd_backup);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (vref_scan_enable)</span><br><span style="color: hsl(120, 100%, 40%);">+         dramc_set_vref(chn, rank, type, vref_dly.vref);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if ((type == RX_WIN_RD_DQC) || (type == RX_WIN_TEST_ENG))</span><br><span style="color: hsl(120, 100%, 40%);">+             dramc_set_rx_best_dly(chn, rank, vref_dly.perbit_dly);</span><br><span style="color: hsl(120, 100%, 40%);">+        else</span><br><span style="color: hsl(120, 100%, 40%);">+          dramc_set_tx_best_dly(chn, rank, vref_dly.perbit_dly,</span><br><span style="color: hsl(120, 100%, 40%);">+                 dq_precal_result, params);</span><br><span style="color: hsl(120, 100%, 40%);">+    return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void dramc_rx_dqs_gating_post_process(u8 chn)</span><br><span> {</span><br><span>  u8 dqs, rank_rx_dvs, dqsinctl, rank;</span><br><span>@@ -971,6 +1809,10 @@</span><br><span>                         dramc_write_leveling(chn, rk, pams->wr_level);</span><br><span>                    auto_refresh_switch(chn, 1);</span><br><span>                         dramc_rx_dqs_gating_cal(chn, rk);</span><br><span style="color: hsl(120, 100%, 40%);">+                     dramc_window_perbit_cal(chn, rk, RX_WIN_RD_DQC, pams);</span><br><span style="color: hsl(120, 100%, 40%);">+                        dramc_window_perbit_cal(chn, rk, TX_WIN_DQ_DQM, pams);</span><br><span style="color: hsl(120, 100%, 40%);">+                        dramc_window_perbit_cal(chn, rk, TX_WIN_DQ_ONLY, pams);</span><br><span style="color: hsl(120, 100%, 40%);">+                       dramc_window_perbit_cal(chn, rk, RX_WIN_TEST_ENG, pams);</span><br><span>             }</span><br><span> </span><br><span>                dramc_rx_dqs_gating_post_process(chn);</span><br><span>diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h</span><br><span>index 761fff6..a67e16d 100644</span><br><span>--- a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h</span><br><span>+++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h</span><br><span>@@ -38,6 +38,7 @@</span><br><span> #define DRAMC_BROADCAST_ON 0x1f</span><br><span> #define DRAMC_BROADCAST_OFF 0x0</span><br><span> #define MAX_BACKUP_REG_CNT 32</span><br><span style="color: hsl(120, 100%, 40%);">+#define TX_DQ_COARSE_TUNE_TO_FINE_TUNE_TAP 64</span><br><span> </span><br><span> #define IMP_LP4X_TERM_VREF_SEL             0x1b</span><br><span> #define IMP_DRVP_LP4X_UNTERM_VREF_SEL   0x1a</span><br><span>diff --git a/src/soc/mediatek/mt8183/include/soc/memlayout.ld b/src/soc/mediatek/mt8183/include/soc/memlayout.ld</span><br><span>index f148eed..2a6d42d 100644</span><br><span>--- a/src/soc/mediatek/mt8183/include/soc/memlayout.ld</span><br><span>+++ b/src/soc/mediatek/mt8183/include/soc/memlayout.ld</span><br><span>@@ -39,7 +39,7 @@</span><br><span>        SRAM_END(0x00120000)</span><br><span> </span><br><span>     SRAM_L2C_START(0x00200000)</span><br><span style="color: hsl(0, 100%, 40%);">-      OVERLAP_DECOMPRESSOR_ROMSTAGE(0x000201000, 92K)</span><br><span style="color: hsl(120, 100%, 40%);">+       OVERLAP_DECOMPRESSOR_ROMSTAGE(0x000201000, 110K)</span><br><span>     BOOTBLOCK(0x00227000, 89K)</span><br><span>   VERSTAGE(0x0023E000, 114K)</span><br><span>   SRAM_L2C_END(0x00280000)</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/28842">change 28842</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/28842"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I4434897864993e254e1362416316470083351493 </div>
<div style="display:none"> Gerrit-Change-Number: 28842 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Tristan Hsieh <tristan.shieh@mediatek.com> </div>