diff --git a/src/soc/mediatek/common/Kconfig b/src/soc/mediatek/common/Kconfig index 7d1e4554bc..27f6cec125 100644 --- a/src/soc/mediatek/common/Kconfig +++ b/src/soc/mediatek/common/Kconfig @@ -22,6 +22,13 @@ config MEDIATEK_DRAM_DVFS_LIMIT_FREQ_CNT This options limit DRAM frequency calibration count from total 7 to 3, other frequency will directly use the low frequency shu result. +config MEDIATEK_BLOB_FAST_INIT + bool "Enable running fast calibration by blob" + default n + help + This option allows performing fast calibration through different + open-source policy. + config MEMORY_TEST bool default y diff --git a/src/soc/mediatek/common/memory.c b/src/soc/mediatek/common/memory.c index 1b18dc7210..3ca36117e9 100644 --- a/src/soc/mediatek/common/memory.c +++ b/src/soc/mediatek/common/memory.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -95,31 +96,11 @@ const char *get_dram_type_str(u32 ddr_type) return s; } -static int dram_run_fast_calibration(struct dramc_param *dparam) -{ - const u16 config = CONFIG(MEDIATEK_DRAM_DVFS) ? DRAMC_ENABLE_DVFS : DRAMC_DISABLE_DVFS; - if (dparam->dramc_datas.ddr_info.config_dvfs != config) { - printk(BIOS_WARNING, - "DRAM-K: Incompatible config for calibration data from flash " - "(expected: %#x, saved: %#x)\n", - config, dparam->dramc_datas.ddr_info.config_dvfs); - return -1; - } - - printk(BIOS_INFO, "DRAM-K: DRAM calibration data valid pass\n"); - init_dram_by_params(dparam); - if (mt_mem_test(&dparam->dramc_datas) == 0) - return 0; - - return DRAMC_ERR_FAST_CALIBRATION; -} - -static int dram_run_full_calibration(struct dramc_param *dparam) +static int run_dram_blob(struct dramc_param *dparam) { /* Load and run the provided blob for full-calibration if available */ struct prog dram = PROG_INIT(PROG_REFCODE, CONFIG_CBFS_PREFIX "/dram"); - initialize_dramc_param(dparam); dump_param_header(dparam); if (cbfs_prog_stage_load(&dram)) { @@ -132,12 +113,13 @@ static int dram_run_full_calibration(struct dramc_param *dparam) prog_set_entry(&dram, prog_entry(&dram), dparam); prog_run(&dram); if (dparam->header.status != DRAMC_SUCCESS) { - printk(BIOS_ERR, "DRAM-K: Full calibration failed: status = %d\n", + printk(BIOS_ERR, "DRAM-K: calibration failed: status = %d\n", dparam->header.status); return -3; } - if (!(dparam->header.flags & DRAMC_FLAG_HAS_SAVED_DATA)) { + if (!(dparam->header.config & DRAMC_CONFIG_FAST_K) + && !(dparam->header.flags & DRAMC_FLAG_HAS_SAVED_DATA)) { printk(BIOS_ERR, "DRAM-K: Full calibration executed without saving parameters. " "Please ensure the blob is built properly.\n"); @@ -147,6 +129,49 @@ static int dram_run_full_calibration(struct dramc_param *dparam) return 0; } +static int dram_run_fast_calibration(struct dramc_param *dparam) +{ + const u16 config = CONFIG(MEDIATEK_DRAM_DVFS) ? DRAMC_ENABLE_DVFS : DRAMC_DISABLE_DVFS; + + if (dparam->dramc_datas.ddr_info.config_dvfs != config) { + printk(BIOS_WARNING, + "DRAM-K: Incompatible config for calibration data from flash " + "(expected: %#x, saved: %#x)\n", + config, dparam->dramc_datas.ddr_info.config_dvfs); + return -1; + } + + printk(BIOS_INFO, "DRAM-K: DRAM calibration data valid pass\n"); + + if (CONFIG(MEDIATEK_BLOB_FAST_INIT)) { + printk(BIOS_INFO, "DRAM-K: Run fast calibration run in blob mode\n"); + + /* + * The loaded config should not contain FAST_K (done in full calibration), + * so we have to set that now to indicate the blob taking the config instead + * of generating a new config. + */ + dparam->header.config |= DRAMC_CONFIG_FAST_K; + + if (run_dram_blob(dparam) < 0) + return -3; + } else { + init_dram_by_params(dparam); + } + + if (mt_mem_test(&dparam->dramc_datas) < 0) + return -4; + + return 0; +} + +static int dram_run_full_calibration(struct dramc_param *dparam) +{ + initialize_dramc_param(dparam); + + return run_dram_blob(dparam); +} + static void mem_init_set_default_config(struct dramc_param *dparam, const struct sdram_info *dram_info) { diff --git a/src/soc/mediatek/mt8186/Kconfig b/src/soc/mediatek/mt8186/Kconfig index 11a18f2e10..654baf20d0 100644 --- a/src/soc/mediatek/mt8186/Kconfig +++ b/src/soc/mediatek/mt8186/Kconfig @@ -9,6 +9,7 @@ config SOC_MEDIATEK_MT8186 select CACHE_MRC_SETTINGS select HAVE_UART_SPECIAL select SOC_MEDIATEK_COMMON + select MEDIATEK_BLOB_FAST_INIT if SOC_MEDIATEK_MT8186 diff --git a/src/soc/mediatek/mt8186/include/soc/dramc_param.h b/src/soc/mediatek/mt8186/include/soc/dramc_param.h index 5559b0a914..b5c019fbff 100644 --- a/src/soc/mediatek/mt8186/include/soc/dramc_param.h +++ b/src/soc/mediatek/mt8186/include/soc/dramc_param.h @@ -59,48 +59,53 @@ struct sdram_info { }; struct sdram_params { + /* Sometimes, we may need to compare params member + * between coreboot and blob for analysis. Here, + * add member size using xxxB. + */ + /* 4 + 4 = 8B */ u32 rank_num; u16 num_dlycell_perT; u16 delay_cell_timex100; - /* duty */ + /* duty 16B */ s8 duty_clk_delay[CHANNEL_MAX][RANK_MAX]; s8 duty_dqs_delay[CHANNEL_MAX][DQS_NUMBER_LP4]; - s8 duty_wck_delay[CHANNEL_MAX][DQS_NUMBER_LP4]; s8 duty_dq_delay[CHANNEL_MAX][DQS_NUMBER_LP4]; s8 duty_dqm_delay[CHANNEL_MAX][DQS_NUMBER_LP4]; - /* CBT */ + /* CBT 48B */ u8 cbt_final_vref[CHANNEL_MAX][RANK_MAX]; - s8 cbt_cmd_dly[CHANNEL_MAX][RANK_MAX]; + u8 cbt_clk_dly[CHANNEL_MAX][RANK_MAX]; + u8 cbt_cmd_dly[CHANNEL_MAX][RANK_MAX]; u8 cbt_cs_dly[CHANNEL_MAX][RANK_MAX]; u8 cbt_ca_prebit_dly[CHANNEL_MAX][RANK_MAX][DQS_BIT_NUMBER]; - /* write leveling */ + /* write leveling 8B */ u8 wr_level[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; - /* Gating */ + /* Gating 32B */ u8 gating_MCK[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; u8 gating_UI[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; u8 gating_PI[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; u8 gating_pass_count[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; - /* TX perbit */ + /* TX perbit 164B */ u8 tx_window_vref[CHANNEL_MAX][RANK_MAX]; u16 tx_center_min[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; u16 tx_center_max[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; u16 tx_win_center[CHANNEL_MAX][RANK_MAX][DQ_DATA_WIDTH_LP4]; - /* rx datlat */ + /* rx datlat 4B */ u8 rx_datlat[CHANNEL_MAX][RANK_MAX]; - /* RX perbit */ + /* RX perbit 88B */ u8 rx_best_vref[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; - u16 rx_perbit_dqs[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; - u16 rx_perbit_dqm[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; - u16 rx_perbit_dq[CHANNEL_MAX][RANK_MAX][DQ_DATA_WIDTH_LP4]; + u8 rx_perbit_dqs[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; + u8 rx_perbit_dqm[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; + u8 rx_perbit_dq[CHANNEL_MAX][RANK_MAX][DQ_DATA_WIDTH_LP4]; - /* TX OE */ + /* TX OE 16B */ u8 tx_oe_dq_mck[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; u8 tx_oe_dq_ui[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; }; @@ -112,6 +117,15 @@ struct emi_mdl { u32 chn_cona_val; }; +struct ddr_mrr_info { + u16 mr5_vendor_id; + u16 mr6_revision_id; + u16 mr7_revision_id; + u64 mr8_density[RANK_MAX]; + u32 rank_nums; + u8 die_num[RANK_MAX]; +}; + struct ddr_base_info { u32 config_dvfs; /* SDRAM_DVFS_FLAG */ struct sdram_info sdram; @@ -120,6 +134,8 @@ struct ddr_base_info { u64 rank_size[RANK_MAX]; struct emi_mdl emi_config; DRAM_CBT_MODE_T cbt_mode[RANK_MAX]; + struct ddr_mrr_info mrr_info; + u32 data_rate; }; struct dramc_data { diff --git a/src/soc/mediatek/mt8186/include/soc/dramc_soc.h b/src/soc/mediatek/mt8186/include/soc/dramc_soc.h index 34e8414d47..5602e144cb 100644 --- a/src/soc/mediatek/mt8186/include/soc/dramc_soc.h +++ b/src/soc/mediatek/mt8186/include/soc/dramc_soc.h @@ -15,6 +15,11 @@ typedef enum { RANK_MAX, } DRAM_RANK_T; +typedef enum { + RANK_SINGLE = 1, + RANK_DUAL, +} DRAM_RANK_NUMBER_T; + /* DRAM SHUFFLE RG type */ typedef enum { DRAM_DFS_SHUFFLE_1 = 0,