xref: /openbmc/u-boot/cmd/fuse.c (revision a5c289b9bca3805fa35e42f389dc8225c6b916be)
1  /*
2   * (C) Copyright 2009-2013 ADVANSEE
3   * Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
4   *
5   * Based on the mpc512x iim code:
6   * Copyright 2008 Silicon Turnkey Express, Inc.
7   * Martha Marx <mmarx@silicontkx.com>
8   *
9   * SPDX-License-Identifier:	GPL-2.0+
10   */
11  
12  #include <common.h>
13  #include <command.h>
14  #include <console.h>
15  #include <fuse.h>
16  #include <linux/errno.h>
17  
18  static int strtou32(const char *str, unsigned int base, u32 *result)
19  {
20  	char *ep;
21  
22  	*result = simple_strtoul(str, &ep, base);
23  	if (ep == str || *ep != '\0')
24  		return -EINVAL;
25  
26  	return 0;
27  }
28  
29  static int confirm_prog(void)
30  {
31  	puts("Warning: Programming fuses is an irreversible operation!\n"
32  			"         This may brick your system.\n"
33  			"         Use this command only if you are sure of "
34  					"what you are doing!\n"
35  			"\nReally perform this fuse programming? <y/N>\n");
36  
37  	if (confirm_yesno())
38  		return 1;
39  
40  	puts("Fuse programming aborted\n");
41  	return 0;
42  }
43  
44  static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
45  {
46  	const char *op = argc >= 2 ? argv[1] : NULL;
47  	int confirmed = argc >= 3 && !strcmp(argv[2], "-y");
48  	u32 bank, word, cnt, val;
49  	int ret, i;
50  
51  	argc -= 2 + confirmed;
52  	argv += 2 + confirmed;
53  
54  	if (argc < 2 || strtou32(argv[0], 0, &bank) ||
55  			strtou32(argv[1], 0, &word))
56  		return CMD_RET_USAGE;
57  
58  	if (!strcmp(op, "read")) {
59  		if (argc == 2)
60  			cnt = 1;
61  		else if (argc != 3 || strtou32(argv[2], 0, &cnt))
62  			return CMD_RET_USAGE;
63  
64  		printf("Reading bank %u:\n", bank);
65  		for (i = 0; i < cnt; i++, word++) {
66  			if (!(i % 4))
67  				printf("\nWord 0x%.8x:", word);
68  
69  			ret = fuse_read(bank, word, &val);
70  			if (ret)
71  				goto err;
72  
73  			printf(" %.8x", val);
74  		}
75  		putc('\n');
76  	} else if (!strcmp(op, "sense")) {
77  		if (argc == 2)
78  			cnt = 1;
79  		else if (argc != 3 || strtou32(argv[2], 0, &cnt))
80  			return CMD_RET_USAGE;
81  
82  		printf("Sensing bank %u:\n", bank);
83  		for (i = 0; i < cnt; i++, word++) {
84  			if (!(i % 4))
85  				printf("\nWord 0x%.8x:", word);
86  
87  			ret = fuse_sense(bank, word, &val);
88  			if (ret)
89  				goto err;
90  
91  			printf(" %.8x", val);
92  		}
93  		putc('\n');
94  	} else if (!strcmp(op, "prog")) {
95  		if (argc < 3)
96  			return CMD_RET_USAGE;
97  
98  		for (i = 2; i < argc; i++, word++) {
99  			if (strtou32(argv[i], 16, &val))
100  				return CMD_RET_USAGE;
101  
102  			printf("Programming bank %u word 0x%.8x to 0x%.8x...\n",
103  					bank, word, val);
104  			if (!confirmed && !confirm_prog())
105  				return CMD_RET_FAILURE;
106  			ret = fuse_prog(bank, word, val);
107  			if (ret)
108  				goto err;
109  		}
110  	} else if (!strcmp(op, "override")) {
111  		if (argc < 3)
112  			return CMD_RET_USAGE;
113  
114  		for (i = 2; i < argc; i++, word++) {
115  			if (strtou32(argv[i], 16, &val))
116  				return CMD_RET_USAGE;
117  
118  			printf("Overriding bank %u word 0x%.8x with "
119  					"0x%.8x...\n", bank, word, val);
120  			ret = fuse_override(bank, word, val);
121  			if (ret)
122  				goto err;
123  		}
124  	} else {
125  		return CMD_RET_USAGE;
126  	}
127  
128  	return 0;
129  
130  err:
131  	puts("ERROR\n");
132  	return CMD_RET_FAILURE;
133  }
134  
135  U_BOOT_CMD(
136  	fuse, CONFIG_SYS_MAXARGS, 0, do_fuse,
137  	"Fuse sub-system",
138  	     "read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n"
139  	"    starting at 'word'\n"
140  	"fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n"
141  	"    starting at 'word'\n"
142  	"fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n"
143  	"    several fuse words, starting at 'word' (PERMANENT)\n"
144  	"fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n"
145  	"    several fuse words, starting at 'word'"
146  );
147