diff options
| author | Benoît Thébaudeau <benoit.thebaudeau@advansee.com> | 2013-04-23 10:17:40 +0000 | 
|---|---|---|
| committer | Stefano Babic <sbabic@denx.de> | 2013-04-28 11:07:40 +0200 | 
| commit | ccca7dfd0273af41e5b4bdec7f8731b177a20fde (patch) | |
| tree | 015f9912580d549ea1605d967d9ea56adf4ca161 /common/cmd_fuse.c | |
| parent | 6adbd30203a2839894d9b61f810d9fedc25a64ff (diff) | |
| download | olio-uboot-2014.01-ccca7dfd0273af41e5b4bdec7f8731b177a20fde.tar.xz olio-uboot-2014.01-ccca7dfd0273af41e5b4bdec7f8731b177a20fde.zip | |
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>
Diffstat (limited to 'common/cmd_fuse.c')
| -rw-r--r-- | common/cmd_fuse.c | 168 | 
1 files changed, 168 insertions, 0 deletions
| diff --git a/common/cmd_fuse.c b/common/cmd_fuse.c new file mode 100644 index 000000000..f24c01c2d --- /dev/null +++ b/common/cmd_fuse.c @@ -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'" +); |