400 lines
11 KiB
C
Executable File
400 lines
11 KiB
C
Executable File
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <malloc.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include "include/arisc.h"
|
|
|
|
#define MAX_PATH (260)
|
|
#define HEADER_OFFSET (0x4000)
|
|
#define ARISC_INF //printf
|
|
|
|
static void usage(void)
|
|
{
|
|
printf(" update_scp scp.bin dtb.bin\n");
|
|
printf(" update arisc para from dtb\n");
|
|
|
|
return ;
|
|
}
|
|
|
|
int IsFullName(const char *FilePath)
|
|
{
|
|
if (isalpha(FilePath[0]) && ':' == FilePath[1])
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void GetFullPath(char *dName, const char *sName)
|
|
{
|
|
char Buffer[256];
|
|
|
|
if(IsFullName(sName))
|
|
{
|
|
strcpy(dName, sName);
|
|
return ;
|
|
}
|
|
|
|
/* Get the current working directory: */
|
|
if(getcwd(Buffer, 256 ) == NULL)
|
|
{
|
|
perror( "getcwd error" );
|
|
return ;
|
|
}
|
|
sprintf(dName, "%s/%s", Buffer, sName);
|
|
}
|
|
|
|
char *probe_file_data(char *file_name, int *file_len)
|
|
{
|
|
FILE *pfile;
|
|
int len;
|
|
char *buffer;
|
|
|
|
pfile = fopen(file_name, "rb");
|
|
if (pfile == NULL) {
|
|
printf("file %s cant be opened\n",file_name);
|
|
|
|
return NULL;
|
|
}
|
|
fseek(pfile, 0, SEEK_END);
|
|
len = ftell(pfile);
|
|
|
|
buffer = malloc(len);
|
|
if (buffer == NULL) {
|
|
printf("buffer cant be malloc\n");
|
|
fclose(pfile);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
memset(buffer, 0, len);
|
|
|
|
fseek(pfile, 0, SEEK_SET);
|
|
fread(buffer, len, 1, pfile);
|
|
fclose(pfile);
|
|
|
|
*file_len = len;
|
|
|
|
return buffer;
|
|
}
|
|
|
|
int parse_arisc_space_node(const void*working_fdt,arisc_para_t *arisc_para)
|
|
{
|
|
int nodeoffset;
|
|
uint value[4] = {0, 0, 0};
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt,"/soc/arisc_space");
|
|
if(nodeoffset < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "space4", value);
|
|
arisc_para->message_pool_phys = value[0];
|
|
arisc_para->message_pool_size = value[2];
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int parse_standby_space_node(const void*working_fdt,arisc_para_t *arisc_para)
|
|
{
|
|
int nodeoffset;
|
|
uint value[4] = {0, 0, 0};
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt,"/soc/standby_space");
|
|
if(nodeoffset < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "space1", value);
|
|
arisc_para->standby_base = value[0];
|
|
arisc_para->standby_size = value[2];
|
|
|
|
return 0;
|
|
}
|
|
|
|
int parse_s_uart_node(const void*working_fdt,arisc_para_t *arisc_para)
|
|
{
|
|
int nodeoffset;
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt, "/soc/s_uart");
|
|
if(nodeoffset < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
arisc_para->suart_status = fdtdec_get_is_enabled(working_fdt, nodeoffset);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int parse_pmu0_node(const void*working_fdt,arisc_para_t *arisc_para)
|
|
{
|
|
int nodeoffset;
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt, "/soc/pmu0");
|
|
if(nodeoffset < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "pmu_bat_shutdown_ltf", &arisc_para->pmu_bat_shutdown_ltf);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "pmu_bat_shutdown_htf", &arisc_para->pmu_bat_shutdown_htf);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "pmu_pwroff_vol", &arisc_para->pmu_pwroff_vol);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "power_start", &arisc_para->power_start);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int parse_arisc_node(const void*working_fdt,arisc_para_t *arisc_para)
|
|
{
|
|
int nodeoffset;
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt, "/soc/arisc");
|
|
if(nodeoffset < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "powchk_used", &arisc_para->powchk_used);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "power_reg", &arisc_para->power_reg );
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "system_power", &arisc_para->system_power);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int parse_s_cir_node(const void*working_fdt,arisc_para_t *arisc_para)
|
|
{
|
|
int nodeoffset;
|
|
int i;
|
|
char subkey[64];
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt, "/soc/s_cir");
|
|
if(nodeoffset < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (fdt_getprop_u32(working_fdt, nodeoffset, "ir_power_key_code", &arisc_para->ir_key.ir_code_depot[0].key_code)>0)
|
|
{
|
|
if (fdt_getprop_u32(working_fdt, nodeoffset, "ir_addr_code", &arisc_para->ir_key.ir_code_depot[0].addr_code)>0)
|
|
{
|
|
arisc_para->ir_key.num = 1;
|
|
goto print_ir_paras;
|
|
}
|
|
}
|
|
|
|
arisc_para->ir_key.num = 0;
|
|
for (i = 0; i < IR_NUM_KEY_SUP; i++) {
|
|
sprintf(subkey, "%s%d", "ir_power_key_code", i);
|
|
if (fdt_getprop_u32(working_fdt, nodeoffset, subkey, &arisc_para->ir_key.ir_code_depot[i].key_code)>0) {
|
|
sprintf(subkey, "%s%d", "ir_addr_code", i);
|
|
if (fdt_getprop_u32(working_fdt, nodeoffset, subkey, &arisc_para->ir_key.ir_code_depot[i].addr_code)>0) {
|
|
arisc_para->ir_key.num++;
|
|
}
|
|
}
|
|
}
|
|
|
|
print_ir_paras:
|
|
for (i = 0; i < arisc_para->ir_key.num; i++)
|
|
{
|
|
ARISC_INF(" ir_code[%u].key_code:0x%x, ir_code[%u].addr_code:0x%x\n",
|
|
i, arisc_para->ir_key.ir_code_depot[i].key_code, i, arisc_para->ir_key.ir_code_depot[i].addr_code);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int parse_dram_node(const void*working_fdt,arisc_para_t *arisc_para)
|
|
{
|
|
int nodeoffset;
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt, "/dram");
|
|
if(nodeoffset < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_clk", &arisc_para->dram_para.dram_clk);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_type", &arisc_para->dram_para.dram_type);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_zq", &arisc_para->dram_para.dram_zq);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_odt_en", &arisc_para->dram_para.dram_odt_en);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_para1", &arisc_para->dram_para.dram_para1);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_para2", &arisc_para->dram_para.dram_para2);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_mr0", &arisc_para->dram_para.dram_mr0);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_mr1", &arisc_para->dram_para.dram_mr1);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_mr2", &arisc_para->dram_para.dram_mr2);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_mr3", &arisc_para->dram_para.dram_mr3);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr0", &arisc_para->dram_para.dram_tpr0);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr1", &arisc_para->dram_para.dram_tpr1);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr2", &arisc_para->dram_para.dram_tpr2);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr3", &arisc_para->dram_para.dram_tpr3);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr4", &arisc_para->dram_para.dram_tpr4);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr5", &arisc_para->dram_para.dram_tpr5);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr6", &arisc_para->dram_para.dram_tpr6);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr7", &arisc_para->dram_para.dram_tpr7);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr8", &arisc_para->dram_para.dram_tpr8);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr9", &arisc_para->dram_para.dram_tpr9);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr10", &arisc_para->dram_para.dram_tpr10);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr11", &arisc_para->dram_para.dram_tpr11);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr12", &arisc_para->dram_para.dram_tpr12);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "dram_tpr13", &arisc_para->dram_para.dram_tpr13);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int parse_dvfs_table_node(const void*working_fdt,arisc_para_t *arisc_para)
|
|
{
|
|
int nodeoffset;
|
|
int i;
|
|
uint val;
|
|
uint vf_table_count = 0;
|
|
uint vf_table_type = 0;
|
|
char vf_table_main_key[64];
|
|
char vf_table_sub_key[64];
|
|
uint vf_table_size = 0;
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt, "/dvfs_table");
|
|
if (nodeoffset < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (fdt_getprop_u32(working_fdt, nodeoffset, "vf_table_count", &vf_table_count)<0)
|
|
{
|
|
ARISC_INF("%s: support only one vf_table\n", __func__);
|
|
sprintf(vf_table_main_key, "%s", "/dvfs_table");
|
|
}
|
|
else
|
|
{
|
|
sprintf(vf_table_main_key, "%s%d", "/vf_table", vf_table_type);
|
|
}
|
|
ARISC_INF("%s: vf table type [%d=%s]\n", __func__, vf_table_type, vf_table_main_key);
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt, vf_table_main_key);
|
|
|
|
/* parse system config v-f table information */
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "lv_count", &vf_table_size);
|
|
|
|
for (i = 0; i < vf_table_size; i++)
|
|
{
|
|
sprintf(vf_table_sub_key, "lv%d_freq", i + 1);
|
|
if (fdt_getprop_u32(working_fdt, nodeoffset, vf_table_sub_key, &val)>0)
|
|
{
|
|
arisc_para->vf[i].freq = val;
|
|
}
|
|
ARISC_INF("%s: freq [%s-%d=%d]\n", __func__, vf_table_sub_key, i, val);
|
|
sprintf(vf_table_sub_key, "lv%d_volt", i + 1);
|
|
if (fdt_getprop_u32(working_fdt, nodeoffset, vf_table_sub_key, &val))
|
|
{
|
|
arisc_para->vf[i].voltage = val;
|
|
}
|
|
ARISC_INF("%s: volt [%s-%d=%d]\n", __func__, vf_table_sub_key, i, val);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int parse_box_start_os0_node(const void*working_fdt,arisc_para_t *arisc_para)
|
|
{
|
|
int nodeoffset;
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt, "/soc/box_start_os0");
|
|
if(nodeoffset < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
arisc_para->start_os.used = fdtdec_get_is_enabled(working_fdt, nodeoffset);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "start_type", &arisc_para->start_os.start_type);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "irkey_used", &arisc_para->start_os.irkey_used);
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "pmukey_used", &arisc_para->start_os.pmukey_used);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int parse_power_mode(const void*working_fdt,arisc_para_t *arisc_para)
|
|
{
|
|
int nodeoffset;
|
|
|
|
nodeoffset = fdt_path_offset(working_fdt, "/soc/target");
|
|
if(nodeoffset < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
fdt_getprop_u32(working_fdt, nodeoffset, "power_mode", &arisc_para->power_mode);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char dtbpath[MAX_PATH]="";
|
|
char scppath[MAX_PATH]="";
|
|
FILE *scp_file;
|
|
char *working_fdt;
|
|
char *working_scp;
|
|
int dtb_len,scp_len,i;
|
|
arisc_para_t *arisc_para;
|
|
|
|
if(argc != 3)
|
|
{
|
|
printf("parameters invalid\n");
|
|
usage();
|
|
return -1;
|
|
}
|
|
|
|
GetFullPath(dtbpath, argv[2]);
|
|
GetFullPath(scppath, argv[1]);
|
|
printf("dtbpath=%s\n", dtbpath);
|
|
printf("scppath=%s\n", scppath);
|
|
|
|
working_fdt = probe_file_data(dtbpath, &dtb_len);
|
|
working_scp = probe_file_data(scppath, &scp_len);
|
|
|
|
if ((working_fdt == NULL) ||(working_scp == NULL))
|
|
{
|
|
printf("file invalid\n");
|
|
return -1;
|
|
}
|
|
|
|
scp_file = fopen(scppath, "wb");
|
|
if (scp_file == NULL)
|
|
{
|
|
printf("file %s cant be opened\n",scppath);
|
|
return -1;
|
|
}
|
|
|
|
arisc_para = (arisc_para_t *)(working_scp+HEADER_OFFSET);
|
|
|
|
parse_arisc_space_node(working_fdt,arisc_para);
|
|
parse_standby_space_node(working_fdt,arisc_para);
|
|
parse_s_uart_node(working_fdt,arisc_para);
|
|
parse_pmu0_node(working_fdt,arisc_para);
|
|
parse_arisc_node(working_fdt,arisc_para);
|
|
parse_s_cir_node(working_fdt,arisc_para);
|
|
parse_dram_node(working_fdt,arisc_para);
|
|
parse_dvfs_table_node(working_fdt,arisc_para);
|
|
parse_box_start_os0_node(working_fdt,arisc_para);
|
|
parse_power_mode(working_fdt,arisc_para);
|
|
|
|
fwrite(working_scp, scp_len, 1, scp_file);
|
|
fclose(scp_file);
|
|
|
|
if (working_fdt)
|
|
free(working_fdt);
|
|
if (working_scp)
|
|
free(working_scp);
|
|
|
|
printf("update scp finish!\n");
|
|
|
|
return 0;
|
|
}
|
|
|