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