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