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