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