From 7b78a805da0207449c5ea1baf56030ab9f54e2d6 Mon Sep 17 00:00:00 2001 From: Huayang Duan Date: Wed, 26 Sep 2018 21:09:54 +0800 Subject: mediatek/mt8183: Add DDR driver of runtime config part BUG=b:80501386 BRANCH=none TEST=Boots correctly on Kukui, and inits DRAM successfully with related patches. Change-Id: Id1e8862ff6feb9628d37fe5300780ff56865a563 Signed-off-by: Huayang Duan Reviewed-on: https://review.coreboot.org/c/28844 Tested-by: build bot (Jenkins) Reviewed-by: Hung-Te Lin --- src/soc/mediatek/mt8183/dramc_pi_basic_api.c | 197 +++++++++++++++++++++ src/soc/mediatek/mt8183/dramc_pi_calibration_api.c | 23 +-- src/soc/mediatek/mt8183/emi.c | 22 ++- src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h | 3 + 4 files changed, 228 insertions(+), 17 deletions(-) diff --git a/src/soc/mediatek/mt8183/dramc_pi_basic_api.c b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c index 2cb0db2f1b..7b3ee8801d 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_basic_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -109,3 +110,199 @@ void dramc_sw_impedance(const struct sdram_params *params) clrsetbits_le32(&ch[0].phy.shu[0].ca_dll[1], 0x1f << 16, 0x9 << 16); } + +static void transfer_pll_to_spm_control(void) +{ + u8 shu_lev = (read32(&ch[0].ao.shustatus) & 0x00000006) >> 1; + + clrsetbits_le32(&mtk_spm->poweron_config_set, + (0xffff << 16) | (0x1 << 0), + (0xb16 << 16) | (0x1 << 0)); + + /* Set SPM pinmux */ + clrbits_le32(&mtk_spm->pcm_pwr_io_en, (0xff << 0) | (0xff << 16)); + setbits_le32(&mtk_spm->dramc_dpy_clk_sw_con_sel, 0xffffffff); + setbits_le32(&mtk_spm->dramc_dpy_clk_sw_con_sel2, 0xffffffff); + + setbits_le32(&mtk_spm->spm_power_on_val0, (0x1 << 8) | (0xf << 12)); + setbits_le32(&mtk_spm->spm_s1_mode_ch, 0x3 << 0); + + shu_lev = (shu_lev == 1) ? 2 : 1; + clrsetbits_le32(&mtk_spm->spm_power_on_val0, 0x3 << 28, shu_lev << 28); + clrsetbits_le32(&mtk_spm->dramc_dpy_clk_sw_con2, + 0x3 << 2, shu_lev << 2); + + udelay(1); + for (size_t chn = CHANNEL_A; chn < CHANNEL_MAX; chn++) { + clrbits_le32(&ch[chn].phy.pll1, 0x1 << 31); + clrbits_le32(&ch[chn].phy.pll2, 0x1 << 31); + } +} + +static void dramc_rx_input_delay_tracking(u8 chn) +{ + /* Enable RX_FIFO macro DIV4 clock CG */ + write32(&ch[chn].phy.misc_cg_ctrl1, 0xffffffff); + + /* DVS mode to RG mode */ + for (size_t r = 0; r < 2; r++) + for (size_t b = 0; b < 2; b++) + clrbits_le32(&ch[chn].phy.r[r].b[b].rxdvs[2], 3 << 30); + + clrsetbits_le32(&ch[chn].phy.b0_rxdvs[0], 0x1 << 19, 0x1 << 9); + clrsetbits_le32(&ch[chn].phy.b1_rxdvs[0], 0x1 << 19, 0x1 << 9); + + for (size_t r = 0; r < 2; r++) + for (size_t b = 0; b < 2; b++) { + /* Track rising and update rising/falling together */ + clrbits_le32(&ch[chn].phy.r[r].b[b].rxdvs[2], + 0x1 << 29); + clrsetbits_le32(&ch[chn].phy.r[r].b[b].rxdvs[7], + (0x3f << 0) | (0x3f << 8) | + (0x7f << 16) | (0x7f << 24), + (0x0 << 0) | (0x3f << 8) | + (0x0 << 16) | (0x7f << 24)); + clrsetbits_le32(&ch[chn].phy.r[r].b[b].rxdvs[1], + (0xffff << 16) | (0xffff << 0), + (0x2 << 16) | (0x2 << 0)); + + /* DQ/DQS Rx DLY adjustment for tracking mode */ + clrbits_le32(&ch[chn].phy.r[r].b[b].rxdvs[2], + (0x3 << 26) | (0x3 << 24) | + (0x3 << 18) | (0x3 << 16)); + } + + clrbits_le32(&ch[chn].phy.ca_cmd[10], (0x7 << 28) | (0x7 << 24)); + + /* Rx DLY tracking setting (Static) */ + clrsetbits_le32(&ch[chn].phy.b0_rxdvs[0], + (0x1 << 29) | (0xf << 4) | (0x1 << 0), + (0x1 << 29) | (0x0 << 4) | (0x1 << 0)); + clrsetbits_le32(&ch[chn].phy.b1_rxdvs[0], + (0x1 << 29) | (0xf << 4) | (0x1 << 0), + (0x1 << 29) | (0x0 << 4) | (0x1 << 0)); + + for (u8 b = 0; b < 2; b++) { + clrsetbits_le32(&ch[chn].phy.b[b].dq[9], + (0x7 << 28) | (0x7 << 24), + (0x1 << 28) | (0x0 << 24)); + setbits_le32(&ch[chn].phy.b[b].dq[5], 0x1 << 31); + } + + setbits_le32(&ch[chn].phy.b0_rxdvs[0], (0x1 << 28) | (0x1 << 31)); + setbits_le32(&ch[chn].phy.b1_rxdvs[0], (0x1 << 28) | (0x1 << 31)); + for (u8 rank = RANK_0; rank < RANK_MAX; rank++) + for (u8 b = 0; b < 2; b++) + clrsetbits_le32(&ch[chn].phy.r[rank].b[b].rxdvs[2], + (0x3 << 30) | (0x1 << 28) | (0x1 << 23), + (0x2 << 30) | (0x1 << 28) | (0x1 << 23)); + +} + +static void dramc_hw_dqs_gating_tracking(u8 chn) +{ + setbits_le32(&ch[chn].ao.stbcal, (0x3 << 26) | (0x1 << 0)); + clrsetbits_le32(&ch[chn].ao.stbcal1, + (0xffff << 16) | (0x1 << 8) | (0x1 << 6), + (0x1 << 16) | (0x1 << 8) | (0x0 << 6)); + + clrsetbits_le32(&ch[chn].phy.misc_ctrl0, + (0x1 << 24) | (0x1f << 11) | (0xf << 0), + (0x1 << 24) | (0x0 << 11) | (0x0 << 0)); + + clrbits_le32(&ch[chn].phy.b[0].dq[6], 0x1 << 31); + clrbits_le32(&ch[chn].phy.b[1].dq[6], 0x1 << 31); + clrbits_le32(&ch[chn].phy.ca_cmd[6], 0x1 << 31); +} + +static void dramc_hw_gating_init(void) +{ + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { + clrbits_le32(&ch[chn].ao.stbcal, + (0x7 << 22) | (0x3 << 14) | (0x1 << 19) | (0x1 << 21)); + setbits_le32(&ch[chn].ao.stbcal, (0x1 << 20) | (0x3 << 28)); + setbits_le32(&ch[chn].phy.misc_ctrl1, 0x1 << 24); + + dramc_hw_dqs_gating_tracking(chn); + } +} + +static void dramc_impedance_tracking_enable(void) +{ + setbits_le32(&ch[0].phy.misc_ctrl0, 0x1 << 10); + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { + setbits_le32(&ch[chn].ao.impcal, (0x1 << 31) | (0x1 << 29) | + (0x1 << 26) | (0x1 << 17) | (0x7 << 11)); + clrbits_le32(&ch[chn].ao.impcal, 0x1 << 30); + setbits_le32(&ch[chn].phy.misc_ctrl0, 0x1 << 18); + setbits_le32(&ch[chn].ao.impcal, 0x1 << 19); + } + setbits_le32(&ch[0].ao.impcal, 0x1 << 14); + setbits_le32(&ch[1].ao.refctrl0, 0x1 << 2); + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) + setbits_le32(&ch[chn].ao.refctrl0, 0x1 << 3); +} + +static void dramc_phy_low_power_enable(void) +{ + u32 broadcast_bak = dramc_get_broadcast(); + dramc_set_broadcast(DRAMC_BROADCAST_OFF); + + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { + for (size_t b = 0; b < 2; b++) { + clrbits_le32(&ch[chn].phy.b[b].dll_fine_tune[2], + 0x3fffff << 10); + write32(&ch[chn].phy.b[b].dll_fine_tune[3], 0x2e800); + } + clrsetbits_le32(&ch[chn].phy.ca_dll_fine_tune[2], + 0x3fffff << 10, 0x2 << 10); + } + write32(&ch[0].phy.ca_dll_fine_tune[3], 0xba000); + write32(&ch[1].phy.ca_dll_fine_tune[3], 0x3a000); + + dramc_set_broadcast(broadcast_bak); +} +void dramc_runtime_config(void) +{ + clrbits_le32(&ch[0].ao.refctrl0, 0x1 << 29); + clrbits_le32(&ch[1].ao.refctrl0, 0x1 << 29); + + transfer_pll_to_spm_control(); + setbits_le32(&mtk_spm->spm_power_on_val0, 0x3 << 25); + + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) + dramc_rx_input_delay_tracking(chn); + + dramc_hw_gating_init(); + dramc_hw_gating_onoff(CHANNEL_A, true); + + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) + clrbits_le32(&ch[chn].ao.stbcal2, + (0x3 << 4) | (0x3 << 8) | (0x1 << 28)); + + clrbits_le32(&ch[0].ao.spcmdctrl, 0x1 << 30); + clrbits_le32(&ch[1].ao.spcmdctrl, 0x1 << 30); + + dramc_phy_low_power_enable(); + dramc_enable_phy_dcm(true); + + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) + for (size_t shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) + clrbits_le32(&ch[chn].ao.shu[shu].dqsg_retry, + (0x1 << 1) | (0x3 << 13)); + + write32(&ch[0].phy.misc_spm_ctrl0, 0xfbffefff); + write32(&ch[1].phy.misc_spm_ctrl0, 0xfbffefff); + write32(&ch[0].phy.misc_spm_ctrl2, 0xffffffef); + write32(&ch[1].phy.misc_spm_ctrl2, 0x7fffffef); + + dramc_impedance_tracking_enable(); + + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { + clrbits_le32(&ch[chn].ao.spcmdctrl, 0x3 << 28); + setbits_le32(&ch[chn].ao.hw_mrr_fun, (0x1 << 0) | (0x1 << 11)); + clrbits_le32(&ch[0].ao.refctrl0, 0x1 << 18); + setbits_le32(&ch[chn].phy.dvfs_emi_clk, 0x1 << 24); + setbits_le32(&ch[chn].ao.dvfsdll, 0x1 << 7); + } +} diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c index 1db0514778..7c39b634ef 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -190,22 +190,24 @@ static void dramc_write_dbi_onoff(bool on) (on ? 1 : 0) << SHU1_WODT_DBIWR_SHIFT); } -static void dramc_phy_dcm_disable(u8 chn) +static void dramc_phy_dcm_2_channel(u8 chn, bool en) { - clrsetbits_le32(&ch[chn].phy.misc_cg_ctrl0, - (0x1 << 20) | (0x1 << 19) | 0x3ff << 8, - (0x0 << 20) | (0x1 << 19) | 0x3ff << 8); + clrsetbits_le32(&ch[chn].phy.misc_cg_ctrl0, (0x3 << 19) | (0x3ff << 8), + ((en ? 0 : 0x1) << 19) | ((en ? 0 : 0x1ff) << 9) | (1 << 8)); for (size_t i = 0; i < DRAM_DFS_SHUFFLE_MAX; i++) { struct ddrphy_ao_shu *shu = &ch[chn].phy.shu[i]; - setbits_le32(&shu->b[0].dq[8], 0x1fff << 19); - setbits_le32(&shu->b[1].dq[8], 0x1fff << 19); + for (size_t b = 0; b < 2; b++) + clrsetbits_le32(&shu->b[b].dq[8], 0x1fff << 19, + ((en ? 0 : 0x7ff) << 22) | (0x1 << 21) | + ((en ? 0 : 0x3) << 19)); clrbits_le32(&shu->ca_cmd[8], 0x1fff << 19); } - clrbits_le32(&ch[chn].phy.misc_cg_ctrl5, (0x7 << 16) | (0x7 << 20)); + clrsetbits_le32(&ch[chn].phy.misc_cg_ctrl5, (0x7 << 16) | (0x7 << 20), + ((en ? 0x7 : 0) << 16) | ((en ? 0x7 : 0) << 20)); } -static void dramc_enable_phy_dcm(bool en) +void dramc_enable_phy_dcm(bool en) { u32 broadcast_bak = dramc_get_broadcast(); dramc_set_broadcast(DRAMC_BROADCAST_OFF); @@ -250,8 +252,7 @@ static void dramc_enable_phy_dcm(bool en) clrsetbits_le32(&shu->ca_cmd[7], mask, value); } - if (!en) - dramc_phy_dcm_disable(chn); + dramc_phy_dcm_2_channel(chn, en); } dramc_set_broadcast(broadcast_bak); } @@ -270,7 +271,7 @@ static void reset_delay_chain_before_calibration(void) } } -static void dramc_hw_gating_onoff(u8 chn, bool on) +void dramc_hw_gating_onoff(u8 chn, bool on) { clrsetbits_le32(&ch[chn].ao.shuctrl2, 0x3 << 14, (on ? 0x3 : 0) << 14); diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c index c1d9250f28..bb617f94fa 100644 --- a/src/soc/mediatek/mt8183/emi.c +++ b/src/soc/mediatek/mt8183/emi.c @@ -121,12 +121,9 @@ size_t sdram_size(void) static void set_rank_info_to_conf(const struct sdram_params *params) { - u8 u4value = 0; - - /* CONA 17th bit 0: Disable dual rank mode - 1: Enable dual rank mode */ - u4value = ((params->emi_cona_val & (0x1 << 17)) >> 17) ? 0 : 1; - clrsetbits_le32(&ch[0].ao.arbctl, 0x1 << 12, u4value << 12); + bool is_dual_rank = (params->emi_cona_val & (0x1 << 17)) != 0; + clrsetbits_le32(&ch[0].ao.rstmask, 0x1 << 12, + (is_dual_rank ? 0 : 1) << 12); } static void set_MRR_pinmux_mapping(void) @@ -271,6 +268,17 @@ static void dramc_init_pre_settings(void) setbits_le32(&ch[0].phy.misc_ctrl1, 0x1 << 31); } +static void dramc_ac_timing_optimize(void) +{ + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { + clrsetbits_le32(&ch[chn].ao.shu[0].actim[3], + 0xff << 16, 0x64 << 16); + clrbits_le32(&ch[chn].ao.shu[0].ac_time_05t, 0x1 << 2); + clrsetbits_le32(&ch[chn].ao.shu[0].actim[4], + 0x3ff << 0, 0x77 << 0); + } +} + static void init_dram(const struct sdram_params *params) { global_option_init(params); @@ -288,6 +296,8 @@ static void do_calib(const struct sdram_params *params) { dramc_apply_pre_calibration_config(); dramc_calibrate_all_channels(params); + dramc_ac_timing_optimize(); + dramc_runtime_config(); } 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 7b3215840d..04bb2bb28e 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h @@ -118,10 +118,13 @@ enum { }; void dramc_get_rank_size(u64 *dram_rank_size); +void dramc_runtime_config(void); void dramc_set_broadcast(u32 onoff); u32 dramc_get_broadcast(void); void dramc_init(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); +void dramc_hw_gating_onoff(u8 chn, bool onoff); +void dramc_enable_phy_dcm(bool bEn); #endif /* _DRAMC_PI_API_MT8183_H */ -- cgit v1.2.3