Merge branch '2019-07-11-master-imports'
[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(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
44 {
45         const char *op = argc >= 2 ? argv[1] : NULL;
46         int confirmed = argc >= 3 && !strcmp(argv[2], "-y");
47         u32 bank, word, cnt, val;
48         int ret, i;
49
50         argc -= 2 + confirmed;
51         argv += 2 + confirmed;
52
53         if (argc < 2 || strtou32(argv[0], 0, &bank) ||
54                         strtou32(argv[1], 0, &word))
55                 return CMD_RET_USAGE;
56
57         if (!strcmp(op, "read")) {
58                 if (argc == 2)
59                         cnt = 1;
60                 else if (argc != 3 || strtou32(argv[2], 0, &cnt))
61                         return CMD_RET_USAGE;
62
63                 printf("Reading bank %u:\n", bank);
64                 for (i = 0; i < cnt; i++, word++) {
65                         if (!(i % 4))
66                                 printf("\nWord 0x%.8x:", word);
67
68                         ret = fuse_read(bank, word, &val);
69                         if (ret)
70                                 goto err;
71
72                         printf(" %.8x", val);
73                 }
74                 putc('\n');
75         } else if (!strcmp(op, "sense")) {
76                 if (argc == 2)
77                         cnt = 1;
78                 else if (argc != 3 || strtou32(argv[2], 0, &cnt))
79                         return CMD_RET_USAGE;
80
81                 printf("Sensing bank %u:\n", bank);
82                 for (i = 0; i < cnt; i++, word++) {
83                         if (!(i % 4))
84                                 printf("\nWord 0x%.8x:", word);
85
86                         ret = fuse_sense(bank, word, &val);
87                         if (ret)
88                                 goto err;
89
90                         printf(" %.8x", val);
91                 }
92                 putc('\n');
93         } else if (!strcmp(op, "prog")) {
94                 if (argc < 3)
95                         return CMD_RET_USAGE;
96
97                 for (i = 2; i < argc; i++, word++) {
98                         if (strtou32(argv[i], 16, &val))
99                                 return CMD_RET_USAGE;
100
101                         printf("Programming bank %u word 0x%.8x to 0x%.8x...\n",
102                                         bank, word, val);
103                         if (!confirmed && !confirm_prog())
104                                 return CMD_RET_FAILURE;
105                         ret = fuse_prog(bank, word, val);
106                         if (ret)
107                                 goto err;
108                 }
109         } else if (!strcmp(op, "override")) {
110                 if (argc < 3)
111                         return CMD_RET_USAGE;
112
113                 for (i = 2; i < argc; i++, word++) {
114                         if (strtou32(argv[i], 16, &val))
115                                 return CMD_RET_USAGE;
116
117                         printf("Overriding bank %u word 0x%.8x with "
118                                         "0x%.8x...\n", bank, word, val);
119                         ret = fuse_override(bank, word, val);
120                         if (ret)
121                                 goto err;
122                 }
123         } else {
124                 return CMD_RET_USAGE;
125         }
126
127         return 0;
128
129 err:
130         puts("ERROR\n");
131         return CMD_RET_FAILURE;
132 }
133
134 U_BOOT_CMD(
135         fuse, CONFIG_SYS_MAXARGS, 0, do_fuse,
136         "Fuse sub-system",
137              "read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n"
138         "    starting at 'word'\n"
139         "fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n"
140         "    starting at 'word'\n"
141         "fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n"
142         "    several fuse words, starting at 'word' (PERMANENT)\n"
143         "fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n"
144         "    several fuse words, starting at 'word'"
145 );