fdt: remove unaligned access in fdt_fixup_ethernet()
[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  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25  * MA 02111-1307 USA
26  */
27
28 #include <common.h>
29 #include <command.h>
30 #include <fuse.h>
31 #include <asm/errno.h>
32
33 static int strtou32(const char *str, unsigned int base, u32 *result)
34 {
35         char *ep;
36
37         *result = simple_strtoul(str, &ep, base);
38         if (ep == str || *ep != '\0')
39                 return -EINVAL;
40
41         return 0;
42 }
43
44 static int confirm_prog(void)
45 {
46         puts("Warning: Programming fuses is an irreversible operation!\n"
47                         "         This may brick your system.\n"
48                         "         Use this command only if you are sure of "
49                                         "what you are doing!\n"
50                         "\nReally perform this fuse programming? <y/N>\n");
51
52         if (getc() == 'y') {
53                 int c;
54
55                 putc('y');
56                 c = getc();
57                 putc('\n');
58                 if (c == '\r')
59                         return 1;
60         }
61
62         puts("Fuse programming aborted\n");
63         return 0;
64 }
65
66 static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
67 {
68         const char *op = argc >= 2 ? argv[1] : NULL;
69         int confirmed = argc >= 3 && !strcmp(argv[2], "-y");
70         u32 bank, word, cnt, val;
71         int ret, i;
72
73         argc -= 2 + confirmed;
74         argv += 2 + confirmed;
75
76         if (argc < 2 || strtou32(argv[0], 0, &bank) ||
77                         strtou32(argv[1], 0, &word))
78                 return CMD_RET_USAGE;
79
80         if (!strcmp(op, "read")) {
81                 if (argc == 2)
82                         cnt = 1;
83                 else if (argc != 3 || strtou32(argv[2], 0, &cnt))
84                         return CMD_RET_USAGE;
85
86                 printf("Reading bank %u:\n", bank);
87                 for (i = 0; i < cnt; i++, word++) {
88                         if (!(i % 4))
89                                 printf("\nWord 0x%.8x:", word);
90
91                         ret = fuse_read(bank, word, &val);
92                         if (ret)
93                                 goto err;
94
95                         printf(" %.8x", val);
96                 }
97                 putc('\n');
98         } else if (!strcmp(op, "sense")) {
99                 if (argc == 2)
100                         cnt = 1;
101                 else if (argc != 3 || strtou32(argv[2], 0, &cnt))
102                         return CMD_RET_USAGE;
103
104                 printf("Sensing bank %u:\n", bank);
105                 for (i = 0; i < cnt; i++, word++) {
106                         if (!(i % 4))
107                                 printf("\nWord 0x%.8x:", word);
108
109                         ret = fuse_sense(bank, word, &val);
110                         if (ret)
111                                 goto err;
112
113                         printf(" %.8x", val);
114                 }
115                 putc('\n');
116         } else if (!strcmp(op, "prog")) {
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("Programming bank %u word 0x%.8x to 0x%.8x...\n",
125                                         bank, word, val);
126                         if (!confirmed && !confirm_prog())
127                                 return CMD_RET_FAILURE;
128                         ret = fuse_prog(bank, word, val);
129                         if (ret)
130                                 goto err;
131                 }
132         } else if (!strcmp(op, "override")) {
133                 if (argc < 3)
134                         return CMD_RET_USAGE;
135
136                 for (i = 2; i < argc; i++, word++) {
137                         if (strtou32(argv[i], 16, &val))
138                                 return CMD_RET_USAGE;
139
140                         printf("Overriding bank %u word 0x%.8x with "
141                                         "0x%.8x...\n", bank, word, val);
142                         ret = fuse_override(bank, word, val);
143                         if (ret)
144                                 goto err;
145                 }
146         } else {
147                 return CMD_RET_USAGE;
148         }
149
150         return 0;
151
152 err:
153         puts("ERROR\n");
154         return ret;
155 }
156
157 U_BOOT_CMD(
158         fuse, CONFIG_SYS_MAXARGS, 0, do_fuse,
159         "Fuse sub-system",
160              "read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n"
161         "    starting at 'word'\n"
162         "fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n"
163         "    starting at 'word'\n"
164         "fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n"
165         "    several fuse words, starting at 'word' (PERMANENT)\n"
166         "fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n"
167         "    several fuse words, starting at 'word'"
168 );