summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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];