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