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