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