uboot/drivers/ram/stm32mp1/stm32mp1_tests.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
   2/*
   3 * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
   4 */
   5
   6#define LOG_CATEGORY UCLASS_RAM
   7
   8#include <common.h>
   9#include <console.h>
  10#include <init.h>
  11#include <log.h>
  12#include <rand.h>
  13#include <watchdog.h>
  14#include <asm/global_data.h>
  15#include <asm/io.h>
  16#include <linux/log2.h>
  17#include "stm32mp1_tests.h"
  18
  19#define ADDR_INVALID    0xFFFFFFFF
  20
  21#define PATTERN_DEFAULT "-"
  22
  23DECLARE_GLOBAL_DATA_PTR;
  24
  25static int get_bufsize(char *string, int argc, char *argv[], int arg_nb,
  26                       size_t *bufsize, size_t default_size, size_t min_size)
  27{
  28        unsigned long value;
  29
  30        if (argc > arg_nb) {
  31                if (strict_strtoul(argv[arg_nb], 0, &value) < 0) {
  32                        sprintf(string, "invalid %d parameter %s",
  33                                arg_nb, argv[arg_nb]);
  34                        return -1;
  35                }
  36                if (value > STM32_DDR_SIZE || value < min_size) {
  37                        sprintf(string, "invalid size %s (min=%d)",
  38                                argv[arg_nb], min_size);
  39                        return -1;
  40                }
  41                if (value & (min_size - 1)) {
  42                        sprintf(string, "unaligned size %s (min=%d)",
  43                                argv[arg_nb], min_size);
  44                        return -1;
  45                }
  46                *bufsize = value;
  47        } else {
  48                if (default_size != STM32_DDR_SIZE)
  49                        *bufsize = default_size;
  50                else
  51                        *bufsize = get_ram_size((long *)STM32_DDR_BASE,
  52                                                STM32_DDR_SIZE);
  53        }
  54        return 0;
  55}
  56
  57static int get_nb_loop(char *string, int argc, char *argv[], int arg_nb,
  58                       u32 *nb_loop, u32 default_nb_loop)
  59{
  60        unsigned long value;
  61
  62        if (argc > arg_nb) {
  63                if (strict_strtoul(argv[arg_nb], 0, &value) < 0) {
  64                        sprintf(string, "invalid %d parameter %s",
  65                                arg_nb, argv[arg_nb]);
  66                        return -1;
  67                }
  68                if (value == 0)
  69                        printf("WARNING: infinite loop requested\n");
  70                *nb_loop = value;
  71        } else {
  72                *nb_loop = default_nb_loop;
  73        }
  74
  75        return 0;
  76}
  77
  78static int get_addr(char *string, int argc, char *argv[], int arg_nb,
  79                    u32 *addr)
  80{
  81        unsigned long value;
  82
  83        if (argc > arg_nb) {
  84                if (strict_strtoul(argv[arg_nb], 16, &value) < 0) {
  85                        sprintf(string, "invalid %d parameter %s",
  86                                arg_nb, argv[arg_nb]);
  87                        return -1;
  88                }
  89                if (value < STM32_DDR_BASE) {
  90                        sprintf(string, "too low address %s", argv[arg_nb]);
  91                        return -1;
  92                }
  93                if (value & 0x3 && value != ADDR_INVALID) {
  94                        sprintf(string, "unaligned address %s",
  95                                argv[arg_nb]);
  96                        return -1;
  97                }
  98                *addr = value;
  99        } else {
 100                *addr = STM32_DDR_BASE;
 101        }
 102
 103        return 0;
 104}
 105
 106static int get_pattern(char *string, int argc, char *argv[], int arg_nb,
 107                       u32 *pattern, u32 default_pattern)
 108{
 109        unsigned long value;
 110
 111        if (argc > arg_nb) {
 112                if (!strcmp(argv[arg_nb], PATTERN_DEFAULT)) {
 113                        *pattern = default_pattern;
 114                        return 0;
 115                }
 116                if (strict_strtoul(argv[arg_nb], 16, &value) < 0) {
 117                        sprintf(string, "invalid %d parameter %s",
 118                                arg_nb, argv[arg_nb]);
 119                        return -1;
 120                }
 121                *pattern = value;
 122        } else {
 123                *pattern = default_pattern;
 124        }
 125
 126        return 0;
 127}
 128
 129static u32 check_addr(u32 addr, u32 value)
 130{
 131        u32 data = readl(addr);
 132
 133        if (value !=  data) {
 134                printf("0x%08x: 0x%08x <=> 0x%08x", addr, data, value);
 135                data = readl(addr);
 136                printf("(2nd read: 0x%08x)", data);
 137                if (value == data)
 138                        printf("- read error");
 139                else
 140                        printf("- write error");
 141                printf("\n");
 142                return -1;
 143        }
 144        return 0;
 145}
 146
 147static int progress(u32 offset)
 148{
 149        if (!(offset & 0xFFFFFF)) {
 150                putc('.');
 151                if (ctrlc()) {
 152                        printf("\ntest interrupted!\n");
 153                        return 1;
 154                }
 155        }
 156        return 0;
 157}
 158
 159static int test_loop_end(u32 *loop, u32 nb_loop, u32 progress)
 160{
 161        (*loop)++;
 162        if (nb_loop && *loop >= nb_loop)
 163                return 1;
 164        if ((*loop) % progress)
 165                return 0;
 166        /* allow to interrupt the test only for progress step */
 167        if (ctrlc()) {
 168                printf("test interrupted!\n");
 169                return 1;
 170        }
 171        printf("loop #%d\n", *loop);
 172        WATCHDOG_RESET();
 173
 174        return 0;
 175}
 176
 177/**********************************************************************
 178 *
 179 * Function:    memTestDataBus()
 180 *
 181 * Description: Test the data bus wiring in a memory region by
 182 *              performing a walking 1's test at a fixed address
 183 *              within that region.  The address is selected
 184 *              by the caller.
 185 *
 186 * Notes:
 187 *
 188 * Returns:     0 if the test succeeds.
 189 *              A non-zero result is the first pattern that failed.
 190 *
 191 **********************************************************************/
 192static u32 databus(u32 *address)
 193{
 194        u32 pattern;
 195        u32 read_value;
 196
 197        /* Perform a walking 1's test at the given address. */
 198        for (pattern = 1; pattern != 0; pattern <<= 1) {
 199                /* Write the test pattern. */
 200                writel(pattern, address);
 201
 202                /* Read it back (immediately is okay for this test). */
 203                read_value = readl(address);
 204                log_debug("%x: %x <=> %x\n",
 205                          (u32)address, read_value, pattern);
 206
 207                if (read_value != pattern)
 208                        return pattern;
 209        }
 210
 211        return 0;
 212}
 213
 214/**********************************************************************
 215 *
 216 * Function:    memTestAddressBus()
 217 *
 218 * Description: Test the address bus wiring in a memory region by
 219 *              performing a walking 1's test on the relevant bits
 220 *              of the address and checking for aliasing. This test
 221 *              will find single-bit address failures such as stuck
 222 *              -high, stuck-low, and shorted pins.  The base address
 223 *              and size of the region are selected by the caller.
 224 *
 225 * Notes:       For best results, the selected base address should
 226 *              have enough LSB 0's to guarantee single address bit
 227 *              changes.  For example, to test a 64-Kbyte region,
 228 *              select a base address on a 64-Kbyte boundary.  Also,
 229 *              select the region size as a power-of-two--if at all
 230 *              possible.
 231 *
 232 * Returns:     NULL if the test succeeds.
 233 *              A non-zero result is the first address at which an
 234 *              aliasing problem was uncovered.  By examining the
 235 *              contents of memory, it may be possible to gather
 236 *              additional information about the problem.
 237 *
 238 **********************************************************************/
 239static u32 *addressbus(u32 *address, u32 nb_bytes)
 240{
 241        u32 mask = (nb_bytes / sizeof(u32) - 1);
 242        u32 offset;
 243        u32 test_offset;
 244        u32 read_value;
 245
 246        u32 pattern     = 0xAAAAAAAA;
 247        u32 antipattern = 0x55555555;
 248
 249        /* Write the default pattern at each of the power-of-two offsets. */
 250        for (offset = 1; (offset & mask) != 0; offset <<= 1)
 251                writel(pattern, &address[offset]);
 252
 253        /* Check for address bits stuck high. */
 254        test_offset = 0;
 255        writel(antipattern, &address[test_offset]);
 256
 257        for (offset = 1; (offset & mask) != 0; offset <<= 1) {
 258                read_value = readl(&address[offset]);
 259                log_debug("%x: %x <=> %x\n",
 260                          (u32)&address[offset], read_value, pattern);
 261                if (read_value != pattern)
 262                        return &address[offset];
 263        }
 264
 265        writel(pattern, &address[test_offset]);
 266
 267        /* Check for address bits stuck low or shorted. */
 268        for (test_offset = 1; (test_offset & mask) != 0; test_offset <<= 1) {
 269                writel(antipattern, &address[test_offset]);
 270                if (readl(&address[0]) != pattern)
 271                        return &address[test_offset];
 272
 273                for (offset = 1; (offset & mask) != 0; offset <<= 1) {
 274                        if (readl(&address[offset]) != pattern &&
 275                            offset != test_offset)
 276                                return &address[test_offset];
 277                }
 278                writel(pattern, &address[test_offset]);
 279        }
 280
 281        return NULL;
 282}
 283
 284/**********************************************************************
 285 *
 286 * Function:    memTestDevice()
 287 *
 288 * Description: Test the integrity of a physical memory device by
 289 *              performing an increment/decrement test over the
 290 *              entire region.  In the process every storage bit
 291 *              in the device is tested as a zero and a one.  The
 292 *              base address and the size of the region are
 293 *              selected by the caller.
 294 *
 295 * Notes:
 296 *
 297 * Returns:     NULL if the test succeeds.
 298 *
 299 *              A non-zero result is the first address at which an
 300 *              incorrect value was read back.  By examining the
 301 *              contents of memory, it may be possible to gather
 302 *              additional information about the problem.
 303 *
 304 **********************************************************************/
 305static u32 *memdevice(u32 *address, u32 nb_bytes)
 306{
 307        u32 offset;
 308        u32 nb_words = nb_bytes / sizeof(u32);
 309
 310        u32 pattern;
 311        u32 antipattern;
 312
 313        puts("Fill with pattern");
 314        /* Fill memory with a known pattern. */
 315        for (pattern = 1, offset = 0; offset < nb_words; pattern++, offset++) {
 316                writel(pattern, &address[offset]);
 317                if (progress(offset))
 318                        return NULL;
 319        }
 320
 321        puts("\nCheck and invert pattern");
 322        /* Check each location and invert it for the second pass. */
 323        for (pattern = 1, offset = 0; offset < nb_words; pattern++, offset++) {
 324                if (readl(&address[offset]) != pattern)
 325                        return &address[offset];
 326
 327                antipattern = ~pattern;
 328                writel(antipattern, &address[offset]);
 329                if (progress(offset))
 330                        return NULL;
 331        }
 332
 333        puts("\nCheck inverted pattern");
 334        /* Check each location for the inverted pattern and zero it. */
 335        for (pattern = 1, offset = 0; offset < nb_words; pattern++, offset++) {
 336                antipattern = ~pattern;
 337                if (readl(&address[offset]) != antipattern)
 338                        return &address[offset];
 339                if (progress(offset))
 340                        return NULL;
 341        }
 342        printf("\n");
 343
 344        return NULL;
 345}
 346
 347static enum test_result databuswalk0(struct stm32mp1_ddrctl *ctl,
 348                                     struct stm32mp1_ddrphy *phy,
 349                                     char *string, int argc, char *argv[])
 350{
 351        int i;
 352        u32 loop = 0, nb_loop;
 353        u32 addr;
 354        u32 error = 0;
 355        u32 data;
 356
 357        if (get_nb_loop(string, argc, argv, 0, &nb_loop, 100))
 358                return TEST_ERROR;
 359        if (get_addr(string, argc, argv, 1, &addr))
 360                return TEST_ERROR;
 361
 362        printf("running %d loops at 0x%x\n", nb_loop, addr);
 363        while (!error) {
 364                for (i = 0; i < 32; i++)
 365                        writel(~(1 << i), addr + 4 * i);
 366                for (i = 0; i < 32; i++) {
 367                        data = readl(addr + 4 * i);
 368                        if (~(1 << i) !=  data) {
 369                                error |= 1 << i;
 370                                log_debug("%x: error %x expected %x => error:%x\n",
 371                                          addr + 4 * i, data, ~(1 << i), error);
 372                        }
 373                }
 374                if (test_loop_end(&loop, nb_loop, 1000))
 375                        break;
 376                for (i = 0; i < 32; i++)
 377                        writel(0, addr + 4 * i);
 378        }
 379        if (error) {
 380                sprintf(string, "loop %d: error for bits 0x%x",
 381                        loop, error);
 382                return TEST_FAILED;
 383        }
 384        sprintf(string, "no error for %d loops", loop);
 385        return TEST_PASSED;
 386}
 387
 388static enum test_result databuswalk1(struct stm32mp1_ddrctl *ctl,
 389                                     struct stm32mp1_ddrphy *phy,
 390                                     char *string, int argc, char *argv[])
 391{
 392        int i;
 393        u32 loop = 0, nb_loop;
 394        u32 addr;
 395        u32 error = 0;
 396        u32 data;
 397
 398        if (get_nb_loop(string, argc, argv, 0, &nb_loop, 100))
 399                return TEST_ERROR;
 400        if (get_addr(string, argc, argv, 1, &addr))
 401                return TEST_ERROR;
 402        printf("running %d loops at 0x%x\n", nb_loop, addr);
 403        while (!error) {
 404                for (i = 0; i < 32; i++)
 405                        writel(1 << i, addr + 4 * i);
 406                for (i = 0; i < 32; i++) {
 407                        data = readl(addr + 4 * i);
 408                        if ((1 << i) !=  data) {
 409                                error |= 1 << i;
 410                                log_debug("%x: error %x expected %x => error:%x\n",
 411                                          addr + 4 * i, data, (1 << i), error);
 412                        }
 413                }
 414                if (test_loop_end(&loop, nb_loop, 1000))
 415                        break;
 416                for (i = 0; i < 32; i++)
 417                        writel(0, addr + 4 * i);
 418        }
 419        if (error) {
 420                sprintf(string, "loop %d: error for bits 0x%x",
 421                        loop, error);
 422                return TEST_FAILED;
 423        }
 424        sprintf(string, "no error for %d loops", loop);
 425        return TEST_PASSED;
 426}
 427
 428static enum test_result test_databus(struct stm32mp1_ddrctl *ctl,
 429                                     struct stm32mp1_ddrphy *phy,
 430                                     char *string, int argc, char *argv[])
 431{
 432        u32 addr;
 433        u32 error;
 434
 435        if (get_addr(string, argc, argv, 0, &addr))
 436                return TEST_ERROR;
 437        error = databus((u32 *)addr);
 438        if (error) {
 439                sprintf(string, "0x%x: error for bits 0x%x",
 440                        addr, error);
 441                return TEST_FAILED;
 442        }
 443        sprintf(string, "address 0x%x", addr);
 444        return TEST_PASSED;
 445}
 446
 447static enum test_result test_addressbus(struct stm32mp1_ddrctl *ctl,
 448                                        struct stm32mp1_ddrphy *phy,
 449                                        char *string, int argc, char *argv[])
 450{
 451        u32 addr;
 452        u32 bufsize;
 453        u32 error;
 454
 455        if (get_bufsize(string, argc, argv, 0, &bufsize, STM32_DDR_SIZE, 4))
 456                return TEST_ERROR;
 457        if (!is_power_of_2(bufsize)) {
 458                sprintf(string, "size 0x%x is not a power of 2",
 459                        (u32)bufsize);
 460                return TEST_ERROR;
 461        }
 462        if (get_addr(string, argc, argv, 1, &addr))
 463                return TEST_ERROR;
 464
 465        printf("running at 0x%08x length 0x%x\n", addr, bufsize);
 466        error = (u32)addressbus((u32 *)addr, bufsize);
 467        if (error) {
 468                sprintf(string, "0x%x: error for address 0x%x",
 469                        addr, error);
 470                return TEST_FAILED;
 471        }
 472        sprintf(string, "address 0x%x, size 0x%x",
 473                addr, bufsize);
 474        return TEST_PASSED;
 475}
 476
 477static enum test_result test_memdevice(struct stm32mp1_ddrctl *ctl,
 478                                       struct stm32mp1_ddrphy *phy,
 479                                       char *string, int argc, char *argv[])
 480{
 481        u32 addr;
 482        size_t bufsize;
 483        u32 error;
 484
 485        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
 486                return TEST_ERROR;
 487        if (get_addr(string, argc, argv, 1, &addr))
 488                return TEST_ERROR;
 489        error = (u32)memdevice((u32 *)addr, (unsigned long)bufsize);
 490        if (error) {
 491                sprintf(string, "0x%x: error for address 0x%x",
 492                        addr, error);
 493                return TEST_FAILED;
 494        }
 495        sprintf(string, "address 0x%x, size 0x%x",
 496                addr, bufsize);
 497        return TEST_PASSED;
 498}
 499
 500/**********************************************************************
 501 *
 502 * Function:    sso
 503 *
 504 * Description: Test the Simultaneous Switching Output.
 505 *              Verifies succes sive reads and writes to the same memory word,
 506 *              holding one bit constant while toggling all other data bits
 507 *              simultaneously
 508 *              => stress the data bus over an address range
 509 *
 510 *              The CPU writes to each address in the given range.
 511 *              For each bit, first the CPU holds the bit at 1 while
 512 *              toggling the other bits, and then the CPU holds the bit at 0
 513 *              while toggling the other bits.
 514 *              After each write, the CPU reads the address that was written
 515 *              to verify that it contains the correct data
 516 *
 517 **********************************************************************/
 518static enum test_result test_sso(struct stm32mp1_ddrctl *ctl,
 519                                 struct stm32mp1_ddrphy *phy,
 520                                 char *string, int argc, char *argv[])
 521{
 522        int i, j;
 523        u32 addr, bufsize, remaining, offset;
 524        u32 error = 0;
 525        u32 data;
 526
 527        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
 528                return TEST_ERROR;
 529        if (get_addr(string, argc, argv, 1, &addr))
 530                return TEST_ERROR;
 531
 532        printf("running sso at 0x%x length 0x%x", addr, bufsize);
 533        offset = addr;
 534        remaining = bufsize;
 535        while (remaining) {
 536                for (i = 0; i < 32; i++) {
 537                        /* write pattern. */
 538                        for (j = 0; j < 6; j++) {
 539                                switch (j) {
 540                                case 0:
 541                                case 2:
 542                                        data = 1 << i;
 543                                        break;
 544                                case 3:
 545                                case 5:
 546                                        data = ~(1 << i);
 547                                        break;
 548                                case 1:
 549                                        data = ~0x0;
 550                                        break;
 551                                case 4:
 552                                        data = 0x0;
 553                                        break;
 554                                }
 555
 556                                writel(data, offset);
 557                                error = check_addr(offset, data);
 558                                if (error)
 559                                        goto end;
 560                        }
 561                }
 562                offset += 4;
 563                remaining -= 4;
 564                if (progress(offset << 7))
 565                        goto end;
 566        }
 567        puts("\n");
 568
 569end:
 570        if (error) {
 571                sprintf(string, "error for pattern 0x%x @0x%x",
 572                        data, offset);
 573                return TEST_FAILED;
 574        }
 575        sprintf(string, "no error for sso at 0x%x length 0x%x", addr, bufsize);
 576        return TEST_PASSED;
 577}
 578
 579/**********************************************************************
 580 *
 581 * Function:    Random
 582 *
 583 * Description: Verifies r/w with pseudo-ramdom value on one region
 584 *              + write the region (individual access)
 585 *              + memcopy to the 2nd region (try to use burst)
 586 *              + verify the 2 regions
 587 *
 588 **********************************************************************/
 589static enum test_result test_random(struct stm32mp1_ddrctl *ctl,
 590                                    struct stm32mp1_ddrphy *phy,
 591                                    char *string, int argc, char *argv[])
 592{
 593        u32 addr, offset, value = 0;
 594        size_t bufsize;
 595        u32 loop = 0, nb_loop;
 596        u32 error = 0;
 597        unsigned int seed;
 598
 599        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 8))
 600                return TEST_ERROR;
 601        if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
 602                return TEST_ERROR;
 603        if (get_addr(string, argc, argv, 2, &addr))
 604                return TEST_ERROR;
 605
 606        bufsize /= 2;
 607        printf("running %d loops copy from 0x%x to 0x%x (buffer size=0x%x)\n",
 608               nb_loop, addr, addr + bufsize, bufsize);
 609        while (!error) {
 610                seed = rand();
 611                for (offset = 0; offset < bufsize; offset += 4)
 612                        writel(rand(), addr + offset);
 613
 614                memcpy((void *)addr + bufsize, (void *)addr, bufsize);
 615
 616                srand(seed);
 617                for (offset = 0; offset < 2 * bufsize; offset += 4) {
 618                        if (offset == bufsize)
 619                                srand(seed);
 620                        value = rand();
 621                        error = check_addr(addr + offset, value);
 622                        if (error)
 623                                break;
 624                        if (progress(offset))
 625                                return TEST_FAILED;
 626                }
 627                if (test_loop_end(&loop, nb_loop, 100))
 628                        break;
 629        }
 630        putc('\n');
 631
 632        if (error) {
 633                sprintf(string,
 634                        "loop %d: error for address 0x%x: 0x%x expected 0x%x",
 635                        loop, offset, readl(offset), value);
 636                return TEST_FAILED;
 637        }
 638        sprintf(string, "no error for %d loops, size 0x%x",
 639                loop, bufsize);
 640        return TEST_PASSED;
 641}
 642
 643/**********************************************************************
 644 *
 645 * Function:    noise
 646 *
 647 * Description: Verifies r/w while forcing switching of all data bus lines.
 648 *              optimised 4 iteration write/read/write/read cycles...
 649 *              for pattern and inversed pattern
 650 *
 651 **********************************************************************/
 652void do_noise(u32 addr, u32 pattern, u32 *result)
 653{
 654        __asm__("push {R0-R11}");
 655        __asm__("mov r0, %0" : : "r" (addr));
 656        __asm__("mov r1, %0" : : "r" (pattern));
 657        __asm__("mov r11, %0" : : "r" (result));
 658
 659        __asm__("mvn r2, r1");
 660
 661        __asm__("str r1, [r0]");
 662        __asm__("ldr r3, [r0]");
 663        __asm__("str r2, [r0]");
 664        __asm__("ldr r4, [r0]");
 665
 666        __asm__("str r1, [r0]");
 667        __asm__("ldr r5, [r0]");
 668        __asm__("str r2, [r0]");
 669        __asm__("ldr r6, [r0]");
 670
 671        __asm__("str r1, [r0]");
 672        __asm__("ldr r7, [r0]");
 673        __asm__("str r2, [r0]");
 674        __asm__("ldr r8, [r0]");
 675
 676        __asm__("str r1, [r0]");
 677        __asm__("ldr r9, [r0]");
 678        __asm__("str r2, [r0]");
 679        __asm__("ldr r10, [r0]");
 680
 681        __asm__("stmia R11!, {R3-R10}");
 682
 683        __asm__("pop {R0-R11}");
 684}
 685
 686static enum test_result test_noise(struct stm32mp1_ddrctl *ctl,
 687                                   struct stm32mp1_ddrphy *phy,
 688                                   char *string, int argc, char *argv[])
 689{
 690        u32 addr, pattern;
 691        u32 result[8];
 692        int i;
 693        enum test_result res = TEST_PASSED;
 694
 695        if (get_pattern(string, argc, argv, 0, &pattern, 0xFFFFFFFF))
 696                return TEST_ERROR;
 697        if (get_addr(string, argc, argv, 1, &addr))
 698                return TEST_ERROR;
 699
 700        printf("running noise for 0x%x at 0x%x\n", pattern, addr);
 701
 702        do_noise(addr, pattern, result);
 703
 704        for (i = 0; i < 0x8;) {
 705                if (check_addr((u32)&result[i++], pattern))
 706                        res = TEST_FAILED;
 707                if (check_addr((u32)&result[i++], ~pattern))
 708                        res = TEST_FAILED;
 709        }
 710
 711        return res;
 712}
 713
 714/**********************************************************************
 715 *
 716 * Function:    noise_burst
 717 *
 718 * Description: Verifies r/w while forcing switching of all data bus lines.
 719 *              optimised write loop witrh store multiple to use burst
 720 *              for pattern and inversed pattern
 721 *
 722 **********************************************************************/
 723void do_noise_burst(u32 addr, u32 pattern, size_t bufsize)
 724{
 725        __asm__("push {R0-R9}");
 726        __asm__("mov r0, %0" : : "r" (addr));
 727        __asm__("mov r1, %0" : : "r" (pattern));
 728        __asm__("mov r9, %0" : : "r" (bufsize));
 729
 730        __asm__("mvn r2, r1");
 731        __asm__("mov r3, r1");
 732        __asm__("mov r4, r2");
 733        __asm__("mov r5, r1");
 734        __asm__("mov r6, r2");
 735        __asm__("mov r7, r1");
 736        __asm__("mov r8, r2");
 737
 738        __asm__("loop1:");
 739        __asm__("stmia R0!, {R1-R8}");
 740        __asm__("stmia R0!, {R1-R8}");
 741        __asm__("stmia R0!, {R1-R8}");
 742        __asm__("stmia R0!, {R1-R8}");
 743        __asm__("subs r9, r9, #128");
 744        __asm__("bge loop1");
 745        __asm__("pop {R0-R9}");
 746}
 747
 748/* chunk size enough to allow interruption with Ctrl-C*/
 749#define CHUNK_SIZE      0x8000000
 750static enum test_result test_noise_burst(struct stm32mp1_ddrctl *ctl,
 751                                         struct stm32mp1_ddrphy *phy,
 752                                         char *string, int argc, char *argv[])
 753{
 754        u32 addr, offset, pattern;
 755        size_t bufsize, remaining, size;
 756        int i;
 757        enum test_result res = TEST_PASSED;
 758
 759        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 128))
 760                return TEST_ERROR;
 761        if (get_pattern(string, argc, argv, 1, &pattern, 0xFFFFFFFF))
 762                return TEST_ERROR;
 763        if (get_addr(string, argc, argv, 2, &addr))
 764                return TEST_ERROR;
 765
 766        printf("running noise burst for 0x%x at 0x%x + 0x%x",
 767               pattern, addr, bufsize);
 768
 769        offset = addr;
 770        remaining = bufsize;
 771        size = CHUNK_SIZE;
 772        while (remaining) {
 773                if (remaining < size)
 774                        size = remaining;
 775                do_noise_burst(offset, pattern, size);
 776                remaining -= size;
 777                offset += size;
 778                if (progress(offset)) {
 779                        res = TEST_FAILED;
 780                        goto end;
 781                }
 782        }
 783        puts("\ncheck buffer");
 784        for (i = 0; i < bufsize;) {
 785                if (check_addr(addr + i, pattern))
 786                        res = TEST_FAILED;
 787                i += 4;
 788                if (check_addr(addr + i, ~pattern))
 789                        res = TEST_FAILED;
 790                i += 4;
 791                if (progress(i)) {
 792                        res = TEST_FAILED;
 793                        goto end;
 794                }
 795        }
 796end:
 797        puts("\n");
 798        return res;
 799}
 800
 801/**********************************************************************
 802 *
 803 * Function:    pattern test
 804 *
 805 * Description: optimized loop for read/write pattern (array of 8 u32)
 806 *
 807 **********************************************************************/
 808#define PATTERN_SIZE    8
 809static enum test_result test_loop(const u32 *pattern, u32 *address,
 810                                  const u32 bufsize)
 811{
 812        int i;
 813        int j;
 814        enum test_result res = TEST_PASSED;
 815        u32 offset, testsize, remaining;
 816
 817        offset = (u32)address;
 818        remaining = bufsize;
 819        while (remaining) {
 820                testsize = bufsize > 0x1000000 ? 0x1000000 : bufsize;
 821
 822                __asm__("push {R0-R10}");
 823                __asm__("mov r0, %0" : : "r" (pattern));
 824                __asm__("mov r1, %0" : : "r" (offset));
 825                __asm__("mov r2, %0" : : "r" (testsize));
 826                __asm__("ldmia r0!, {R3-R10}");
 827
 828                __asm__("loop2:");
 829                __asm__("stmia r1!, {R3-R10}");
 830                __asm__("stmia r1!, {R3-R10}");
 831                __asm__("stmia r1!, {R3-R10}");
 832                __asm__("stmia r1!, {R3-R10}");
 833                __asm__("subs r2, r2, #128");
 834                __asm__("bge loop2");
 835                __asm__("pop {R0-R10}");
 836
 837                offset += testsize;
 838                remaining -= testsize;
 839                if (progress((u32)offset)) {
 840                        res = TEST_FAILED;
 841                        goto end;
 842                }
 843        }
 844
 845        puts("\ncheck buffer");
 846        for (i = 0; i < bufsize; i += PATTERN_SIZE * 4) {
 847                for (j = 0; j < PATTERN_SIZE; j++, address++)
 848                        if (check_addr((u32)address, pattern[j])) {
 849                                res = TEST_FAILED;
 850                                goto end;
 851                        }
 852                if (progress(i)) {
 853                        res = TEST_FAILED;
 854                        goto end;
 855                }
 856        }
 857
 858end:
 859        puts("\n");
 860        return res;
 861}
 862
 863const u32 pattern_div1_x16[PATTERN_SIZE] = {
 864        0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF,
 865        0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF
 866};
 867
 868const u32 pattern_div2_x16[PATTERN_SIZE] = {
 869        0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
 870        0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000
 871};
 872
 873const u32 pattern_div4_x16[PATTERN_SIZE] = {
 874        0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
 875        0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000
 876};
 877
 878const u32 pattern_div4_x32[PATTERN_SIZE] = {
 879        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
 880        0x00000000, 0x00000000, 0x00000000, 0x00000000
 881};
 882
 883const u32 pattern_mostly_zero_x16[PATTERN_SIZE] = {
 884        0x00000000, 0x00000000, 0x00000000, 0x0000FFFF,
 885        0x00000000, 0x00000000, 0x00000000, 0x00000000
 886};
 887
 888const u32 pattern_mostly_zero_x32[PATTERN_SIZE] = {
 889        0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF,
 890        0x00000000, 0x00000000, 0x00000000, 0x00000000
 891};
 892
 893const u32 pattern_mostly_one_x16[PATTERN_SIZE] = {
 894        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF,
 895        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
 896};
 897
 898const u32 pattern_mostly_one_x32[PATTERN_SIZE] = {
 899        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
 900        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
 901};
 902
 903#define NB_PATTERN      5
 904static enum test_result test_freq_pattern(struct stm32mp1_ddrctl *ctl,
 905                                          struct stm32mp1_ddrphy *phy,
 906                                          char *string, int argc, char *argv[])
 907{
 908        const u32 * const patterns_x16[NB_PATTERN] = {
 909                pattern_div1_x16,
 910                pattern_div2_x16,
 911                pattern_div4_x16,
 912                pattern_mostly_zero_x16,
 913                pattern_mostly_one_x16,
 914        };
 915        const u32 * const patterns_x32[NB_PATTERN] = {
 916                pattern_div2_x16,
 917                pattern_div4_x16,
 918                pattern_div4_x32,
 919                pattern_mostly_zero_x32,
 920                pattern_mostly_one_x32
 921        };
 922        const char *patterns_comments[NB_PATTERN] = {
 923                "switching at frequency F/1",
 924                "switching at frequency F/2",
 925                "switching at frequency F/4",
 926                "mostly zero",
 927                "mostly one"
 928        };
 929
 930        enum test_result res = TEST_PASSED, pattern_res;
 931        int i, bus_width;
 932        const u32 **patterns;
 933        u32 bufsize, addr;
 934
 935        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 128))
 936                return TEST_ERROR;
 937        if (get_addr(string, argc, argv, 1, &addr))
 938                return TEST_ERROR;
 939
 940        switch (readl(&ctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK) {
 941        case DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF:
 942        case DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER:
 943                bus_width = 16;
 944                break;
 945        default:
 946                bus_width = 32;
 947                break;
 948        }
 949
 950        printf("running test pattern at 0x%08x length 0x%x width = %d\n",
 951               addr, bufsize, bus_width);
 952
 953        patterns =
 954                (const u32 **)(bus_width == 16 ? patterns_x16 : patterns_x32);
 955
 956        for (i = 0; i < NB_PATTERN; i++) {
 957                printf("test data pattern %s:", patterns_comments[i]);
 958                pattern_res = test_loop(patterns[i], (u32 *)addr, bufsize);
 959                if (pattern_res != TEST_PASSED) {
 960                        printf("Failed\n");
 961                        return pattern_res;
 962                }
 963                printf("Passed\n");
 964        }
 965
 966        return res;
 967}
 968
 969/**********************************************************************
 970 *
 971 * Function:    pattern test with size
 972 *
 973 * Description: loop for write pattern
 974 *
 975 **********************************************************************/
 976
 977static enum test_result test_loop_size(const u32 *pattern, u32 size,
 978                                       u32 *address,
 979                                       const u32 bufsize)
 980{
 981        int i, j;
 982        enum test_result res = TEST_PASSED;
 983        u32 *p = address;
 984
 985        for (i = 0; i < bufsize; i += size * 4) {
 986                for (j = 0; j < size ; j++, p++)
 987                        *p = pattern[j];
 988                if (progress(i)) {
 989                        res = TEST_FAILED;
 990                        goto end;
 991                }
 992        }
 993
 994        puts("\ncheck buffer");
 995        p = address;
 996        for (i = 0; i < bufsize; i += size * 4) {
 997                for (j = 0; j < size; j++, p++)
 998                        if (check_addr((u32)p, pattern[j])) {
 999                                res = TEST_FAILED;
1000                                goto end;
1001                        }
1002                if (progress(i)) {
1003                        res = TEST_FAILED;
1004                        goto end;
1005                }
1006        }
1007
1008end:
1009        puts("\n");
1010        return res;
1011}
1012
1013static enum test_result test_checkboard(struct stm32mp1_ddrctl *ctl,
1014                                        struct stm32mp1_ddrphy *phy,
1015                                        char *string, int argc, char *argv[])
1016{
1017        enum test_result res = TEST_PASSED;
1018        u32 bufsize, nb_loop, loop = 0, addr;
1019        int i;
1020
1021        u32 checkboard[2] = {0x55555555, 0xAAAAAAAA};
1022
1023        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 8))
1024                return TEST_ERROR;
1025        if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
1026                return TEST_ERROR;
1027        if (get_addr(string, argc, argv, 2, &addr))
1028                return TEST_ERROR;
1029
1030        printf("running %d loops at 0x%08x length 0x%x\n",
1031               nb_loop, addr, bufsize);
1032        while (1) {
1033                for (i = 0; i < 2; i++) {
1034                        res = test_loop_size(checkboard, 2, (u32 *)addr,
1035                                             bufsize);
1036                        if (res)
1037                                return res;
1038                        checkboard[0] = ~checkboard[0];
1039                        checkboard[1] = ~checkboard[1];
1040                }
1041                if (test_loop_end(&loop, nb_loop, 1))
1042                        break;
1043        }
1044        sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
1045                loop, addr, bufsize);
1046
1047        return res;
1048}
1049
1050static enum test_result test_blockseq(struct stm32mp1_ddrctl *ctl,
1051                                      struct stm32mp1_ddrphy *phy,
1052                                      char *string, int argc, char *argv[])
1053{
1054        enum test_result res = TEST_PASSED;
1055        u32 bufsize, nb_loop, loop = 0, addr, value;
1056        int i;
1057
1058        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
1059                return TEST_ERROR;
1060        if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
1061                return TEST_ERROR;
1062        if (get_addr(string, argc, argv, 2, &addr))
1063                return TEST_ERROR;
1064
1065        printf("running %d loops at 0x%08x length 0x%x\n",
1066               nb_loop, addr, bufsize);
1067        while (1) {
1068                for (i = 0; i < 256; i++) {
1069                        value = i | i << 8 | i << 16 | i << 24;
1070                        printf("pattern = %08x", value);
1071                        res = test_loop_size(&value, 1, (u32 *)addr, bufsize);
1072                        if (res != TEST_PASSED)
1073                                return res;
1074                }
1075                if (test_loop_end(&loop, nb_loop, 1))
1076                        break;
1077        }
1078        sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
1079                loop, addr, bufsize);
1080
1081        return res;
1082}
1083
1084static enum test_result test_walkbit0(struct stm32mp1_ddrctl *ctl,
1085                                      struct stm32mp1_ddrphy *phy,
1086                                      char *string, int argc, char *argv[])
1087{
1088        enum test_result res = TEST_PASSED;
1089        u32 bufsize, nb_loop, loop = 0, addr, value;
1090        int i;
1091
1092        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
1093                return TEST_ERROR;
1094        if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
1095                return TEST_ERROR;
1096        if (get_addr(string, argc, argv, 2, &addr))
1097                return TEST_ERROR;
1098
1099        printf("running %d loops at 0x%08x length 0x%x\n",
1100               nb_loop, addr, bufsize);
1101        while (1) {
1102                for (i = 0; i < 64; i++) {
1103                        if (i < 32)
1104                                value = 1 << i;
1105                        else
1106                                value = 1 << (63 - i);
1107
1108                        printf("pattern = %08x", value);
1109                        res = test_loop_size(&value, 1, (u32 *)addr, bufsize);
1110                        if (res != TEST_PASSED)
1111                                return res;
1112                }
1113                if (test_loop_end(&loop, nb_loop, 1))
1114                        break;
1115        }
1116        sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
1117                loop, addr, bufsize);
1118
1119        return res;
1120}
1121
1122static enum test_result test_walkbit1(struct stm32mp1_ddrctl *ctl,
1123                                      struct stm32mp1_ddrphy *phy,
1124                                      char *string, int argc, char *argv[])
1125{
1126        enum test_result res = TEST_PASSED;
1127        u32 bufsize, nb_loop, loop = 0, addr, value;
1128        int i;
1129
1130        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 4))
1131                return TEST_ERROR;
1132        if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
1133                return TEST_ERROR;
1134        if (get_addr(string, argc, argv, 2, &addr))
1135                return TEST_ERROR;
1136
1137        printf("running %d loops at 0x%08x length 0x%x\n",
1138               nb_loop, addr, bufsize);
1139        while (1) {
1140                for (i = 0; i < 64; i++) {
1141                        if (i < 32)
1142                                value = ~(1 << i);
1143                        else
1144                                value = ~(1 << (63 - i));
1145
1146                        printf("pattern = %08x", value);
1147                        res = test_loop_size(&value, 1, (u32 *)addr, bufsize);
1148                        if (res != TEST_PASSED)
1149                                return res;
1150                }
1151                if (test_loop_end(&loop, nb_loop, 1))
1152                        break;
1153        }
1154        sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
1155                loop, addr, bufsize);
1156
1157        return res;
1158}
1159
1160/*
1161 * try to catch bad bits which are dependent on the current values of
1162 * surrounding bits in either the same word32
1163 */
1164static enum test_result test_bitspread(struct stm32mp1_ddrctl *ctl,
1165                                       struct stm32mp1_ddrphy *phy,
1166                                       char *string, int argc, char *argv[])
1167{
1168        enum test_result res = TEST_PASSED;
1169        u32 bufsize, nb_loop, loop = 0, addr, bitspread[4];
1170        int i, j;
1171
1172        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 32))
1173                return TEST_ERROR;
1174        if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
1175                return TEST_ERROR;
1176        if (get_addr(string, argc, argv, 2, &addr))
1177                return TEST_ERROR;
1178
1179        printf("running %d loops at 0x%08x length 0x%x\n",
1180               nb_loop, addr, bufsize);
1181        while (1) {
1182                for (i = 1; i < 32; i++) {
1183                        for (j = 0; j < i; j++) {
1184                                if (i < 32)
1185                                        bitspread[0] = (1 << i) | (1 << j);
1186                                else
1187                                        bitspread[0] = (1 << (63 - i)) |
1188                                                       (1 << (63 - j));
1189                                bitspread[1] = bitspread[0];
1190                                bitspread[2] = ~bitspread[0];
1191                                bitspread[3] = ~bitspread[0];
1192                                printf("pattern = %08x", bitspread[0]);
1193
1194                                res = test_loop_size(bitspread, 4, (u32 *)addr,
1195                                                     bufsize);
1196                                if (res != TEST_PASSED)
1197                                        return res;
1198                        }
1199                }
1200                if (test_loop_end(&loop, nb_loop, 1))
1201                        break;
1202        }
1203        sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
1204                loop, addr, bufsize);
1205
1206        return res;
1207}
1208
1209static enum test_result test_bitflip(struct stm32mp1_ddrctl *ctl,
1210                                     struct stm32mp1_ddrphy *phy,
1211                                     char *string, int argc, char *argv[])
1212{
1213        enum test_result res = TEST_PASSED;
1214        u32 bufsize, nb_loop, loop = 0, addr;
1215        int i;
1216
1217        u32 bitflip[4];
1218
1219        if (get_bufsize(string, argc, argv, 0, &bufsize, 4 * 1024, 32))
1220                return TEST_ERROR;
1221        if (get_nb_loop(string, argc, argv, 1, &nb_loop, 1))
1222                return TEST_ERROR;
1223        if (get_addr(string, argc, argv, 2, &addr))
1224                return TEST_ERROR;
1225
1226        printf("running %d loops at 0x%08x length 0x%x\n",
1227               nb_loop, addr, bufsize);
1228        while (1) {
1229                for (i = 0; i < 32; i++) {
1230                        bitflip[0] = 1 << i;
1231                        bitflip[1] = bitflip[0];
1232                        bitflip[2] = ~bitflip[0];
1233                        bitflip[3] = bitflip[2];
1234                        printf("pattern = %08x", bitflip[0]);
1235
1236                        res = test_loop_size(bitflip, 4, (u32 *)addr, bufsize);
1237                        if (res != TEST_PASSED)
1238                                return res;
1239                }
1240                if (test_loop_end(&loop, nb_loop, 1))
1241                        break;
1242        }
1243        sprintf(string, "no error for %d loops at 0x%08x length 0x%x",
1244                loop, addr, bufsize);
1245
1246        return res;
1247}
1248
1249/**********************************************************************
1250 *
1251 * Function: infinite read access to DDR
1252 *
1253 * Description: continuous read the same pattern at the same address
1254 *
1255 **********************************************************************/
1256static enum test_result test_read(struct stm32mp1_ddrctl *ctl,
1257                                  struct stm32mp1_ddrphy *phy,
1258                                  char *string, int argc, char *argv[])
1259{
1260        u32 *addr;
1261        u32 data;
1262        u32 loop = 0;
1263        int i, size = 1024 * 1024;
1264        bool random = false;
1265
1266        if (get_addr(string, argc, argv, 0, (u32 *)&addr))
1267                return TEST_ERROR;
1268
1269        if (get_pattern(string, argc, argv, 1, &data, 0xA5A5AA55))
1270                return TEST_ERROR;
1271
1272        if ((u32)addr == ADDR_INVALID) {
1273                printf("running random\n");
1274                random = true;
1275        } else {
1276                printf("running at 0x%08x with pattern=0x%08x\n",
1277                       (u32)addr, data);
1278                writel(data, addr);
1279        }
1280
1281        while (1) {
1282                for (i = 0; i < size; i++) {
1283                        if (random)
1284                                addr = (u32 *)(STM32_DDR_BASE +
1285                                       (rand() & (STM32_DDR_SIZE - 1) & ~0x3));
1286                        data = readl(addr);
1287                }
1288                if (test_loop_end(&loop, 0, 1))
1289                        break;
1290        }
1291        if (random)
1292                sprintf(string, "%d loops random", loop);
1293        else
1294                sprintf(string, "%d loops at 0x%x: %x", loop, (u32)addr, data);
1295
1296        return TEST_PASSED;
1297}
1298
1299/**********************************************************************
1300 *
1301 * Function: infinite write access to DDR
1302 *
1303 * Description: continuous write the same pattern at the same address
1304 *
1305 **********************************************************************/
1306static enum test_result test_write(struct stm32mp1_ddrctl *ctl,
1307                                   struct stm32mp1_ddrphy *phy,
1308                                   char *string, int argc, char *argv[])
1309{
1310        u32 *addr;
1311        u32 data;
1312        u32 loop = 0;
1313        int i, size = 1024 * 1024;
1314        bool random = false;
1315
1316        if (get_addr(string, argc, argv, 0, (u32 *)&addr))
1317                return TEST_ERROR;
1318
1319        if (get_pattern(string, argc, argv, 1, &data, 0xA5A5AA55))
1320                return TEST_ERROR;
1321
1322        if ((u32)addr == ADDR_INVALID) {
1323                printf("running random\n");
1324                random = true;
1325        } else {
1326                printf("running at 0x%08x with pattern 0x%08x\n",
1327                       (u32)addr, data);
1328        }
1329
1330        while (1) {
1331                for (i = 0; i < size; i++) {
1332                        if (random) {
1333                                addr = (u32 *)(STM32_DDR_BASE +
1334                                       (rand() & (STM32_DDR_SIZE - 1) & ~0x3));
1335                                data = rand();
1336                        }
1337                        writel(data, addr);
1338                }
1339                if (test_loop_end(&loop, 0, 1))
1340                        break;
1341        }
1342        if (random)
1343                sprintf(string, "%d loops random", loop);
1344        else
1345                sprintf(string, "%d loops at 0x%x: %x", loop, (u32)addr, data);
1346
1347        return TEST_PASSED;
1348}
1349
1350#define NB_TEST_INFINITE 2
1351static enum test_result test_all(struct stm32mp1_ddrctl *ctl,
1352                                 struct stm32mp1_ddrphy *phy,
1353                                 char *string, int argc, char *argv[])
1354{
1355        enum test_result res = TEST_PASSED, result;
1356        int i, j, nb_error = 0, len;
1357        u32 loop = 0, nb_loop;
1358        int argc_test;
1359        char *argv_test[4];
1360        char loop_string[] = "1";
1361        char pattern_string[] = PATTERN_DEFAULT;
1362        u32 *addr;
1363
1364        if (get_nb_loop(string, argc, argv, 0, &nb_loop, 1))
1365                return TEST_ERROR;
1366
1367        if (get_addr(string, argc, argv, 2, (u32 *)&addr))
1368                return TEST_ERROR;
1369
1370        while (!nb_error) {
1371                /* execute all the test except the lasts which are infinite */
1372                for (i = 1; i < test_nb - NB_TEST_INFINITE; i++) {
1373                        argc_test = 0;
1374                        j = 0;
1375                        len = strlen(test[i].usage);
1376                        if (argc > 1 && j < len &&
1377                            !strncmp("[size]", &test[i].usage[j], 6)) {
1378                                argv_test[argc_test++] = argv[1];
1379                                j += 7;
1380                        }
1381                        if (argc > 2) {
1382                                if (j < len &&
1383                                    !strncmp("[loop]", &test[i].usage[j], 6)) {
1384                                        argv_test[argc_test++] = loop_string;
1385                                        j += 7;
1386                                }
1387                                if (j < len &&
1388                                    !strncmp("[pattern]", &test[i].usage[j],
1389                                             9)) {
1390                                        argv_test[argc_test++] = pattern_string;
1391                                        j += 10;
1392                                }
1393                                if (j < len &&
1394                                    !strncmp("[addr]", &test[i].usage[j], 6)) {
1395                                        argv_test[argc_test++] = argv[2];
1396                                        j += 7;
1397                                }
1398                        }
1399                        printf("execute %d:%s\n", (int)i, test[i].name);
1400                        result = test[i].fct(ctl, phy, string,
1401                                             argc_test, argv_test);
1402                        printf("result %d:%s = ", (int)i, test[i].name);
1403                        if (result != TEST_PASSED) {
1404                                nb_error++;
1405                                res = TEST_FAILED;
1406                                puts("Failed");
1407                        } else {
1408                                puts("Passed");
1409                        }
1410                        puts("\n\n");
1411                }
1412                printf("loop %d: %d/%d test failed\n\n\n",
1413                       loop + 1, nb_error, test_nb - NB_TEST_INFINITE);
1414                if (test_loop_end(&loop, nb_loop, 1))
1415                        break;
1416        }
1417        if (res != TEST_PASSED) {
1418                sprintf(string, "loop %d: %d/%d test failed", loop, nb_error,
1419                        test_nb - NB_TEST_INFINITE);
1420        } else {
1421                sprintf(string, "loop %d: %d tests passed", loop,
1422                        test_nb - NB_TEST_INFINITE);
1423        }
1424        return res;
1425}
1426
1427/****************************************************************
1428 * TEST Description
1429 ****************************************************************/
1430
1431const struct test_desc test[] = {
1432        {test_all, "All", "[loop] [size] [addr]", "Execute all tests", 3 },
1433        {test_databus, "Simple DataBus", "[addr]",
1434         "Verifies each data line by walking 1 on fixed address",
1435         1
1436         },
1437        {databuswalk0, "DataBusWalking0", "[loop] [addr]",
1438         "Verifies each data bus signal can be driven low (32 word burst)",
1439         2
1440        },
1441        {databuswalk1, "DataBusWalking1", "[loop] [addr]",
1442         "Verifies each data bus signal can be driven high (32 word burst)",
1443         2
1444        },
1445        {test_addressbus, "AddressBus", "[size] [addr]",
1446         "Verifies each relevant bits of the address and checking for aliasing",
1447         2
1448         },
1449        {test_memdevice, "MemDevice", "[size] [addr]",
1450         "Test the integrity of a physical memory (test every storage bit in the region)",
1451         2
1452         },
1453        {test_sso, "SimultaneousSwitchingOutput", "[size] [addr] ",
1454         "Stress the data bus over an address range",
1455         2
1456        },
1457        {test_noise, "Noise", "[pattern] [addr]",
1458         "Verifies r/w while forcing switching of all data bus lines.",
1459         3
1460        },
1461        {test_noise_burst, "NoiseBurst", "[size] [pattern] [addr]",
1462         "burst transfers while forcing switching of the data bus lines",
1463         3
1464        },
1465        {test_random, "Random", "[size] [loop] [addr]",
1466         "Verifies r/w and memcopy(burst for pseudo random value.",
1467         3
1468        },
1469        {test_freq_pattern, "FrequencySelectivePattern", "[size] [addr]",
1470         "write & test patterns: Mostly Zero, Mostly One and F/n",
1471         2
1472        },
1473        {test_blockseq, "BlockSequential", "[size] [loop] [addr]",
1474         "test incremental pattern",
1475         3
1476        },
1477        {test_checkboard, "Checkerboard", "[size] [loop] [addr]",
1478         "test checker pattern",
1479         3
1480        },
1481        {test_bitspread, "BitSpread", "[size] [loop] [addr]",
1482         "test Bit Spread pattern",
1483         3
1484        },
1485        {test_bitflip, "BitFlip", "[size] [loop] [addr]",
1486         "test Bit Flip pattern",
1487         3
1488        },
1489        {test_walkbit0, "WalkingOnes", "[size] [loop] [addr]",
1490         "test Walking Ones pattern",
1491         3
1492        },
1493        {test_walkbit1, "WalkingZeroes", "[size] [loop] [addr]",
1494         "test Walking Zeroes pattern",
1495         3
1496        },
1497        /* need to the the 2 last one (infinite) : skipped for test all */
1498        {test_read, "infinite read", "[addr] [pattern]",
1499         "basic test : infinite read access (random: addr=0xFFFFFFFF)", 2},
1500        {test_write, "infinite write", "[addr] [pattern]",
1501         "basic test : infinite write access (random: addr=0xFFFFFFFF)", 2},
1502};
1503
1504const int test_nb = ARRAY_SIZE(test);
1505