Duan Huayang has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/41949 )
Change subject: soc/mediatek/mt8183: Support 6GB, 8GB DDR bootup ......................................................................
soc/mediatek/mt8183: Support 6GB, 8GB DDR bootup
Current the DRAM control only support 4GB DDR, add more large size DDR support to meet the market requirement.
BUG=none BRANCH=kukui TEST=Boots correctly on Kukui
Change-Id: I1fdf50b75c6a552c0a889f21e1a81ab4b9a305fa Signed-off-by: Huayang Duan huayang.duan@mediatek.com --- M src/mainboard/google/kukui/sdram_configs.c M src/soc/mediatek/mt8183/dramc_param.c M src/soc/mediatek/mt8183/dramc_pi_calibration_api.c M src/soc/mediatek/mt8183/emi.c M src/soc/mediatek/mt8183/include/soc/dramc_param.h M src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h M src/soc/mediatek/mt8183/include/soc/emi.h 7 files changed, 175 insertions(+), 23 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/49/41949/1
diff --git a/src/mainboard/google/kukui/sdram_configs.c b/src/mainboard/google/kukui/sdram_configs.c index 73bd2f8..649ab10 100644 --- a/src/mainboard/google/kukui/sdram_configs.c +++ b/src/mainboard/google/kukui/sdram_configs.c @@ -30,3 +30,8 @@
return ¶ms; } + +u32 get_rom_code(void) +{ + return ram_code(); +} diff --git a/src/soc/mediatek/mt8183/dramc_param.c b/src/soc/mediatek/mt8183/dramc_param.c index 54d2209..546ad3a 100644 --- a/src/soc/mediatek/mt8183/dramc_param.c +++ b/src/soc/mediatek/mt8183/dramc_param.c @@ -31,12 +31,37 @@ return validate_dramc_param(blob) == DRAMC_SUCCESS; }
+static void set_ddr_size_type(struct dramc_param *param) +{ + u32 ramcode = get_rom_code(); + u16 ddr_size_type = DDR_TYPE_2CH_2RK_4GB_2_2; + + switch (ramcode) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + ddr_size_type = DDR_TYPE_2CH_2RK_4GB_2_2; + break; + default: + break; + } + + param->header.ddr_size_type = ddr_size_type; +} + int initialize_dramc_param(void *blob, u16 config) { struct dramc_param *param = blob; struct dramc_param_header *hdr = ¶m->header;
memset(blob, 0, sizeof(*param)); + + set_ddr_size_type(param); hdr->magic = DRAMC_PARAM_HEADER_MAGIC; hdr->size = sizeof(*param); hdr->version = DRAMC_PARAM_HEADER_VERSION; diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c index b557550..6d5db3a 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -131,6 +131,19 @@ dramc_dbg("Write MR%d =0x%x\n", mr_idx, value); }
+static u16 dramc_mode_reg_read_by_rank(u8 chn, u8 rank, u8 mr_idx) +{ + u8 value; + u32 rk_bak = READ32_BITFIELD(&ch[chn].ao.mrs, MRS_MRRRK); + + SET32_BITFIELDS(&ch[chn].ao.mrs, MRS_MRRRK, rank); + value = dramc_mode_reg_read(chn, mr_idx); + SET32_BITFIELDS(&ch[chn].ao.mrs, MRS_MRRRK, rk_bak); + + dramc_dbg("Mode reg read rank%d MR%d = %#x\n", rank, mr_idx, value); + return value; +} + static void dramc_mode_reg_write_by_rank(u8 chn, u8 rank, u8 mr_idx, u8 value) { @@ -2678,6 +2691,54 @@ } }
+u8 get_dram_infor_after_cal(void) +{ + u8 vendor_id, density, max_density = 0; + u64 dram_size, max_size = 0; + + vendor_id = dramc_mode_reg_read_by_rank(CHANNEL_A, RANK_0, 5) & 0xff; + dramc_show("Vendor id is %#x\n", vendor_id); + + for (u8 rk = RANK_0; rk < RANK_MAX; 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) { + case 0x0: + dram_size = 0x20000000; + break; + case 0x1: + dram_size = 0x30000000; + break; + case 0x2: + dram_size = 0x40000000; + break; + case 0x3: + dram_size = 0x60000000; + break; + case 0x4: + dram_size = 0x80000000; + break; + case 0x5: + dram_size = 0xc0000000; + break; + case 0x6: + dram_size = 0x100000000L; + break; + default: + dram_size = 0; + } + if (dram_size > max_size) { + max_size = dram_size; + max_density = density; + } + dramc_show("RK%d size %dGb, density:%d\n", rk, (u32)(dram_size >> 27), max_density); + } + + return max_density; +} + int dramc_calibrate_all_channels(const struct sdram_params *pams, u8 freq_group, const struct mr_value *mr) { diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c index c03f945..6a465e3 100644 --- a/src/soc/mediatek/mt8183/emi.c +++ b/src/soc/mediatek/mt8183/emi.c @@ -50,10 +50,10 @@ };
struct optimize_ac_time { - u8 rfc; - u8 rfc_05t; - u8 rfc_pb; - u8 rfrc_pb05t; + u8 trfc; + u8 trfrc_05t; + u8 trfc_pb; + u8 trfrc_pb_05t; u16 tx_ref_cnt; };
@@ -320,30 +320,79 @@ setbits32(&ch[0].phy.misc_ctrl1, 0x1 << 31); }
-static void dramc_ac_timing_optimize(u8 freq_group) +static void dramc_ac_timing_optimize(u8 freq_group, u8 density) { - struct optimize_ac_time rf_cab_opt[LP4X_DDRFREQ_MAX] = { - [LP4X_DDR1600] = {.rfc = 44, .rfc_05t = 0, .rfc_pb = 16, - .rfrc_pb05t = 0, .tx_ref_cnt = 62}, - [LP4X_DDR2400] = {.rfc = 72, .rfc_05t = 0, .rfc_pb = 30, - .rfrc_pb05t = 0, .tx_ref_cnt = 91}, - [LP4X_DDR3200] = {.rfc = 100, .rfc_05t = 0, .rfc_pb = 44, - .rfrc_pb05t = 0, .tx_ref_cnt = 119}, - [LP4X_DDR3600] = {.rfc = 118, .rfc_05t = 1, .rfc_pb = 53, - .rfrc_pb05t = 1, .tx_ref_cnt = 138}, + u8 rfcab_grp = 0; + u8 trfc = 101, trfrc_05t = 0, trfc_pb = 44, trfrc_pb_05t = 0, tx_ref_cnt = 118; + enum tRFCAB{tRFCAB_130 = 0, tRFCAB_180, tRFCAB_280, tRFCAB_380, tRFCAB_NUM}; + + struct optimize_ac_time rf_cab_opt[LP4X_DDRFREQ_MAX][tRFCAB_NUM] = { + /* LP4X_DDR1600 */ + {{.trfc = 14, .trfrc_05t = 0, .trfc_pb = 0, .trfrc_pb_05t = 0, .tx_ref_cnt = 32}, + {.trfc = 24, .trfrc_05t = 0, .trfc_pb = 6, .trfrc_pb_05t = 0, .tx_ref_cnt = 42}, + {.trfc = 44, .trfrc_05t = 0, .trfc_pb = 16, .trfrc_pb_05t = 0, .tx_ref_cnt = 62}, + {.trfc = 64, .trfrc_05t = 0, .trfc_pb = 26, .trfrc_pb_05t = 0, .tx_ref_cnt = 82}}, + /* LP4X_DDR2400 */ + {{.trfc = 27, .trfrc_05t = 0, .trfc_pb = 6, .trfrc_pb_05t = 0, .tx_ref_cnt = 46}, + {.trfc = 42, .trfrc_05t = 0, .trfc_pb = 15, .trfrc_pb_05t = 0, .tx_ref_cnt = 61}, + {.trfc = 72, .trfrc_05t = 0, .trfc_pb = 30, .trfrc_pb_05t = 0, .tx_ref_cnt = 91}, + {.trfc = 102, .trfrc_05t = 0, .trfc_pb = 45, .trfrc_pb_05t = 0, .tx_ref_cnt = 121}}, + /* LP4X_DDR3200 */ + {{.trfc = 40, .trfrc_05t = 0, .trfc_pb = 12, .trfrc_pb_05t = 0, .tx_ref_cnt = 59}, + {.trfc = 60, .trfrc_05t = 0, .trfc_pb = 24, .trfrc_pb_05t = 0, .tx_ref_cnt = 79}, + {.trfc = 100, .trfrc_05t = 0, .trfc_pb = 44, .trfrc_pb_05t = 0, .tx_ref_cnt = 119}, + {.trfc = 140, .trfrc_05t = 0, .trfc_pb = 64, .trfrc_pb_05t = 0, .tx_ref_cnt = 159}}, + /* LP4X_DDR3600 */ + {{.trfc = 48, .trfrc_05t = 1, .trfc_pb = 16, .trfrc_pb_05t = 0, .tx_ref_cnt = 68}, + {.trfc = 72, .trfrc_05t = 0, .trfc_pb = 30, .trfrc_pb_05t = 0, .tx_ref_cnt = 92}, + {.trfc = 118, .trfrc_05t = 1, .trfc_pb = 53, .trfrc_pb_05t = 1, .tx_ref_cnt = 138}, + {.trfc = 165, .trfrc_05t = 0, .trfc_pb = 76, .trfrc_pb_05t = 1, .tx_ref_cnt = 185}}, };
+ switch (density) { + /* 4Gb per die (2Gb per channel) */ + case 0x0: + rfcab_grp = tRFCAB_130; + break; + /* 6Gb per die (3Gb per channel) or 8Gb per die (4Gb per channel) */ + case 0x1: + case 0x2: + rfcab_grp = tRFCAB_180; + break; + /* 12Gb per die (6Gb per channel) or 16Gb per die (8Gb per channel) */ + case 0x3: + case 0x4: + rfcab_grp = tRFCAB_280; + break; + /* 24Gb per die (12Gb per channel) or 32Gb per die (16Gb per channel) */ + case 0x5: + case 0x6: + rfcab_grp = tRFCAB_380; + break; + default: + dramc_dbg("density err!\n"); + break; + } + + trfc = rf_cab_opt[freq_group][rfcab_grp].trfc; + trfrc_05t = rf_cab_opt[freq_group][rfcab_grp].trfrc_05t; + trfc_pb = rf_cab_opt[freq_group][rfcab_grp].trfc_pb; + trfrc_pb_05t = rf_cab_opt[freq_group][rfcab_grp].trfrc_pb_05t; + tx_ref_cnt = rf_cab_opt[freq_group][rfcab_grp].tx_ref_cnt; + dramc_dbg("Density %d, trfc %u, trfrc_05t %d, tx_ref_cnt %d, trfc_pb %d, trfrc_pb_05t %d\n", + density, trfc, trfrc_05t, tx_ref_cnt, trfc_pb, trfrc_pb_05t); + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { clrsetbits32(&ch[chn].ao.shu[0].actim[3], - 0xff << 16, rf_cab_opt[freq_group].rfc << 16); + 0xff << 16, trfc << 16); clrsetbits32(&ch[chn].ao.shu[0].ac_time_05t, - 0x1 << 2, rf_cab_opt[freq_group].rfc_05t << 2); + 0x1 << 2, trfrc_05t << 2); clrsetbits32(&ch[chn].ao.shu[0].actim[4], - 0x3ff << 0, rf_cab_opt[freq_group].tx_ref_cnt << 0); + 0x3ff << 0, tx_ref_cnt << 0); clrsetbits32(&ch[chn].ao.shu[0].actim[3], - 0xff << 0, rf_cab_opt[freq_group].rfc_pb << 0); + 0xff << 0, trfc_pb << 0); clrsetbits32(&ch[chn].ao.shu[0].ac_time_05t, - 0x1 << 1, rf_cab_opt[freq_group].rfrc_pb05t << 1); + 0x1 << 1, trfrc_pb_05t << 1); } }
@@ -495,6 +544,7 @@ struct dram_shared_data *shared, const int shuffle, bool *first_run) { + u8 density = 0; const u8 *freq_tbl;
if (CONFIG(MT8183_DRAM_EMCP)) @@ -519,7 +569,9 @@ dramc_dbg("Start K (current clock: %u\n", params->frequency); if (dramc_calibrate_all_channels(params, freq_group, &shared->mr) != 0) return -1; - dramc_ac_timing_optimize(freq_group); + + density = get_dram_infor_after_cal(); + dramc_ac_timing_optimize(freq_group, density); dramc_dbg("K finished (current clock: %u\n", params->frequency);
dramc_save_result_to_shuffle(DRAM_DFS_SHUFFLE_1, shuffle); diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_param.h b/src/soc/mediatek/mt8183/include/soc/dramc_param.h index 7b3ba7e..8cadb28 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_param.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_param.h @@ -11,7 +11,7 @@
enum { DRAMC_PARAM_HEADER_MAGIC = 0x44524d4b, - DRAMC_PARAM_HEADER_VERSION = 2, + DRAMC_PARAM_HEADER_VERSION = 3, };
enum DRAMC_PARAM_STATUS_CODES { @@ -38,11 +38,18 @@ DRAMC_FLAG_HAS_SAVED_DATA = 0x0001, };
+enum DRAMC_PARAM_DDR_SIZE_TYPE { + DDR_TYPE_2CH_2RK_4GB_2_2, + DDR_TYPE_2CH_2RK_6GB_3_3, + DDR_TYPE_2CH_2RK_8GB_4_4, +}; + struct dramc_param_header { u32 status; /* DRAMC_PARAM_STATUS_CODES */ u32 magic; - u32 version; - u32 size; /* size of whole dramc_param */ + u32 version; /* DRAMC_PARAM_HEADER_VERSION */ + u32 size; /* size of whole dramc_param */ + u16 ddr_size_type; /* DRAMC_PARAM_DDR_SIZE_TYPE */ u16 config; /* DRAMC_PARAM_CONFIG */ u16 flags; /* DRAMC_PARAM_FLAGS */ u32 checksum; diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h index 0de86f6..6aa8f0b 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h @@ -107,5 +107,6 @@ u32 get_shu_freq(u8 shu); void dramc_hw_dqsosc(u8 chn); void dramc_dqs_precalculation_preset(void); +u8 get_dram_infor_after_cal(void);
#endif /* _DRAMC_PI_API_MT8183_H */ diff --git a/src/soc/mediatek/mt8183/include/soc/emi.h b/src/soc/mediatek/mt8183/include/soc/emi.h index 3862d54..46921fe 100644 --- a/src/soc/mediatek/mt8183/include/soc/emi.h +++ b/src/soc/mediatek/mt8183/include/soc/emi.h @@ -86,6 +86,7 @@
extern const u8 phy_mapping[CHANNEL_MAX][16];
+u32 get_rom_code(void); int complex_mem_test(u8 *start, unsigned int len); size_t sdram_size(void); const struct sdram_params *get_sdram_config(void);