xref: /rk3399_rockchip-uboot/cmd/ddr_tool/stressapptest/stressapptest.c (revision 50e09059b02d8b730826fdbb2f88c711cc3cec85)
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;
629 	pick = pick / sat->cpu_num * sat->cpu_num + cpu_id;
630 	if (pick >= sat->page_num)
631 		pick = cpu_id;
632 
633 	while (page_list[pick].valid != valid) {
634 		pick += sat->cpu_num;
635 		if (pick >= sat->page_num)
636 			pick = cpu_id;
637 	}
638 
639 	return pick;
640 }
641 
642 static u32 block_inv_mis_search(void *dst_addr, struct pattern *src_pattern,
643 				struct stressapptest_params *sat)
644 {
645 	u32 *dst_mem;
646 	u32 dst_data;
647 	u32 expc_data;
648 	u32 mis_bit;
649 	u32 err = 0;
650 
651 	dst_mem = (u32 *)dst_addr;
652 
653 	for (int i = 0; i < sat->block_size_byte / sizeof(u32); i++) {
654 		dst_data = dst_mem[i];
655 		expc_data = pattern_get(src_pattern, i);
656 
657 		if (dst_data != expc_data) {
658 			lock_byte_mutex(&print_mutex);
659 
660 			print_time_stamp();
661 			printf("INV ERROR at 0x%010lx:\n", (ulong)&dst_mem[i]);
662 			printf("	data = 0x%08x\n", dst_data);
663 			printf("	expc = 0x%08x\n", expc_data);
664 
665 			mis_bit = dst_data ^ expc_data;
666 			printf("	mismatch at bit");
667 			for (int j = 31; j >= 0; j--) {
668 				if (((mis_bit >> j) & 1) == 1)
669 					printf(" %d", j);
670 			}
671 			printf("\n");
672 
673 			unlock_byte_mutex(&print_mutex);
674 			dst_mem[i] = expc_data;
675 			err++;
676 		}
677 	}
678 	flush_dcache_all();
679 
680 	if (err == 0) {
681 		lock_byte_mutex(&print_mutex);
682 		printf("INV ERROR detected but cannot find mismatch data (maybe read error).\n");
683 		unlock_byte_mutex(&print_mutex);
684 	}
685 
686 	return err;
687 }
688 
689 static u32 block_inv_check(void *dst_addr, struct pattern *src_pattern,
690 			   struct stressapptest_params *sat, u8 cpu_id)
691 {
692 	u32 *dst_mem;
693 	u32 err = 0;
694 	int i = 0;
695 #if defined(WARM_CPU)
696 	double a, b, c, d;
697 #endif
698 
699 	struct adler_sum adler_sum = {
700 		1, 0, 1, 0
701 	};
702 
703 	dst_mem = (u32 *)dst_addr;
704 
705 #if defined(WARM_CPU)
706 	a = 2.0 * dst_mem[0];
707 	b = 5.0 * dst_mem[0];
708 	c = 7.0 * dst_mem[0];
709 	d = 9.0 * dst_mem[0];
710 #endif
711 
712 	while (i < sat->block_size_byte / sizeof(u32)) {
713 		adler_sum.a1 += dst_mem[i++];
714 		adler_sum.b1 += adler_sum.a1;
715 		adler_sum.a1 += dst_mem[i++];
716 		adler_sum.b1 += adler_sum.a1;
717 
718 #if defined(WARM_CPU)
719 		a = a * b;
720 		b = b + c;
721 #endif
722 
723 		adler_sum.a2 += dst_mem[i++];
724 		adler_sum.b2 += adler_sum.a2;
725 		adler_sum.a2 += dst_mem[i++];
726 		adler_sum.b2 += adler_sum.a2;
727 #if defined(WARM_CPU)
728 		c = c * d;
729 		d = d + d;
730 #endif
731 	}
732 
733 #if defined(WARM_CPU)
734 	d = a + b + c + d;
735 	if (d == 1.0)
736 		/* Reference the result so that it can't be discarded by the compiler. */
737 		printf("This will probably never happen.\n");
738 #endif
739 
740 	if (adler_sum.a1 != src_pattern->adler_sum.a1 ||
741 	    adler_sum.b1 != src_pattern->adler_sum.b1 ||
742 	    adler_sum.a2 != src_pattern->adler_sum.a2 ||
743 	    adler_sum.b2 != src_pattern->adler_sum.b2) {
744 		err = block_inv_mis_search(dst_addr, src_pattern, sat);
745 
746 		lock_byte_mutex(&print_mutex);
747 		printf("(CPU%d, Pattern: %s, inv: %d, repeat: %d)\n\n",
748 		       cpu_id, src_pattern->pat->name, src_pattern->inv,
749 		       src_pattern->repeat);
750 		unlock_byte_mutex(&print_mutex);
751 	}
752 
753 	return err;
754 }
755 
756 static void page_inv_up(void *src_addr, struct stressapptest_params *sat)
757 {
758 	void *dst_addr = src_addr;
759 	uint data;
760 	uint *dst_mem;
761 
762 	for (int i = 0; i < sat->block_num; i++) {
763 		dst_mem = (uint *)dst_addr;
764 		for (int j = 0; j < sat->block_size_byte / sizeof(uint); j++) {
765 			data = dst_mem[j];
766 			dst_mem[j] = ~data;
767 		}
768 		dst_addr += sat->block_size_byte;
769 		flush_dcache_all();
770 	}
771 }
772 
773 static void page_inv_down(void *src_addr, struct stressapptest_params *sat)
774 {
775 	void *dst_addr = src_addr;
776 	uint data;
777 	uint *dst_mem;
778 
779 	dst_addr += sat->block_size_byte * (sat->block_num - 1);
780 
781 	for (int i = sat->block_num - 1; i >= 0; i--) {
782 		dst_mem = (uint *)dst_addr;
783 		for (int j = sat->block_size_byte / sizeof(uint) - 1; j >= 0; j--) {
784 			data = dst_mem[j];
785 			dst_mem[j] = ~data;
786 		}
787 		dst_addr -= sat->block_size_byte;
788 		flush_dcache_all();
789 	}
790 }
791 
792 static u32 page_inv(struct stressapptest_params *sat, u8 cpu_id)
793 {
794 	u32 src;
795 	void *dst_block_addr;
796 	u32 err = 0;
797 
798 	src = page_rand_pick(page_list, 1, sat, cpu_id);	/* pick a valid page */
799 	dst_block_addr = page_list[src].base_addr;
800 
801 	for (int i = 0; i < 4; i++) {
802 		if (rand() % 2 == 0)
803 			page_inv_up(page_list[src].base_addr, sat);
804 		else
805 			page_inv_down(page_list[src].base_addr, sat);
806 	}
807 
808 	for (int i = 0; i < sat->block_num; i++) {
809 		err += block_inv_check(dst_block_addr, page_list[src].pattern, sat, cpu_id);
810 		dst_block_addr += sat->block_size_byte;
811 	}
812 
813 	flush_dcache_all();
814 
815 	return err;
816 }
817 
818 static u32 block_copy_mis_search(void *dst_addr, void *src_addr,
819 				 struct pattern *src_pattern,
820 				 struct stressapptest_params *sat)
821 {
822 	u32 *dst_mem;
823 	u32 *src_mem;
824 	u32 dst_data;
825 	u32 src_data;
826 	u32 expc_data;
827 	u32 mis_bit;
828 	u32 err = 0;
829 
830 	dst_mem = (u32 *)dst_addr;
831 	src_mem = (u32 *)src_addr;
832 
833 	for (int i = 0; i < sat->block_size_byte / sizeof(u32); i++) {
834 		dst_data = dst_mem[i];
835 		src_data = src_mem[i];
836 		expc_data = pattern_get(src_pattern, i);
837 
838 		if (dst_data != expc_data) {
839 			lock_byte_mutex(&print_mutex);
840 
841 			print_time_stamp();
842 			printf("COPY ERROR (");
843 			if (src_data == expc_data)
844 				printf("read");
845 			else if (src_data != expc_data)
846 				printf("write");
847 			printf(" error) at 0x%010lx:\n", (ulong)&src_mem[i]);
848 			printf("	data = 0x%08x\n", dst_data);
849 			printf("	expc = 0x%08x\n", expc_data);
850 
851 			mis_bit = dst_data ^ expc_data;
852 			printf("	mismatch at bit");
853 			for (int j = 31; j >= 0; j--) {
854 				if (((mis_bit >> j) & 1) == 1)
855 					printf(" %d", j);
856 			}
857 			printf("\n");
858 
859 			unlock_byte_mutex(&print_mutex);
860 			err++;
861 			dst_mem[i] = expc_data;
862 		}
863 	}
864 	flush_dcache_all();
865 
866 	if (err == 0) {
867 		lock_byte_mutex(&print_mutex);
868 		printf("COPY ERROR detected but cannot find mismatch data (maybe read error).\n");
869 		unlock_byte_mutex(&print_mutex);
870 	}
871 
872 	return err;
873 }
874 
875 static u32 block_copy_check(void *dst_addr, void *src_addr,
876 			    struct adler_sum *adler_sum,
877 			    struct pattern *src_pattern,
878 			    struct stressapptest_params *sat, u8 cpu_id)
879 {
880 	u32 err = 0;
881 
882 	if (adler_sum->a1 != src_pattern->adler_sum.a1 ||
883 	    adler_sum->b1 != src_pattern->adler_sum.b1 ||
884 	    adler_sum->a2 != src_pattern->adler_sum.a2 ||
885 	    adler_sum->b2 != src_pattern->adler_sum.b2) {
886 		err += block_copy_mis_search(dst_addr, src_addr, src_pattern, sat);
887 
888 		lock_byte_mutex(&print_mutex);
889 		printf("(CPU%d, Pattern: %s, inv: %d, repeat: %d)\n\n",
890 		       cpu_id, src_pattern->pat->name, src_pattern->inv,
891 		       src_pattern->repeat);
892 		unlock_byte_mutex(&print_mutex);
893 	}
894 
895 	return err;
896 }
897 
898 static u32 block_copy(void *dst_addr, void *src_addr,
899 		      struct pattern *src_pattern,
900 		      struct stressapptest_params *sat, u8 cpu_id)
901 {
902 	u64 *dst_mem;
903 	u64 *src_mem;
904 	u64 data;
905 	int i = 0;
906 #if defined(WARM_CPU)
907 	double a, b, c, d;
908 #endif
909 
910 	struct adler_sum adler_sum = {
911 		1, 0, 1, 0
912 	};
913 
914 	dst_mem = (u64 *)dst_addr;
915 	src_mem = (u64 *)src_addr;
916 
917 #if defined(WARM_CPU)
918 	a = 2.0 * src_mem[0];
919 	b = 5.0 * src_mem[0];
920 	c = 7.0 * src_mem[0];
921 	d = 9.0 * src_mem[0];
922 #endif
923 
924 	while (i < sat->block_size_byte / sizeof(u64)) {
925 		data = src_mem[i];
926 		adler_sum.a1 += data & 0xffffffff;
927 		adler_sum.b1 += adler_sum.a1;
928 		adler_sum.a1 += data >> 32;
929 		adler_sum.b1 += adler_sum.a1;
930 		dst_mem[i] = data;
931 		i++;
932 
933 #if defined(WARM_CPU)
934 		a = a * b;
935 		b = b + c;
936 #endif
937 
938 		data = src_mem[i];
939 		adler_sum.a2 += data & 0xffffffff;
940 		adler_sum.b2 += adler_sum.a2;
941 		adler_sum.a2 += data >> 32;
942 		adler_sum.b2 += adler_sum.a2;
943 		dst_mem[i] = data;
944 		i++;
945 
946 #if defined(WARM_CPU)
947 		c = c * d;
948 		d = d + d;
949 #endif
950 	}
951 
952 	flush_dcache_all();
953 
954 #if defined(WARM_CPU)
955 	d = a + b + c + d;
956 	if (d == 1.0)
957 		/* Reference the result so that it can't be discarded by the compiler. */
958 		printf("This will probably never happen.\n");
959 #endif
960 
961 	return block_copy_check(dst_addr, src_addr, &adler_sum, src_pattern, sat, cpu_id);
962 }
963 
964 static u32 page_copy(struct stressapptest_params *sat, u8 cpu_id)
965 {
966 	u32 dst;
967 	u32 src;
968 	void *dst_block_addr;
969 	void *src_block_addr;
970 	u32 err = 0;
971 
972 	dst = page_rand_pick(page_list, 0, sat, cpu_id);	/* pick a empty page */
973 	dst_block_addr = page_list[dst].base_addr;
974 	src = page_rand_pick(page_list, 1, sat, cpu_id);	/* pick a valid page */
975 	src_block_addr = page_list[src].base_addr;
976 	flush_dcache_all();
977 
978 	for (int i = 0; i < sat->block_num; i++) {
979 		err += block_copy(dst_block_addr, src_block_addr,
980 				  page_list[src].pattern, sat, cpu_id);
981 		dst_block_addr += sat->block_size_byte;
982 		src_block_addr += sat->block_size_byte;
983 	}
984 
985 	page_list[dst].pattern = page_list[src].pattern;
986 	page_list[dst].valid = 1;
987 	page_list[src].valid = 0;
988 	flush_dcache_all();
989 
990 	return err;
991 }
992 
993 void secondary_main(void)
994 {
995 #if (CPU_NUM_MAX > 1)
996 	u8 cpu_id;
997 	ulong test = 0;
998 
999 #ifndef CONFIG_ARM64
1000 	asm volatile("mov r9, %0" : : "r" (__gd));	/* set r9 to gd addr */
1001 #else
1002 	asm volatile("mov x18, %0" : : "r" (__gd));	/* set x18 to gd addr */
1003 #endif
1004 	dcache_enable();
1005 	icache_enable();
1006 
1007 	udelay(100);
1008 
1009 	flush_dcache_all();
1010 
1011 	cpu_id = sat.cpu_num;
1012 	cpu_init_finish[cpu_id] = 1;
1013 	printf("CPU%d start OK.\n", cpu_id);
1014 
1015 	while (pattern_page_init_finish == 0) {
1016 		udelay(100);
1017 		flush_dcache_all();
1018 	}
1019 
1020 	while (1) {
1021 		udelay(100);
1022 		flush_dcache_all();
1023 		while (test < test_count) {
1024 			cpu_test_finish[cpu_id] = 0;
1025 			flush_dcache_all();
1026 			while (run_time_us() < test_time_us) {
1027 				if (rand() % 2 == 0)
1028 					cpu_copy_err[cpu_id] += page_copy(&sat, cpu_id);
1029 				else
1030 					cpu_inv_err[cpu_id] += page_inv(&sat, cpu_id);
1031 			}
1032 			test++;
1033 			cpu_test_finish[cpu_id] = 1;
1034 			flush_dcache_all();
1035 		}
1036 	}
1037 #else
1038 	return;
1039 #endif
1040 }
1041 
1042 static int doing_stressapptest(void)
1043 {
1044 	int i;
1045 	u32 pre_10s;
1046 	u32 now_10s;
1047 
1048 	struct pattern pattern_list[PATTERN_LIST_SIZE];
1049 	void *page_info;
1050 
1051 	u32 all_copy_err = 0;
1052 	u32 all_inv_err = 0;
1053 	u32 cpu_no_response_err = 0;
1054 
1055 	int ret = CMD_RET_SUCCESS;
1056 
1057 	for (i = 0; i < CPU_NUM_MAX; i++) {
1058 		cpu_copy_err[i] = 0;
1059 		cpu_inv_err[i] = 0;
1060 		cpu_init_finish[i] = 0;
1061 		cpu_test_finish[i] = 0;
1062 	}
1063 	pattern_page_init_finish = 0;
1064 	print_mutex = 0;
1065 	asm volatile("clrex");
1066 
1067 #if (CPU_NUM_MAX > 1)
1068 	if (test_count == 0) {
1069 		__gd = (ulong)gd;
1070 		asm volatile("mov %0, sp" : "=r" (__sp));
1071 		printf("CPU0 sp is at 0x%lx now.\n", __sp);
1072 		__sp &= ~(ulong)0xffff;
1073 		for (sat.cpu_num = 1; sat.cpu_num < CPU_NUM_MAX; sat.cpu_num++) {
1074 			__sp -= 0x10000;
1075 			flush_dcache_all();
1076 			if (psci_cpu_on(sat.cpu_num, (ulong)secondary_init) == 0) {
1077 				mdelay(10);
1078 				printf("Calling CPU%d, sp = 0x%lx\n", sat.cpu_num, __sp);
1079 			} else {
1080 				break;
1081 			}
1082 			while (cpu_init_finish[sat.cpu_num] == 0) {
1083 				udelay(1000);
1084 				flush_dcache_all();
1085 			}
1086 		}
1087 	}
1088 #else
1089 	sat.cpu_num = 1;
1090 #endif
1091 
1092 	sat.page_num = (sat.total_test_size_mb << 20) / sat.page_size_byte;
1093 	sat.block_num = sat.page_size_byte / sat.block_size_byte;
1094 
1095 	udelay(100);
1096 
1097 	page_info = malloc(sizeof(struct page) * sat.page_num);
1098 	if (page_info == 0) {
1099 		printf("ERROR: StressAppTest fail to malloc.\n");
1100 		printf("Please try increasing CONFIG_SYS_MALLOC_LEN in include/configs/rxxxxx_common.h.\n");
1101 		ret = CMD_RET_FAILURE;
1102 		goto out;
1103 	}
1104 	page_list = (struct page *)page_info;
1105 
1106 	if (get_page_addr(page_list, &sat) < 0) {
1107 		ret = CMD_RET_FAILURE;
1108 		goto out;
1109 	}
1110 
1111 	pattern_list_init(pattern_list, &sat);
1112 	page_init(pattern_list, &sat);
1113 
1114 #if (CPU_NUM_MAX > 1)
1115 	if (sat.cpu_num > 1) {
1116 		pattern_page_init_finish = 1;
1117 		test_count++;
1118 		flush_dcache_all();
1119 	}
1120 #endif
1121 
1122 	pre_10s = (u32)(run_time_us() / 1000000 / 10);
1123 	lock_byte_mutex(&print_mutex);
1124 	print_time_stamp();
1125 	printf("Start StressAppTest in U-Boot:\n");
1126 	unlock_byte_mutex(&print_mutex);
1127 
1128 	while (run_time_us() < test_time_us) {
1129 		if (rand() % 2 == 0)
1130 			cpu_copy_err[0] += page_copy(&sat, 0);
1131 		else
1132 			cpu_inv_err[0] += page_inv(&sat, 0);
1133 
1134 		/* Print every 10 seconds */
1135 		now_10s = (u32)(run_time_us() / 1000000 / 10);
1136 		if (now_10s > pre_10s) {
1137 			pre_10s = now_10s;
1138 			lock_byte_mutex(&print_mutex);
1139 			print_time_stamp();
1140 			printf("Seconds remaining: %d\n", (u32)(test_time_us / 1000000 - now_10s * 10));
1141 			unlock_byte_mutex(&print_mutex);
1142 		}
1143 	}
1144 
1145 #if (CPU_NUM_MAX > 1)
1146 	for (i = 1; i < sat.cpu_num; i++) {
1147 		while (cpu_test_finish[i] == 0) {
1148 			if ((u32)(run_time_us() / 1000000 / 10) > pre_10s + 6) {
1149 				/* wait for secondary CPU in 60s */
1150 				lock_byte_mutex(&print_mutex);
1151 				print_time_stamp();
1152 				printf("ERROR: Cannot wait for CPU%d to finish!\n", i);
1153 				unlock_byte_mutex(&print_mutex);
1154 				cpu_no_response_err++;
1155 				break;
1156 			}
1157 			mdelay(1);
1158 			flush_dcache_all();
1159 		}
1160 	}
1161 #endif
1162 
1163 	for (i = 0; i < sat.cpu_num; i++) {
1164 		all_copy_err += cpu_copy_err[i];
1165 		all_inv_err += cpu_inv_err[i];
1166 	}
1167 	print_time_stamp();
1168 	printf("StressAppTest Result: ");
1169 	if (all_copy_err == 0 && all_inv_err == 0 && cpu_no_response_err == 0)
1170 		printf("Pass.\n");
1171 	else
1172 		printf("FAIL!\nStressAppTest detects %d copy errors, %d inv errors.\n",
1173 		       all_copy_err, all_inv_err);
1174 
1175 out:
1176 	free(page_info);
1177 
1178 	return ret;
1179 }
1180 
1181 static int do_stressapptest(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1182 {
1183 	ulong test_time_sec = 20;
1184 	ulong page_size_kb = 1024;
1185 
1186 	sat.total_test_size_mb = 32;
1187 	sat.block_size_byte = 4096;
1188 	sat.total_start_addr = 0x0;
1189 
1190 	printf("StressAppTest in U-Boot, " __version__ "\n");
1191 
1192 	if (argc > 1) {
1193 		if (strict_strtoul(argv[1], 0, &test_time_sec) < 0)
1194 			return CMD_RET_USAGE;
1195 		if (test_time_sec < 1)
1196 			test_time_sec = 20;
1197 	}
1198 	if (argc > 2) {
1199 		if (strict_strtoul(argv[2], 0, &sat.total_test_size_mb) < 0)
1200 			return CMD_RET_USAGE;
1201 		if (sat.total_test_size_mb < 1)
1202 			sat.total_test_size_mb = 32;
1203 	}
1204 	if (argc > 3) {
1205 		if (strict_strtoul(argv[3], 0, &sat.total_start_addr) < 0)
1206 			return CMD_RET_USAGE;
1207 		if (sat.total_start_addr < 0x1)
1208 			sat.total_start_addr = 0x0;
1209 	}
1210 	if (argc > 4) {
1211 		if (strict_strtoul(argv[4], 0, &page_size_kb) < 0)
1212 			return CMD_RET_USAGE;
1213 		if (page_size_kb < 1)
1214 			page_size_kb = 1024;
1215 	}
1216 
1217 	sat.page_size_byte = page_size_kb << 10;
1218 
1219 	start_time_us = get_time_us();
1220 	test_time_us = (u64)test_time_sec * 1000000;
1221 
1222 	/* Change rand seed. If not do this, rand() would be same after boot.*/
1223 	srand((unsigned int)(start_time_us & 0xffffffff));
1224 
1225 	return doing_stressapptest();
1226 }
1227 
1228 U_BOOT_CMD(stressapptest,	5,	1,	do_stressapptest,
1229 	   "StressAppTest for Rockchip\n",
1230 	   "\narg1: test time in second, default value is 20s.\n"
1231 	   "arg2: test size in MB, default value is 32MB.\n"
1232 	   "arg3: start addr for test.\n"
1233 	   "arg4: test page size in kB, default value is 1024kB(1MB).\n"
1234 	   "example:\n"
1235 	   "	stressapptest: test for 20s, test size is 32MB, each page size is 1MB (32 pages).\n"
1236 	   "	stressapptest 43200 64: test for 12h, test size is 64MB, each page size is 1MB (64 pages).\n"
1237 	   "	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"
1238 	   "	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"
1239 );
1240