1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * memtester version 4
4 *
5 * Very simple but very effective user-space memory tester.
6 * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org>
7 * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca>
8 * Version 3 not publicly released.
9 * Version 4 rewrite:
10 * Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca>
11 * Licensed under the terms of the GNU General Public License version 2 (only).
12 * See the file COPYING for details.
13 *
14 */
15
16 #define __version__ "4.3.0"
17
18 #include <common.h>
19 #include <console.h>
20 #include "sizes.h"
21 #include "types.h"
22 #include "tests.h"
23 #include "../ddr_tool_common.h"
24 #include "../io_map.h"
25
26 #define EXIT_FAIL_NONSTARTER 0x01
27 #define EXIT_FAIL_ADDRESSLINES 0x02
28 #define EXIT_FAIL_OTHERTEST 0x04
29
30 struct test tests[] = {
31 {"Random Value", test_random_value},
32 {"Compare XOR", test_xor_comparison},
33 {"Compare SUB", test_sub_comparison},
34 {"Compare MUL", test_mul_comparison},
35 {"Compare DIV", test_div_comparison},
36 {"Compare OR", test_or_comparison},
37 {"Compare AND", test_and_comparison},
38 {"Sequential Increment", test_seqinc_comparison},
39 {"Solid Bits", test_solidbits_comparison},
40 {"Block Sequential", test_blockseq_comparison},
41 {"Checkerboard", test_checkerboard_comparison},
42 {"Bit Spread", test_bitspread_comparison},
43 {"Bit Flip", test_bitflip_comparison},
44 {"Walking Ones", test_walkbits1_comparison},
45 {"Walking Zeroes", test_walkbits0_comparison},
46 #ifdef TEST_NARROW_WRITES
47 {"8-bit Writes", test_8bit_wide_random},
48 {"16-bit Writes", test_16bit_wide_random},
49 #endif
50 {NULL, NULL}
51 };
52
53 int use_phys;
54 off_t physaddrbase;
55
56 /*
57 * arg[0]: test start address
58 * arg[1]: test length, unit: byte
59 * testenable: enable test case, if 0 enable all case
60 * loops: test loops, if 0 endless loop
61 * err_exit: 1: exit test when found fail.
62 * return 0: success, other: fail
63 */
doing_memtester(ul * arg,ul testenable,ul loops,ul err_exit,ul fix_bit,ul fix_level)64 int doing_memtester(ul *arg, ul testenable, ul loops, ul err_exit,
65 ul fix_bit, ul fix_level)
66 {
67 ul loop, i, j;
68 ul start_adr[CONFIG_NR_DRAM_BANKS], length[CONFIG_NR_DRAM_BANKS];
69 u32v * bufa[CONFIG_NR_DRAM_BANKS], *bufb[CONFIG_NR_DRAM_BANKS];
70 ul count[CONFIG_NR_DRAM_BANKS];
71 int exit_code = 0;
72 int abort = 0;
73 int test_banks;
74
75 get_print_available_addr(start_adr, length, 0);
76
77 test_banks = judge_test_addr(arg, start_adr, length);
78
79 if (!test_banks) {
80 printf("unavailable test address\n");
81 return -1;
82 }
83
84 for (i = 0; i < ARRAY_SIZE(start_adr); i++) {
85 bufa[i] = (u32v *)start_adr[i];
86 bufb[i] = (u32v *)(start_adr[i] + length[i] / 2);
87 count[i] = length[i] / 2 / sizeof(u32);
88 }
89
90 data_cpu_2_io_init();
91
92 for (loop = 1; ((!loops) || loop <= loops); loop++) {
93 for (j = 0; j < test_banks; j++) {
94 if (!count[j])
95 continue;
96 printf("testing:0x%lx - 0x%lx\n", (ul)bufa[j],
97 (ul)bufa[j] + count[j] * 2 * sizeof(u32));
98 printf("Loop %lu", loop);
99 if (loops)
100 printf("/%lu", loops);
101 printf(":\n");
102 if (testenable && ((1 << 17) & testenable)) {
103 printf(" %-20s: ", "Stuck Address");
104 if (!test_stuck_address(bufa[j], count[j] * 2))
105 printf("ok\n");
106 else
107 exit_code |= EXIT_FAIL_ADDRESSLINES;
108 }
109 for (i = 0;; i++) {
110 if (!tests[i].name)
111 break;
112 /* If using a custom testenable, only run this
113 * test if the bit corresponding to this test
114 * was set by the user.
115 */
116 if (testenable && (!((1 << i) & testenable)))
117 continue;
118 printf(" %-20s: ", tests[i].name);
119 if (!tests[i].fp(bufa[j], bufb[j], count[j],
120 fix_bit, fix_level)) {
121 printf("ok\n");
122 } else {
123 exit_code |= EXIT_FAIL_OTHERTEST;
124 if (err_exit) {
125 goto out;
126 }
127 }
128 if (ctrlc()) {
129 abort = 1;
130 break;
131 }
132 }
133 printf("\n");
134 if (abort)
135 break;
136 }
137 if (abort)
138 break;
139 }
140
141 out:
142 if (exit_code & EXIT_FAIL_NONSTARTER)
143 printf("Fail: EXIT_FAIL_NONSTARTER\n");
144 if (exit_code & EXIT_FAIL_ADDRESSLINES)
145 printf("Fail: EXIT_FAIL_ADDRESSLINES\n");
146 if (exit_code & EXIT_FAIL_OTHERTEST)
147 printf("Fail: EXIT_FAIL_OTHERTEST\n");
148
149 if (exit_code)
150 return -1;
151 return 0;
152 }
153
do_memtester(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])154 static int do_memtester(cmd_tbl_t *cmdtp, int flag, int argc,
155 char *const argv[])
156 {
157 ul start_adr[CONFIG_NR_DRAM_BANKS], length[CONFIG_NR_DRAM_BANKS];
158 ul arg[2];
159 ul loops = 0;
160 ul testenable = 0;
161 ul err_exit = 0;
162 ul fix_bit = 0;
163 ul fix_level = 0;
164
165 printf("memtester version " __version__ " (%d-bit)\n", UL_LEN);
166 printf("Copyright (C) 2001-2012 Charles Cazabon.\n");
167 printf("Licensed under the GNU General Public License version 2 (only).\n");
168 printf("\n");
169
170 get_print_available_addr(start_adr, length, 1);
171
172 if (argc < 2)
173 return CMD_RET_USAGE;
174
175 if (strict_strtoul(argv[1], 0, &arg[0]) < 0)
176 return CMD_RET_USAGE;
177
178 if (argc > 2)
179 if (strict_strtoul(argv[2], 0, &arg[1]) < 0)
180 return CMD_RET_USAGE;
181
182 if (argc > 3)
183 if (strict_strtoul(argv[3], 0, &testenable) < 0)
184 return CMD_RET_USAGE;
185
186 if (argc > 4)
187 if (strict_strtoul(argv[4], 0, &err_exit) < 0)
188 return CMD_RET_USAGE;
189
190 if (argc > 5)
191 if (strict_strtoul(argv[5], 0, &fix_bit) < 0)
192 return CMD_RET_USAGE;
193
194 if (argc > 6)
195 if (strict_strtoul(argv[6], 0, &fix_level) < 0)
196 return CMD_RET_USAGE;
197
198 if (argc > 7)
199 if (strict_strtoul(argv[7], 0, &loops) < 0)
200 return CMD_RET_USAGE;
201
202 doing_memtester(arg, testenable, loops, err_exit, fix_bit, fix_level);
203
204 printf("Done.\n");
205 return 0;
206 }
207
208 U_BOOT_CMD(memtester, 8, 1, do_memtester,
209 "do memtester",
210 "[start length [testenable err_exit fix_bit fix_level [loop]]]\n"
211 "start: start address, should be 4k align\n"
212 "length: test length, should be 4k align, if 0 testing full space\n"
213 "testenable[option]: enable pattern by set bit to 1, null or 0"
214 " enable all pattern\n"
215 " bit0: Random Value\n"
216 " bit1: Compare XOR\n"
217 " bit2: Compare SUB\n"
218 " bit3: Compare MUL\n"
219 " bit4: Compare DIV\n"
220 " bit5: Compare OR\n"
221 " bit6: Compare AND\n"
222 " bit7: Sequential Increment\n"
223 " bit8: Solid Bits\n"
224 " bit9: Block Sequential\n"
225 " bit10: Checkerboard\n"
226 " bit11: Bit Spread\n"
227 " bit12: Bit Flip\n"
228 " bit13: Walking Ones\n"
229 " bit14: Walking Zeroes\n"
230 " bit15: 8-bit Writes\n"
231 " bit16: 16-bit Writes\n"
232 " bit17: test stuck address\n"
233 " example: testenable=0x1000,enable Bit Flip only\n"
234 "err_exit: if 1 stop testing immediately when finding error\n"
235 "fix_bit: fixed bit to a exact level\n"
236 "fix_level: fix_bit's level, 0: low, 1: high\n"
237 "loop[option]: testing loop, if 0 or null endless loop\n"
238 "example:\n"
239 " memtester 0x200000 0x1000000: start address: 0x200000 length:"
240 "0x1000000, enable all pattern, endless loop\n"
241 " memtester 0x200000 0x1000000 0x1000 100: start address:0x200000"
242 " length:0x1000000, Bit Flip only, loop 100 times\n"
243 " memtester 0 0: testing full space\n");
244