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