tegra210: mtc: support external tables (WIP)

This commit is contained in:
SwtcR 2018-02-17 06:21:12 +09:00 committed by Andre Heider
parent b581707d8e
commit 1684df7e58
7 changed files with 243 additions and 1 deletions

View file

@ -220,3 +220,8 @@ struct chip_operations mainboard_ops = {
.name = "switch", .name = "switch",
.enable_dev = mainboard_enable, .enable_dev = mainboard_enable,
}; };
void lb_board(struct lb_header *header)
{
soc_add_mtc(header);
}

View file

@ -30,7 +30,7 @@ static const struct sdram_params sdram_configs[] = {
#define FUSE_BASE ((void *)TEGRA_FUSE_BASE) #define FUSE_BASE ((void *)TEGRA_FUSE_BASE)
#define FUSE_RESERVED_ODM4 0x1d8 #define FUSE_RESERVED_ODM4 0x1d8
static uint32_t switch_sdram_get_id(void) uint32_t switch_sdram_get_id(void)
{ {
return (read32(FUSE_BASE + FUSE_RESERVED_ODM4) & 0x38) >> 3; return (read32(FUSE_BASE + FUSE_RESERVED_ODM4) & 0x38) >> 3;
} }
@ -48,3 +48,8 @@ const struct sdram_params *get_sdram_config()
return &sdram_configs[id]; return &sdram_configs[id];
} }
uint32_t ram_code(void)
{
return switch_sdram_get_id();
}

View file

@ -142,6 +142,24 @@ config MTC_ADDRESS
The DRAM location where MTC firmware to be loaded in. This location The DRAM location where MTC firmware to be loaded in. This location
needs to be consistent with the location defined in tegra_mtc.ld needs to be consistent with the location defined in tegra_mtc.ld
config HAVE_MTC_TABLES
bool "Add external Memory controller Training Code tables"
default n
depends on USE_BLOBS
help
Select this option to add external emc training tables
if HAVE_MTC_TABLES
config MTC_TABLES_DIRECTORY
string "Directory where MTC table files are located"
default "mtc_tables"
help
Path to directory where MTC tables files are located. They should be
named tegra_mtc_table_<ram_code>.bin.
endif # HAVE_MTC_TABLES
endif # HAVE_MTC endif # HAVE_MTC
endif # SOC_NVIDIA_TEGRA210 endif # SOC_NVIDIA_TEGRA210

View file

@ -162,4 +162,18 @@ cbfs-files-$(CONFIG_HAVE_MTC) += $(MTC_FILE_CBFS)
$(MTC_FILE_CBFS)-file := $(MTC_FILE) $(MTC_FILE_CBFS)-file := $(MTC_FILE)
$(MTC_FILE_CBFS)-type := raw $(MTC_FILE_CBFS)-type := raw
ifeq ($(CONFIG_HAVE_MTC_TABLES),y)
MTC_TABLES_DIRECTORY = $(call strip_quotes,$(CONFIG_MTC_TABLES_DIRECTORY))
define MTC_CBFS_template =
cbfs-files-y += $(1)
$(1)-file := $(MTC_TABLES_DIRECTORY)/$(1)
$(1)-type := raw
endef
MTC_TABLE_NAMES = $(notdir $(wildcard $(MTC_TABLES_DIRECTORY)/tegra_mtc_table_*.bin))
$(foreach table,$(MTC_TABLE_NAMES),$(eval $(call MTC_CBFS_template,$(table))))
endif
endif endif

View file

@ -20,6 +20,89 @@
#if IS_ENABLED(CONFIG_HAVE_MTC) #if IS_ENABLED(CONFIG_HAVE_MTC)
typedef struct {
unsigned int rev;
char dvfs_ver[60];
unsigned int rate;
unsigned int min_volt;
unsigned int gpu_min_volt;
char clock_src[32];
unsigned int clk_src_emc;
unsigned int needs_training;
unsigned int training_pattern;
unsigned int trained;
unsigned int periodic_training;
unsigned int trained_dram_clktree_c0d0u0;
unsigned int trained_dram_clktree_c0d0u1;
unsigned int trained_dram_clktree_c0d1u0;
unsigned int trained_dram_clktree_c0d1u1;
unsigned int trained_dram_clktree_c1d0u0;
unsigned int trained_dram_clktree_c1d0u1;
unsigned int trained_dram_clktree_c1d1u0;
unsigned int trained_dram_clktree_c1d1u1;
unsigned int current_dram_clktree_c0d0u0;
unsigned int current_dram_clktree_c0d0u1;
unsigned int current_dram_clktree_c0d1u0;
unsigned int current_dram_clktree_c0d1u1;
unsigned int current_dram_clktree_c1d0u0;
unsigned int current_dram_clktree_c1d0u1;
unsigned int current_dram_clktree_c1d1u0;
unsigned int current_dram_clktree_c1d1u1;
unsigned int run_clocks;
unsigned int tree_margin;
unsigned int num_burst;
unsigned int num_burst_per_ch;
unsigned int num_trim;
unsigned int num_trim_per_ch;
unsigned int num_mc_regs;
unsigned int num_up_down;
unsigned int vref_num;
unsigned int training_mod_num;
unsigned int dram_timing_num;
unsigned int burst_regs[221];
unsigned int burst_reg_per_ch[8];
unsigned int shadow_regs_ca_train[221];
unsigned int shadow_regs_quse_train[221];
unsigned int shadow_regs_rdwr_train[221];
unsigned int trim_regs[138];
unsigned int trim_perch_regs[10];
/* Vref regs, impacted by training. */
unsigned int vref_perch_regs[4];
/* DRAM timing parameters are required in some calculations. */
unsigned int dram_timings[5];
unsigned int training_mod_regs[20];
unsigned int save_restore_mod_regs[12];
unsigned int burst_mc_regs[33];
unsigned int la_scale_regs[24];
unsigned int min_mrs_wait;
unsigned int emc_mrw;
unsigned int emc_mrw2;
unsigned int emc_mrw3;
unsigned int emc_mrw4;
unsigned int emc_mrw9;
unsigned int emc_mrs;
unsigned int emc_emrs;
unsigned int emc_emrs2;
unsigned int emc_auto_cal_config;
unsigned int emc_auto_cal_config2;
unsigned int emc_auto_cal_config3;
unsigned int emc_auto_cal_config4;
unsigned int emc_auto_cal_config5;
unsigned int emc_auto_cal_config6;
unsigned int emc_auto_cal_config7;
unsigned int emc_auto_cal_config8;
unsigned int emc_cfg_2;
unsigned int emc_sel_dpd_ctrl;
unsigned int emc_fdpd_ctrl_cmd_no_ramp;
unsigned int dll_clk_src;
unsigned int clk_out_enb_x_0_clk_enb_emc_dll;
unsigned int latency;
} tegra210_emc_table;
int tegra210_run_mtc(void); int tegra210_run_mtc(void);
void soc_add_mtc(struct lb_header *header); void soc_add_mtc(struct lb_header *header);

View file

@ -13,10 +13,14 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <arch/io.h>
#include <cbfs.h> #include <cbfs.h>
#include <cbmem.h> #include <cbmem.h>
#include <console/console.h> #include <console/console.h>
#include <soc/mtc.h> #include <soc/mtc.h>
#include <soc/addressmap.h>
#include <soc/clock.h>
#include <boardid.h>
#include <string.h> #include <string.h>
static size_t mtc_table_size; static size_t mtc_table_size;
@ -25,6 +29,111 @@ static size_t mtc_table_size;
#define MTC_TABLE_ENTRY_SIZE 4880 #define MTC_TABLE_ENTRY_SIZE 4880
#define MTC_TABLE_MAX_SIZE (MAX_MTC_TABLE_ENTRIES * MTC_TABLE_ENTRY_SIZE) #define MTC_TABLE_MAX_SIZE (MAX_MTC_TABLE_ENTRIES * MTC_TABLE_ENTRY_SIZE)
#define TRAIN_FUNC 0x5100
#define OP_SWITCH 0
#define OP_TRAIN 1
static int train_all(void *mtc)
{
void * const mtc_entry = (void *)(((uintptr_t)mtc) + TRAIN_FUNC);
int (*train_one)(int z, unsigned int to, unsigned int from,
void *table, int count, int mode) = (void *)(mtc_entry);
char filename[32];
int entries;
struct region_device fh;
struct cbfsf mtc_file;
int ret = 0;
snprintf(filename, sizeof(filename), "tegra_mtc_table_%d.bin", ram_code());
if (cbfs_boot_locate(&mtc_file, filename, NULL)) {
printk(BIOS_ERR, "MTC: Table file not found: %s\n", filename);
return -1;
}
cbfs_file_data(&fh, &mtc_file);
mtc_table_size = region_device_sz(&fh);
entries = mtc_table_size / sizeof(tegra210_emc_table);
printk(BIOS_ERR, "MTC: Using MTC table %s (size: 0x%lx / %d entries)\n",
filename, mtc_table_size, entries);
void *cbmem_tab = cbmem_add(CBMEM_ID_MTC, mtc_table_size);
if (cbmem_tab == NULL) {
printk(BIOS_ERR, "MTC table allocation in cbmem failed!\n");
return -1;
}
printk(BIOS_INFO, "MTC: table is at %p\n", cbmem_tab);
printk(BIOS_INFO, "MTC: entry is at %p\n", train_one);
ssize_t nread = rdev_readat(&fh, cbmem_tab, 0, mtc_table_size);
if (nread != region_device_sz(&fh)) {
printk(BIOS_ERR, "MTC bytes read (%zu) != file length(%zu)!\n",
nread, region_device_sz(&fh));
goto cleanup;
}
tegra210_emc_table *table = cbmem_tab;
int boot_index = 0;
u32 reg = read32(CLK_RST_REG(clk_src_emc));
printk(BIOS_INFO, "MTC: clk_src_emc=0x%08x\n", reg);
for (boot_index = 0; boot_index < entries; boot_index++) {
if (reg == table[boot_index].clk_src_emc)
break;
}
if (boot_index >= entries) {
printk(BIOS_ERR, "MTC: failed to find boot entry\n");
goto cleanup;
}
printk(BIOS_INFO, "MTC: booted using entry #%d (%d kHz): %s\n", boot_index,
table[boot_index].rate, table[boot_index].dvfs_ver);
printk(BIOS_INFO, "MTC: running training\n");
for (int i = 0; i < entries; i++) {
printk(BIOS_INFO, "MTC: Training %d kHz -> %d kHz\n",
table[boot_index].rate, table[i].rate);
ret = train_one(0, table[i].rate, table[boot_index].rate,
table, entries, OP_TRAIN);
if (ret) {
printk(BIOS_ERR, "MTC: Training failed (%d)\n", ret);
goto cleanup;
} else {
printk(BIOS_ERR, "MTC: Training OK\n");
}
}
printk(BIOS_INFO, "MTC: increasing memory clocks\n");
for (int i = boot_index + 1; i < entries; i++) {
if (table[i].periodic_training)
break;
printk(BIOS_INFO, "MTC: Switching %d kHz -> %d kHz\n",
table[i - 1].rate, table[i].rate);
ret = train_one(0, table[i].rate, table[i - 1].rate,
table, entries, OP_SWITCH);
if (ret) {
printk(BIOS_ERR, "MTC: Switch failed (%d)\n", ret);
goto cleanup;
}
}
printk(BIOS_INFO, "MTC: successful\n");
return 0;
cleanup:
cbmem_entry_remove(cbmem_entry_find(CBMEM_ID_MTC));
mtc_table_size = 0;
return -1;
}
int tegra210_run_mtc(void) int tegra210_run_mtc(void)
{ {
ssize_t nread; ssize_t nread;
@ -53,6 +162,7 @@ int tegra210_run_mtc(void)
printk(BIOS_INFO, "MTC: %zu bytes loaded @ %p\n", nread, mtc); printk(BIOS_INFO, "MTC: %zu bytes loaded @ %p\n", nread, mtc);
#if !IS_ENABLED(CONFIG_HAVE_MTC_TABLES)
mtc_table_size = (*mtc_fw)(&dvfs_table); mtc_table_size = (*mtc_fw)(&dvfs_table);
if ((mtc_table_size == 0) || (mtc_table_size > MTC_TABLE_MAX_SIZE)) { if ((mtc_table_size == 0) || (mtc_table_size > MTC_TABLE_MAX_SIZE)) {
@ -72,6 +182,9 @@ int tegra210_run_mtc(void)
memcpy(cbmem_tab, dvfs_table, mtc_table_size); memcpy(cbmem_tab, dvfs_table, mtc_table_size);
printk(BIOS_INFO, "MTC: Copied 0x%zx bytes from %p to %p\n", printk(BIOS_INFO, "MTC: Copied 0x%zx bytes from %p to %p\n",
mtc_table_size, dvfs_table, cbmem_tab); mtc_table_size, dvfs_table, cbmem_tab);
#else
return train_all(mtc);
#endif
return 0; return 0;
} }

View file

@ -16,6 +16,7 @@
#include <arch/clock.h> #include <arch/clock.h>
#include <arch/cpu.h> #include <arch/cpu.h>
#include <arch/stages.h> #include <arch/stages.h>
#include <cbmem.h>
#include <gic.h> #include <gic.h>
#include <soc/addressmap.h> #include <soc/addressmap.h>
#include <soc/clock.h> #include <soc/clock.h>
@ -68,6 +69,9 @@ void ramstage_entry(void)
clock_init_arm_generic_timer(); clock_init_arm_generic_timer();
/* Needed to store MTC data */
cbmem_initialize();
if (tegra210_run_mtc() != 0) if (tegra210_run_mtc() != 0)
printk(BIOS_ERR, "MTC: No training data.\n"); printk(BIOS_ERR, "MTC: No training data.\n");