aboutsummaryrefslogtreecommitdiff
path: root/src/soc/mediatek/mt8192
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/mediatek/mt8192')
-rw-r--r--src/soc/mediatek/mt8192/dramc_pi_basic_api.c35
-rw-r--r--src/soc/mediatek/mt8192/dramc_pi_main.c58
2 files changed, 93 insertions, 0 deletions
diff --git a/src/soc/mediatek/mt8192/dramc_pi_basic_api.c b/src/soc/mediatek/mt8192/dramc_pi_basic_api.c
index e2ca919260..7f8d83a4d3 100644
--- a/src/soc/mediatek/mt8192/dramc_pi_basic_api.c
+++ b/src/soc/mediatek/mt8192/dramc_pi_basic_api.c
@@ -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)
{
diff --git a/src/soc/mediatek/mt8192/dramc_pi_main.c b/src/soc/mediatek/mt8192/dramc_pi_main.c
index fb8630503c..8eba016dd8 100644
--- a/src/soc/mediatek/mt8192/dramc_pi_main.c
+++ b/src/soc/mediatek/mt8192/dramc_pi_main.c
@@ -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;
}
}