Tristan Hsieh has uploaded this change for review. ( https://review.coreboot.org/28839
Change subject: mediatek/mt8183: Add DDR driver of cmd bus training part ......................................................................
mediatek/mt8183: Add DDR driver of cmd bus training part
BUG=b:80501386 BRANCH=none TEST=Boots correctly on Kukui, and inits DRAM successfully with related patches.
Change-Id: Icb281f1b23c637971497eb28ed428235adf42f2d Signed-off-by: Huayang Duan huayang.duan@mediatek.com --- M src/soc/mediatek/mt8183/dramc_pi_calibration_api.c M src/soc/mediatek/mt8183/emi.c M src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h 3 files changed, 94 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/39/28839/1
diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c index c5ec9c7..0542baa 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -20,6 +20,88 @@ #include <soc/dramc_register.h> #include <soc/dramc_pi_api.h>
+static void auto_refresh_switch(u8 chn, u8 option) +{ + clrsetbits_le32(&ch[chn].ao.refctrl0, 1 << REFCTRL0_REFDIS_SHIFT, + (option ? 0 : 1) << REFCTRL0_REFDIS_SHIFT); + + if (option == DISABLE) { + /* because HW will actually disable autorefresh + * after refresh_queue empty, we need to wait quene empty */ + udelay(((read32(&ch[chn].nao.misc_statusa) & + MISC_STATUSA_REFRESH_QUEUE_CNT_MASK) >> + MISC_STATUSA_REFRESH_QUEUE_CNT_SHIFT)*4); + } +} + +static void dramc_cke_fix_onoff(int option, u8 chn) +{ + u8 on = 0, off = 0; + + /* if CKE is dynamic, set both CKE fix On and Off as 0 */ + if (option != CKE_DYNAMIC) { + on = option; + off = (1 - option); + } + + clrsetbits_le32(&ch[chn].ao.ckectrl, + (0x1 << 6) | (0x1 << 7), (on << 6) | (off << 7)); +} + +static void dramc_mode_reg_write(u8 chn, u8 mr_idx, u8 value) +{ + u32 rank = 0; + u32 ckectrl_bak = read32(&ch[chn].ao.ckectrl); + + dramc_cke_fix_onoff(CKE_FIXON, chn); + clrsetbits_le32(&ch[chn].ao.mrs, + MRS_MRSMA_MASK, mr_idx << MRS_MRSMA_SHIFT); + clrsetbits_le32(&ch[chn].ao.mrs, + MRS_MRSOP_MASK, value << MRS_MRSOP_SHIFT); + setbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_MRWEN_SHIFT); + + while ((read32(&ch[chn].nao.spcmdresp) & 1) == 0) { + dramc_dbg("wait MRW command fired\n"); + udelay(1); + } + + clrbits_le32(&ch[chn].ao.spcmd, 1 << SPCMD_MRWEN_SHIFT); + setbits_le32(&ch[chn].ao.ckectrl, ckectrl_bak); + + rank = (read32(&ch[chn].ao.mrs) & MRS_MRSRK_MASK) >> MRS_MRSRK_SHIFT; + dramc_dbg("Write Rank%d MR%d =0x%x\n", rank, mr_idx, value); +} + +static void dramc_mode_reg_write_by_rank(u8 chn, u8 rank, + u8 mr_idx, u8 value) +{ + u32 mrs_back = read32(&ch[chn].ao.mrs) & MRS_MRSRK_MASK; + + clrsetbits_le32(&ch[chn].ao.mrs, + MRS_MRSRK_MASK, rank << MRS_MRSRK_SHIFT); + dramc_mode_reg_write(chn, mr_idx, value); + clrsetbits_le32(&ch[chn].ao.mrs, MRS_MRSRK_MASK, mrs_back); +} + +static void cmd_bus_training(u8 chn, u8 rank, + const struct sdram_params *params) +{ + u32 cbt_cs, mr12_value; + + cbt_cs = params->cbt_cs[chn][rank]; + mr12_value = params->cbt_mr12[chn][rank]; + + dramc_dbg("start chn:%d, rank:%d, cbt_cs:0x%x, mr12_value:0x%x\n", + chn, rank, cbt_cs, mr12_value); + + /* 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); + + /* cbt_set_vref */ + dramc_mode_reg_write_by_rank(chn, rank, 12, mr12_value); +} + static void dramc_read_dbi_onoff(u8 onoff) { for (u8 chn = 0; chn < CHANNEL_MAX; chn++) @@ -203,3 +285,13 @@ } }
+void dramc_calibrate_all_channels(const struct sdram_params *pams) +{ + 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); + auto_refresh_switch(chn, 0); + cmd_bus_training(chn, rk, pams); + } + } +} diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c index ba913a2..eb75890 100644 --- a/src/soc/mediatek/mt8183/emi.c +++ b/src/soc/mediatek/mt8183/emi.c @@ -296,6 +296,7 @@ static void do_calib(const struct sdram_params *params) { dramc_apply_pre_calibration_config(); + dramc_calibrate_all_channels(params); }
void mt_set_emi(const struct sdram_params *params) diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h index ed9eb81..f5b6251 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h @@ -139,4 +139,5 @@ u32 dramc_get_broadcast(void); void dramc_sw_impedance(const struct sdram_params *params); void dramc_apply_pre_calibration_config(void); +void dramc_calibrate_all_channels(const struct sdram_params *params); #endif /* _DRAMC_PI_API_MT8183_H */