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