Hello Duan huayang,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/44716
to review the following change.
Change subject: soc/mediatek/mt8192: Do dramc command bus training ......................................................................
soc/mediatek/mt8192: Do dramc command bus training
Signed-off-by: Huayang Duan huayang.duan@mediatek.com Change-Id: I06ee26e3b82811bffa09ab5e3e535b3174c3e3a6 --- M src/soc/mediatek/mt8192/dramc_dvfs.c M src/soc/mediatek/mt8192/dramc_pi_basic_api.c M src/soc/mediatek/mt8192/dramc_pi_calibration_api.c M src/soc/mediatek/mt8192/dramc_pi_main.c 4 files changed, 761 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/16/44716/1
diff --git a/src/soc/mediatek/mt8192/dramc_dvfs.c b/src/soc/mediatek/mt8192/dramc_dvfs.c index 67e2340..c51c261 100644 --- a/src/soc/mediatek/mt8192/dramc_dvfs.c +++ b/src/soc/mediatek/mt8192/dramc_dvfs.c @@ -193,3 +193,19 @@ MISC_SRAM_DMA0_SW_MODE, 0); } } + +void shuffle_dfs_to_fsp1(const struct ddr_cali* cali) +{ + u8 operating_fsp = cali->fsp; + struct mr_values *mr_value = cali->mr_value; + + /* Double confirm PLL switched from CLRPLL to PHYPLL */ + if (operating_fsp == FSP_1) { + for (u8 rk = 0; rk < cali->support_ranks; rk++) { + u8 mr13 = mr_value->mr13[rk]; + mr13 |= (BIT(6) | BIT(7)); + mr_value->mr13[rk] = mr13; + } + cbt_switch_freq(cali, CBT_HIGH_FREQ); + } +} diff --git a/src/soc/mediatek/mt8192/dramc_pi_basic_api.c b/src/soc/mediatek/mt8192/dramc_pi_basic_api.c index 8362c05..84acb3e 100644 --- a/src/soc/mediatek/mt8192/dramc_pi_basic_api.c +++ b/src/soc/mediatek/mt8192/dramc_pi_basic_api.c @@ -111,6 +111,26 @@ set_dqO1_pinmux_mapping(cali); }
+u8 get_cbt_vref_pinmux_value(const struct ddr_cali* cali, u8 range, u8 vref_lev) +{ + u8 chn = cali->chn; + u8 vref_bit, vref_org; + u8 vref_new = 0; + const u8 *map = mrr_o1_pinmux_mapping[get_pinmux_type(cali)][chn]; + + if (get_cbt_mode(cali) == CBT_BYTE_MODE1) + return ((range & 0x1) << 6) | (vref_lev & 0x3f); + + vref_org = ((range & 0x1) << 6) | (vref_lev & 0x3f); + + for (vref_bit = 0; vref_bit < 8; vref_bit++) + if (vref_org & (1 << vref_bit)) + vref_new |= (1 << map[vref_bit]); + + dramc_dbg("=== vref_new: 0x%x --> 0x%x\n", vref_org, vref_new); + return vref_new; +} + static void dramc_init_default_mr_value(const struct ddr_cali *cali) { struct mr_values *mr_value = cali->mr_value; diff --git a/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c index e1f3d67..e531de0 100644 --- a/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8192/dramc_pi_calibration_api.c @@ -5,6 +5,19 @@ #include <soc/dramc_register.h> #include <timer.h>
+static const u8 ca_pinmux_mapping[PINMUX_MAX][CHANNEL_MAX][CA_NUM_LP4] = { + [PINMUX_DSC] = { + [CHANNEL_A] = {1, 4, 5, 3, 2, 0}, + [CHANNEL_B] = {3, 5, 0, 2, 4, 1}, + }, + [PINMUX_LPBK] = { + }, + [PINMUX_EMCP] = { + [CHANNEL_A] = {2, 4, 3, 5, 1, 0}, + [CHANNEL_B] = {4, 5, 2, 0, 3, 1} + }, +}; + static const u8 imp_vref_sel[ODT_MAX][IMP_DRV_MAX] = { /* DRVP DRVN ODTP ODTN */ [ODT_OFF] = {0x37, 0x33, 0x00, 0x37}, @@ -580,6 +593,710 @@ write32(regs_bak[i].addr, regs_bak[i].value); }
+static void ca_training_set_perbit_delay_cell(const struct ddr_cali* cali, + u8 chn, u8 rank, u8 *ca_center) +{ + u8 ca_prebit_delay[DQS_BIT_NUMBER] = {0}; + const u8 *ca_mapping = ca_pinmux_mapping[get_pinmux_type(cali)][chn]; + + for (u8 u1CA = 0;u1CA < CA_NUM_LP4;u1CA++) { + ca_prebit_delay[ca_mapping[u1CA]] = ca_center[u1CA]; + dramc_dbg("CA_PerBit_DelayLine[%d]= %d\n", + ca_mapping[u1CA], ca_prebit_delay[ca_mapping[u1CA]]); + } + + SET32_BITFIELDS(&ch[chn].phy_ao.ca_rk[rank].shu_r0_ca_txdly0, + SHU_R0_CA_TXDLY0_TX_ARCA0_DLY, ca_prebit_delay[0], + SHU_R0_CA_TXDLY0_TX_ARCA1_DLY, ca_prebit_delay[1], + SHU_R0_CA_TXDLY0_TX_ARCA2_DLY, ca_prebit_delay[2], + SHU_R0_CA_TXDLY0_TX_ARCA3_DLY, ca_prebit_delay[3]); + SET32_BITFIELDS(&ch[chn].phy_ao.ca_rk[rank].shu_r0_ca_txdly1, + SHU_R0_CA_TXDLY1_TX_ARCA4_DLY, ca_prebit_delay[4], + SHU_R0_CA_TXDLY1_TX_ARCA5_DLY, ca_prebit_delay[5], + SHU_R0_CA_TXDLY1_TX_ARCA6_DLY, ca_prebit_delay[6], + SHU_R0_CA_TXDLY1_TX_ARCA7_DLY, ca_prebit_delay[7]); +} + +static u32 get_ca_ui(u8 chn) +{ + u32 dly = read32(&ch[chn].ao.shu_selph_ca7); + return dly & 0x0FFFFFFFU; +} + +static void put_ca_ui(u8 chn, u32 ca_ui) +{ + u32 dly; + + dly = read32(&ch[chn].ao.shu_selph_ca7); + dly &= 0xF0000000U; + ca_ui &= 0x0FFFFFFFU; + dly |= ca_ui; + + write32(&ch[chn].ao.shu_selph_ca7, dly); + SET32_BITFIELDS(&ch[chn].ao.shu_selph_ca5, SHU_SELPH_CA5_DLY_CKE, ca_ui & 0xF); + SET32_BITFIELDS(&ch[chn].ao.shu_selph_ca6, SHU_SELPH_CA6_DLY_CKE1, ca_ui & 0xF); +} + +static void put_ca_mck(u8 chn, u32 ca_mck) +{ + u32 dly; + + dly = read32(&ch[chn].ao.shu_selph_ca3); + dly &= 0xF0000000U; + ca_mck &= 0x0FFFFFFFU; + dly |= ca_mck; + + write32(&ch[chn].ao.shu_selph_ca3, dly); +} + +static u32 get_cs_ui(u8 chn, u8 rank) +{ + if (rank == RANK_1) + return READ32_BITFIELD(&ch[chn].ao.shu_selph_ca5, SHU_SELPH_CA5_DLY_CS1); + else + return READ32_BITFIELD(&ch[chn].ao.shu_selph_ca5, SHU_SELPH_CA5_DLY_CS); +} + +static u32 get_cs_mck(u8 chn, u8 rank) +{ + if (rank == RANK_1) + return READ32_BITFIELD(&ch[chn].ao.shu_selph_ca1, SHU_SELPH_CA1_TXDLY_CS1); + else + return READ32_BITFIELD(&ch[chn].ao.shu_selph_ca1, SHU_SELPH_CA1_TXDLY_CS); +} + +static int get_capi_max(dram_freq_grp freq_group) +{ + if (freq_group == DDRFREQ_400) + return 32; + + return 64; +} + +static u8 get_ca_pi_per_ui(void) +{ + return 32; +} + +static u8 get_mck_ck_ratio(u8 chn) +{ + u32 ratio = READ32_BITFIELD(&ch[chn].ao.shu_lp5_cmd, SHU_LP5_CMD_LP5_CMD1TO2EN); + + dramc_dbg("MCK:CK=%s\n", ratio == 1 ? "1:1" : "1:2"); + return ratio; +} + +static u8 get_cbtui_adjustable_maxvalue(u8 chn) +{ + u8 ratio = get_mck_ck_ratio(chn); + return ratio == 1 ? 1 : 3; +} + +static void put_cs_ui(u8 chn, u8 rank, u32 cs_ui) +{ + if (rank == RANK_1) + SET32_BITFIELDS(&ch[chn].ao.shu_selph_ca5, SHU_SELPH_CA5_DLY_CS1, cs_ui); + else + SET32_BITFIELDS(&ch[chn].ao.shu_selph_ca5, SHU_SELPH_CA5_DLY_CS, cs_ui); +} + +static void put_cs_mck(u8 chn, u8 rank, u32 cs_ui) +{ + if (rank == RANK_1) + SET32_BITFIELDS(&ch[chn].ao.shu_selph_ca1, SHU_SELPH_CA1_TXDLY_CS1, cs_ui); + else + SET32_BITFIELDS(&ch[chn].ao.shu_selph_ca1, SHU_SELPH_CA1_TXDLY_CS, cs_ui); +} + +static u32 get_ca_mck(u8 chn) +{ + u32 dly = read32(&ch[chn].ao.shu_selph_ca3); + return dly & 0x0FFFFFFFU; +} + +static void xlate_ca_mck_ui(u8 chn, u32 ui_delta, + u32 mck_old, u32 ui_old, u32 *mck_new, u32 *ui_new) +{ + u8 i; + u32 mask, max; + u32 bit_ui, bit_mck; + u32 ui_tmp = 0, mck_tmp = 0; + + max = get_cbtui_adjustable_maxvalue(chn); + mask = max; + + for (i = 0; i < 7; i++) { + bit_mck = 0; + bit_ui = ((ui_old >> (i * 4)) & mask) + ui_delta; + if (bit_ui > max) { + bit_mck = bit_ui / (max + 1); + bit_ui = bit_ui % (max + 1); + } + + mck_tmp += (bit_mck << (i * 4)); + ui_tmp += (bit_ui << (i * 4)); + } + + if (ui_new) + *ui_new = ui_tmp; + + if (mck_new) + *mck_new = mck_old + mck_tmp; +} + +static s16 adjust_cs_ui(const struct ddr_cali* cali, u32 cs_mck, u32 cs_ui, s16 pi_dly) +{ + u8 ratio; + s16 p2u,ui = 0, pi = 0; + u32 ui_max, cs_bit_mask, cs_ui_tmp, cs_mck_tmp; + dram_freq_grp freq_group = get_freq_group(cali); + + u8 chn = cali->chn; + u8 rank = cali->rank; + dramc_dbg("pi_dly:%d, get_capi_max:%d\n", pi_dly, get_capi_max(freq_group)); + + if (pi_dly < get_capi_max(freq_group)) + return pi_dly; + + p2u = get_ca_pi_per_ui(); + + ui = pi_dly / p2u; + pi = pi_dly % p2u; + + ratio = get_mck_ck_ratio(chn); + if (ratio) + /* 1:1 */ + cs_bit_mask = 1; + else + /* 1:2 */ + cs_bit_mask = 3; + + ui_max = get_cbtui_adjustable_maxvalue(chn); + cs_ui_tmp = (cs_ui & cs_bit_mask) + ui; + cs_mck_tmp = 0; + if (cs_ui_tmp > ui_max) { + cs_mck_tmp = cs_ui_tmp / (ui_max + 1); + cs_ui_tmp = cs_ui_tmp % (ui_max + 1); + } + + cs_mck_tmp += cs_mck; + put_cs_ui(chn, rank, cs_ui_tmp); + put_cs_mck(chn, rank, cs_mck_tmp); + + return pi; +} + +static s8 adjust_ca_ui(const struct ddr_cali* cali, u32 ca_mck, u32 ca_ui, s16 pi_dly) +{ + s16 p2u; + s16 ui, pi; + u32 ui_new = 0, mck_new = 0; + dram_freq_grp freq_group = get_freq_group(cali); + + u8 chn = cali->chn; + if (pi_dly < get_capi_max(freq_group)) + return pi_dly; + + p2u = get_ca_pi_per_ui(); + ui = pi_dly / p2u; + pi = pi_dly % p2u; + xlate_ca_mck_ui(chn, ui, ca_mck, ca_ui, &mck_new, &ui_new); + + put_ca_ui(chn, ui_new); + put_ca_mck(chn, mck_new); + dramc_dbg("mck_new: %#x, ui_new: %#x, pi:%d\n", mck_new, ui_new, pi); + + return pi; +} + +static void cbt_set_ca_clk_result(const struct ddr_cali* cali, u32 mck, u32 ui) +{ + s8 final_ca_clk; + u8 chn, rank; + u8 ca_center[DQS_BIT_NUMBER] = {0}; + + chn = cali->chn; + rank = cali->rank; + const struct sdram_params *params = cali->params; + s8 cmd_dly = params->cbt_cmd_dly[chn][rank]; + + for (u8 ca = 0; ca < CA_NUM_LP4; ca++) { + ca_center[ca] = params->cbt_ca_prebit_dly[chn][rank][ca]; + dramc_dbg("ca_center[%d]= %d\n", ca, ca_center[ca]); + } + + final_ca_clk = cmd_dly; + dramc_dbg("CA Dly = %d\n", final_ca_clk); + + final_ca_clk = adjust_ca_ui(cali, mck, ui, final_ca_clk); + dramc_dbg("after adjust, CA Dly = %d\n", final_ca_clk); + for (u8 rk = RANK_0; rk <= rank; rk++) { + cbt_delay_ca_clk(chn, rk, final_ca_clk); + ca_training_set_perbit_delay_cell(cali, chn, rk, ca_center); + } +} + +static void cbt_adjust_cs(const struct ddr_cali* cali) +{ + u8 chn, rank, cs_dly[RANK_MAX]; + u8 cs_final_delay; + u32 pi_dly; + u32 cs_ui, cs_mck; + + const struct sdram_params *params = cali->params; + chn = cali->chn; + rank = cali->rank; + cs_dly[RANK_0] = params->cbt_cs_dly[chn][RANK_0]; + cs_dly[RANK_1] = params->cbt_cs_dly[chn][RANK_1]; + + cs_ui = get_cs_ui(chn, rank); + cs_mck = get_cs_mck(chn, rank); + + if (rank == RANK_0) + cs_final_delay = cs_dly[RANK_0]; + else + cs_final_delay = (cs_dly[RANK_0] + cs_dly[RANK_1]) >> 1; + + for (u8 rk = RANK_0; rk <= rank; rk++) { + pi_dly = adjust_cs_ui(cali, cs_mck, cs_ui, cs_final_delay); + SET32_BITFIELDS(&ch[chn].phy_ao.ca_rk[rk].shu_r0_ca_cmd0, + SHU_R0_CA_CMD0_RG_ARPI_CS, pi_dly); + } + + dramc_dbg("CS Dly: %d\n", cs_final_delay); +} + +static void set_dram_mr_cbt_on_off(const struct ddr_cali* cali, o1_state o1) +{ + u8 chn, rank, fsp; + struct mr_values *mr_value = cali->mr_value; + + chn = cali->chn; + rank = cali->rank; + fsp = get_fsp(cali); + u8 mr13 = mr_value->mr13[rank] & (~ BIT(0)) & (~ BIT(6)) & (~ BIT(7)) ; + + if (o1 == O1_ON) { + if (fsp == FSP_1) + mr13 |= BIT(0) | BIT(6); + else + mr13 |= BIT(0) | BIT(7); + + if (get_cbt_mode(cali) == CBT_BYTE_MODE1) + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl0, + CBT_WLEV_CTRL0_BYTEMODECBTEN, 1, + CBT_WLEV_CTRL0_CBT_CMP_BYTEMODE, 1); + } else { + if (fsp == FSP_1) + mr13 |= BIT(6); + } + + dramc_mode_reg_write_by_rank(cali, chn, rank, 13, mr13); + mr_value->mr13[rank] = mr13; +} + +void o1_path_on_off(const struct ddr_cali* cali, o1_state o1) +{ + u8 chn = cali->chn; + u8 rank = cali->rank; + u8 vref_sel = 0x37; + + if (o1 == O1_ON) { + SET32_BITFIELDS(&ch[chn].phy_ao.byte[0].shu_b0_vref, + SHU_B0_VREF_RG_RX_ARDQ_VREF_UNTERM_EN_B0, 1); + SET32_BITFIELDS(&ch[chn].phy_ao.byte[1].shu_b0_vref, + SHU_B1_VREF_RG_RX_ARDQ_VREF_UNTERM_EN_B1, 1); + SET32_BITFIELDS(&ch[chn].phy_ao.byte[0].rk[rank].shu_b0_phy_vref_sel, + RG_RX_ARDQ_VREF_SEL_LB_B0, vref_sel, + RG_RX_ARDQ_VREF_SEL_UB_B0, vref_sel); + SET32_BITFIELDS(&ch[chn].phy_ao.byte[1].rk[rank].shu_b0_phy_vref_sel, + RG_RX_ARDQ_VREF_SEL_LB_B1, vref_sel, + RG_RX_ARDQ_VREF_SEL_UB_B1, vref_sel); + } + + SET32_BITFIELDS(&ch[chn].phy_ao.dvs_b[0].b0_dq6, + B0_DQ6_RG_RX_ARDQ_O1_SEL_B0, o1); + SET32_BITFIELDS(&ch[chn].phy_ao.dvs_b[1].b0_dq6, + B1_DQ6_RG_RX_ARDQ_O1_SEL_B1, o1); + SET32_BITFIELDS(&ch[chn].phy_ao.dvs_b[0].b0_dq3, + B0_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B0, o1, + B0_DQ3_RG_RX_ARDQS0_IN_BUFF_EN_B0, o1); + SET32_BITFIELDS(&ch[chn].phy_ao.dvs_b[1].b0_dq3, + B1_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B1, o1, + B1_DQ3_RG_RX_ARDQS0_IN_BUFF_EN_B1, o1); + SET32_BITFIELDS(&ch[chn].phy_ao.dvs_b[0].b0_phy3, + B0_PHY3_RG_RX_ARDQ_BUFF_EN_SEL_B0, o1); + SET32_BITFIELDS(&ch[chn].phy_ao.dvs_b[1].b0_phy3, + B1_PHY3_RG_RX_ARDQ_BUFF_EN_SEL_B1, o1); + SET32_BITFIELDS(&ch[chn].phy_ao.misc_rx_in_gate_en_ctrl, + MISC_RX_IN_GATE_EN_CTRL_FIX_IN_GATE_EN, (o1 << 1) | o1); + + udelay(1); +} + +static void dramc_mode_reg_ca_term(const struct ddr_cali* cali, u8 do_term) +{ + + u8 chn = cali->chn; + u8 fsp = get_fsp(cali); + u8 mr11, mr13, mr22; + struct mr_values *mr_value = cali->mr_value; + static u8 state_do_term[CHANNEL_MAX] = {0}; + + if (state_do_term[chn] == do_term) + return; + + state_do_term[chn] = do_term; + u32 bc_bak = dramc_get_broadcast(); + dramc_set_broadcast(DRAMC_BROADCAST_OFF); + + mr11 = 0x3; + if (get_cbt_mode(cali) == CBT_NORMAL_MODE) + mr11 |= 0x40; + else + mr11 |= 0x20; + + for (u8 rk = RANK_0; rk < cali->support_ranks; rk++) { + mr13 = mr_value->mr13[rk] & (~ BIT(6)) & (~ BIT(7)); + mr13 |= BIT(6); + dramc_mode_reg_write_by_rank(cali, chn, rk, 13, mr13); + mr_value->mr13[rk] = mr13; + + dramc_mode_reg_write_by_rank(cali, chn, rk, 11, mr11); + mr_value->mr11[fsp] = mr11; + + if (do_term) { + mr22 = 0x4; + } else { + if (rk == RANK_0) + mr22 = 0x4; + else + mr22 = 0x2c; + } + + dramc_mode_reg_write_by_rank(cali, chn, rk, 22, mr22); + mr_value->mr22[fsp] = mr22; + } + + dramc_set_broadcast(bc_bak); +} + +static void cbt_entry(const struct ddr_cali* cali) +{ + u8 chn, rank, fsp; + u8 mr13, dram_dq_b0 = 0; + struct mr_values *mr_value = cali->mr_value; + + chn = cali->chn; + rank = cali->rank; + fsp = get_fsp(cali); + mr13 = mr_value->mr13[rank]; + + if (fsp == FSP_1) + dramc_mode_reg_ca_term(cali, 1); + + SET32_BITFIELDS(&ch[chn].phy_ao.misc_stbcal, MISC_STBCAL_DQSIENCG_NORMAL_EN, 0); + + cke_fix_onoff(cali, chn, rank, CKE_FIXON); + SET32_BITFIELDS(&ch[chn].ao.swcmd_ctrl0, SWCMD_CTRL0_MRSRK, rank); + + set_dram_mr_cbt_on_off(cali, true); + + if (get_cbt_mode(cali) == CBT_NORMAL_MODE) { + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl0, + CBT_WLEV_CTRL0_WRITE_LEVEL_EN, 1); + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl0, + CBT_WLEV_CTRL0_DQSOEAOEN, 0x1); + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl0, + CBT_WLEV_CTRL0_CBT_DQBYTE_OEAO_EN, 1 << dram_dq_b0); + } + + udelay(1); + cke_fix_onoff(cali, chn, rank, CKE_FIXOFF); + + if (fsp == FSP_1) + mr13 |= BIT(7); + else + mr13 &= (~ BIT(7)); + mr_value->mr13[rank] = mr13; + + o1_path_on_off(cali, O1_ON); + + udelay(1); +} + +static void cbt_exit(const struct ddr_cali* cali) +{ + u8 chn = cali->chn; + u8 rank = cali->rank; + u8 cbt_mode = get_cbt_mode(cali); + + if (cbt_mode == CBT_NORMAL_MODE || cbt_mode == CBT_BYTE_MODE1) { + cke_fix_onoff(cali, chn, rank, CKE_FIXON); + udelay(1); + set_dram_mr_cbt_on_off(cali, false); + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl0, CBT_WLEV_CTRL0_WRITE_LEVEL_EN, 0); + } + + o1_path_on_off(cali, O1_OFF); + if (cbt_mode == CBT_BYTE_MODE1) + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl0, + CBT_WLEV_CTRL0_BYTEMODECBTEN, 0, + CBT_WLEV_CTRL0_CBT_CMP_BYTEMODE, 0); + + udelay(1); +} + +static void cbt_entry_top(const struct ddr_cali* cali) +{ + u8 chn, fsp; + + chn = cali->chn; + fsp = get_fsp(cali); + + if(fsp == FSP_1) { + SET32_BITFIELDS(&ch[chn].phy_ao.ca_cmd2, + CA_CMD2_RG_TX_ARCMD_OE_DIS_CA, 1, + CA_CMD2_RG_TX_ARCA_OE_TIE_SEL_CA, 0, + CA_CMD2_RG_TX_ARCA_OE_TIE_EN_CA, 0xff); + cbt_switch_freq(cali, CBT_LOW_FREQ); + SET32_BITFIELDS(&ch[chn].phy_ao.ca_cmd2, + CA_CMD2_RG_TX_ARCMD_OE_DIS_CA, 0, + CA_CMD2_RG_TX_ARCA_OE_TIE_SEL_CA, 1, + CA_CMD2_RG_TX_ARCA_OE_TIE_EN_CA, 0xff); + } + cbt_entry(cali); + + if(fsp == FSP_1) + cbt_switch_freq(cali, CBT_HIGH_FREQ); +} + +static void cbt_exit_top(const struct ddr_cali* cali, cbt_state state) +{ + if (state == OUT_CBT || get_cbt_mode(cali) == CBT_BYTE_MODE1){ + if (get_fsp(cali) == FSP_1) + cbt_switch_freq(cali, CBT_LOW_FREQ); + cbt_exit(cali); + } +} + +static void cbt_set_vref(const struct ddr_cali* cali, cbt_state state) +{ + u8 chn, rank, fsp, range; + u8 dram_dq_b0 = 0; + u8 vref_value_pinmux; + u8 ca_vref, mr12, mr13; + struct mr_values *mr_value = cali->mr_value; + const struct sdram_params *params = cali->params; + + chn = cali->chn; + rank = cali->rank; + fsp = get_fsp(cali); + ca_vref = params->cbt_final_vref[chn][rank]; + mr12 = mr_value->mr12[chn][rank][fsp]; + range = mr12 >> 6; + + if (state == IN_CBT && get_cbt_mode(cali) == CBT_NORMAL_MODE) { + vref_value_pinmux = get_cbt_vref_pinmux_value(cali, range, ca_vref); + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl4, + CBT_WLEV_CTRL4_CBT_TXDQ_B0, vref_value_pinmux); + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl0, + CBT_WLEV_CTRL0_CBT_WLEV_DQS_SEL, 0x1 << dram_dq_b0); + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl3, + CBT_WLEV_CTRL3_DQSBX_G, 0xa); + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl0, + CBT_WLEV_CTRL0_CBT_WLEV_DQS_TRIG, 1); + udelay(1); + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl0, + CBT_WLEV_CTRL0_CBT_WLEV_DQS_TRIG, 0); + } else { + if (fsp == FSP_1) { + mr13 = mr_value->mr13[rank] | (0x1 << 6); + dramc_mode_reg_write_by_rank(cali, chn, rank, 13, mr13); + mr_value->mr13[rank] = mr13; + } + + dramc_dbg("CmdBusTraining Vref(ca) range %d: %d\n", range, ca_vref); + + ca_vref = ((range & 0x1) << 6) | (ca_vref & 0x3f); + dramc_mode_reg_write_by_rank(cali, chn, rank, 12, ca_vref); + mr_value->mr12[chn][rank][fsp] = ca_vref; + } + udelay(1); +} + +static void cbt_set_best_vref(const struct ddr_cali* cali, cbt_state state) +{ + u8 fsp = get_fsp(cali); + + if (state == IN_CBT && get_cbt_mode(cali) == CBT_BYTE_MODE1) { + if (fsp == FSP_1) + cbt_switch_freq(cali, CBT_LOW_FREQ); + + cbt_exit(cali); + cbt_set_vref(cali, state); + cbt_entry(cali); + if (fsp == FSP_1) + cbt_switch_freq(cali, CBT_HIGH_FREQ); + } else { + cbt_set_vref(cali, state); + } +} + +static void set_cbt_wlev_intv(u8 chn, dram_freq_grp freq_group) +{ + u8 tcmdo1lat; + u8 catrain_intv; + u8 new_cbt_pat_intv; + u8 wlev_dqspat_lat; + + switch (freq_group) { + case DDRFREQ_400: + tcmdo1lat = 12; + catrain_intv = 13; + new_cbt_pat_intv = 12; + wlev_dqspat_lat = 12; + break; + case DDRFREQ_600: + tcmdo1lat = 9; + catrain_intv = 8; + new_cbt_pat_intv = 11; + wlev_dqspat_lat = 11; + break; + case DDRFREQ_800: + tcmdo1lat = 10; + catrain_intv = 8; + new_cbt_pat_intv = 12; + wlev_dqspat_lat = 12; + break; + case DDRFREQ_933: + tcmdo1lat = 11; + catrain_intv = 9; + new_cbt_pat_intv = 13; + wlev_dqspat_lat = 13; + break; + case DDRFREQ_1200: + tcmdo1lat = 12; + catrain_intv = 9; + new_cbt_pat_intv = 14; + wlev_dqspat_lat = 14; + break; + case DDRFREQ_1600: + tcmdo1lat = 14; + catrain_intv = 11; + new_cbt_pat_intv = 16; + wlev_dqspat_lat = 16; + break; + case DDRFREQ_2133: + tcmdo1lat = 17; + catrain_intv = 14; + new_cbt_pat_intv = 19; + wlev_dqspat_lat = 19; + break; + default: + die("Invalid DDR frequency group %u\n", freq_group); + return; + } + + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl1, + CBT_WLEV_CTRL1_TCMDO1LAT, tcmdo1lat, + CBT_WLEV_CTRL1_CATRAIN_INTV, catrain_intv); + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl5, + CBT_WLEV_CTRL5_NEW_CBT_PAT_INTV, new_cbt_pat_intv); + SET32_BITFIELDS(&ch[chn].ao.cbt_wlev_ctrl0, + CBT_WLEV_CTRL0_WLEV_DQSPAT_LAT, wlev_dqspat_lat); +} + +static void dramc_cmd_ui_delay_setting(u8 chn, u8 value) +{ + SET32_BITFIELDS(&ch[chn].ao.shu_selph_ca7, + SHU_SELPH_CA7_DLY_RA0, value, + SHU_SELPH_CA7_DLY_RA1, value, + SHU_SELPH_CA7_DLY_RA2, value, + SHU_SELPH_CA7_DLY_RA3, value, + SHU_SELPH_CA7_DLY_RA4, value, + SHU_SELPH_CA7_DLY_RA5, value, + SHU_SELPH_CA7_DLY_RA6, value); + + SET32_BITFIELDS(&ch[chn].ao.shu_selph_ca5, + SHU_SELPH_CA5_DLY_CKE, value); + SET32_BITFIELDS(&ch[chn].ao.shu_selph_ca6, + SHU_SELPH_CA6_DLY_CKE1, value); +} + +void dramc_cmd_bus_training(const struct ddr_cali* cali) +{ + u8 chn, rank, fsp; + u32 ca_ui, ca_mck; + u8 ca_final_center[CA_NUM_LP4] = {0}; + + chn = cali->chn; + rank = cali->rank; + fsp = get_fsp(cali); + + struct reg_bak regs_bak[] = { + {&ch[chn].ao.dramc_pd_ctrl}, + {&ch[chn].phy_ao.misc_stbcal}, + {&ch[chn].ao.ckectrl}, + {&ch[chn].phy_ao.dvs_b[0].b0_dq2}, + {&ch[chn].phy_ao.dvs_b[1].b0_dq2}, + {&ch[chn].ao.cbt_wlev_ctrl0}, + {&ch[chn].ao.cbt_wlev_ctrl1}, + {&ch[chn].ao.cbt_wlev_ctrl2}, + {&ch[chn].ao.cbt_wlev_ctrl3}, + {&ch[chn].ao.cbt_wlev_ctrl4}, + {&ch[chn].ao.swcmd_ctrl0}, + {&ch[chn].ao.refctrl0}, + {&ch[chn].phy_ao.byte[0].shu_b0_vref}, + {&ch[chn].phy_ao.byte[1].shu_b0_vref}, + {&ch[chn].phy_ao.byte[0].rk[rank].shu_b0_phy_vref_sel}, + {&ch[chn].phy_ao.byte[1].rk[rank].shu_b0_phy_vref_sel}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++) + regs_bak[i].value = read32(regs_bak[i].addr); + + ca_training_set_perbit_delay_cell(cali, chn, rank, ca_final_center); + dramc_cmd_ui_delay_setting(chn, 1); + cbt_delay_ca_clk(chn, rank, 0); + + ca_mck = get_ca_mck(chn); + dramc_auto_refresh_switch(chn, false); + + set_cbt_wlev_intv(chn, get_freq_group(cali)); + SET32_BITFIELDS(&ch[chn].ao.tx_set0, TX_SET0_TXRANK, rank); + SET32_BITFIELDS(&ch[chn].ao.tx_set0, TX_SET0_TXRANKFIX, 1); + SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl, + DRAMC_PD_CTRL_DCMEN2, 0, + DRAMC_PD_CTRL_MIOCKCTRLOFF, 1, + DRAMC_PD_CTRL_PHYCLKDYNGEN, 0, + DRAMC_PD_CTRL_COMBCLKCTRL, 0, + DRAMC_PD_CTRL_APHYCKCG_FIXOFF, 1, + DRAMC_PD_CTRL_TCKFIXON, 1); + + cbt_entry_top(cali); + cbt_set_best_vref(cali, IN_CBT); + dramc_cmd_UI_delay_setting(chn, 0); + ca_ui = get_ca_ui(chn); + + put_ca_ui(chn, ca_ui); + cbt_set_ca_clk_result(cali, ca_mck, ca_ui); + udelay(1); + + cbt_adjust_cs(cali); + cbt_exit_top(cali, OUT_CBT); + cbt_set_best_vref(cali, OUT_CBT); + + if (fsp == FSP_1) + dramc_mode_reg_ca_term(cali, 0); + + SET32_BITFIELDS(&ch[chn].ao.tx_set0, TX_SET0_TXRANK, 0); + SET32_BITFIELDS(&ch[chn].ao.tx_set0, TX_SET0_TXRANKFIX, 0); + for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++) + write32(regs_bak[i].addr, regs_bak[i].value); + +} + static void duty_delay_reg_convert(s8 duty_delay, u8 *delay) { u8 delay_tmp; @@ -615,7 +1332,6 @@ } }
- static void dramc_duty_set_wck_delay_cell(u8 chn, const s8* duty_delay) { u8 dqs; diff --git a/src/soc/mediatek/mt8192/dramc_pi_main.c b/src/soc/mediatek/mt8192/dramc_pi_main.c index 11ec636..214bf55 100644 --- a/src/soc/mediatek/mt8192/dramc_pi_main.c +++ b/src/soc/mediatek/mt8192/dramc_pi_main.c @@ -225,6 +225,14 @@ CA_CMD2_RG_TX_ARCMD_OE_DIS_CA, 0, CA_CMD2_RG_TX_ARCA_OE_TIE_SEL_CA, 1, CA_CMD2_RG_TX_ARCA_OE_TIE_EN_CA, 0xff); + + for (u8 rank = RANK_0; rank < cali->support_ranks; rank++) { + cali->rank = rank; + dramc_auto_refresh_switch(chn, false); + dramc_cmd_bus_training(cali); + } + + shuffle_dfs_to_fsp1(cali); }
static void dramc_calibration_all_channels(struct ddr_cali *cali)