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