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