u-boot/cmd/fuse.c
Harsha Vardhan V M 578e7882bf cmd: fuse: Add fuse writebuff sub-system command
Add CMD_FUSE_WRITEBUFF config option to add and enable fuse writebuff
sub-system command. Add fuse_writebuff function to be invoked on
writebuff command.

Signed-off-by: Harsha Vardhan V M <h-vm@ti.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
2025-04-04 12:25:02 -06:00

210 lines
5 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* (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>
*/
#include <command.h>
#include <console.h>
#include <fuse.h>
#include <mapmem.h>
#include <vsprintf.h>
#include <linux/errno.h>
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(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
const char *op = cmd_arg1(argc, argv);
int confirmed = argc >= 3 && !strcmp(argv[2], "-y");
u32 bank, word, cnt, val, cmp;
ulong addr;
void *buf, *start;
int ret, i;
argc -= 2 + confirmed;
argv += 2 + confirmed;
if (IS_ENABLED(CONFIG_CMD_FUSE_WRITEBUFF) && !strcmp(op, "writebuff")) {
if (argc == 1)
addr = simple_strtoul(argv[0], NULL, 16);
else
return CMD_RET_USAGE;
} else {
if (argc < 2)
return CMD_RET_USAGE;
bank = simple_strtoul(argv[0], NULL, 0);
word = simple_strtoul(argv[1], NULL, 0);
}
if (!strcmp(op, "read")) {
if (argc == 2)
cnt = 1;
else if (argc == 3)
cnt = simple_strtoul(argv[2], NULL, 0);
else
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, "readm")) {
if (argc == 3)
cnt = 1;
else if (argc == 4)
cnt = simple_strtoul(argv[3], NULL, 0);
else
return CMD_RET_USAGE;
addr = simple_strtoul(argv[2], NULL, 16);
start = map_sysmem(addr, 4);
buf = start;
printf("Reading bank %u len %u to 0x%lx\n", bank, cnt, addr);
for (i = 0; i < cnt; i++, word++) {
ret = fuse_read(bank, word, &val);
if (ret)
goto err;
*((u32 *)buf) = val;
buf += 4;
}
unmap_sysmem(start);
} else if (!strcmp(op, "cmp")) {
if (argc == 3)
cmp = simple_strtoul(argv[2], NULL, 0);
else
return CMD_RET_USAGE;
printf("Comparing bank %u:\n", bank);
printf("\nWord 0x%.8x:", word);
printf("\nValue 0x%.8x:", cmp);
ret = fuse_read(bank, word, &val);
if (ret)
goto err;
printf("0x%.8x\n", val);
if (val != cmp) {
printf("failed\n");
return CMD_RET_FAILURE;
}
printf("passed\n");
} else if (!strcmp(op, "sense")) {
if (argc == 2)
cnt = 1;
else if (argc == 3)
cnt = simple_strtoul(argv[2], NULL, 0);
else
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++) {
val = simple_strtoul(argv[i], NULL, 16);
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++) {
val = simple_strtoul(argv[i], NULL, 16);
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 if (IS_ENABLED(CONFIG_CMD_FUSE_WRITEBUFF) && !strcmp(op, "writebuff")) {
printf("Programming fuses using a structured buffer in memory "
"starting at addr 0x%lx\n", addr);
if (!confirmed && !confirm_prog())
return CMD_RET_FAILURE;
ret = fuse_writebuff(addr);
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 cmp <bank> <word> <hexval> - compare 'hexval' to fuse\n"
" at 'word'\n"
"fuse readm <bank> <word> <addr> [<cnt>] - read 1 or 'cnt' fuse words,\n"
" starting at 'word' into memory at 'addr'\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'\n"
#ifdef CONFIG_CMD_FUSE_WRITEBUFF
"fuse writebuff [-y] <addr> - program fuse data\n"
" using a structured buffer in memory starting at 'addr'\n"
#endif /* CONFIG_CMD_FUSE_WRITEBUFF */
);