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