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