huayang duan has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/35164 )
Change subject: mediatek/mt8183: Use calibration result do fast calibration ......................................................................
mediatek/mt8183: Use calibration result do fast calibration
Load calibration result from flash, if result was correct, use this calibration result do fast calibration to reduce the bootup time.
BUG=b:80501386 BRANCH=none TEST=Boots correctly on Kukui.
Change-Id: I9ef4265dd369a1c276bb02294696556df927e7bc Signed-off-by: Huayang Duan huayang.duan@mediatek.com --- M src/soc/mediatek/mt8183/dramc_init_setting.c M src/soc/mediatek/mt8183/dramc_pi_calibration_api.c M src/soc/mediatek/mt8183/emi.c M src/soc/mediatek/mt8183/include/soc/emi.h M src/soc/mediatek/mt8183/memory.c 5 files changed, 366 insertions(+), 254 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/64/35164/1
diff --git a/src/soc/mediatek/mt8183/dramc_init_setting.c b/src/soc/mediatek/mt8183/dramc_init_setting.c index 9103c2d..232b4cf 100644 --- a/src/soc/mediatek/mt8183/dramc_init_setting.c +++ b/src/soc/mediatek/mt8183/dramc_init_setting.c @@ -601,45 +601,54 @@
static void dramc_duty_calibration(const struct sdram_params *params, u8 freq_group) { - s8 clkDelay[CHANNEL_MAX] = {0x0}; - s8 dqsDelay[CHANNEL_MAX][DQS_NUMBER] = {0x0}; + if (params->have_full_k_params) { + dramc_dbg("bypass duty calibration\n");
- switch (freq_group) { - case LP4X_DDR1600: - clkDelay[CHANNEL_A] = 2; - clkDelay[CHANNEL_B] = 1; - dqsDelay[CHANNEL_A][0] = 0; - dqsDelay[CHANNEL_A][1] = 0; - dqsDelay[CHANNEL_B][0] = -1; - dqsDelay[CHANNEL_B][1] = 0; - break; - case LP4X_DDR2400: - clkDelay[CHANNEL_A] = clkDelay[CHANNEL_B] = 0; - dqsDelay[CHANNEL_A][0] = 0; - dqsDelay[CHANNEL_A][1] = -2; - dqsDelay[CHANNEL_B][0] = 0; - dqsDelay[CHANNEL_B][1] = -2; - break; - case LP4X_DDR3200: - clkDelay[CHANNEL_A] = clkDelay[CHANNEL_B] = 1; - dqsDelay[CHANNEL_A][0] = 1; - dqsDelay[CHANNEL_A][1] = -2; - dqsDelay[CHANNEL_B][0] = 1; - dqsDelay[CHANNEL_B][1] = -2; - break; - case LP4X_DDR3600: - clkDelay[CHANNEL_A] = 2; - clkDelay[CHANNEL_B] = 1; - dqsDelay[CHANNEL_A][0] = 0; - dqsDelay[CHANNEL_A][1] = 0; - dqsDelay[CHANNEL_B][0] = -1; - dqsDelay[CHANNEL_B][1] = 0; - break; - } + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { + dramc_duty_set_clk_delay(chn, params->duty_clk_delay[chn]); + dramc_duty_set_dqs_delay(chn, params->duty_dqs_delay[chn]); + } + } else { + s8 clkDelay[CHANNEL_MAX] = {0x0}; + s8 dqsDelay[CHANNEL_MAX][DQS_NUMBER] = {0x0};
- for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { - dramc_duty_set_clk_delay(chn, clkDelay[chn]); - dramc_duty_set_dqs_delay(chn, dqsDelay[chn]); + switch (freq_group) { + case LP4X_DDR1600: + clkDelay[CHANNEL_A] = 2; + clkDelay[CHANNEL_B] = 1; + dqsDelay[CHANNEL_A][0] = 0; + dqsDelay[CHANNEL_A][1] = 0; + dqsDelay[CHANNEL_B][0] = -1; + dqsDelay[CHANNEL_B][1] = 0; + break; + case LP4X_DDR2400: + clkDelay[CHANNEL_A] = clkDelay[CHANNEL_B] = 0; + dqsDelay[CHANNEL_A][0] = 0; + dqsDelay[CHANNEL_A][1] = -2; + dqsDelay[CHANNEL_B][0] = 0; + dqsDelay[CHANNEL_B][1] = -2; + break; + case LP4X_DDR3200: + clkDelay[CHANNEL_A] = clkDelay[CHANNEL_B] = 1; + dqsDelay[CHANNEL_A][0] = 1; + dqsDelay[CHANNEL_A][1] = -2; + dqsDelay[CHANNEL_B][0] = 1; + dqsDelay[CHANNEL_B][1] = -2; + break; + case LP4X_DDR3600: + clkDelay[CHANNEL_A] = 2; + clkDelay[CHANNEL_B] = 1; + dqsDelay[CHANNEL_A][0] = 0; + dqsDelay[CHANNEL_A][1] = 0; + dqsDelay[CHANNEL_B][0] = -1; + dqsDelay[CHANNEL_B][1] = 0; + break; + } + + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { + dramc_duty_set_clk_delay(chn, clkDelay[chn]); + dramc_duty_set_dqs_delay(chn, dqsDelay[chn]); + } } }
diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c index 39ea0b3..220a319 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -244,17 +244,25 @@ static void dramc_cmd_bus_training(u8 chn, u8 rank, u8 freq_group, const struct sdram_params *params) { - u32 cbt_cs, mr12_value; + u32 final_vref, clk_dly, cmd_dly, cs_dly;
- cbt_cs = params->cbt_cs[chn][rank]; - mr12_value = params->cbt_mr12[chn][rank]; + clk_dly = params->cbt_clk_dly[chn][rank]; + cmd_dly = params->cbt_cmd_dly[chn][rank]; + cs_dly = params->cbt_cs_dly[chn][rank]; + final_vref = params->cbt_final_vref[chn][rank];
- /* CBT adjust cs */ - clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].ca_cmd[9], - SHU1_CA_CMD9_RG_RK_ARFINE_TUNE_CS_MASK, cbt_cs << 0); + if (params->have_full_k_params) { + /* Set CLK and CA delay */ + clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].ca_cmd[9], + (0x3f << 8) | (0x3f << 24), (cmd_dly << 8) | (clk_dly << 24)); + udelay(1); + } + + /* Set CLK and CS delay */ + clrsetbits_le32(&ch[chn].phy.shu[0].rk[rank].ca_cmd[9], 0x3f, cs_dly << 0);
/* CBT set vref */ - dramc_mode_reg_write_by_rank(chn, rank, 12, mr12_value); + dramc_mode_reg_write_by_rank(chn, rank, 12, final_vref); }
static void dramc_read_dbi_onoff(bool on) @@ -885,112 +893,124 @@
coarse_end = coarse_start + 12; dramc_dbg("[Gating]\n"); - for (u32 coarse_tune = coarse_start; coarse_tune < coarse_end; coarse_tune++) { - u32 dly_coarse_large_rodt = 0, dly_coarse_0p5t_rodt = 0; - u32 dly_coarse_large_rodt_p1 = 4, dly_coarse_0p5t_rodt_p1 = 4;
- u8 dly_coarse_large = coarse_tune / RX_DQS_CTL_LOOP; - u8 dly_coarse_0p5t = coarse_tune % RX_DQS_CTL_LOOP; - u32 dly_coarse_large_p1 = (coarse_tune + freqDiv) / RX_DQS_CTL_LOOP; - u32 dly_coarse_0p5t_p1 = (coarse_tune + freqDiv) % RX_DQS_CTL_LOOP; - u32 value = (dly_coarse_large << 3) + dly_coarse_0p5t; + if (params->have_full_k_params) { + dramc_dbg("[bypass Gating]\n"); + } else { + for (u32 coarse_tune = coarse_start; coarse_tune < coarse_end; coarse_tune++) { + u32 dly_coarse_large_rodt = 0, dly_coarse_0p5t_rodt = 0; + u32 dly_coarse_large_rodt_p1 = 4, dly_coarse_0p5t_rodt_p1 = 4;
- if (value >= 11) { - value -= 11; - dly_coarse_large_rodt = value >> 3; + u8 dly_coarse_large = coarse_tune / RX_DQS_CTL_LOOP; + u8 dly_coarse_0p5t = coarse_tune % RX_DQS_CTL_LOOP; + u32 dly_coarse_large_p1 = (coarse_tune + freqDiv) / RX_DQS_CTL_LOOP; + u32 dly_coarse_0p5t_p1 = (coarse_tune + freqDiv) % RX_DQS_CTL_LOOP; + u32 value = (dly_coarse_large << 3) + dly_coarse_0p5t; + + if (value >= 11) { + value -= 11; + dly_coarse_large_rodt = value >> 3; dly_coarse_0p5t_rodt = value - (dly_coarse_large_rodt << 3);
- value = (dly_coarse_large << 3) + dly_coarse_0p5t - 11; - dly_coarse_large_rodt_p1 = value >> 3; + value = (dly_coarse_large << 3) + dly_coarse_0p5t - 11; + dly_coarse_large_rodt_p1 = value >> 3; dly_coarse_0p5t_rodt_p1 = value - (dly_coarse_large_rodt_p1 << 3); - } + }
- clrsetbits_le32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg0, - 0x77777777, - (dly_coarse_large << 0) | (dly_coarse_large << 8) | - (dly_coarse_large << 16) | (dly_coarse_large << 24) | - (dly_coarse_large_p1 << 4) | (dly_coarse_large_p1 << 12) | - (dly_coarse_large_p1 << 20) | (dly_coarse_large_p1 << 28)); - clrsetbits_le32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg1, - 0x77777777, - (dly_coarse_0p5t << 0) | (dly_coarse_0p5t << 8) | - (dly_coarse_0p5t << 16) | (dly_coarse_0p5t << 24) | - (dly_coarse_0p5t_p1 << 4) | (dly_coarse_0p5t_p1 << 12) | - (dly_coarse_0p5t_p1 << 20) | (dly_coarse_0p5t_p1 << 28)); - clrsetbits_le32(&ch[chn].ao.shu[0].rk[rank].selph_odten0, - 0x77777777, - (dly_coarse_large_rodt << 0) | (dly_coarse_large_rodt << 8) | - (dly_coarse_large_rodt << 16) | (dly_coarse_large_rodt << 24) | - (dly_coarse_large_rodt_p1 << 4) | (dly_coarse_large_rodt_p1 << 12) | - (dly_coarse_large_rodt_p1 << 20) | (dly_coarse_large_rodt_p1 << 28)); - clrsetbits_le32(&ch[chn].ao.shu[0].rk[rank].selph_odten1, - 0x77777777, - (dly_coarse_0p5t_rodt << 0) | (dly_coarse_0p5t_rodt << 8) | - (dly_coarse_0p5t_rodt << 16) | (dly_coarse_0p5t_rodt << 24) | - (dly_coarse_0p5t_rodt_p1 << 4) | (dly_coarse_0p5t_rodt_p1 << 12) | - (dly_coarse_0p5t_rodt_p1 << 20) | (dly_coarse_0p5t_rodt_p1 << 28)); + clrsetbits_le32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg0, + 0x77777777, + (dly_coarse_large << 0) | (dly_coarse_large << 8) | + (dly_coarse_large << 16) | (dly_coarse_large << 24) | + (dly_coarse_large_p1 << 4) | (dly_coarse_large_p1 << 12) | + (dly_coarse_large_p1 << 20) | (dly_coarse_large_p1 << 28)); + clrsetbits_le32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg1, + 0x77777777, + (dly_coarse_0p5t << 0) | (dly_coarse_0p5t << 8) | + (dly_coarse_0p5t << 16) | (dly_coarse_0p5t << 24) | + (dly_coarse_0p5t_p1 << 4) | (dly_coarse_0p5t_p1 << 12) | + (dly_coarse_0p5t_p1 << 20) | (dly_coarse_0p5t_p1 << 28)); + clrsetbits_le32(&ch[chn].ao.shu[0].rk[rank].selph_odten0, + 0x77777777, + (dly_coarse_large_rodt << 0) | (dly_coarse_large_rodt << 8) | + (dly_coarse_large_rodt << 16) | (dly_coarse_large_rodt << 24) | + (dly_coarse_large_rodt_p1 << 4) | (dly_coarse_large_rodt_p1 << 12) | + (dly_coarse_large_rodt_p1 << 20) | (dly_coarse_large_rodt_p1 << 28)); + clrsetbits_le32(&ch[chn].ao.shu[0].rk[rank].selph_odten1, + 0x77777777, + (dly_coarse_0p5t_rodt << 0) | (dly_coarse_0p5t_rodt << 8) | + (dly_coarse_0p5t_rodt << 16) | (dly_coarse_0p5t_rodt << 24) | + (dly_coarse_0p5t_rodt_p1 << 4) | (dly_coarse_0p5t_rodt_p1 << 12) | + (dly_coarse_0p5t_rodt_p1 << 20) | (dly_coarse_0p5t_rodt_p1 << 28));
- for (u8 dly_fine_xt = 0; dly_fine_xt < DQS_GW_FINE_END; dly_fine_xt += 4) { - dramc_set_gating_mode(chn, 0); - write32(&ch[chn].ao.shu[0].rk[rank].dqsien, - dly_fine_xt | (dly_fine_xt << 8)); + for (u8 dly_fine_xt = 0; dly_fine_xt < DQS_GW_FINE_END; dly_fine_xt += 4) { + dramc_set_gating_mode(chn, 0); + write32(&ch[chn].ao.shu[0].rk[rank].dqsien, + dly_fine_xt | (dly_fine_xt << 8));
- dram_phy_reset(chn); + dram_phy_reset(chn); setbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_DQSGCNTRST_SHIFT); udelay(1); clrbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_DQSGCNTRST_SHIFT);
- dramc_engine2_run(chn, TE_OP_READ_CHECK); + dramc_engine2_run(chn, TE_OP_READ_CHECK);
- u32 result_r = read32(&ch[chn].phy.misc_stberr_rk0_r) & - MISC_STBERR_RK_R_STBERR_RK_R_MASK; - u32 result_f = read32(&ch[chn].phy.misc_stberr_rk0_f) & - MISC_STBERR_RK_F_STBERR_RK_F_MASK; - debug_cnt[0] = read32(&ch[chn].nao.dqsgnwcnt[0]); - debug_cnt[1] = (debug_cnt[0] >> 16) & 0xffff; - debug_cnt[0] &= 0xffff; + u32 result_r = read32(&ch[chn].phy.misc_stberr_rk0_r) & + MISC_STBERR_RK_R_STBERR_RK_R_MASK; + u32 result_f = read32(&ch[chn].phy.misc_stberr_rk0_f) & + MISC_STBERR_RK_F_STBERR_RK_F_MASK; + debug_cnt[0] = read32(&ch[chn].nao.dqsgnwcnt[0]); + debug_cnt[1] = (debug_cnt[0] >> 16) & 0xffff; + debug_cnt[0] &= 0xffff;
- dramc_set_gating_mode(chn, 1); - dramc_engine2_run(chn, TE_OP_READ_CHECK); + dramc_set_gating_mode(chn, 1); + dramc_engine2_run(chn, TE_OP_READ_CHECK);
- dramc_find_dly_tune(chn, dly_coarse_large, - dly_coarse_0p5t, dly_fine_xt, dqs_high, - dly_coarse_large_cnt, dly_coarse_0p5t_cnt, - dly_fine_tune_cnt, dqs_transition, dqs_done); + dramc_find_dly_tune(chn, dly_coarse_large, + dly_coarse_0p5t, dly_fine_xt, dqs_high, + dly_coarse_large_cnt, dly_coarse_0p5t_cnt, + dly_fine_tune_cnt, dqs_transition, dqs_done);
- dramc_dbg("%d %d %d |", dly_coarse_large, - dly_coarse_0p5t, dly_fine_xt); - for (dqs = 0; dqs < DQS_NUMBER; dqs++) - dramc_dbg("%X ", debug_cnt[dqs]); + dramc_dbg("%d %d %d |", dly_coarse_large, + dly_coarse_0p5t, dly_fine_xt); + for (dqs = 0; dqs < DQS_NUMBER; dqs++) + dramc_dbg("%X ", debug_cnt[dqs]);
- dramc_dbg(" |"); - for (dqs = 0; dqs < DQS_NUMBER; dqs++) { - dramc_dbg("(%X %X)", - (result_f >> (DQS_BIT_NUMBER * dqs)) & 0xff, - (result_r >> (DQS_BIT_NUMBER * dqs)) & 0xff); + dramc_dbg(" |"); + for (dqs = 0; dqs < DQS_NUMBER; dqs++) { + dramc_dbg("(%X %X)", + (result_f >> (DQS_BIT_NUMBER * dqs)) & 0xff, + (result_r >> (DQS_BIT_NUMBER * dqs)) & 0xff); + } + + dramc_dbg("\n"); + if (dramc_find_gating_window(result_r, result_f, debug_cnt, + dly_coarse_large, dly_coarse_0p5t, pass_begin, pass_count, + pass_count_1, &dly_fine_xt, dqs_high, dqs_done)) + coarse_tune = coarse_end; } - - dramc_dbg("\n"); - if (dramc_find_gating_window(result_r, result_f, debug_cnt, - dly_coarse_large, dly_coarse_0p5t, pass_begin, pass_count, - pass_count_1, &dly_fine_xt, dqs_high, dqs_done)) - coarse_tune = coarse_end; } + + dramc_engine2_end(chn); + write32(&ch[chn].ao.dummy_rd, dummy_rd_backup); }
- dramc_engine2_end(chn); - write32(&ch[chn].ao.dummy_rd, dummy_rd_backup); - for (dqs = 0; dqs < DQS_NUMBER; dqs++) { - pass_count[dqs] = dqs_transition[dqs]; - min_fine_tune[dqs] = dly_fine_tune_cnt[dqs]; - min_coarse_tune0p5t[dqs] = dly_coarse_0p5t_cnt[dqs]; - min_coarse_tune2t[dqs] = dly_coarse_large_cnt[dqs]; - + if (params->have_full_k_params) { + dramc_dbg("[bypass Gating params] dqs:%d\n", dqs); + pass_count[dqs] = params->gating_pass_count[chn][rank][dqs]; + min_fine_tune[dqs] = params->gating_fine_tune[chn][rank][dqs]; + min_coarse_tune0p5t[dqs] = params->gating05T[chn][rank][dqs]; + min_coarse_tune2t[dqs] = params->gating2T[chn][rank][dqs]; + } else { + pass_count[dqs] = dqs_transition[dqs]; + min_fine_tune[dqs] = dly_fine_tune_cnt[dqs]; + min_coarse_tune0p5t[dqs] = dly_coarse_0p5t_cnt[dqs]; + min_coarse_tune2t[dqs] = dly_coarse_large_cnt[dqs]; + } u8 tmp_offset = pass_count[dqs] * DQS_GW_FINE_STEP / 2; u8 tmp_value = min_fine_tune[dqs] + tmp_offset; best_fine_tune[dqs] = tmp_value % RX_DLY_DQSIENSTB_LOOP; @@ -1551,20 +1571,34 @@ else use_delay_cell = 0;
- for (u8 byte = 0; byte < DQS_NUMBER; byte++) { - center_dly[byte].min_center = 0xffff; - center_dly[byte].max_center = 0; - - for (u8 bit = 0; bit < DQS_BIT_NUMBER; bit++) { - index = bit + 8 * byte; - if (vref_dly[index].win_center < center_dly[byte].min_center) - center_dly[byte].min_center = vref_dly[index].win_center; - if (vref_dly[index].win_center > center_dly[byte].max_center) - center_dly[byte].max_center = vref_dly[index].win_center; + if (params->have_full_k_params && (bypass_tx)) { + dramc_dbg("bypass TX\n"); + for (u8 byte = 0; byte < DQS_NUMBER; byte++) { + center_dly[byte].min_center = params->tx_center_min[chn][rank][byte]; + center_dly[byte].max_center = params->tx_center_max[chn][rank][byte]; + for (u8 bit = 0; bit < DQS_BIT_NUMBER; bit++) { + index = bit + 8 * byte; + vref_dly[index].win_center = params->tx_win_center[chn][rank][index]; + vref_dly[index].best_first = params->tx_first_pass[chn][rank][index]; + vref_dly[index].best_last = params->tx_last_pass[chn][rank][index]; + } } - dramc_dbg("[channel %d] [rank %d] byte:%d, center_dly[byte].min_center:%d, center_dly[byte].max_center:%d\n", - chn, rank, byte, center_dly[byte].min_center, - center_dly[byte].max_center); + } else { + for (u8 byte = 0; byte < DQS_NUMBER; byte++) { + center_dly[byte].min_center = 0xffff; + center_dly[byte].max_center = 0; + + for (u8 bit = 0; bit < DQS_BIT_NUMBER; bit++) { + index = bit + 8 * byte; + if (vref_dly[index].win_center < center_dly[byte].min_center) + center_dly[byte].min_center = vref_dly[index].win_center; + if (vref_dly[index].win_center > center_dly[byte].max_center) + center_dly[byte].max_center = vref_dly[index].win_center; + } + dramc_dbg("[channel %d] [rank %d] byte:%d, center_dly[byte].min_center:%d, center_dly[byte].max_center:%d\n", + chn, rank, byte, center_dly[byte].min_center, + center_dly[byte].max_center); + } }
for (u8 byte = 0; byte < DQS_NUMBER; byte++) { @@ -1681,12 +1715,26 @@
u8 fsp = get_freq_fsq(freq_group); u8 vref_range = !fsp; + bool bypass_tx = !fsp;
dramc_get_vref_prop(rank, type, fsp, &vref_scan_enable, &vref_begin, &vref_end); dramc_get_dly_range(chn, rank, type, freq_group, dq_precal_result, &dly_begin, &dly_end, params);
+ if (params->have_full_k_params) { + if (type == RX_WIN_TEST_ENG && vref_scan_enable == 1) { + vref_begin = params->rx_vref[chn]; + vref_end = vref_begin + 1; + dramc_dbg("bypass RX vref:%d\n", vref_begin); + } else if (type == TX_WIN_DQ_ONLY) { + vref_begin = params->tx_vref[chn][rank]; + vref_end = vref_begin + 1; + dramc_dbg("bypass TX vref:%d\n", vref_begin); + } + vref_dly.best_vref = vref_begin; + } + if ((type == RX_WIN_RD_DQC || type == RX_WIN_TEST_ENG) && fsp == FSP_0) dly_step = 2;
@@ -1705,98 +1753,112 @@ vref_step = 2; }
- if (type == RX_WIN_RD_DQC) { - dramc_rx_rd_dqc_init(chn, rank); - } else { - if (type == RX_WIN_TEST_ENG) - dramc_rx_vref_pre_setting(chn); - dummy_rd_bak_engine2 = read32(&ch[chn].ao.dummy_rd); - dramc_engine2_init(chn, rank, TEST2_1_CAL, TEST2_2_CAL, false); - } - - vref_dly.max_win_sum = 0; - for (vref = vref_begin; vref < vref_end; vref += vref_step) { - small_reg_value = 0xff; - finish_bit = 0; - if (type == TX_WIN_DQ_ONLY) - vref_use = vref | (vref_range << 6); - else - vref_use = vref; - - for (size_t bit = 0; bit < DQ_DATA_WIDTH; bit++) { - win_perbit[bit].first_pass = PASS_RANGE_NA; - win_perbit[bit].last_pass = PASS_RANGE_NA; - win_perbit[bit].best_first = PASS_RANGE_NA; - win_perbit[bit].best_last = PASS_RANGE_NA; + if (params->have_full_k_params && bypass_tx && + (type == TX_WIN_DQ_ONLY || type == TX_WIN_DQ_DQM)) { + dramc_set_tx_best_dly(chn, rank, bypass_tx,vref_dly.perbit_dly, type, + freq_group, dq_precal_result, dly_cell_unit, params); + } else { + if (type == RX_WIN_RD_DQC) { + dramc_rx_rd_dqc_init(chn, rank); + } else { + if (type == RX_WIN_TEST_ENG) + dramc_rx_vref_pre_setting(chn); + dummy_rd_bak_engine2 = read32(&ch[chn].ao.dummy_rd); + dramc_engine2_init(chn, rank, TEST2_1_CAL, TEST2_2_CAL, false); }
- if (vref_scan_enable) - dramc_set_vref(chn, rank, type, vref_use); - - if (type == RX_WIN_RD_DQC || type == RX_WIN_TEST_ENG) { - dramc_set_rx_dly_factor(chn, rank, - RX_DQM, FIRST_DQ_DELAY); - dramc_set_rx_dly_factor(chn, rank, - RX_DQ, FIRST_DQ_DELAY); - } - - for (dly = dly_begin; dly < dly_end; dly += dly_step) { - dramc_set_dqdqs_dly(chn, rank, type, &small_reg_value, dly); - - err_value = dram_k_perbit(chn, type); - if (!vref_scan_enable) - dramc_dbg("%d ", dly); + vref_dly.max_win_sum = 0; + for (vref = vref_begin; vref < vref_end; vref += vref_step) { + small_reg_value = 0xff; + finish_bit = 0; + if (type == TX_WIN_DQ_ONLY) + vref_use = vref | (vref_range << 6); + else + vref_use = vref;
for (size_t bit = 0; bit < DQ_DATA_WIDTH; bit++) { - bool bit_fail = (err_value & ((u32) 1 << bit)) != 0; - - /* pass window bigger than 7, consider as real pass window */ - if (dramc_check_dqdqs_win(&(win_perbit[bit]), - dly, dly_end, bit_fail) > 7) - finish_bit |= (1 << bit); - - if (vref_scan_enable) - continue; - dramc_dbg("%s", bit_fail ? "x" : "o"); - if (bit % DQS_BIT_NUMBER == 7) - dramc_dbg(" "); + win_perbit[bit].first_pass = PASS_RANGE_NA; + win_perbit[bit].last_pass = PASS_RANGE_NA; + win_perbit[bit].best_first = PASS_RANGE_NA; + win_perbit[bit].best_last = PASS_RANGE_NA; }
- if (!vref_scan_enable) - dramc_dbg(" [MSB]\n"); + if (vref_scan_enable) + dramc_set_vref(chn, rank, type, vref_use);
- if (finish_bit == 0xffff && (err_value & 0xffff) == 0xffff) { - dramc_dbg("all bits window found, early break! delay=0x%x\n", - dly); - break; + if (type == RX_WIN_RD_DQC || type == RX_WIN_TEST_ENG) { + dramc_set_rx_dly_factor(chn, rank, + RX_DQM, FIRST_DQ_DELAY); + dramc_set_rx_dly_factor(chn, rank, + RX_DQ, FIRST_DQ_DELAY); + } + + if (params->have_full_k_params && (type == RX_WIN_RD_DQC ||type == RX_WIN_TEST_ENG)) { + dramc_dbg("bypass RX params\n"); + for (size_t bit = 0; bit < DQ_DATA_WIDTH; bit++) { + win_perbit[bit].best_first = params->rx_firspass[chn][rank][bit]; + win_perbit[bit].best_last = params->rx_lastpass[chn][rank][bit]; + } + } else { + for (dly = dly_begin; dly < dly_end; dly += dly_step) { + dramc_set_dqdqs_dly(chn, rank, type, &small_reg_value, dly); + + err_value = dram_k_perbit(chn, type); + if (!vref_scan_enable) + dramc_dbg("%d ", dly); + + for (size_t bit = 0; bit < DQ_DATA_WIDTH; bit++) { + bool bit_fail = (err_value & ((u32) 1 << bit)) != 0; + + /* pass window bigger than 7, consider as real pass window */ + if (dramc_check_dqdqs_win(&(win_perbit[bit]), + dly, dly_end, bit_fail) > 7) + finish_bit |= (1 << bit); + + if (vref_scan_enable) + continue; + dramc_dbg("%s", bit_fail ? "x" : "o"); + if (bit % DQS_BIT_NUMBER == 7) + dramc_dbg(" "); + } + + if (!vref_scan_enable) + dramc_dbg(" [MSB]\n"); + + if (finish_bit == 0xffff && (err_value & 0xffff) == 0xffff) { + dramc_dbg("all bits window found, early break! delay=0x%x\n", + dly); + break; + } } }
- for (size_t bit = 0; bit < DQ_DATA_WIDTH; bit++) - dramc_dbg("Dq[%zd] win width (%d ~ %d) %d\n", bit, - win_perbit[bit].best_first, win_perbit[bit].best_last, - win_perbit[bit].best_last - win_perbit[bit].best_first); + for (size_t bit = 0; bit < DQ_DATA_WIDTH; bit++) + dramc_dbg("Dq[%zd] win width (%d ~ %d) %d\n", bit, + win_perbit[bit].best_first, win_perbit[bit].best_last, + win_perbit[bit].best_last - win_perbit[bit].best_first);
- if (dramk_calc_best_vref(type, vref_use, &vref_dly, win_perbit, &win_min_max)) - break; + if (dramk_calc_best_vref(type, vref_use, &vref_dly, win_perbit, &win_min_max)) + break; + } + + if (type == RX_WIN_RD_DQC) { + dramc_rx_rd_dqc_end(chn); + } else { + dramc_engine2_end(chn); + write32(&ch[chn].ao.dummy_rd, dummy_rd_bak_engine2); + } + + if (vref_scan_enable && type == RX_WIN_TEST_ENG) + dramc_set_vref(chn, rank, type, vref_dly.best_vref); + + if (type == RX_WIN_RD_DQC || type == RX_WIN_TEST_ENG) + dramc_set_rx_best_dly(chn, rank, vref_dly.perbit_dly); + else + dramc_set_tx_best_dly(chn, rank, false, vref_dly.perbit_dly, type, + freq_group, dq_precal_result, dly_cell_unit, params); }
- if (type == RX_WIN_RD_DQC) { - dramc_rx_rd_dqc_end(chn); - } else { - dramc_engine2_end(chn); - write32(&ch[chn].ao.dummy_rd, dummy_rd_bak_engine2); - } - - if (vref_scan_enable && type == RX_WIN_TEST_ENG) - dramc_set_vref(chn, rank, type, vref_dly.best_vref); - - if (type == RX_WIN_RD_DQC || type == RX_WIN_TEST_ENG) - dramc_set_rx_best_dly(chn, rank, vref_dly.perbit_dly); - else - dramc_set_tx_best_dly(chn, rank, false, vref_dly.perbit_dly, type, - freq_group, dq_precal_result, dly_cell_unit, params); - if (vref_scan_enable && type == TX_WIN_DQ_ONLY) dramc_set_vref(chn, rank, type, vref_dly.best_vref);
@@ -1843,40 +1905,45 @@ u32 dummy_rd_backup = read32(&ch[chn].ao.dummy_rd); dramc_engine2_init(chn, rank, TEST2_1_CAL, TEST2_2_CAL, false);
- for (datlat = datlat_start; datlat < DATLAT_TAP_NUMBER; datlat++) { - dramc_dle_factor_handler(chn, datlat, freq_group); + if (params->have_full_k_params) { + best_step = params->rx_datlat[chn][rank]; + dramc_dbg("bypass DATLAT, best_step:%d\n", best_step); + } else { + for (datlat = datlat_start; datlat < DATLAT_TAP_NUMBER; datlat++) { + dramc_dle_factor_handler(chn, datlat, freq_group);
- u32 err = dramc_engine2_run(chn, TE_OP_WRITE_READ_CHECK); - if (err == 0) { - if (begin == 0) { - first = datlat; - begin = 1; + u32 err = dramc_engine2_run(chn, TE_OP_WRITE_READ_CHECK); + if (err == 0) { + if (begin == 0) { + first = datlat; + begin = 1; + } + if (begin == 1) { + sum++; + if (sum > 4) + break; + } + } else { + if (begin == 1) + begin = 0xff; } - if (begin == 1) { - sum++; - if (sum > 4) - break; - } - } else { - if (begin == 1) - begin = 0xff; + + dramc_dbg("Datlat=%2d, err_value=0x%4x, sum=%d\n", datlat, err, sum); }
- dramc_dbg("Datlat=%2d, err_value=0x%4x, sum=%d\n", datlat, err, sum); + dramc_engine2_end(chn); + write32(&ch[chn].ao.dummy_rd, dummy_rd_backup); + + assert(sum != 0); + + if (sum <= 3) + best_step = first + (sum >> 1); + else + best_step = first + 2; + dramc_dbg("First_step=%d, total pass=%d, best_step=%d\n", + begin, sum, best_step); }
- dramc_engine2_end(chn); - write32(&ch[chn].ao.dummy_rd, dummy_rd_backup); - - assert(sum != 0); - - if (sum <= 3) - best_step = first + (sum >> 1); - else - best_step = first + 2; - dramc_dbg("First_step=%d, total pass=%d, best_step=%d\n", - begin, sum, best_step); - dramc_dle_factor_handler(chn, best_step, freq_group);
clrsetbits_le32(&ch[chn].ao.padctrl, 0x3 | (0x1 << 3), diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c index 818458c..f51428b 100644 --- a/src/soc/mediatek/mt8183/emi.c +++ b/src/soc/mediatek/mt8183/emi.c @@ -383,17 +383,19 @@ pmic_set_vdram2_vol(vddq); }
-void mt_set_emi(const struct sdram_params *params) +void mt_set_emi(const struct sdram_params *freq_params) { - u32 current_freq = LP4X_HIGH_FREQ; + u8 current_freq = LP4X_HIGH_FREQ; + const struct sdram_params *params = NULL;
#if DUAL_FREQ_K - u32 low_freq, middle_freq, high_freq; + u8 low_freq, middle_freq, high_freq;
low_freq = LP4X_LOW_FREQ; middle_freq = LP4X_MIDDLE_FREQ; high_freq = LP4X_HIGH_FREQ; current_freq = low_freq; + params = &freq_params[current_freq]; #endif
set_dram_voltage_by_freq(current_freq); @@ -402,11 +404,13 @@
#if DUAL_FREQ_K current_freq = middle_freq; + params = &freq_params[current_freq]; set_dram_voltage_by_freq(current_freq); dfs_init_for_calibration(params, current_freq); do_calib(params, current_freq);
current_freq = high_freq; + params = &freq_params[current_freq]; set_dram_voltage_by_freq(current_freq); dfs_init_for_calibration(params, current_freq); do_calib(params, current_freq); diff --git a/src/soc/mediatek/mt8183/include/soc/emi.h b/src/soc/mediatek/mt8183/include/soc/emi.h index 264d918..07c4827 100644 --- a/src/soc/mediatek/mt8183/include/soc/emi.h +++ b/src/soc/mediatek/mt8183/include/soc/emi.h @@ -21,10 +21,42 @@ #include <soc/dramc_common_mt8183.h>
struct sdram_params { - u32 impedance[2][4]; + bool have_full_k_params; + u16 frequency; u8 wr_level[CHANNEL_MAX][RANK_MAX][DQS_NUMBER]; - u8 cbt_cs[CHANNEL_MAX][RANK_MAX]; - u8 cbt_mr12[CHANNEL_MAX][RANK_MAX]; + + /* DUTY */ + s8 duty_clk_delay[CHANNEL_MAX]; + s8 duty_dqs_delay[CHANNEL_MAX][DQS_NUMBER]; + + /* CBT */ + u8 cbt_final_vref[CHANNEL_MAX][RANK_MAX]; + u8 cbt_clk_dly[CHANNEL_MAX][RANK_MAX]; + u8 cbt_cmd_dly[CHANNEL_MAX][RANK_MAX]; + u8 cbt_cs_dly[CHANNEL_MAX][RANK_MAX]; + + /* Gating */ + u8 gating2T[CHANNEL_MAX][RANK_MAX][DQS_NUMBER]; + u8 gating05T[CHANNEL_MAX][RANK_MAX][DQS_NUMBER]; + u8 gating_fine_tune[CHANNEL_MAX][RANK_MAX][DQS_NUMBER]; + u8 gating_pass_count[CHANNEL_MAX][RANK_MAX][DQS_NUMBER]; + + /* TX perbit */ + u8 tx_vref[CHANNEL_MAX][RANK_MAX]; + u16 tx_center_min[CHANNEL_MAX][RANK_MAX][DQS_NUMBER]; + u16 tx_center_max[CHANNEL_MAX][RANK_MAX][DQS_NUMBER]; + u16 tx_win_center[CHANNEL_MAX][RANK_MAX][DQ_DATA_WIDTH]; + u16 tx_first_pass[CHANNEL_MAX][RANK_MAX][DQ_DATA_WIDTH]; + u16 tx_last_pass[CHANNEL_MAX][RANK_MAX][DQ_DATA_WIDTH]; + + /* datlat */ + u8 rx_datlat[CHANNEL_MAX][RANK_MAX]; + + /* RX perbit */ + u8 rx_vref[CHANNEL_MAX]; + s16 rx_firspass[CHANNEL_MAX][RANK_MAX][DQ_DATA_WIDTH]; + u8 rx_lastpass[CHANNEL_MAX][RANK_MAX][DQ_DATA_WIDTH]; + u32 emi_cona_val; u32 emi_conh_val; u32 emi_conf_val; @@ -47,7 +79,7 @@ size_t sdram_size(void); const struct sdram_params *get_sdram_config(void); void enable_emi_dcm(void); -void mt_set_emi(const struct sdram_params *params); -void mt_mem_init(const struct sdram_params *params); +void mt_set_emi(const struct sdram_params *freq_params); +void mt_mem_init(const struct sdram_params *freq_params);
#endif /* SOC_MEDIATEK_MT8183_EMI_H */ diff --git a/src/soc/mediatek/mt8183/memory.c b/src/soc/mediatek/mt8183/memory.c index b2c7441..67f6c65 100644 --- a/src/soc/mediatek/mt8183/memory.c +++ b/src/soc/mediatek/mt8183/memory.c @@ -19,12 +19,12 @@ #include <soc/emi.h> #include <symbols.h>
-void mt_mem_init(const struct sdram_params *params) +void mt_mem_init(const struct sdram_params *freq_params) { u64 rank_size[RANK_MAX];
/* memory calibration */ - mt_set_emi(params); + mt_set_emi(freq_params);
if (CONFIG(MEMORY_TEST)) { size_t r;