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