uboot/cmd/mem.c
<<
>>
Prefs
   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
  30DECLARE_GLOBAL_DATA_PTR;
  31
  32#ifndef CONFIG_SYS_MEMTEST_SCRATCH
  33#define CONFIG_SYS_MEMTEST_SCRATCH 0
  34#endif
  35
  36static 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 */
  41static ulong    dp_last_addr, dp_last_size;
  42static ulong    dp_last_length = 0x40;
  43static ulong    mm_last_addr, mm_last_size;
  44
  45static  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
  53static 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
 153static 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}
 157static 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
 162static 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
 223static 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
 250static 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
 278static 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
 373static 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
 495static 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
 509static 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
 607static 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
 713static 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
 937static 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 */
1001static 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 */
1100static int
1101mod_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
1219static 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/**************************************************/
1244U_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
1255U_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
1266U_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
1276U_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
1286U_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
1296U_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
1310U_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
1318U_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
1336static 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
1345U_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
1352U_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
1363U_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
1375U_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
1383U_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
1393U_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
1405U_BOOT_CMD(
1406        meminfo,        3,      1,      do_mem_info,
1407        "display memory information",
1408        ""
1409);
1410#endif
1411