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