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