mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-31 03:58:17 +00:00 
			
		
		
		
	Signed-off-by: Wolfgang Denk <wd@denx.de> [trini: Fixup common/cmd_io.c] Signed-off-by: Tom Rini <trini@ti.com>
		
			
				
	
	
		
			153 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * (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>
 | |
|  *
 | |
|  * SPDX-License-Identifier:	GPL-2.0+
 | |
|  */
 | |
| 
 | |
| #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'"
 | |
| );
 |