diff options
Diffstat (limited to 'src/soc/mediatek/common')
-rw-r--r-- | src/soc/mediatek/common/Kconfig | 32 | ||||
-rw-r--r-- | src/soc/mediatek/common/dpm.c | 47 | ||||
-rw-r--r-- | src/soc/mediatek/common/dram_init.c | 37 | ||||
-rw-r--r-- | src/soc/mediatek/common/dramc_param.c | 56 | ||||
-rw-r--r-- | src/soc/mediatek/common/include/soc/dpm.h | 49 | ||||
-rw-r--r-- | src/soc/mediatek/common/include/soc/dramc_common.h | 17 | ||||
-rw-r--r-- | src/soc/mediatek/common/include/soc/dramc_param.h | 161 | ||||
-rw-r--r-- | src/soc/mediatek/common/include/soc/emi.h | 18 | ||||
-rw-r--r-- | src/soc/mediatek/common/memory.c | 244 |
9 files changed, 661 insertions, 0 deletions
diff --git a/src/soc/mediatek/common/Kconfig b/src/soc/mediatek/common/Kconfig new file mode 100644 index 0000000000..543bc02d13 --- /dev/null +++ b/src/soc/mediatek/common/Kconfig @@ -0,0 +1,32 @@ +config SOC_MEDIATEK_COMMON + bool + help + common code blocks for Mediatek SOCs + +if SOC_MEDIATEK_COMMON + +config MEDIATEK_DRAM_DVFS + bool + default n + help + This option enables DRAM calibration with multiple frequencies (low, + medium and high frequency groups, with total 7 frequencies) for DVFS + feature. All supported data rates are: 800, 1200, 1600, 1866, 2400, + 3200, 4266. + +config MEDIATEK_DRAM_DVFS_LIMIT_FREQ_CNT + bool + default y + select MEDIATEK_DRAM_DVFS + help + This options limit DRAM frequency calibration count from total 7 to 3, + other frequency will directly use the low frequency shu result. + +config MEMORY_TEST + bool + default y + help + This option enables memory basic compare test to verify the DRAM read + or write is as expected. + +endif diff --git a/src/soc/mediatek/common/dpm.c b/src/soc/mediatek/common/dpm.c new file mode 100644 index 0000000000..991441e74c --- /dev/null +++ b/src/soc/mediatek/common/dpm.c @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <device/mmio.h> +#include <soc/dpm.h> +#include <soc/mcu_common.h> +#include <soc/symbols.h> + +static void reset_dpm(struct mtk_mcu *mcu) +{ + /* write bootargs */ + write32(&mtk_dpm->twam_window_len, 0x0); + write32(&mtk_dpm->twam_mon_type, 0x0); + + /* free RST */ + setbits32(&mtk_dpm->sw_rstn, DPM_SW_RSTN_RESET); +} + +static struct mtk_mcu dpm_mcu[] = { + { + .firmware_name = CONFIG_DPM_DM_FIRMWARE, + .run_address = (void *)DPM_DM_SRAM_BASE, + }, + { + .firmware_name = CONFIG_DPM_PM_FIRMWARE, + .run_address = (void *)DPM_PM_SRAM_BASE, + .reset = reset_dpm, + }, +}; + +int dpm_init(void) +{ + int i; + struct mtk_mcu *dpm; + + /* config DPM SRAM layout */ + clrsetbits32(&mtk_dpm->sw_rstn, DPM_MEM_RATIO_MASK, DPM_MEM_RATIO_CFG1); + + for (i = 0; i < ARRAY_SIZE(dpm_mcu); i++) { + dpm = &dpm_mcu[i]; + dpm->load_buffer = _dram_dma; + dpm->buffer_size = REGION_SIZE(dram_dma); + if (mtk_init_mcu(dpm)) + return -1; + } + + return 0; +} diff --git a/src/soc/mediatek/common/dram_init.c b/src/soc/mediatek/common/dram_init.c new file mode 100644 index 0000000000..accc7ac5e7 --- /dev/null +++ b/src/soc/mediatek/common/dram_init.c @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <delay.h> +#include <stdint.h> +#include <soc/dramc_common.h> +#include <soc/dramc_param.h> +#include <soc/emi.h> + +struct dramc_param *dramc_params; + +bool is_dvfs_enabled(void) +{ + dramc_info("dram_init: config_dvfs: %d\n", + dramc_params->dramc_datas.ddr_info.config_dvfs); + return !!(dramc_params->dramc_datas.ddr_info.config_dvfs); +} + +u32 get_ddr_geometry(void) +{ + dramc_info("dram_init: ddr_geometry: %d\n", + dramc_params->dramc_datas.ddr_info.ddr_geometry); + return dramc_params->dramc_datas.ddr_info.ddr_geometry; +} + +u32 get_ddr_type(void) +{ + dramc_info("dram_init: ddr_type: %d\n", + dramc_params->dramc_datas.ddr_info.ddr_type); + return dramc_params->dramc_datas.ddr_info.ddr_type; +} + +void init_dram_by_params(struct dramc_param *dparam) +{ + dramc_params = dparam; + mt_set_emi(dramc_params); +} diff --git a/src/soc/mediatek/common/dramc_param.c b/src/soc/mediatek/common/dramc_param.c new file mode 100644 index 0000000000..8548dbc665 --- /dev/null +++ b/src/soc/mediatek/common/dramc_param.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <string.h> +#include <soc/dramc_param.h> + +#define print(_x_...) printk(BIOS_INFO, _x_) + +struct dramc_param *get_dramc_param_from_blob(void *blob) +{ + return (struct dramc_param *)blob; +} + +void dump_param_header(const void *blob) +{ + const struct dramc_param *dparam = blob; + const struct dramc_param_header *header = &dparam->header; + + print("header.status = %#x\n", header->status); + print("header.version = %#x (expected: %#x)\n", + header->version, DRAMC_PARAM_HEADER_VERSION); + print("header.size = %#x (expected: %#lx)\n", + header->size, sizeof(*dparam)); + print("header.flags = %#x\n", header->flags); + print("header.checksum = %#x\n", header->checksum); +} + +int validate_dramc_param(const void *blob) +{ + const struct dramc_param *param = blob; + const struct dramc_param_header *hdr = ¶m->header; + + if (hdr->version != DRAMC_PARAM_HEADER_VERSION) + return DRAMC_ERR_INVALID_VERSION; + + if (hdr->size != sizeof(*param)) + return DRAMC_ERR_INVALID_SIZE; + + return DRAMC_SUCCESS; +} + +int is_valid_dramc_param(const void *blob) +{ + return validate_dramc_param(blob) == DRAMC_SUCCESS; +} + +int initialize_dramc_param(void *blob) +{ + struct dramc_param *param = blob; + struct dramc_param_header *hdr = ¶m->header; + + memset(hdr, 0, sizeof(*hdr)); + hdr->version = DRAMC_PARAM_HEADER_VERSION; + hdr->size = sizeof(*param); + return 0; +} diff --git a/src/soc/mediatek/common/include/soc/dpm.h b/src/soc/mediatek/common/include/soc/dpm.h new file mode 100644 index 0000000000..7262e09a6f --- /dev/null +++ b/src/soc/mediatek/common/include/soc/dpm.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_DPM_H__ +#define __SOC_MEDIATEK_DPM_H__ + +#include <soc/addressmap.h> +#include <stdint.h> +#include <types.h> + +struct dpm_regs { + u32 sw_rstn; + u32 rsvd_0[3072]; + u32 mclk_div; + u32 rsvd_1[3071]; + u32 twam_window_len; + u32 twam_mon_type; + u32 rsvd_2[1022]; + u32 low_power_cfg_0; + u32 low_power_cfg_1; + u32 rsvd_3[1]; + u32 fsm_out_ctrl_0; + u32 rsvd_4[8]; + u32 fsm_cfg_1; + u32 low_power_cfg_3; + u32 dfd_dbug_0; + u32 rsvd_5[28]; + u32 status_4; +}; + +check_member(dpm_regs, mclk_div, 0x3004); +check_member(dpm_regs, twam_window_len, 0x6004); +check_member(dpm_regs, low_power_cfg_0, 0x7004); +check_member(dpm_regs, low_power_cfg_1, 0x7008); +check_member(dpm_regs, fsm_out_ctrl_0, 0x7010); +check_member(dpm_regs, fsm_cfg_1, 0x7034); +check_member(dpm_regs, low_power_cfg_3, 0x7038); +check_member(dpm_regs, dfd_dbug_0, 0x703C); +check_member(dpm_regs, status_4, 0x70B0); + +#define DPM_SW_RSTN_RESET BIT(0) +#define DPM_MEM_RATIO_OFFSET 28 +#define DPM_MEM_RATIO_MASK (0x3 << DPM_MEM_RATIO_OFFSET) +#define DPM_MEM_RATIO_CFG1 (1 << DPM_MEM_RATIO_OFFSET) + +static struct dpm_regs *const mtk_dpm = (void *)DPM_CFG_BASE; + +int dpm_init(void); + +#endif /* __SOC_MEDIATEK_MT8192_DPM_H__ */ diff --git a/src/soc/mediatek/common/include/soc/dramc_common.h b/src/soc/mediatek/common/include/soc/dramc_common.h new file mode 100644 index 0000000000..a5716dc50f --- /dev/null +++ b/src/soc/mediatek/common/include/soc/dramc_common.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_DRAMC_COMMON_H__ +#define __SOC_MEDIATEK_DRAMC_COMMON_H__ + +#include <console/console.h> + +#define dramc_err(_x_...) printk(BIOS_ERR, _x_) +#define dramc_info(_x_...) printk(BIOS_INFO, _x_) +#define dramc_show dramc_info +#define dramc_dbg(_x_...) \ + do { \ + if (CONFIG(DEBUG_RAM_SETUP)) \ + printk(BIOS_INFO, _x_); \ + } while (0) + +#endif diff --git a/src/soc/mediatek/common/include/soc/dramc_param.h b/src/soc/mediatek/common/include/soc/dramc_param.h new file mode 100644 index 0000000000..d3eda8da92 --- /dev/null +++ b/src/soc/mediatek/common/include/soc/dramc_param.h @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_DRAMC_PARAM_H__ +#define __SOC_MEDIATEK_DRAMC_PARAM_H__ + +/* any change in this file should sync to blob dramc_param.h */ + +#include <stdint.h> +#include <sys/types.h> +#include <soc/dramc_soc.h> + +enum { + DRAMC_PARAM_HEADER_VERSION = 5, +}; + +enum DRAMC_PARAM_STATUS_CODES { + DRAMC_SUCCESS = 0, + DRAMC_ERR_INVALID_VERSION, + DRAMC_ERR_INVALID_SIZE, + DRAMC_ERR_INVALID_CHECKSUM, + DRAMC_ERR_INVALID_FLAGS, + DRAMC_ERR_RECALIBRATE, + DRAMC_ERR_INIT_DRAM, + DRAMC_ERR_COMPLEX_RW_MEM_TEST, + DRAMC_ERR_1ST_COMPLEX_RW_MEM_TEST, + DRAMC_ERR_2ND_COMPLEX_RW_MEM_TEST, + DRAMC_ERR_FAST_CALIBRATION, +}; + +enum DRAMC_PARAM_DVFS_FLAG { + DRAMC_DISABLE_DVFS, + DRAMC_ENABLE_DVFS, +}; + +enum DRAMC_PARAM_FLAGS { + DRAMC_FLAG_HAS_SAVED_DATA = 0x0001, +}; + +enum DRAMC_PARAM_DDR_TYPE { + DDR_TYPE_DISCRETE, + DDR_TYPE_EMCP, +}; + +/* Don't change the order, which is matched with blob */ +enum DRAMC_PARAM_GEOMETRY_TYPE { + DDR_TYPE_2CH_2RK_4GB_2_2, + DDR_TYPE_2CH_2RK_6GB_3_3, + DDR_TYPE_2CH_2RK_8GB_4_4_BYTE, + DDR_TYPE_2CH_1RK_4GB_4_0, + DDR_TYPE_2CH_2RK_6GB_2_4, + DDR_TYPE_2CH_2RK_8GB_4_4, +}; + +enum DRAM_PARAM_VOLTAGE_TYPE { + DRAM_VOLTAGE_NVCORE_NVDRAM, + DRAM_VOLTAGE_HVCORE_HVDRAM, + DRAM_VOLTAGE_LVCORE_LVDRAM, +}; + +struct dramc_param_header { + u32 checksum; /* checksum of dramc_datas, update in the coreboot */ + u16 version; /* DRAMC_PARAM_HEADER_VERSION, update in the coreboot */ + u16 size; /* size of whole dramc_param, update in the coreboot */ + u16 status; /* DRAMC_PARAM_STATUS_CODES, update in the dram blob */ + u16 flags; /* DRAMC_PARAM_FLAGS, update in the dram blob */ +}; + +struct sdram_params { + u32 rank_num; + u16 num_dlycell_perT; + u16 delay_cell_timex100; + + /* duty */ + 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 */ + u8 cbt_final_vref[CHANNEL_MAX][RANK_MAX]; + s8 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 */ + u8 wr_level[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; + + /* Gating */ + 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 */ + 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 */ + u8 rx_datlat[CHANNEL_MAX][RANK_MAX]; + + /* RX perbit */ + 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]; + + /* TX OE */ + u8 tx_oe_dq_mck[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; + u8 tx_oe_dq_ui[CHANNEL_MAX][RANK_MAX][DQS_NUMBER_LP4]; +}; + +struct emi_mdl { + u32 cona_val; + u32 conh_val; + u32 conf_val; + u32 chn_cona_val; +}; + +struct ddr_base_info { + u32 config_dvfs; /* DRAMC_PARAM_DVFS_FLAG */ + u32 ddr_type; /* DRAMC_PARAM_DDR_TYPE */ + u32 ddr_geometry; /* DRAMC_PARAM_GEOMETRY_TYPE */ + u32 voltage_type; /* DRAM_PARAM_VOLTAGE_TYPE */ + u32 support_ranks; + u64 rank_size[RANK_MAX]; + struct emi_mdl emi_config; + dram_cbt_mode cbt_mode[RANK_MAX]; +}; + +struct dramc_data { + struct ddr_base_info ddr_info; + struct sdram_params freq_params[DRAM_DFS_SHU_MAX]; +}; + +struct dramc_param { + struct dramc_param_header header; + void (*do_putc)(unsigned char c); + struct dramc_data dramc_datas; +}; + +struct dramc_param_ops { + struct dramc_param *param; + bool (*read_from_flash)(struct dramc_param *dparam); + bool (*write_to_flash)(const struct dramc_param *dparam); +}; + +struct sdram_info { + u32 ddr_geometry; /* DRAMC_PARAM_GEOMETRY_TYPE */ + u32 ddr_type; /* DRAMC_PARAM_DDR_TYPE */ +}; + +const struct sdram_info *get_sdram_config(void); +struct dramc_param *get_dramc_param_from_blob(void *blob); +void dump_param_header(const void *blob); +int validate_dramc_param(const void *blob); +int is_valid_dramc_param(const void *blob); +int initialize_dramc_param(void *blob); +#endif /* __SOC_MEDIATEK_DRAMC_PARAM_H__ */ diff --git a/src/soc/mediatek/common/include/soc/emi.h b/src/soc/mediatek/common/include/soc/emi.h new file mode 100644 index 0000000000..c91c8706c4 --- /dev/null +++ b/src/soc/mediatek/common/include/soc/emi.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SOC_MEDIATEK_EMI_H +#define SOC_MEDIATEK_EMI_H + +#include <soc/dramc_param.h> + +size_t sdram_size(void); +void mt_set_emi(struct dramc_param *dparam); +void mt_mem_init(struct dramc_param_ops *dparam_ops); +int complex_mem_test(u8 *start, unsigned int len); + +bool is_dvfs_enabled(void); +u32 get_ddr_geometry(void); +u32 get_ddr_type(void); +void init_dram_by_params(struct dramc_param *dparam); + +#endif /* SOC_MEDIATEK_MT8192_EMI_H */ diff --git a/src/soc/mediatek/common/memory.c b/src/soc/mediatek/common/memory.c new file mode 100644 index 0000000000..2cc05713a1 --- /dev/null +++ b/src/soc/mediatek/common/memory.c @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <bootmode.h> +#include <cbfs.h> +#include <console/console.h> +#include <ip_checksum.h> +#include <soc/emi.h> +#include <symbols.h> +#include <timer.h> + +const char *get_dram_geometry_str(u32 ddr_geometry); +const char *get_dram_type_str(u32 ddr_type); + +static int mt_mem_test(const struct dramc_data *dparam) +{ + if (CONFIG(MEMORY_TEST)) { + u8 *addr = _dram; + const struct ddr_base_info *ddr_info = &dparam->ddr_info; + + for (u8 rank = RANK_0; rank < ddr_info->support_ranks; rank++) { + int result = complex_mem_test(addr, 0x2000); + + if (result != 0) { + printk(BIOS_ERR, + "[MEM] complex R/W mem test failed: %d\n", result); + return -1; + } + printk(BIOS_DEBUG, "[MEM] rank %u complex R/W mem test passed\n", rank); + + addr += ddr_info->rank_size[rank]; + } + } + + return 0; +} + +static u32 compute_checksum(const struct dramc_param *dparam) +{ + return (u32)compute_ip_checksum(&dparam->dramc_datas, + sizeof(dparam->dramc_datas)); +} + +const char *get_dram_geometry_str(u32 ddr_geometry) +{ + const char *s; + + switch (ddr_geometry) { + case DDR_TYPE_2CH_2RK_4GB_2_2: + s = "2CH_2RK_4GB_2_2"; + break; + case DDR_TYPE_2CH_2RK_6GB_3_3: + s = "2CH_2RK_6GB_3_3"; + break; + case DDR_TYPE_2CH_2RK_8GB_4_4: + s = "2CH_2RK_8GB_4_4"; + break; + case DDR_TYPE_2CH_2RK_8GB_4_4_BYTE: + s = "2CH_2RK_8GB_4_4_BYTE"; + break; + case DDR_TYPE_2CH_1RK_4GB_4_0: + s = "2CH_1RK_4GB_4_0"; + break; + case DDR_TYPE_2CH_2RK_6GB_2_4: + s = "2CH_2RK_6GB_2_4"; + break; + default: + s = ""; + break; + } + + return s; +} + +const char *get_dram_type_str(u32 ddr_type) +{ + const char *s; + + switch (ddr_type) { + case DDR_TYPE_DISCRETE: + s = "DSC"; + break; + case DDR_TYPE_EMCP: + s = "EMCP"; + break; + default: + s = ""; + break; + } + + return s; +} + +static int dram_run_fast_calibration(struct dramc_param *dparam) +{ + if (!is_valid_dramc_param(dparam)) { + printk(BIOS_WARNING, "DRAM-K: Invalid DRAM calibration data from flash\n"); + dump_param_header((void *)dparam); + return -1; + } + + const u32 checksum = compute_checksum(dparam); + if (dparam->header.checksum != checksum) { + printk(BIOS_ERR, + "DRAM-K: Invalid DRAM calibration checksum from flash " + "(expected: %#x, saved: %#x)\n", + checksum, dparam->header.checksum); + return DRAMC_ERR_INVALID_CHECKSUM; + } + + 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) +{ + /* 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); + + if (prog_locate(&dram)) { + printk(BIOS_ERR, "DRAM-K: Locate program failed\n"); + return -1; + } + + if (cbfs_prog_stage_load(&dram)) { + printk(BIOS_ERR, "DRAM-K: CBFS load program failed\n"); + return -2; + } + + dparam->do_putc = do_putchar; + + 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", + dparam->header.status); + return -3; + } + + if (!(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"); + return -4; + } + + return 0; +} + +static void mem_init_set_default_config(struct dramc_param *dparam, + const struct sdram_info *dram_info) +{ + u32 type, geometry; + memset(dparam, 0, sizeof(*dparam)); + + type = dram_info->ddr_type; + geometry = dram_info->ddr_geometry; + + dparam->dramc_datas.ddr_info.ddr_type = type; + + if (CONFIG(MEDIATEK_DRAM_DVFS)) + dparam->dramc_datas.ddr_info.config_dvfs = DRAMC_ENABLE_DVFS; + + dparam->dramc_datas.ddr_info.ddr_geometry = geometry; + + printk(BIOS_INFO, "DRAM-K: ddr_type: %s, config_dvfs: %d, ddr_geometry: %s\n", + get_dram_type_str(type), + dparam->dramc_datas.ddr_info.config_dvfs, + get_dram_geometry_str(geometry)); +} + +static void mt_mem_init_run(struct dramc_param_ops *dparam_ops, + const struct sdram_info *dram_info) +{ + struct dramc_param *dparam = dparam_ops->param; + struct stopwatch sw; + int ret; + + /* Load calibration params from flash and run fast calibration */ + mem_init_set_default_config(dparam, dram_info); + if (dparam_ops->read_from_flash(dparam)) { + printk(BIOS_INFO, "DRAM-K: Running fast calibration\n"); + stopwatch_init(&sw); + + ret = dram_run_fast_calibration(dparam); + if (ret != 0) { + printk(BIOS_ERR, "DRAM-K: Failed to run fast calibration " + "in %ld msecs, error: %d\n", + stopwatch_duration_msecs(&sw), ret); + + /* Erase flash data after fast calibration failed */ + memset(dparam, 0xa5, sizeof(*dparam)); + dparam_ops->write_to_flash(dparam); + } else { + printk(BIOS_INFO, "DRAM-K: Fast calibration passed in %ld msecs\n", + stopwatch_duration_msecs(&sw)); + return; + } + } else { + printk(BIOS_WARNING, "DRAM-K: Failed to read calibration data from flash\n"); + } + + /* Run full calibration */ + printk(BIOS_INFO, "DRAM-K: Running full calibration\n"); + mem_init_set_default_config(dparam, dram_info); + + stopwatch_init(&sw); + int err = dram_run_full_calibration(dparam); + if (err == 0) { + printk(BIOS_INFO, "DRAM-K: Full calibration passed in %ld msecs\n", + stopwatch_duration_msecs(&sw)); + + dparam->header.checksum = compute_checksum(dparam); + dparam_ops->write_to_flash(dparam); + printk(BIOS_DEBUG, "DRAM-K: Calibration params saved to flash: " + "version=%#x, size=%#x\n", + dparam->header.version, dparam->header.size); + } else { + printk(BIOS_ERR, "DRAM-K: Full calibration failed in %ld msecs\n", + stopwatch_duration_msecs(&sw)); + } +} + +void mt_mem_init(struct dramc_param_ops *dparam_ops) +{ + const struct sdram_info *sdram_param = get_sdram_config(); + + mt_mem_init_run(dparam_ops, sdram_param); +} |