cmd: fuse: add a fuse comparison function
[platform/kernel/u-boot.git] / cmd / fuse.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2009-2013 ADVANSEE
4  * Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
5  *
6  * Based on the mpc512x iim code:
7  * Copyright 2008 Silicon Turnkey Express, Inc.
8  * Martha Marx <mmarx@silicontkx.com>
9  */
10
11 #include <common.h>
12 #include <command.h>
13 #include <console.h>
14 #include <fuse.h>
15 #include <linux/errno.h>
16
17 static int strtou32(const char *str, unsigned int base, u32 *result)
18 {
19         char *ep;
20
21         *result = simple_strtoul(str, &ep, base);
22         if (ep == str || *ep != '\0')
23                 return -EINVAL;
24
25         return 0;
26 }
27
28 static int confirm_prog(void)
29 {
30         puts("Warning: Programming fuses is an irreversible operation!\n"
31                         "         This may brick your system.\n"
32                         "         Use this command only if you are sure of "
33                                         "what you are doing!\n"
34                         "\nReally perform this fuse programming? <y/N>\n");
35
36         if (confirm_yesno())
37                 return 1;
38
39         puts("Fuse programming aborted\n");
40         return 0;
41 }
42
43 static int do_fuse(struct cmd_tbl *cmdtp, int flag, int argc,
44                    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, cmp;
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, "cmp")) {
77                 if (argc != 3 || strtou32(argv[2], 0, &cmp))
78                         return CMD_RET_USAGE;
79
80                 printf("Comparing bank %u:\n", bank);
81                 printf("\nWord 0x%.8x:", word);
82                 printf("\nValue 0x%.8x:", cmp);
83
84                 ret = fuse_read(bank, word, &val);
85                 if (ret)
86                         goto err;
87
88                 printf("0x%.8x\n", val);
89                 if (val != cmp) {
90                         printf("failed\n");
91                         return CMD_RET_FAILURE;
92                 }
93                 printf("passed\n");
94         } else if (!strcmp(op, "sense")) {
95                 if (argc == 2)
96                         cnt = 1;
97                 else if (argc != 3 || strtou32(argv[2], 0, &cnt))
98                         return CMD_RET_USAGE;
99
100                 printf("Sensing bank %u:\n", bank);
101                 for (i = 0; i < cnt; i++, word++) {
102                         if (!(i % 4))
103                                 printf("\nWord 0x%.8x:", word);
104
105                         ret = fuse_sense(bank, word, &val);
106                         if (ret)
107                                 goto err;
108
109                         printf(" %.8x", val);
110                 }
111                 putc('\n');
112         } else if (!strcmp(op, "prog")) {
113                 if (argc < 3)
114                         return CMD_RET_USAGE;
115
116                 for (i = 2; i < argc; i++, word++) {
117                         if (strtou32(argv[i], 16, &val))
118                                 return CMD_RET_USAGE;
119
120                         printf("Programming bank %u word 0x%.8x to 0x%.8x...\n",
121                                         bank, word, val);
122                         if (!confirmed && !confirm_prog())
123                                 return CMD_RET_FAILURE;
124                         ret = fuse_prog(bank, word, val);
125                         if (ret)
126                                 goto err;
127                 }
128         } else if (!strcmp(op, "override")) {
129                 if (argc < 3)
130                         return CMD_RET_USAGE;
131
132                 for (i = 2; i < argc; i++, word++) {
133                         if (strtou32(argv[i], 16, &val))
134                                 return CMD_RET_USAGE;
135
136                         printf("Overriding bank %u word 0x%.8x with "
137                                         "0x%.8x...\n", bank, word, val);
138                         ret = fuse_override(bank, word, val);
139                         if (ret)
140                                 goto err;
141                 }
142         } else {
143                 return CMD_RET_USAGE;
144         }
145
146         return 0;
147
148 err:
149         puts("ERROR\n");
150         return CMD_RET_FAILURE;
151 }
152
153 U_BOOT_CMD(
154         fuse, CONFIG_SYS_MAXARGS, 0, do_fuse,
155         "Fuse sub-system",
156              "read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n"
157         "    starting at 'word'\n"
158         "fuse cmp <bank> <word> <hexval> - compare 'hexval' to fuse\n"
159         "    at 'word'\n"
160         "fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n"
161         "    starting at 'word'\n"
162         "fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n"
163         "    several fuse words, starting at 'word' (PERMANENT)\n"
164         "fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n"
165         "    several fuse words, starting at 'word'"
166 );