Add fuse API and commands
This can be useful for fuse-like hardware, OTP SoC options, etc. Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
This commit is contained in:
committed by
Stefano Babic
parent
6adbd30203
commit
ccca7dfd02
@@ -111,6 +111,7 @@ ifdef CONFIG_FPGA
|
||||
COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o
|
||||
endif
|
||||
COBJS-$(CONFIG_CMD_FS_GENERIC) += cmd_fs.o
|
||||
COBJS-$(CONFIG_CMD_FUSE) += cmd_fuse.o
|
||||
COBJS-$(CONFIG_CMD_GETTIME) += cmd_gettime.o
|
||||
COBJS-$(CONFIG_CMD_GPIO) += cmd_gpio.o
|
||||
COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o
|
||||
|
||||
168
common/cmd_fuse.c
Normal file
168
common/cmd_fuse.c
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* (C) Copyright 2009-2013 ADVANSEE
|
||||
* Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
|
||||
*
|
||||
* Based on the mpc512x iim code:
|
||||
* Copyright 2008 Silicon Turnkey Express, Inc.
|
||||
* Martha Marx <mmarx@silicontkx.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <fuse.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
static int strtou32(const char *str, unsigned int base, u32 *result)
|
||||
{
|
||||
char *ep;
|
||||
|
||||
*result = simple_strtoul(str, &ep, base);
|
||||
if (ep == str || *ep != '\0')
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int confirm_prog(void)
|
||||
{
|
||||
puts("Warning: Programming fuses is an irreversible operation!\n"
|
||||
" This may brick your system.\n"
|
||||
" Use this command only if you are sure of "
|
||||
"what you are doing!\n"
|
||||
"\nReally perform this fuse programming? <y/N>\n");
|
||||
|
||||
if (getc() == 'y') {
|
||||
int c;
|
||||
|
||||
putc('y');
|
||||
c = getc();
|
||||
putc('\n');
|
||||
if (c == '\r')
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts("Fuse programming aborted\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
const char *op = argc >= 2 ? argv[1] : NULL;
|
||||
int confirmed = argc >= 3 && !strcmp(argv[2], "-y");
|
||||
u32 bank, word, cnt, val;
|
||||
int ret, i;
|
||||
|
||||
argc -= 2 + confirmed;
|
||||
argv += 2 + confirmed;
|
||||
|
||||
if (argc < 2 || strtou32(argv[0], 0, &bank) ||
|
||||
strtou32(argv[1], 0, &word))
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
if (!strcmp(op, "read")) {
|
||||
if (argc == 2)
|
||||
cnt = 1;
|
||||
else if (argc != 3 || strtou32(argv[2], 0, &cnt))
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
printf("Reading bank %u:\n", bank);
|
||||
for (i = 0; i < cnt; i++, word++) {
|
||||
if (!(i % 4))
|
||||
printf("\nWord 0x%.8x:", word);
|
||||
|
||||
ret = fuse_read(bank, word, &val);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
printf(" %.8x", val);
|
||||
}
|
||||
putc('\n');
|
||||
} else if (!strcmp(op, "sense")) {
|
||||
if (argc == 2)
|
||||
cnt = 1;
|
||||
else if (argc != 3 || strtou32(argv[2], 0, &cnt))
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
printf("Sensing bank %u:\n", bank);
|
||||
for (i = 0; i < cnt; i++, word++) {
|
||||
if (!(i % 4))
|
||||
printf("\nWord 0x%.8x:", word);
|
||||
|
||||
ret = fuse_sense(bank, word, &val);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
printf(" %.8x", val);
|
||||
}
|
||||
putc('\n');
|
||||
} else if (!strcmp(op, "prog")) {
|
||||
if (argc < 3)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
for (i = 2; i < argc; i++, word++) {
|
||||
if (strtou32(argv[i], 16, &val))
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
printf("Programming bank %u word 0x%.8x to 0x%.8x...\n",
|
||||
bank, word, val);
|
||||
if (!confirmed && !confirm_prog())
|
||||
return CMD_RET_FAILURE;
|
||||
ret = fuse_prog(bank, word, val);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
} else if (!strcmp(op, "override")) {
|
||||
if (argc < 3)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
for (i = 2; i < argc; i++, word++) {
|
||||
if (strtou32(argv[i], 16, &val))
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
printf("Overriding bank %u word 0x%.8x with "
|
||||
"0x%.8x...\n", bank, word, val);
|
||||
ret = fuse_override(bank, word, val);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
puts("ERROR\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
fuse, CONFIG_SYS_MAXARGS, 0, do_fuse,
|
||||
"Fuse sub-system",
|
||||
"read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n"
|
||||
" starting at 'word'\n"
|
||||
"fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n"
|
||||
" starting at 'word'\n"
|
||||
"fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n"
|
||||
" several fuse words, starting at 'word' (PERMANENT)\n"
|
||||
"fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n"
|
||||
" several fuse words, starting at 'word'"
|
||||
);
|
||||
Reference in New Issue
Block a user