~ubuntu-branches/ubuntu/maverick/u-boot-omap3/maverick

« back to all changes in this revision

Viewing changes to common/cmd_flash.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-03-22 15:06:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100322150623-i21g8rgiyl5dohag
Tags: upstream-2010.3git20100315
ImportĀ upstreamĀ versionĀ 2010.3git20100315

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (C) Copyright 2000
 
3
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
4
 *
 
5
 * See file CREDITS for list of people who contributed to this
 
6
 * project.
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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,
 
21
 * MA 02111-1307 USA
 
22
 */
 
23
 
 
24
/*
 
25
 * FLASH support
 
26
 */
 
27
#include <common.h>
 
28
#include <command.h>
 
29
 
 
30
#ifdef CONFIG_HAS_DATAFLASH
 
31
#include <dataflash.h>
 
32
#endif
 
33
 
 
34
#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
 
35
#include <jffs2/jffs2.h>
 
36
 
 
37
/* parition handling routines */
 
38
int mtdparts_init(void);
 
39
int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num);
 
40
int find_dev_and_part(const char *id, struct mtd_device **dev,
 
41
                u8 *part_num, struct part_info **part);
 
42
#endif
 
43
 
 
44
#ifndef CONFIG_SYS_NO_FLASH
 
45
extern flash_info_t flash_info[];       /* info for FLASH chips */
 
46
 
 
47
/*
 
48
 * The user interface starts numbering for Flash banks with 1
 
49
 * for historical reasons.
 
50
 */
 
51
 
 
52
/*
 
53
 * this routine looks for an abbreviated flash range specification.
 
54
 * the syntax is B:SF[-SL], where B is the bank number, SF is the first
 
55
 * sector to erase, and SL is the last sector to erase (defaults to SF).
 
56
 * bank numbers start at 1 to be consistent with other specs, sector numbers
 
57
 * start at zero.
 
58
 *
 
59
 * returns:     1       - correct spec; *pinfo, *psf and *psl are
 
60
 *                        set appropriately
 
61
 *              0       - doesn't look like an abbreviated spec
 
62
 *              -1      - looks like an abbreviated spec, but got
 
63
 *                        a parsing error, a number out of range,
 
64
 *                        or an invalid flash bank.
 
65
 */
 
66
static int
 
67
abbrev_spec (char *str, flash_info_t ** pinfo, int *psf, int *psl)
 
68
{
 
69
        flash_info_t *fp;
 
70
        int bank, first, last;
 
71
        char *p, *ep;
 
72
 
 
73
        if ((p = strchr (str, ':')) == NULL)
 
74
                return 0;
 
75
        *p++ = '\0';
 
76
 
 
77
        bank = simple_strtoul (str, &ep, 10);
 
78
        if (ep == str || *ep != '\0' ||
 
79
                bank < 1 || bank > CONFIG_SYS_MAX_FLASH_BANKS ||
 
80
                (fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN)
 
81
                return -1;
 
82
 
 
83
        str = p;
 
84
        if ((p = strchr (str, '-')) != NULL)
 
85
                *p++ = '\0';
 
86
 
 
87
        first = simple_strtoul (str, &ep, 10);
 
88
        if (ep == str || *ep != '\0' || first >= fp->sector_count)
 
89
                return -1;
 
90
 
 
91
        if (p != NULL) {
 
92
                last = simple_strtoul (p, &ep, 10);
 
93
                if (ep == p || *ep != '\0' ||
 
94
                        last < first || last >= fp->sector_count)
 
95
                        return -1;
 
96
        } else {
 
97
                last = first;
 
98
        }
 
99
 
 
100
        *pinfo = fp;
 
101
        *psf = first;
 
102
        *psl = last;
 
103
 
 
104
        return 1;
 
105
}
 
106
 
 
107
/*
 
108
 * Take *addr in Flash and adjust it to fall on the end of its sector
 
109
 */
 
110
int flash_sect_roundb (ulong *addr)
 
111
{
 
112
        flash_info_t *info;
 
113
        ulong bank, sector_end_addr;
 
114
        char found;
 
115
        int i;
 
116
 
 
117
        /* find the end addr of the sector where the *addr is */
 
118
        found = 0;
 
119
        for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS && !found; ++bank) {
 
120
                info = &flash_info[bank];
 
121
                for (i = 0; i < info->sector_count && !found; ++i) {
 
122
                        /* get the end address of the sector */
 
123
                        if (i == info->sector_count - 1) {
 
124
                                sector_end_addr = info->start[0] +
 
125
                                                                info->size - 1;
 
126
                        } else {
 
127
                                sector_end_addr = info->start[i+1] - 1;
 
128
                        }
 
129
 
 
130
                        if (*addr <= sector_end_addr &&
 
131
                                                *addr >= info->start[i]) {
 
132
                                found = 1;
 
133
                                /* adjust *addr if necessary */
 
134
                                if (*addr < sector_end_addr)
 
135
                                        *addr = sector_end_addr;
 
136
                        } /* sector */
 
137
                } /* bank */
 
138
        }
 
139
        if (!found) {
 
140
                /* error, addres not in flash */
 
141
                printf("Error: end address (0x%08lx) not in flash!\n", *addr);
 
142
                return 1;
 
143
        }
 
144
 
 
145
        return 0;
 
146
}
 
147
 
 
148
/*
 
149
 * This function computes the start and end addresses for both
 
150
 * erase and protect commands. The range of the addresses on which
 
151
 * either of the commands is to operate can be given in two forms:
 
152
 * 1. <cmd> start end - operate on <'start',  'end')
 
153
 * 2. <cmd> start +length - operate on <'start', start + length)
 
154
 * If the second form is used and the end address doesn't fall on the
 
155
 * sector boundary, than it will be adjusted to the next sector boundary.
 
156
 * If it isn't in the flash, the function will fail (return -1).
 
157
 * Input:
 
158
 *    arg1, arg2: address specification (i.e. both command arguments)
 
159
 * Output:
 
160
 *    addr_first, addr_last: computed address range
 
161
 * Return:
 
162
 *    1: success
 
163
 *   -1: failure (bad format, bad address).
 
164
*/
 
165
static int
 
166
addr_spec(char *arg1, char *arg2, ulong *addr_first, ulong *addr_last)
 
167
{
 
168
        char *ep;
 
169
        char len_used; /* indicates if the "start +length" form used */
 
170
 
 
171
        *addr_first = simple_strtoul(arg1, &ep, 16);
 
172
        if (ep == arg1 || *ep != '\0')
 
173
                return -1;
 
174
 
 
175
        len_used = 0;
 
176
        if (arg2 && *arg2 == '+'){
 
177
                len_used = 1;
 
178
                ++arg2;
 
179
        }
 
180
 
 
181
        *addr_last = simple_strtoul(arg2, &ep, 16);
 
182
        if (ep == arg2 || *ep != '\0')
 
183
                return -1;
 
184
 
 
185
        if (len_used){
 
186
                /*
 
187
                 * *addr_last has the length, compute correct *addr_last
 
188
                 * XXX watch out for the integer overflow! Right now it is
 
189
                 * checked for in both the callers.
 
190
                 */
 
191
                *addr_last = *addr_first + *addr_last - 1;
 
192
 
 
193
                /*
 
194
                 * It may happen that *addr_last doesn't fall on the sector
 
195
                 * boundary. We want to round such an address to the next
 
196
                 * sector boundary, so that the commands don't fail later on.
 
197
                 */
 
198
 
 
199
                if (flash_sect_roundb(addr_last) > 0)
 
200
                        return -1;
 
201
        } /* "start +length" from used */
 
202
 
 
203
        return 1;
 
204
}
 
205
 
 
206
static int
 
207
flash_fill_sect_ranges (ulong addr_first, ulong addr_last,
 
208
                        int *s_first, int *s_last,
 
209
                        int *s_count )
 
210
{
 
211
        flash_info_t *info;
 
212
        ulong bank;
 
213
        int rcode = 0;
 
214
 
 
215
        *s_count = 0;
 
216
 
 
217
        for (bank=0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 
218
                s_first[bank] = -1;     /* first sector to erase        */
 
219
                s_last [bank] = -1;     /* last  sector to erase        */
 
220
        }
 
221
 
 
222
        for (bank=0,info = &flash_info[0];
 
223
             (bank < CONFIG_SYS_MAX_FLASH_BANKS) && (addr_first <= addr_last);
 
224
             ++bank, ++info) {
 
225
                ulong b_end;
 
226
                int sect;
 
227
                short s_end;
 
228
 
 
229
                if (info->flash_id == FLASH_UNKNOWN) {
 
230
                        continue;
 
231
                }
 
232
 
 
233
                b_end = info->start[0] + info->size - 1;        /* bank end addr */
 
234
                s_end = info->sector_count - 1;                 /* last sector   */
 
235
 
 
236
 
 
237
                for (sect=0; sect < info->sector_count; ++sect) {
 
238
                        ulong end;      /* last address in current sect */
 
239
 
 
240
                        end = (sect == s_end) ? b_end : info->start[sect + 1] - 1;
 
241
 
 
242
                        if (addr_first > end)
 
243
                                continue;
 
244
                        if (addr_last < info->start[sect])
 
245
                                continue;
 
246
 
 
247
                        if (addr_first == info->start[sect]) {
 
248
                                s_first[bank] = sect;
 
249
                        }
 
250
                        if (addr_last  == end) {
 
251
                                s_last[bank]  = sect;
 
252
                        }
 
253
                }
 
254
                if (s_first[bank] >= 0) {
 
255
                        if (s_last[bank] < 0) {
 
256
                                if (addr_last > b_end) {
 
257
                                        s_last[bank] = s_end;
 
258
                                } else {
 
259
                                        puts ("Error: end address"
 
260
                                                " not on sector boundary\n");
 
261
                                        rcode = 1;
 
262
                                        break;
 
263
                                }
 
264
                        }
 
265
                        if (s_last[bank] < s_first[bank]) {
 
266
                                puts ("Error: end sector"
 
267
                                        " precedes start sector\n");
 
268
                                rcode = 1;
 
269
                                break;
 
270
                        }
 
271
                        sect = s_last[bank];
 
272
                        addr_first = (sect == s_end) ? b_end + 1: info->start[sect + 1];
 
273
                        (*s_count) += s_last[bank] - s_first[bank] + 1;
 
274
                } else if (addr_first >= info->start[0] && addr_first < b_end) {
 
275
                        puts ("Error: start address not on sector boundary\n");
 
276
                        rcode = 1;
 
277
                        break;
 
278
                } else if (s_last[bank] >= 0) {
 
279
                        puts ("Error: cannot span across banks when they are"
 
280
                               " mapped in reverse order\n");
 
281
                        rcode = 1;
 
282
                        break;
 
283
                }
 
284
        }
 
285
 
 
286
        return rcode;
 
287
}
 
288
#endif /* CONFIG_SYS_NO_FLASH */
 
289
 
 
290
int do_flinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 
291
{
 
292
#ifndef CONFIG_SYS_NO_FLASH
 
293
        ulong bank;
 
294
#endif
 
295
 
 
296
#ifdef CONFIG_HAS_DATAFLASH
 
297
        dataflash_print_info();
 
298
#endif
 
299
 
 
300
#ifndef CONFIG_SYS_NO_FLASH
 
301
        if (argc == 1) {        /* print info for all FLASH banks */
 
302
                for (bank=0; bank <CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 
303
                        printf ("\nBank # %ld: ", bank+1);
 
304
 
 
305
                        flash_print_info (&flash_info[bank]);
 
306
                }
 
307
                return 0;
 
308
        }
 
309
 
 
310
        bank = simple_strtoul(argv[1], NULL, 16);
 
311
        if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
 
312
                printf ("Only FLASH Banks # 1 ... # %d supported\n",
 
313
                        CONFIG_SYS_MAX_FLASH_BANKS);
 
314
                return 1;
 
315
        }
 
316
        printf ("\nBank # %ld: ", bank);
 
317
        flash_print_info (&flash_info[bank-1]);
 
318
#endif /* CONFIG_SYS_NO_FLASH */
 
319
        return 0;
 
320
}
 
321
 
 
322
int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 
323
{
 
324
#ifndef CONFIG_SYS_NO_FLASH
 
325
        flash_info_t *info;
 
326
        ulong bank, addr_first, addr_last;
 
327
        int n, sect_first, sect_last;
 
328
#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
 
329
        struct mtd_device *dev;
 
330
        struct part_info *part;
 
331
        u8 dev_type, dev_num, pnum;
 
332
#endif
 
333
        int rcode = 0;
 
334
 
 
335
        if (argc < 2) {
 
336
                cmd_usage(cmdtp);
 
337
                return 1;
 
338
        }
 
339
 
 
340
        if (strcmp(argv[1], "all") == 0) {
 
341
                for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 
342
                        printf ("Erase Flash Bank # %ld ", bank);
 
343
                        info = &flash_info[bank-1];
 
344
                        rcode = flash_erase (info, 0, info->sector_count-1);
 
345
                }
 
346
                return rcode;
 
347
        }
 
348
 
 
349
        if ((n = abbrev_spec(argv[1], &info, &sect_first, &sect_last)) != 0) {
 
350
                if (n < 0) {
 
351
                        puts ("Bad sector specification\n");
 
352
                        return 1;
 
353
                }
 
354
                printf ("Erase Flash Sectors %d-%d in Bank # %zu ",
 
355
                        sect_first, sect_last, (info-flash_info)+1);
 
356
                rcode = flash_erase(info, sect_first, sect_last);
 
357
                return rcode;
 
358
        }
 
359
 
 
360
#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
 
361
        /* erase <part-id> - erase partition */
 
362
        if ((argc == 2) && (mtd_id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) {
 
363
                mtdparts_init();
 
364
                if (find_dev_and_part(argv[1], &dev, &pnum, &part) == 0) {
 
365
                        if (dev->id->type == MTD_DEV_TYPE_NOR) {
 
366
                                bank = dev->id->num;
 
367
                                info = &flash_info[bank];
 
368
                                addr_first = part->offset + info->start[0];
 
369
                                addr_last = addr_first + part->size - 1;
 
370
 
 
371
                                printf ("Erase Flash Parition %s, "
 
372
                                                "bank %ld, 0x%08lx - 0x%08lx ",
 
373
                                                argv[1], bank, addr_first,
 
374
                                                addr_last);
 
375
 
 
376
                                rcode = flash_sect_erase(addr_first, addr_last);
 
377
                                return rcode;
 
378
                        }
 
379
 
 
380
                        printf("cannot erase, not a NOR device\n");
 
381
                        return 1;
 
382
                }
 
383
        }
 
384
#endif
 
385
 
 
386
        if (argc != 3) {
 
387
                cmd_usage(cmdtp);
 
388
                return 1;
 
389
        }
 
390
 
 
391
        if (strcmp(argv[1], "bank") == 0) {
 
392
                bank = simple_strtoul(argv[2], NULL, 16);
 
393
                if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
 
394
                        printf ("Only FLASH Banks # 1 ... # %d supported\n",
 
395
                                CONFIG_SYS_MAX_FLASH_BANKS);
 
396
                        return 1;
 
397
                }
 
398
                printf ("Erase Flash Bank # %ld ", bank);
 
399
                info = &flash_info[bank-1];
 
400
                rcode = flash_erase (info, 0, info->sector_count-1);
 
401
                return rcode;
 
402
        }
 
403
 
 
404
        if (addr_spec(argv[1], argv[2], &addr_first, &addr_last) < 0){
 
405
                printf ("Bad address format\n");
 
406
                return 1;
 
407
        }
 
408
 
 
409
        if (addr_first >= addr_last) {
 
410
                cmd_usage(cmdtp);
 
411
                return 1;
 
412
        }
 
413
 
 
414
        rcode = flash_sect_erase(addr_first, addr_last);
 
415
        return rcode;
 
416
#else
 
417
        return 0;
 
418
#endif /* CONFIG_SYS_NO_FLASH */
 
419
}
 
420
 
 
421
#ifndef CONFIG_SYS_NO_FLASH
 
422
int flash_sect_erase (ulong addr_first, ulong addr_last)
 
423
{
 
424
        flash_info_t *info;
 
425
        ulong bank;
 
426
#ifdef CONFIG_SYS_MAX_FLASH_BANKS_DETECT
 
427
        int s_first[CONFIG_SYS_MAX_FLASH_BANKS_DETECT], s_last[CONFIG_SYS_MAX_FLASH_BANKS_DETECT];
 
428
#else
 
429
        int s_first[CONFIG_SYS_MAX_FLASH_BANKS], s_last[CONFIG_SYS_MAX_FLASH_BANKS];
 
430
#endif
 
431
        int erased = 0;
 
432
        int planned;
 
433
        int rcode = 0;
 
434
 
 
435
        rcode = flash_fill_sect_ranges (addr_first, addr_last,
 
436
                                        s_first, s_last, &planned );
 
437
 
 
438
        if (planned && (rcode == 0)) {
 
439
                for (bank=0,info = &flash_info[0];
 
440
                     (bank < CONFIG_SYS_MAX_FLASH_BANKS) && (rcode == 0);
 
441
                     ++bank, ++info) {
 
442
                        if (s_first[bank]>=0) {
 
443
                                erased += s_last[bank] - s_first[bank] + 1;
 
444
                                debug ("Erase Flash from 0x%08lx to 0x%08lx "
 
445
                                        "in Bank # %ld ",
 
446
                                        info->start[s_first[bank]],
 
447
                                        (s_last[bank] == info->sector_count) ?
 
448
                                                info->start[0] + info->size - 1:
 
449
                                                info->start[s_last[bank]+1] - 1,
 
450
                                        bank+1);
 
451
                                rcode = flash_erase (info, s_first[bank], s_last[bank]);
 
452
                        }
 
453
                }
 
454
                printf ("Erased %d sectors\n", erased);
 
455
        } else if (rcode == 0) {
 
456
                puts ("Error: start and/or end address"
 
457
                        " not on sector boundary\n");
 
458
                rcode = 1;
 
459
        }
 
460
        return rcode;
 
461
}
 
462
#endif /* CONFIG_SYS_NO_FLASH */
 
463
 
 
464
int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 
465
{
 
466
#ifndef CONFIG_SYS_NO_FLASH
 
467
        flash_info_t *info;
 
468
        ulong bank;
 
469
        int i, n, sect_first, sect_last;
 
470
#endif /* CONFIG_SYS_NO_FLASH */
 
471
#if !defined(CONFIG_SYS_NO_FLASH) || defined(CONFIG_HAS_DATAFLASH)
 
472
        ulong addr_first, addr_last;
 
473
#endif
 
474
#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
 
475
        struct mtd_device *dev;
 
476
        struct part_info *part;
 
477
        u8 dev_type, dev_num, pnum;
 
478
#endif
 
479
#ifdef CONFIG_HAS_DATAFLASH
 
480
        int status;
 
481
#endif
 
482
        int p;
 
483
        int rcode = 0;
 
484
 
 
485
        if (argc < 3) {
 
486
                cmd_usage(cmdtp);
 
487
                return 1;
 
488
        }
 
489
 
 
490
        if (strcmp(argv[1], "off") == 0) {
 
491
                p = 0;
 
492
        } else if (strcmp(argv[1], "on") == 0) {
 
493
                p = 1;
 
494
        } else {
 
495
                cmd_usage(cmdtp);
 
496
                return 1;
 
497
        }
 
498
 
 
499
#ifdef CONFIG_HAS_DATAFLASH
 
500
        if ((strcmp(argv[2], "all") != 0) && (strcmp(argv[2], "bank") != 0)) {
 
501
                addr_first = simple_strtoul(argv[2], NULL, 16);
 
502
                addr_last  = simple_strtoul(argv[3], NULL, 16);
 
503
 
 
504
                if (addr_dataflash(addr_first) && addr_dataflash(addr_last)) {
 
505
                        status = dataflash_real_protect(p,addr_first,addr_last);
 
506
                        if (status < 0){
 
507
                                puts ("Bad DataFlash sector specification\n");
 
508
                                return 1;
 
509
                        }
 
510
                        printf("%sProtect %d DataFlash Sectors\n",
 
511
                                p ? "" : "Un-", status);
 
512
                        return 0;
 
513
                }
 
514
        }
 
515
#endif
 
516
 
 
517
#ifndef CONFIG_SYS_NO_FLASH
 
518
        if (strcmp(argv[2], "all") == 0) {
 
519
                for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
 
520
                        info = &flash_info[bank-1];
 
521
                        if (info->flash_id == FLASH_UNKNOWN) {
 
522
                                continue;
 
523
                        }
 
524
                        printf ("%sProtect Flash Bank # %ld\n",
 
525
                                p ? "" : "Un-", bank);
 
526
 
 
527
                        for (i=0; i<info->sector_count; ++i) {
 
528
#if defined(CONFIG_SYS_FLASH_PROTECTION)
 
529
                                if (flash_real_protect(info, i, p))
 
530
                                        rcode = 1;
 
531
                                putc ('.');
 
532
#else
 
533
                                info->protect[i] = p;
 
534
#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 
535
                        }
 
536
#if defined(CONFIG_SYS_FLASH_PROTECTION)
 
537
                        if (!rcode) puts (" done\n");
 
538
#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 
539
                }
 
540
                return rcode;
 
541
        }
 
542
 
 
543
        if ((n = abbrev_spec(argv[2], &info, &sect_first, &sect_last)) != 0) {
 
544
                if (n < 0) {
 
545
                        puts ("Bad sector specification\n");
 
546
                        return 1;
 
547
                }
 
548
                printf("%sProtect Flash Sectors %d-%d in Bank # %zu\n",
 
549
                        p ? "" : "Un-", sect_first, sect_last,
 
550
                        (info-flash_info)+1);
 
551
                for (i = sect_first; i <= sect_last; i++) {
 
552
#if defined(CONFIG_SYS_FLASH_PROTECTION)
 
553
                        if (flash_real_protect(info, i, p))
 
554
                                rcode =  1;
 
555
                        putc ('.');
 
556
#else
 
557
                        info->protect[i] = p;
 
558
#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 
559
                }
 
560
 
 
561
#if defined(CONFIG_SYS_FLASH_PROTECTION)
 
562
                if (!rcode) puts (" done\n");
 
563
#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 
564
 
 
565
                return rcode;
 
566
        }
 
567
 
 
568
#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
 
569
        /* protect on/off <part-id> */
 
570
        if ((argc == 3) && (mtd_id_parse(argv[2], NULL, &dev_type, &dev_num) == 0)) {
 
571
                mtdparts_init();
 
572
                if (find_dev_and_part(argv[2], &dev, &pnum, &part) == 0) {
 
573
                        if (dev->id->type == MTD_DEV_TYPE_NOR) {
 
574
                                bank = dev->id->num;
 
575
                                info = &flash_info[bank];
 
576
                                addr_first = part->offset + info->start[0];
 
577
                                addr_last = addr_first + part->size - 1;
 
578
 
 
579
                                printf ("%sProtect Flash Parition %s, "
 
580
                                                "bank %ld, 0x%08lx - 0x%08lx\n",
 
581
                                                p ? "" : "Un", argv[1],
 
582
                                                bank, addr_first, addr_last);
 
583
 
 
584
                                rcode = flash_sect_protect (p, addr_first, addr_last);
 
585
                                return rcode;
 
586
                        }
 
587
 
 
588
                        printf("cannot %sprotect, not a NOR device\n",
 
589
                                        p ? "" : "un");
 
590
                        return 1;
 
591
                }
 
592
        }
 
593
#endif
 
594
 
 
595
        if (argc != 4) {
 
596
                cmd_usage(cmdtp);
 
597
                return 1;
 
598
        }
 
599
 
 
600
        if (strcmp(argv[2], "bank") == 0) {
 
601
                bank = simple_strtoul(argv[3], NULL, 16);
 
602
                if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
 
603
                        printf ("Only FLASH Banks # 1 ... # %d supported\n",
 
604
                                CONFIG_SYS_MAX_FLASH_BANKS);
 
605
                        return 1;
 
606
                }
 
607
                printf ("%sProtect Flash Bank # %ld\n",
 
608
                        p ? "" : "Un-", bank);
 
609
                info = &flash_info[bank-1];
 
610
 
 
611
                if (info->flash_id == FLASH_UNKNOWN) {
 
612
                        puts ("missing or unknown FLASH type\n");
 
613
                        return 1;
 
614
                }
 
615
                for (i=0; i<info->sector_count; ++i) {
 
616
#if defined(CONFIG_SYS_FLASH_PROTECTION)
 
617
                        if (flash_real_protect(info, i, p))
 
618
                                rcode =  1;
 
619
                        putc ('.');
 
620
#else
 
621
                        info->protect[i] = p;
 
622
#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 
623
                }
 
624
 
 
625
#if defined(CONFIG_SYS_FLASH_PROTECTION)
 
626
                if (!rcode) puts (" done\n");
 
627
#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 
628
 
 
629
                return rcode;
 
630
        }
 
631
 
 
632
        if (addr_spec(argv[2], argv[3], &addr_first, &addr_last) < 0){
 
633
                printf("Bad address format\n");
 
634
                return 1;
 
635
        }
 
636
 
 
637
        if (addr_first >= addr_last) {
 
638
                cmd_usage(cmdtp);
 
639
                return 1;
 
640
        }
 
641
        rcode = flash_sect_protect (p, addr_first, addr_last);
 
642
#endif /* CONFIG_SYS_NO_FLASH */
 
643
        return rcode;
 
644
}
 
645
 
 
646
#ifndef CONFIG_SYS_NO_FLASH
 
647
int flash_sect_protect (int p, ulong addr_first, ulong addr_last)
 
648
{
 
649
        flash_info_t *info;
 
650
        ulong bank;
 
651
#ifdef CONFIG_SYS_MAX_FLASH_BANKS_DETECT
 
652
        int s_first[CONFIG_SYS_MAX_FLASH_BANKS_DETECT], s_last[CONFIG_SYS_MAX_FLASH_BANKS_DETECT];
 
653
#else
 
654
        int s_first[CONFIG_SYS_MAX_FLASH_BANKS], s_last[CONFIG_SYS_MAX_FLASH_BANKS];
 
655
#endif
 
656
        int protected, i;
 
657
        int planned;
 
658
        int rcode;
 
659
 
 
660
        rcode = flash_fill_sect_ranges( addr_first, addr_last, s_first, s_last, &planned );
 
661
 
 
662
        protected = 0;
 
663
 
 
664
        if (planned && (rcode == 0)) {
 
665
                for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) {
 
666
                        if (info->flash_id == FLASH_UNKNOWN) {
 
667
                                continue;
 
668
                        }
 
669
 
 
670
                        if (s_first[bank]>=0 && s_first[bank]<=s_last[bank]) {
 
671
                                debug ("%sProtecting sectors %d..%d in bank %ld\n",
 
672
                                        p ? "" : "Un-",
 
673
                                        s_first[bank], s_last[bank], bank+1);
 
674
                                protected += s_last[bank] - s_first[bank] + 1;
 
675
                                for (i=s_first[bank]; i<=s_last[bank]; ++i) {
 
676
#if defined(CONFIG_SYS_FLASH_PROTECTION)
 
677
                                        if (flash_real_protect(info, i, p))
 
678
                                                rcode = 1;
 
679
                                        putc ('.');
 
680
#else
 
681
                                        info->protect[i] = p;
 
682
#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 
683
                                }
 
684
                        }
 
685
                }
 
686
#if defined(CONFIG_SYS_FLASH_PROTECTION)
 
687
                puts (" done\n");
 
688
#endif  /* CONFIG_SYS_FLASH_PROTECTION */
 
689
 
 
690
                printf ("%sProtected %d sectors\n",
 
691
                        p ? "" : "Un-", protected);
 
692
        } else if (rcode == 0) {
 
693
                puts ("Error: start and/or end address"
 
694
                        " not on sector boundary\n");
 
695
                rcode = 1;
 
696
        }
 
697
        return rcode;
 
698
}
 
699
#endif /* CONFIG_SYS_NO_FLASH */
 
700
 
 
701
 
 
702
/**************************************************/
 
703
#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
 
704
# define TMP_ERASE      "erase <part-id>\n    - erase partition\n"
 
705
# define TMP_PROT_ON    "protect on <part-id>\n    - protect partition\n"
 
706
# define TMP_PROT_OFF   "protect off <part-id>\n    - make partition writable\n"
 
707
#else
 
708
# define TMP_ERASE      /* empty */
 
709
# define TMP_PROT_ON    /* empty */
 
710
# define TMP_PROT_OFF   /* empty */
 
711
#endif
 
712
 
 
713
U_BOOT_CMD(
 
714
        flinfo,    2,    1,    do_flinfo,
 
715
        "print FLASH memory information",
 
716
        "\n    - print information for all FLASH memory banks\n"
 
717
        "flinfo N\n    - print information for FLASH memory bank # N"
 
718
);
 
719
 
 
720
U_BOOT_CMD(
 
721
        erase,   3,   0,  do_flerase,
 
722
        "erase FLASH memory",
 
723
        "start end\n"
 
724
        "    - erase FLASH from addr 'start' to addr 'end'\n"
 
725
        "erase start +len\n"
 
726
        "    - erase FLASH from addr 'start' to the end of sect "
 
727
        "w/addr 'start'+'len'-1\n"
 
728
        "erase N:SF[-SL]\n    - erase sectors SF-SL in FLASH bank # N\n"
 
729
        "erase bank N\n    - erase FLASH bank # N\n"
 
730
        TMP_ERASE
 
731
        "erase all\n    - erase all FLASH banks"
 
732
);
 
733
 
 
734
U_BOOT_CMD(
 
735
        protect,  4,  0,   do_protect,
 
736
        "enable or disable FLASH write protection",
 
737
        "on  start end\n"
 
738
        "    - protect FLASH from addr 'start' to addr 'end'\n"
 
739
        "protect on start +len\n"
 
740
        "    - protect FLASH from addr 'start' to end of sect "
 
741
        "w/addr 'start'+'len'-1\n"
 
742
        "protect on  N:SF[-SL]\n"
 
743
        "    - protect sectors SF-SL in FLASH bank # N\n"
 
744
        "protect on  bank N\n    - protect FLASH bank # N\n"
 
745
        TMP_PROT_ON
 
746
        "protect on  all\n    - protect all FLASH banks\n"
 
747
        "protect off start end\n"
 
748
        "    - make FLASH from addr 'start' to addr 'end' writable\n"
 
749
        "protect off start +len\n"
 
750
        "    - make FLASH from addr 'start' to end of sect "
 
751
        "w/addr 'start'+'len'-1 wrtable\n"
 
752
        "protect off N:SF[-SL]\n"
 
753
        "    - make sectors SF-SL writable in FLASH bank # N\n"
 
754
        "protect off bank N\n    - make FLASH bank # N writable\n"
 
755
        TMP_PROT_OFF
 
756
        "protect off all\n    - make all FLASH banks writable"
 
757
);
 
758
 
 
759
#undef  TMP_ERASE
 
760
#undef  TMP_PROT_ON
 
761
#undef  TMP_PROT_OFF