summaryrefslogtreecommitdiff
path: root/src/soc/mediatek/mt8183/dramc_pi_basic_api.c
diff options
context:
space:
mode:
authorHuayang Duan <huayang.duan@mediatek.com>2018-09-26 21:09:54 +0800
committerPatrick Georgi <pgeorgi@google.com>2019-01-03 22:22:48 +0000
commit7b78a805da0207449c5ea1baf56030ab9f54e2d6 (patch)
tree0de9d9fb71948454225b811aac5151c41d3c1905 /src/soc/mediatek/mt8183/dramc_pi_basic_api.c
parent6202d1b51a45e9ed00f742318363920776e32d52 (diff)
downloadcoreboot-7b78a805da0207449c5ea1baf56030ab9f54e2d6.tar.xz
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> Reviewed-on: https://review.coreboot.org/c/28844 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Diffstat (limited to 'src/soc/mediatek/mt8183/dramc_pi_basic_api.c')
-rw-r--r--src/soc/mediatek/mt8183/dramc_pi_basic_api.c197
1 files changed, 197 insertions, 0 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 <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>
@@ -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);
+ }
+}