Hello Duan huayang,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/44723
to review the following change.
Change subject: soc/mediatek/mt8192: set dramc dqsosc shuffle setting ......................................................................
soc/mediatek/mt8192: set dramc dqsosc shuffle setting
Signed-off-by: Huayang Duan huayang.duan@mediatek.com Change-Id: Icf638f4d88a10ce451d63ea431facb2899b2be85 --- M src/soc/mediatek/mt8192/dramc_pi_calibration_api.c M src/soc/mediatek/mt8192/dramc_pi_main.c 2 files changed, 225 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/23/44723/1
diff --git a/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c index ce03db4..2082f4d 100644 --- a/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c @@ -2794,3 +2794,223 @@ dramc_dle_factor_handler(chn, final_datlat); }
+static void dramc_start_dqsosc(const struct ddr_cali* cali) +{ + u8 chn = cali->chn; + const u32 timeout = 100; + + struct reg_bak regs_bak[] = { + {&ch[chn].ao.swcmd_en}, + {&ch[chn].ao.swcmd_ctrl0}, + {&ch[chn].ao.dramc_pd_ctrl}, + {&ch[chn].ao.ckectrl}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++) + regs_bak[i].value = read32(regs_bak[i].addr); + + SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl, DRAMC_PD_CTRL_APHYCKCG_FIXOFF, 1); + SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl, DRAMC_PD_CTRL_TCKFIXON, 1); + + udelay(1); + cke_fix_onoff(cali, chn, RANK_MAX, CKE_FIXON); + SET32_BITFIELDS(&ch[chn].ao.swcmd_en, SWCMD_EN_WCK2DQI_START_SWTRIG, 1); + + if (!wait_us(timeout, READ32_BITFIELD(&ch[chn].nao.spcmdresp3, + SPCMDRESP3_WCK2DQI_START_SWTRIG_RESPONSE))) { + dramc_err("ZQCAL Start fail (time out)\n"); + return; + } + SET32_BITFIELDS(&ch[chn].ao.swcmd_en, SWCMD_EN_WCK2DQI_START_SWTRIG, 0); + + for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++) + write32(regs_bak[i].addr, regs_bak[i].value); +} + +static u16 dramc_dqsosc_auto(const struct ddr_cali* cali) +{ + u8 chn, rank; + u8 mr18, mr19, mr23; + u32 frequency; + + u16 dqs_cnt; + u16 dqsosc_cnt[RANK_MAX]; + u16 final_dqsosc; + + chn = cali->chn; + rank = cali->rank; + mr23 = cali->mr_value->mr23[chn][rank]; + frequency = get_frequency(cali); + + struct reg_bak regs_bak[] = { + {&ch[chn].ao.dramc_pd_ctrl}, + {&ch[chn].ao.ckectrl} + }; + for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++) + regs_bak[i].value = read32(regs_bak[i].addr); + + dramc_mode_reg_write_by_rank(cali, chn, rank, 23, mr23); + SET32_BITFIELDS(&ch[chn].ao.shu_dqsosc_set0, SHU_DQSOSC_SET0_DQSOSCENDIS, 1); + SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl, DRAMC_PD_CTRL_APHYCKCG_FIXOFF, 1); + SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl, DRAMC_PD_CTRL_TCKFIXON, 1); + + cke_fix_onoff(cali, chn, rank, CKE_FIXON); + dramc_start_dqsosc(cali); + udelay(1); + + mr18 = dramc_mode_reg_read_by_rank(chn, rank, 18); + mr19 = dramc_mode_reg_read_by_rank(chn, rank, 19); + + dqs_cnt = mr18 | (mr19 << 8); + if (dqs_cnt != 0) + dqsosc_cnt[0] = mr23 * 16 * 1000000 / (2 * dqs_cnt * frequency); + else + dqsosc_cnt[0] = 0; + + dqs_cnt = (mr18 >> 8) | (mr19 & 0xff00); + if (dqs_cnt != 0) + dqsosc_cnt[1] = mr23 * 16 * 1000000 / (2 * dqs_cnt * frequency); + else + dqsosc_cnt[1] = 0; + dramc_dbg("[DQSOSCAuto] RK%d, (LSB)MR18= %#x, (MSB)MR19= %#x, tDQSOscB0 = %d ps tDQSOscB1 = %d ps\n", + rank, mr18, mr19, dqsosc_cnt[0], dqsosc_cnt[1]); + + cali->mr_value->mr18[chn][rank] = mr18; + cali->mr_value->mr19[chn][rank] = mr19; + + if (dqsosc_cnt[1] != 0 && dqsosc_cnt[1] < dqsosc_cnt[0]) + final_dqsosc = dqsosc_cnt[1]; + else + final_dqsosc = dqsosc_cnt[0]; + + for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++) + write32(regs_bak[i].addr, regs_bak[i].value); + + return final_dqsosc; +} + +void dramc_dqsosc_set_mr18_mr19(const struct ddr_cali* cali, + u16 *dqsosc_thrd_inc, u16 *dqsosc_thrd_dec) +{ + u8 chn, rank; + u8 mr18, mr19, mr23; + u16 dqsosc_cnt[2], dqsosc; + u32 tCK; + + chn = cali->chn; + rank = cali->rank; + + dqsosc = dramc_dqsosc_auto(cali); + mr18 = cali->mr_value->mr18[chn][rank]; + mr19 = cali->mr_value->mr19[chn][rank]; + mr23 = cali->mr_value->mr23[chn][rank]; + + dqsosc_cnt[0] = mr18 | (mr19 << 8); + dqsosc_cnt[1] = (mr18 >> 8) | ((mr19 & 0xff00)); + + if ((get_cbt_mode(cali) == CBT_NORMAL_MODE) && (dqsosc_cnt[1] == 0)) + dqsosc_cnt[1] = dqsosc_cnt[0]; + + SET32_BITFIELDS(&ch[chn].ao.shu_rk[rank].shurk_dqsosc, + SHURK_DQSOSC_DQSOSC_BASE_RK0, dqsosc_cnt[0], + SHURK_DQSOSC_DQSOSC_BASE_RK0_B1, dqsosc_cnt[1]); + + tCK = 1000000 / get_frequency(cali); + if (dqsosc != 0) { + dqsosc_thrd_inc[rank] = (3 * mr23 * tCK * tCK) / (dqsosc * dqsosc * 20); + dqsosc_thrd_dec[rank] = (mr23 * tCK * tCK) / (dqsosc * dqsosc * 10); + } + + dramc_dbg("CH%d_RK%d: MR19=0x%X, MR18=0x%X, DQSOSC=%d, MR23=%u, INC=%u, DEC=%u\n", + chn, rank, mr19, mr18, dqsosc, mr23, + dqsosc_thrd_inc[rank], dqsosc_thrd_dec[rank]); +} + +void dqsosc_shu_settings(const struct ddr_cali* cali, + u16 *dqsosc_thrd_inc, u16 *dqsosc_thrd_dec) +{ + u8 prd_cnt_div = 4; + u8 filt_pi_thrd = 0; + u8 w2r_sel = 0; + u8 dqsosc_cr_cnt = 0, is_div4 = 0, round_up= 0; + u16 dqsosc_en_cnt = 0xfff; + u16 prd_cnt = 0x3ff, prd_cnt_tmp = 0x3ff; + + u8 chn = cali->chn; + u32 frequency = get_frequency(cali); + dram_freq_grp freq_group = cali->freq_group; + u8 mr23[RANK_MAX] = {cali->mr_value->mr23[chn][0], cali->mr_value->mr23[chn][1]}; + + SET32_BITFIELDS(&ch[chn].ao.shu_tx_set0, SHU_TX_SET0_DQS2DQ_FILT_PITHRD, 0x0); + SET32_BITFIELDS(&ch[chn].ao.dqsoscr, DQSOSCR_R_DMDQS2DQ_FILT_OPT, 0x0); + + switch (freq_group) { + case DDRFREQ_400: + filt_pi_thrd = 0x5; + w2r_sel = 0x2; + prd_cnt_div = 2; + is_div4 = 1; + break; + case DDRFREQ_600: + filt_pi_thrd = 0x6; + w2r_sel = 0x5; + break; + case DDRFREQ_800: + filt_pi_thrd = 0x6; + w2r_sel = 0x5; + break; + case DDRFREQ_933: + filt_pi_thrd = 0x9; + w2r_sel = 0x2; + break; + case DDRFREQ_1200: + filt_pi_thrd = 0xb; + w2r_sel = 0x2; + break; + case DDRFREQ_1600: + filt_pi_thrd = 0xE; + w2r_sel = 0x2; + break; + case DDRFREQ_2133: + filt_pi_thrd = 0x17; + w2r_sel = 0x2; + break; + default: + die("Invalid DDR frequency group %u\n", freq_group); + return; + } + + dqsosc_cr_cnt = ((frequency << is_div4)) / 100; + if ((frequency % 100) != 0) + dqsosc_cr_cnt++; + + if (mr23[RANK_1] > mr23[RANK_0]) + prd_cnt_tmp = ((mr23[RANK_1] * 100) / prd_cnt_div); + else + prd_cnt_tmp = ((mr23[RANK_0] * 100) / prd_cnt_div); + + prd_cnt = (prd_cnt_tmp + dqsosc_cr_cnt * 100 / 16) / 100; + round_up = (prd_cnt_tmp + dqsosc_cr_cnt *100 / 16) % 100; + if (round_up != 0) + prd_cnt++; + + SET32_BITFIELDS(&ch[chn].ao.shu_dqsosc_set0, + SHU_DQSOSC_SET0_DQSOSC_PRDCNT, prd_cnt); + SET32_BITFIELDS(&ch[chn].ao.shu_dqsoscr, + SHU_DQSOSCR_DQSOSCRCNT, dqsosc_cr_cnt); + SET32_BITFIELDS(&ch[chn].ao.shu_tx_set0, + SHU_TX_SET0_DQS2DQ_FILT_PITHRD, filt_pi_thrd); + SET32_BITFIELDS(&ch[chn].ao.shu_tx_set0, + SHU_TX_SET0_TXUPD_W2R_SEL, w2r_sel, + SHU_TX_SET0_TXUPD_SEL, 0x0); + + for (u8 rk = RANK_0; rk < cali->support_ranks; rk++) { + SET32_BITFIELDS(&ch[chn].ao.shu_rk[rk].shurk_dqsosc_thrd, + SHURK_DQSOSC_THRD_DQSOSCTHRD_INC, dqsosc_thrd_inc[rk]); + SET32_BITFIELDS(&ch[chn].ao.shu_rk[rk].shurk_dqsosc_thrd, + SHURK_DQSOSC_THRD_DQSOSCTHRD_DEC, dqsosc_thrd_dec[rk]); + } + + SET32_BITFIELDS(&ch[chn].ao.shu_dqsosc_set0, + SHU_DQSOSC_SET0_DQSOSCENCNT, dqsosc_en_cnt); +} diff --git a/src/soc/mediatek/mt8192/dramc_pi_main.c b/src/soc/mediatek/mt8192/dramc_pi_main.c index 052b320..11c5d3a 100644 --- a/src/soc/mediatek/mt8192/dramc_pi_main.c +++ b/src/soc/mediatek/mt8192/dramc_pi_main.c @@ -242,6 +242,8 @@ { u8 txdly_min, txdly_max; u8 dqs_final_delay[RANK_MAX][DQS_NUMBER]; + u16 dqsosc_thrd_inc[RANK_MAX]; + u16 dqsosc_thrd_dec[RANK_MAX];
cali->chn = chn; SET32_BITFIELDS(&ch[chn].phy_ao.ca_cmd2, @@ -290,7 +292,10 @@ dramc_rx_datlat_cal(cali); dramc_rx_window_perbit_cal(cali, RX_WIN_TEST_ENG); dramc_tx_oe_calibration(cali); + dramc_auto_refresh_switch(chn, false); + dramc_dqsosc_set_mr18_mr19(cali, dqsosc_thrd_inc, dqsosc_thrd_dec); } + dqsosc_shu_settings(cali, dqsosc_thrd_inc, dqsosc_thrd_dec); dramc_rx_dqs_gating_post_process(cali, txdly_min, txdly_max); dramc_dual_rank_rx_datlat_cal(cali); }