summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHuayang Duan <huayang.duan@mediatek.com>2020-06-01 16:30:27 +0800
committerHung-Te Lin <hungte@chromium.org>2020-09-25 01:33:11 +0000
commit63ee16075e7e4dee90c0cb9b05caeb91f77bf1e5 (patch)
tree31a9df5073b1248a6dece2d390e017da733e3a31
parent92c1546c01795f8c8c079e7ea03c9cb36314e92a (diff)
downloadcoreboot-63ee16075e7e4dee90c0cb9b05caeb91f77bf1e5.tar.gz
coreboot-63ee16075e7e4dee90c0cb9b05caeb91f77bf1e5.tar.bz2
coreboot-63ee16075e7e4dee90c0cb9b05caeb91f77bf1e5.zip
soc/mediatek/mt8183: Enable CA perbit mechanism
LPDDR4x has 6 CA PINs, but for some 8GB LPDDR4X DDR, the left margin of some CA PIN window is too small than others. Need to enable the CA perbit mechanism to avoid those risks. BUG=none BRANCH=kukui TEST=Boots correctly on Kukui Change-Id: I58e29d0c91a469112b0b1292da80bcb802322d47 Signed-off-by: Huayang Duan <huayang.duan@mediatek.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/41965 Reviewed-by: Hung-Te Lin <hungte@chromium.org> Reviewed-by: Yu-Ping Wu <yupingso@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r--src/soc/mediatek/mt8183/dramc_init_setting.c46
-rw-r--r--src/soc/mediatek/mt8183/dramc_pi_calibration_api.c344
-rw-r--r--src/soc/mediatek/mt8183/emi.c4
-rw-r--r--src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h1
-rw-r--r--src/soc/mediatek/mt8183/include/soc/dramc_param.h2
-rw-r--r--src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h17
-rw-r--r--src/soc/mediatek/mt8183/include/soc/dramc_register.h88
-rw-r--r--src/soc/mediatek/mt8183/include/soc/emi.h1
8 files changed, 449 insertions, 54 deletions
diff --git a/src/soc/mediatek/mt8183/dramc_init_setting.c b/src/soc/mediatek/mt8183/dramc_init_setting.c
index 794fad1c3d11..8a5d319b293f 100644
--- a/src/soc/mediatek/mt8183/dramc_init_setting.c
+++ b/src/soc/mediatek/mt8183/dramc_init_setting.c
@@ -11,24 +11,19 @@
#include <string.h>
#include <timer.h>
-enum {
- CKE_FIXOFF = 0,
- CKE_FIXON,
- CKE_DYNAMIC
-};
-
-static void cke_fix_onoff(int option, u8 chn)
+void dramc_cke_fix_onoff(enum cke_type option, u8 chn)
{
u8 on = 0, off = 0;
/* if CKE is dynamic, set both CKE fix On and Off as 0 */
if (option != CKE_DYNAMIC) {
on = option;
- off = (1 - option);
+ off = 1 - option;
}
- clrsetbits32(&ch[chn].ao.ckectrl,
- (0x1 << 6) | (0x1 << 7), (on << 6) | (off << 7));
+ SET32_BITFIELDS(&ch[chn].ao.ckectrl,
+ CKECTRL_CKEFIXON, on,
+ CKECTRL_CKEFIXOFF, off);
}
static void dvfs_settings(u8 freq_group)
@@ -296,8 +291,8 @@ static void ddr_phy_pll_setting(u8 chn, u8 freq_group)
for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++)
write32(regs_bak[i].addr, regs_bak[i].value);
- cke_fix_onoff(CKE_DYNAMIC, CHANNEL_A);
- cke_fix_onoff(CKE_DYNAMIC, CHANNEL_B);
+ dramc_cke_fix_onoff(CKE_DYNAMIC, CHANNEL_A);
+ dramc_cke_fix_onoff(CKE_DYNAMIC, CHANNEL_B);
if (freq_group == LP4X_DDR3200 || freq_group == LP4X_DDR3600) {
setbits32(&ch[chn].phy.shu[0].pll[5], 0x1 << 0);
@@ -522,6 +517,19 @@ static void update_initial_settings(u8 freq_group)
(0x1 << 31) | (0xa << 21) | (0xa << 26));
setbits32(&ch[0].ao.ckectrl, 0x1 << 23);
clrbits32(&ch[0].ao.shu[0].rodtenstb, 0x1 << 31);
+
+ /* CA prebit shift and delay */
+ SET32_BITFIELDS(&ch[0].ao.shu[0].selph_ca7,
+ SHU_SELPH_CA7_DLY_RA0, 0x0,
+ SHU_SELPH_CA7_DLY_RA1, 0x0,
+ SHU_SELPH_CA7_DLY_RA2, 0x0,
+ SHU_SELPH_CA7_DLY_RA3, 0x0,
+ SHU_SELPH_CA7_DLY_RA4, 0x0,
+ SHU_SELPH_CA7_DLY_RA5, 0x0);
+ SET32_BITFIELDS(&ch[0].phy.shu[0].rk[0].ca_cmd[9],
+ SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD, 0x20);
+ SET32_BITFIELDS(&ch[0].phy.shu[0].rk[1].ca_cmd[9],
+ SHU1_R1_CA_CMD9_RG_RK1_ARPI_CMD, 0x20);
}
static void dramc_power_on_sequence(void)
@@ -529,8 +537,8 @@ static void dramc_power_on_sequence(void)
for (size_t chn = 0; chn < CHANNEL_MAX; chn++)
clrbits32(&ch[chn].phy.misc_ctrl1, 0x1 << 13);
- dramc_cke_fix_onoff(CHANNEL_A, false, true);
- dramc_cke_fix_onoff(CHANNEL_B, false, true);
+ dramc_cke_fix_onoff(CKE_FIXOFF, CHANNEL_A);
+ dramc_cke_fix_onoff(CKE_FIXOFF, CHANNEL_B);
udelay(200);
for (size_t chn = 0; chn < CHANNEL_MAX; chn++)
@@ -540,8 +548,8 @@ static void dramc_power_on_sequence(void)
setbits32(&ch[chn].ao.dramc_pd_ctrl, 0x1 << 26);
udelay(2000);
- dramc_cke_fix_onoff(CHANNEL_A, true, false);
- dramc_cke_fix_onoff(CHANNEL_B, true, false);
+ dramc_cke_fix_onoff(CKE_FIXON, CHANNEL_A);
+ dramc_cke_fix_onoff(CKE_FIXON, CHANNEL_B);
udelay(2);
}
@@ -698,7 +706,7 @@ static u8 dramc_zq_calibration(u8 chn, u8 rank)
regs_bak[i].value = read32(regs_bak[i].addr);
setbits32(&ch[chn].ao.dramc_pd_ctrl, 0x1 << 26);
- dramc_cke_fix_onoff(chn, true, false);
+ dramc_cke_fix_onoff(CKE_FIXON, chn);
SET32_BITFIELDS(&ch[chn].ao.mrs, MRS_MRSRK, rank);
SET32_BITFIELDS(&ch[chn].ao.mpc_option, MPC_OPTION_MPCRKEN, 1);
@@ -842,8 +850,8 @@ static void auto_refresh_cke_off(void)
setbits32(&ch[chn].ao.refctrl0, 0x1 << 29);
udelay(3);
- cke_fix_onoff(CKE_FIXOFF, CHANNEL_A);
- cke_fix_onoff(CKE_FIXOFF, CHANNEL_B);
+ dramc_cke_fix_onoff(CKE_FIXOFF, CHANNEL_A);
+ dramc_cke_fix_onoff(CKE_FIXOFF, CHANNEL_B);
dramc_set_broadcast(broadcast_bak);
}
diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c
index fce7c9ff4a10..17fa2306e39d 100644
--- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c
+++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c
@@ -8,6 +8,7 @@
#include <soc/dramc_register.h>
#include <soc/dramc_param.h>
#include <soc/dramc_pi_api.h>
+#include <soc/spm.h>
#include <timer.h>
enum {
@@ -72,6 +73,11 @@ struct per_byte_dly {
u16 final_dly;
};
+static const u8 lp4_ca_mapping_pop[CHANNEL_MAX][CA_NUM_LP4] = {
+ [CHANNEL_A] = {1, 4, 3, 2, 0, 5},
+ [CHANNEL_B] = {0, 3, 2, 4, 1, 5},
+};
+
static void dramc_auto_refresh_switch(u8 chn, bool option)
{
SET32_BITFIELDS(&ch[chn].ao.refctrl0, REFCTRL0_REFDIS, option ? 0 : 1);
@@ -86,13 +92,6 @@ static void dramc_auto_refresh_switch(u8 chn, bool option)
}
}
-void dramc_cke_fix_onoff(u8 chn, bool cke_on, bool cke_off)
-{
- SET32_BITFIELDS(&ch[chn].ao.ckectrl,
- CKECTRL_CKEFIXON, cke_on,
- CKECTRL_CKEFIXOFF, cke_off);
-}
-
static u16 dramc_mode_reg_read(u8 chn, u8 mr_idx)
{
u16 value;
@@ -116,7 +115,7 @@ void dramc_mode_reg_write(u8 chn, u8 mr_idx, u8 value)
{
u32 ckectrl_bak = read32(&ch[chn].ao.ckectrl);
- dramc_cke_fix_onoff(chn, true, false);
+ dramc_cke_fix_onoff(CKE_FIXON, chn);
SET32_BITFIELDS(&ch[chn].ao.mrs, MRS_MRSMA, mr_idx);
SET32_BITFIELDS(&ch[chn].ao.mrs, MRS_MRSOP, value);
SET32_BITFIELDS(&ch[chn].ao.spcmd, SPCMD_MRWEN, 1);
@@ -255,33 +254,320 @@ static void dramc_write_leveling(u8 chn, u8 rank, u8 freq_group,
}
}
-static void dramc_cmd_bus_training(u8 chn, u8 rank, u8 freq_group,
- const struct sdram_params *params, const bool fast_calib)
+static void cbt_set_perbit_delay_cell(u8 chn, u8 rank)
{
- u32 final_vref, clk_dly, cmd_dly, cs_dly;
+ SET32_BITFIELDS(&ch[chn].phy.shu[0].rk[rank].ca_cmd[0],
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY, 0,
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY, 0,
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY, 0,
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY, 0,
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY, 0,
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY, 0);
+}
- clk_dly = params->cbt_clk_dly[chn][rank];
- cmd_dly = params->cbt_cmd_dly[chn][rank];
- cs_dly = params->cbt_cs_dly[chn][rank];
- final_vref = params->cbt_final_vref[chn][rank];
+static void set_dram_mr_cbt_on_off(u8 chn, u8 rank, u8 fsp,
+ u8 cbt_on, struct mr_value *mr)
+{
+ u8 MR13Value = mr->MR13Value;
- if (fast_calib) {
+ if (cbt_on) {
+ MR13Value |= 0x1;
+ if (fsp == FSP_1)
+ MR13Value &= 0x7f;
+ else
+ MR13Value |= 0x80;
+ } else {
+ MR13Value &= 0xfe;
+ if (fsp == FSP_1)
+ MR13Value |= 0x80;
+ else
+ MR13Value &= 0x7f;
+ }
+
+ dramc_mode_reg_write_by_rank(chn, rank, 13, MR13Value);
+ mr->MR13Value = MR13Value;
+}
+
+static void cbt_set_fsp(u8 chn, u8 rank, u8 fsp, struct mr_value *mr)
+{
+ u8 MR13Value = mr->MR13Value;
+
+ if (fsp == FSP_0) {
+ MR13Value &= ~(BIT(6));
+ MR13Value &= 0x7f;
+ } else {
+ MR13Value |= BIT(6);
+ MR13Value |= 0x80;
+ }
+
+ dramc_mode_reg_write_by_rank(chn, rank, 13, MR13Value);
+ mr->MR13Value = MR13Value;
+}
+
+static void o1_path_on_off(u8 cbt_on)
+{
+ u8 fix_dqien = (cbt_on == 1) ? 3 : 0;
+
+ for (u8 chn = 0; chn < CHANNEL_MAX; chn++) {
+ SET32_BITFIELDS(&ch[chn].ao.padctrl, PADCTRL_FIXDQIEN, fix_dqien);
+ SET32_BITFIELDS(&ch[chn].phy.b[0].dq[5],
+ B0_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B0, cbt_on);
+ SET32_BITFIELDS(&ch[chn].phy.b[1].dq[5],
+ B1_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B1, cbt_on);
+ SET32_BITFIELDS(&ch[chn].phy.b[0].dq[3],
+ B0_DQ3_RG_RX_ARDQ_SMT_EN_B0, cbt_on);
+ SET32_BITFIELDS(&ch[chn].phy.b[1].dq[3],
+ B1_DQ3_RG_RX_ARDQ_SMT_EN_B1, cbt_on);
+ }
+ udelay(1);
+}
+
+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_PHYCLKDYNGEN, 0,
+ DRAMC_PD_CTRL_DCMEN, 0);
+ SET32_BITFIELDS(&ch[chn].ao.stbcal, STBCAL_DQSIENCG_NORMAL_EN, 0);
+ 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);
+
+ 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)
+{
+ dramc_cke_fix_onoff(CKE_FIXON, chn);
+
+ udelay(1);
+ set_dram_mr_cbt_on_off(chn, rank, fsp, 0, mr);
+ o1_path_on_off(0);
+}
+
+static void cbt_set_vref(u8 chn, u8 rank, u8 vref, bool is_final)
+{
+ if (!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);
+ SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_DQS_WLEV, 1);
+ udelay(1);
+ SET32_BITFIELDS(&ch[chn].ao.write_lev, WRITE_LEV_DQS_WLEV, 0);
+ } else {
+ vref |= BIT(6);
+ dramc_dbg("final_vref: %#x\n", vref);
+
+ /* CBT set vref */
+ dramc_mode_reg_write_by_rank(chn, rank, 12, vref);
+ }
+}
+
+static void cbt_set_ca_clk_result(u8 chn, u8 rank,
+ const struct sdram_params *params)
+{
+ const u8 *perbit_dly;
+ u8 clk_dly = params->cbt_clk_dly[chn][rank];
+ u8 cmd_dly = params->cbt_cmd_dly[chn][rank];
+ const u8 *ca_mapping = lp4_ca_mapping_pop[chn];
+
+ for (u8 rk = 0; rk < rank + 1; rk++) {
/* Set CLK and CA delay */
- SET32_BITFIELDS(&ch[chn].phy.shu[0].rk[rank].ca_cmd[9],
+ SET32_BITFIELDS(&ch[chn].phy.shu[0].rk[rk].ca_cmd[9],
SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD, cmd_dly,
SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK, clk_dly);
udelay(1);
+
+ perbit_dly = params->cbt_ca_perbit_delay[chn][rk];
+
+ /* Set CA perbit delay line calibration results */
+ SET32_BITFIELDS(&ch[chn].phy.shu[0].rk[rk].ca_cmd[0],
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY, perbit_dly[ca_mapping[0]],
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY, perbit_dly[ca_mapping[1]],
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY, perbit_dly[ca_mapping[2]],
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY, perbit_dly[ca_mapping[3]],
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY, perbit_dly[ca_mapping[4]],
+ SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY, perbit_dly[ca_mapping[5]]);
}
+}
- /* Set CLK and CS delay */
- SET32_BITFIELDS(&ch[chn].phy.shu[0].rk[rank].ca_cmd[9],
- SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS, cs_dly);
+static u8 get_cbt_vref_pinmux_value(u8 chn, u8 vref_level)
+{
+ u8 vref_bit, vref_new, vref_org;
- final_vref |= (1 << 6);
+ vref_new = 0;
+ vref_org = BIT(6) | (vref_level & 0x3f);
+ for (vref_bit = 0; vref_bit < 8; vref_bit++) {
+ if (vref_org & (1 << vref_bit))
+ vref_new |= (1 << phy_mapping[chn][vref_bit]);
+ }
+
+ dramc_dbg("vref_new: %#x --> %#x\n", vref_org, vref_new);
+
+ return vref_new;
+}
+
+static void cbt_dramc_dfs_direct_jump(u8 shu_level)
+{
+ u8 shu_ack = 0;
+ static bool phy_pll_en = true;
+
+ for (u8 chn = 0; chn < CHANNEL_MAX; chn++)
+ shu_ack |= (0x1 << chn);
+
+ if (phy_pll_en) {
+ dramc_dbg("Disable CLRPLL\n");
+ SET32_BITFIELDS(&ch[0].phy.pll2, PLL2_RG_RCLRPLL_EN, 0);
+ dramc_dbg("DFS jump to CLRPLL, shu lev=%d, ACK=%x\n",
+ shu_level, shu_ack);
+ } else {
+ dramc_dbg("Disable PHYPLL\n");
+ SET32_BITFIELDS(&ch[0].phy.pll1, PLL1_RG_RPHYPLL_EN, 0);
+ dramc_dbg("DFS jump to PHYPLL, shu lev=%d, ACK=%x\n",
+ shu_level, shu_ack);
+ }
+
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_PHYPLL1_SHU_EN_PCM, 0);
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_PHYPLL2_SHU_EN_PCM, 0);
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_DR_SHU_LEVEL_PCM, 0);
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_DR_SHU_LEVEL_PCM, shu_level);
+
+ if (phy_pll_en) {
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_PHYPLL2_SHU_EN_PCM, 1);
+ udelay(1);
+ SET32_BITFIELDS(&ch[0].phy.pll2, PLL2_RG_RCLRPLL_EN, 1);
+ dramc_dbg("Enable CLRPLL\n");
+ } else {
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_PHYPLL1_SHU_EN_PCM, 1);
+ udelay(1);
+ SET32_BITFIELDS(&ch[0].phy.pll1, PLL1_RG_RPHYPLL_EN, 1);
+ dramc_dbg("Enable PHYPLL\n");
+ }
+
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_TX_TRACKING_DIS, 3);
+
+ udelay(20);
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_DDRPHY_FB_CK_EN_PCM, 1);
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_DPHY_RXDLY_TRACK_EN, 0);
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_DR_SHU_EN_PCM, 1);
- /* CBT set vref */
- dramc_mode_reg_write_by_rank(chn, rank, 12, final_vref);
- dramc_dbg("final_vref: %#x\n", final_vref);
+ while ((READ32_BITFIELD(&mtk_spm->dramc_dpy_clk_sw_con,
+ DRAMC_DPY_CLK_SW_CON_SC_DMDRAMCSHU_ACK) & shu_ack)
+ != shu_ack) {
+ dramc_dbg("wait shu_en ack.\n");
+ }
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_DR_SHU_EN_PCM, 0);
+
+ if (shu_level == 0)
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_DPHY_RXDLY_TRACK_EN, 3);
+
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_TX_TRACKING_DIS, 0);
+ SET32_BITFIELDS(&mtk_spm->spm_power_on_val0,
+ SPM_POWER_ON_VAL0_SC_DDRPHY_FB_CK_EN_PCM, 0);
+
+ if (phy_pll_en)
+ SET32_BITFIELDS(&ch[0].phy.pll1, PLL1_RG_RPHYPLL_EN, 0);
+ else
+ SET32_BITFIELDS(&ch[0].phy.pll2, PLL2_RG_RCLRPLL_EN, 0);
+ dramc_dbg("Shuffle flow complete\n");
+
+ phy_pll_en = !phy_pll_en;
+}
+
+static void cbt_switch_freq(cbt_freq freq)
+{
+ if (freq == CBT_LOW_FREQ)
+ cbt_dramc_dfs_direct_jump(DRAM_DFS_SHUFFLE_MAX - 1);
+ else
+ cbt_dramc_dfs_direct_jump(DRAM_DFS_SHUFFLE_1);
+}
+
+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)
+{
+ u8 final_vref, cs_dly;
+ u8 fsp = get_freq_fsq(freq_group);
+
+ cs_dly = params->cbt_cs_dly[chn][rank];
+ final_vref = params->cbt_final_vref[chn][rank];
+
+ struct reg_value regs_bak[] = {
+ {&ch[chn].ao.dramc_pd_ctrl},
+ {&ch[chn].ao.stbcal},
+ {&ch[chn].ao.ckectrl},
+ {&ch[chn].ao.write_lev},
+ {&ch[chn].ao.refctrl0},
+ {&ch[chn].ao.spcmdctrl},
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(regs_bak); i++)
+ 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);
+ SET32_BITFIELDS(&ch[chn].ao.rkcfg, RKCFG_TXRANKFIX, 1);
+ SET32_BITFIELDS(&ch[chn].ao.mpc_option, MPC_OPTION_MPCRKEN, 0);
+ }
+
+ 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);
+
+ u8 new_vref = get_cbt_vref_pinmux_value(chn, final_vref);
+ cbt_set_vref(chn, rank, new_vref, 0);
+
+ cbt_set_ca_clk_result(chn, rank, params);
+
+ for (u8 rk = 0; rk < rank + 1; rk++) {
+ /* Set CLK and CS delay */
+ SET32_BITFIELDS(&ch[chn].phy.shu[0].rk[rk].ca_cmd[9],
+ SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS, cs_dly);
+ }
+
+ if (fsp == FSP_1)
+ cbt_switch_freq(CBT_LOW_FREQ);
+ cbt_exit(chn, rank, fsp, mr);
+
+ cbt_set_fsp(chn, rank, fsp, mr);
+ cbt_set_vref(chn, rank, final_vref, 1);
+
+ if (fsp == FSP_1)
+ cbt_switch_freq(CBT_HIGH_FREQ);
+
+ /* restore MRR pinmux */
+ set_mrr_pinmux_mapping();
+ if (rank == RANK_1) {
+ SET32_BITFIELDS(&ch[chn].ao.mrs, MRS_MRSRK, 0);
+ SET32_BITFIELDS(&ch[chn].ao.rkcfg, RKCFG_TXRANK, 0);
+ SET32_BITFIELDS(&ch[chn].ao.rkcfg, RKCFG_TXRANKFIX, 0);
+ SET32_BITFIELDS(&ch[chn].ao.mpc_option, MPC_OPTION_MPCRKEN, 0x1);
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(regs_bak); i++)
+ write32(regs_bak[i].addr, regs_bak[i].value);
}
static void dramc_read_dbi_onoff(size_t chn, bool on)
@@ -505,7 +791,7 @@ void dramc_apply_config_after_calibration(const struct mr_value *mr)
clrbits32(&ch[chn].ao.shu[shu].scintv, 0x1 << 30);
clrbits32(&ch[chn].ao.dummy_rd, (0x7 << 20) | (0x1 << 7));
- dramc_cke_fix_onoff(chn, false, false);
+ dramc_cke_fix_onoff(CKE_DYNAMIC, chn);
clrbits32(&ch[chn].ao.dramc_pd_ctrl, 0x1 << 26);
clrbits32(&ch[chn].ao.eyescan, 0x7 << 8);
@@ -2189,7 +2475,7 @@ static void dqsosc_auto(u8 chn, u8 rank, u8 freq_group,
SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl,
DRAMC_PD_CTRL_MIOCKCTRLOFF, 1);
- dramc_cke_fix_onoff(chn, true, false);
+ dramc_cke_fix_onoff(CKE_FIXON, chn);
start_dqsosc(chn);
udelay(1);
@@ -2757,8 +3043,8 @@ void get_dram_info_after_cal(u8 *density_result)
*density_result = max_density;
}
-int dramc_calibrate_all_channels(const struct sdram_params *pams, u8 freq_group,
- const struct mr_value *mr)
+int dramc_calibrate_all_channels(const struct sdram_params *pams,
+ u8 freq_group, struct mr_value *mr)
{
bool fast_calib;
switch (pams->source) {
@@ -2782,7 +3068,7 @@ int dramc_calibrate_all_channels(const struct sdram_params *pams, u8 freq_group,
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);
+ fast_calib, mr);
dramc_write_leveling(chn, rk, freq_group, pams->wr_level);
dramc_auto_refresh_switch(chn, true);
diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c
index 579bfbecbcc9..8afbef00d87a 100644
--- a/src/soc/mediatek/mt8183/emi.c
+++ b/src/soc/mediatek/mt8183/emi.c
@@ -157,7 +157,7 @@ static void set_rank_info_to_conf(const struct sdram_params *params)
(is_dual_rank ? 0 : 1) << 12);
}
-static void set_MRR_pinmux_mapping(void)
+void set_mrr_pinmux_mapping(void)
{
for (size_t chn = 0; chn < CHANNEL_MAX; chn++) {
const u8 *map = phy_mapping[chn];
@@ -182,7 +182,7 @@ static void set_MRR_pinmux_mapping(void)
static void global_option_init(const struct sdram_params *params)
{
set_rank_info_to_conf(params);
- set_MRR_pinmux_mapping();
+ set_mrr_pinmux_mapping();
}
static void set_vcore_voltage(u8 freq_group)
diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h b/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h
index b5ae253cdfe2..c630b5aa9087 100644
--- a/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h
+++ b/src/soc/mediatek/mt8183/include/soc/dramc_common_mt8183.h
@@ -29,6 +29,7 @@ enum dram_odt_type {
};
enum {
+ CA_NUM_LP4 = 6,
DQ_DATA_WIDTH = 16,
DQS_BIT_NUMBER = 8,
DQS_NUMBER = (DQ_DATA_WIDTH / DQS_BIT_NUMBER)
diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_param.h b/src/soc/mediatek/mt8183/include/soc/dramc_param.h
index e35e4f542125..f925162e4a0d 100644
--- a/src/soc/mediatek/mt8183/include/soc/dramc_param.h
+++ b/src/soc/mediatek/mt8183/include/soc/dramc_param.h
@@ -10,7 +10,7 @@
enum {
DRAMC_PARAM_HEADER_MAGIC = 0x44524d4b,
- DRAMC_PARAM_HEADER_VERSION = 3,
+ DRAMC_PARAM_HEADER_VERSION = 4,
};
enum DRAMC_PARAM_STATUS_CODES {
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 437ed3db2d71..a0937d01c620 100644
--- a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h
+++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h
@@ -27,6 +27,7 @@
#define IMP_DRVN_LP4X_UNTERM_VREF_SEL 0x16
#define IMP_TRACK_LP4X_UNTERM_VREF_SEL 0x1a
#define MR23_DEFAULT_VALUE 0x3f
+#define CA_TRAINING_NUM 10
enum dram_te_op {
TE_OP_WRITE_READ_CHECK = 0,
@@ -42,6 +43,17 @@ enum {
GATING_GOLDEND_DQSCNT = 0x4646
};
+enum cke_type {
+ CKE_FIXOFF = 0,
+ CKE_FIXON,
+ CKE_DYNAMIC
+};
+
+typedef enum {
+ CBT_LOW_FREQ = 0,
+ CBT_HIGH_FREQ,
+} cbt_freq;
+
enum {
IMPCAL_STAGE_DRVP = 0x1,
IMPCAL_STAGE_DRVN,
@@ -98,14 +110,15 @@ void dramc_sw_impedance_cal(const struct sdram_params *params, u8 term_option,
void dramc_apply_config_before_calibration(u8 freq_group);
void dramc_apply_config_after_calibration(const struct mr_value *mr);
int dramc_calibrate_all_channels(const struct sdram_params *pams,
- u8 freq_group, const struct mr_value *mr);
+ u8 freq_group, struct mr_value *mr);
void dramc_hw_gating_onoff(u8 chn, bool onoff);
void dramc_enable_phy_dcm(u8 chn, bool bEn);
void dramc_mode_reg_write(u8 chn, u8 mr_idx, u8 value);
-void dramc_cke_fix_onoff(u8 chn, bool fix_on, bool fix_off);
u32 get_shu_freq(u8 shu);
void dramc_hw_dqsosc(u8 chn);
void dramc_dqs_precalculation_preset(void);
void get_dram_info_after_cal(u8 *density);
+void set_mrr_pinmux_mapping(void);
+void dramc_cke_fix_onoff(enum cke_type option, u8 chn);
#endif /* _DRAMC_PI_API_MT8183_H */
diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_register.h b/src/soc/mediatek/mt8183/include/soc/dramc_register.h
index 1e1448b92341..99005a19a673 100644
--- a/src/soc/mediatek/mt8183/include/soc/dramc_register.h
+++ b/src/soc/mediatek/mt8183/include/soc/dramc_register.h
@@ -623,8 +623,9 @@ DEFINE_BIT(DDRCONF0_DM4TO1MODE, 22)
DEFINE_BIT(DDRCONF0_RDATRST, 0)
DEFINE_BIT(PERFCTL0_RWOFOEN, 4)
+DEFINE_BITFIELD(RKCFG_TXRANK, 1, 0)
+DEFINE_BIT(RKCFG_TXRANKFIX, 3)
DEFINE_BIT(RKCFG_DQSOSC2RK, 11)
-DEFINE_BIT(DRAMC_PD_CTRL_MIOCKCTRLOFF, 26)
DEFINE_BIT(PADCTRL_DQIENLATEBEGIN, 3)
DEFINE_BITFIELD(PADCTRL_DQIENQKEND, 1, 0)
@@ -797,6 +798,7 @@ DEFINE_BITFIELD(FINE_TUNE_DQ, 13, 8)
DEFINE_BITFIELD(SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK, 29, 24)
DEFINE_BITFIELD(SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD, 13, 8)
+DEFINE_BITFIELD(SHU1_R1_CA_CMD9_RG_RK1_ARPI_CMD, 13, 8)
DEFINE_BITFIELD(SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS, 5, 0)
/* DRAMC_REG_ADDR(DRAMC_REG_PRE_TDQSCK1) */
@@ -908,6 +910,90 @@ DEFINE_BITFIELD(RK0_PRE_TDQSCK12_TDQSCK_UIFREQ1_P1_B3R0, 5, 0)
DEFINE_BITFIELD(RK0_PRE_TDQSCK11_TDQSCK_PIFREQ3_B3R0, 12, 6)
DEFINE_BITFIELD(RK0_PRE_TDQSCK11_TDQSCK_UIFREQ3_B3R0, 5, 0)
+/* DRAMC_REG_MRR_BIT_MUX1 */
+DEFINE_BITFIELD(MRR_BIT_MUX1_MRR_BIT3_SEL, 28, 24)
+DEFINE_BITFIELD(MRR_BIT_MUX1_MRR_BIT2_SEL, 20, 16)
+DEFINE_BITFIELD(MRR_BIT_MUX1_MRR_BIT1_SEL, 12, 8)
+DEFINE_BITFIELD(MRR_BIT_MUX1_MRR_BIT0_SEL, 4, 0)
+
+/* DRAMC_REG_SHU_SELPH_CA7 */
+DEFINE_BITFIELD(SHU_SELPH_CA7_DLY_RA5, 22, 20)
+DEFINE_BITFIELD(SHU_SELPH_CA7_DLY_RA4, 18, 16)
+DEFINE_BITFIELD(SHU_SELPH_CA7_DLY_RA3, 14, 12)
+DEFINE_BITFIELD(SHU_SELPH_CA7_DLY_RA2, 10, 8)
+DEFINE_BITFIELD(SHU_SELPH_CA7_DLY_RA1, 6, 4)
+DEFINE_BITFIELD(SHU_SELPH_CA7_DLY_RA0, 2, 0)
+
+/* DRAMC_REG_MRR_BIT_MUX2 */
+DEFINE_BITFIELD(MRR_BIT_MUX2_MRR_BIT5_SEL, 12, 8)
+DEFINE_BITFIELD(MRR_BIT_MUX2_MRR_BIT4_SEL, 4, 0)
+
+/* DDRPHY_SHU1_R0_CA_CMD0 */
+DEFINE_BITFIELD(SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY, 23, 20)
+DEFINE_BITFIELD(SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY, 19, 16)
+DEFINE_BITFIELD(SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY, 15, 12)
+DEFINE_BITFIELD(SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY, 11, 8)
+DEFINE_BITFIELD(SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY, 7, 4)
+DEFINE_BITFIELD(SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY, 3, 0)
+
+/* DDRPHY_PLL2 */
+DEFINE_BIT(PLL2_RG_RCLRPLL_EN, 31)
+
+/* DDRPHY_PLL1 */
+DEFINE_BIT(PLL1_RG_RPHYPLL_EN, 31)
+
+/* DRAMC_REG_PADCTRL */
+DEFINE_BITFIELD(PADCTRL_FIXDQIEN, 19, 16)
+
+/* SPM_POWER_ON_VAL0 */
+DEFINE_BIT(SPM_POWER_ON_VAL0_SC_DR_SHU_EN_PCM, 22)
+DEFINE_BIT(SPM_POWER_ON_VAL0_SC_DPHY_RXDLY_TRACK_EN, 25)
+DEFINE_BIT(SPM_POWER_ON_VAL0_SC_DDRPHY_FB_CK_EN_PCM, 16)
+DEFINE_BIT(SPM_POWER_ON_VAL0_SC_TX_TRACKING_DIS, 11)
+DEFINE_BITFIELD(SPM_POWER_ON_VAL0_SC_DR_SHU_LEVEL_PCM, 31, 30)
+DEFINE_BIT(SPM_POWER_ON_VAL0_SC_PHYPLL2_SHU_EN_PCM, 27)
+DEFINE_BIT(SPM_POWER_ON_VAL0_SC_PHYPLL1_SHU_EN_PCM, 26)
+
+/* SPM_POWER_ON_VAL1 */
+DEFINE_BIT(SPM_POWER_ON_VAL1_SC_DR_SHORT_QUEUE_PCM, 31)
+
+/* SPM_DRAMC_DPY_CLK_SW_CON */
+DEFINE_BITFIELD(DRAMC_DPY_CLK_SW_CON_SC_DMDRAMCSHU_ACK, 25, 24)
+
+/* DRAMC_REG_DRAMC_PD_CTRL */
+DEFINE_BIT(DRAMC_PD_CTRL_DCMEN, 0)
+DEFINE_BIT(DRAMC_PD_CTRL_PHYCLKDYNGEN, 30)
+DEFINE_BIT(DRAMC_PD_CTRL_MIOCKCTRLOFF, 26)
+
+/* DRAMC_REG_WRITE_LEV */
+DEFINE_BIT(WRITE_LEV_DQS_WLEV, 7)
+DEFINE_BITFIELD(WRITE_LEV_DQSBX_G, 11, 8)
+DEFINE_BITFIELD(WRITE_LEV_DQS_SEL, 19, 16)
+DEFINE_BITFIELD(WRITE_LEV_DMVREFCA, 27, 20)
+DEFINE_BIT(WRITE_LEV_WRITE_LEVEL_EN, 0)
+DEFINE_BIT(WRITE_LEV_BYTEMODECBTEN, 3)
+
+/* DRAMC_REG_STBCAL */
+DEFINE_BIT(STBCAL_DQSIENCG_NORMAL_EN, 29)
+
+/* DDRPHY_B0_DQ5 */
+DEFINE_BIT(B0_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B0, 17)
+
+/* DDRPHY_B1_DQ5 */
+DEFINE_BIT(B1_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B1, 17)
+
+/* DDRPHY_B0_DQ3 */
+DEFINE_BIT(B0_DQ3_RG_RX_ARDQ_SMT_EN_B0, 1)
+
+/* DDRPHY_B1_DQ3 */
+DEFINE_BIT(B1_DQ3_RG_RX_ARDQ_SMT_EN_B1, 1)
+
+/* DDRPHY_CA_CMD5 */
+DEFINE_BIT(CA_CMD5_RG_RX_ARCMD_EYE_VREF_EN, 17)
+
+/* DDRPHY_CA_CMD3 */
+DEFINE_BIT(CA_CMD3_RG_RX_ARCMD_SMT_EN, 1)
+
struct dramc_channel_regs {
union {
struct dramc_ddrphy_ao_regs phy;
diff --git a/src/soc/mediatek/mt8183/include/soc/emi.h b/src/soc/mediatek/mt8183/include/soc/emi.h
index cf794dee8951..6931d5bb8150 100644
--- a/src/soc/mediatek/mt8183/include/soc/emi.h
+++ b/src/soc/mediatek/mt8183/include/soc/emi.h
@@ -27,6 +27,7 @@ struct sdram_params {
u8 cbt_clk_dly[CHANNEL_MAX][RANK_MAX];
u8 cbt_cmd_dly[CHANNEL_MAX][RANK_MAX];
u8 cbt_cs_dly[CHANNEL_MAX][RANK_MAX];
+ u8 cbt_ca_perbit_delay[CHANNEL_MAX][RANK_MAX][DQS_BIT_NUMBER];
/* Gating */
u8 gating2T[CHANNEL_MAX][RANK_MAX][DQS_NUMBER];