bdk: minerva: add IRB support

Aka no table support.
This commit is contained in:
CTCaer
2025-12-17 05:24:16 +02:00
parent 8b4d5507f6
commit 0db758592a
4 changed files with 55 additions and 68 deletions

View File

@@ -26,22 +26,22 @@
#include <soc/hw_init.h> #include <soc/hw_init.h>
#include <soc/t210.h> #include <soc/t210.h>
#define FREQ_NO_TABLE_MAX FREQ_408
#define TABLE_FREQ_KHZ_OFFSET 0x40 #define TABLE_FREQ_KHZ_OFFSET 0x40
#define TABLE_LA_REGS_T210_OFFSET 0x1284 #define TABLE_LA_REGS_T210_OFFSET 0x1284
#define TABLE_LA_REGS_T210B01_OFFSET 0xFA4 #define TABLE_LA_REGS_T210B01_OFFSET 0xFA4
#define LA_SDMMC1_INDEX 6 #define LA_SDMMC1_INDEX 6
static bool no_table = false;
static mtc_config_t *mtc_cfg = NULL; static mtc_config_t *mtc_cfg = NULL;
void (*mtc_call)(mtc_config_t *mtc_cfg, void *); void (*mtc_call)(mtc_config_t *mtc_cfg, void *);
u32 minerva_init(minerva_str_t *mtc_str) u32 minerva_init(minerva_str_t *mtc_str)
{ {
mtc_call = NULL; mtc_call = NULL;
mtc_cfg = (mtc_config_t *)&mtc_str->mtc_cfg; mtc_cfg = (mtc_config_t *)&mtc_str->mtc_cfg;
no_table = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01;
//!TODO: Not supported on T210B01 yet.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
return 0;
#ifdef BDK_MINERVA_CFG_FROM_RAM #ifdef BDK_MINERVA_CFG_FROM_RAM
// Set table to nyx storage. // Set table to nyx storage.
@@ -50,7 +50,8 @@ u32 minerva_init(minerva_str_t *mtc_str)
// Check if Minerva is already initialized. // Check if Minerva is already initialized.
if (mtc_cfg->init_done == MTC_INIT_MAGIC) if (mtc_cfg->init_done == MTC_INIT_MAGIC)
{ {
mtc_cfg->train_mode = OP_PERIODIC_TRAIN; // Retrain if needed. // Load library and do a periodic training if needed.
mtc_cfg->train_mode = OP_PERIODIC_TRAIN;
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg); u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
mtc_call = (void *)ep_addr; mtc_call = (void *)ep_addr;
@@ -60,13 +61,15 @@ u32 minerva_init(minerva_str_t *mtc_str)
{ {
mtc_config_t mtc_tmp; mtc_config_t mtc_tmp;
mtc_tmp.mtc_table = mtc_cfg->mtc_table; // Initialize table.
mtc_tmp.sdram_id = fuse_read_dramid(false); mtc_tmp.mtc_table = mtc_cfg->mtc_table;
mtc_tmp.init_done = MTC_NEW_MAGIC; mtc_tmp.sdram_id = fuse_read_dramid(false);
mtc_tmp.init_done = !no_table ? MTC_NEW_MAGIC : MTC_IRB_MAGIC;
// Load library and get table.
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp); u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp);
// Ensure that Minerva is new. // Ensure that Minerva is initialized.
if (mtc_tmp.init_done == MTC_INIT_MAGIC) if (mtc_tmp.init_done == MTC_INIT_MAGIC)
mtc_call = (void *)ep_addr; mtc_call = (void *)ep_addr;
else else
@@ -77,17 +80,17 @@ u32 minerva_init(minerva_str_t *mtc_str)
memcpy(mtc_cfg, (void *)&mtc_tmp, sizeof(mtc_config_t)); memcpy(mtc_cfg, (void *)&mtc_tmp, sizeof(mtc_config_t));
} }
#else #else
// Fully initialize Minerva.
memset(mtc_cfg, 0, sizeof(mtc_config_t)); memset(mtc_cfg, 0, sizeof(mtc_config_t));
// Set table to nyx storage. // Initialize mtc table.
mtc_cfg->mtc_table = (emc_table_t *)mtc_str->mtc_table; mtc_cfg->mtc_table = mtc_str->mtc_table;
mtc_cfg->sdram_id = fuse_read_dramid(false);
mtc_cfg->sdram_id = fuse_read_dramid(false); mtc_cfg->init_done = !no_table ? MTC_NEW_MAGIC : MTC_IRB_MAGIC;
mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table.
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg); u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
// Ensure that Minerva is new. // Ensure that Minerva is initialized.
if (mtc_cfg->init_done == MTC_INIT_MAGIC) if (mtc_cfg->init_done == MTC_INIT_MAGIC)
mtc_call = (void *)ep_addr; mtc_call = (void *)ep_addr;
else else
@@ -97,18 +100,20 @@ u32 minerva_init(minerva_str_t *mtc_str)
if (!mtc_call) if (!mtc_call)
return 1; return 1;
// Get current frequency if (no_table)
u32 current_emc_clk_src = CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC);
u32 tbl_idx = 0;
for (tbl_idx = 0; tbl_idx < mtc_cfg->table_entries; tbl_idx++)
{ {
if (current_emc_clk_src == mtc_cfg->mtc_table[tbl_idx].clk_src_emc) mtc_cfg->train_mode = OP_SWITCH;
break; mtc_cfg->rate_from = FREQ_204;
mtc_cfg->rate_to = FREQ_NO_TABLE_MAX;
mtc_call(mtc_cfg, NULL);
return 0;
} }
mtc_cfg->rate_from = mtc_cfg->mtc_table[tbl_idx].rate_khz; // Train frequencies.
mtc_cfg->rate_to = FREQ_204;
mtc_cfg->train_mode = OP_TRAIN; mtc_cfg->train_mode = OP_TRAIN;
mtc_cfg->rate_from = FREQ_204;
mtc_cfg->rate_to = FREQ_204;
mtc_call(mtc_cfg, NULL); mtc_call(mtc_cfg, NULL);
mtc_cfg->rate_to = FREQ_800; mtc_cfg->rate_to = FREQ_800;
mtc_call(mtc_cfg, NULL); mtc_call(mtc_cfg, NULL);
@@ -132,11 +137,15 @@ void minerva_change_freq(minerva_freq_t freq)
if (!mtc_call) if (!mtc_call)
return; return;
// Clamp max allowed frequency when no table exists.
if (no_table && freq > FREQ_NO_TABLE_MAX)
freq = FREQ_NO_TABLE_MAX;
// Check if requested frequency is different. Do not allow otherwise because it will hang. // Check if requested frequency is different. Do not allow otherwise because it will hang.
if (mtc_cfg->rate_from != freq) if (mtc_cfg->rate_from != freq)
{ {
mtc_cfg->rate_to = freq;
mtc_cfg->train_mode = OP_SWITCH; mtc_cfg->train_mode = OP_SWITCH;
mtc_cfg->rate_to = freq;
mtc_call(mtc_cfg, NULL); mtc_call(mtc_cfg, NULL);
} }
} }
@@ -170,11 +179,19 @@ void minerva_sdmmc_la_program(void *table, bool t210b01)
} }
} }
void minerva_prep_boot_freq() void minerva_prep_boot_hos()
{ {
if (!mtc_call) if (!mtc_call)
return; return;
// Restore boot frequency for no table mode.
if (no_table)
{
minerva_deinit();
return;
}
// Check if there's RAM OC. If not exit. // Check if there's RAM OC. If not exit.
if (mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600) if (mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600)
return; return;
@@ -187,7 +204,7 @@ void minerva_prep_boot_freq()
void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom, bool prg_sdmmc_la) void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom, bool prg_sdmmc_la)
{ {
if (!mtc_call) if (!mtc_call || no_table)
return; return;
// Program SDMMC LA regs. // Program SDMMC LA regs.
@@ -255,7 +272,7 @@ void minerva_periodic_training()
if (!mtc_call) if (!mtc_call)
return; return;
if (mtc_cfg->rate_from == FREQ_1600) if (mtc_cfg->rate_from >= FREQ_1066)
{ {
mtc_cfg->train_mode = OP_PERIODIC_TRAIN; mtc_cfg->train_mode = OP_PERIODIC_TRAIN;
mtc_call(mtc_cfg, NULL); mtc_call(mtc_cfg, NULL);
@@ -264,7 +281,7 @@ void minerva_periodic_training()
emc_table_t *minerva_get_mtc_table() emc_table_t *minerva_get_mtc_table()
{ {
if (!mtc_call) if (!mtc_call || no_table)
return NULL; return NULL;
return mtc_cfg->mtc_table; return mtc_cfg->mtc_table;
@@ -272,7 +289,7 @@ emc_table_t *minerva_get_mtc_table()
int minerva_get_mtc_table_entries() int minerva_get_mtc_table_entries()
{ {
if (!mtc_call) if (!mtc_call || no_table)
return 0; return 0;
return mtc_cfg->table_entries; return mtc_cfg->table_entries;

View File

@@ -22,6 +22,7 @@
#define MTC_INIT_MAGIC 0x3043544D #define MTC_INIT_MAGIC 0x3043544D
#define MTC_NEW_MAGIC 0x5243544D #define MTC_NEW_MAGIC 0x5243544D
#define MTC_IRB_MAGIC 0x4943544D
#define EMC_PERIODIC_TRAIN_MS 250 #define EMC_PERIODIC_TRAIN_MS 250
@@ -60,9 +61,14 @@ typedef enum
{ {
FREQ_204 = 204000, FREQ_204 = 204000,
FREQ_408 = 408000, FREQ_408 = 408000,
FREQ_666 = 665600,
FREQ_800 = 800000, FREQ_800 = 800000,
FREQ_1066 = 1065600,
FREQ_1333 = 1331200, FREQ_1333 = 1331200,
FREQ_1600 = 1600000 FREQ_1600 = 1600000,
FREQ_MIN = FREQ_204,
FREQ_MAX = FREQ_1600
} minerva_freq_t; } minerva_freq_t;
extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *); extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
@@ -70,7 +76,7 @@ u32 minerva_init(minerva_str_t *mtc_str);
void minerva_deinit(); void minerva_deinit();
void minerva_change_freq(minerva_freq_t freq); void minerva_change_freq(minerva_freq_t freq);
void minerva_sdmmc_la_program(void *table, bool t210b01); void minerva_sdmmc_la_program(void *table, bool t210b01);
void minerva_prep_boot_freq(); void minerva_prep_boot_hos();
void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom, bool prg_sdmmc_la); void minerva_prep_boot_l4t(u32 oc_freq, u32 opt_custom, bool prg_sdmmc_la);
void minerva_periodic_training(); void minerva_periodic_training();
emc_table_t *minerva_get_mtc_table(); emc_table_t *minerva_get_mtc_table();

View File

@@ -182,41 +182,6 @@ emc_mr_data_t sdram_read_mrx(emc_mr_t mrx)
return data; return data;
} }
void sdram_src_pllc(bool enable)
{
static bool enabled = false;
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210 || enable == enabled)
return;
enabled = enable;
// Clear CC interrupt.
EMC(EMC_INTSTATUS) = BIT(4);
(void)EMC(EMC_INTSTATUS);
u32 clk_src_emc = _dram_cfg_08_10_12_14_samsung_hynix_4gb.emc_clock_source;
if (enable)
{
// Check if clock source is not the expected one.
if (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) != clk_src_emc)
return;
// Set source as PLLC_OUT0.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = 0x20188002;
}
else
{
// Restore MC/EMC clock.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = clk_src_emc;
}
// Wait for CC interrupt.
while (!(EMC(EMC_INTSTATUS) & BIT(4)))
usleep(1);
}
static void _sdram_config_t210(const sdram_params_t210_t *params) static void _sdram_config_t210(const sdram_params_t210_t *params)
{ {
// VDDP Select. // VDDP Select.

View File

@@ -135,7 +135,6 @@ void sdram_init();
void *sdram_get_params_patched(); void *sdram_get_params_patched();
void *sdram_get_params_t210b01(); void *sdram_get_params_t210b01();
void sdram_lp0_save_params(const void *params); void sdram_lp0_save_params(const void *params);
void sdram_src_pllc(bool enable);
emc_mr_data_t sdram_read_mrx(emc_mr_t mrx); emc_mr_data_t sdram_read_mrx(emc_mr_t mrx);
#endif #endif