Lockpick_RCM/bdk/mem/minerva.c

152 lines
3.8 KiB
C
Raw Permalink Normal View History

2019-09-25 18:18:08 +00:00
/*
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stdlib.h>
#include "minerva.h"
2020-06-26 20:17:06 +00:00
#include <soc/clock.h>
#include <ianos/ianos.h>
#include <soc/clock.h>
#include <soc/fuse.h>
#include <soc/hw_init.h>
2020-06-26 20:17:06 +00:00
#include <soc/t210.h>
#include <utils/util.h>
2019-09-25 18:18:08 +00:00
2019-12-09 02:17:46 +00:00
extern volatile nyx_storage_t *nyx_str;
2020-06-26 20:17:06 +00:00
void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
2019-09-25 18:18:08 +00:00
u32 minerva_init()
2019-09-25 18:18:08 +00:00
{
u32 curr_ram_idx = 0;
2019-12-29 21:32:37 +00:00
minerva_cfg = NULL;
2019-09-25 18:18:08 +00:00
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
2020-06-26 20:17:06 +00:00
//!TODO: Not supported on T210B01 yet.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
return 0;
2020-06-26 20:17:06 +00:00
#ifdef NYX
// Set table to nyx storage.
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
// Check if Minerva is already initialized.
if (mtc_cfg->init_done == MTC_INIT_MAGIC)
{
mtc_cfg->train_mode = OP_PERIODIC_TRAIN; // Retrain if needed.
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
minerva_cfg = (void *)ep_addr;
return !minerva_cfg ? 1 : 0;
2020-06-26 20:17:06 +00:00
}
else
{
mtc_config_t mtc_tmp;
mtc_tmp.mtc_table = mtc_cfg->mtc_table;
mtc_tmp.sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
mtc_tmp.init_done = MTC_NEW_MAGIC;
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp);
// Ensure that Minerva is new.
if (mtc_tmp.init_done == MTC_INIT_MAGIC)
minerva_cfg = (void *)ep_addr;
else
mtc_cfg->init_done = 0;
// Copy Minerva context to Nyx storage.
if (minerva_cfg)
memcpy(mtc_cfg, (void *)&mtc_tmp, sizeof(mtc_config_t));
}
#else
2020-04-15 22:18:58 +00:00
memset(mtc_cfg, 0, sizeof(mtc_config_t));
2019-09-25 18:18:08 +00:00
2019-12-09 02:17:46 +00:00
// Set table to nyx storage.
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
2019-12-09 02:17:46 +00:00
2019-09-25 18:18:08 +00:00
mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table.
2020-04-15 22:18:58 +00:00
2020-06-26 20:17:06 +00:00
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
// Ensure that Minerva is new.
if (mtc_cfg->init_done == MTC_INIT_MAGIC)
minerva_cfg = (void *)ep_addr;
2020-04-15 22:18:58 +00:00
else
mtc_cfg->init_done = 0;
2020-06-26 20:17:06 +00:00
#endif
2019-09-25 18:18:08 +00:00
if (!minerva_cfg)
return 1;
2019-09-25 18:18:08 +00:00
// Get current frequency
for (curr_ram_idx = 0; curr_ram_idx < 10; curr_ram_idx++)
{
if (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) == mtc_cfg->mtc_table[curr_ram_idx].clk_src_emc)
break;
}
mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz;
mtc_cfg->rate_to = 204000;
mtc_cfg->train_mode = OP_TRAIN;
minerva_cfg(mtc_cfg, NULL);
mtc_cfg->rate_to = 800000;
minerva_cfg(mtc_cfg, NULL);
mtc_cfg->rate_to = 1600000;
minerva_cfg(mtc_cfg, NULL);
2019-12-09 02:17:46 +00:00
// FSP WAR.
mtc_cfg->train_mode = OP_SWITCH;
mtc_cfg->rate_to = 800000;
minerva_cfg(mtc_cfg, NULL);
// Switch to max.
mtc_cfg->rate_to = 1600000;
minerva_cfg(mtc_cfg, NULL);
return 0;
2019-09-25 18:18:08 +00:00
}
void minerva_change_freq(minerva_freq_t freq)
{
if (!minerva_cfg)
return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
2019-12-09 02:17:46 +00:00
if (mtc_cfg->rate_from != freq)
2019-09-25 18:18:08 +00:00
{
mtc_cfg->rate_to = freq;
mtc_cfg->train_mode = OP_SWITCH;
minerva_cfg(mtc_cfg, NULL);
}
}
void minerva_periodic_training()
{
if (!minerva_cfg)
return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
2019-12-09 02:17:46 +00:00
if (mtc_cfg->rate_from == FREQ_1600)
2019-09-25 18:18:08 +00:00
{
mtc_cfg->train_mode = OP_PERIODIC_TRAIN;
minerva_cfg(mtc_cfg, NULL);
}
}