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