blob: 816adaefd2e3f38821d49dc7ef49c64612d12bf0 [file] [log] [blame]
/*
* common/cmd_efuse.c
*
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <config.h>
#include <common.h>
#include <asm/arch/io.h>
#include <command.h>
#include <malloc.h>
#include <asm/arch/efuse.h>
#include <asm/arch/bl31_apis.h>
#include <asm/cpu_id.h>
#define CMD_EFUSE_WRITE 0
#define CMD_EFUSE_READ 1
#define CMD_EFUSE_SECURE_BOOT_SET 6
#define CMD_EFUSE_PASSWORD_SET 7
#define CMD_EFUSE_CUSTOMER_ID_SET 8
#define CMD_EFUSE_AMLOGIC_SET 20
int cmd_efuse(int argc, char * const argv[], char *buf)
{
int i, action = -1;
uint32_t offset;
uint32_t size, max_size;
char *end;
char *s;
int ret;
long lAddr1, lAddr2;
if (strncmp(argv[1], "read", 4) == 0) {
action = CMD_EFUSE_READ;
} else if (strncmp(argv[1], "write", 5) == 0) {
action = CMD_EFUSE_WRITE;
} else if (strncmp(argv[1], "secure_boot_set", 15) == 0) {
action = CMD_EFUSE_SECURE_BOOT_SET;
goto efuse_action;
} else if (strncmp(argv[1], "password_set", 12) == 0) {
action = CMD_EFUSE_PASSWORD_SET;
goto efuse_action;
} else if (strncmp(argv[1], "customer_id_set", 15) == 0) {
action = CMD_EFUSE_CUSTOMER_ID_SET;
goto efuse_action;
} else if (strncmp(argv[1], "amlogic_set", 11) == 0) {
action = CMD_EFUSE_AMLOGIC_SET;
goto efuse_action;
} else{
printf("%s arg error\n", argv[1]);
return CMD_RET_USAGE;
}
if ((get_cpu_id().family_id == MESON_CPU_MAJOR_ID_AXG)
&&((action == CMD_EFUSE_READ) || (action == CMD_EFUSE_WRITE))) {
printf("error: AXG not support read/write normal efuse\n");
return -1;
}
if (argc < 4)
return CMD_RET_USAGE;
/*check efuse user data max size*/
offset = simple_strtoul(argv[2], &end, 16);
size = simple_strtoul(argv[3], &end, 16);
printf("%s: offset is %d size is %d\n", __func__, offset, size);
max_size = efuse_get_max();
if (!size) {
printf("\n error: size is zero!!!\n");
return -1;
}
if (offset > max_size) {
printf("\n error: offset is too large!!!\n");
printf("\n offset should be less than %d!\n", max_size);
return -1;
}
if (offset+size > max_size) {
printf("\n error: offset + size is too large!!!\n");
printf("\n offset + size should be less than %d!\n", max_size);
return -1;
}
efuse_action:
/* efuse read */
if (action == CMD_EFUSE_READ) {
memset(buf, 0, size);
ret = efuse_read_usr(buf, size, (loff_t *)&offset);
if (ret == -1) {
printf("ERROR: efuse read user data fail!\n");
return -1;
}
if (ret != size)
printf("ERROR: read %d byte(s) not %d byte(s) data\n",
ret, size);
printf("efuse read data");
for (i = 0; i < size; i++) {
if (i%16 == 0)
printf("\n");
printf(":%02x", buf[i]);
}
printf("\n");
}
/* efuse write */
else if (action == CMD_EFUSE_WRITE) {
if (argc < 5) {
printf("arg count error\n");
return CMD_RET_USAGE;
}
memset(buf, 0, size);
s = argv[4];
memcpy(buf, s, strlen(s));
if (efuse_write_usr(buf, size, (loff_t *)&offset) < 0) {
printf("error: efuse write fail.\n");
return -1;
} else {
printf("%s written done.\n", __func__);
}
} else if (CMD_EFUSE_SECURE_BOOT_SET == action) {
/*efuse secure_boot_set*/
lAddr1 = GXB_IMG_LOAD_ADDR;
if (argc > 2)
lAddr1 = simple_strtoul(argv[2], &end, 16);
lAddr2 = get_sharemem_info(GET_SHARE_MEM_INPUT_BASE);
memcpy((void *)lAddr2, (void *)lAddr1, GXB_EFUSE_PATTERN_SIZE);
flush_cache(lAddr2,GXB_EFUSE_PATTERN_SIZE);
ret = aml_sec_boot_check(AML_D_P_W_EFUSE_SECURE_BOOT, lAddr2,
GXB_EFUSE_PATTERN_SIZE, 0);
if (ret)
printf("aml log : Secure boot EFUSE pattern programming fail [%d]!\n",
ret);
else
printf("aml log : Secure boot EFUSE pattern programming success!\n");
return ret;
} else if (CMD_EFUSE_AMLOGIC_SET == action) {
/*efuse amlogic_set*/
lAddr1 = GXB_IMG_LOAD_ADDR;
if (argc > 2)
lAddr1 = simple_strtoul(argv[2], &end, 16);
lAddr2 = get_sharemem_info(GET_SHARE_MEM_INPUT_BASE);
memcpy((void *)lAddr2, (void *)lAddr1, GXB_EFUSE_PATTERN_SIZE);
flush_cache(lAddr2,GXB_EFUSE_PATTERN_SIZE);
ret = aml_sec_boot_check(AML_D_P_W_EFUSE_AMLOGIC, lAddr2,
GXB_EFUSE_PATTERN_SIZE, 0);
if (ret)
printf("aml log : Amlogic EFUSE pattern programming fail [%d]!\n",
ret);
else
printf("aml log : Amlogic EFUSE pattern programming success!\n");
return ret;
} else if(CMD_EFUSE_PASSWORD_SET == action) {
/*efuse password_set*/
lAddr1 = GXB_IMG_LOAD_ADDR;
if (argc > 2)
lAddr1 = simple_strtoul(argv[2], &end, 16);
lAddr2 = get_sharemem_info(GET_SHARE_MEM_INPUT_BASE);
memcpy((void *)lAddr2, (void *)lAddr1, GXB_EFUSE_PATTERN_SIZE);
flush_cache(lAddr2,GXB_EFUSE_PATTERN_SIZE);
ret = aml_sec_boot_check(AML_D_P_W_EFUSE_PASSWORD, lAddr2,
GXB_EFUSE_PATTERN_SIZE, 0);
if (ret)
printf("aml log : Password EFUSE pattern programming fail [%d]!\n",
ret);
else
printf("aml log : Password EFUSE pattern programming success!\n");
return ret;
}else if(CMD_EFUSE_CUSTOMER_ID_SET == action) {
/*efuse customer_id_set*/
lAddr1 = GXB_IMG_LOAD_ADDR;
if (argc > 2)
lAddr1 = simple_strtoul(argv[2], &end, 16);
lAddr2 = get_sharemem_info(GET_SHARE_MEM_INPUT_BASE);
memcpy((void *)lAddr2, (void *)lAddr1, GXB_EFUSE_PATTERN_SIZE);
flush_cache(lAddr2,GXB_EFUSE_PATTERN_SIZE);
ret = aml_sec_boot_check(AML_D_P_W_EFUSE_CUSTOMER_ID, lAddr2,
GXB_EFUSE_PATTERN_SIZE, 0);
if (ret)
printf("aml log : Customer ID EFUSE pattern programming fail [%d]!\n",
ret);
else
printf("aml log : Customer ID EFUSE pattern programming success!\n");
return ret;
}
return 0;
}
int do_efuse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
char buf[EFUSE_BYTES];
memset(buf, 0, sizeof(buf));
if (argc < 2)
return CMD_RET_USAGE;
return cmd_efuse(argc, argv, buf);
}
static char efuse_help_text[] =
#ifndef CONFIG_AML_MESON_AXG
"[read/write offset size [data]]\n"
" [read/wirte] - read or write 'size' data from\n"
" 'offset' from efuse user data ;\n"
" [offset] - the offset byte from the beginning\n"
" of efuse user data zone;\n"
" [size] - data size\n"
" [data] - the optional argument for 'write',\n"
" data is treated as characters\n"
" examples: efuse write 0xc 0xd abcdABCD1234\n"
#endif
"[amlogic_set addr]\n";
U_BOOT_CMD(
efuse, 5, 1, do_efuse,
"efuse commands", efuse_help_text
);
#include <asm/arch/secure_apb.h>
static int do_query(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int nReturn = CMD_RET_USAGE;
if (argc < 2)
goto exit;
struct{
char *szQuery; unsigned long lAddrConfig; unsigned int nMask; unsigned int nNegFlag;
} ArrQuery[] = {
{"SecureBoot",AO_SEC_SD_CFG10,1<<4,0},//SecureBoot : 1:enabled;0:disabled
{"Dolby",AO_SEC_SD_CFG10,1<<16,0}, //Dolby : 1:enabled; 0: disabled
{"DTS",AO_SEC_SD_CFG10,1<<14,0}, //DTS: 1: enabled; 0:disabled
//add more query support here ...
{NULL,0,0,0}
};
int nIndex;
for (nIndex = 0;nIndex < sizeof(ArrQuery)/sizeof(ArrQuery[0]);++nIndex)
{
if (ArrQuery[nIndex].szQuery)
{
if (!strcmp(ArrQuery[nIndex].szQuery,argv[1]))
{
nReturn = (readl(ArrQuery[nIndex].lAddrConfig) & ArrQuery[nIndex].nMask) ? 1 : 0;
nReturn ^= (ArrQuery[nIndex].nNegFlag ? 1 : 0);
break;
}
}
}
exit:
return nReturn;
}
static char query_text[] =
"[query SecureBoot/Dolby/DTS]\n"
" [SecureBoot] - query SoC is secure boot enabled(1) or not(0)\n"
" [Dolby] - query SoC support Dolby (1) or not(0)\n"
" [DTS] - query SoC support DTS (1) or not(0)\n"
" examples: query SecureBoot\n";
U_BOOT_CMD(
query, 5, 2, do_query,
"SoC query commands", query_text
);
/****************************************************/