Patrick Georgi submitted this change.

View Change

Approvals: build bot (Jenkins): Verified Hung-Te Lin: Looks good to me, approved
soc/mediatek/mt8183: Run DRAM full calibration

Load the calibration params from flash first and check the correctness
of the params. If the params have correct format, perform DRAM fast
calibration with these params to reduce bootup time. Otherwise, load the
DRAM blob and perform DRAM full calibration.

Bootup time of DRAM partial calibration:
- 1,349,385 usecs with low frequency
- 924,698 usecs with middle frequency
- 1,270,089 usecs with high frequency
3,544,172 usecs in total.

Bootup time of DRAM fast calibration:
- 216,663 usecs with low frequency
- 328,220 usecs with middle frequency
- 322,612 usecs with high frequency
867,495 usecs in total.

BUG=b:139099592
BRANCH=none
TEST=emerge-kukui coreboot

Change-Id: I8de29b14b1fb24b3b4f351c855c5c4d8f350cc34
Signed-off-by: Huayang Duan <huayang.duan@mediatek.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/35110
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
---
M src/mainboard/google/kukui/romstage.c
M src/soc/mediatek/mt8183/Makefile.inc
M src/soc/mediatek/mt8183/include/soc/emi.h
M src/soc/mediatek/mt8183/memory.c
4 files changed, 184 insertions(+), 6 deletions(-)

diff --git a/src/mainboard/google/kukui/romstage.c b/src/mainboard/google/kukui/romstage.c
index a86690b..2b7dd6a 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 @@
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 72a4d9c..70fd080 100644
--- a/src/soc/mediatek/mt8183/Makefile.inc
+++ b/src/soc/mediatek/mt8183/Makefile.inc
@@ -81,6 +81,14 @@
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 ab21bc7..624c0a4 100644
--- a/src/soc/mediatek/mt8183/include/soc/emi.h
+++ b/src/soc/mediatek/mt8183/include/soc/emi.h
@@ -71,6 +71,8 @@
u16 delay_cell_unit;
};

+struct dramc_param_ops;
+
enum {
LP4X_DDR1600,
LP4X_DDR2400,
@@ -86,6 +88,6 @@
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 67f6c65..c2ddb99 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 @@
}
}
}
+
+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();
+}

To view, visit change 35110. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I8de29b14b1fb24b3b4f351c855c5c4d8f350cc34
Gerrit-Change-Number: 35110
Gerrit-PatchSet: 54
Gerrit-Owner: huayang duan <huayangduan@gmail.com>
Gerrit-Reviewer: Hung-Te Lin <hungte@chromium.org>
Gerrit-Reviewer: Julius Werner <jwerner@chromium.org>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-Reviewer: Yu-Ping Wu <yupingso@google.com>
Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org>
Gerrit-Reviewer: huayang duan <huayangduan@gmail.com>
Gerrit-CC: Angel Pons <th3fanbus@gmail.com>
Gerrit-CC: Huayang Duan <huayang.duan@mediatek.corp-partner.google.com>
Gerrit-CC: Paul Menzel <paulepanter@users.sourceforge.net>
Gerrit-MessageType: merged