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