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