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