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>
This commit is contained in:
Huayang Duan 2020-06-01 16:30:27 +08:00 committed by Hung-Te Lin
parent 92c1546c01
commit 63ee16075e
8 changed files with 449 additions and 54 deletions

View File

@ -11,24 +11,19 @@
#include <string.h> #include <string.h>
#include <timer.h> #include <timer.h>
enum { void dramc_cke_fix_onoff(enum cke_type option, u8 chn)
CKE_FIXOFF = 0,
CKE_FIXON,
CKE_DYNAMIC
};
static void cke_fix_onoff(int option, u8 chn)
{ {
u8 on = 0, off = 0; u8 on = 0, off = 0;
/* if CKE is dynamic, set both CKE fix On and Off as 0 */ /* if CKE is dynamic, set both CKE fix On and Off as 0 */
if (option != CKE_DYNAMIC) { if (option != CKE_DYNAMIC) {
on = option; on = option;
off = (1 - option); off = 1 - option;
} }
clrsetbits32(&ch[chn].ao.ckectrl, SET32_BITFIELDS(&ch[chn].ao.ckectrl,
(0x1 << 6) | (0x1 << 7), (on << 6) | (off << 7)); CKECTRL_CKEFIXON, on,
CKECTRL_CKEFIXOFF, off);
} }
static void dvfs_settings(u8 freq_group) 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++) for (size_t i = 0; i < ARRAY_SIZE(regs_bak); i++)
write32(regs_bak[i].addr, regs_bak[i].value); write32(regs_bak[i].addr, regs_bak[i].value);
cke_fix_onoff(CKE_DYNAMIC, CHANNEL_A); dramc_cke_fix_onoff(CKE_DYNAMIC, CHANNEL_A);
cke_fix_onoff(CKE_DYNAMIC, CHANNEL_B); dramc_cke_fix_onoff(CKE_DYNAMIC, CHANNEL_B);
if (freq_group == LP4X_DDR3200 || freq_group == LP4X_DDR3600) { if (freq_group == LP4X_DDR3200 || freq_group == LP4X_DDR3600) {
setbits32(&ch[chn].phy.shu[0].pll[5], 0x1 << 0); 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)); (0x1 << 31) | (0xa << 21) | (0xa << 26));
setbits32(&ch[0].ao.ckectrl, 0x1 << 23); setbits32(&ch[0].ao.ckectrl, 0x1 << 23);
clrbits32(&ch[0].ao.shu[0].rodtenstb, 0x1 << 31); 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) 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++) for (size_t chn = 0; chn < CHANNEL_MAX; chn++)
clrbits32(&ch[chn].phy.misc_ctrl1, 0x1 << 13); clrbits32(&ch[chn].phy.misc_ctrl1, 0x1 << 13);
dramc_cke_fix_onoff(CHANNEL_A, false, true); dramc_cke_fix_onoff(CKE_FIXOFF, CHANNEL_A);
dramc_cke_fix_onoff(CHANNEL_B, false, true); dramc_cke_fix_onoff(CKE_FIXOFF, CHANNEL_B);
udelay(200); udelay(200);
for (size_t chn = 0; chn < CHANNEL_MAX; chn++) 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); setbits32(&ch[chn].ao.dramc_pd_ctrl, 0x1 << 26);
udelay(2000); udelay(2000);
dramc_cke_fix_onoff(CHANNEL_A, true, false); dramc_cke_fix_onoff(CKE_FIXON, CHANNEL_A);
dramc_cke_fix_onoff(CHANNEL_B, true, false); dramc_cke_fix_onoff(CKE_FIXON, CHANNEL_B);
udelay(2); udelay(2);
} }
@ -698,7 +706,7 @@ static u8 dramc_zq_calibration(u8 chn, u8 rank)
regs_bak[i].value = read32(regs_bak[i].addr); regs_bak[i].value = read32(regs_bak[i].addr);
setbits32(&ch[chn].ao.dramc_pd_ctrl, 0x1 << 26); 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.mrs, MRS_MRSRK, rank);
SET32_BITFIELDS(&ch[chn].ao.mpc_option, MPC_OPTION_MPCRKEN, 1); 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); setbits32(&ch[chn].ao.refctrl0, 0x1 << 29);
udelay(3); udelay(3);
cke_fix_onoff(CKE_FIXOFF, CHANNEL_A); dramc_cke_fix_onoff(CKE_FIXOFF, CHANNEL_A);
cke_fix_onoff(CKE_FIXOFF, CHANNEL_B); dramc_cke_fix_onoff(CKE_FIXOFF, CHANNEL_B);
dramc_set_broadcast(broadcast_bak); dramc_set_broadcast(broadcast_bak);
} }

View File

@ -8,6 +8,7 @@
#include <soc/dramc_register.h> #include <soc/dramc_register.h>
#include <soc/dramc_param.h> #include <soc/dramc_param.h>
#include <soc/dramc_pi_api.h> #include <soc/dramc_pi_api.h>
#include <soc/spm.h>
#include <timer.h> #include <timer.h>
enum { enum {
@ -72,6 +73,11 @@ struct per_byte_dly {
u16 final_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) static void dramc_auto_refresh_switch(u8 chn, bool option)
{ {
SET32_BITFIELDS(&ch[chn].ao.refctrl0, REFCTRL0_REFDIS, option ? 0 : 1); 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) static u16 dramc_mode_reg_read(u8 chn, u8 mr_idx)
{ {
u16 value; 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); 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_MRSMA, mr_idx);
SET32_BITFIELDS(&ch[chn].ao.mrs, MRS_MRSOP, value); SET32_BITFIELDS(&ch[chn].ao.mrs, MRS_MRSOP, value);
SET32_BITFIELDS(&ch[chn].ao.spcmd, SPCMD_MRWEN, 1); 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, static void cbt_set_perbit_delay_cell(u8 chn, u8 rank)
const struct sdram_params *params, const bool fast_calib)
{ {
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]; static void set_dram_mr_cbt_on_off(u8 chn, u8 rank, u8 fsp,
cmd_dly = params->cbt_cmd_dly[chn][rank]; u8 cbt_on, struct mr_value *mr)
cs_dly = params->cbt_cs_dly[chn][rank]; {
final_vref = params->cbt_final_vref[chn][rank]; u8 MR13Value = mr->MR13Value;
if (fast_calib) { if (cbt_on) {
/* Set CLK and CA delay */ MR13Value |= 0x1;
SET32_BITFIELDS(&ch[chn].phy.shu[0].rk[rank].ca_cmd[9], if (fsp == FSP_1)
SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD, cmd_dly, MR13Value &= 0x7f;
SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK, clk_dly); 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); udelay(1);
} }
/* Set CLK and CS delay */ static void cbt_entry(u8 chn, u8 rank, u8 fsp, struct mr_value *mr)
SET32_BITFIELDS(&ch[chn].phy.shu[0].rk[rank].ca_cmd[9], {
SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS, cs_dly); 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);
final_vref |= (1 << 6); 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 */ /* CBT set vref */
dramc_mode_reg_write_by_rank(chn, rank, 12, final_vref); dramc_mode_reg_write_by_rank(chn, rank, 12, vref);
dramc_dbg("final_vref: %#x\n", final_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[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]]);
}
}
static u8 get_cbt_vref_pinmux_value(u8 chn, u8 vref_level)
{
u8 vref_bit, vref_new, vref_org;
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);
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) 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.shu[shu].scintv, 0x1 << 30);
clrbits32(&ch[chn].ao.dummy_rd, (0x7 << 20) | (0x1 << 7)); 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.dramc_pd_ctrl, 0x1 << 26);
clrbits32(&ch[chn].ao.eyescan, 0x7 << 8); 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, SET32_BITFIELDS(&ch[chn].ao.dramc_pd_ctrl,
DRAMC_PD_CTRL_MIOCKCTRLOFF, 1); DRAMC_PD_CTRL_MIOCKCTRLOFF, 1);
dramc_cke_fix_onoff(chn, true, false); dramc_cke_fix_onoff(CKE_FIXON, chn);
start_dqsosc(chn); start_dqsosc(chn);
udelay(1); udelay(1);
@ -2757,8 +3043,8 @@ void get_dram_info_after_cal(u8 *density_result)
*density_result = max_density; *density_result = max_density;
} }
int dramc_calibrate_all_channels(const struct sdram_params *pams, u8 freq_group, int dramc_calibrate_all_channels(const struct sdram_params *pams,
const struct mr_value *mr) u8 freq_group, struct mr_value *mr)
{ {
bool fast_calib; bool fast_calib;
switch (pams->source) { 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", dramc_dbg("Start K: freq=%d, ch=%d, rank=%d\n",
freq_group, chn, rk); freq_group, chn, rk);
dramc_cmd_bus_training(chn, rk, freq_group, pams, 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_write_leveling(chn, rk, freq_group, pams->wr_level);
dramc_auto_refresh_switch(chn, true); dramc_auto_refresh_switch(chn, true);

View File

@ -157,7 +157,7 @@ static void set_rank_info_to_conf(const struct sdram_params *params)
(is_dual_rank ? 0 : 1) << 12); (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++) { for (size_t chn = 0; chn < CHANNEL_MAX; chn++) {
const u8 *map = phy_mapping[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) static void global_option_init(const struct sdram_params *params)
{ {
set_rank_info_to_conf(params); set_rank_info_to_conf(params);
set_MRR_pinmux_mapping(); set_mrr_pinmux_mapping();
} }
static void set_vcore_voltage(u8 freq_group) static void set_vcore_voltage(u8 freq_group)

View File

@ -29,6 +29,7 @@ enum dram_odt_type {
}; };
enum { enum {
CA_NUM_LP4 = 6,
DQ_DATA_WIDTH = 16, DQ_DATA_WIDTH = 16,
DQS_BIT_NUMBER = 8, DQS_BIT_NUMBER = 8,
DQS_NUMBER = (DQ_DATA_WIDTH / DQS_BIT_NUMBER) DQS_NUMBER = (DQ_DATA_WIDTH / DQS_BIT_NUMBER)

View File

@ -10,7 +10,7 @@
enum { enum {
DRAMC_PARAM_HEADER_MAGIC = 0x44524d4b, DRAMC_PARAM_HEADER_MAGIC = 0x44524d4b,
DRAMC_PARAM_HEADER_VERSION = 3, DRAMC_PARAM_HEADER_VERSION = 4,
}; };
enum DRAMC_PARAM_STATUS_CODES { enum DRAMC_PARAM_STATUS_CODES {

View File

@ -27,6 +27,7 @@
#define IMP_DRVN_LP4X_UNTERM_VREF_SEL 0x16 #define IMP_DRVN_LP4X_UNTERM_VREF_SEL 0x16
#define IMP_TRACK_LP4X_UNTERM_VREF_SEL 0x1a #define IMP_TRACK_LP4X_UNTERM_VREF_SEL 0x1a
#define MR23_DEFAULT_VALUE 0x3f #define MR23_DEFAULT_VALUE 0x3f
#define CA_TRAINING_NUM 10
enum dram_te_op { enum dram_te_op {
TE_OP_WRITE_READ_CHECK = 0, TE_OP_WRITE_READ_CHECK = 0,
@ -42,6 +43,17 @@ enum {
GATING_GOLDEND_DQSCNT = 0x4646 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 { enum {
IMPCAL_STAGE_DRVP = 0x1, IMPCAL_STAGE_DRVP = 0x1,
IMPCAL_STAGE_DRVN, 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_before_calibration(u8 freq_group);
void dramc_apply_config_after_calibration(const struct mr_value *mr); void dramc_apply_config_after_calibration(const struct mr_value *mr);
int dramc_calibrate_all_channels(const struct sdram_params *pams, 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_hw_gating_onoff(u8 chn, bool onoff);
void dramc_enable_phy_dcm(u8 chn, bool bEn); void dramc_enable_phy_dcm(u8 chn, bool bEn);
void dramc_mode_reg_write(u8 chn, u8 mr_idx, u8 value); 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); u32 get_shu_freq(u8 shu);
void dramc_hw_dqsosc(u8 chn); void dramc_hw_dqsosc(u8 chn);
void dramc_dqs_precalculation_preset(void); void dramc_dqs_precalculation_preset(void);
void get_dram_info_after_cal(u8 *density); 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 */ #endif /* _DRAMC_PI_API_MT8183_H */

View File

@ -623,8 +623,9 @@ DEFINE_BIT(DDRCONF0_DM4TO1MODE, 22)
DEFINE_BIT(DDRCONF0_RDATRST, 0) DEFINE_BIT(DDRCONF0_RDATRST, 0)
DEFINE_BIT(PERFCTL0_RWOFOEN, 4) DEFINE_BIT(PERFCTL0_RWOFOEN, 4)
DEFINE_BITFIELD(RKCFG_TXRANK, 1, 0)
DEFINE_BIT(RKCFG_TXRANKFIX, 3)
DEFINE_BIT(RKCFG_DQSOSC2RK, 11) DEFINE_BIT(RKCFG_DQSOSC2RK, 11)
DEFINE_BIT(DRAMC_PD_CTRL_MIOCKCTRLOFF, 26)
DEFINE_BIT(PADCTRL_DQIENLATEBEGIN, 3) DEFINE_BIT(PADCTRL_DQIENLATEBEGIN, 3)
DEFINE_BITFIELD(PADCTRL_DQIENQKEND, 1, 0) 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_CLK, 29, 24)
DEFINE_BITFIELD(SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD, 13, 8) 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) DEFINE_BITFIELD(SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS, 5, 0)
/* DRAMC_REG_ADDR(DRAMC_REG_PRE_TDQSCK1) */ /* 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_PIFREQ3_B3R0, 12, 6)
DEFINE_BITFIELD(RK0_PRE_TDQSCK11_TDQSCK_UIFREQ3_B3R0, 5, 0) 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 { struct dramc_channel_regs {
union { union {
struct dramc_ddrphy_ao_regs phy; struct dramc_ddrphy_ao_regs phy;

View File

@ -27,6 +27,7 @@ struct sdram_params {
u8 cbt_clk_dly[CHANNEL_MAX][RANK_MAX]; u8 cbt_clk_dly[CHANNEL_MAX][RANK_MAX];
u8 cbt_cmd_dly[CHANNEL_MAX][RANK_MAX]; u8 cbt_cmd_dly[CHANNEL_MAX][RANK_MAX];
u8 cbt_cs_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 */ /* Gating */
u8 gating2T[CHANNEL_MAX][RANK_MAX][DQS_NUMBER]; u8 gating2T[CHANNEL_MAX][RANK_MAX][DQS_NUMBER];