soc/mediatek/mt8192: Do dramc software impedance calibration
Signed-off-by: Huayang Duan <huayang.duan@mediatek.com> Change-Id: I2c6ffe885717997540a0a9721310e355a3b6a87d Reviewed-on: https://review.coreboot.org/c/coreboot/+/44704 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Yu-Ping Wu <yupingso@google.com>
This commit is contained in:
parent
cc064c6c93
commit
e05298b1d2
|
@ -25,7 +25,7 @@ verstage-y += ../common/uart.c
|
|||
|
||||
romstage-y += ../common/auxadc.c
|
||||
romstage-y += ../common/cbmem.c
|
||||
romstage-y += dramc_pi_main.c dramc_pi_basic_api.c dramc_utility.c
|
||||
romstage-y += dramc_pi_main.c dramc_pi_basic_api.c dramc_pi_calibration_api.c dramc_utility.c
|
||||
romstage-y += emi.c
|
||||
romstage-y += flash_controller.c
|
||||
romstage-y += ../common/gpio.c gpio.c
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <soc/dramc_pi_api.h>
|
||||
#include <soc/dramc_register.h>
|
||||
|
||||
static const u8 imp_vref_sel[ODT_MAX][IMP_DRV_MAX] = {
|
||||
/* DRVP DRVN ODTP ODTN */
|
||||
[ODT_OFF] = {0x37, 0x33, 0x00, 0x37},
|
||||
[ODT_ON] = {0x3a, 0x33, 0x00, 0x3a},
|
||||
};
|
||||
|
||||
static void dramc_imp_cal_vref_sel(dram_odt_state odt, imp_drv_type drv_type)
|
||||
{
|
||||
u8 vref_tmp = imp_vref_sel[odt][drv_type];
|
||||
|
||||
switch (drv_type) {
|
||||
case DRVP:
|
||||
SET32_BITFIELDS(&ch[0].phy_ao.shu_ca_cmd12,
|
||||
SHU_CA_CMD12_RG_RIMP_VREF_SEL_DRVP, vref_tmp);
|
||||
break;
|
||||
case DRVN:
|
||||
SET32_BITFIELDS(&ch[0].phy_ao.shu_ca_cmd12,
|
||||
SHU_CA_CMD12_RG_RIMP_VREF_SEL_DRVN, vref_tmp);
|
||||
break;
|
||||
case ODTN:
|
||||
SET32_BITFIELDS(&ch[0].phy_ao.shu_ca_cmd12,
|
||||
SHU_CA_CMD12_RG_RIMP_VREF_SEL_ODTN, vref_tmp);
|
||||
break;
|
||||
default:
|
||||
die("Can't support drv_type %d\n", drv_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 dramc_sw_imp_cal_result(imp_drv_type drv_type)
|
||||
{
|
||||
u32 drive = 0, cal_res = 0;
|
||||
u32 change = (drv_type == DRVP) ? 1 : 0;
|
||||
|
||||
static const char *const drv_type_str[IMP_DRV_MAX] = {
|
||||
[DRVP] = "DRVP",
|
||||
[DRVN] = "DRVN",
|
||||
[ODTP] = "ODTP",
|
||||
[ODTN] = "ODTN",
|
||||
};
|
||||
if (drv_type >= IMP_DRV_MAX)
|
||||
die("Can't support drv_type %d", drv_type);
|
||||
|
||||
const char *drv_str = drv_type_str[drv_type];
|
||||
|
||||
for (drive = 0; drive < 32; drive++) {
|
||||
if (drv_type == DRVP)
|
||||
SET32_BITFIELDS(&ch[0].phy_ao.shu_misc_impcal1,
|
||||
SHU_MISC_IMPCAL1_IMPDRVP, drive);
|
||||
else if (drv_type == DRVN || drv_type == ODTN)
|
||||
SET32_BITFIELDS(&ch[0].phy_ao.shu_misc_impcal1,
|
||||
SHU_MISC_IMPCAL1_IMPDRVN, drive);
|
||||
|
||||
udelay(1);
|
||||
cal_res = READ32_BITFIELD(&ch[0].phy_nao.misc_phy_rgs_cmd,
|
||||
MISC_PHY_RGS_CMD_RGS_RIMPCALOUT);
|
||||
dramc_dbg("OCD %s=%d ,CALOUT=%d\n", drv_str, drive, cal_res);
|
||||
|
||||
if (cal_res == change) {
|
||||
dramc_info("%s calibration passed! result=%d\n", drv_str, drive);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (drive == 32) {
|
||||
drive = 31;
|
||||
dramc_err("OCD %s calibration failed! %s=%d\n", drv_str, drv_str, drive);
|
||||
}
|
||||
|
||||
return drive;
|
||||
}
|
||||
|
||||
void dramc_sw_impedance_cal(dram_odt_state odt, struct dram_impedance *imp)
|
||||
{
|
||||
const u8 chn = 0;
|
||||
u8 i_chn, enp, enn;
|
||||
u32 bc_bak, impcal_bak, cal_res;
|
||||
u32 drvp_result = 0xff, odtn_result = 0xff, drvn_result = 0xff;
|
||||
|
||||
bc_bak = dramc_get_broadcast();
|
||||
dramc_set_broadcast(DRAMC_BROADCAST_OFF);
|
||||
for (i_chn = 0; i_chn < CHANNEL_MAX; i_chn++) {
|
||||
SET32_BITFIELDS(&ch[i_chn].phy_ao.misc_lp_ctrl,
|
||||
MISC_LP_CTRL_RG_ARDMSUS_10, 0x0,
|
||||
MISC_LP_CTRL_RG_ARDMSUS_10_LP_SEL, 0x0,
|
||||
MISC_LP_CTRL_RG_RIMP_DMSUS_10, 0x0,
|
||||
MISC_LP_CTRL_RG_RIMP_DMSUS_10_LP_SEL, 0x0);
|
||||
SET32_BITFIELDS(&ch[i_chn].phy_ao.misc_impcal, MISC_IMPCAL_IMPCAL_HW, 0);
|
||||
}
|
||||
|
||||
impcal_bak = read32(&ch[chn].phy_ao.misc_impcal);
|
||||
SET32_BITFIELDS(&ch[chn].phy_ao.misc_imp_ctrl1, MISC_IMP_CTRL1_RG_RIMP_PRE_EN, 0);
|
||||
SET32_BITFIELDS(&ch[chn].phy_ao.misc_impcal,
|
||||
MISC_IMPCAL_IMPCAL_CALI_ENN, 0,
|
||||
MISC_IMPCAL_IMPCAL_IMPPDP, 1,
|
||||
MISC_IMPCAL_IMPCAL_IMPPDN, 1);
|
||||
SET32_BITFIELDS(&ch[chn].phy_ao.misc_imp_ctrl1,
|
||||
MISC_IMP_CTRL1_RG_IMP_EN, 1,
|
||||
MISC_IMP_CTRL1_RG_RIMP_DDR3_SEL, 0,
|
||||
MISC_IMP_CTRL1_RG_RIMP_VREF_EN, 1,
|
||||
MISC_IMP_CTRL1_RG_RIMP_DDR4_SEL, 1);
|
||||
udelay(1);
|
||||
SET32_BITFIELDS(&ch[chn].phy_ao.misc_impcal, MISC_IMPCAL_IMPCAL_CALI_EN, 1);
|
||||
SET32_BITFIELDS(&ch[chn].phy_ao.shu_misc_impcal1,
|
||||
SHU_MISC_IMPCAL1_IMPDRVN, 0,
|
||||
SHU_MISC_IMPCAL1_IMPDRVP, 0);
|
||||
|
||||
for (imp_drv_type drv_type = DRVP; drv_type < IMP_DRV_MAX; drv_type++) {
|
||||
if (drv_type == ODTP)
|
||||
continue;
|
||||
dramc_imp_cal_vref_sel(odt, drv_type);
|
||||
|
||||
switch (drv_type) {
|
||||
case DRVP:
|
||||
enp = 0x1;
|
||||
enn = 0x0;
|
||||
drvp_result = 0;
|
||||
break;
|
||||
case DRVN:
|
||||
case ODTN:
|
||||
enp = 0x0;
|
||||
enn = (drv_type == DRVN) ? 0x0 : 0x1;
|
||||
break;
|
||||
default:
|
||||
die("Can't support drv_type %d\n", drv_type);
|
||||
break;
|
||||
}
|
||||
|
||||
SET32_BITFIELDS(&ch[chn].phy_ao.misc_impcal,
|
||||
MISC_IMPCAL_IMPCAL_CALI_ENP, enp);
|
||||
SET32_BITFIELDS(&ch[chn].phy_ao.misc_impcal,
|
||||
MISC_IMPCAL_IMPCAL_CALI_ENN, enn);
|
||||
SET32_BITFIELDS(&ch[chn].phy_ao.shu_misc_impcal1,
|
||||
SHU_MISC_IMPCAL1_IMPDRVP, drvp_result);
|
||||
SET32_BITFIELDS(&ch[chn].phy_ao.shu_ca_cmd12,
|
||||
SHU_CA_CMD12_RG_RIMP_DRV05, 0);
|
||||
|
||||
cal_res = dramc_sw_imp_cal_result(drv_type);
|
||||
switch (drv_type) {
|
||||
case DRVP:
|
||||
drvp_result = cal_res;
|
||||
break;
|
||||
case DRVN:
|
||||
drvn_result = cal_res;
|
||||
break;
|
||||
case ODTN:
|
||||
odtn_result = cal_res;
|
||||
break;
|
||||
default:
|
||||
die("Can't support drv_type %d\n", drv_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
imp->result[odt][DRVP] = drvp_result;
|
||||
imp->result[odt][DRVN] = drvn_result;
|
||||
imp->result[odt][ODTP] = 0;
|
||||
imp->result[odt][ODTN] = odtn_result;
|
||||
|
||||
dramc_info("freq_region=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d\n",
|
||||
odt, drvp_result, drvn_result, odtn_result);
|
||||
|
||||
write32(&ch[chn].phy_ao.misc_impcal, impcal_bak);
|
||||
dramc_set_broadcast(bc_bak);
|
||||
}
|
|
@ -64,6 +64,9 @@ void init_dram(const struct dramc_data *dparam)
|
|||
emi_mdl_init(cali.emi_config);
|
||||
dramc_set_broadcast(bc_bak);
|
||||
|
||||
dramc_sw_impedance_cal(ODT_OFF, &cali.impedance);
|
||||
dramc_sw_impedance_cal(ODT_ON, &cali.impedance);
|
||||
|
||||
if (ddr_info->config_dvfs == DRAMC_ENABLE_DVFS)
|
||||
k_shuffle_end = CALI_SEQ_MAX;
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue