Merge branch 'next' of ../master
[platform/kernel/u-boot.git] / common / cmd_mem.c
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  * Memory Functions
26  *
27  * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
28  */
29
30 #include <common.h>
31 #include <command.h>
32 #ifdef CONFIG_HAS_DATAFLASH
33 #include <dataflash.h>
34 #endif
35 #include <watchdog.h>
36
37 #ifdef  CMD_MEM_DEBUG
38 #define PRINTF(fmt,args...)     printf (fmt ,##args)
39 #else
40 #define PRINTF(fmt,args...)
41 #endif
42
43 static int mod_mem(cmd_tbl_t *, int, int, int, char *[]);
44
45 /* Display values from last command.
46  * Memory modify remembered values are different from display memory.
47  */
48 uint    dp_last_addr, dp_last_size;
49 uint    dp_last_length = 0x40;
50 uint    mm_last_addr, mm_last_size;
51
52 static  ulong   base_address = 0;
53
54 /* Memory Display
55  *
56  * Syntax:
57  *      md{.b, .w, .l} {addr} {len}
58  */
59 #define DISP_LINE_LEN   16
60 int do_mem_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
61 {
62         ulong   addr, length;
63 #if defined(CONFIG_HAS_DATAFLASH)
64         ulong   nbytes, linebytes;
65 #endif
66         int     size;
67         int rc = 0;
68
69         /* We use the last specified parameters, unless new ones are
70          * entered.
71          */
72         addr = dp_last_addr;
73         size = dp_last_size;
74         length = dp_last_length;
75
76         if (argc < 2) {
77                 cmd_usage(cmdtp);
78                 return 1;
79         }
80
81         if ((flag & CMD_FLAG_REPEAT) == 0) {
82                 /* New command specified.  Check for a size specification.
83                  * Defaults to long if no or incorrect specification.
84                  */
85                 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
86                         return 1;
87
88                 /* Address is specified since argc > 1
89                 */
90                 addr = simple_strtoul(argv[1], NULL, 16);
91                 addr += base_address;
92
93                 /* If another parameter, it is the length to display.
94                  * Length is the number of objects, not number of bytes.
95                  */
96                 if (argc > 2)
97                         length = simple_strtoul(argv[2], NULL, 16);
98         }
99
100 #if defined(CONFIG_HAS_DATAFLASH)
101         /* Print the lines.
102          *
103          * We buffer all read data, so we can make sure data is read only
104          * once, and all accesses are with the specified bus width.
105          */
106         nbytes = length * size;
107         do {
108                 char    linebuf[DISP_LINE_LEN];
109                 void* p;
110                 linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
111
112                 rc = read_dataflash(addr, (linebytes/size)*size, linebuf);
113                 p = (rc == DATAFLASH_OK) ? linebuf : (void*)addr;
114                 print_buffer(addr, p, size, linebytes/size, DISP_LINE_LEN/size);
115
116                 nbytes -= linebytes;
117                 addr += linebytes;
118                 if (ctrlc()) {
119                         rc = 1;
120                         break;
121                 }
122         } while (nbytes > 0);
123 #else
124
125 # if defined(CONFIG_BLACKFIN)
126         /* See if we're trying to display L1 inst */
127         if (addr_bfin_on_chip_mem(addr)) {
128                 char linebuf[DISP_LINE_LEN];
129                 ulong linebytes, nbytes = length * size;
130                 do {
131                         linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
132                         memcpy(linebuf, (void *)addr, linebytes);
133                         print_buffer(addr, linebuf, size, linebytes/size, DISP_LINE_LEN/size);
134
135                         nbytes -= linebytes;
136                         addr += linebytes;
137                         if (ctrlc()) {
138                                 rc = 1;
139                                 break;
140                         }
141                 } while (nbytes > 0);
142         } else
143 # endif
144
145         {
146                 /* Print the lines. */
147                 print_buffer(addr, (void*)addr, size, length, DISP_LINE_LEN/size);
148                 addr += size*length;
149         }
150 #endif
151
152         dp_last_addr = addr;
153         dp_last_length = length;
154         dp_last_size = size;
155         return (rc);
156 }
157
158 int do_mem_mm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
159 {
160         return mod_mem (cmdtp, 1, flag, argc, argv);
161 }
162 int do_mem_nm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
163 {
164         return mod_mem (cmdtp, 0, flag, argc, argv);
165 }
166
167 int do_mem_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
168 {
169         ulong   addr, writeval, count;
170         int     size;
171
172         if ((argc < 3) || (argc > 4)) {
173                 cmd_usage(cmdtp);
174                 return 1;
175         }
176
177         /* Check for size specification.
178         */
179         if ((size = cmd_get_data_size(argv[0], 4)) < 1)
180                 return 1;
181
182         /* Address is specified since argc > 1
183         */
184         addr = simple_strtoul(argv[1], NULL, 16);
185         addr += base_address;
186
187         /* Get the value to write.
188         */
189         writeval = simple_strtoul(argv[2], NULL, 16);
190
191         /* Count ? */
192         if (argc == 4) {
193                 count = simple_strtoul(argv[3], NULL, 16);
194         } else {
195                 count = 1;
196         }
197
198         while (count-- > 0) {
199                 if (size == 4)
200                         *((ulong  *)addr) = (ulong )writeval;
201                 else if (size == 2)
202                         *((ushort *)addr) = (ushort)writeval;
203                 else
204                         *((u_char *)addr) = (u_char)writeval;
205                 addr += size;
206         }
207         return 0;
208 }
209
210 #ifdef CONFIG_MX_CYCLIC
211 int do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
212 {
213         int i;
214         ulong count;
215
216         if (argc < 4) {
217                 cmd_usage(cmdtp);
218                 return 1;
219         }
220
221         count = simple_strtoul(argv[3], NULL, 10);
222
223         for (;;) {
224                 do_mem_md (NULL, 0, 3, argv);
225
226                 /* delay for <count> ms... */
227                 for (i=0; i<count; i++)
228                         udelay (1000);
229
230                 /* check for ctrl-c to abort... */
231                 if (ctrlc()) {
232                         puts("Abort\n");
233                         return 0;
234                 }
235         }
236
237         return 0;
238 }
239
240 int do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
241 {
242         int i;
243         ulong count;
244
245         if (argc < 4) {
246                 cmd_usage(cmdtp);
247                 return 1;
248         }
249
250         count = simple_strtoul(argv[3], NULL, 10);
251
252         for (;;) {
253                 do_mem_mw (NULL, 0, 3, argv);
254
255                 /* delay for <count> ms... */
256                 for (i=0; i<count; i++)
257                         udelay (1000);
258
259                 /* check for ctrl-c to abort... */
260                 if (ctrlc()) {
261                         puts("Abort\n");
262                         return 0;
263                 }
264         }
265
266         return 0;
267 }
268 #endif /* CONFIG_MX_CYCLIC */
269
270 int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
271 {
272         ulong   addr1, addr2, count, ngood;
273         int     size;
274         int     rcode = 0;
275
276         if (argc != 4) {
277                 cmd_usage(cmdtp);
278                 return 1;
279         }
280
281         /* Check for size specification.
282         */
283         if ((size = cmd_get_data_size(argv[0], 4)) < 0)
284                 return 1;
285
286         addr1 = simple_strtoul(argv[1], NULL, 16);
287         addr1 += base_address;
288
289         addr2 = simple_strtoul(argv[2], NULL, 16);
290         addr2 += base_address;
291
292         count = simple_strtoul(argv[3], NULL, 16);
293
294 #ifdef CONFIG_HAS_DATAFLASH
295         if (addr_dataflash(addr1) | addr_dataflash(addr2)){
296                 puts ("Comparison with DataFlash space not supported.\n\r");
297                 return 0;
298         }
299 #endif
300
301 #ifdef CONFIG_BLACKFIN
302         if (addr_bfin_on_chip_mem(addr1) || addr_bfin_on_chip_mem(addr2)) {
303                 puts ("Comparison with L1 instruction memory not supported.\n\r");
304                 return 0;
305         }
306 #endif
307
308         ngood = 0;
309
310         while (count-- > 0) {
311                 if (size == 4) {
312                         ulong word1 = *(ulong *)addr1;
313                         ulong word2 = *(ulong *)addr2;
314                         if (word1 != word2) {
315                                 printf("word at 0x%08lx (0x%08lx) "
316                                         "!= word at 0x%08lx (0x%08lx)\n",
317                                         addr1, word1, addr2, word2);
318                                 rcode = 1;
319                                 break;
320                         }
321                 }
322                 else if (size == 2) {
323                         ushort hword1 = *(ushort *)addr1;
324                         ushort hword2 = *(ushort *)addr2;
325                         if (hword1 != hword2) {
326                                 printf("halfword at 0x%08lx (0x%04x) "
327                                         "!= halfword at 0x%08lx (0x%04x)\n",
328                                         addr1, hword1, addr2, hword2);
329                                 rcode = 1;
330                                 break;
331                         }
332                 }
333                 else {
334                         u_char byte1 = *(u_char *)addr1;
335                         u_char byte2 = *(u_char *)addr2;
336                         if (byte1 != byte2) {
337                                 printf("byte at 0x%08lx (0x%02x) "
338                                         "!= byte at 0x%08lx (0x%02x)\n",
339                                         addr1, byte1, addr2, byte2);
340                                 rcode = 1;
341                                 break;
342                         }
343                 }
344                 ngood++;
345                 addr1 += size;
346                 addr2 += size;
347         }
348
349         printf("Total of %ld %s%s were the same\n",
350                 ngood, size == 4 ? "word" : size == 2 ? "halfword" : "byte",
351                 ngood == 1 ? "" : "s");
352         return rcode;
353 }
354
355 int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
356 {
357         ulong   addr, dest, count;
358         int     size;
359
360         if (argc != 4) {
361                 cmd_usage(cmdtp);
362                 return 1;
363         }
364
365         /* Check for size specification.
366         */
367         if ((size = cmd_get_data_size(argv[0], 4)) < 0)
368                 return 1;
369
370         addr = simple_strtoul(argv[1], NULL, 16);
371         addr += base_address;
372
373         dest = simple_strtoul(argv[2], NULL, 16);
374         dest += base_address;
375
376         count = simple_strtoul(argv[3], NULL, 16);
377
378         if (count == 0) {
379                 puts ("Zero length ???\n");
380                 return 1;
381         }
382
383 #ifndef CONFIG_SYS_NO_FLASH
384         /* check if we are copying to Flash */
385         if ( (addr2info(dest) != NULL)
386 #ifdef CONFIG_HAS_DATAFLASH
387            && (!addr_dataflash(dest))
388 #endif
389            ) {
390                 int rc;
391
392                 puts ("Copy to Flash... ");
393
394                 rc = flash_write ((char *)addr, dest, count*size);
395                 if (rc != 0) {
396                         flash_perror (rc);
397                         return (1);
398                 }
399                 puts ("done\n");
400                 return 0;
401         }
402 #endif
403
404 #ifdef CONFIG_HAS_DATAFLASH
405         /* Check if we are copying from RAM or Flash to DataFlash */
406         if (addr_dataflash(dest) && !addr_dataflash(addr)){
407                 int rc;
408
409                 puts ("Copy to DataFlash... ");
410
411                 rc = write_dataflash (dest, addr, count*size);
412
413                 if (rc != 1) {
414                         dataflash_perror (rc);
415                         return (1);
416                 }
417                 puts ("done\n");
418                 return 0;
419         }
420
421         /* Check if we are copying from DataFlash to RAM */
422         if (addr_dataflash(addr) && !addr_dataflash(dest)
423 #ifndef CONFIG_SYS_NO_FLASH
424                                  && (addr2info(dest) == NULL)
425 #endif
426            ){
427                 int rc;
428                 rc = read_dataflash(addr, count * size, (char *) dest);
429                 if (rc != 1) {
430                         dataflash_perror (rc);
431                         return (1);
432                 }
433                 return 0;
434         }
435
436         if (addr_dataflash(addr) && addr_dataflash(dest)){
437                 puts ("Unsupported combination of source/destination.\n\r");
438                 return 1;
439         }
440 #endif
441
442 #ifdef CONFIG_BLACKFIN
443         /* See if we're copying to/from L1 inst */
444         if (addr_bfin_on_chip_mem(dest) || addr_bfin_on_chip_mem(addr)) {
445                 memcpy((void *)dest, (void *)addr, count * size);
446                 return 0;
447         }
448 #endif
449
450         while (count-- > 0) {
451                 if (size == 4)
452                         *((ulong  *)dest) = *((ulong  *)addr);
453                 else if (size == 2)
454                         *((ushort *)dest) = *((ushort *)addr);
455                 else
456                         *((u_char *)dest) = *((u_char *)addr);
457                 addr += size;
458                 dest += size;
459         }
460         return 0;
461 }
462
463 int do_mem_base (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
464 {
465         if (argc > 1) {
466                 /* Set new base address.
467                 */
468                 base_address = simple_strtoul(argv[1], NULL, 16);
469         }
470         /* Print the current base address.
471         */
472         printf("Base Address: 0x%08lx\n", base_address);
473         return 0;
474 }
475
476 int do_mem_loop (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
477 {
478         ulong   addr, length, i, junk;
479         int     size;
480         volatile uint   *longp;
481         volatile ushort *shortp;
482         volatile u_char *cp;
483
484         if (argc < 3) {
485                 cmd_usage(cmdtp);
486                 return 1;
487         }
488
489         /* Check for a size spefication.
490          * Defaults to long if no or incorrect specification.
491          */
492         if ((size = cmd_get_data_size(argv[0], 4)) < 0)
493                 return 1;
494
495         /* Address is always specified.
496         */
497         addr = simple_strtoul(argv[1], NULL, 16);
498
499         /* Length is the number of objects, not number of bytes.
500         */
501         length = simple_strtoul(argv[2], NULL, 16);
502
503         /* We want to optimize the loops to run as fast as possible.
504          * If we have only one object, just run infinite loops.
505          */
506         if (length == 1) {
507                 if (size == 4) {
508                         longp = (uint *)addr;
509                         for (;;)
510                                 i = *longp;
511                 }
512                 if (size == 2) {
513                         shortp = (ushort *)addr;
514                         for (;;)
515                                 i = *shortp;
516                 }
517                 cp = (u_char *)addr;
518                 for (;;)
519                         i = *cp;
520         }
521
522         if (size == 4) {
523                 for (;;) {
524                         longp = (uint *)addr;
525                         i = length;
526                         while (i-- > 0)
527                                 junk = *longp++;
528                 }
529         }
530         if (size == 2) {
531                 for (;;) {
532                         shortp = (ushort *)addr;
533                         i = length;
534                         while (i-- > 0)
535                                 junk = *shortp++;
536                 }
537         }
538         for (;;) {
539                 cp = (u_char *)addr;
540                 i = length;
541                 while (i-- > 0)
542                         junk = *cp++;
543         }
544 }
545
546 #ifdef CONFIG_LOOPW
547 int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
548 {
549         ulong   addr, length, i, data;
550         int     size;
551         volatile uint   *longp;
552         volatile ushort *shortp;
553         volatile u_char *cp;
554
555         if (argc < 4) {
556                 cmd_usage(cmdtp);
557                 return 1;
558         }
559
560         /* Check for a size spefication.
561          * Defaults to long if no or incorrect specification.
562          */
563         if ((size = cmd_get_data_size(argv[0], 4)) < 0)
564                 return 1;
565
566         /* Address is always specified.
567         */
568         addr = simple_strtoul(argv[1], NULL, 16);
569
570         /* Length is the number of objects, not number of bytes.
571         */
572         length = simple_strtoul(argv[2], NULL, 16);
573
574         /* data to write */
575         data = simple_strtoul(argv[3], NULL, 16);
576
577         /* We want to optimize the loops to run as fast as possible.
578          * If we have only one object, just run infinite loops.
579          */
580         if (length == 1) {
581                 if (size == 4) {
582                         longp = (uint *)addr;
583                         for (;;)
584                                 *longp = data;
585                                         }
586                 if (size == 2) {
587                         shortp = (ushort *)addr;
588                         for (;;)
589                                 *shortp = data;
590                 }
591                 cp = (u_char *)addr;
592                 for (;;)
593                         *cp = data;
594         }
595
596         if (size == 4) {
597                 for (;;) {
598                         longp = (uint *)addr;
599                         i = length;
600                         while (i-- > 0)
601                                 *longp++ = data;
602                 }
603         }
604         if (size == 2) {
605                 for (;;) {
606                         shortp = (ushort *)addr;
607                         i = length;
608                         while (i-- > 0)
609                                 *shortp++ = data;
610                 }
611         }
612         for (;;) {
613                 cp = (u_char *)addr;
614                 i = length;
615                 while (i-- > 0)
616                         *cp++ = data;
617         }
618 }
619 #endif /* CONFIG_LOOPW */
620
621 /*
622  * Perform a memory test. A more complete alternative test can be
623  * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
624  * interrupted by ctrl-c or by a failure of one of the sub-tests.
625  */
626 int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
627 {
628         vu_long *addr, *start, *end;
629         ulong   val;
630         ulong   readback;
631         int     rcode = 0;
632         int iterations = 1;
633         int iteration_limit;
634
635 #if defined(CONFIG_SYS_ALT_MEMTEST)
636         vu_long len;
637         vu_long offset;
638         vu_long test_offset;
639         vu_long pattern;
640         vu_long temp;
641         vu_long anti_pattern;
642         vu_long num_words;
643 #if defined(CONFIG_SYS_MEMTEST_SCRATCH)
644         vu_long *dummy = (vu_long*)CONFIG_SYS_MEMTEST_SCRATCH;
645 #else
646         vu_long *dummy = 0;     /* yes, this is address 0x0, not NULL */
647 #endif
648         int     j;
649
650         static const ulong bitpattern[] = {
651                 0x00000001,     /* single bit */
652                 0x00000003,     /* two adjacent bits */
653                 0x00000007,     /* three adjacent bits */
654                 0x0000000F,     /* four adjacent bits */
655                 0x00000005,     /* two non-adjacent bits */
656                 0x00000015,     /* three non-adjacent bits */
657                 0x00000055,     /* four non-adjacent bits */
658                 0xaaaaaaaa,     /* alternating 1/0 */
659         };
660 #else
661         ulong   incr;
662         ulong   pattern;
663 #endif
664
665         if (argc > 1)
666                 start = (ulong *)simple_strtoul(argv[1], NULL, 16);
667         else
668                 start = (ulong *)CONFIG_SYS_MEMTEST_START;
669
670         if (argc > 2)
671                 end = (ulong *)simple_strtoul(argv[2], NULL, 16);
672         else
673                 end = (ulong *)(CONFIG_SYS_MEMTEST_END);
674
675         if (argc > 3)
676                 pattern = (ulong)simple_strtoul(argv[3], NULL, 16);
677         else
678                 pattern = 0;
679
680         if (argc > 4)
681                 iteration_limit = (ulong)simple_strtoul(argv[4], NULL, 16);
682         else
683                 iteration_limit = 0;
684
685 #if defined(CONFIG_SYS_ALT_MEMTEST)
686         printf ("Testing %08x ... %08x:\n", (uint)start, (uint)end);
687         PRINTF("%s:%d: start 0x%p end 0x%p\n",
688                 __FUNCTION__, __LINE__, start, end);
689
690         for (;;) {
691                 if (ctrlc()) {
692                         putc ('\n');
693                         return 1;
694                 }
695
696
697                 if (iteration_limit && iterations > iteration_limit) {
698                         printf("Tested %d iteration(s) without errors.\n",
699                                 iterations-1);
700                         return 0;
701                 }
702
703                 printf("Iteration: %6d\r", iterations);
704                 PRINTF("\n");
705                 iterations++;
706
707                 /*
708                  * Data line test: write a pattern to the first
709                  * location, write the 1's complement to a 'parking'
710                  * address (changes the state of the data bus so a
711                  * floating bus doen't give a false OK), and then
712                  * read the value back. Note that we read it back
713                  * into a variable because the next time we read it,
714                  * it might be right (been there, tough to explain to
715                  * the quality guys why it prints a failure when the
716                  * "is" and "should be" are obviously the same in the
717                  * error message).
718                  *
719                  * Rather than exhaustively testing, we test some
720                  * patterns by shifting '1' bits through a field of
721                  * '0's and '0' bits through a field of '1's (i.e.
722                  * pattern and ~pattern).
723                  */
724                 addr = start;
725                 for (j = 0; j < sizeof(bitpattern)/sizeof(bitpattern[0]); j++) {
726                     val = bitpattern[j];
727                     for(; val != 0; val <<= 1) {
728                         *addr  = val;
729                         *dummy  = ~val; /* clear the test data off of the bus */
730                         readback = *addr;
731                         if(readback != val) {
732                              printf ("FAILURE (data line): "
733                                 "expected %08lx, actual %08lx\n",
734                                           val, readback);
735                         }
736                         *addr  = ~val;
737                         *dummy  = val;
738                         readback = *addr;
739                         if(readback != ~val) {
740                             printf ("FAILURE (data line): "
741                                 "Is %08lx, should be %08lx\n",
742                                         readback, ~val);
743                         }
744                     }
745                 }
746
747                 /*
748                  * Based on code whose Original Author and Copyright
749                  * information follows: Copyright (c) 1998 by Michael
750                  * Barr. This software is placed into the public
751                  * domain and may be used for any purpose. However,
752                  * this notice must not be changed or removed and no
753                  * warranty is either expressed or implied by its
754                  * publication or distribution.
755                  */
756
757                 /*
758                  * Address line test
759                  *
760                  * Description: Test the address bus wiring in a
761                  *              memory region by performing a walking
762                  *              1's test on the relevant bits of the
763                  *              address and checking for aliasing.
764                  *              This test will find single-bit
765                  *              address failures such as stuck -high,
766                  *              stuck-low, and shorted pins. The base
767                  *              address and size of the region are
768                  *              selected by the caller.
769                  *
770                  * Notes:       For best results, the selected base
771                  *              address should have enough LSB 0's to
772                  *              guarantee single address bit changes.
773                  *              For example, to test a 64-Kbyte
774                  *              region, select a base address on a
775                  *              64-Kbyte boundary. Also, select the
776                  *              region size as a power-of-two if at
777                  *              all possible.
778                  *
779                  * Returns:     0 if the test succeeds, 1 if the test fails.
780                  */
781                 len = ((ulong)end - (ulong)start)/sizeof(vu_long);
782                 pattern = (vu_long) 0xaaaaaaaa;
783                 anti_pattern = (vu_long) 0x55555555;
784
785                 PRINTF("%s:%d: length = 0x%.8lx\n",
786                         __FUNCTION__, __LINE__,
787                         len);
788                 /*
789                  * Write the default pattern at each of the
790                  * power-of-two offsets.
791                  */
792                 for (offset = 1; offset < len; offset <<= 1) {
793                         start[offset] = pattern;
794                 }
795
796                 /*
797                  * Check for address bits stuck high.
798                  */
799                 test_offset = 0;
800                 start[test_offset] = anti_pattern;
801
802                 for (offset = 1; offset < len; offset <<= 1) {
803                     temp = start[offset];
804                     if (temp != pattern) {
805                         printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
806                                 " expected 0x%.8lx, actual 0x%.8lx\n",
807                                 (ulong)&start[offset], pattern, temp);
808                         return 1;
809                     }
810                 }
811                 start[test_offset] = pattern;
812                 WATCHDOG_RESET();
813
814                 /*
815                  * Check for addr bits stuck low or shorted.
816                  */
817                 for (test_offset = 1; test_offset < len; test_offset <<= 1) {
818                     start[test_offset] = anti_pattern;
819
820                     for (offset = 1; offset < len; offset <<= 1) {
821                         temp = start[offset];
822                         if ((temp != pattern) && (offset != test_offset)) {
823                             printf ("\nFAILURE: Address bit stuck low or shorted @"
824                                 " 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n",
825                                 (ulong)&start[offset], pattern, temp);
826                             return 1;
827                         }
828                     }
829                     start[test_offset] = pattern;
830                 }
831
832                 /*
833                  * Description: Test the integrity of a physical
834                  *              memory device by performing an
835                  *              increment/decrement test over the
836                  *              entire region. In the process every
837                  *              storage bit in the device is tested
838                  *              as a zero and a one. The base address
839                  *              and the size of the region are
840                  *              selected by the caller.
841                  *
842                  * Returns:     0 if the test succeeds, 1 if the test fails.
843                  */
844                 num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1;
845
846                 /*
847                  * Fill memory with a known pattern.
848                  */
849                 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
850                         WATCHDOG_RESET();
851                         start[offset] = pattern;
852                 }
853
854                 /*
855                  * Check each location and invert it for the second pass.
856                  */
857                 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
858                     WATCHDOG_RESET();
859                     temp = start[offset];
860                     if (temp != pattern) {
861                         printf ("\nFAILURE (read/write) @ 0x%.8lx:"
862                                 " expected 0x%.8lx, actual 0x%.8lx)\n",
863                                 (ulong)&start[offset], pattern, temp);
864                         return 1;
865                     }
866
867                     anti_pattern = ~pattern;
868                     start[offset] = anti_pattern;
869                 }
870
871                 /*
872                  * Check each location for the inverted pattern and zero it.
873                  */
874                 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
875                     WATCHDOG_RESET();
876                     anti_pattern = ~pattern;
877                     temp = start[offset];
878                     if (temp != anti_pattern) {
879                         printf ("\nFAILURE (read/write): @ 0x%.8lx:"
880                                 " expected 0x%.8lx, actual 0x%.8lx)\n",
881                                 (ulong)&start[offset], anti_pattern, temp);
882                         return 1;
883                     }
884                     start[offset] = 0;
885                 }
886         }
887
888 #else /* The original, quickie test */
889         incr = 1;
890         for (;;) {
891                 if (ctrlc()) {
892                         putc ('\n');
893                         return 1;
894                 }
895
896                 if (iteration_limit && iterations > iteration_limit) {
897                         printf("Tested %d iteration(s) without errors.\n",
898                                 iterations-1);
899                         return 0;
900                 }
901                 ++iterations;
902
903                 printf ("\rPattern %08lX  Writing..."
904                         "%12s"
905                         "\b\b\b\b\b\b\b\b\b\b",
906                         pattern, "");
907
908                 for (addr=start,val=pattern; addr<end; addr++) {
909                         WATCHDOG_RESET();
910                         *addr = val;
911                         val  += incr;
912                 }
913
914                 puts ("Reading...");
915
916                 for (addr=start,val=pattern; addr<end; addr++) {
917                         WATCHDOG_RESET();
918                         readback = *addr;
919                         if (readback != val) {
920                                 printf ("\nMem error @ 0x%08X: "
921                                         "found %08lX, expected %08lX\n",
922                                         (uint)addr, readback, val);
923                                 rcode = 1;
924                         }
925                         val += incr;
926                 }
927
928                 /*
929                  * Flip the pattern each time to make lots of zeros and
930                  * then, the next time, lots of ones.  We decrement
931                  * the "negative" patterns and increment the "positive"
932                  * patterns to preserve this feature.
933                  */
934                 if(pattern & 0x80000000) {
935                         pattern = -pattern;     /* complement & increment */
936                 }
937                 else {
938                         pattern = ~pattern;
939                 }
940                 incr = -incr;
941         }
942 #endif
943         return rcode;
944 }
945
946
947 /* Modify memory.
948  *
949  * Syntax:
950  *      mm{.b, .w, .l} {addr}
951  *      nm{.b, .w, .l} {addr}
952  */
953 static int
954 mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
955 {
956         ulong   addr, i;
957         int     nbytes, size;
958         extern char console_buffer[];
959
960         if (argc != 2) {
961                 cmd_usage(cmdtp);
962                 return 1;
963         }
964
965 #ifdef CONFIG_BOOT_RETRY_TIME
966         reset_cmd_timeout();    /* got a good command to get here */
967 #endif
968         /* We use the last specified parameters, unless new ones are
969          * entered.
970          */
971         addr = mm_last_addr;
972         size = mm_last_size;
973
974         if ((flag & CMD_FLAG_REPEAT) == 0) {
975                 /* New command specified.  Check for a size specification.
976                  * Defaults to long if no or incorrect specification.
977                  */
978                 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
979                         return 1;
980
981                 /* Address is specified since argc > 1
982                 */
983                 addr = simple_strtoul(argv[1], NULL, 16);
984                 addr += base_address;
985         }
986
987 #ifdef CONFIG_HAS_DATAFLASH
988         if (addr_dataflash(addr)){
989                 puts ("Can't modify DataFlash in place. Use cp instead.\n\r");
990                 return 0;
991         }
992 #endif
993
994 #ifdef CONFIG_BLACKFIN
995         if (addr_bfin_on_chip_mem(addr)) {
996                 puts ("Can't modify L1 instruction in place. Use cp instead.\n\r");
997                 return 0;
998         }
999 #endif
1000
1001         /* Print the address, followed by value.  Then accept input for
1002          * the next value.  A non-converted value exits.
1003          */
1004         do {
1005                 printf("%08lx:", addr);
1006                 if (size == 4)
1007                         printf(" %08x", *((uint   *)addr));
1008                 else if (size == 2)
1009                         printf(" %04x", *((ushort *)addr));
1010                 else
1011                         printf(" %02x", *((u_char *)addr));
1012
1013                 nbytes = readline (" ? ");
1014                 if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
1015                         /* <CR> pressed as only input, don't modify current
1016                          * location and move to next. "-" pressed will go back.
1017                          */
1018                         if (incrflag)
1019                                 addr += nbytes ? -size : size;
1020                         nbytes = 1;
1021 #ifdef CONFIG_BOOT_RETRY_TIME
1022                         reset_cmd_timeout(); /* good enough to not time out */
1023 #endif
1024                 }
1025 #ifdef CONFIG_BOOT_RETRY_TIME
1026                 else if (nbytes == -2) {
1027                         break;  /* timed out, exit the command  */
1028                 }
1029 #endif
1030                 else {
1031                         char *endp;
1032                         i = simple_strtoul(console_buffer, &endp, 16);
1033                         nbytes = endp - console_buffer;
1034                         if (nbytes) {
1035 #ifdef CONFIG_BOOT_RETRY_TIME
1036                                 /* good enough to not time out
1037                                  */
1038                                 reset_cmd_timeout();
1039 #endif
1040                                 if (size == 4)
1041                                         *((uint   *)addr) = i;
1042                                 else if (size == 2)
1043                                         *((ushort *)addr) = i;
1044                                 else
1045                                         *((u_char *)addr) = i;
1046                                 if (incrflag)
1047                                         addr += size;
1048                         }
1049                 }
1050         } while (nbytes);
1051
1052         mm_last_addr = addr;
1053         mm_last_size = size;
1054         return 0;
1055 }
1056
1057 #ifndef CONFIG_CRC32_VERIFY
1058
1059 int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1060 {
1061         ulong addr, length;
1062         ulong crc;
1063         ulong *ptr;
1064
1065         if (argc < 3) {
1066                 cmd_usage(cmdtp);
1067                 return 1;
1068         }
1069
1070         addr = simple_strtoul (argv[1], NULL, 16);
1071         addr += base_address;
1072
1073         length = simple_strtoul (argv[2], NULL, 16);
1074
1075         crc = crc32 (0, (const uchar *) addr, length);
1076
1077         printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
1078                         addr, addr + length - 1, crc);
1079
1080         if (argc > 3) {
1081                 ptr = (ulong *) simple_strtoul (argv[3], NULL, 16);
1082                 *ptr = crc;
1083         }
1084
1085         return 0;
1086 }
1087
1088 #else   /* CONFIG_CRC32_VERIFY */
1089
1090 int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1091 {
1092         ulong addr, length;
1093         ulong crc;
1094         ulong *ptr;
1095         ulong vcrc;
1096         int verify;
1097         int ac;
1098         char **av;
1099
1100         if (argc < 3) {
1101   usage:
1102                 cmd_usage(cmdtp);
1103                 return 1;
1104         }
1105
1106         av = argv + 1;
1107         ac = argc - 1;
1108         if (strcmp(*av, "-v") == 0) {
1109                 verify = 1;
1110                 av++;
1111                 ac--;
1112                 if (ac < 3)
1113                         goto usage;
1114         } else
1115                 verify = 0;
1116
1117         addr = simple_strtoul(*av++, NULL, 16);
1118         addr += base_address;
1119         length = simple_strtoul(*av++, NULL, 16);
1120
1121         crc = crc32(0, (const uchar *) addr, length);
1122
1123         if (!verify) {
1124                 printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
1125                                 addr, addr + length - 1, crc);
1126                 if (ac > 2) {
1127                         ptr = (ulong *) simple_strtoul (*av++, NULL, 16);
1128                         *ptr = crc;
1129                 }
1130         } else {
1131                 vcrc = simple_strtoul(*av++, NULL, 16);
1132                 if (vcrc != crc) {
1133                         printf ("CRC32 for %08lx ... %08lx ==> %08lx != %08lx ** ERROR **\n",
1134                                         addr, addr + length - 1, crc, vcrc);
1135                         return 1;
1136                 }
1137         }
1138
1139         return 0;
1140
1141 }
1142 #endif  /* CONFIG_CRC32_VERIFY */
1143
1144
1145 #ifdef CONFIG_CMD_UNZIP
1146 int  gunzip (void *, int, unsigned char *, unsigned long *);
1147
1148 int do_unzip ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1149 {
1150         unsigned long src, dst;
1151         unsigned long src_len = ~0UL, dst_len = ~0UL;
1152
1153         switch (argc) {
1154                 case 4:
1155                         dst_len = simple_strtoul(argv[3], NULL, 16);
1156                         /* fall through */
1157                 case 3:
1158                         src = simple_strtoul(argv[1], NULL, 16);
1159                         dst = simple_strtoul(argv[2], NULL, 16);
1160                         break;
1161                 default:
1162                         cmd_usage(cmdtp);
1163                         return 1;
1164         }
1165
1166         return !!gunzip((void *) dst, dst_len, (void *) src, &src_len);
1167 }
1168 #endif /* CONFIG_CMD_UNZIP */
1169
1170
1171 /**************************************************/
1172 U_BOOT_CMD(
1173         md,     3,      1,      do_mem_md,
1174         "memory display",
1175         "[.b, .w, .l] address [# of objects]"
1176 );
1177
1178
1179 U_BOOT_CMD(
1180         mm,     2,      1,      do_mem_mm,
1181         "memory modify (auto-incrementing address)",
1182         "[.b, .w, .l] address"
1183 );
1184
1185
1186 U_BOOT_CMD(
1187         nm,     2,      1,      do_mem_nm,
1188         "memory modify (constant address)",
1189         "[.b, .w, .l] address"
1190 );
1191
1192 U_BOOT_CMD(
1193         mw,     4,      1,      do_mem_mw,
1194         "memory write (fill)",
1195         "[.b, .w, .l] address value [count]"
1196 );
1197
1198 U_BOOT_CMD(
1199         cp,     4,      1,      do_mem_cp,
1200         "memory copy",
1201         "[.b, .w, .l] source target count"
1202 );
1203
1204 U_BOOT_CMD(
1205         cmp,    4,      1,      do_mem_cmp,
1206         "memory compare",
1207         "[.b, .w, .l] addr1 addr2 count"
1208 );
1209
1210 #ifndef CONFIG_CRC32_VERIFY
1211
1212 U_BOOT_CMD(
1213         crc32,  4,      1,      do_mem_crc,
1214         "checksum calculation",
1215         "address count [addr]\n    - compute CRC32 checksum [save at addr]"
1216 );
1217
1218 #else   /* CONFIG_CRC32_VERIFY */
1219
1220 U_BOOT_CMD(
1221         crc32,  5,      1,      do_mem_crc,
1222         "checksum calculation",
1223         "address count [addr]\n    - compute CRC32 checksum [save at addr]\n"
1224         "-v address count crc\n    - verify crc of memory area"
1225 );
1226
1227 #endif  /* CONFIG_CRC32_VERIFY */
1228
1229 U_BOOT_CMD(
1230         base,   2,      1,      do_mem_base,
1231         "print or set address offset",
1232         "\n    - print address offset for memory commands\n"
1233         "base off\n    - set address offset for memory commands to 'off'"
1234 );
1235
1236 U_BOOT_CMD(
1237         loop,   3,      1,      do_mem_loop,
1238         "infinite loop on address range",
1239         "[.b, .w, .l] address number_of_objects"
1240 );
1241
1242 #ifdef CONFIG_LOOPW
1243 U_BOOT_CMD(
1244         loopw,  4,      1,      do_mem_loopw,
1245         "infinite write loop on address range",
1246         "[.b, .w, .l] address number_of_objects data_to_write"
1247 );
1248 #endif /* CONFIG_LOOPW */
1249
1250 U_BOOT_CMD(
1251         mtest,  5,      1,      do_mem_mtest,
1252         "simple RAM read/write test",
1253         "[start [end [pattern [iterations]]]]"
1254 );
1255
1256 #ifdef CONFIG_MX_CYCLIC
1257 U_BOOT_CMD(
1258         mdc,    4,      1,      do_mem_mdc,
1259         "memory display cyclic",
1260         "[.b, .w, .l] address count delay(ms)"
1261 );
1262
1263 U_BOOT_CMD(
1264         mwc,    4,      1,      do_mem_mwc,
1265         "memory write cyclic",
1266         "[.b, .w, .l] address value delay(ms)"
1267 );
1268 #endif /* CONFIG_MX_CYCLIC */
1269
1270 #ifdef CONFIG_CMD_UNZIP
1271 U_BOOT_CMD(
1272         unzip,  4,      1,      do_unzip,
1273         "unzip a memory region",
1274         "srcaddr dstaddr [dstsize]"
1275 );
1276 #endif /* CONFIG_CMD_UNZIP */