soc/mediatek/common: Move DRAM implementation from mt8192 to common

To reduce duplicated dram sources on seperate SOCs,
add dpm, dram_init, dramc_params, memory(fast-k or full-k)
implementations, also add dramc log level macro header files.

Signed-off-by: Xi Chen <xixi.chen@mediatek.com>
Change-Id: I557c96b3d09828472b8b6f932b0192a90894043e
Reviewed-on: https://review.coreboot.org/c/coreboot/+/51203
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
This commit is contained in:
Xi Chen
2021-03-03 17:58:07 +08:00
committed by Hung-Te Lin
parent 022b1b992f
commit e8c681cc62
16 changed files with 244 additions and 67 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -18,9 +18,9 @@ void dump_param_header(const void *blob)
print("header.status = %#x\n", header->status);
print("header.version = %#x (expected: %#x)\n",
header->version, DRAMC_PARAM_HEADER_VERSION);
header->version, DRAMC_PARAM_HEADER_VERSION);
print("header.size = %#x (expected: %#lx)\n",
header->size, sizeof(*dparam));
header->size, sizeof(*dparam));
print("header.flags = %#x\n", header->flags);
print("header.checksum = %#x\n", header->checksum);
}

View File

@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SOC_MEDIATEK_MT8192_DPM_H__
#define __SOC_MEDIATEK_MT8192_DPM_H__
#ifndef __SOC_MEDIATEK_DPM_H__
#define __SOC_MEDIATEK_DPM_H__
#include <soc/addressmap.h>
#include <stdint.h>

View File

@@ -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

View File

@@ -1,14 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SOC_MEDIATEK_MT8192_DRAMC_PARAM_H__
#define __SOC_MEDIATEK_MT8192_DRAMC_PARAM_H__
#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_common_mt8192.h>
#include <soc/dramc_soc.h>
enum {
DRAMC_PARAM_HEADER_VERSION = 3,
DRAMC_PARAM_HEADER_VERSION = 5,
};
enum DRAMC_PARAM_STATUS_CODES {
@@ -39,12 +41,14 @@ enum DRAMC_PARAM_DDR_TYPE {
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,
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 {
@@ -116,10 +120,10 @@ struct emi_mdl {
};
struct ddr_base_info {
u16 config_dvfs; /* DRAMC_PARAM_DVFS_FLAG */
u16 ddr_type; /* DRAMC_PARAM_DDR_TYPE */
u16 ddr_geometry; /* DRAMC_PARAM_GEOMETRY_TYPE */
u16 voltage_type; /* DRAM_PARAM_VOLTAGE_TYPE */
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;
@@ -145,6 +149,7 @@ struct dramc_param_ops {
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);
@@ -153,4 +158,4 @@ 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_MT8192_DRAMC_PARAM_H__ */
#endif /* __SOC_MEDIATEK_DRAMC_PARAM_H__ */

View File

@@ -1,13 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SOC_MEDIATEK_MT8192_EMI_H
#define SOC_MEDIATEK_MT8192_EMI_H
#ifndef SOC_MEDIATEK_EMI_H
#define SOC_MEDIATEK_EMI_H
#include <soc/dramc_param.h>
size_t sdram_size(void);
void mt_set_emi(const struct dramc_data *dparam);
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 */

View File

@@ -9,6 +9,9 @@
#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)) {
@@ -22,9 +25,8 @@ static int mt_mem_test(const struct dramc_data *dparam)
printk(BIOS_ERR,
"[MEM] complex R/W mem test failed: %d\n", result);
return -1;
} else {
printk(BIOS_DEBUG, "[MEM] complex R/W mem test passed\n");
}
printk(BIOS_DEBUG, "[MEM] rank %u complex R/W mem test passed\n", rank);
addr += ddr_info->rank_size[rank];
}
@@ -39,7 +41,57 @@ static u32 compute_checksum(const struct dramc_param *dparam)
sizeof(dparam->dramc_datas));
}
static int dram_run_fast_calibration(const struct dramc_param *dparam)
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");
@@ -56,7 +108,7 @@ static int dram_run_fast_calibration(const struct dramc_param *dparam)
return DRAMC_ERR_INVALID_CHECKSUM;
}
const u16 config = CONFIG(MT8192_DRAM_DVFS) ? DRAMC_ENABLE_DVFS : DRAMC_DISABLE_DVFS;
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 "
@@ -66,7 +118,7 @@ static int dram_run_fast_calibration(const struct dramc_param *dparam)
}
printk(BIOS_INFO, "DRAM-K: DRAM calibration data valid pass\n");
mt_set_emi(&dparam->dramc_datas);
init_dram_by_params(dparam);
if (mt_mem_test(&dparam->dramc_datas) == 0)
return 0;
@@ -96,7 +148,7 @@ static int dram_run_full_calibration(struct dramc_param *dparam)
prog_run(&dram);
if (dparam->header.status != DRAMC_SUCCESS) {
printk(BIOS_ERR, "DRAM-K: Full calibration failed: status = %d\n",
dparam->header.status);
dparam->header.status);
return -3;
}
@@ -111,31 +163,36 @@ static int dram_run_full_calibration(struct dramc_param *dparam)
}
static void mem_init_set_default_config(struct dramc_param *dparam,
u32 ddr_geometry)
const struct sdram_info *dram_info)
{
u32 type, geometry;
memset(dparam, 0, sizeof(*dparam));
if (CONFIG(MT8192_DRAM_EMCP))
dparam->dramc_datas.ddr_info.ddr_type = DDR_TYPE_EMCP;
type = dram_info->ddr_type;
geometry = dram_info->ddr_geometry;
if (CONFIG(MT8192_DRAM_DVFS))
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 = ddr_geometry;
printk(BIOS_INFO, "DRAM-K: ddr_type: %d, config_dvfs: %d, ddr_geometry: %d\n",
dparam->dramc_datas.ddr_info.ddr_type,
dparam->dramc_datas.ddr_info.config_dvfs,
dparam->dramc_datas.ddr_info.ddr_geometry);
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, u32 ddr_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, ddr_geometry);
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);
@@ -160,7 +217,7 @@ static void mt_mem_init_run(struct dramc_param_ops *dparam_ops, u32 ddr_geometry
/* Run full calibration */
printk(BIOS_INFO, "DRAM-K: Running full calibration\n");
mem_init_set_default_config(dparam, ddr_geometry);
mem_init_set_default_config(dparam, dram_info);
stopwatch_init(&sw);
int err = dram_run_full_calibration(dparam);
@@ -183,5 +240,5 @@ 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->ddr_geometry);
mt_mem_init_run(dparam_ops, sdram_param);
}

View File

@@ -10,6 +10,7 @@ config SOC_MEDIATEK_MT8173
select HAVE_UART_SPECIAL
select GENERIC_GPIO_LIB
select RTC
select SOC_MEDIATEK_COMMON
if SOC_MEDIATEK_MT8173
@@ -22,10 +23,6 @@ config VBOOT
select VBOOT_STARTS_IN_BOOTBLOCK
select VBOOT_SEPARATE_VERSTAGE
config MEMORY_TEST
bool
default n
config DEBUG_SOC_DRIVER
bool "The top level switch for soc driver debug messages"
default n

View File

@@ -8,6 +8,7 @@ config SOC_MEDIATEK_MT8183
select ARM64_USE_ARM_TRUSTED_FIRMWARE
select HAVE_UART_SPECIAL
select COMPRESS_BOOTBLOCK
select SOC_MEDIATEK_COMMON
if SOC_MEDIATEK_MT8183
@@ -41,10 +42,6 @@ config MT8183_DRAM_DVFS
This options enables DRAM calibration with multiple frequencies (low,
medium and high) for DVFS feature.
config MEMORY_TEST
bool
default y
config SSPM_FIRMWARE
string
default "sspm.bin"

View File

@@ -7,6 +7,7 @@ config SOC_MEDIATEK_MT8192
select ARCH_RAMSTAGE_ARMV8_64
select ARM64_USE_ARM_TRUSTED_FIRMWARE
select HAVE_UART_SPECIAL
select SOC_MEDIATEK_COMMON
if SOC_MEDIATEK_MT8192

View File

@@ -28,6 +28,7 @@ verstage-y += ../common/uart.c
romstage-y += ../common/auxadc.c
romstage-y += ../common/cbmem.c
romstage-y += ../common/dram_init.c
romstage-y += dramc_pi_main.c dramc_pi_basic_api.c dramc_pi_calibration_api.c
romstage-y += dramc_utility.c dramc_dvfs.c
romstage-y += emi.c
@@ -35,7 +36,7 @@ romstage-y += ../common/flash_controller.c
romstage-y += ../common/gpio.c gpio.c
romstage-y += ../common/i2c.c i2c.c
romstage-y += ../common/mmu_operations.c mmu_operations.c
romstage-y += memory.c dramc_param.c ../common/memory_test.c
romstage-y += ../common/memory.c ../common/dramc_param.c ../common/memory_test.c
romstage-y += ../common/pll.c pll.c
romstage-$(CONFIG_SPI_FLASH) += ../common/spi.c spi.c
romstage-y += ../common/timer.c
@@ -47,7 +48,7 @@ romstage-y += mt6359p.c
ramstage-y += ../common/auxadc.c
ramstage-y += ../common/ddp.c ddp.c
ramstage-y += devapc.c
ramstage-y += dpm.c
ramstage-y += ../common/dpm.c
ramstage-y += ../common/dsi.c ../common/mtk_mipi_dphy.c
ramstage-y += ../common/flash_controller.c
ramstage-y += ../common/gpio.c gpio.c

View File

@@ -434,7 +434,7 @@ size_t sdram_size(void)
return dram_size;
}
void mt_set_emi(const struct dramc_data *dparam)
void mt_set_emi(struct dramc_param *dparam)
{
init_dram(dparam);
init_dram(&dparam->dramc_datas);
}

View File

@@ -3,18 +3,6 @@
#ifndef __SOC_MEDIATEK_MT8192_DRAMC_COMMON_MT8192_H__
#define __SOC_MEDIATEK_MT8192_DRAMC_COMMON_MT8192_H__
enum {
CHANNEL_A = 0,
CHANNEL_B,
CHANNEL_MAX
};
enum {
RANK_0 = 0,
RANK_1,
RANK_MAX
};
enum {
FSP_0 = 0,
FSP_1,
@@ -56,13 +44,6 @@ enum {
DQS_NUMBER = (DQ_DATA_WIDTH / DQS_BIT_NUMBER),
};
#define BYTE_NUM DQS_NUMBER
#define DQS_NUMBER_LP4 DQS_NUMBER
#define DQ_DATA_WIDTH_LP4 DQ_DATA_WIDTH
typedef enum {
CBT_NORMAL_MODE = 0,
CBT_BYTE_MODE1
} dram_cbt_mode;
/* DONOT change the sequence of pinmux */
typedef enum {

View File

@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SOC_MEDIATEK_DRAMC_SOC_H__
#define __SOC_MEDIATEK_DRAMC_SOC_H__
typedef enum {
CHANNEL_A = 0,
CHANNEL_B,
CHANNEL_MAX
} DRAM_CHANNEL_T;
typedef enum {
RANK_0 = 0,
RANK_1,
RANK_MAX
} DRAM_RANK_T;
typedef enum {
DRAM_DFS_SHUFFLE_1 = 0,
DRAM_DFS_SHUFFLE_2,
DRAM_DFS_SHUFFLE_3,
DRAM_DFS_SHUFFLE_4,
DRAM_DFS_SHUFFLE_5,
DRAM_DFS_SHUFFLE_6,
DRAM_DFS_SHUFFLE_7,
DRAM_DFS_SHUFFLE_MAX
} DRAM_DFS_SHUFFLE_TYPE_T; // DRAM SHUFFLE RG type
/*
* Internal CBT mode enum
* 1. Calibration flow uses vGet_Dram_CBT_Mode to
* differentiate between mixed vs non-mixed LP4
* 2. Declared as dram_cbt_mode[RANK_MAX] internally to
* store each rank's CBT mode type
*/
typedef enum {
CBT_NORMAL_MODE = 0,
CBT_BYTE_MODE1
} DRAM_CBT_MODE_T, dram_cbt_mode;
#define DRAM_DFS_SHU_MAX DRAM_DFS_SHUFFLE_MAX
#define DQS_NUMBER_LP4 2
#define DQS_BIT_NUMBER 8
#define DQ_DATA_WIDTH_LP4 16
#endif /* __SOC_MEDIATEK_DRAMC_SOC_H__ */