diff options
-rw-r--r-- | src/mainboard/google/kukui/romstage.c | 41 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/Makefile.inc | 8 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/include/soc/emi.h | 4 | ||||
-rw-r--r-- | src/soc/mediatek/mt8183/memory.c | 137 |
4 files changed, 184 insertions, 6 deletions
diff --git a/src/mainboard/google/kukui/romstage.c b/src/mainboard/google/kukui/romstage.c index a86690b6fb..2b7dd6a20c 100644 --- a/src/mainboard/google/kukui/romstage.c +++ b/src/mainboard/google/kukui/romstage.c @@ -14,6 +14,9 @@ */ #include <arch/stages.h> +#include <console/console.h> +#include <fmap.h> +#include <soc/dramc_param.h> #include <soc/emi.h> #include <soc/mmu_operations.h> #include <soc/mt6358.h> @@ -22,6 +25,42 @@ #include "early_init.h" +/* This must be defined in chromeos.fmd in same name and size. */ +#define CALIBRATION_REGION "RW_DDR_TRAINING" +#define CALIBRATION_REGION_SIZE 0x2000 + +_Static_assert(sizeof(struct dramc_param) <= CALIBRATION_REGION_SIZE, + "sizeof(struct dramc_param) exceeds " CALIBRATION_REGION); + +static bool read_calibration_data_from_flash(struct dramc_param *dparam) +{ + const size_t length = sizeof(*dparam); + size_t ret = fmap_read_area(CALIBRATION_REGION, dparam, length); + printk(BIOS_DEBUG, "%s: ret=%#lx, length=%#lx\n", + __func__, ret, length); + + return ret == length; +} + +static bool write_calibration_data_to_flash(const struct dramc_param *dparam) +{ + const size_t length = sizeof(*dparam); + size_t ret = fmap_overwrite_area(CALIBRATION_REGION, dparam, length); + printk(BIOS_DEBUG, "%s: ret=%#lx, length=%#lx\n", + __func__, ret, length); + + return ret == length; +} + +/* dramc_param is ~2K and too large to fit in stack. */ +static struct dramc_param dramc_parameter; + +static struct dramc_param_ops dparam_ops = { + .param = &dramc_parameter, + .read_from_flash = &read_calibration_data_from_flash, + .write_to_flash = &write_calibration_data_to_flash, +}; + void platform_romstage_main(void) { /* This will be done in verstage if CONFIG_VBOOT is enabled. */ @@ -34,6 +73,6 @@ void platform_romstage_main(void) mt_pll_raise_ca53_freq(1989 * MHz); pmic_init_scp_voltage(); rtc_boot(); - mt_mem_init(get_sdram_config()); + mt_mem_init(&dparam_ops); mtk_mmu_after_dram(); } diff --git a/src/soc/mediatek/mt8183/Makefile.inc b/src/soc/mediatek/mt8183/Makefile.inc index 72a4d9cf62..70fd08052c 100644 --- a/src/soc/mediatek/mt8183/Makefile.inc +++ b/src/soc/mediatek/mt8183/Makefile.inc @@ -81,6 +81,14 @@ sspm.bin-file := $(MT8183_BLOB_DIR)/sspm.bin sspm.bin-type := raw sspm.bin-compression := $(CBFS_COMPRESS_FLAG) +DRAM_CBFS := $(CONFIG_CBFS_PREFIX)/dram +$(DRAM_CBFS)-file := $(MT8183_BLOB_DIR)/dram.elf +$(DRAM_CBFS)-type := stage +$(DRAM_CBFS)-compression := none +ifneq ($(wildcard $($(DRAM_CBFS)-file)),) + cbfs-files-y += $(DRAM_CBFS) +endif + BL31_MAKEARGS += PLAT=mt8183 CPPFLAGS_common += -Isrc/soc/mediatek/mt8183/include diff --git a/src/soc/mediatek/mt8183/include/soc/emi.h b/src/soc/mediatek/mt8183/include/soc/emi.h index ab21bc7e12..624c0a4ac3 100644 --- a/src/soc/mediatek/mt8183/include/soc/emi.h +++ b/src/soc/mediatek/mt8183/include/soc/emi.h @@ -71,6 +71,8 @@ struct sdram_params { u16 delay_cell_unit; }; +struct dramc_param_ops; + enum { LP4X_DDR1600, LP4X_DDR2400, @@ -86,6 +88,6 @@ size_t sdram_size(void); const struct sdram_params *get_sdram_config(void); void enable_emi_dcm(void); void mt_set_emi(const struct sdram_params *freq_params); -void mt_mem_init(const struct sdram_params *freq_params); +void mt_mem_init(struct dramc_param_ops *dparam_ops); #endif /* SOC_MEDIATEK_MT8183_EMI_H */ diff --git a/src/soc/mediatek/mt8183/memory.c b/src/soc/mediatek/mt8183/memory.c index 67f6c65363..c2ddb999de 100644 --- a/src/soc/mediatek/mt8183/memory.c +++ b/src/soc/mediatek/mt8183/memory.c @@ -14,18 +14,18 @@ */ #include <assert.h> +#include <cbfs.h> #include <console/console.h> +#include <soc/dramc_param.h> #include <soc/dramc_pi_api.h> #include <soc/emi.h> +#include <string.h> #include <symbols.h> -void mt_mem_init(const struct sdram_params *freq_params) +static void mt_mem_test(void) { u64 rank_size[RANK_MAX]; - /* memory calibration */ - mt_set_emi(freq_params); - if (CONFIG(MEMORY_TEST)) { size_t r; u8 *addr = _dram; @@ -49,3 +49,132 @@ void mt_mem_init(const struct sdram_params *freq_params) } } } + +static void dump_param_header(const struct dramc_param *dparam) +{ + const struct dramc_param_header *header = &dparam->header; + + printk(BIOS_DEBUG, "header.status = %#x\n", header->status); + printk(BIOS_DEBUG, "header.magic = %#x (expected: %#x)\n", + header->magic, DRAMC_PARAM_HEADER_MAGIC); + printk(BIOS_DEBUG, "header.version = %#x (expected: %#x)\n", + header->version, DRAMC_PARAM_HEADER_VERSION); + printk(BIOS_DEBUG, "header.size = %#x (expected: %#lx)\n", + header->size, sizeof(*dparam)); + printk(BIOS_DEBUG, "header.config = %#x\n", header->config); + printk(BIOS_DEBUG, "header.flags = %#x\n", header->flags); + printk(BIOS_DEBUG, "header.checksum = %#x\n", header->checksum); +} + +static int dram_run_fast_calibration(const struct dramc_param *dparam, + u16 config) +{ + if (!is_valid_dramc_param(dparam)) { + printk(BIOS_WARNING, + "Invalid DRAM calibration data from flash\n"); + dump_param_header(dparam); + return -1; + } + + if (dparam->header.config != config) { + printk(BIOS_WARNING, + "Incompatible config for calibration data from flash " + "(expected: %#x, saved: %#x)\n", + config, dparam->header.config); + return -1; + } + + return 0; +} + +static int dram_run_full_calibration(struct dramc_param *dparam, u16 config) +{ + initialize_dramc_param(dparam, config); + + /* Load and run the provided blob for full-calibration if available */ + struct prog dram = PROG_INIT(PROG_REFCODE, CONFIG_CBFS_PREFIX "/dram"); + + if (prog_locate(&dram)) + return -1; + + if (cbfs_prog_stage_load(&dram)) + return -2; + + prog_set_entry(&dram, prog_entry(&dram), dparam); + prog_run(&dram); + + if (dparam->header.status != DRAMC_SUCCESS) { + printk(BIOS_ERR, "Full calibration failed: status = %d\n", + dparam->header.status); + return -3; + } + + if (!(dparam->header.flags & DRAMC_FLAG_HAS_SAVED_DATA)) { + printk(BIOS_ERR, + "Full calibration executed without saving parameters. " + "Please ensure the blob is built properly.\n"); + return -4; + } + + return 0; +} + +static void set_source_to_flash(struct sdram_params *freq_params) +{ + for (u8 shuffle = DRAM_DFS_SHUFFLE_1; shuffle < DRAM_DFS_SHUFFLE_MAX; + shuffle++) + freq_params[shuffle].source = DRAMC_PARAM_SOURCE_FLASH; +} + +static void init_sdram_params(struct sdram_params *dst, + const struct sdram_params *src) +{ + for (u8 shuffle = DRAM_DFS_SHUFFLE_1; shuffle < DRAM_DFS_SHUFFLE_MAX; + shuffle++) + memcpy(&dst[shuffle], src, sizeof(*dst)); +} + +void mt_mem_init(struct dramc_param_ops *dparam_ops) +{ + struct dramc_param *dparam = dparam_ops->param; + struct sdram_params *freq_params = dparam->freq_params; + + u16 config = 0; + if (CONFIG(MT8183_DRAM_EMCP)) + config |= DRAMC_CONFIG_EMCP; + + /* Load calibration params from flash and run fast calibration */ + if (dparam_ops->read_from_flash(dparam)) { + if (dram_run_fast_calibration(dparam, config) == 0) { + printk(BIOS_INFO, + "DRAM calibraion params loaded from flash\n"); + mt_set_emi(freq_params); + mt_mem_test(); + return; + } + } else { + printk(BIOS_WARNING, + "Failed to read calibration data from flash\n"); + } + + /* Run full calibration */ + int err = dram_run_full_calibration(dparam, config); + if (err == 0) { + printk(BIOS_INFO, "Successfully loaded DRAM blobs and " + "ran DRAM calibration\n"); + set_source_to_flash(dparam->freq_params); + dparam_ops->write_to_flash(dparam); + printk(BIOS_DEBUG, "Calibration params saved to flash: " + "version=%#x, size=#%x\n", + dparam->header.version, dparam->header.size); + return; + } + + printk(BIOS_ERR, "Failed to do full calibration (%d), " + "falling back to load default sdram param\n", err); + + /* Init params from sdram configs and run partial calibration */ + init_sdram_params(freq_params, get_sdram_config()); + mt_set_emi(freq_params); + mt_mem_test(); +} |