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 #ifdef CONFIG_HAS_DATAFLASH
33 #include <dataflash.h>
36 #if (CONFIG_COMMANDS & CFG_CMD_FLASH)
38 extern flash_info_t flash_info[]; /* info for FLASH chips */
41 * The user interface starts numbering for Flash banks with 1
42 * for historical reasons.
46 * this routine looks for an abbreviated flash range specification.
47 * the syntax is B:SF[-SL], where B is the bank number, SF is the first
48 * sector to erase, and SL is the last sector to erase (defaults to SF).
49 * bank numbers start at 1 to be consistent with other specs, sector numbers
52 * returns: 1 - correct spec; *pinfo, *psf and *psl are
54 * 0 - doesn't look like an abbreviated spec
55 * -1 - looks like an abbreviated spec, but got
56 * a parsing error, a number out of range,
57 * or an invalid flash bank.
60 abbrev_spec(char *str, flash_info_t **pinfo, int *psf, int *psl)
63 int bank, first, last;
66 if ((p = strchr(str, ':')) == NULL)
70 bank = simple_strtoul(str, &ep, 10);
71 if (ep == str || *ep != '\0' ||
72 bank < 1 || bank > CFG_MAX_FLASH_BANKS ||
73 (fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN)
77 if ((p = strchr(str, '-')) != NULL)
80 first = simple_strtoul(str, &ep, 10);
81 if (ep == str || *ep != '\0' || first >= fp->sector_count)
85 last = simple_strtoul(p, &ep, 10);
86 if (ep == p || *ep != '\0' ||
87 last < first || last >= fp->sector_count)
99 int do_flinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
103 #ifdef CONFIG_HAS_DATAFLASH
104 dataflash_print_info();
107 if (argc == 1) { /* print info for all FLASH banks */
108 for (bank=0; bank <CFG_MAX_FLASH_BANKS; ++bank) {
109 printf ("\nBank # %ld: ", bank+1);
111 flash_print_info (&flash_info[bank]);
116 bank = simple_strtoul(argv[1], NULL, 16);
117 if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
118 printf ("Only FLASH Banks # 1 ... # %d supported\n",
119 CFG_MAX_FLASH_BANKS);
122 printf ("\nBank # %ld: ", bank);
123 flash_print_info (&flash_info[bank-1]);
126 int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
129 ulong bank, addr_first, addr_last;
130 int n, sect_first, sect_last;
134 printf ("Usage:\n%s\n", cmdtp->usage);
138 if (strcmp(argv[1], "all") == 0) {
139 for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank) {
140 printf ("Erase Flash Bank # %ld ", bank);
141 info = &flash_info[bank-1];
142 rcode = flash_erase (info, 0, info->sector_count-1);
147 if ((n = abbrev_spec(argv[1], &info, §_first, §_last)) != 0) {
149 printf("Bad sector specification\n");
152 printf ("Erase Flash Sectors %d-%d in Bank # %d ",
153 sect_first, sect_last, (info-flash_info)+1);
154 rcode = flash_erase(info, sect_first, sect_last);
159 printf ("Usage:\n%s\n", cmdtp->usage);
163 if (strcmp(argv[1], "bank") == 0) {
164 bank = simple_strtoul(argv[2], NULL, 16);
165 if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
166 printf ("Only FLASH Banks # 1 ... # %d supported\n",
167 CFG_MAX_FLASH_BANKS);
170 printf ("Erase Flash Bank # %ld ", bank);
171 info = &flash_info[bank-1];
172 rcode = flash_erase (info, 0, info->sector_count-1);
176 addr_first = simple_strtoul(argv[1], NULL, 16);
177 addr_last = simple_strtoul(argv[2], NULL, 16);
179 if (addr_first >= addr_last) {
180 printf ("Usage:\n%s\n", cmdtp->usage);
184 printf ("Erase Flash from 0x%08lx to 0x%08lx ", addr_first, addr_last);
185 rcode = flash_sect_erase(addr_first, addr_last);
189 int flash_sect_erase (ulong addr_first, ulong addr_last)
199 for (bank=0,info=&flash_info[0]; bank < CFG_MAX_FLASH_BANKS; ++bank, ++info) {
203 if (info->flash_id == FLASH_UNKNOWN) {
207 b_end = info->start[0] + info->size - 1; /* bank end addr */
209 s_first = -1; /* first sector to erase */
210 s_last = -1; /* last sector to erase */
212 for (sect=0; sect < info->sector_count; ++sect) {
213 ulong end; /* last address in current sect */
216 s_end = info->sector_count - 1;
218 end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
220 if (addr_first > end)
222 if (addr_last < info->start[sect])
225 if (addr_first == info->start[sect]) {
228 if (addr_last == end) {
232 if (s_first>=0 && s_first<=s_last) {
233 erased += s_last - s_first + 1;
234 rcode = flash_erase (info, s_first, s_last);
238 printf ("Erased %d sectors\n", erased);
240 printf ("Error: start and/or end address"
241 " not on sector boundary\n");
248 int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
251 ulong bank, addr_first, addr_last;
252 int i, p, n, sect_first, sect_last;
256 printf ("Usage:\n%s\n", cmdtp->usage);
260 if (strcmp(argv[1], "off") == 0)
262 else if (strcmp(argv[1], "on") == 0)
265 printf ("Usage:\n%s\n", cmdtp->usage);
269 if (strcmp(argv[2], "all") == 0) {
270 for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank) {
271 info = &flash_info[bank-1];
272 if (info->flash_id == FLASH_UNKNOWN) {
275 printf ("%sProtect Flash Bank # %ld\n",
276 p ? "" : "Un-", bank);
278 for (i=0; i<info->sector_count; ++i) {
279 #if defined(CFG_FLASH_PROTECTION)
280 if (flash_real_protect(info, i, p))
284 info->protect[i] = p;
285 #endif /* CFG_FLASH_PROTECTION */
289 #if defined(CFG_FLASH_PROTECTION)
290 if (!rcode) puts (" done\n");
291 #endif /* CFG_FLASH_PROTECTION */
296 if ((n = abbrev_spec(argv[2], &info, §_first, §_last)) != 0) {
298 printf("Bad sector specification\n");
301 printf("%sProtect Flash Sectors %d-%d in Bank # %d\n",
302 p ? "" : "Un-", sect_first, sect_last,
303 (info-flash_info)+1);
304 for (i = sect_first; i <= sect_last; i++) {
305 #if defined(CFG_FLASH_PROTECTION)
306 if (flash_real_protect(info, i, p))
310 info->protect[i] = p;
311 #endif /* CFG_FLASH_PROTECTION */
314 #if defined(CFG_FLASH_PROTECTION)
315 if (!rcode) puts (" done\n");
316 #endif /* CFG_FLASH_PROTECTION */
322 printf ("Usage:\n%s\n", cmdtp->usage);
326 if (strcmp(argv[2], "bank") == 0) {
327 bank = simple_strtoul(argv[3], NULL, 16);
328 if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
329 printf ("Only FLASH Banks # 1 ... # %d supported\n",
330 CFG_MAX_FLASH_BANKS);
333 printf ("%sProtect Flash Bank # %ld\n",
334 p ? "" : "Un-", bank);
335 info = &flash_info[bank-1];
337 if (info->flash_id == FLASH_UNKNOWN) {
338 printf ("missing or unknown FLASH type\n");
341 for (i=0; i<info->sector_count; ++i) {
342 #if defined(CFG_FLASH_PROTECTION)
343 if (flash_real_protect(info, i, p))
347 info->protect[i] = p;
348 #endif /* CFG_FLASH_PROTECTION */
351 #if defined(CFG_FLASH_PROTECTION)
352 if (!rcode) puts (" done\n");
353 #endif /* CFG_FLASH_PROTECTION */
358 addr_first = simple_strtoul(argv[2], NULL, 16);
359 addr_last = simple_strtoul(argv[3], NULL, 16);
361 if (addr_first >= addr_last) {
362 printf ("Usage:\n%s\n", cmdtp->usage);
365 rcode = flash_sect_protect (p, addr_first, addr_last);
370 int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
380 for (bank=0,info=&flash_info[0]; bank < CFG_MAX_FLASH_BANKS; ++bank, ++info) {
384 if (info->flash_id == FLASH_UNKNOWN) {
388 b_end = info->start[0] + info->size - 1; /* bank end addr */
390 s_first = -1; /* first sector to erase */
391 s_last = -1; /* last sector to erase */
393 for (sect=0; sect < info->sector_count; ++sect) {
394 ulong end; /* last address in current sect */
397 s_end = info->sector_count - 1;
399 end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
401 if (addr_first > end)
403 if (addr_last < info->start[sect])
406 if (addr_first == info->start[sect]) {
409 if (addr_last == end) {
413 if (s_first>=0 && s_first<=s_last) {
414 protected += s_last - s_first + 1;
415 for (i=s_first; i<=s_last; ++i) {
416 #if defined(CFG_FLASH_PROTECTION)
417 if (flash_real_protect(info, i, p))
421 info->protect[i] = p;
422 #endif /* CFG_FLASH_PROTECTION */
425 #if defined(CFG_FLASH_PROTECTION)
426 if (!rcode) putc ('\n');
427 #endif /* CFG_FLASH_PROTECTION */
431 printf ("%sProtected %d sectors\n",
432 p ? "" : "Un-", protected);
434 printf ("Error: start and/or end address"
435 " not on sector boundary\n");
441 #endif /* CFG_CMD_FLASH */