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