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