summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mainboard/google/kukui/romstage.c41
-rw-r--r--src/soc/mediatek/mt8183/Makefile.inc8
-rw-r--r--src/soc/mediatek/mt8183/include/soc/emi.h4
-rw-r--r--src/soc/mediatek/mt8183/memory.c137
4 files changed, 184 insertions, 6 deletions
diff --git a/src/mainboard/google/kukui/romstage.c b/src/mainboard/google/kukui/romstage.c
index a86690b6fbe9..2b7dd6a20ceb 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 72a4d9cf625e..70fd08052ce7 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 ab21bc7e1216..624c0a4ac314 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 67f6c6536324..c2ddb999de78 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();
+}