forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.3 KiB
145 lines
3.3 KiB
// SPDX-License-Identifier: GPL-2.0+ |
|
/* |
|
* (C) Copyright 2009-2013 ADVANSEE |
|
* Benoît Thébaudeau <[email protected]> |
|
* |
|
* Based on the mpc512x iim code: |
|
* Copyright 2008 Silicon Turnkey Express, Inc. |
|
* Martha Marx <[email protected]> |
|
*/ |
|
|
|
#include <common.h> |
|
#include <command.h> |
|
#include <console.h> |
|
#include <fuse.h> |
|
#include <linux/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 (confirm_yesno()) |
|
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 CMD_RET_FAILURE; |
|
} |
|
|
|
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'" |
|
);
|
|
|