xref: /rk3399_rockchip-uboot/cmd/ddr_tool/stressapptest/stressapptest.c (revision 2d08ea87864a34c9e03c965b76b5fb18c1573675)
1 // Copyright 2006 Google Inc. All Rights Reserved.
2 /* Licensed under the Apache License, Version 2.0 (the "License");
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  *	http://www.apache.org/licenses/LICENSE-2.0
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14 
15 /* This is stressapptest for Rockchip platform in U-Boot, the design idea and
16  * the patterns are from code.google.com/p/stressapptest.
17  */
18 
19 #include <common.h>
20 #include <amp.h>
21 #include <div64.h>
22 #include <malloc.h>
23 #include <asm/arch/rockchip_smccc.h>
24 #include "stressapptest.h"
25 #include "../ddr_tool_common.h"
26 
27 #define __version__ "v1.0.0 20230214"
28 
29 #if defined(CONFIG_ARM64)
30 /* Float operation in TOOLCHAIN_ARM32 will cause the compile error */
31 #define WARM_CPU
32 #endif
33 
34 #define PAT_NUM			26
35 #define PATTERN_LIST_SIZE	(PAT_NUM * 2 * 4)
36 
37 #define CPU_NUM_MAX		16
38 
39 static u32 walking_1_data[] = {
40 	0x00000001, 0x00000002, 0x00000004, 0x00000008,
41 	0x00000010, 0x00000020, 0x00000040, 0x00000080,
42 	0x00000100, 0x00000200, 0x00000400, 0x00000800,
43 	0x00001000, 0x00002000, 0x00004000, 0x00008000,
44 	0x00010000, 0x00020000, 0x00040000, 0x00080000,
45 	0x00100000, 0x00200000, 0x00400000, 0x00800000,
46 	0x01000000, 0x02000000, 0x04000000, 0x08000000,
47 	0x10000000, 0x20000000, 0x40000000, 0x80000000,
48 	0x40000000, 0x20000000, 0x10000000, 0x08000000,
49 	0x04000000, 0x02000000, 0x01000000, 0x00800000,
50 	0x00400000, 0x00200000, 0x00100000, 0x00080000,
51 	0x00040000, 0x00020000, 0x00010000, 0x00008000,
52 	0x00004000, 0x00002000, 0x00001000, 0x00000800,
53 	0x00000400, 0x00000200, 0x00000100, 0x00000080,
54 	0x00000040, 0x00000020, 0x00000010, 0x00000008,
55 	0x00000004, 0x00000002, 0x00000001, 0x00000000
56 };
57 
58 static struct pat walking_1 = {
59 	"walking_1",
60 	walking_1_data,
61 	ARRAY_SIZE(walking_1_data) - 1,	/* mask */
62 	{1, 1, 2, 1}	/* weight */
63 };
64 
65 static u32 walking_1_x16_data[] =   {
66 	0x00020001, 0x00080004, 0x00200010, 0x00800040,
67 	0x02000100, 0x08000400, 0x20001000, 0x80004000,
68 	0x20004000, 0x08001000, 0x02000400, 0x00800100,
69 	0x00200040, 0x00080010, 0x00020004, 0x00000001
70 };
71 
72 static struct pat walking_1_x16 = {
73 	"walking_1_x16",
74 	walking_1_x16_data,
75 	ARRAY_SIZE(walking_1_x16_data) - 1,	/* mask */
76 	{2, 0, 0, 0}	/* Weight for choosing 32/64/128/256 bit wide of this pattern */
77 	/* Reuse for walking_0_x16, because of invert */
78 };
79 
80 static u32 walking_1_x16_repeat_data[] =   {
81 	0x00010001, 0x00020002, 0x00040004, 0x00080008,
82 	0x00100010, 0x00200020, 0x00400040, 0x00800080,
83 	0x01000100, 0x02000200, 0x04000400, 0x08000800,
84 	0x10001000, 0x20002000, 0x40004000, 0x80008000,
85 	0x40004000, 0x20002000, 0x10001000, 0x08000800,
86 	0x04000400, 0x02000200, 0x01000100, 0x00800080,
87 	0x00400040, 0x00200020, 0x00100010, 0x00080008,
88 	0x00040004, 0x00020002, 0x00010001, 0x00000000
89 };
90 
91 static struct pat walking_1_x16_repeat = {
92 	"walking_1_x16_repeat",
93 	walking_1_x16_repeat_data,
94 	ARRAY_SIZE(walking_1_x16_repeat_data) - 1,	/* mask */
95 	{2, 4, 2, 0}	/* Weight for choosing 32/64/128/256 bit wide of this pattern */
96 	/* Reuse for walking_0_x16_repeat, because of invert */
97 };
98 
99 static u32 walking_inv_1_data[] = {
100 	0x00000001, 0xfffffffe, 0x00000002, 0xfffffffd,
101 	0x00000004, 0xfffffffb, 0x00000008, 0xfffffff7,
102 	0x00000010, 0xffffffef, 0x00000020, 0xffffffdf,
103 	0x00000040, 0xffffffbf, 0x00000080, 0xffffff7f,
104 	0x00000100, 0xfffffeff, 0x00000200, 0xfffffdff,
105 	0x00000400, 0xfffffbff, 0x00000800, 0xfffff7ff,
106 	0x00001000, 0xffffefff, 0x00002000, 0xffffdfff,
107 	0x00004000, 0xffffbfff, 0x00008000, 0xffff7fff,
108 	0x00010000, 0xfffeffff, 0x00020000, 0xfffdffff,
109 	0x00040000, 0xfffbffff, 0x00080000, 0xfff7ffff,
110 	0x00100000, 0xffefffff, 0x00200000, 0xffdfffff,
111 	0x00400000, 0xffbfffff, 0x00800000, 0xff7fffff,
112 	0x01000000, 0xfeffffff, 0x02000000, 0xfdffffff,
113 	0x04000000, 0xfbffffff, 0x08000000, 0xf7ffffff,
114 	0x10000000, 0xefffffff, 0x20000000, 0xdfffffff,
115 	0x40000000, 0xbfffffff, 0x80000000, 0x7fffffff,
116 	0x40000000, 0xbfffffff, 0x20000000, 0xdfffffff,
117 	0x10000000, 0xefffffff, 0x08000000, 0xf7ffffff,
118 	0x04000000, 0xfbffffff, 0x02000000, 0xfdffffff,
119 	0x01000000, 0xfeffffff, 0x00800000, 0xff7fffff,
120 	0x00400000, 0xffbfffff, 0x00200000, 0xffdfffff,
121 	0x00100000, 0xffefffff, 0x00080000, 0xfff7ffff,
122 	0x00040000, 0xfffbffff, 0x00020000, 0xfffdffff,
123 	0x00010000, 0xfffeffff, 0x00008000, 0xffff7fff,
124 	0x00004000, 0xffffbfff, 0x00002000, 0xffffdfff,
125 	0x00001000, 0xffffefff, 0x00000800, 0xfffff7ff,
126 	0x00000400, 0xfffffbff, 0x00000200, 0xfffffdff,
127 	0x00000100, 0xfffffeff, 0x00000080, 0xffffff7f,
128 	0x00000040, 0xffffffbf, 0x00000020, 0xffffffdf,
129 	0x00000010, 0xffffffef, 0x00000008, 0xfffffff7,
130 	0x00000004, 0xfffffffb, 0x00000002, 0xfffffffd,
131 	0x00000001, 0xfffffffe, 0x00000000, 0xffffffff
132 };
133 
134 static struct pat walking_inv_1 = {
135 	"walking_inv_1",
136 	walking_inv_1_data,
137 	ARRAY_SIZE(walking_inv_1_data) - 1,	/* mask */
138 	{2, 2, 5, 5}	/* weight */
139 };
140 
141 static u32 walking_inv_1_x16_data[] = {
142 	0xfffe0001, 0xfffd0002, 0xfffb0004, 0xfff70008,
143 	0xffef0010, 0xffdf0020, 0xffbf0040, 0xff7f0080,
144 	0xfeff0100, 0xfdff0200, 0xfbff0400, 0xf7ff0800,
145 	0xefff1000, 0xdfff2000, 0xbfff4000, 0x7fff8000,
146 	0xbfff4000, 0xdfff2000, 0xefff1000, 0xf7ff0800,
147 	0xfbff0400, 0xfdff0200, 0xfeff0100, 0xff7f0080,
148 	0xffbf0040, 0xffdf0020, 0xffef0010, 0xfff70008,
149 	0xfffb0004, 0xfffd0002, 0xfffe0001, 0xffff0000
150 };
151 
152 static struct pat walking_inv_1_x16 = {
153 	"walking_inv_1_x16",
154 	walking_inv_1_x16_data,
155 	ARRAY_SIZE(walking_inv_1_x16_data) - 1,	/* mask */
156 	{2, 0, 0, 0}	/* weight */
157 };
158 
159 static u32 walking_inv_1_x16_repeat_data[] = {
160 	0x00010001, 0xfffefffe, 0x00020002, 0xfffdfffd,
161 	0x00040004, 0xfffbfffb, 0x00080008, 0xfff7fff7,
162 	0x00100010, 0xffefffef, 0x00200020, 0xffdfffdf,
163 	0x00400040, 0xffbfffbf, 0x00800080, 0xff7fff7f,
164 	0x01000100, 0xfefffeff, 0x02000200, 0xfdfffdff,
165 	0x04000400, 0xfbfffbff, 0x08000800, 0xf7fff7ff,
166 	0x10001000, 0xefffefff, 0x20002000, 0xdfffdfff,
167 	0x40004000, 0xbfffbfff, 0x80008000, 0x7fff7fff,
168 	0x40004000, 0xbfffbfff, 0x20002000, 0xdfffdfff,
169 	0x10001000, 0xefffefff, 0x08000800, 0xf7fff7ff,
170 	0x04000400, 0xfbfffbff, 0x02000200, 0xfdfffdff,
171 	0x01000100, 0xfefffeff, 0x00800080, 0xff7fff7f,
172 	0x00400040, 0xffbfffbf, 0x00200020, 0xffdfffdf,
173 	0x00100010, 0xffefffef, 0x00080008, 0xfff7fff7,
174 	0x00040004, 0xfffbfffb, 0x00020002, 0xfffdfffd,
175 	0x00010001, 0xfffefffe, 0x00000000, 0xffffffff
176 };
177 
178 static struct pat walking_inv_1_x16_repeat = {
179 	"walking_inv_1_x16_repeat",
180 	walking_inv_1_x16_repeat_data,
181 	ARRAY_SIZE(walking_inv_1_x16_repeat_data) - 1,	/* mask */
182 	{2, 5, 5, 0}	/* weight */
183 };
184 
185 static u32 walking_0_data[] = {
186 	0xfffffffe, 0xfffffffd, 0xfffffffb, 0xfffffff7,
187 	0xffffffef, 0xffffffdf, 0xffffffbf, 0xffffff7f,
188 	0xfffffeff, 0xfffffdff, 0xfffffbff, 0xfffff7ff,
189 	0xffffefff, 0xffffdfff, 0xffffbfff, 0xffff7fff,
190 	0xfffeffff, 0xfffdffff, 0xfffbffff, 0xfff7ffff,
191 	0xffefffff, 0xffdfffff, 0xffbfffff, 0xff7fffff,
192 	0xfeffffff, 0xfdffffff, 0xfbffffff, 0xf7ffffff,
193 	0xefffffff, 0xdfffffff, 0xbfffffff, 0x7fffffff,
194 	0xbfffffff, 0xdfffffff, 0xefffffff, 0xf7ffffff,
195 	0xfbffffff, 0xfdffffff, 0xfeffffff, 0xff7fffff,
196 	0xffbfffff, 0xffdfffff, 0xffefffff, 0xfff7ffff,
197 	0xfffbffff, 0xfffdffff, 0xfffeffff, 0xffff7fff,
198 	0xffffbfff, 0xffffdfff, 0xffffefff, 0xfffff7ff,
199 	0xfffffbff, 0xfffffdff, 0xfffffeff, 0xffffff7f,
200 	0xffffffbf, 0xffffffdf, 0xffffffef, 0xfffffff7,
201 	0xfffffffb, 0xfffffffd, 0xfffffffe, 0xffffffff
202 };
203 
204 static struct pat walking_0 = {
205 	"walking_0",
206 	walking_0_data,
207 	ARRAY_SIZE(walking_0_data) - 1,	/* mask */
208 	{1, 1, 2, 1}	/* weight */
209 };
210 
211 static u32 one_zero_data[] = {0x00000000, 0xffffffff};
212 
213 static struct pat one_zero = {
214 	"one_zero",
215 	one_zero_data,
216 	ARRAY_SIZE(one_zero_data) - 1,	/* mask */
217 	{5, 5, 15, 5}	/* weight */
218 };
219 
220 static unsigned int one_zero_x16_data[] = {0x0000ffff, 0x0000ffff};
221 
222 static struct pat one_zero_x16 = {
223 	"one_zero_x16",
224 	one_zero_x16_data,
225 	ARRAY_SIZE(one_zero_x16_data) - 1,	/* mask */
226 	{5, 0, 0, 0}	/* weight */
227 };
228 
229 static u32 just_0_data[] = {0x00000000, 0x00000000};
230 
231 static struct pat just_0 = {
232 	"just_0",
233 	just_0_data,
234 	ARRAY_SIZE(just_0_data) - 1,	/* mask */
235 	{2, 0, 0, 0}	/* weight */
236 };
237 
238 static u32 just_1_data[] = {0xffffffff, 0xffffffff};
239 
240 static struct pat just_1 = {
241 	"just_1",
242 	just_1_data,
243 	ARRAY_SIZE(just_1_data) - 1,	/* mask */
244 	{2, 0, 0, 0}	/* weight */
245 };
246 
247 static u32 just_5_data[] = {0x55555555, 0x55555555};
248 
249 static struct pat just_5 = {
250 	"just_5",
251 	just_5_data,
252 	ARRAY_SIZE(just_5_data) - 1,	/* mask */
253 	{2, 0, 0, 0}	/* weight */
254 };
255 
256 static u32 just_a_data[] = {0xaaaaaaaa, 0xaaaaaaaa};
257 
258 static struct pat just_a = {
259 	"just_a",
260 	just_a_data,
261 	ARRAY_SIZE(just_a_data) - 1,	/* mask */
262 	{2, 0, 0, 0}	/* weight */
263 };
264 
265 static u32 five_a_data[] = {0x55555555, 0xaaaaaaaa};
266 
267 static struct pat five_a = {
268 	"five_a",
269 	five_a_data,
270 	ARRAY_SIZE(five_a_data) - 1,	/* mask */
271 	{1, 1, 1, 1}	/* weight */
272 };
273 
274 static unsigned int five_a_x16_data[] = {0x5555aaaa, 0x5555aaaa};
275 
276 static struct pat five_a_x16 = {
277 	"five_a_x16",
278 	five_a_x16_data,
279 	ARRAY_SIZE(five_a_x16_data) - 1,	/* mask */
280 	{1, 0, 0, 0}	/* weight */
281 };
282 
283 static u32 five_a8_data[] = {
284 	0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a
285 };
286 
287 static struct pat five_a8 = {
288 	"five_a8",
289 	five_a8_data,
290 	ARRAY_SIZE(five_a8_data) - 1,	/* mask */
291 	{1, 1, 1, 1}	/* weight */
292 };
293 
294 static u32 five_a8_x16_data[] = {0x5aa5a55a, 0xa55a5aa5};
295 
296 static struct pat five_a8_x16 = {
297 	"five_a8_x16",
298 	five_a8_x16_data,
299 	ARRAY_SIZE(five_a8_x16_data) - 1,	/* mask */
300 	{1, 0, 0, 0}	/* weight */
301 };
302 
303 static unsigned int five_a8_x16_repeat_data[] = {
304 	0x5aa55aa5, 0xa55aa55a, 0xa55aa55a, 0x5aa55aa5
305 };
306 
307 static struct pat five_a8_x16_repeat = {
308 	"five_a8_x16_repeat",
309 	five_a8_x16_repeat_data,
310 	ARRAY_SIZE(five_a8_x16_repeat_data) - 1,	/* mask */
311 	{1, 1, 1, 0}	/* weight */
312 };
313 
314 static u32 long_8b10b_data[] = {0x16161616, 0x16161616};
315 
316 static struct pat long_8b10b = {
317 	"long_8b10b",
318 	long_8b10b_data,
319 	ARRAY_SIZE(long_8b10b_data) - 1,	/* mask */
320 	{2, 0, 0, 0}	/* weight */
321 };
322 
323 static u32 short_8b10b_data[] = {0xb5b5b5b5, 0xb5b5b5b5};
324 
325 static struct pat short_8b10b = {
326 	"short_8b10b",
327 	short_8b10b_data,
328 	ARRAY_SIZE(short_8b10b_data) - 1,	/* mask */
329 	{2, 0, 0, 0}	/* weight */
330 };
331 
332 static u32 checker_8b10b_data[] = {0xb5b5b5b5, 0x4a4a4a4a};
333 
334 static struct pat checker_8b10b = {
335 	"checker_8b10b",
336 	checker_8b10b_data,
337 	ARRAY_SIZE(checker_8b10b_data) - 1,	/* mask */
338 	{1, 0, 1, 1}	/* weight */
339 };
340 
341 static u32 checker_8b10b_x16_data[] = {0xb5b54a4a, 0xb5b54a4a};
342 
343 static struct pat checker_8b10b_x16 = {
344 	"checker_8b10b_x16",
345 	checker_8b10b_x16_data,
346 	ARRAY_SIZE(checker_8b10b_x16_data) - 1,	/* mask */
347 	{1, 0, 0, 0}	/* weight */
348 };
349 
350 static u32 five_7_data[] = {0x55555557, 0x55575555};
351 
352 static struct pat five_7 = {
353 	"five_7",
354 	five_7_data,
355 	ARRAY_SIZE(five_7_data) - 1,	/* mask */
356 	{0, 2, 0, 0}	/* weight */
357 };
358 
359 static u32 five_7_x16_data[] = {0x55575557, 0x57555755};
360 
361 static struct pat five_7_x16 = {
362 	"five_7_x16",
363 	five_7_x16_data,
364 	ARRAY_SIZE(five_7_x16_data) - 1,	/* mask */
365 	{2, 0, 0, 0}	/* weight */
366 };
367 
368 static u32 zero2_fd_data[] = {0x00020002, 0xfffdfffd};
369 
370 static struct pat zero2_fd = {
371 	"zero2_fd",
372 	zero2_fd_data,
373 	ARRAY_SIZE(zero2_fd_data) - 1,	/* mask */
374 	{0, 2, 0, 0}	/* weight */
375 };
376 
377 static u32 zero2_fd_x16_data[] = {0x02020202, 0xfdfdfdfd};
378 
379 static struct pat zero2_fd_x16 = {
380 	"zero2_fd_x16",
381 	zero2_fd_x16_data,
382 	ARRAY_SIZE(zero2_fd_x16_data) - 1,	/* mask */
383 	{2, 0, 0, 0}	/* weight */
384 };
385 
386 static struct pat *pat_array[] = {
387 	&walking_1,
388 	&walking_1_x16,
389 	&walking_1_x16_repeat,
390 	&walking_inv_1,
391 	&walking_inv_1_x16,
392 	&walking_inv_1_x16_repeat,
393 	&walking_0,
394 	&one_zero,
395 	&one_zero_x16,
396 	&just_0,
397 	&just_1,
398 	&just_5,
399 	&just_a,
400 	&five_a,
401 	&five_a_x16,
402 	&five_a8,
403 	&five_a8_x16,
404 	&five_a8_x16_repeat,
405 	&long_8b10b,
406 	&short_8b10b,
407 	&checker_8b10b,
408 	&checker_8b10b_x16,
409 	&five_7,
410 	&five_7_x16,
411 	&zero2_fd,
412 	&zero2_fd_x16
413 };
414 
415 static u32 cpu_copy_err[CPU_NUM_MAX];
416 static u32 cpu_inv_err[CPU_NUM_MAX];
417 
418 static u64 start_time_us;
419 static u64 test_time_us;
420 
421 static bool cpu_init_finish[CPU_NUM_MAX];
422 static bool cpu_test_finish[CPU_NUM_MAX];
423 static bool pattern_page_init_finish;
424 
425 #if (CPU_NUM_MAX > 1)
426 static ulong test_count = 0;
427 static ulong __gd;	/* set r9/x18 of secondary cpu to gd addr */
428 #endif
429 ulong __sp;		/* set sp of secondary cpu */
430 
431 u32 print_mutex;	/* 0: unlock, 1: lock */
432 
433 static u64 get_time_us(void)
434 {
435 	return lldiv(get_ticks(), CONFIG_SYS_HZ_CLOCK / (CONFIG_SYS_HZ * 1000));
436 }
437 
438 static u64 run_time_us(void)
439 {
440 	return get_time_us() - start_time_us;
441 }
442 
443 static void print_time_stamp(void)
444 {
445 	u64 time_us;
446 
447 	time_us = run_time_us();
448 
449 	printf("[%5d.%06d] ", (u32)(time_us / 1000000), (u32)(time_us % 1000000));
450 }
451 
452 static u32 pattern_get(struct pattern *pattern, u32 offset)
453 {
454 	u32 ret;
455 
456 	ret = pattern->pat->data_array[(offset >> pattern->repeat) &
457 				       pattern->pat->mask];
458 
459 	return pattern->inv ? ~ret : ret;
460 }
461 
462 static void pattern_adler_sum_calc(struct pattern *pattern,
463 				   struct stressapptest_params *sat)
464 {
465 	int i = 0;
466 	u64 a1 = 1;
467 	u64 b1 = 0;
468 	u64 a2 = 1;
469 	u64 b2 = 0;
470 
471 	while (i < sat->block_size_byte / sizeof(u32)) {
472 		a1 += (u64)pattern_get(pattern, i++);
473 		b1 += a1;
474 		a1 += pattern_get(pattern, i++);
475 		b1 += a1;
476 
477 		a2 += (u64)pattern_get(pattern, i++);
478 		b2 += a2;
479 		a2 += pattern_get(pattern, i++);
480 		b2 += a2;
481 	}
482 
483 	pattern->adler_sum.a1 = a1;
484 	pattern->adler_sum.b1 = b1;
485 	pattern->adler_sum.a2 = a2;
486 	pattern->adler_sum.b2 = b2;
487 }
488 
489 static void pattern_list_init(struct pattern *pattern_list,
490 			      struct stressapptest_params *sat)
491 {
492 	u32 weight_count = 0;
493 	int k = 0;
494 
495 	for (int i = 0; i < PAT_NUM; i++) {
496 		for (int j = 0; j < 8; j++) {
497 			pattern_list[k].pat = pat_array[i];
498 			pattern_list[k].inv = j % 2;
499 			pattern_list[k].repeat = j / 2;
500 			pattern_list[k].weight = pattern_list[k].pat->weight[j / 2];
501 			pattern_adler_sum_calc(&pattern_list[k], sat);
502 			weight_count += pattern_list[k].weight;
503 			k++;
504 		}
505 	}
506 
507 	sat->weight_count = weight_count;
508 }
509 
510 static int get_page_addr(struct page *page_list,
511 			 struct stressapptest_params *sat)
512 {
513 	ulong start_adr[CONFIG_NR_DRAM_BANKS], length[CONFIG_NR_DRAM_BANKS];
514 	ulong used_length;
515 	u32 page = 0;
516 
517 	get_print_available_addr(start_adr, length, 1);
518 
519 	printf("Pages for test:\n	Page	Start        End        Length\n");
520 
521 	for (int i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
522 		if ((start_adr[i] == 0 && length[i] == 0) || page >= sat->page_num)
523 			break;
524 		if (start_adr[i] + length[i] < sat->total_start_addr)
525 			continue;
526 		if (start_adr[i] < sat->total_start_addr) {
527 			length[i] -= sat->total_start_addr - start_adr[i];
528 			start_adr[i] = sat->total_start_addr;
529 		}
530 
531 		used_length = 0;
532 		while (page < sat->page_num &&
533 		       length[i] >= used_length + sat->page_size_byte) {
534 			page_list[page].base_addr = (void *)(start_adr[i] + used_length);
535 			used_length += sat->page_size_byte;
536 			printf("	%d	0x%08lx - 0x%08lx 0x%08lx\n",
537 			       page, (ulong)page_list[page].base_addr,
538 			       (ulong)page_list[page].base_addr + sat->page_size_byte,
539 			       (ulong)sat->page_size_byte);
540 			page++;
541 		}
542 	}
543 
544 	if (page < sat->page_num) {
545 		printf("ERROR: Cannot get enough pages to test.\n");
546 		printf("Please decrease page_size or test_size\n");
547 
548 		return -1;
549 	}
550 
551 	return 0;
552 }
553 
554 static void page_init_valid(struct page *page, struct pattern *pattern_list,
555 			    struct stressapptest_params *sat)
556 {
557 	int target;
558 	int i = 0;
559 	u64 *mem;
560 
561 	target = (rand() % sat->weight_count) + 1;
562 	do {
563 		target -= pattern_list[i++].weight;
564 		if (target <= 0)
565 			break;
566 	} while (i < PATTERN_LIST_SIZE);
567 	page->pattern = &pattern_list[--i];
568 	page->valid = 1;
569 
570 	mem = (u64 *)page->base_addr;
571 	for (i = 0; i < sat->page_size_byte / sizeof(u64); i++)
572 		mem[i] = (u64)pattern_get(page->pattern, i * 2) |
573 			 (u64)pattern_get(page->pattern, i * 2 + 1) << 32;
574 }
575 
576 static void page_init_empty(struct page *page)
577 {
578 	page->valid = 0;
579 }
580 
581 static void page_init(struct pattern *pattern_list,
582 		      struct stressapptest_params *sat)
583 {
584 	int i, cpu;
585 	u32 empty_page_num;
586 
587 	for (cpu = 0; cpu < sat->cpu_num; cpu++) {
588 		empty_page_num = 0;
589 		for (i = cpu; i < sat->page_num; i += sat->cpu_num) {
590 			if (rand() % 5 < 3) {
591 				page_list[i].valid = 1;
592 			} else {
593 				page_list[i].valid = 0;
594 				empty_page_num++;
595 			}
596 		}
597 		while (empty_page_num >= sat->page_num / sat->cpu_num / 2 && i > 0) {
598 			i -= sat->cpu_num;
599 			if (page_list[i].valid == 0) {
600 				page_list[i].valid = 1;
601 				empty_page_num--;
602 			}
603 		}
604 		i = cpu;
605 		while (empty_page_num < 2 && i < sat->page_num) {
606 			if (page_list[i].valid == 1) {
607 				page_list[i].valid = 0;
608 				empty_page_num++;
609 			}
610 			i += sat->cpu_num;
611 		}
612 	}
613 
614 	for (i = 0; i < sat->page_num; i++) {
615 		if (page_list[i].valid == 1)
616 			page_init_valid(&page_list[i], pattern_list, sat);
617 		else
618 			page_init_empty(&page_list[i]);
619 	}
620 	flush_dcache_all();
621 }
622 
623 static u32 page_rand_pick(struct page *page_list, bool valid,
624 			  struct stressapptest_params *sat, u8 cpu_id)
625 {
626 	u32 pick;
627 
628 	pick = rand() % (sat->page_num / sat->cpu_num) * sat->cpu_num + cpu_id;
629 	while (page_list[pick].valid != valid) {
630 		pick += sat->cpu_num;
631 		if (pick >= sat->page_num)
632 			pick = cpu_id;
633 	}
634 
635 	return pick;
636 }
637 
638 static u32 block_inv_mis_search(void *dst_addr, struct pattern *src_pattern,
639 				struct stressapptest_params *sat)
640 {
641 	u32 *dst_mem;
642 	u32 dst_data;
643 	u32 expc_data;
644 	u32 mis_bit;
645 	u32 err = 0;
646 
647 	dst_mem = (u32 *)dst_addr;
648 
649 	for (int i = 0; i < sat->block_size_byte / sizeof(u32); i++) {
650 		dst_data = dst_mem[i];
651 		expc_data = pattern_get(src_pattern, i);
652 
653 		if (dst_data != expc_data) {
654 			lock_byte_mutex(&print_mutex);
655 
656 			print_time_stamp();
657 			printf("INV ERROR at 0x%010lx:\n", (ulong)&dst_mem[i]);
658 			printf("	data = 0x%08x\n", dst_data);
659 			printf("	expc = 0x%08x\n", expc_data);
660 
661 			mis_bit = dst_data ^ expc_data;
662 			printf("	mismatch at bit");
663 			for (int j = 31; j >= 0; j--) {
664 				if (((mis_bit >> j) & 1) == 1)
665 					printf(" %d", j);
666 			}
667 			printf("\n");
668 
669 			unlock_byte_mutex(&print_mutex);
670 			dst_mem[i] = expc_data;
671 			err++;
672 		}
673 	}
674 	flush_dcache_all();
675 
676 	if (err == 0) {
677 		lock_byte_mutex(&print_mutex);
678 		printf("INV ERROR detected but cannot find mismatch data (maybe read error).\n");
679 		unlock_byte_mutex(&print_mutex);
680 	}
681 
682 	return err;
683 }
684 
685 static u32 block_inv_check(void *dst_addr, struct pattern *src_pattern,
686 			   struct stressapptest_params *sat, u8 cpu_id)
687 {
688 	u32 *dst_mem;
689 	u32 err = 0;
690 	int i = 0;
691 #if defined(WARM_CPU)
692 	double a, b, c, d;
693 #endif
694 
695 	struct adler_sum adler_sum = {
696 		1, 0, 1, 0
697 	};
698 
699 	dst_mem = (u32 *)dst_addr;
700 
701 #if defined(WARM_CPU)
702 	a = 2.0 * dst_mem[0];
703 	b = 5.0 * dst_mem[0];
704 	c = 7.0 * dst_mem[0];
705 	d = 9.0 * dst_mem[0];
706 #endif
707 
708 	while (i < sat->block_size_byte / sizeof(u32)) {
709 		adler_sum.a1 += dst_mem[i++];
710 		adler_sum.b1 += adler_sum.a1;
711 		adler_sum.a1 += dst_mem[i++];
712 		adler_sum.b1 += adler_sum.a1;
713 
714 #if defined(WARM_CPU)
715 		a = a * b;
716 		b = b + c;
717 #endif
718 
719 		adler_sum.a2 += dst_mem[i++];
720 		adler_sum.b2 += adler_sum.a2;
721 		adler_sum.a2 += dst_mem[i++];
722 		adler_sum.b2 += adler_sum.a2;
723 #if defined(WARM_CPU)
724 		c = c * d;
725 		d = d + d;
726 #endif
727 	}
728 
729 #if defined(WARM_CPU)
730 	d = a + b + c + d;
731 	if (d == 1.0)
732 		/* Reference the result so that it can't be discarded by the compiler. */
733 		printf("This will probably never happen.\n");
734 #endif
735 
736 	if (adler_sum.a1 != src_pattern->adler_sum.a1 ||
737 	    adler_sum.b1 != src_pattern->adler_sum.b1 ||
738 	    adler_sum.a2 != src_pattern->adler_sum.a2 ||
739 	    adler_sum.b2 != src_pattern->adler_sum.b2) {
740 		err = block_inv_mis_search(dst_addr, src_pattern, sat);
741 
742 		lock_byte_mutex(&print_mutex);
743 		printf("(CPU%d, Pattern: %s, inv: %d, repeat: %d)\n\n",
744 		       cpu_id, src_pattern->pat->name, src_pattern->inv,
745 		       src_pattern->repeat);
746 		unlock_byte_mutex(&print_mutex);
747 	}
748 
749 	return err;
750 }
751 
752 static void page_inv_up(void *src_addr, struct stressapptest_params *sat)
753 {
754 	void *dst_addr = src_addr;
755 	uint data;
756 	uint *dst_mem;
757 
758 	for (int i = 0; i < sat->block_num; i++) {
759 		dst_mem = (uint *)dst_addr;
760 		for (int j = 0; j < sat->block_size_byte / sizeof(uint); j++) {
761 			data = dst_mem[j];
762 			dst_mem[j] = ~data;
763 		}
764 		dst_addr += sat->block_size_byte;
765 		flush_dcache_all();
766 	}
767 }
768 
769 static void page_inv_down(void *src_addr, struct stressapptest_params *sat)
770 {
771 	void *dst_addr = src_addr;
772 	uint data;
773 	uint *dst_mem;
774 
775 	dst_addr += sat->block_size_byte * (sat->block_num - 1);
776 
777 	for (int i = sat->block_num - 1; i >= 0; i--) {
778 		dst_mem = (uint *)dst_addr;
779 		for (int j = sat->block_size_byte / sizeof(uint) - 1; j >= 0; j--) {
780 			data = dst_mem[j];
781 			dst_mem[j] = ~data;
782 		}
783 		dst_addr -= sat->block_size_byte;
784 		flush_dcache_all();
785 	}
786 }
787 
788 static u32 page_inv(struct stressapptest_params *sat, u8 cpu_id)
789 {
790 	u32 src;
791 	void *dst_block_addr;
792 	u32 err = 0;
793 
794 	src = page_rand_pick(page_list, 1, sat, cpu_id);	/* pick a valid page */
795 	dst_block_addr = page_list[src].base_addr;
796 
797 	for (int i = 0; i < 4; i++) {
798 		if (rand() % 2 == 0)
799 			page_inv_up(page_list[src].base_addr, sat);
800 		else
801 			page_inv_down(page_list[src].base_addr, sat);
802 	}
803 
804 	for (int i = 0; i < sat->block_num; i++) {
805 		err += block_inv_check(dst_block_addr, page_list[src].pattern, sat, cpu_id);
806 		dst_block_addr += sat->block_size_byte;
807 	}
808 
809 	flush_dcache_all();
810 
811 	return err;
812 }
813 
814 static u32 block_copy_mis_search(void *dst_addr, void *src_addr,
815 				 struct pattern *src_pattern,
816 				 struct stressapptest_params *sat)
817 {
818 	u32 *dst_mem;
819 	u32 *src_mem;
820 	u32 dst_data;
821 	u32 src_data;
822 	u32 expc_data;
823 	u32 mis_bit;
824 	u32 err = 0;
825 
826 	dst_mem = (u32 *)dst_addr;
827 	src_mem = (u32 *)src_addr;
828 
829 	for (int i = 0; i < sat->block_size_byte / sizeof(u32); i++) {
830 		dst_data = dst_mem[i];
831 		src_data = src_mem[i];
832 		expc_data = pattern_get(src_pattern, i);
833 
834 		if (dst_data != expc_data) {
835 			lock_byte_mutex(&print_mutex);
836 
837 			print_time_stamp();
838 			printf("COPY ERROR (");
839 			if (src_data == expc_data)
840 				printf("read");
841 			else if (src_data != expc_data)
842 				printf("write");
843 			printf(" error) at 0x%010lx:\n", (ulong)&src_mem[i]);
844 			printf("	data = 0x%08x\n", dst_data);
845 			printf("	expc = 0x%08x\n", expc_data);
846 
847 			mis_bit = dst_data ^ expc_data;
848 			printf("	mismatch at bit");
849 			for (int j = 31; j >= 0; j--) {
850 				if (((mis_bit >> j) & 1) == 1)
851 					printf(" %d", j);
852 			}
853 			printf("\n");
854 
855 			unlock_byte_mutex(&print_mutex);
856 			err++;
857 			dst_mem[i] = expc_data;
858 		}
859 	}
860 	flush_dcache_all();
861 
862 	if (err == 0) {
863 		lock_byte_mutex(&print_mutex);
864 		printf("COPY ERROR detected but cannot find mismatch data (maybe read error).\n");
865 		unlock_byte_mutex(&print_mutex);
866 	}
867 
868 	return err;
869 }
870 
871 static u32 block_copy_check(void *dst_addr, void *src_addr,
872 			    struct adler_sum *adler_sum,
873 			    struct pattern *src_pattern,
874 			    struct stressapptest_params *sat, u8 cpu_id)
875 {
876 	u32 err = 0;
877 
878 	if (adler_sum->a1 != src_pattern->adler_sum.a1 ||
879 	    adler_sum->b1 != src_pattern->adler_sum.b1 ||
880 	    adler_sum->a2 != src_pattern->adler_sum.a2 ||
881 	    adler_sum->b2 != src_pattern->adler_sum.b2) {
882 		err += block_copy_mis_search(dst_addr, src_addr, src_pattern, sat);
883 
884 		lock_byte_mutex(&print_mutex);
885 		printf("(CPU%d, Pattern: %s, inv: %d, repeat: %d)\n\n",
886 		       cpu_id, src_pattern->pat->name, src_pattern->inv,
887 		       src_pattern->repeat);
888 		unlock_byte_mutex(&print_mutex);
889 	}
890 
891 	return err;
892 }
893 
894 static u32 block_copy(void *dst_addr, void *src_addr,
895 		      struct pattern *src_pattern,
896 		      struct stressapptest_params *sat, u8 cpu_id)
897 {
898 	u64 *dst_mem;
899 	u64 *src_mem;
900 	u64 data;
901 	int i = 0;
902 #if defined(WARM_CPU)
903 	double a, b, c, d;
904 #endif
905 
906 	struct adler_sum adler_sum = {
907 		1, 0, 1, 0
908 	};
909 
910 	dst_mem = (u64 *)dst_addr;
911 	src_mem = (u64 *)src_addr;
912 
913 #if defined(WARM_CPU)
914 	a = 2.0 * src_mem[0];
915 	b = 5.0 * src_mem[0];
916 	c = 7.0 * src_mem[0];
917 	d = 9.0 * src_mem[0];
918 #endif
919 
920 	while (i < sat->block_size_byte / sizeof(u64)) {
921 		data = src_mem[i];
922 		adler_sum.a1 += data & 0xffffffff;
923 		adler_sum.b1 += adler_sum.a1;
924 		adler_sum.a1 += data >> 32;
925 		adler_sum.b1 += adler_sum.a1;
926 		dst_mem[i] = data;
927 		i++;
928 
929 #if defined(WARM_CPU)
930 		a = a * b;
931 		b = b + c;
932 #endif
933 
934 		data = src_mem[i];
935 		adler_sum.a2 += data & 0xffffffff;
936 		adler_sum.b2 += adler_sum.a2;
937 		adler_sum.a2 += data >> 32;
938 		adler_sum.b2 += adler_sum.a2;
939 		dst_mem[i] = data;
940 		i++;
941 
942 #if defined(WARM_CPU)
943 		c = c * d;
944 		d = d + d;
945 #endif
946 	}
947 
948 	flush_dcache_all();
949 
950 #if defined(WARM_CPU)
951 	d = a + b + c + d;
952 	if (d == 1.0)
953 		/* Reference the result so that it can't be discarded by the compiler. */
954 		printf("This will probably never happen.\n");
955 #endif
956 
957 	return block_copy_check(dst_addr, src_addr, &adler_sum, src_pattern, sat, cpu_id);
958 }
959 
960 static u32 page_copy(struct stressapptest_params *sat, u8 cpu_id)
961 {
962 	u32 dst;
963 	u32 src;
964 	void *dst_block_addr;
965 	void *src_block_addr;
966 	u32 err = 0;
967 
968 	dst = page_rand_pick(page_list, 0, sat, cpu_id);	/* pick a empty page */
969 	dst_block_addr = page_list[dst].base_addr;
970 	src = page_rand_pick(page_list, 1, sat, cpu_id);	/* pick a valid page */
971 	src_block_addr = page_list[src].base_addr;
972 	flush_dcache_all();
973 
974 	for (int i = 0; i < sat->block_num; i++) {
975 		err += block_copy(dst_block_addr, src_block_addr,
976 				  page_list[src].pattern, sat, cpu_id);
977 		dst_block_addr += sat->block_size_byte;
978 		src_block_addr += sat->block_size_byte;
979 	}
980 
981 	page_list[dst].pattern = page_list[src].pattern;
982 	page_list[dst].valid = 1;
983 	page_list[src].valid = 0;
984 	flush_dcache_all();
985 
986 	return err;
987 }
988 
989 void secondary_main(void)
990 {
991 #if (CPU_NUM_MAX > 1)
992 	u8 cpu_id;
993 	ulong test = 0;
994 
995 #ifndef CONFIG_ARM64
996 	asm volatile("mov r9, %0" : : "r" (__gd));	/* set r9 to gd addr */
997 #else
998 	asm volatile("mov x18, %0" : : "r" (__gd));	/* set x18 to gd addr */
999 #endif
1000 	dcache_enable();
1001 	icache_enable();
1002 
1003 	udelay(100);
1004 
1005 	flush_dcache_all();
1006 
1007 	cpu_id = sat.cpu_num;
1008 	cpu_init_finish[cpu_id] = 1;
1009 	printf("CPU%d start OK.\n", cpu_id);
1010 
1011 	while (pattern_page_init_finish == 0) {
1012 		udelay(100);
1013 		flush_dcache_all();
1014 	}
1015 
1016 	while (1) {
1017 		udelay(100);
1018 		flush_dcache_all();
1019 		while (test < test_count) {
1020 			cpu_test_finish[cpu_id] = 0;
1021 			flush_dcache_all();
1022 			while (run_time_us() < test_time_us) {
1023 				if (rand() % 2 == 0)
1024 					cpu_copy_err[cpu_id] += page_copy(&sat, cpu_id);
1025 				else
1026 					cpu_inv_err[cpu_id] += page_inv(&sat, cpu_id);
1027 			}
1028 			test++;
1029 			cpu_test_finish[cpu_id] = 1;
1030 			flush_dcache_all();
1031 		}
1032 	}
1033 #else
1034 	return;
1035 #endif
1036 }
1037 
1038 static int doing_stressapptest(void)
1039 {
1040 	int i;
1041 	u32 pre_10s;
1042 	u32 now_10s;
1043 
1044 	struct pattern pattern_list[PATTERN_LIST_SIZE];
1045 	void *page_info;
1046 
1047 	u32 all_copy_err = 0;
1048 	u32 all_inv_err = 0;
1049 	u32 cpu_no_response_err = 0;
1050 
1051 	int ret = CMD_RET_SUCCESS;
1052 
1053 	for (i = 0; i < CPU_NUM_MAX; i++) {
1054 		cpu_copy_err[i] = 0;
1055 		cpu_inv_err[i] = 0;
1056 		cpu_init_finish[i] = 0;
1057 		cpu_test_finish[i] = 0;
1058 	}
1059 	pattern_page_init_finish = 0;
1060 	print_mutex = 0;
1061 	asm volatile("clrex");
1062 
1063 #if (CPU_NUM_MAX > 1)
1064 	if (test_count == 0) {
1065 		__gd = (ulong)gd;
1066 		asm volatile("mov %0, sp" : "=r" (__sp));
1067 		printf("CPU0 sp is at 0x%lx now.\n", __sp);
1068 		__sp &= ~(ulong)0xffff;
1069 		for (sat.cpu_num = 1; sat.cpu_num < CPU_NUM_MAX; sat.cpu_num++) {
1070 			__sp -= 0x10000;
1071 			flush_dcache_all();
1072 			if (psci_cpu_on(sat.cpu_num, (ulong)secondary_init) == 0) {
1073 				mdelay(10);
1074 				printf("Calling CPU%d, sp = 0x%lx\n", sat.cpu_num, __sp);
1075 			} else {
1076 				break;
1077 			}
1078 			while (cpu_init_finish[sat.cpu_num] == 0) {
1079 				udelay(1000);
1080 				flush_dcache_all();
1081 			}
1082 		}
1083 	}
1084 #else
1085 	sat.cpu_num = 1;
1086 #endif
1087 
1088 	sat.page_num = (sat.total_test_size_mb << 20) / sat.page_size_byte;
1089 	sat.block_num = sat.page_size_byte / sat.block_size_byte;
1090 
1091 	udelay(100);
1092 
1093 	page_info = malloc(sizeof(struct page) * sat.page_num);
1094 	if (page_info == 0) {
1095 		printf("ERROR: StressAppTest fail to malloc.\n");
1096 		printf("Please try increasing CONFIG_SYS_MALLOC_LEN in include/configs/rxxxxx_common.h.\n");
1097 		ret = CMD_RET_FAILURE;
1098 		goto out;
1099 	}
1100 	page_list = (struct page *)page_info;
1101 
1102 	if (get_page_addr(page_list, &sat) < 0) {
1103 		ret = CMD_RET_FAILURE;
1104 		goto out;
1105 	}
1106 
1107 	pattern_list_init(pattern_list, &sat);
1108 	page_init(pattern_list, &sat);
1109 
1110 #if (CPU_NUM_MAX > 1)
1111 	if (sat.cpu_num > 1) {
1112 		pattern_page_init_finish = 1;
1113 		test_count++;
1114 		flush_dcache_all();
1115 	}
1116 #endif
1117 
1118 	pre_10s = (u32)(run_time_us() / 1000000 / 10);
1119 	lock_byte_mutex(&print_mutex);
1120 	print_time_stamp();
1121 	printf("Start StressAppTest in U-Boot:\n");
1122 	unlock_byte_mutex(&print_mutex);
1123 
1124 	while (run_time_us() < test_time_us) {
1125 		if (rand() % 2 == 0)
1126 			cpu_copy_err[0] += page_copy(&sat, 0);
1127 		else
1128 			cpu_inv_err[0] += page_inv(&sat, 0);
1129 
1130 		/* Print every 10 seconds */
1131 		now_10s = (u32)(run_time_us() / 1000000 / 10);
1132 		if (now_10s > pre_10s) {
1133 			pre_10s = now_10s;
1134 			lock_byte_mutex(&print_mutex);
1135 			print_time_stamp();
1136 			printf("Seconds remaining: %d\n", (u32)(test_time_us / 1000000 - now_10s * 10));
1137 			unlock_byte_mutex(&print_mutex);
1138 		}
1139 	}
1140 
1141 #if (CPU_NUM_MAX > 1)
1142 	for (i = 1; i < sat.cpu_num; i++) {
1143 		while (cpu_test_finish[i] == 0) {
1144 			if ((u32)(run_time_us() / 1000000 / 10) > pre_10s + 6) {
1145 				/* wait for secondary CPU in 60s */
1146 				lock_byte_mutex(&print_mutex);
1147 				print_time_stamp();
1148 				printf("ERROR: Cannot wait for CPU%d to finish!\n", i);
1149 				unlock_byte_mutex(&print_mutex);
1150 				cpu_no_response_err++;
1151 				break;
1152 			}
1153 			mdelay(1);
1154 			flush_dcache_all();
1155 		}
1156 	}
1157 #endif
1158 
1159 	for (i = 0; i < sat.cpu_num; i++) {
1160 		all_copy_err += cpu_copy_err[i];
1161 		all_inv_err += cpu_inv_err[i];
1162 	}
1163 	print_time_stamp();
1164 	printf("StressAppTest Result: ");
1165 	if (all_copy_err == 0 && all_inv_err == 0 && cpu_no_response_err == 0)
1166 		printf("Pass.\n");
1167 	else
1168 		printf("FAIL!\nStressAppTest detects %d copy errors, %d inv errors.\n",
1169 		       all_copy_err, all_inv_err);
1170 
1171 out:
1172 	free(page_info);
1173 
1174 	return ret;
1175 }
1176 
1177 static int do_stressapptest(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1178 {
1179 	ulong test_time_sec = 20;
1180 	ulong page_size_kb = 1024;
1181 
1182 	sat.total_test_size_mb = 32;
1183 	sat.block_size_byte = 4096;
1184 	sat.total_start_addr = 0x0;
1185 
1186 	printf("StressAppTest in U-Boot, " __version__ "\n");
1187 
1188 	if (argc > 1) {
1189 		if (strict_strtoul(argv[1], 0, &test_time_sec) < 0)
1190 			return CMD_RET_USAGE;
1191 		if (test_time_sec < 1)
1192 			test_time_sec = 20;
1193 	}
1194 	if (argc > 2) {
1195 		if (strict_strtoul(argv[2], 0, &sat.total_test_size_mb) < 0)
1196 			return CMD_RET_USAGE;
1197 		if (sat.total_test_size_mb < 1)
1198 			sat.total_test_size_mb = 32;
1199 	}
1200 	if (argc > 3) {
1201 		if (strict_strtoul(argv[3], 0, &sat.total_start_addr) < 0)
1202 			return CMD_RET_USAGE;
1203 		if (sat.total_start_addr < 0x1)
1204 			sat.total_start_addr = 0x0;
1205 	}
1206 	if (argc > 4) {
1207 		if (strict_strtoul(argv[4], 0, &page_size_kb) < 0)
1208 			return CMD_RET_USAGE;
1209 		if (page_size_kb < 1)
1210 			page_size_kb = 1024;
1211 	}
1212 
1213 	sat.page_size_byte = page_size_kb << 10;
1214 
1215 	start_time_us = get_time_us();
1216 	test_time_us = (u64)test_time_sec * 1000000;
1217 
1218 	/* Change rand seed. If not do this, rand() would be same after boot.*/
1219 	srand((unsigned int)(start_time_us & 0xffffffff));
1220 
1221 	return doing_stressapptest();
1222 }
1223 
1224 U_BOOT_CMD(stressapptest,	5,	1,	do_stressapptest,
1225 	   "StressAppTest for Rockchip\n",
1226 	   "\narg1: test time in second, default value is 20s.\n"
1227 	   "arg2: test size in MB, default value is 32MB.\n"
1228 	   "arg3: start addr for test.\n"
1229 	   "arg4: test page size in kB, default value is 1024kB(1MB).\n"
1230 	   "example:\n"
1231 	   "	stressapptest: test for 20s, test size is 32MB, each page size is 1MB (32 pages).\n"
1232 	   "	stressapptest 43200 64: test for 12h, test size is 64MB, each page size is 1MB (64 pages).\n"
1233 	   "	stressapptest 86400 1024 0x80000000: test for 24h, test size is 1024MB, start addr for test is 0x80000000, each page size is 1MB (1024 pages).\n"
1234 	   "	stressapptest 43200 16 0x40000000 512: test for 12h, test size is 16MB, start addr for test is 0x40000000, each page size is 512kB (32 pages).\n"
1235 );
1236