3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * SPDX-License-Identifier: GPL-2.0+
15 #if defined(CONFIG_CMD_FLASH)
17 extern flash_info_t flash_info[]; /* info for FLASH chips */
20 * The user interface starts numbering for Flash banks with 1
21 * for historical reasons.
25 * this routine looks for an abbreviated flash range specification.
26 * the syntax is B:SF[-SL], where B is the bank number, SF is the first
27 * sector to erase, and SL is the last sector to erase (defaults to SF).
28 * bank numbers start at 1 to be consistent with other specs, sector numbers
31 * returns: 1 - correct spec; *pinfo, *psf and *psl are
33 * 0 - doesn't look like an abbreviated spec
34 * -1 - looks like an abbreviated spec, but got
35 * a parsing error, a number out of range,
36 * or an invalid flash bank.
39 abbrev_spec(char *str, flash_info_t **pinfo, int *psf, int *psl)
42 int bank, first, last;
45 if ((p = strchr(str, ':')) == NULL)
49 bank = simple_strtoul(str, &ep, 10);
50 if (ep == str || *ep != '\0' ||
51 bank < 1 || bank > CONFIG_SYS_MAX_FLASH_BANKS ||
52 (fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN)
56 if ((p = strchr(str, '-')) != NULL)
59 first = simple_strtoul(str, &ep, 10);
60 if (ep == str || *ep != '\0' || first >= fp->sector_count)
64 last = simple_strtoul(p, &ep, 10);
65 if (ep == p || *ep != '\0' ||
66 last < first || last >= fp->sector_count)
78 int do_flinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
82 if (argc == 1) { /* print info for all FLASH banks */
83 for (bank=0; bank <CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
84 printf ("\nBank # %ld: ", bank+1);
86 flash_print_info (&flash_info[bank]);
91 bank = simple_strtoul(argv[1], NULL, 16);
92 if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
93 printf ("Only FLASH Banks # 1 ... # %d supported\n",
94 CONFIG_SYS_MAX_FLASH_BANKS);
97 printf ("\nBank # %ld: ", bank);
98 flash_print_info (&flash_info[bank-1]);
101 int do_flerase(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
104 ulong bank, addr_first, addr_last;
105 int n, sect_first, sect_last;
109 return cmd_usage(cmdtp);
111 if (strcmp(argv[1], "all") == 0) {
112 for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
113 printf ("Erase Flash Bank # %ld ", bank);
114 info = &flash_info[bank-1];
115 rcode = flash_erase (info, 0, info->sector_count-1);
120 if ((n = abbrev_spec(argv[1], &info, §_first, §_last)) != 0) {
122 printf("Bad sector specification\n");
125 printf ("Erase Flash Sectors %d-%d in Bank # %d ",
126 sect_first, sect_last, (info-flash_info)+1);
127 rcode = flash_erase(info, sect_first, sect_last);
132 return cmd_usage(cmdtp);
134 if (strcmp(argv[1], "bank") == 0) {
135 bank = simple_strtoul(argv[2], NULL, 16);
136 if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
137 printf ("Only FLASH Banks # 1 ... # %d supported\n",
138 CONFIG_SYS_MAX_FLASH_BANKS);
141 printf ("Erase Flash Bank # %ld ", bank);
142 info = &flash_info[bank-1];
143 rcode = flash_erase (info, 0, info->sector_count-1);
147 addr_first = simple_strtoul(argv[1], NULL, 16);
148 addr_last = simple_strtoul(argv[2], NULL, 16);
150 if (addr_first >= addr_last)
151 return cmd_usage(cmdtp);
153 printf ("Erase Flash from 0x%08lx to 0x%08lx ", addr_first, addr_last);
154 rcode = flash_sect_erase(addr_first, addr_last);
158 int flash_sect_erase (ulong addr_first, ulong addr_last)
168 for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) {
172 if (info->flash_id == FLASH_UNKNOWN) {
176 b_end = info->start[0] + info->size - 1; /* bank end addr */
178 s_first = -1; /* first sector to erase */
179 s_last = -1; /* last sector to erase */
181 for (sect=0; sect < info->sector_count; ++sect) {
182 ulong end; /* last address in current sect */
185 s_end = info->sector_count - 1;
187 end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
189 if (addr_first > end)
191 if (addr_last < info->start[sect])
194 if (addr_first == info->start[sect]) {
197 if (addr_last == end) {
201 if (s_first>=0 && s_first<=s_last) {
202 erased += s_last - s_first + 1;
203 rcode = flash_erase (info, s_first, s_last);
207 /* printf ("Erased %d sectors\n", erased); */
209 printf ("Error: start and/or end address"
210 " not on sector boundary\n");
217 int do_protect(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
220 ulong bank, addr_first, addr_last;
221 int i, p, n, sect_first, sect_last;
225 return cmd_usage(cmdtp);
227 if (strcmp(argv[1], "off") == 0)
229 else if (strcmp(argv[1], "on") == 0)
232 return cmd_usage(cmdtp);
234 if (strcmp(argv[2], "all") == 0) {
235 for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
236 info = &flash_info[bank-1];
237 if (info->flash_id == FLASH_UNKNOWN) {
240 /*printf ("%sProtect Flash Bank # %ld\n", */
241 /* p ? "" : "Un-", bank); */
243 for (i=0; i<info->sector_count; ++i) {
244 #if defined(CONFIG_SYS_FLASH_PROTECTION)
245 if (flash_real_protect(info, i, p))
249 info->protect[i] = p;
250 #endif /* CONFIG_SYS_FLASH_PROTECTION */
254 #if defined(CONFIG_SYS_FLASH_PROTECTION)
255 if (!rcode) puts (" done\n");
256 #endif /* CONFIG_SYS_FLASH_PROTECTION */
261 if ((n = abbrev_spec(argv[2], &info, §_first, §_last)) != 0) {
263 printf("Bad sector specification\n");
266 /*printf("%sProtect Flash Sectors %d-%d in Bank # %d\n", */
267 /* p ? "" : "Un-", sect_first, sect_last, */
268 /* (info-flash_info)+1); */
269 for (i = sect_first; i <= sect_last; i++) {
270 #if defined(CONFIG_SYS_FLASH_PROTECTION)
271 if (flash_real_protect(info, i, p))
275 info->protect[i] = p;
276 #endif /* CONFIG_SYS_FLASH_PROTECTION */
279 #if defined(CONFIG_SYS_FLASH_PROTECTION)
280 if (!rcode) puts (" done\n");
281 #endif /* CONFIG_SYS_FLASH_PROTECTION */
287 return cmd_usage(cmdtp);
289 if (strcmp(argv[2], "bank") == 0) {
290 bank = simple_strtoul(argv[3], NULL, 16);
291 if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
292 printf ("Only FLASH Banks # 1 ... # %d supported\n",
293 CONFIG_SYS_MAX_FLASH_BANKS);
296 printf ("%sProtect Flash Bank # %ld\n",
297 p ? "" : "Un-", bank);
298 info = &flash_info[bank-1];
300 if (info->flash_id == FLASH_UNKNOWN) {
301 printf ("missing or unknown FLASH type\n");
304 for (i=0; i<info->sector_count; ++i) {
305 #if defined(CONFIG_SYS_FLASH_PROTECTION)
306 if (flash_real_protect(info, i, p))
310 info->protect[i] = p;
311 #endif /* CONFIG_SYS_FLASH_PROTECTION */
314 #if defined(CONFIG_SYS_FLASH_PROTECTION)
317 #endif /* CONFIG_SYS_FLASH_PROTECTION */
322 addr_first = simple_strtoul(argv[2], NULL, 16);
323 addr_last = simple_strtoul(argv[3], NULL, 16);
325 if (addr_first >= addr_last)
326 return cmd_usage(cmdtp);
328 return flash_sect_protect (p, addr_first, addr_last);
330 int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
340 for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) {
344 if (info->flash_id == FLASH_UNKNOWN) {
348 b_end = info->start[0] + info->size - 1; /* bank end addr */
350 s_first = -1; /* first sector to erase */
351 s_last = -1; /* last sector to erase */
353 for (sect=0; sect < info->sector_count; ++sect) {
354 ulong end; /* last address in current sect */
357 s_end = info->sector_count - 1;
359 end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
361 if (addr_first > end)
363 if (addr_last < info->start[sect])
366 if (addr_first == info->start[sect]) {
369 if (addr_last == end) {
373 if (s_first>=0 && s_first<=s_last) {
374 protected += s_last - s_first + 1;
375 for (i=s_first; i<=s_last; ++i) {
376 #if defined(CONFIG_SYS_FLASH_PROTECTION)
377 if (flash_real_protect(info, i, p))
381 info->protect[i] = p;
382 #endif /* CONFIG_SYS_FLASH_PROTECTION */
385 #if defined(CONFIG_SYS_FLASH_PROTECTION)
386 if (!rcode) putc ('\n');
387 #endif /* CONFIG_SYS_FLASH_PROTECTION */
391 /* printf ("%sProtected %d sectors\n", */
392 /* p ? "" : "Un-", protected); */
394 printf ("Error: start and/or end address"
395 " not on sector boundary\n");