diff options
-rw-r--r-- | src/soc/mediatek/mt8192/dramc_pi_basic_api.c | 35 | ||||
-rw-r--r-- | src/soc/mediatek/mt8192/dramc_pi_main.c | 58 |
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; } } |