Tristan Hsieh has uploaded this change for review. ( https://review.coreboot.org/28843
Change subject: mediatek/mt8183: Add DDR driver of rx datlat calibration part ......................................................................
mediatek/mt8183: Add DDR driver of rx datlat calibration part
BUG=b:80501386 BRANCH=none TEST=Boots correctly on Kukui, and inits DRAM successfully with related patches.
Change-Id: Ia20de54633bf1077bd469df75ccb4390308e0b97 Signed-off-by: Huayang Duan huayang.duan@mediatek.com --- M src/soc/mediatek/mt8183/dramc_pi_calibration_api.c 1 file changed, 78 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/43/28843/1
diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c index f6ab9a0..2295f39 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -1701,6 +1701,81 @@ return 0; }
+ +static void dle_factor_handler(u8 chn, u8 curr_val) +{ + curr_val = MAX(curr_val, 2); + clrsetbits_le32(&ch[chn].ao.shu[0].conf[1], + (SHU_CONF1_DATLAT_MASK) | (SHU_CONF1_DATLAT_DSEL_MASK) | + (SHU_CONF1_DATLAT_DSEL_PHY_MASK), + (curr_val << SHU_CONF1_DATLAT_SHIFT) | + ((curr_val - 2) << SHU_CONF1_DATLAT_DSEL_SHIFT) | + ((curr_val - 2) << SHU_CONF1_DATLAT_DSEL_PHY_SHIFT)); + dram_phy_reset(chn); +} + +static u8 dramc_rx_datlat_cal(u8 chn, u8 rank) +{ + u32 err = 0xffffffff, datlat_begin = 7; + s32 datlat, first = -1, sum = 0, best_step = 0; + + best_step = read32(&ch[chn].ao.shu[0].conf[1]) & + (SHU_CONF1_DATLAT_MASK); + + dramc_show("[DATLAT] start. CH%d RK%d DATLAT Default: 0x%x\n", + chn, rank, best_step); + + u32 dummy_rd_backup = read32(&ch[chn].ao.dummy_rd); + dramc_engine2_init(chn, rank, 0x400, 0); + + for (datlat = datlat_begin; datlat < DATLAT_TAP_NUMBER; datlat++) { + dle_factor_handler(chn, datlat); + + err = dramc_engine2_run(chn, TE_OP_WRITE_READ_CHECK); + + if (err && (first != -1)) + break; + + if (sum > 4) + break; + + if (err == 0) { + if (first == -1) + first = datlat; + + sum++; + } + + dramc_show("TAP=%2d, err_value=0x%8x, sum=%d\n", + datlat, err, sum); + } + + dramc_engine2_end(chn); + write32(&ch[chn].ao.dummy_rd, dummy_rd_backup); + + best_step = first + (sum >> 1); + dramc_dbg("first_step=%d, total pass=%d, best_step=%d\n", + first, sum, best_step); + + assert(sum != 0); + + dle_factor_handler(chn, best_step); + + clrsetbits_le32(&ch[chn].ao.padctrl, PADCTRL_DQIENQKEND_MASK, + (0x1 << PADCTRL_DQIENQKEND_SHIFT) | + (0x1 << PADCTRL_DQIENLATEBEGIN_SHIFT)); + + return (u8)best_step; +} + +static void dramc_dual_rank_rx_datlat_cal(u8 chn, u8 datlat0, u8 datlat1) +{ + u8 final_datlat = MAX(datlat0, datlat1); + dle_factor_handler(chn, final_datlat); + dramc_dbg("[%s] RK0: %d, RK1: %d, Final_Datlat %d\n", + __func__, datlat0, datlat1, final_datlat); +} + static void dramc_rx_dqs_gating_post_process(u8 chn) { u8 dqs, rank_rx_dvs, dqsinctl, rank; @@ -1801,6 +1876,7 @@
void dramc_calibrate_all_channels(const struct sdram_params *pams) { + u8 rx_datlat[RANK_MAX] = {0x0}; for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { for (u8 rk = RANK_0; rk < RANK_MAX; rk++) { dramc_show("start K ch:%d, rank:%d\n", chn, rk); @@ -1812,9 +1888,11 @@ dramc_window_perbit_cal(chn, rk, RX_WIN_RD_DQC, pams); dramc_window_perbit_cal(chn, rk, TX_WIN_DQ_DQM, pams); dramc_window_perbit_cal(chn, rk, TX_WIN_DQ_ONLY, pams); + rx_datlat[rk] = dramc_rx_datlat_cal(chn, rk); dramc_window_perbit_cal(chn, rk, RX_WIN_TEST_ENG, pams); }
dramc_rx_dqs_gating_post_process(chn); + dramc_dual_rank_rx_datlat_cal(chn, rx_datlat[0], rx_datlat[1]); } }