soc/mediatek/mt8192: Get DDR base information after calibration
After calibration, we can get ddr vendor id or density info from MR5 or MR8, this helps to make sure the DDR HW is as we expected. Signed-off-by: Huayang Duan <huayang.duan@mediatek.com> Change-Id: Ie62948368716d309aab8149372b2b6093fc33552 Reviewed-on: https://review.coreboot.org/c/coreboot/+/44712 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Yu-Ping Wu <yupingso@google.com>
This commit is contained in:
parent
58ba83fe74
commit
c37b9aa9f0
|
@ -3833,6 +3833,41 @@ static void dramc_zq_calibration(const struct ddr_cali *cali, u8 chn, u8 rank)
|
|||
write32(regs_bak[i].addr, regs_bak[i].value);
|
||||
}
|
||||
|
||||
u8 dramc_mode_reg_read(u8 chn, u8 mr_idx)
|
||||
{
|
||||
const u32 timeout = 10000;
|
||||
u8 value;
|
||||
|
||||
SET32_BITFIELDS(&ch[chn].ao.swcmd_ctrl0, SWCMD_CTRL0_MRSMA, mr_idx);
|
||||
SET32_BITFIELDS(&ch[chn].ao.swcmd_en, SWCMD_EN_MRREN, 1);
|
||||
|
||||
/* Wait until MRW command fired */
|
||||
if (!wait_ms(timeout, READ32_BITFIELD(&ch[chn].nao.spcmdresp,
|
||||
SPCMDRESP_MRR_RESPONSE))) {
|
||||
dramc_err("Read mode register time out\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
value = READ32_BITFIELD(&ch[chn].nao.mrr_status, MRR_STATUS_MRR_SW_REG);
|
||||
SET32_BITFIELDS(&ch[chn].ao.swcmd_en, SWCMD_EN_MRREN, 0);
|
||||
dramc_dbg("Read MR%d = %#x\n", mr_idx, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
u8 dramc_mode_reg_read_by_rank(u8 chn, u8 rank, u8 mr_idx)
|
||||
{
|
||||
u8 value;
|
||||
u8 rank_bak;
|
||||
|
||||
rank_bak = READ32_BITFIELD(&ch[chn].ao.swcmd_ctrl0, SWCMD_CTRL0_MRSRK);
|
||||
SET32_BITFIELDS(&ch[chn].ao.swcmd_ctrl0, SWCMD_CTRL0_MRSRK, rank);
|
||||
value = dramc_mode_reg_read(chn, mr_idx);
|
||||
SET32_BITFIELDS(&ch[chn].ao.swcmd_ctrl0, SWCMD_CTRL0_MRSRK, rank_bak);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void dramc_mode_reg_write_by_rank(const struct ddr_cali *cali,
|
||||
u8 chn, u8 rank, u8 mr_idx, u8 value)
|
||||
{
|
||||
|
|
|
@ -14,6 +14,60 @@ static void set_vcore_voltage(const struct ddr_cali *cali)
|
|||
mainboard_set_regulator_vol(MTK_REGULATOR_VCORE, vcore);
|
||||
}
|
||||
|
||||
static void get_dram_info_after_cal(struct ddr_cali *cali)
|
||||
{
|
||||
u8 vendor_id, density, max_density = 0;
|
||||
u32 size_gb, max_size = 0;
|
||||
|
||||
vendor_id = dramc_mode_reg_read_by_rank(CHANNEL_A, RANK_0, 5) & 0xff;
|
||||
dramc_info("Vendor id is %#x\n", vendor_id);
|
||||
|
||||
for (u8 rk = RANK_0; rk < cali->support_ranks; rk++) {
|
||||
density = dramc_mode_reg_read_by_rank(CHANNEL_A, rk, 8) & 0xff;
|
||||
dramc_dbg("MR8 %#x\n", density);
|
||||
density = (density >> 2) & 0xf;
|
||||
|
||||
switch (density) {
|
||||
/* these case values are from JESD209-4C MR8 Density OP[5:2] */
|
||||
case 0x0:
|
||||
size_gb = 4;
|
||||
break;
|
||||
case 0x1:
|
||||
size_gb = 6;
|
||||
break;
|
||||
case 0x2:
|
||||
size_gb = 8;
|
||||
break;
|
||||
case 0x3:
|
||||
size_gb = 12;
|
||||
break;
|
||||
case 0x4:
|
||||
size_gb = 16;
|
||||
break;
|
||||
case 0x5:
|
||||
size_gb = 24;
|
||||
break;
|
||||
case 0x6:
|
||||
size_gb = 32;
|
||||
break;
|
||||
case 0xC:
|
||||
size_gb = 2;
|
||||
break;
|
||||
default:
|
||||
dramc_err("Unexpected mode register density value: %#x\n", density);
|
||||
size_gb = 0;
|
||||
break;
|
||||
}
|
||||
if (size_gb > max_size) {
|
||||
max_size = size_gb;
|
||||
max_density = density;
|
||||
}
|
||||
dramc_dbg("RK%u size %uGb, density:%u\n", rk, size_gb, max_density);
|
||||
}
|
||||
|
||||
cali->density = max_density;
|
||||
}
|
||||
|
||||
static void dramc_calibration_all_channels(struct ddr_cali *cali)
|
||||
{
|
||||
}
|
||||
|
@ -82,6 +136,10 @@ void init_dram(const struct dramc_data *dparam)
|
|||
|
||||
dramc_calibration_all_channels(&cali);
|
||||
|
||||
/* only need to do once to get DDR's base information */
|
||||
if (first_freq_k)
|
||||
get_dram_info_after_cal(&cali);
|
||||
|
||||
first_freq_k = false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue