diff options
author | Shaoming Chen <shaoming.chen@mediatek.corp-partner.google.com> | 2020-12-04 17:00:56 +0800 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2021-01-15 11:29:17 +0000 |
commit | 5ff588dbc10bbf69f140cebf3a584f1ed563b1c5 (patch) | |
tree | fd72c40c3efe8160bb36f8c70ef14531c949de01 /src/soc/mediatek/mt8183/dramc_pi_calibration_api.c | |
parent | f296273692785da1bc88df8d28d955f8d79390e7 (diff) |
soc/mediatek/mt8183: Support byte mode and single rank DDR
1. Add emi setting to support byte mode and single rank ddr sample
2. Modify initial setting for DDR with different architecture
BUG=b:165768895
BRANCH=kukui
TEST=DDR boot up correctly on Kukui
Signed-off-by: Shaoming Chen <shaoming.chen@mediatek.corp-partner.google.com>
Change-Id: Id2845b2b60e2c447486ee25259dc6a05a0bb619b
Reviewed-on: https://review.coreboot.org/c/coreboot/+/48300
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Diffstat (limited to 'src/soc/mediatek/mt8183/dramc_pi_calibration_api.c')
-rw-r--r-- | src/soc/mediatek/mt8183/dramc_pi_calibration_api.c | 145 |
1 files changed, 100 insertions, 45 deletions
diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c index 17fa2306e3..ec39049a8a 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -266,7 +266,7 @@ static void cbt_set_perbit_delay_cell(u8 chn, u8 rank) } static void set_dram_mr_cbt_on_off(u8 chn, u8 rank, u8 fsp, - u8 cbt_on, struct mr_value *mr) + bool cbt_on, struct mr_value *mr, u32 cbt_mode) { u8 MR13Value = mr->MR13Value; @@ -276,6 +276,9 @@ static void set_dram_mr_cbt_on_off(u8 chn, u8 rank, u8 fsp, MR13Value &= 0x7f; else MR13Value |= 0x80; + + if (cbt_mode) + SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_BYTEMODECBTEN, 1); } else { MR13Value &= 0xfe; if (fsp == FSP_1) @@ -322,7 +325,7 @@ static void o1_path_on_off(u8 cbt_on) udelay(1); } -static void cbt_entry(u8 chn, u8 rank, u8 fsp, struct mr_value *mr) +static void cbt_entry(u8 chn, u8 rank, u8 fsp, struct mr_value *mr, u32 cbt_mode) { SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl, DRAMC_PD_CTRL_PHYCLKDYNGEN, 0, @@ -331,26 +334,31 @@ static void cbt_entry(u8 chn, u8 rank, u8 fsp, struct mr_value *mr) SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl, DRAMC_PD_CTRL_MIOCKCTRLOFF, 1); dramc_cke_fix_onoff(CKE_FIXON, chn); - set_dram_mr_cbt_on_off(chn, rank, fsp, 1, mr); - SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_WRITE_LEVEL_EN, 1); + set_dram_mr_cbt_on_off(chn, rank, fsp, true, mr, cbt_mode); + + if (cbt_mode == 0) + SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_WRITE_LEVEL_EN, 1); udelay(1); dramc_cke_fix_onoff(CKE_FIXOFF, chn); o1_path_on_off(1); } -static void cbt_exit(u8 chn, u8 rank, u8 fsp, struct mr_value *mr) +static void cbt_exit(u8 chn, u8 rank, u8 fsp, struct mr_value *mr, u32 cbt_mode) { dramc_cke_fix_onoff(CKE_FIXON, chn); udelay(1); - set_dram_mr_cbt_on_off(chn, rank, fsp, 0, mr); + set_dram_mr_cbt_on_off(chn, rank, fsp, false, mr, cbt_mode); o1_path_on_off(0); + + if (cbt_mode) + SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_BYTEMODECBTEN, 0); } -static void cbt_set_vref(u8 chn, u8 rank, u8 vref, bool is_final) +static void cbt_set_vref(u8 chn, u8 rank, u8 vref, bool is_final, u32 cbt_mode) { - if (!is_final) { + if (cbt_mode == 0 && !is_final) { SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_DMVREFCA, vref); SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_DQS_SEL, 1); SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_DQSBX_G, 0xa); @@ -394,12 +402,18 @@ static void cbt_set_ca_clk_result(u8 chn, u8 rank, } } -static u8 get_cbt_vref_pinmux_value(u8 chn, u8 vref_level) +static u8 get_cbt_vref_pinmux_value(u8 chn, u8 vref_level, u32 cbt_mode) { u8 vref_bit, vref_new, vref_org; vref_new = 0; vref_org = BIT(6) | (vref_level & 0x3f); + + if (cbt_mode) { + dramc_dbg("vref_org: %#x for byte mode\n", vref_org); + + return vref_org; + } for (vref_bit = 0; vref_bit < 8; vref_bit++) { if (vref_org & (1 << vref_bit)) vref_new |= (1 << phy_mapping[chn][vref_bit]); @@ -410,11 +424,14 @@ static u8 get_cbt_vref_pinmux_value(u8 chn, u8 vref_level) return vref_new; } -static void cbt_dramc_dfs_direct_jump(u8 shu_level) +static void cbt_dramc_dfs_direct_jump(u8 shu_level, bool run_dvfs) { u8 shu_ack = 0; static bool phy_pll_en = true; + if (!run_dvfs) + return; + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) shu_ack |= (0x1 << chn); @@ -490,20 +507,21 @@ static void cbt_dramc_dfs_direct_jump(u8 shu_level) phy_pll_en = !phy_pll_en; } -static void cbt_switch_freq(cbt_freq freq) +static void cbt_switch_freq(cbt_freq freq, bool run_dvfs) { if (freq == CBT_LOW_FREQ) - cbt_dramc_dfs_direct_jump(DRAM_DFS_SHUFFLE_MAX - 1); + cbt_dramc_dfs_direct_jump(DRAM_DFS_SHUFFLE_MAX - 1, run_dvfs); else - cbt_dramc_dfs_direct_jump(DRAM_DFS_SHUFFLE_1); + cbt_dramc_dfs_direct_jump(DRAM_DFS_SHUFFLE_1, run_dvfs); } static void dramc_cmd_bus_training(u8 chn, u8 rank, u8 freq_group, - const struct sdram_params *params, const bool fast_calib, - struct mr_value *mr) + const struct sdram_params *params, struct mr_value *mr, + bool run_dvfs) { u8 final_vref, cs_dly; u8 fsp = get_freq_fsq(freq_group); + u32 cbt_mode = params->cbt_mode_extern; cs_dly = params->cbt_cs_dly[chn][rank]; final_vref = params->cbt_final_vref[chn][rank]; @@ -521,6 +539,7 @@ static void dramc_cmd_bus_training(u8 chn, u8 rank, u8 freq_group, regs_bak[i].value = read32(regs_bak[i].addr); dramc_auto_refresh_switch(chn, false); + if (rank == RANK_1) { SET32_BITFIELDS(&ch[chn].ao.mrs, MRS_MRSRK, rank); SET32_BITFIELDS(&ch[chn].ao.rkcfg, RKCFG_TXRANK, rank); @@ -530,16 +549,35 @@ static void dramc_cmd_bus_training(u8 chn, u8 rank, u8 freq_group, cbt_set_perbit_delay_cell(chn, rank); - if (fsp == FSP_1) - cbt_switch_freq(CBT_LOW_FREQ); - cbt_entry(chn, rank, fsp, mr); - if (fsp == FSP_1) - cbt_switch_freq(CBT_HIGH_FREQ); + if (cbt_mode == 0) { + cbt_mrr_pinmux_mapping(); + if (fsp == FSP_1) + cbt_switch_freq(CBT_LOW_FREQ, run_dvfs); + cbt_entry(chn, rank, fsp, mr, cbt_mode); + udelay(1); + if (fsp == FSP_1) + cbt_switch_freq(CBT_HIGH_FREQ, run_dvfs); + } - u8 new_vref = get_cbt_vref_pinmux_value(chn, final_vref); - cbt_set_vref(chn, rank, new_vref, 0); + u8 new_vref = get_cbt_vref_pinmux_value(chn, final_vref, cbt_mode); + + if (cbt_mode) { + if (fsp == FSP_1) + cbt_switch_freq(CBT_LOW_FREQ, run_dvfs); + + cbt_set_fsp(chn, rank, fsp, mr); + cbt_set_vref(chn, rank, new_vref, true, cbt_mode); + cbt_entry(chn, rank, fsp, mr, cbt_mode); + udelay(1); + + if (fsp == FSP_1) + cbt_switch_freq(CBT_HIGH_FREQ, run_dvfs); + } else { + cbt_set_vref(chn, rank, new_vref, false, cbt_mode); + } cbt_set_ca_clk_result(chn, rank, params); + udelay(1); for (u8 rk = 0; rk < rank + 1; rk++) { /* Set CLK and CS delay */ @@ -548,14 +586,16 @@ static void dramc_cmd_bus_training(u8 chn, u8 rank, u8 freq_group, } if (fsp == FSP_1) - cbt_switch_freq(CBT_LOW_FREQ); - cbt_exit(chn, rank, fsp, mr); + cbt_switch_freq(CBT_LOW_FREQ, run_dvfs); + cbt_exit(chn, rank, fsp, mr, cbt_mode); - cbt_set_fsp(chn, rank, fsp, mr); - cbt_set_vref(chn, rank, final_vref, 1); + if (cbt_mode == 0) { + cbt_set_fsp(chn, rank, fsp, mr); + cbt_set_vref(chn, rank, final_vref, true, cbt_mode); + } if (fsp == FSP_1) - cbt_switch_freq(CBT_HIGH_FREQ); + cbt_switch_freq(CBT_HIGH_FREQ, run_dvfs); /* restore MRR pinmux */ set_mrr_pinmux_mapping(); @@ -693,7 +733,7 @@ static void dramc_rx_input_delay_tracking_init_by_freq(u8 chn, u8 freq_group) clrbits32(&shu->b[1].dq[7], (0x1 << 12) | (0x1 << 13)); } -void dramc_apply_config_before_calibration(u8 freq_group) +void dramc_apply_config_before_calibration(u8 freq_group, u32 cbt_mode) { for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { dramc_enable_phy_dcm(chn, false); @@ -710,8 +750,20 @@ void dramc_apply_config_before_calibration(u8 freq_group) clrbits32(&ch[chn].ao.dramctrl, 0x1 << 18); clrbits32(&ch[chn].ao.spcmdctrl, 0x1 << 31); clrbits32(&ch[chn].ao.spcmdctrl, 0x1 << 30); - clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 26); - clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 25); + + if (cbt_mode == CBT_R0_R1_NORMAL) { + clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 26); + clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 25); + } else if (cbt_mode == CBT_R0_R1_BYTE) { + setbits32(&ch[chn].ao.dqsoscr, 0x1 << 26); + setbits32(&ch[chn].ao.dqsoscr, 0x1 << 25); + } else if (cbt_mode == CBT_R0_NORMAL_R1_BYTE) { + clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 26); + setbits32(&ch[chn].ao.dqsoscr, 0x1 << 25); + } else if (cbt_mode == CBT_R0_BYTE_R1_NORMAL) { + setbits32(&ch[chn].ao.dqsoscr, 0x1 << 26); + clrbits32(&ch[chn].ao.dqsoscr, 0x1 << 25); + } dramc_write_dbi_onoff(chn, false); dramc_read_dbi_onoff(chn, false); @@ -751,9 +803,9 @@ void dramc_apply_config_before_calibration(u8 freq_group) } } -static void dramc_set_mr13_vrcg_to_Normal(u8 chn, const struct mr_value *mr) +static void dramc_set_mr13_vrcg_to_normal(u8 chn, const struct mr_value *mr, u32 rk_num) { - for (u8 rank = 0; rank < RANK_MAX; rank++) + for (u8 rank = 0; rank < rk_num; rank++) dramc_mode_reg_write_by_rank(chn, rank, 13, mr->MR13Value & ~(0x1 << 3)); @@ -761,14 +813,14 @@ static void dramc_set_mr13_vrcg_to_Normal(u8 chn, const struct mr_value *mr) clrbits32(&ch[chn].ao.shu[shu].hwset_vrcg, 0x1 << 19); } -void dramc_apply_config_after_calibration(const struct mr_value *mr) +void dramc_apply_config_after_calibration(const struct mr_value *mr, u32 rk_num) { for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { write32(&ch[chn].phy.misc_cg_ctrl4, 0x11400000); clrbits32(&ch[chn].ao.refctrl1, 0x1 << 7); clrbits32(&ch[chn].ao.shuctrl, 0x1 << 2); clrbits32(&ch[chn].phy.ca_cmd[6], 0x1 << 6); - dramc_set_mr13_vrcg_to_Normal(chn, mr); + dramc_set_mr13_vrcg_to_normal(chn, mr, rk_num); clrbits32(&ch[chn].phy.b[0].dq[6], 0x3); clrbits32(&ch[chn].phy.b[1].dq[6], 0x3); @@ -2358,7 +2410,7 @@ static void dramc_dual_rank_rx_datlat_cal(u8 chn, u8 freq_group, u8 datlat0, u8 dramc_dle_factor_handler(chn, final_datlat, freq_group); } -static void dramc_rx_dqs_gating_post_process(u8 chn, u8 freq_group) +static void dramc_rx_dqs_gating_post_process(u8 chn, u8 freq_group, u32 rk_num) { s8 dqsinctl; u32 read_dqsinctl, rankinctl_root, reg_tx_dly_dqsgated_min = 3; @@ -2372,7 +2424,7 @@ static void dramc_rx_dqs_gating_post_process(u8 chn, u8 freq_group) reg_tx_dly_dqsgated_min = 1; /* get TXDLY_Cal_min and TXDLY_Cal_max value */ - for (size_t rank = 0; rank < RANK_MAX; rank++) { + for (size_t rank = 0; rank < rk_num; rank++) { u32 dqsg0 = read32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg0); for (size_t dqs = 0; dqs < DQS_NUMBER; dqs++) { best_coarse_tune2t[rank][dqs] = (dqsg0 >> (dqs * 8)) & 0x7; @@ -2397,7 +2449,7 @@ static void dramc_rx_dqs_gating_post_process(u8 chn, u8 freq_group) txdly_cal_min += dqsinctl; txdly_cal_max += dqsinctl; - for (size_t rank = 0; rank < RANK_MAX; rank++) { + for (size_t rank = 0; rank < rk_num; rank++) { dramc_dbg("Rank: %zd\n", rank); for (size_t dqs = 0; dqs < DQS_NUMBER; dqs++) { best_coarse_tune2t[rank][dqs] += dqsinctl; @@ -2515,7 +2567,7 @@ static void dqsosc_auto(u8 chn, u8 rank, u8 freq_group, SHU1RK0_DQSOSC_DQSOSC_BASE_RK0_B1, dqsosc_cnt[1]); } -void dramc_hw_dqsosc(u8 chn) +void dramc_hw_dqsosc(u8 chn, u32 rk_num) { u32 freq_shu1 = get_shu_freq(DRAM_DFS_SHUFFLE_1); u32 freq_shu2 = get_shu_freq(DRAM_DFS_SHUFFLE_2); @@ -2544,7 +2596,10 @@ void dramc_hw_dqsosc(u8 chn) SET32_BITFIELDS(&ch[chn].ao.dqsoscr, DQSOSCR_DQSOSCRDIS, 1); SET32_BITFIELDS(&ch[chn].ao.rk[0].dqsosc, RK0_DQSOSC_DQSOSCR_RK0EN, 1); - SET32_BITFIELDS(&ch[chn].ao.rk[1].dqsosc, RK1_DQSOSC_DQSOSCR_RK1EN, 1); + + if (rk_num == RANK_MAX) + SET32_BITFIELDS(&ch[chn].ao.rk[1].dqsosc, RK1_DQSOSC_DQSOSCR_RK1EN, 1); + SET32_BITFIELDS(&ch[chn].ao.dqsoscr, DQSOSCR_DQSOSC_CALEN, 1); for (u8 shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) @@ -2994,7 +3049,7 @@ void dramc_dqs_precalculation_preset(void) } } -void get_dram_info_after_cal(u8 *density_result) +void get_dram_info_after_cal(u8 *density_result, u32 rk_num) { u8 vendor_id, density, max_density = 0; u32 ddr_size, max_size = 0; @@ -3002,7 +3057,7 @@ void get_dram_info_after_cal(u8 *density_result) vendor_id = dramc_mode_reg_read_by_rank(CHANNEL_A, RANK_0, 5); dramc_show("Vendor id is %#x\n", vendor_id); - for (u8 rk = RANK_0; rk < RANK_MAX; rk++) { + for (u8 rk = RANK_0; rk < rk_num; rk++) { density = dramc_mode_reg_read_by_rank(CHANNEL_A, rk, 8); dramc_dbg("MR8 %#x\n", density); density = (density >> 2) & 0xf; @@ -3044,7 +3099,7 @@ void get_dram_info_after_cal(u8 *density_result) } int dramc_calibrate_all_channels(const struct sdram_params *pams, - u8 freq_group, struct mr_value *mr) + u8 freq_group, struct mr_value *mr, bool run_dvfs) { bool fast_calib; switch (pams->source) { @@ -3064,11 +3119,11 @@ int dramc_calibrate_all_channels(const struct sdram_params *pams, u16 osc_thrd_inc[RANK_MAX]; u16 osc_thrd_dec[RANK_MAX]; for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { - for (u8 rk = RANK_0; rk < RANK_MAX; rk++) { + for (u8 rk = RANK_0; rk < pams->rank_num; rk++) { dramc_dbg("Start K: freq=%d, ch=%d, rank=%d\n", freq_group, chn, rk); dramc_cmd_bus_training(chn, rk, freq_group, pams, - fast_calib, mr); + mr, run_dvfs); dramc_write_leveling(chn, rk, freq_group, pams->wr_level); dramc_auto_refresh_switch(chn, true); @@ -3092,7 +3147,7 @@ int dramc_calibrate_all_channels(const struct sdram_params *pams, } dqsosc_shu_settings(chn, freq_group, osc_thrd_inc, osc_thrd_dec); - dramc_rx_dqs_gating_post_process(chn, freq_group); + dramc_rx_dqs_gating_post_process(chn, freq_group, pams->rank_num); dramc_dual_rank_rx_datlat_cal(chn, freq_group, rx_datlat[0], rx_datlat[1]); } return 0; |