<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>