2019-06-30 01:49:33 +01: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-14 14:45:45 +01:00
|
|
|
#include <soc/clock.h>
|
|
|
|
#include <ianos/ianos.h>
|
|
|
|
#include <soc/clock.h>
|
|
|
|
#include <soc/fuse.h>
|
|
|
|
#include <soc/t210.h>
|
|
|
|
#include <utils/util.h>
|
2019-06-30 01:49:33 +01:00
|
|
|
|
|
|
|
extern volatile nyx_storage_t *nyx_str;
|
2020-06-13 16:16:29 +01:00
|
|
|
|
2020-05-08 23:32:44 +01:00
|
|
|
void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
|
2019-06-30 01:49:33 +01:00
|
|
|
|
2019-12-09 20:27:01 +00:00
|
|
|
u32 minerva_init()
|
2019-06-30 01:49:33 +01:00
|
|
|
{
|
|
|
|
u32 curr_ram_idx = 0;
|
|
|
|
|
2019-12-16 20:06:13 +00:00
|
|
|
minerva_cfg = NULL;
|
2019-06-30 01:49:33 +01:00
|
|
|
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
|
2020-06-13 16:16:29 +01: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.
|
2020-06-14 11:17:26 +01:00
|
|
|
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
|
2020-06-13 16:16:29 +01:00
|
|
|
minerva_cfg = (void *)ep_addr;
|
|
|
|
|
2020-11-15 11:40:13 +00:00
|
|
|
return !minerva_cfg ? 1 : 0;
|
2020-06-13 16:16:29 +01: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;
|
|
|
|
|
2020-06-14 11:17:26 +01:00
|
|
|
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)&mtc_tmp);
|
2020-06-13 16:16:29 +01:00
|
|
|
|
|
|
|
// 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-03-21 20:10:06 +00:00
|
|
|
memset(mtc_cfg, 0, sizeof(mtc_config_t));
|
2019-06-30 01:49:33 +01:00
|
|
|
|
2019-12-04 19:56:45 +00:00
|
|
|
// Set table to nyx storage.
|
2020-04-30 01:47:23 +01:00
|
|
|
mtc_cfg->mtc_table = (emc_table_t *)nyx_str->mtc_table;
|
2019-12-04 19:56:45 +00:00
|
|
|
|
2019-06-30 01:49:33 +01:00
|
|
|
mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
|
2019-12-09 20:27:01 +00:00
|
|
|
mtc_cfg->init_done = MTC_NEW_MAGIC; // Initialize mtc table.
|
2020-03-21 20:10:06 +00:00
|
|
|
|
2020-06-14 11:17:26 +01:00
|
|
|
u32 ep_addr = ianos_loader("bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
|
2019-12-09 20:27:01 +00:00
|
|
|
|
|
|
|
// Ensure that Minerva is new.
|
|
|
|
if (mtc_cfg->init_done == MTC_INIT_MAGIC)
|
|
|
|
minerva_cfg = (void *)ep_addr;
|
2020-03-21 20:10:06 +00:00
|
|
|
else
|
|
|
|
mtc_cfg->init_done = 0;
|
2020-06-13 16:16:29 +01:00
|
|
|
#endif
|
2019-06-30 01:49:33 +01:00
|
|
|
|
|
|
|
if (!minerva_cfg)
|
2019-12-09 20:27:01 +00:00
|
|
|
return 1;
|
2019-06-30 01:49:33 +01: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-07 23:15:35 +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);
|
2019-12-09 20:27:01 +00:00
|
|
|
|
|
|
|
return 0;
|
2019-06-30 01:49:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void minerva_change_freq(minerva_freq_t freq)
|
|
|
|
{
|
|
|
|
if (!minerva_cfg)
|
|
|
|
return;
|
2019-09-12 21:08:38 +01:00
|
|
|
|
2019-06-30 01:49:33 +01:00
|
|
|
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
|
2019-12-04 19:56:45 +00:00
|
|
|
if (mtc_cfg->rate_from != freq)
|
2019-06-30 01:49:33 +01: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;
|
2019-09-12 21:08:38 +01:00
|
|
|
|
2019-06-30 01:49:33 +01:00
|
|
|
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
|
2019-12-04 19:56:45 +00:00
|
|
|
if (mtc_cfg->rate_from == FREQ_1600)
|
2019-06-30 01:49:33 +01:00
|
|
|
{
|
|
|
|
mtc_cfg->train_mode = OP_PERIODIC_TRAIN;
|
|
|
|
minerva_cfg(mtc_cfg, NULL);
|
|
|
|
}
|
|
|
|
}
|