Tristan Hsieh has uploaded this change for review. ( https://review.coreboot.org/28844
Change subject: mediatek/mt8183: Add DDR driver of runtime config part ......................................................................
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 huayang.duan@mediatek.com --- M src/soc/mediatek/mt8183/dramc_pi_basic_api.c 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 4 files changed, 228 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/44/28844/1
diff --git a/src/soc/mediatek/mt8183/dramc_pi_basic_api.c b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c index 74eddd5..b172e16 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 <arch/io.h> #include <delay.h> #include <soc/emi.h> +#include <soc/spm.h> #include <soc/dramc_register.h> #include <soc/dramc_pi_api.h>
@@ -132,3 +133,212 @@ dramc_set_broadcast(broadcast_bak); }
+static void transfer_pll_to_spm_control(void) +{ + u8 shu_lev = (read32(&ch[0].ao.shustatus) & 0x00000006) >> 1; + + /* set SPM project code and enable clock enable */ + 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 << 0); + setbits_le32(&mtk_spm->dramc_dpy_clk_sw_con_sel2, 0xffffffff << 0); + + 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 (u8 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 (u8 r = 0; r < 2; r++) + for (u8 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 b = 0; b < 2; b++) { + /* tracking rising and update rising/falling together */ + clrbits_le32(&ch[chn].phy.r[0].b[b].rxdvs[2], (0x1 << 29)); + clrbits_le32(&ch[chn].phy.r[1].b[b].rxdvs[2], (0x1 << 29)); + + /* DQS, DQ, DQM (DQ, DQM are tied together now) + * -> controlled using DQM MAX_MIN */ + clrsetbits_le32(&ch[chn].phy.r[0].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[0].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[0].b[b].rxdvs[2], + (0x3 << 26) | (0x3 << 24) | (0x3 << 18) | (0x3 << 16)); + + /* DQS, DQ, DQM (DQ, DQM are tied together now) + * -> controlled using DQM MAX_MIN */ + clrsetbits_le32(&ch[chn].phy.r[1].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[1].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[1].b[b].rxdvs[2], + (0x3 << 26) | (0x3 << 24)); + clrbits_le32(&ch[chn].phy.r[1].b[b].rxdvs[2], + (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 (u8 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) +{ + u8 chn; + + setbits_le32(&ch[0].phy.misc_ctrl0, (0x1 << 10)); + for (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 (chn = 0; chn < CHANNEL_MAX; chn++) + setbits_le32(&ch[chn].ao.refctrl0, (0x1 << 3)); +} + +void dramc_runtime_config(void) +{ + u8 chn = 0, shu = 0, shu_cnt = DRAM_DFS_SHUFFLE_MAX; + + 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)); + + dramc_dbg("TX_TRACKING: OFF\n"); + for (chn = 0; chn < CHANNEL_MAX; chn++) + dramc_rx_input_delay_tracking(chn); + dramc_dbg("RX_TRACKING: ON\n"); + + dramc_hw_gating_init(); + dramc_hw_gating_onoff(CHANNEL_A, GATING_ON); + dramc_dbg("HW_GATING: ON\n"); + + for (chn = 0; chn < CHANNEL_MAX; chn++) + clrbits_le32(&ch[chn].ao.stbcal2, + (0x3 << 4) | (0x3 << 8) | (0x1 << 28)); + dramc_dbg("HW_GATING DBG: OFF\n"); + + /* ZQCS_ENABLE_LP4 */ + clrbits_le32(&ch[0].ao.spcmdctrl, (0x1 << 30)); + clrbits_le32(&ch[1].ao.spcmdctrl, (0x1 << 30)); + dramc_dbg("ZQCS_ENABLE_LP4: OFF\n"); + + dramc_enable_phy_dcm(0); + dramc_dbg("LOWPOWER_GOLDEN_SETTINGS(DCM): OFF\n"); + + for (chn = 0; chn < CHANNEL_MAX; chn++) + for (shu = 0; shu < shu_cnt; shu++) + clrbits_le32(&ch[chn].ao.shu[shu].dqsg_retry, + (0x1 << 1) | (0x3 << 13)); + dramc_dbg("DUMMY_READ_FOR_DQS_GATING_RETRY: OFF\n"); + + 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_dbg("SPM_CONTROL_AFTERK: ON\n"); + + dramc_impedance_tracking_enable(); + dramc_dbg("IMPEDANCE_TRACKING: ON\n"); + + for (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)); + dramc_dbg("TEMP_SENSOR: ON\n"); + + clrbits_le32(&ch[0].ao.refctrl0, (0x1 << 18)); + dramc_dbg("PER_BANK_REFRESH: OFF\n"); + + 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 2295f39..f1ce236 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -241,7 +241,7 @@ } }
-static void dramc_enable_phy_dcm(u8 en) +void dramc_enable_phy_dcm(u8 en) { u32 broadcast_bak = dramc_get_broadcast(); u8 shu, shu_cnt = DRAM_DFS_SHUFFLE_MAX; @@ -309,7 +309,7 @@ } }
-static void dramc_hw_gating_onoff(u8 chn, u8 onoff) +void dramc_hw_gating_onoff(u8 chn, u8 onoff) { clrsetbits_le32(&ch[chn].ao.shuctrl2, 0x3 << 14, (onoff << 14) | (onoff << 15)); diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c index eb75890..f991932 100644 --- a/src/soc/mediatek/mt8183/emi.c +++ b/src/soc/mediatek/mt8183/emi.c @@ -274,6 +274,17 @@ setbits_le32(&ch[0].phy.misc_ctrl1, (0x1 << 31)); }
+static void dramc_ac_timing_optimize(void) +{ + for (u8 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 dramc_init(void) { for (int i = 0; i < ARRAY_SIZE(init_settings); i++) @@ -297,6 +308,8 @@ { 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 a67e16d..e1a0333 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h @@ -136,6 +136,7 @@ };
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_sw_impedance(const struct sdram_params *params); @@ -143,4 +144,6 @@ void dramc_calibrate_all_channels(const struct sdram_params *params); void dramc_save_restore_multi_reg(u8 type, u32 *store_mem, u32 **addr, u32 count); +void dramc_hw_gating_onoff(u8 chn, u8 onoff); +void dramc_enable_phy_dcm(u8 bEn); #endif /* _DRAMC_PI_API_MT8183_H */