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