1
2
3
4
5
6
7
8
9
10
11
12
13#include <common.h>
14#include <console.h>
15#include <bootretry.h>
16#include <cli.h>
17#include <command.h>
18#include <console.h>
19#include <display_options.h>
20#ifdef CONFIG_MTD_NOR_FLASH
21#include <flash.h>
22#endif
23#include <hash.h>
24#include <log.h>
25#include <mapmem.h>
26#include <rand.h>
27#include <watchdog.h>
28#include <asm/global_data.h>
29#include <asm/io.h>
30#include <linux/bitops.h>
31#include <linux/compiler.h>
32#include <linux/ctype.h>
33#include <linux/delay.h>
34
35DECLARE_GLOBAL_DATA_PTR;
36
37
38#ifdef MEM_SUPPORT_64BIT_DATA
39#define SUPPORT_64BIT_DATA 1
40#define HELP_Q ", .q"
41#else
42#define SUPPORT_64BIT_DATA 0
43#define HELP_Q ""
44#endif
45
46static int mod_mem(struct cmd_tbl *, int, int, int, char * const []);
47
48
49
50
51static ulong dp_last_addr, dp_last_size;
52static ulong dp_last_length = 0x40;
53static ulong mm_last_addr, mm_last_size;
54
55static ulong base_address = 0;
56#ifdef CONFIG_CMD_MEM_SEARCH
57static ulong dp_last_ms_length;
58static u8 search_buf[64];
59static uint search_len;
60#endif
61
62
63
64
65
66
67#define DISP_LINE_LEN 16
68static int do_mem_md(struct cmd_tbl *cmdtp, int flag, int argc,
69 char *const argv[])
70{
71 ulong addr, length, bytes;
72 const void *buf;
73 int size;
74 int rc = 0;
75
76
77
78
79 addr = dp_last_addr;
80 size = dp_last_size;
81 length = dp_last_length;
82
83 if (argc < 2)
84 return CMD_RET_USAGE;
85
86 if ((flag & CMD_FLAG_REPEAT) == 0) {
87
88
89
90 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
91 return 1;
92
93
94
95 addr = hextoul(argv[1], NULL);
96 addr += base_address;
97
98
99
100
101 if (argc > 2)
102 length = hextoul(argv[2], NULL);
103 }
104
105 bytes = size * length;
106 buf = map_sysmem(addr, bytes);
107
108
109 print_buffer(addr, buf, size, length, DISP_LINE_LEN / size);
110 addr += bytes;
111 unmap_sysmem(buf);
112
113 dp_last_addr = addr;
114 dp_last_length = length;
115 dp_last_size = size;
116 return (rc);
117}
118
119static int do_mem_mm(struct cmd_tbl *cmdtp, int flag, int argc,
120 char *const argv[])
121{
122 return mod_mem (cmdtp, 1, flag, argc, argv);
123}
124
125static int do_mem_nm(struct cmd_tbl *cmdtp, int flag, int argc,
126 char *const argv[])
127{
128 return mod_mem (cmdtp, 0, flag, argc, argv);
129}
130
131static int do_mem_mw(struct cmd_tbl *cmdtp, int flag, int argc,
132 char *const argv[])
133{
134 ulong writeval;
135 ulong addr, count;
136 int size;
137 void *buf, *start;
138 ulong bytes;
139
140 if ((argc < 3) || (argc > 4))
141 return CMD_RET_USAGE;
142
143
144
145 if ((size = cmd_get_data_size(argv[0], 4)) < 1)
146 return 1;
147
148
149
150 addr = hextoul(argv[1], NULL);
151 addr += base_address;
152
153
154
155 if (SUPPORT_64BIT_DATA)
156 writeval = simple_strtoull(argv[2], NULL, 16);
157 else
158 writeval = hextoul(argv[2], NULL);
159
160
161 if (argc == 4) {
162 count = hextoul(argv[3], NULL);
163 } else {
164 count = 1;
165 }
166
167 bytes = size * count;
168 start = map_sysmem(addr, bytes);
169 buf = start;
170 while (count-- > 0) {
171 if (size == 4)
172 *((u32 *)buf) = (u32)writeval;
173 else if (SUPPORT_64BIT_DATA && size == 8)
174 *((ulong *)buf) = writeval;
175 else if (size == 2)
176 *((u16 *)buf) = (u16)writeval;
177 else
178 *((u8 *)buf) = (u8)writeval;
179 buf += size;
180 }
181 unmap_sysmem(start);
182 return 0;
183}
184
185#ifdef CONFIG_CMD_MX_CYCLIC
186static int do_mem_mdc(struct cmd_tbl *cmdtp, int flag, int argc,
187 char *const argv[])
188{
189 int i;
190 ulong count;
191
192 if (argc < 4)
193 return CMD_RET_USAGE;
194
195 count = dectoul(argv[3], NULL);
196
197 for (;;) {
198 do_mem_md (NULL, 0, 3, argv);
199
200
201 for (i=0; i<count; i++)
202 udelay(1000);
203
204
205 if (ctrlc()) {
206 puts("Abort\n");
207 return 0;
208 }
209 }
210
211 return 0;
212}
213
214static int do_mem_mwc(struct cmd_tbl *cmdtp, int flag, int argc,
215 char *const argv[])
216{
217 int i;
218 ulong count;
219
220 if (argc < 4)
221 return CMD_RET_USAGE;
222
223 count = dectoul(argv[3], NULL);
224
225 for (;;) {
226 do_mem_mw (NULL, 0, 3, argv);
227
228
229 for (i=0; i<count; i++)
230 udelay(1000);
231
232
233 if (ctrlc()) {
234 puts("Abort\n");
235 return 0;
236 }
237 }
238
239 return 0;
240}
241#endif
242
243static int do_mem_cmp(struct cmd_tbl *cmdtp, int flag, int argc,
244 char *const argv[])
245{
246 ulong addr1, addr2, count, ngood, bytes;
247 int size;
248 int rcode = 0;
249 const char *type;
250 const void *buf1, *buf2, *base;
251 ulong word1, word2;
252
253 if (argc != 4)
254 return CMD_RET_USAGE;
255
256
257
258 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
259 return 1;
260 type = size == 8 ? "double word" :
261 size == 4 ? "word" :
262 size == 2 ? "halfword" : "byte";
263
264 addr1 = hextoul(argv[1], NULL);
265 addr1 += base_address;
266
267 addr2 = hextoul(argv[2], NULL);
268 addr2 += base_address;
269
270 count = hextoul(argv[3], NULL);
271
272 bytes = size * count;
273 base = buf1 = map_sysmem(addr1, bytes);
274 buf2 = map_sysmem(addr2, bytes);
275 for (ngood = 0; ngood < count; ++ngood) {
276 if (size == 4) {
277 word1 = *(u32 *)buf1;
278 word2 = *(u32 *)buf2;
279 } else if (SUPPORT_64BIT_DATA && size == 8) {
280 word1 = *(ulong *)buf1;
281 word2 = *(ulong *)buf2;
282 } else if (size == 2) {
283 word1 = *(u16 *)buf1;
284 word2 = *(u16 *)buf2;
285 } else {
286 word1 = *(u8 *)buf1;
287 word2 = *(u8 *)buf2;
288 }
289 if (word1 != word2) {
290 ulong offset = buf1 - base;
291 printf("%s at 0x%08lx (%#0*lx) != %s at 0x%08lx (%#0*lx)\n",
292 type, (ulong)(addr1 + offset), size, word1,
293 type, (ulong)(addr2 + offset), size, word2);
294 rcode = 1;
295 break;
296 }
297
298 buf1 += size;
299 buf2 += size;
300
301
302 if ((ngood % (64 << 10)) == 0)
303 WATCHDOG_RESET();
304 }
305 unmap_sysmem(buf1);
306 unmap_sysmem(buf2);
307
308 printf("Total of %ld %s(s) were the same\n", ngood, type);
309 return rcode;
310}
311
312static int do_mem_cp(struct cmd_tbl *cmdtp, int flag, int argc,
313 char *const argv[])
314{
315 ulong addr, dest, count;
316 void *src, *dst;
317 int size;
318
319 if (argc != 4)
320 return CMD_RET_USAGE;
321
322
323
324 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
325 return 1;
326
327 addr = hextoul(argv[1], NULL);
328 addr += base_address;
329
330 dest = hextoul(argv[2], NULL);
331 dest += base_address;
332
333 count = hextoul(argv[3], NULL);
334
335 if (count == 0) {
336 puts ("Zero length ???\n");
337 return 1;
338 }
339
340 src = map_sysmem(addr, count * size);
341 dst = map_sysmem(dest, count * size);
342
343#ifdef CONFIG_MTD_NOR_FLASH
344
345 if (addr2info((ulong)dst)) {
346 int rc;
347
348 puts ("Copy to Flash... ");
349
350 rc = flash_write((char *)src, (ulong)dst, count * size);
351 if (rc != 0) {
352 flash_perror(rc);
353 unmap_sysmem(src);
354 unmap_sysmem(dst);
355 return (1);
356 }
357 puts ("done\n");
358 unmap_sysmem(src);
359 unmap_sysmem(dst);
360 return 0;
361 }
362#endif
363
364 memcpy(dst, src, count * size);
365
366 unmap_sysmem(src);
367 unmap_sysmem(dst);
368 return 0;
369}
370
371#ifdef CONFIG_CMD_MEM_SEARCH
372static int do_mem_search(struct cmd_tbl *cmdtp, int flag, int argc,
373 char *const argv[])
374{
375 ulong addr, length, bytes, offset;
376 u8 *ptr, *end, *buf;
377 bool quiet = false;
378 ulong last_pos;
379 ulong last_addr;
380 int limit = 10;
381 int used_len;
382 int count;
383 int size;
384 int i;
385
386
387 addr = dp_last_addr;
388 size = dp_last_size;
389 length = dp_last_ms_length;
390
391 if (argc < 3)
392 return CMD_RET_USAGE;
393
394 if (!(flag & CMD_FLAG_REPEAT)) {
395
396
397
398
399 size = cmd_get_data_size(argv[0], 4);
400 if (size < 0 && size != CMD_DATA_SIZE_STR)
401 return 1;
402
403 argc--;
404 argv++;
405 while (argc && *argv[0] == '-') {
406 int ch = argv[0][1];
407
408 if (ch == 'q')
409 quiet = true;
410 else if (ch == 'l' && isxdigit(argv[0][2]))
411 limit = hextoul(argv[0] + 2, NULL);
412 else
413 return CMD_RET_USAGE;
414 argc--;
415 argv++;
416 }
417
418
419 addr = hextoul(argv[0], NULL);
420 addr += base_address;
421
422
423 length = hextoul(argv[1], NULL);
424
425
426 end = search_buf + sizeof(search_buf);
427 for (i = 2, ptr = search_buf; i < argc && ptr < end; i++) {
428 if (MEM_SUPPORT_64BIT_DATA && size == 8) {
429 u64 val = simple_strtoull(argv[i], NULL, 16);
430
431 *(u64 *)ptr = val;
432 } else if (size == -2) {
433 int len = min(strlen(argv[i]),
434 (size_t)(end - ptr));
435
436 memcpy(ptr, argv[i], len);
437 ptr += len;
438 continue;
439 } else {
440 u32 val = hextoul(argv[i], NULL);
441
442 switch (size) {
443 case 1:
444 *ptr = val;
445 break;
446 case 2:
447 *(u16 *)ptr = val;
448 break;
449 case 4:
450 *(u32 *)ptr = val;
451 break;
452 }
453 }
454 ptr += size;
455 }
456 search_len = ptr - search_buf;
457 }
458
459
460 if (size == -2)
461 size = 1;
462 bytes = size * length;
463 buf = map_sysmem(addr, bytes);
464 last_pos = 0;
465 last_addr = 0;
466 count = 0;
467 for (offset = 0;
468 offset < bytes && offset <= bytes - search_len && count < limit;
469 offset += size) {
470 void *ptr = buf + offset;
471
472 if (!memcmp(ptr, search_buf, search_len)) {
473 uint align = (addr + offset) & 0xf;
474 ulong match = addr + offset;
475
476 if (!count || (last_addr & ~0xf) != (match & ~0xf)) {
477 if (!quiet) {
478 if (count)
479 printf("--\n");
480 print_buffer(match - align, ptr - align,
481 size,
482 ALIGN(search_len + align,
483 16) / size, 0);
484 }
485 last_addr = match;
486 last_pos = offset / size;
487 }
488 count++;
489 }
490 }
491 if (!quiet) {
492 printf("%d match%s", count, count == 1 ? "" : "es");
493 if (count == limit)
494 printf(" (repeat command to check for more)");
495 printf("\n");
496 }
497 env_set_hex("memmatches", count);
498 env_set_hex("memaddr", last_addr);
499 env_set_hex("mempos", last_pos);
500
501 unmap_sysmem(buf);
502
503 used_len = offset / size;
504 dp_last_addr = addr + used_len;
505 dp_last_size = size;
506 dp_last_ms_length = length < used_len ? 0 : length - used_len;
507
508 return count ? 0 : CMD_RET_FAILURE;
509}
510#endif
511
512static int do_mem_base(struct cmd_tbl *cmdtp, int flag, int argc,
513 char *const argv[])
514{
515 if (argc > 1) {
516
517
518 base_address = hextoul(argv[1], NULL);
519 }
520
521
522 printf("Base Address: 0x%08lx\n", base_address);
523 return 0;
524}
525
526static int do_mem_loop(struct cmd_tbl *cmdtp, int flag, int argc,
527 char *const argv[])
528{
529 ulong addr, length, i, bytes;
530 int size;
531 volatile ulong *llp;
532 volatile u32 *longp;
533 volatile u16 *shortp;
534 volatile u8 *cp;
535 const void *buf;
536
537 if (argc < 3)
538 return CMD_RET_USAGE;
539
540
541
542
543
544 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
545 return 1;
546
547
548
549 addr = hextoul(argv[1], NULL);
550
551
552
553 length = hextoul(argv[2], NULL);
554
555 bytes = size * length;
556 buf = map_sysmem(addr, bytes);
557
558
559
560
561 if (length == 1) {
562 if (SUPPORT_64BIT_DATA && size == 8) {
563 llp = (ulong *)buf;
564 for (;;)
565 i = *llp;
566 }
567 if (size == 4) {
568 longp = (u32 *)buf;
569 for (;;)
570 i = *longp;
571 }
572 if (size == 2) {
573 shortp = (u16 *)buf;
574 for (;;)
575 i = *shortp;
576 }
577 cp = (u8 *)buf;
578 for (;;)
579 i = *cp;
580 }
581
582 if (SUPPORT_64BIT_DATA && size == 8) {
583 for (;;) {
584 llp = (ulong *)buf;
585 i = length;
586 while (i-- > 0)
587 *llp++;
588 }
589 }
590 if (size == 4) {
591 for (;;) {
592 longp = (u32 *)buf;
593 i = length;
594 while (i-- > 0)
595 *longp++;
596 }
597 }
598 if (size == 2) {
599 for (;;) {
600 shortp = (u16 *)buf;
601 i = length;
602 while (i-- > 0)
603 *shortp++;
604 }
605 }
606 for (;;) {
607 cp = (u8 *)buf;
608 i = length;
609 while (i-- > 0)
610 *cp++;
611 }
612 unmap_sysmem(buf);
613
614 return 0;
615}
616
617#ifdef CONFIG_LOOPW
618static int do_mem_loopw(struct cmd_tbl *cmdtp, int flag, int argc,
619 char *const argv[])
620{
621 ulong addr, length, i, bytes;
622 int size;
623 volatile ulong *llp;
624 ulong data;
625 volatile u32 *longp;
626 volatile u16 *shortp;
627 volatile u8 *cp;
628 void *buf;
629
630 if (argc < 4)
631 return CMD_RET_USAGE;
632
633
634
635
636
637 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
638 return 1;
639
640
641
642 addr = hextoul(argv[1], NULL);
643
644
645
646 length = hextoul(argv[2], NULL);
647
648
649 if (SUPPORT_64BIT_DATA)
650 data = simple_strtoull(argv[3], NULL, 16);
651 else
652 data = hextoul(argv[3], NULL);
653
654 bytes = size * length;
655 buf = map_sysmem(addr, bytes);
656
657
658
659
660 if (length == 1) {
661 if (SUPPORT_64BIT_DATA && size == 8) {
662 llp = (ulong *)buf;
663 for (;;)
664 *llp = data;
665 }
666 if (size == 4) {
667 longp = (u32 *)buf;
668 for (;;)
669 *longp = data;
670 }
671 if (size == 2) {
672 shortp = (u16 *)buf;
673 for (;;)
674 *shortp = data;
675 }
676 cp = (u8 *)buf;
677 for (;;)
678 *cp = data;
679 }
680
681 if (SUPPORT_64BIT_DATA && size == 8) {
682 for (;;) {
683 llp = (ulong *)buf;
684 i = length;
685 while (i-- > 0)
686 *llp++ = data;
687 }
688 }
689 if (size == 4) {
690 for (;;) {
691 longp = (u32 *)buf;
692 i = length;
693 while (i-- > 0)
694 *longp++ = data;
695 }
696 }
697 if (size == 2) {
698 for (;;) {
699 shortp = (u16 *)buf;
700 i = length;
701 while (i-- > 0)
702 *shortp++ = data;
703 }
704 }
705 for (;;) {
706 cp = (u8 *)buf;
707 i = length;
708 while (i-- > 0)
709 *cp++ = data;
710 }
711}
712#endif
713
714#ifdef CONFIG_CMD_MEMTEST
715static ulong mem_test_alt(vu_long *buf, ulong start_addr, ulong end_addr,
716 vu_long *dummy)
717{
718 vu_long *addr;
719 ulong errs = 0;
720 ulong val, readback;
721 int j;
722 vu_long offset;
723 vu_long test_offset;
724 vu_long pattern;
725 vu_long temp;
726 vu_long anti_pattern;
727 vu_long num_words;
728 static const ulong bitpattern[] = {
729 0x00000001,
730 0x00000003,
731 0x00000007,
732 0x0000000F,
733 0x00000005,
734 0x00000015,
735 0x00000055,
736 0xaaaaaaaa,
737 };
738
739 num_words = (end_addr - start_addr) / sizeof(vu_long);
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758 addr = buf;
759 for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
760 val = bitpattern[j];
761 for (; val != 0; val <<= 1) {
762 *addr = val;
763 *dummy = ~val;
764 readback = *addr;
765 if (readback != val) {
766 printf("FAILURE (data line): "
767 "expected %08lx, actual %08lx\n",
768 val, readback);
769 errs++;
770 if (ctrlc())
771 return -1;
772 }
773 *addr = ~val;
774 *dummy = val;
775 readback = *addr;
776 if (readback != ~val) {
777 printf("FAILURE (data line): "
778 "Is %08lx, should be %08lx\n",
779 readback, ~val);
780 errs++;
781 if (ctrlc())
782 return -1;
783 }
784 }
785 }
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821 pattern = (vu_long) 0xaaaaaaaa;
822 anti_pattern = (vu_long) 0x55555555;
823
824 debug("%s:%d: length = 0x%.8lx\n", __func__, __LINE__, num_words);
825
826
827
828
829 for (offset = 1; offset < num_words; offset <<= 1)
830 addr[offset] = pattern;
831
832
833
834
835 test_offset = 0;
836 addr[test_offset] = anti_pattern;
837
838 for (offset = 1; offset < num_words; offset <<= 1) {
839 temp = addr[offset];
840 if (temp != pattern) {
841 printf("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
842 " expected 0x%.8lx, actual 0x%.8lx\n",
843 start_addr + offset*sizeof(vu_long),
844 pattern, temp);
845 errs++;
846 if (ctrlc())
847 return -1;
848 }
849 }
850 addr[test_offset] = pattern;
851 WATCHDOG_RESET();
852
853
854
855
856 for (test_offset = 1; test_offset < num_words; test_offset <<= 1) {
857 addr[test_offset] = anti_pattern;
858
859 for (offset = 1; offset < num_words; offset <<= 1) {
860 temp = addr[offset];
861 if ((temp != pattern) && (offset != test_offset)) {
862 printf("\nFAILURE: Address bit stuck low or"
863 " shorted @ 0x%.8lx: expected 0x%.8lx,"
864 " actual 0x%.8lx\n",
865 start_addr + offset*sizeof(vu_long),
866 pattern, temp);
867 errs++;
868 if (ctrlc())
869 return -1;
870 }
871 }
872 addr[test_offset] = pattern;
873 }
874
875
876
877
878
879
880
881
882
883
884
885
886
887 num_words++;
888
889
890
891
892 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
893 WATCHDOG_RESET();
894 addr[offset] = pattern;
895 }
896
897
898
899
900 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
901 WATCHDOG_RESET();
902 temp = addr[offset];
903 if (temp != pattern) {
904 printf("\nFAILURE (read/write) @ 0x%.8lx:"
905 " expected 0x%.8lx, actual 0x%.8lx)\n",
906 start_addr + offset*sizeof(vu_long),
907 pattern, temp);
908 errs++;
909 if (ctrlc())
910 return -1;
911 }
912
913 anti_pattern = ~pattern;
914 addr[offset] = anti_pattern;
915 }
916
917
918
919
920 for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
921 WATCHDOG_RESET();
922 anti_pattern = ~pattern;
923 temp = addr[offset];
924 if (temp != anti_pattern) {
925 printf("\nFAILURE (read/write): @ 0x%.8lx:"
926 " expected 0x%.8lx, actual 0x%.8lx)\n",
927 start_addr + offset*sizeof(vu_long),
928 anti_pattern, temp);
929 errs++;
930 if (ctrlc())
931 return -1;
932 }
933 addr[offset] = 0;
934 }
935
936 return errs;
937}
938
939static int compare_regions(volatile unsigned long *bufa,
940 volatile unsigned long *bufb, size_t count)
941{
942 volatile unsigned long *p1 = bufa;
943 volatile unsigned long *p2 = bufb;
944 int errs = 0;
945 size_t i;
946
947 for (i = 0; i < count; i++, p1++, p2++) {
948 if (*p1 != *p2) {
949 printf("FAILURE: 0x%08lx != 0x%08lx (delta=0x%08lx -> bit %ld) at offset 0x%08lx\n",
950 (unsigned long)*p1, (unsigned long)*p2,
951 *p1 ^ *p2, __ffs(*p1 ^ *p2),
952 (unsigned long)(i * sizeof(unsigned long)));
953 errs++;
954 }
955 }
956
957 return errs;
958}
959
960static ulong test_bitflip_comparison(volatile unsigned long *bufa,
961 volatile unsigned long *bufb, size_t count)
962{
963 volatile unsigned long *p1 = bufa;
964 volatile unsigned long *p2 = bufb;
965 unsigned int j, k;
966 unsigned long q;
967 size_t i;
968 int max;
969 int errs = 0;
970
971 max = sizeof(unsigned long) * 8;
972 for (k = 0; k < max; k++) {
973 q = 0x00000001L << k;
974 for (j = 0; j < 8; j++) {
975 WATCHDOG_RESET();
976 q = ~q;
977 p1 = (volatile unsigned long *)bufa;
978 p2 = (volatile unsigned long *)bufb;
979 for (i = 0; i < count; i++)
980 *p1++ = *p2++ = (i % 2) == 0 ? q : ~q;
981
982 errs += compare_regions(bufa, bufb, count);
983 }
984
985 if (ctrlc())
986 return -1UL;
987 }
988
989 return errs;
990}
991
992static ulong mem_test_bitflip(vu_long *buf, ulong start, ulong end)
993{
994
995
996
997
998
999 ulong half_size = (end - start + 1) / 2 / sizeof(unsigned long);
1000
1001 return test_bitflip_comparison(buf, buf + half_size, half_size);
1002}
1003
1004static ulong mem_test_quick(vu_long *buf, ulong start_addr, ulong end_addr,
1005 vu_long pattern, int iteration)
1006{
1007 vu_long *end;
1008 vu_long *addr;
1009 ulong errs = 0;
1010 ulong incr, length;
1011 ulong val, readback;
1012
1013
1014 incr = 1;
1015 if (iteration & 1) {
1016 incr = -incr;
1017
1018
1019
1020
1021
1022
1023 if (pattern & 0x80000000)
1024 pattern = -pattern;
1025 else
1026 pattern = ~pattern;
1027 }
1028 length = (end_addr - start_addr) / sizeof(ulong);
1029 end = buf + length;
1030 printf("\rPattern %08lX Writing..."
1031 "%12s"
1032 "\b\b\b\b\b\b\b\b\b\b",
1033 pattern, "");
1034
1035 for (addr = buf, val = pattern; addr < end; addr++) {
1036 WATCHDOG_RESET();
1037 *addr = val;
1038 val += incr;
1039 }
1040
1041 puts("Reading...");
1042
1043 for (addr = buf, val = pattern; addr < end; addr++) {
1044 WATCHDOG_RESET();
1045 readback = *addr;
1046 if (readback != val) {
1047 ulong offset = addr - buf;
1048
1049 printf("\nMem error @ 0x%08X: "
1050 "found %08lX, expected %08lX\n",
1051 (uint)(uintptr_t)(start_addr + offset*sizeof(vu_long)),
1052 readback, val);
1053 errs++;
1054 if (ctrlc())
1055 return -1;
1056 }
1057 val += incr;
1058 }
1059
1060 return errs;
1061}
1062
1063
1064
1065
1066
1067
1068static int do_mem_mtest(struct cmd_tbl *cmdtp, int flag, int argc,
1069 char *const argv[])
1070{
1071 ulong start, end;
1072 vu_long scratch_space;
1073 vu_long *buf, *dummy = &scratch_space;
1074 ulong iteration_limit = 0;
1075 ulong count = 0;
1076 ulong errs = 0;
1077 ulong pattern = 0;
1078 int iteration;
1079
1080 start = CONFIG_SYS_MEMTEST_START;
1081 end = CONFIG_SYS_MEMTEST_END;
1082
1083 if (argc > 1)
1084 if (strict_strtoul(argv[1], 16, &start) < 0)
1085 return CMD_RET_USAGE;
1086
1087 if (argc > 2)
1088 if (strict_strtoul(argv[2], 16, &end) < 0)
1089 return CMD_RET_USAGE;
1090
1091 if (argc > 3)
1092 if (strict_strtoul(argv[3], 16, &pattern) < 0)
1093 return CMD_RET_USAGE;
1094
1095 if (argc > 4)
1096 if (strict_strtoul(argv[4], 16, &iteration_limit) < 0)
1097 return CMD_RET_USAGE;
1098
1099 if (end < start) {
1100 printf("Refusing to do empty test\n");
1101 return -1;
1102 }
1103
1104 printf("Testing %08lx ... %08lx:\n", start, end);
1105 debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__,
1106 start, end);
1107
1108 buf = map_sysmem(start, end - start);
1109 for (iteration = 0;
1110 !iteration_limit || iteration < iteration_limit;
1111 iteration++) {
1112 if (ctrlc()) {
1113 errs = -1UL;
1114 break;
1115 }
1116
1117 printf("Iteration: %6d\r", iteration + 1);
1118 debug("\n");
1119 if (IS_ENABLED(CONFIG_SYS_ALT_MEMTEST)) {
1120 errs = mem_test_alt(buf, start, end, dummy);
1121 if (errs == -1UL)
1122 break;
1123 if (IS_ENABLED(CONFIG_SYS_ALT_MEMTEST_BITFLIP)) {
1124 count += errs;
1125 errs = mem_test_bitflip(buf, start, end);
1126 }
1127 } else {
1128 errs = mem_test_quick(buf, start, end, pattern,
1129 iteration);
1130 }
1131 if (errs == -1UL)
1132 break;
1133 count += errs;
1134 }
1135
1136 unmap_sysmem((void *)buf);
1137
1138 if (errs == -1UL) {
1139
1140 putc('\n');
1141 }
1142 printf("Tested %d iteration(s) with %lu errors.\n", iteration, count);
1143
1144 return errs != 0;
1145}
1146#endif
1147
1148
1149
1150
1151
1152
1153static int
1154mod_mem(struct cmd_tbl *cmdtp, int incrflag, int flag, int argc,
1155 char *const argv[])
1156{
1157 ulong addr;
1158 ulong i;
1159 int nbytes, size;
1160 void *ptr = NULL;
1161
1162 if (argc != 2)
1163 return CMD_RET_USAGE;
1164
1165 bootretry_reset_cmd_timeout();
1166
1167
1168
1169 addr = mm_last_addr;
1170 size = mm_last_size;
1171
1172 if ((flag & CMD_FLAG_REPEAT) == 0) {
1173
1174
1175
1176 if ((size = cmd_get_data_size(argv[0], 4)) < 0)
1177 return 1;
1178
1179
1180
1181 addr = hextoul(argv[1], NULL);
1182 addr += base_address;
1183 }
1184
1185
1186
1187
1188 do {
1189 ptr = map_sysmem(addr, size);
1190 printf("%08lx:", addr);
1191 if (size == 4)
1192 printf(" %08x", *((u32 *)ptr));
1193 else if (SUPPORT_64BIT_DATA && size == 8)
1194 printf(" %0lx", *((ulong *)ptr));
1195 else if (size == 2)
1196 printf(" %04x", *((u16 *)ptr));
1197 else
1198 printf(" %02x", *((u8 *)ptr));
1199
1200 nbytes = cli_readline(" ? ");
1201 if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
1202
1203
1204
1205 if (incrflag)
1206 addr += nbytes ? -size : size;
1207 nbytes = 1;
1208
1209 bootretry_reset_cmd_timeout();
1210 }
1211#ifdef CONFIG_BOOT_RETRY_TIME
1212 else if (nbytes == -2) {
1213 break;
1214 }
1215#endif
1216 else {
1217 char *endp;
1218 if (SUPPORT_64BIT_DATA)
1219 i = simple_strtoull(console_buffer, &endp, 16);
1220 else
1221 i = hextoul(console_buffer, &endp);
1222 nbytes = endp - console_buffer;
1223 if (nbytes) {
1224
1225
1226 bootretry_reset_cmd_timeout();
1227 if (size == 4)
1228 *((u32 *)ptr) = i;
1229 else if (SUPPORT_64BIT_DATA && size == 8)
1230 *((ulong *)ptr) = i;
1231 else if (size == 2)
1232 *((u16 *)ptr) = i;
1233 else
1234 *((u8 *)ptr) = i;
1235 if (incrflag)
1236 addr += size;
1237 }
1238 }
1239 } while (nbytes);
1240 if (ptr)
1241 unmap_sysmem(ptr);
1242
1243 mm_last_addr = addr;
1244 mm_last_size = size;
1245 return 0;
1246}
1247
1248#ifdef CONFIG_CMD_CRC32
1249
1250static int do_mem_crc(struct cmd_tbl *cmdtp, int flag, int argc,
1251 char *const argv[])
1252{
1253 int flags = 0;
1254 int ac;
1255 char * const *av;
1256
1257 if (argc < 3)
1258 return CMD_RET_USAGE;
1259
1260 av = argv + 1;
1261 ac = argc - 1;
1262#ifdef CONFIG_CRC32_VERIFY
1263 if (strcmp(*av, "-v") == 0) {
1264 flags |= HASH_FLAG_VERIFY | HASH_FLAG_ENV;
1265 av++;
1266 ac--;
1267 }
1268#endif
1269
1270 return hash_command("crc32", flags, cmdtp, flag, ac, av);
1271}
1272
1273#endif
1274
1275#ifdef CONFIG_CMD_RANDOM
1276static int do_random(struct cmd_tbl *cmdtp, int flag, int argc,
1277 char *const argv[])
1278{
1279 unsigned long addr, len;
1280 unsigned long seed;
1281 unsigned int *buf, *start;
1282 unsigned char *buf8;
1283 unsigned int i;
1284
1285 if (argc < 3 || argc > 4)
1286 return CMD_RET_USAGE;
1287
1288 len = hextoul(argv[2], NULL);
1289 addr = hextoul(argv[1], NULL);
1290
1291 if (argc == 4) {
1292 seed = hextoul(argv[3], NULL);
1293 if (seed == 0) {
1294 printf("The seed cannot be 0. Using 0xDEADBEEF.\n");
1295 seed = 0xDEADBEEF;
1296 }
1297 } else {
1298 seed = get_timer(0) ^ rand();
1299 }
1300
1301 srand(seed);
1302 start = map_sysmem(addr, len);
1303 buf = start;
1304 for (i = 0; i < (len / 4); i++)
1305 *buf++ = rand();
1306
1307 buf8 = (unsigned char *)buf;
1308 for (i = 0; i < (len % 4); i++)
1309 *buf8++ = rand() & 0xFF;
1310
1311 unmap_sysmem(start);
1312 printf("%lu bytes filled with random data\n", len);
1313
1314 return CMD_RET_SUCCESS;
1315}
1316#endif
1317
1318
1319U_BOOT_CMD(
1320 md, 3, 1, do_mem_md,
1321 "memory display",
1322 "[.b, .w, .l" HELP_Q "] address [# of objects]"
1323);
1324
1325
1326U_BOOT_CMD(
1327 mm, 2, 1, do_mem_mm,
1328 "memory modify (auto-incrementing address)",
1329 "[.b, .w, .l" HELP_Q "] address"
1330);
1331
1332
1333U_BOOT_CMD(
1334 nm, 2, 1, do_mem_nm,
1335 "memory modify (constant address)",
1336 "[.b, .w, .l" HELP_Q "] address"
1337);
1338
1339U_BOOT_CMD(
1340 mw, 4, 1, do_mem_mw,
1341 "memory write (fill)",
1342 "[.b, .w, .l" HELP_Q "] address value [count]"
1343);
1344
1345U_BOOT_CMD(
1346 cp, 4, 1, do_mem_cp,
1347 "memory copy",
1348 "[.b, .w, .l" HELP_Q "] source target count"
1349);
1350
1351U_BOOT_CMD(
1352 cmp, 4, 1, do_mem_cmp,
1353 "memory compare",
1354 "[.b, .w, .l" HELP_Q "] addr1 addr2 count"
1355);
1356
1357#ifdef CONFIG_CMD_MEM_SEARCH
1358
1359U_BOOT_CMD(
1360 ms, 255, 1, do_mem_search,
1361 "memory search",
1362 "[.b, .w, .l" HELP_Q ", .s] [-q | -<n>] address #-of-objects <value>..."
1363 " -q = quiet, -l<val> = match limit"
1364);
1365#endif
1366
1367#ifdef CONFIG_CMD_CRC32
1368
1369#ifndef CONFIG_CRC32_VERIFY
1370
1371U_BOOT_CMD(
1372 crc32, 4, 1, do_mem_crc,
1373 "checksum calculation",
1374 "address count [addr]\n - compute CRC32 checksum [save at addr]"
1375);
1376
1377#else
1378
1379U_BOOT_CMD(
1380 crc32, 5, 1, do_mem_crc,
1381 "checksum calculation",
1382 "address count [addr]\n - compute CRC32 checksum [save at addr]\n"
1383 "-v address count crc\n - verify crc of memory area"
1384);
1385
1386#endif
1387
1388#endif
1389
1390#ifdef CONFIG_CMD_MEMINFO
1391static int do_mem_info(struct cmd_tbl *cmdtp, int flag, int argc,
1392 char *const argv[])
1393{
1394 puts("DRAM: ");
1395 print_size(gd->ram_size, "\n");
1396
1397 return 0;
1398}
1399#endif
1400
1401U_BOOT_CMD(
1402 base, 2, 1, do_mem_base,
1403 "print or set address offset",
1404 "\n - print address offset for memory commands\n"
1405 "base off\n - set address offset for memory commands to 'off'"
1406);
1407
1408U_BOOT_CMD(
1409 loop, 3, 1, do_mem_loop,
1410 "infinite loop on address range",
1411 "[.b, .w, .l" HELP_Q "] address number_of_objects"
1412);
1413
1414#ifdef CONFIG_LOOPW
1415U_BOOT_CMD(
1416 loopw, 4, 1, do_mem_loopw,
1417 "infinite write loop on address range",
1418 "[.b, .w, .l" HELP_Q "] address number_of_objects data_to_write"
1419);
1420#endif
1421
1422#ifdef CONFIG_CMD_MEMTEST
1423U_BOOT_CMD(
1424 mtest, 5, 1, do_mem_mtest,
1425 "simple RAM read/write test",
1426 "[start [end [pattern [iterations]]]]"
1427);
1428#endif
1429
1430#ifdef CONFIG_CMD_MX_CYCLIC
1431U_BOOT_CMD(
1432 mdc, 4, 1, do_mem_mdc,
1433 "memory display cyclic",
1434 "[.b, .w, .l" HELP_Q "] address count delay(ms)"
1435);
1436
1437U_BOOT_CMD(
1438 mwc, 4, 1, do_mem_mwc,
1439 "memory write cyclic",
1440 "[.b, .w, .l" HELP_Q "] address value delay(ms)"
1441);
1442#endif
1443
1444#ifdef CONFIG_CMD_MEMINFO
1445U_BOOT_CMD(
1446 meminfo, 3, 1, do_mem_info,
1447 "display memory information",
1448 ""
1449);
1450#endif
1451
1452#ifdef CONFIG_CMD_RANDOM
1453U_BOOT_CMD(
1454 random, 4, 0, do_random,
1455 "fill memory with random pattern",
1456 "<addr> <len> [<seed>]\n"
1457 " - Fill 'len' bytes of memory starting at 'addr' with random data\n"
1458);
1459#endif
1460