3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 #if (CONFIG_COMMANDS & CFG_CMD_FLASH)
34 extern flash_info_t flash_info[]; /* info for FLASH chips */
37 * The user interface starts numbering for Flash banks with 1
38 * for historical reasons.
42 * this routine looks for an abbreviated flash range specification.
43 * the syntax is B:SF[-SL], where B is the bank number, SF is the first
44 * sector to erase, and SL is the last sector to erase (defaults to SF).
45 * bank numbers start at 1 to be consistent with other specs, sector numbers
48 * returns: 1 - correct spec; *pinfo, *psf and *psl are
50 * 0 - doesn't look like an abbreviated spec
51 * -1 - looks like an abbreviated spec, but got
52 * a parsing error, a number out of range,
53 * or an invalid flash bank.
56 abbrev_spec(char *str, flash_info_t **pinfo, int *psf, int *psl)
59 int bank, first, last;
62 if ((p = strchr(str, ':')) == NULL)
66 bank = simple_strtoul(str, &ep, 10);
67 if (ep == str || *ep != '\0' ||
68 bank < 1 || bank > CFG_MAX_FLASH_BANKS ||
69 (fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN)
73 if ((p = strchr(str, '-')) != NULL)
76 first = simple_strtoul(str, &ep, 10);
77 if (ep == str || *ep != '\0' || first >= fp->sector_count)
81 last = simple_strtoul(p, &ep, 10);
82 if (ep == p || *ep != '\0' ||
83 last < first || last >= fp->sector_count)
95 int do_flinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
99 if (argc == 1) { /* print info for all FLASH banks */
100 for (bank=0; bank <CFG_MAX_FLASH_BANKS; ++bank) {
101 printf ("\nBank # %ld: ", bank+1);
103 flash_print_info (&flash_info[bank]);
108 bank = simple_strtoul(argv[1], NULL, 16);
109 if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
110 printf ("Only FLASH Banks # 1 ... # %d supported\n",
111 CFG_MAX_FLASH_BANKS);
114 printf ("\nBank # %ld: ", bank);
115 flash_print_info (&flash_info[bank-1]);
118 int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
121 ulong bank, addr_first, addr_last;
122 int n, sect_first, sect_last;
126 printf ("Usage:\n%s\n", cmdtp->usage);
130 if (strcmp(argv[1], "all") == 0) {
131 for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank) {
132 printf ("Erase Flash Bank # %ld ", bank);
133 info = &flash_info[bank-1];
134 rcode = flash_erase (info, 0, info->sector_count-1);
139 if ((n = abbrev_spec(argv[1], &info, §_first, §_last)) != 0) {
141 printf("Bad sector specification\n");
144 printf ("Erase Flash Sectors %d-%d in Bank # %d ",
145 sect_first, sect_last, (info-flash_info)+1);
146 rcode = flash_erase(info, sect_first, sect_last);
151 printf ("Usage:\n%s\n", cmdtp->usage);
155 if (strcmp(argv[1], "bank") == 0) {
156 bank = simple_strtoul(argv[2], NULL, 16);
157 if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
158 printf ("Only FLASH Banks # 1 ... # %d supported\n",
159 CFG_MAX_FLASH_BANKS);
162 printf ("Erase Flash Bank # %ld ", bank);
163 info = &flash_info[bank-1];
164 rcode = flash_erase (info, 0, info->sector_count-1);
168 addr_first = simple_strtoul(argv[1], NULL, 16);
169 addr_last = simple_strtoul(argv[2], NULL, 16);
171 if (addr_first >= addr_last) {
172 printf ("Usage:\n%s\n", cmdtp->usage);
176 printf ("Erase Flash from 0x%08lx to 0x%08lx ", addr_first, addr_last);
177 rcode = flash_sect_erase(addr_first, addr_last);
181 int flash_sect_erase (ulong addr_first, ulong addr_last)
191 for (bank=0,info=&flash_info[0]; bank < CFG_MAX_FLASH_BANKS; ++bank, ++info) {
195 if (info->flash_id == FLASH_UNKNOWN) {
199 b_end = info->start[0] + info->size - 1; /* bank end addr */
201 s_first = -1; /* first sector to erase */
202 s_last = -1; /* last sector to erase */
204 for (sect=0; sect < info->sector_count; ++sect) {
205 ulong end; /* last address in current sect */
208 s_end = info->sector_count - 1;
210 end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
212 if (addr_first > end)
214 if (addr_last < info->start[sect])
217 if (addr_first == info->start[sect]) {
220 if (addr_last == end) {
224 if (s_first>=0 && s_first<=s_last) {
225 erased += s_last - s_first + 1;
226 rcode = flash_erase (info, s_first, s_last);
230 printf ("Erased %d sectors\n", erased);
232 printf ("Error: start and/or end address"
233 " not on sector boundary\n");
240 int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
243 ulong bank, addr_first, addr_last;
244 int i, p, n, sect_first, sect_last;
248 printf ("Usage:\n%s\n", cmdtp->usage);
252 if (strcmp(argv[1], "off") == 0)
254 else if (strcmp(argv[1], "on") == 0)
257 printf ("Usage:\n%s\n", cmdtp->usage);
261 if (strcmp(argv[2], "all") == 0) {
262 for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank) {
263 info = &flash_info[bank-1];
264 if (info->flash_id == FLASH_UNKNOWN) {
267 printf ("%sProtect Flash Bank # %ld\n",
268 p ? "" : "Un-", bank);
270 for (i=0; i<info->sector_count; ++i) {
271 #if defined(CFG_FLASH_PROTECTION)
272 if (flash_real_protect(info, i, p))
276 info->protect[i] = p;
277 #endif /* CFG_FLASH_PROTECTION */
281 #if defined(CFG_FLASH_PROTECTION)
282 if (!rcode) puts (" done\n");
283 #endif /* CFG_FLASH_PROTECTION */
288 if ((n = abbrev_spec(argv[2], &info, §_first, §_last)) != 0) {
290 printf("Bad sector specification\n");
293 printf("%sProtect Flash Sectors %d-%d in Bank # %d\n",
294 p ? "" : "Un-", sect_first, sect_last,
295 (info-flash_info)+1);
296 for (i = sect_first; i <= sect_last; i++) {
297 #if defined(CFG_FLASH_PROTECTION)
298 if (flash_real_protect(info, i, p))
302 info->protect[i] = p;
303 #endif /* CFG_FLASH_PROTECTION */
306 #if defined(CFG_FLASH_PROTECTION)
307 if (!rcode) puts (" done\n");
308 #endif /* CFG_FLASH_PROTECTION */
314 printf ("Usage:\n%s\n", cmdtp->usage);
318 if (strcmp(argv[2], "bank") == 0) {
319 bank = simple_strtoul(argv[3], NULL, 16);
320 if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
321 printf ("Only FLASH Banks # 1 ... # %d supported\n",
322 CFG_MAX_FLASH_BANKS);
325 printf ("%sProtect Flash Bank # %ld\n",
326 p ? "" : "Un-", bank);
327 info = &flash_info[bank-1];
329 if (info->flash_id == FLASH_UNKNOWN) {
330 printf ("missing or unknown FLASH type\n");
333 for (i=0; i<info->sector_count; ++i) {
334 #if defined(CFG_FLASH_PROTECTION)
335 if (flash_real_protect(info, i, p))
339 info->protect[i] = p;
340 #endif /* CFG_FLASH_PROTECTION */
343 #if defined(CFG_FLASH_PROTECTION)
344 if (!rcode) puts (" done\n");
345 #endif /* CFG_FLASH_PROTECTION */
350 addr_first = simple_strtoul(argv[2], NULL, 16);
351 addr_last = simple_strtoul(argv[3], NULL, 16);
353 if (addr_first >= addr_last) {
354 printf ("Usage:\n%s\n", cmdtp->usage);
357 rcode = flash_sect_protect (p, addr_first, addr_last);
362 int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
372 for (bank=0,info=&flash_info[0]; bank < CFG_MAX_FLASH_BANKS; ++bank, ++info) {
376 if (info->flash_id == FLASH_UNKNOWN) {
380 b_end = info->start[0] + info->size - 1; /* bank end addr */
382 s_first = -1; /* first sector to erase */
383 s_last = -1; /* last sector to erase */
385 for (sect=0; sect < info->sector_count; ++sect) {
386 ulong end; /* last address in current sect */
389 s_end = info->sector_count - 1;
391 end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
393 if (addr_first > end)
395 if (addr_last < info->start[sect])
398 if (addr_first == info->start[sect]) {
401 if (addr_last == end) {
405 if (s_first>=0 && s_first<=s_last) {
406 protected += s_last - s_first + 1;
407 for (i=s_first; i<=s_last; ++i) {
408 #if defined(CFG_FLASH_PROTECTION)
409 if (flash_real_protect(info, i, p))
413 info->protect[i] = p;
414 #endif /* CFG_FLASH_PROTECTION */
417 #if defined(CFG_FLASH_PROTECTION)
418 if (!rcode) putc ('\n');
419 #endif /* CFG_FLASH_PROTECTION */
423 printf ("%sProtected %d sectors\n",
424 p ? "" : "Un-", protected);
426 printf ("Error: start and/or end address"
427 " not on sector boundary\n");
433 #endif /* CFG_CMD_FLASH */