huayang duan has uploaded this change for review.

View Change

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;

To view, visit change 35164. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I9ef4265dd369a1c276bb02294696556df927e7bc
Gerrit-Change-Number: 35164
Gerrit-PatchSet: 1
Gerrit-Owner: huayang duan <huayangduan@gmail.com>
Gerrit-MessageType: newchange