xref: /rk3399_rockchip-uboot/cmd/ddr_tool/stressapptest/stressapptest.c (revision 13ceb2afdcb6f5114908e39f0d2453728eb24e0f)
19bf9a700SWesley Yao // Copyright 2006 Google Inc. All Rights Reserved.
29bf9a700SWesley Yao /* Licensed under the Apache License, Version 2.0 (the "License");
39bf9a700SWesley Yao  * you may not use this file except in compliance with the License.
49bf9a700SWesley Yao  * You may obtain a copy of the License at
59bf9a700SWesley Yao  *
69bf9a700SWesley Yao  *	http://www.apache.org/licenses/LICENSE-2.0
79bf9a700SWesley Yao  *
89bf9a700SWesley Yao  * Unless required by applicable law or agreed to in writing, software
99bf9a700SWesley Yao  * distributed under the License is distributed on an "AS IS" BASIS,
109bf9a700SWesley Yao  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119bf9a700SWesley Yao  * See the License for the specific language governing permissions and
129bf9a700SWesley Yao  * limitations under the License.
139bf9a700SWesley Yao  */
149bf9a700SWesley Yao 
159bf9a700SWesley Yao /* This is stressapptest for Rockchip platform in U-Boot, the design idea and
169bf9a700SWesley Yao  * the patterns are from code.google.com/p/stressapptest.
179bf9a700SWesley Yao  */
189bf9a700SWesley Yao 
199bf9a700SWesley Yao #include <common.h>
209bf9a700SWesley Yao #include <amp.h>
219bf9a700SWesley Yao #include <div64.h>
229bf9a700SWesley Yao #include <malloc.h>
239bf9a700SWesley Yao #include <asm/arch/rockchip_smccc.h>
249bf9a700SWesley Yao #include "stressapptest.h"
259bf9a700SWesley Yao #include "../ddr_tool_common.h"
269bf9a700SWesley Yao 
2732640b0aSWesley Yao #define __version__ "v1.3.0 20230713"
289bf9a700SWesley Yao 
299bf9a700SWesley Yao #if defined(CONFIG_ARM64)
309bf9a700SWesley Yao /* Float operation in TOOLCHAIN_ARM32 will cause the compile error */
319bf9a700SWesley Yao #define WARM_CPU
329bf9a700SWesley Yao #endif
339bf9a700SWesley Yao 
349bf9a700SWesley Yao #define PAT_NUM			26
359bf9a700SWesley Yao #define PATTERN_LIST_SIZE	(PAT_NUM * 2 * 4)
369bf9a700SWesley Yao 
379bf9a700SWesley Yao #define CPU_NUM_MAX		16
389bf9a700SWesley Yao 
399bf9a700SWesley Yao static u32 walking_1_data[] = {
409bf9a700SWesley Yao 	0x00000001, 0x00000002, 0x00000004, 0x00000008,
419bf9a700SWesley Yao 	0x00000010, 0x00000020, 0x00000040, 0x00000080,
429bf9a700SWesley Yao 	0x00000100, 0x00000200, 0x00000400, 0x00000800,
439bf9a700SWesley Yao 	0x00001000, 0x00002000, 0x00004000, 0x00008000,
449bf9a700SWesley Yao 	0x00010000, 0x00020000, 0x00040000, 0x00080000,
459bf9a700SWesley Yao 	0x00100000, 0x00200000, 0x00400000, 0x00800000,
469bf9a700SWesley Yao 	0x01000000, 0x02000000, 0x04000000, 0x08000000,
479bf9a700SWesley Yao 	0x10000000, 0x20000000, 0x40000000, 0x80000000,
489bf9a700SWesley Yao 	0x40000000, 0x20000000, 0x10000000, 0x08000000,
499bf9a700SWesley Yao 	0x04000000, 0x02000000, 0x01000000, 0x00800000,
509bf9a700SWesley Yao 	0x00400000, 0x00200000, 0x00100000, 0x00080000,
519bf9a700SWesley Yao 	0x00040000, 0x00020000, 0x00010000, 0x00008000,
529bf9a700SWesley Yao 	0x00004000, 0x00002000, 0x00001000, 0x00000800,
539bf9a700SWesley Yao 	0x00000400, 0x00000200, 0x00000100, 0x00000080,
549bf9a700SWesley Yao 	0x00000040, 0x00000020, 0x00000010, 0x00000008,
559bf9a700SWesley Yao 	0x00000004, 0x00000002, 0x00000001, 0x00000000
569bf9a700SWesley Yao };
579bf9a700SWesley Yao 
589bf9a700SWesley Yao static struct pat walking_1 = {
599bf9a700SWesley Yao 	"walking_1",
609bf9a700SWesley Yao 	walking_1_data,
619bf9a700SWesley Yao 	ARRAY_SIZE(walking_1_data) - 1,	/* mask */
629bf9a700SWesley Yao 	{1, 1, 2, 1}	/* weight */
639bf9a700SWesley Yao };
649bf9a700SWesley Yao 
659bf9a700SWesley Yao static u32 walking_1_x16_data[] =   {
669bf9a700SWesley Yao 	0x00020001, 0x00080004, 0x00200010, 0x00800040,
679bf9a700SWesley Yao 	0x02000100, 0x08000400, 0x20001000, 0x80004000,
689bf9a700SWesley Yao 	0x20004000, 0x08001000, 0x02000400, 0x00800100,
699bf9a700SWesley Yao 	0x00200040, 0x00080010, 0x00020004, 0x00000001
709bf9a700SWesley Yao };
719bf9a700SWesley Yao 
729bf9a700SWesley Yao static struct pat walking_1_x16 = {
739bf9a700SWesley Yao 	"walking_1_x16",
749bf9a700SWesley Yao 	walking_1_x16_data,
759bf9a700SWesley Yao 	ARRAY_SIZE(walking_1_x16_data) - 1,	/* mask */
769bf9a700SWesley Yao 	{2, 0, 0, 0}	/* Weight for choosing 32/64/128/256 bit wide of this pattern */
779bf9a700SWesley Yao 	/* Reuse for walking_0_x16, because of invert */
789bf9a700SWesley Yao };
799bf9a700SWesley Yao 
809bf9a700SWesley Yao static u32 walking_1_x16_repeat_data[] =   {
819bf9a700SWesley Yao 	0x00010001, 0x00020002, 0x00040004, 0x00080008,
829bf9a700SWesley Yao 	0x00100010, 0x00200020, 0x00400040, 0x00800080,
839bf9a700SWesley Yao 	0x01000100, 0x02000200, 0x04000400, 0x08000800,
849bf9a700SWesley Yao 	0x10001000, 0x20002000, 0x40004000, 0x80008000,
859bf9a700SWesley Yao 	0x40004000, 0x20002000, 0x10001000, 0x08000800,
869bf9a700SWesley Yao 	0x04000400, 0x02000200, 0x01000100, 0x00800080,
879bf9a700SWesley Yao 	0x00400040, 0x00200020, 0x00100010, 0x00080008,
889bf9a700SWesley Yao 	0x00040004, 0x00020002, 0x00010001, 0x00000000
899bf9a700SWesley Yao };
909bf9a700SWesley Yao 
919bf9a700SWesley Yao static struct pat walking_1_x16_repeat = {
929bf9a700SWesley Yao 	"walking_1_x16_repeat",
939bf9a700SWesley Yao 	walking_1_x16_repeat_data,
949bf9a700SWesley Yao 	ARRAY_SIZE(walking_1_x16_repeat_data) - 1,	/* mask */
959bf9a700SWesley Yao 	{2, 4, 2, 0}	/* Weight for choosing 32/64/128/256 bit wide of this pattern */
969bf9a700SWesley Yao 	/* Reuse for walking_0_x16_repeat, because of invert */
979bf9a700SWesley Yao };
989bf9a700SWesley Yao 
999bf9a700SWesley Yao static u32 walking_inv_1_data[] = {
1009bf9a700SWesley Yao 	0x00000001, 0xfffffffe, 0x00000002, 0xfffffffd,
1019bf9a700SWesley Yao 	0x00000004, 0xfffffffb, 0x00000008, 0xfffffff7,
1029bf9a700SWesley Yao 	0x00000010, 0xffffffef, 0x00000020, 0xffffffdf,
1039bf9a700SWesley Yao 	0x00000040, 0xffffffbf, 0x00000080, 0xffffff7f,
1049bf9a700SWesley Yao 	0x00000100, 0xfffffeff, 0x00000200, 0xfffffdff,
1059bf9a700SWesley Yao 	0x00000400, 0xfffffbff, 0x00000800, 0xfffff7ff,
1069bf9a700SWesley Yao 	0x00001000, 0xffffefff, 0x00002000, 0xffffdfff,
1079bf9a700SWesley Yao 	0x00004000, 0xffffbfff, 0x00008000, 0xffff7fff,
1089bf9a700SWesley Yao 	0x00010000, 0xfffeffff, 0x00020000, 0xfffdffff,
1099bf9a700SWesley Yao 	0x00040000, 0xfffbffff, 0x00080000, 0xfff7ffff,
1109bf9a700SWesley Yao 	0x00100000, 0xffefffff, 0x00200000, 0xffdfffff,
1119bf9a700SWesley Yao 	0x00400000, 0xffbfffff, 0x00800000, 0xff7fffff,
1129bf9a700SWesley Yao 	0x01000000, 0xfeffffff, 0x02000000, 0xfdffffff,
1139bf9a700SWesley Yao 	0x04000000, 0xfbffffff, 0x08000000, 0xf7ffffff,
1149bf9a700SWesley Yao 	0x10000000, 0xefffffff, 0x20000000, 0xdfffffff,
1159bf9a700SWesley Yao 	0x40000000, 0xbfffffff, 0x80000000, 0x7fffffff,
1169bf9a700SWesley Yao 	0x40000000, 0xbfffffff, 0x20000000, 0xdfffffff,
1179bf9a700SWesley Yao 	0x10000000, 0xefffffff, 0x08000000, 0xf7ffffff,
1189bf9a700SWesley Yao 	0x04000000, 0xfbffffff, 0x02000000, 0xfdffffff,
1199bf9a700SWesley Yao 	0x01000000, 0xfeffffff, 0x00800000, 0xff7fffff,
1209bf9a700SWesley Yao 	0x00400000, 0xffbfffff, 0x00200000, 0xffdfffff,
1219bf9a700SWesley Yao 	0x00100000, 0xffefffff, 0x00080000, 0xfff7ffff,
1229bf9a700SWesley Yao 	0x00040000, 0xfffbffff, 0x00020000, 0xfffdffff,
1239bf9a700SWesley Yao 	0x00010000, 0xfffeffff, 0x00008000, 0xffff7fff,
1249bf9a700SWesley Yao 	0x00004000, 0xffffbfff, 0x00002000, 0xffffdfff,
1259bf9a700SWesley Yao 	0x00001000, 0xffffefff, 0x00000800, 0xfffff7ff,
1269bf9a700SWesley Yao 	0x00000400, 0xfffffbff, 0x00000200, 0xfffffdff,
1279bf9a700SWesley Yao 	0x00000100, 0xfffffeff, 0x00000080, 0xffffff7f,
1289bf9a700SWesley Yao 	0x00000040, 0xffffffbf, 0x00000020, 0xffffffdf,
1299bf9a700SWesley Yao 	0x00000010, 0xffffffef, 0x00000008, 0xfffffff7,
1309bf9a700SWesley Yao 	0x00000004, 0xfffffffb, 0x00000002, 0xfffffffd,
1319bf9a700SWesley Yao 	0x00000001, 0xfffffffe, 0x00000000, 0xffffffff
1329bf9a700SWesley Yao };
1339bf9a700SWesley Yao 
1349bf9a700SWesley Yao static struct pat walking_inv_1 = {
1359bf9a700SWesley Yao 	"walking_inv_1",
1369bf9a700SWesley Yao 	walking_inv_1_data,
1379bf9a700SWesley Yao 	ARRAY_SIZE(walking_inv_1_data) - 1,	/* mask */
1389bf9a700SWesley Yao 	{2, 2, 5, 5}	/* weight */
1399bf9a700SWesley Yao };
1409bf9a700SWesley Yao 
1419bf9a700SWesley Yao static u32 walking_inv_1_x16_data[] = {
1429bf9a700SWesley Yao 	0xfffe0001, 0xfffd0002, 0xfffb0004, 0xfff70008,
1439bf9a700SWesley Yao 	0xffef0010, 0xffdf0020, 0xffbf0040, 0xff7f0080,
1449bf9a700SWesley Yao 	0xfeff0100, 0xfdff0200, 0xfbff0400, 0xf7ff0800,
1459bf9a700SWesley Yao 	0xefff1000, 0xdfff2000, 0xbfff4000, 0x7fff8000,
1469bf9a700SWesley Yao 	0xbfff4000, 0xdfff2000, 0xefff1000, 0xf7ff0800,
1479bf9a700SWesley Yao 	0xfbff0400, 0xfdff0200, 0xfeff0100, 0xff7f0080,
1489bf9a700SWesley Yao 	0xffbf0040, 0xffdf0020, 0xffef0010, 0xfff70008,
1499bf9a700SWesley Yao 	0xfffb0004, 0xfffd0002, 0xfffe0001, 0xffff0000
1509bf9a700SWesley Yao };
1519bf9a700SWesley Yao 
1529bf9a700SWesley Yao static struct pat walking_inv_1_x16 = {
1539bf9a700SWesley Yao 	"walking_inv_1_x16",
1549bf9a700SWesley Yao 	walking_inv_1_x16_data,
1559bf9a700SWesley Yao 	ARRAY_SIZE(walking_inv_1_x16_data) - 1,	/* mask */
1569bf9a700SWesley Yao 	{2, 0, 0, 0}	/* weight */
1579bf9a700SWesley Yao };
1589bf9a700SWesley Yao 
1599bf9a700SWesley Yao static u32 walking_inv_1_x16_repeat_data[] = {
1609bf9a700SWesley Yao 	0x00010001, 0xfffefffe, 0x00020002, 0xfffdfffd,
1619bf9a700SWesley Yao 	0x00040004, 0xfffbfffb, 0x00080008, 0xfff7fff7,
1629bf9a700SWesley Yao 	0x00100010, 0xffefffef, 0x00200020, 0xffdfffdf,
1639bf9a700SWesley Yao 	0x00400040, 0xffbfffbf, 0x00800080, 0xff7fff7f,
1649bf9a700SWesley Yao 	0x01000100, 0xfefffeff, 0x02000200, 0xfdfffdff,
1659bf9a700SWesley Yao 	0x04000400, 0xfbfffbff, 0x08000800, 0xf7fff7ff,
1669bf9a700SWesley Yao 	0x10001000, 0xefffefff, 0x20002000, 0xdfffdfff,
1679bf9a700SWesley Yao 	0x40004000, 0xbfffbfff, 0x80008000, 0x7fff7fff,
1689bf9a700SWesley Yao 	0x40004000, 0xbfffbfff, 0x20002000, 0xdfffdfff,
1699bf9a700SWesley Yao 	0x10001000, 0xefffefff, 0x08000800, 0xf7fff7ff,
1709bf9a700SWesley Yao 	0x04000400, 0xfbfffbff, 0x02000200, 0xfdfffdff,
1719bf9a700SWesley Yao 	0x01000100, 0xfefffeff, 0x00800080, 0xff7fff7f,
1729bf9a700SWesley Yao 	0x00400040, 0xffbfffbf, 0x00200020, 0xffdfffdf,
1739bf9a700SWesley Yao 	0x00100010, 0xffefffef, 0x00080008, 0xfff7fff7,
1749bf9a700SWesley Yao 	0x00040004, 0xfffbfffb, 0x00020002, 0xfffdfffd,
1759bf9a700SWesley Yao 	0x00010001, 0xfffefffe, 0x00000000, 0xffffffff
1769bf9a700SWesley Yao };
1779bf9a700SWesley Yao 
1789bf9a700SWesley Yao static struct pat walking_inv_1_x16_repeat = {
1799bf9a700SWesley Yao 	"walking_inv_1_x16_repeat",
1809bf9a700SWesley Yao 	walking_inv_1_x16_repeat_data,
1819bf9a700SWesley Yao 	ARRAY_SIZE(walking_inv_1_x16_repeat_data) - 1,	/* mask */
1829bf9a700SWesley Yao 	{2, 5, 5, 0}	/* weight */
1839bf9a700SWesley Yao };
1849bf9a700SWesley Yao 
1859bf9a700SWesley Yao static u32 walking_0_data[] = {
1869bf9a700SWesley Yao 	0xfffffffe, 0xfffffffd, 0xfffffffb, 0xfffffff7,
1879bf9a700SWesley Yao 	0xffffffef, 0xffffffdf, 0xffffffbf, 0xffffff7f,
1889bf9a700SWesley Yao 	0xfffffeff, 0xfffffdff, 0xfffffbff, 0xfffff7ff,
1899bf9a700SWesley Yao 	0xffffefff, 0xffffdfff, 0xffffbfff, 0xffff7fff,
1909bf9a700SWesley Yao 	0xfffeffff, 0xfffdffff, 0xfffbffff, 0xfff7ffff,
1919bf9a700SWesley Yao 	0xffefffff, 0xffdfffff, 0xffbfffff, 0xff7fffff,
1929bf9a700SWesley Yao 	0xfeffffff, 0xfdffffff, 0xfbffffff, 0xf7ffffff,
1939bf9a700SWesley Yao 	0xefffffff, 0xdfffffff, 0xbfffffff, 0x7fffffff,
1949bf9a700SWesley Yao 	0xbfffffff, 0xdfffffff, 0xefffffff, 0xf7ffffff,
1959bf9a700SWesley Yao 	0xfbffffff, 0xfdffffff, 0xfeffffff, 0xff7fffff,
1969bf9a700SWesley Yao 	0xffbfffff, 0xffdfffff, 0xffefffff, 0xfff7ffff,
1979bf9a700SWesley Yao 	0xfffbffff, 0xfffdffff, 0xfffeffff, 0xffff7fff,
1989bf9a700SWesley Yao 	0xffffbfff, 0xffffdfff, 0xffffefff, 0xfffff7ff,
1999bf9a700SWesley Yao 	0xfffffbff, 0xfffffdff, 0xfffffeff, 0xffffff7f,
2009bf9a700SWesley Yao 	0xffffffbf, 0xffffffdf, 0xffffffef, 0xfffffff7,
2019bf9a700SWesley Yao 	0xfffffffb, 0xfffffffd, 0xfffffffe, 0xffffffff
2029bf9a700SWesley Yao };
2039bf9a700SWesley Yao 
2049bf9a700SWesley Yao static struct pat walking_0 = {
2059bf9a700SWesley Yao 	"walking_0",
2069bf9a700SWesley Yao 	walking_0_data,
2079bf9a700SWesley Yao 	ARRAY_SIZE(walking_0_data) - 1,	/* mask */
2089bf9a700SWesley Yao 	{1, 1, 2, 1}	/* weight */
2099bf9a700SWesley Yao };
2109bf9a700SWesley Yao 
2119bf9a700SWesley Yao static u32 one_zero_data[] = {0x00000000, 0xffffffff};
2129bf9a700SWesley Yao 
2139bf9a700SWesley Yao static struct pat one_zero = {
2149bf9a700SWesley Yao 	"one_zero",
2159bf9a700SWesley Yao 	one_zero_data,
2169bf9a700SWesley Yao 	ARRAY_SIZE(one_zero_data) - 1,	/* mask */
2179bf9a700SWesley Yao 	{5, 5, 15, 5}	/* weight */
2189bf9a700SWesley Yao };
2199bf9a700SWesley Yao 
2209bf9a700SWesley Yao static unsigned int one_zero_x16_data[] = {0x0000ffff, 0x0000ffff};
2219bf9a700SWesley Yao 
2229bf9a700SWesley Yao static struct pat one_zero_x16 = {
2239bf9a700SWesley Yao 	"one_zero_x16",
2249bf9a700SWesley Yao 	one_zero_x16_data,
2259bf9a700SWesley Yao 	ARRAY_SIZE(one_zero_x16_data) - 1,	/* mask */
2269bf9a700SWesley Yao 	{5, 0, 0, 0}	/* weight */
2279bf9a700SWesley Yao };
2289bf9a700SWesley Yao 
2299bf9a700SWesley Yao static u32 just_0_data[] = {0x00000000, 0x00000000};
2309bf9a700SWesley Yao 
2319bf9a700SWesley Yao static struct pat just_0 = {
2329bf9a700SWesley Yao 	"just_0",
2339bf9a700SWesley Yao 	just_0_data,
2349bf9a700SWesley Yao 	ARRAY_SIZE(just_0_data) - 1,	/* mask */
2359bf9a700SWesley Yao 	{2, 0, 0, 0}	/* weight */
2369bf9a700SWesley Yao };
2379bf9a700SWesley Yao 
2389bf9a700SWesley Yao static u32 just_1_data[] = {0xffffffff, 0xffffffff};
2399bf9a700SWesley Yao 
2409bf9a700SWesley Yao static struct pat just_1 = {
2419bf9a700SWesley Yao 	"just_1",
2429bf9a700SWesley Yao 	just_1_data,
2439bf9a700SWesley Yao 	ARRAY_SIZE(just_1_data) - 1,	/* mask */
2449bf9a700SWesley Yao 	{2, 0, 0, 0}	/* weight */
2459bf9a700SWesley Yao };
2469bf9a700SWesley Yao 
2479bf9a700SWesley Yao static u32 just_5_data[] = {0x55555555, 0x55555555};
2489bf9a700SWesley Yao 
2499bf9a700SWesley Yao static struct pat just_5 = {
2509bf9a700SWesley Yao 	"just_5",
2519bf9a700SWesley Yao 	just_5_data,
2529bf9a700SWesley Yao 	ARRAY_SIZE(just_5_data) - 1,	/* mask */
2539bf9a700SWesley Yao 	{2, 0, 0, 0}	/* weight */
2549bf9a700SWesley Yao };
2559bf9a700SWesley Yao 
2569bf9a700SWesley Yao static u32 just_a_data[] = {0xaaaaaaaa, 0xaaaaaaaa};
2579bf9a700SWesley Yao 
2589bf9a700SWesley Yao static struct pat just_a = {
2599bf9a700SWesley Yao 	"just_a",
2609bf9a700SWesley Yao 	just_a_data,
2619bf9a700SWesley Yao 	ARRAY_SIZE(just_a_data) - 1,	/* mask */
2629bf9a700SWesley Yao 	{2, 0, 0, 0}	/* weight */
2639bf9a700SWesley Yao };
2649bf9a700SWesley Yao 
2659bf9a700SWesley Yao static u32 five_a_data[] = {0x55555555, 0xaaaaaaaa};
2669bf9a700SWesley Yao 
2679bf9a700SWesley Yao static struct pat five_a = {
2689bf9a700SWesley Yao 	"five_a",
2699bf9a700SWesley Yao 	five_a_data,
2709bf9a700SWesley Yao 	ARRAY_SIZE(five_a_data) - 1,	/* mask */
2719bf9a700SWesley Yao 	{1, 1, 1, 1}	/* weight */
2729bf9a700SWesley Yao };
2739bf9a700SWesley Yao 
2749bf9a700SWesley Yao static unsigned int five_a_x16_data[] = {0x5555aaaa, 0x5555aaaa};
2759bf9a700SWesley Yao 
2769bf9a700SWesley Yao static struct pat five_a_x16 = {
2779bf9a700SWesley Yao 	"five_a_x16",
2789bf9a700SWesley Yao 	five_a_x16_data,
2799bf9a700SWesley Yao 	ARRAY_SIZE(five_a_x16_data) - 1,	/* mask */
2809bf9a700SWesley Yao 	{1, 0, 0, 0}	/* weight */
2819bf9a700SWesley Yao };
2829bf9a700SWesley Yao 
2839bf9a700SWesley Yao static u32 five_a8_data[] = {
2849bf9a700SWesley Yao 	0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a
2859bf9a700SWesley Yao };
2869bf9a700SWesley Yao 
2879bf9a700SWesley Yao static struct pat five_a8 = {
2889bf9a700SWesley Yao 	"five_a8",
2899bf9a700SWesley Yao 	five_a8_data,
2909bf9a700SWesley Yao 	ARRAY_SIZE(five_a8_data) - 1,	/* mask */
2919bf9a700SWesley Yao 	{1, 1, 1, 1}	/* weight */
2929bf9a700SWesley Yao };
2939bf9a700SWesley Yao 
2949bf9a700SWesley Yao static u32 five_a8_x16_data[] = {0x5aa5a55a, 0xa55a5aa5};
2959bf9a700SWesley Yao 
2969bf9a700SWesley Yao static struct pat five_a8_x16 = {
2979bf9a700SWesley Yao 	"five_a8_x16",
2989bf9a700SWesley Yao 	five_a8_x16_data,
2999bf9a700SWesley Yao 	ARRAY_SIZE(five_a8_x16_data) - 1,	/* mask */
3009bf9a700SWesley Yao 	{1, 0, 0, 0}	/* weight */
3019bf9a700SWesley Yao };
3029bf9a700SWesley Yao 
3039bf9a700SWesley Yao static unsigned int five_a8_x16_repeat_data[] = {
3049bf9a700SWesley Yao 	0x5aa55aa5, 0xa55aa55a, 0xa55aa55a, 0x5aa55aa5
3059bf9a700SWesley Yao };
3069bf9a700SWesley Yao 
3079bf9a700SWesley Yao static struct pat five_a8_x16_repeat = {
3089bf9a700SWesley Yao 	"five_a8_x16_repeat",
3099bf9a700SWesley Yao 	five_a8_x16_repeat_data,
3109bf9a700SWesley Yao 	ARRAY_SIZE(five_a8_x16_repeat_data) - 1,	/* mask */
3119bf9a700SWesley Yao 	{1, 1, 1, 0}	/* weight */
3129bf9a700SWesley Yao };
3139bf9a700SWesley Yao 
3149bf9a700SWesley Yao static u32 long_8b10b_data[] = {0x16161616, 0x16161616};
3159bf9a700SWesley Yao 
3169bf9a700SWesley Yao static struct pat long_8b10b = {
3179bf9a700SWesley Yao 	"long_8b10b",
3189bf9a700SWesley Yao 	long_8b10b_data,
3199bf9a700SWesley Yao 	ARRAY_SIZE(long_8b10b_data) - 1,	/* mask */
3209bf9a700SWesley Yao 	{2, 0, 0, 0}	/* weight */
3219bf9a700SWesley Yao };
3229bf9a700SWesley Yao 
3239bf9a700SWesley Yao static u32 short_8b10b_data[] = {0xb5b5b5b5, 0xb5b5b5b5};
3249bf9a700SWesley Yao 
3259bf9a700SWesley Yao static struct pat short_8b10b = {
3269bf9a700SWesley Yao 	"short_8b10b",
3279bf9a700SWesley Yao 	short_8b10b_data,
3289bf9a700SWesley Yao 	ARRAY_SIZE(short_8b10b_data) - 1,	/* mask */
3299bf9a700SWesley Yao 	{2, 0, 0, 0}	/* weight */
3309bf9a700SWesley Yao };
3319bf9a700SWesley Yao 
3329bf9a700SWesley Yao static u32 checker_8b10b_data[] = {0xb5b5b5b5, 0x4a4a4a4a};
3339bf9a700SWesley Yao 
3349bf9a700SWesley Yao static struct pat checker_8b10b = {
3359bf9a700SWesley Yao 	"checker_8b10b",
3369bf9a700SWesley Yao 	checker_8b10b_data,
3379bf9a700SWesley Yao 	ARRAY_SIZE(checker_8b10b_data) - 1,	/* mask */
3389bf9a700SWesley Yao 	{1, 0, 1, 1}	/* weight */
3399bf9a700SWesley Yao };
3409bf9a700SWesley Yao 
3419bf9a700SWesley Yao static u32 checker_8b10b_x16_data[] = {0xb5b54a4a, 0xb5b54a4a};
3429bf9a700SWesley Yao 
3439bf9a700SWesley Yao static struct pat checker_8b10b_x16 = {
3449bf9a700SWesley Yao 	"checker_8b10b_x16",
3459bf9a700SWesley Yao 	checker_8b10b_x16_data,
3469bf9a700SWesley Yao 	ARRAY_SIZE(checker_8b10b_x16_data) - 1,	/* mask */
3479bf9a700SWesley Yao 	{1, 0, 0, 0}	/* weight */
3489bf9a700SWesley Yao };
3499bf9a700SWesley Yao 
3509bf9a700SWesley Yao static u32 five_7_data[] = {0x55555557, 0x55575555};
3519bf9a700SWesley Yao 
3529bf9a700SWesley Yao static struct pat five_7 = {
3539bf9a700SWesley Yao 	"five_7",
3549bf9a700SWesley Yao 	five_7_data,
3559bf9a700SWesley Yao 	ARRAY_SIZE(five_7_data) - 1,	/* mask */
3569bf9a700SWesley Yao 	{0, 2, 0, 0}	/* weight */
3579bf9a700SWesley Yao };
3589bf9a700SWesley Yao 
3599bf9a700SWesley Yao static u32 five_7_x16_data[] = {0x55575557, 0x57555755};
3609bf9a700SWesley Yao 
3619bf9a700SWesley Yao static struct pat five_7_x16 = {
3629bf9a700SWesley Yao 	"five_7_x16",
3639bf9a700SWesley Yao 	five_7_x16_data,
3649bf9a700SWesley Yao 	ARRAY_SIZE(five_7_x16_data) - 1,	/* mask */
3659bf9a700SWesley Yao 	{2, 0, 0, 0}	/* weight */
3669bf9a700SWesley Yao };
3679bf9a700SWesley Yao 
3689bf9a700SWesley Yao static u32 zero2_fd_data[] = {0x00020002, 0xfffdfffd};
3699bf9a700SWesley Yao 
3709bf9a700SWesley Yao static struct pat zero2_fd = {
3719bf9a700SWesley Yao 	"zero2_fd",
3729bf9a700SWesley Yao 	zero2_fd_data,
3739bf9a700SWesley Yao 	ARRAY_SIZE(zero2_fd_data) - 1,	/* mask */
3749bf9a700SWesley Yao 	{0, 2, 0, 0}	/* weight */
3759bf9a700SWesley Yao };
3769bf9a700SWesley Yao 
3779bf9a700SWesley Yao static u32 zero2_fd_x16_data[] = {0x02020202, 0xfdfdfdfd};
3789bf9a700SWesley Yao 
3799bf9a700SWesley Yao static struct pat zero2_fd_x16 = {
3809bf9a700SWesley Yao 	"zero2_fd_x16",
3819bf9a700SWesley Yao 	zero2_fd_x16_data,
3829bf9a700SWesley Yao 	ARRAY_SIZE(zero2_fd_x16_data) - 1,	/* mask */
3839bf9a700SWesley Yao 	{2, 0, 0, 0}	/* weight */
3849bf9a700SWesley Yao };
3859bf9a700SWesley Yao 
3869bf9a700SWesley Yao static struct pat *pat_array[] = {
3879bf9a700SWesley Yao 	&walking_1,
3889bf9a700SWesley Yao 	&walking_1_x16,
3899bf9a700SWesley Yao 	&walking_1_x16_repeat,
3909bf9a700SWesley Yao 	&walking_inv_1,
3919bf9a700SWesley Yao 	&walking_inv_1_x16,
3929bf9a700SWesley Yao 	&walking_inv_1_x16_repeat,
3939bf9a700SWesley Yao 	&walking_0,
3949bf9a700SWesley Yao 	&one_zero,
3959bf9a700SWesley Yao 	&one_zero_x16,
3969bf9a700SWesley Yao 	&just_0,
3979bf9a700SWesley Yao 	&just_1,
3989bf9a700SWesley Yao 	&just_5,
3999bf9a700SWesley Yao 	&just_a,
4009bf9a700SWesley Yao 	&five_a,
4019bf9a700SWesley Yao 	&five_a_x16,
4029bf9a700SWesley Yao 	&five_a8,
4039bf9a700SWesley Yao 	&five_a8_x16,
4049bf9a700SWesley Yao 	&five_a8_x16_repeat,
4059bf9a700SWesley Yao 	&long_8b10b,
4069bf9a700SWesley Yao 	&short_8b10b,
4079bf9a700SWesley Yao 	&checker_8b10b,
4089bf9a700SWesley Yao 	&checker_8b10b_x16,
4099bf9a700SWesley Yao 	&five_7,
4109bf9a700SWesley Yao 	&five_7_x16,
4119bf9a700SWesley Yao 	&zero2_fd,
4129bf9a700SWesley Yao 	&zero2_fd_x16
4139bf9a700SWesley Yao };
4149bf9a700SWesley Yao 
4159bf9a700SWesley Yao static u32 cpu_copy_err[CPU_NUM_MAX];
4169bf9a700SWesley Yao static u32 cpu_inv_err[CPU_NUM_MAX];
4179bf9a700SWesley Yao 
4189bf9a700SWesley Yao static u64 start_time_us;
4199bf9a700SWesley Yao static u64 test_time_us;
4209bf9a700SWesley Yao 
4219bf9a700SWesley Yao static bool cpu_init_finish[CPU_NUM_MAX];
4229bf9a700SWesley Yao static bool cpu_test_finish[CPU_NUM_MAX];
4239bf9a700SWesley Yao static bool pattern_page_init_finish;
4249bf9a700SWesley Yao 
4259bf9a700SWesley Yao #if (CPU_NUM_MAX > 1)
4269bf9a700SWesley Yao static ulong test_count = 0;
4279bf9a700SWesley Yao static ulong __gd;	/* set r9/x18 of secondary cpu to gd addr */
4289bf9a700SWesley Yao #endif
4299bf9a700SWesley Yao ulong __sp;		/* set sp of secondary cpu */
4309bf9a700SWesley Yao 
4319bf9a700SWesley Yao u32 print_mutex;	/* 0: unlock, 1: lock */
4329bf9a700SWesley Yao 
get_time_us(void)4339bf9a700SWesley Yao static u64 get_time_us(void)
4349bf9a700SWesley Yao {
435*13ceb2afSXuhui Lin 	return lldiv(get_ticks(), gd->arch.timer_rate_hz / 1000000);
4369bf9a700SWesley Yao }
4379bf9a700SWesley Yao 
run_time_us(void)4389bf9a700SWesley Yao static u64 run_time_us(void)
4399bf9a700SWesley Yao {
4409bf9a700SWesley Yao 	return get_time_us() - start_time_us;
4419bf9a700SWesley Yao }
4429bf9a700SWesley Yao 
print_time_stamp(void)4439bf9a700SWesley Yao static void print_time_stamp(void)
4449bf9a700SWesley Yao {
4459bf9a700SWesley Yao 	u64 time_us;
4469bf9a700SWesley Yao 
4479bf9a700SWesley Yao 	time_us = run_time_us();
4489bf9a700SWesley Yao 
4499bf9a700SWesley Yao 	printf("[%5d.%06d] ", (u32)(time_us / 1000000), (u32)(time_us % 1000000));
4509bf9a700SWesley Yao }
4519bf9a700SWesley Yao 
pattern_get(struct pattern * pattern,u32 offset)4529bf9a700SWesley Yao static u32 pattern_get(struct pattern *pattern, u32 offset)
4539bf9a700SWesley Yao {
4549bf9a700SWesley Yao 	u32 ret;
4559bf9a700SWesley Yao 
4569bf9a700SWesley Yao 	ret = pattern->pat->data_array[(offset >> pattern->repeat) &
4579bf9a700SWesley Yao 				       pattern->pat->mask];
4589bf9a700SWesley Yao 
4599bf9a700SWesley Yao 	return pattern->inv ? ~ret : ret;
4609bf9a700SWesley Yao }
4619bf9a700SWesley Yao 
pattern_adler_sum_calc(struct pattern * pattern,struct stressapptest_params * sat)4629bf9a700SWesley Yao static void pattern_adler_sum_calc(struct pattern *pattern,
4639bf9a700SWesley Yao 				   struct stressapptest_params *sat)
4649bf9a700SWesley Yao {
4659bf9a700SWesley Yao 	int i = 0;
4669bf9a700SWesley Yao 	u64 a1 = 1;
4679bf9a700SWesley Yao 	u64 b1 = 0;
4689bf9a700SWesley Yao 	u64 a2 = 1;
4699bf9a700SWesley Yao 	u64 b2 = 0;
4709bf9a700SWesley Yao 
4719bf9a700SWesley Yao 	while (i < sat->block_size_byte / sizeof(u32)) {
4729bf9a700SWesley Yao 		a1 += (u64)pattern_get(pattern, i++);
4739bf9a700SWesley Yao 		b1 += a1;
4749bf9a700SWesley Yao 		a1 += pattern_get(pattern, i++);
4759bf9a700SWesley Yao 		b1 += a1;
4769bf9a700SWesley Yao 
4779bf9a700SWesley Yao 		a2 += (u64)pattern_get(pattern, i++);
4789bf9a700SWesley Yao 		b2 += a2;
4799bf9a700SWesley Yao 		a2 += pattern_get(pattern, i++);
4809bf9a700SWesley Yao 		b2 += a2;
4819bf9a700SWesley Yao 	}
4829bf9a700SWesley Yao 
4839bf9a700SWesley Yao 	pattern->adler_sum.a1 = a1;
4849bf9a700SWesley Yao 	pattern->adler_sum.b1 = b1;
4859bf9a700SWesley Yao 	pattern->adler_sum.a2 = a2;
4869bf9a700SWesley Yao 	pattern->adler_sum.b2 = b2;
4879bf9a700SWesley Yao }
4889bf9a700SWesley Yao 
pattern_list_init(struct pattern * pattern_list,struct stressapptest_params * sat)4899bf9a700SWesley Yao static void pattern_list_init(struct pattern *pattern_list,
4909bf9a700SWesley Yao 			      struct stressapptest_params *sat)
4919bf9a700SWesley Yao {
4929bf9a700SWesley Yao 	u32 weight_count = 0;
4939bf9a700SWesley Yao 	int k = 0;
4949bf9a700SWesley Yao 
4959bf9a700SWesley Yao 	for (int i = 0; i < PAT_NUM; i++) {
4969bf9a700SWesley Yao 		for (int j = 0; j < 8; j++) {
4979bf9a700SWesley Yao 			pattern_list[k].pat = pat_array[i];
4989bf9a700SWesley Yao 			pattern_list[k].inv = j % 2;
4999bf9a700SWesley Yao 			pattern_list[k].repeat = j / 2;
5009bf9a700SWesley Yao 			pattern_list[k].weight = pattern_list[k].pat->weight[j / 2];
5019bf9a700SWesley Yao 			pattern_adler_sum_calc(&pattern_list[k], sat);
5029bf9a700SWesley Yao 			weight_count += pattern_list[k].weight;
5039bf9a700SWesley Yao 			k++;
5049bf9a700SWesley Yao 		}
5059bf9a700SWesley Yao 	}
5069bf9a700SWesley Yao 
5079bf9a700SWesley Yao 	sat->weight_count = weight_count;
5089bf9a700SWesley Yao }
5099bf9a700SWesley Yao 
get_max_page_num(ulong page_size_byte)5109c15e090SWesley Yao static u32 get_max_page_num(ulong page_size_byte)
5119c15e090SWesley Yao {
5129c15e090SWesley Yao 	ulong start_adr[CONFIG_NR_DRAM_BANKS], length[CONFIG_NR_DRAM_BANKS];
5139c15e090SWesley Yao 	u32 page_num = 0;
5149c15e090SWesley Yao 
5159c15e090SWesley Yao 	get_print_available_addr(start_adr, length, 0);
5169c15e090SWesley Yao 
5179c15e090SWesley Yao 	page_num = 0;
5189c15e090SWesley Yao 	for (int i = 0; i < ARRAY_SIZE(start_adr) || i < ARRAY_SIZE(length); i++) {
5199c15e090SWesley Yao 		if ((start_adr[i] == 0 && length[i] == 0))
5209c15e090SWesley Yao 			break;
5219c15e090SWesley Yao 		page_num += (u32)(length[i] / page_size_byte);
5229c15e090SWesley Yao 	}
5239c15e090SWesley Yao 
5249c15e090SWesley Yao 	return page_num;
5259c15e090SWesley Yao }
5269c15e090SWesley Yao 
get_page_addr(struct page * page_list,struct stressapptest_params * sat)5279bf9a700SWesley Yao static int get_page_addr(struct page *page_list,
5289bf9a700SWesley Yao 			 struct stressapptest_params *sat)
5299bf9a700SWesley Yao {
5309bf9a700SWesley Yao 	ulong start_adr[CONFIG_NR_DRAM_BANKS], length[CONFIG_NR_DRAM_BANKS];
5319bf9a700SWesley Yao 	ulong used_length;
5329bf9a700SWesley Yao 	u32 page = 0;
5339bf9a700SWesley Yao 
534aa9eaea1SWesley Yao 	get_print_available_addr(start_adr, length, 0);
5359bf9a700SWesley Yao 
536aa9eaea1SWesley Yao 	printf("Address for test:\n	Start         End         Length\n");
5379bf9a700SWesley Yao 	for (int i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
5389bf9a700SWesley Yao 		if ((start_adr[i] == 0 && length[i] == 0) || page >= sat->page_num)
5399bf9a700SWesley Yao 			break;
5402ac0a64aSWesley Yao 		if (start_adr[i] + length[i] < sat->total_start_addr)
5412ac0a64aSWesley Yao 			continue;
5422ac0a64aSWesley Yao 		if (start_adr[i] < sat->total_start_addr) {
5432ac0a64aSWesley Yao 			length[i] -= sat->total_start_addr - start_adr[i];
5442ac0a64aSWesley Yao 			start_adr[i] = sat->total_start_addr;
5452ac0a64aSWesley Yao 		}
5469bf9a700SWesley Yao 
5479bf9a700SWesley Yao 		used_length = 0;
5489bf9a700SWesley Yao 		while (page < sat->page_num &&
5499bf9a700SWesley Yao 		       length[i] >= used_length + sat->page_size_byte) {
5509bf9a700SWesley Yao 			page_list[page].base_addr = (void *)(start_adr[i] + used_length);
5519bf9a700SWesley Yao 			used_length += sat->page_size_byte;
5529bf9a700SWesley Yao 			page++;
5539bf9a700SWesley Yao 		}
554aa9eaea1SWesley Yao 		printf("	0x%09lx - 0x%09lx 0x%09lx\n",
555aa9eaea1SWesley Yao 		       start_adr[i], start_adr[i] + used_length, used_length);
5569bf9a700SWesley Yao 	}
5579bf9a700SWesley Yao 
558aa9eaea1SWesley Yao 	printf("page_num = %d, page_size = 0x%lx, total_test_size = 0x%lx\n",
559aa9eaea1SWesley Yao 	       page, sat->page_size_byte, sat->page_size_byte * page);
560aa9eaea1SWesley Yao 
5619c15e090SWesley Yao 	if (sat->total_test_size_mb == 0) {
5629c15e090SWesley Yao 		/* No arg for total_test_size_mb, test all available space by default. */
5639c15e090SWesley Yao 		sat->page_num = page;
5649c15e090SWesley Yao 	} else if (page < sat->page_num || page < sat->cpu_num * 4) {
5659bf9a700SWesley Yao 		printf("ERROR: Cannot get enough pages to test.\n");
5669bf9a700SWesley Yao 		printf("Please decrease page_size or test_size\n");
5679bf9a700SWesley Yao 
5689bf9a700SWesley Yao 		return -1;
5699bf9a700SWesley Yao 	}
5709bf9a700SWesley Yao 
5719bf9a700SWesley Yao 	return 0;
5729bf9a700SWesley Yao }
5739bf9a700SWesley Yao 
page_init_valid(struct page * page,struct pattern * pattern_list,struct stressapptest_params * sat)5749bf9a700SWesley Yao static void page_init_valid(struct page *page, struct pattern *pattern_list,
5759bf9a700SWesley Yao 			    struct stressapptest_params *sat)
5769bf9a700SWesley Yao {
5779bf9a700SWesley Yao 	int target;
5789bf9a700SWesley Yao 	int i = 0;
5799bf9a700SWesley Yao 	u64 *mem;
5809bf9a700SWesley Yao 
5819bf9a700SWesley Yao 	target = (rand() % sat->weight_count) + 1;
5829bf9a700SWesley Yao 	do {
5839bf9a700SWesley Yao 		target -= pattern_list[i++].weight;
5849bf9a700SWesley Yao 		if (target <= 0)
5859bf9a700SWesley Yao 			break;
5869bf9a700SWesley Yao 	} while (i < PATTERN_LIST_SIZE);
5879bf9a700SWesley Yao 	page->pattern = &pattern_list[--i];
5889bf9a700SWesley Yao 	page->valid = 1;
5899bf9a700SWesley Yao 
5909bf9a700SWesley Yao 	mem = (u64 *)page->base_addr;
5919bf9a700SWesley Yao 	for (i = 0; i < sat->page_size_byte / sizeof(u64); i++)
5929bf9a700SWesley Yao 		mem[i] = (u64)pattern_get(page->pattern, i * 2) |
5939bf9a700SWesley Yao 			 (u64)pattern_get(page->pattern, i * 2 + 1) << 32;
5949bf9a700SWesley Yao }
5959bf9a700SWesley Yao 
page_init_empty(struct page * page)5969bf9a700SWesley Yao static void page_init_empty(struct page *page)
5979bf9a700SWesley Yao {
5989bf9a700SWesley Yao 	page->valid = 0;
5999bf9a700SWesley Yao }
6009bf9a700SWesley Yao 
page_init(struct pattern * pattern_list,struct stressapptest_params * sat)6019bf9a700SWesley Yao static void page_init(struct pattern *pattern_list,
6029bf9a700SWesley Yao 		      struct stressapptest_params *sat)
6039bf9a700SWesley Yao {
6049bf9a700SWesley Yao 	int i, cpu;
6059bf9a700SWesley Yao 	u32 empty_page_num;
6069bf9a700SWesley Yao 
6079bf9a700SWesley Yao 	for (cpu = 0; cpu < sat->cpu_num; cpu++) {
6089bf9a700SWesley Yao 		empty_page_num = 0;
6099bf9a700SWesley Yao 		for (i = cpu; i < sat->page_num; i += sat->cpu_num) {
6109bf9a700SWesley Yao 			if (rand() % 5 < 3) {
6119bf9a700SWesley Yao 				page_list[i].valid = 1;
6129bf9a700SWesley Yao 			} else {
6139bf9a700SWesley Yao 				page_list[i].valid = 0;
6149bf9a700SWesley Yao 				empty_page_num++;
6159bf9a700SWesley Yao 			}
6169bf9a700SWesley Yao 		}
6179bf9a700SWesley Yao 		while (empty_page_num >= sat->page_num / sat->cpu_num / 2 && i > 0) {
6189bf9a700SWesley Yao 			i -= sat->cpu_num;
6199bf9a700SWesley Yao 			if (page_list[i].valid == 0) {
6209bf9a700SWesley Yao 				page_list[i].valid = 1;
6219bf9a700SWesley Yao 				empty_page_num--;
6229bf9a700SWesley Yao 			}
6239bf9a700SWesley Yao 		}
6249bf9a700SWesley Yao 		i = cpu;
6259bf9a700SWesley Yao 		while (empty_page_num < 2 && i < sat->page_num) {
6269bf9a700SWesley Yao 			if (page_list[i].valid == 1) {
6279bf9a700SWesley Yao 				page_list[i].valid = 0;
6289bf9a700SWesley Yao 				empty_page_num++;
6299bf9a700SWesley Yao 			}
6309bf9a700SWesley Yao 			i += sat->cpu_num;
6319bf9a700SWesley Yao 		}
6329bf9a700SWesley Yao 	}
6339bf9a700SWesley Yao 
6349bf9a700SWesley Yao 	for (i = 0; i < sat->page_num; i++) {
6359bf9a700SWesley Yao 		if (page_list[i].valid == 1)
6369bf9a700SWesley Yao 			page_init_valid(&page_list[i], pattern_list, sat);
6379bf9a700SWesley Yao 		else
6389bf9a700SWesley Yao 			page_init_empty(&page_list[i]);
6399bf9a700SWesley Yao 	}
6409bf9a700SWesley Yao 	flush_dcache_all();
6419bf9a700SWesley Yao }
6429bf9a700SWesley Yao 
page_rand_pick(struct page * page_list,bool valid,struct stressapptest_params * sat,u8 cpu_id)6439bf9a700SWesley Yao static u32 page_rand_pick(struct page *page_list, bool valid,
6442d08ea87SWesley Yao 			  struct stressapptest_params *sat, u8 cpu_id)
6459bf9a700SWesley Yao {
6469bf9a700SWesley Yao 	u32 pick;
6479bf9a700SWesley Yao 
64850e09059SWesley Yao 	pick = rand() % sat->page_num;
64950e09059SWesley Yao 	pick = pick / sat->cpu_num * sat->cpu_num + cpu_id;
65050e09059SWesley Yao 	if (pick >= sat->page_num)
65150e09059SWesley Yao 		pick = cpu_id;
65250e09059SWesley Yao 
6539bf9a700SWesley Yao 	while (page_list[pick].valid != valid) {
6549bf9a700SWesley Yao 		pick += sat->cpu_num;
6559bf9a700SWesley Yao 		if (pick >= sat->page_num)
6569bf9a700SWesley Yao 			pick = cpu_id;
6579bf9a700SWesley Yao 	}
6589bf9a700SWesley Yao 
6599bf9a700SWesley Yao 	return pick;
6609bf9a700SWesley Yao }
6619bf9a700SWesley Yao 
block_mis_search(void * dst_addr,struct pattern * src_pattern,char * item,struct stressapptest_params * sat,u8 cpu_id)6620ed3d443SWesley Yao static u32 block_mis_search(void *dst_addr, struct pattern *src_pattern, char *item,
6630ed3d443SWesley Yao 			    struct stressapptest_params *sat, u8 cpu_id)
6649bf9a700SWesley Yao {
6659bf9a700SWesley Yao 	u32 *dst_mem;
6660ed3d443SWesley Yao 	u32 read, reread, expected;
6679bf9a700SWesley Yao 	u32 err = 0;
6680ed3d443SWesley Yao 	u32 *print_addr;
6690ed3d443SWesley Yao 	int i, j;
6709bf9a700SWesley Yao 
6719bf9a700SWesley Yao 	dst_mem = (u32 *)dst_addr;
6729bf9a700SWesley Yao 
6730ed3d443SWesley Yao 	for (i = 0; i < sat->block_size_byte / sizeof(u32); i++) {
6740ed3d443SWesley Yao 		read = dst_mem[i];
6750ed3d443SWesley Yao 		expected = pattern_get(src_pattern, i);
6769bf9a700SWesley Yao 
6770ed3d443SWesley Yao 		if (read != expected) {
6780ed3d443SWesley Yao 			flush_dcache_range((ulong)&dst_mem[i], (ulong)&dst_mem[i + 1]);
6790ed3d443SWesley Yao 			reread = dst_mem[i];
6800ed3d443SWesley Yao 
6819bf9a700SWesley Yao 			lock_byte_mutex(&print_mutex);
6829bf9a700SWesley Yao 
6839bf9a700SWesley Yao 			print_time_stamp();
6840ed3d443SWesley Yao 			printf("%s Hardware Error: miscompare on CPU %d at 0x%lx:\n",
6850ed3d443SWesley Yao 			       item, cpu_id, (ulong)&dst_mem[i]);
6860ed3d443SWesley Yao 			printf("	read:    0x%08x\n", read);
6870ed3d443SWesley Yao 			printf("	reread:  0x%08x(reread^read:0x%08x)\n",
6880ed3d443SWesley Yao 			       reread, reread ^ read);
6890ed3d443SWesley Yao 			printf("	expected:0x%08x(expected^read:0x%08x)\n",
6900ed3d443SWesley Yao 			       expected, expected ^ read);
6910ed3d443SWesley Yao 			printf("	\'%s%s%d\'", src_pattern->pat->name,
6920ed3d443SWesley Yao 							  src_pattern->inv ? "~" : "",
6930ed3d443SWesley Yao 							  32 << src_pattern->repeat);
6940ed3d443SWesley Yao 			if (reread == expected)
6950ed3d443SWesley Yao 				printf(" read error");
6969bf9a700SWesley Yao 			printf("\n");
6979bf9a700SWesley Yao 
6980ed3d443SWesley Yao 			/* Dump data around the error address */
6990ed3d443SWesley Yao 			print_addr = &dst_mem[i] - 64;
7000ed3d443SWesley Yao 			for (j = 0; j < 128; j += 8)
7010ed3d443SWesley Yao 				printf("  [0x%010lx] 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
7020ed3d443SWesley Yao 				       (ulong)(print_addr + j),
7030ed3d443SWesley Yao 				       *(print_addr + j), *(print_addr + j + 1),
7040ed3d443SWesley Yao 				       *(print_addr + j + 2), *(print_addr + j + 3),
7050ed3d443SWesley Yao 				       *(print_addr + j + 4), *(print_addr + j + 5),
7060ed3d443SWesley Yao 				       *(print_addr + j + 6), *(print_addr + j + 7));
7070ed3d443SWesley Yao 
7089bf9a700SWesley Yao 			unlock_byte_mutex(&print_mutex);
7090ed3d443SWesley Yao 
7100ed3d443SWesley Yao 			/* fix the error */
7110ed3d443SWesley Yao 			dst_mem[i] = expected;
7129bf9a700SWesley Yao 			err++;
71332640b0aSWesley Yao 			flush_dcache_range((ulong)&dst_mem[i], (ulong)&dst_mem[i + 1]);
7149bf9a700SWesley Yao 		}
7159bf9a700SWesley Yao 	}
7169bf9a700SWesley Yao 
7179bf9a700SWesley Yao 	if (err == 0) {
7189bf9a700SWesley Yao 		lock_byte_mutex(&print_mutex);
7190ed3d443SWesley Yao 		printf("%s ERROR detected but cannot find mismatch data (maybe read error).\n", item);
7209bf9a700SWesley Yao 		unlock_byte_mutex(&print_mutex);
7219bf9a700SWesley Yao 	}
7229bf9a700SWesley Yao 
7239bf9a700SWesley Yao 	return err;
7249bf9a700SWesley Yao }
7259bf9a700SWesley Yao 
block_inv_check(void * dst_addr,struct pattern * src_pattern,struct stressapptest_params * sat,u8 cpu_id)7269bf9a700SWesley Yao static u32 block_inv_check(void *dst_addr, struct pattern *src_pattern,
7272d08ea87SWesley Yao 			   struct stressapptest_params *sat, u8 cpu_id)
7289bf9a700SWesley Yao {
7299bf9a700SWesley Yao 	u32 *dst_mem;
7309bf9a700SWesley Yao 	u32 err = 0;
7319bf9a700SWesley Yao 	int i = 0;
7329bf9a700SWesley Yao #if defined(WARM_CPU)
7339bf9a700SWesley Yao 	double a, b, c, d;
7349bf9a700SWesley Yao #endif
7359bf9a700SWesley Yao 
7369bf9a700SWesley Yao 	struct adler_sum adler_sum = {
7379bf9a700SWesley Yao 		1, 0, 1, 0
7389bf9a700SWesley Yao 	};
7399bf9a700SWesley Yao 
7409bf9a700SWesley Yao 	dst_mem = (u32 *)dst_addr;
7419bf9a700SWesley Yao 
7429bf9a700SWesley Yao #if defined(WARM_CPU)
7439bf9a700SWesley Yao 	a = 2.0 * dst_mem[0];
7449bf9a700SWesley Yao 	b = 5.0 * dst_mem[0];
7459bf9a700SWesley Yao 	c = 7.0 * dst_mem[0];
7469bf9a700SWesley Yao 	d = 9.0 * dst_mem[0];
7479bf9a700SWesley Yao #endif
7489bf9a700SWesley Yao 
7499bf9a700SWesley Yao 	while (i < sat->block_size_byte / sizeof(u32)) {
7509bf9a700SWesley Yao 		adler_sum.a1 += dst_mem[i++];
7519bf9a700SWesley Yao 		adler_sum.b1 += adler_sum.a1;
7529bf9a700SWesley Yao 		adler_sum.a1 += dst_mem[i++];
7539bf9a700SWesley Yao 		adler_sum.b1 += adler_sum.a1;
7549bf9a700SWesley Yao 
7559bf9a700SWesley Yao #if defined(WARM_CPU)
7569bf9a700SWesley Yao 		a = a * b;
7579bf9a700SWesley Yao 		b = b + c;
7589bf9a700SWesley Yao #endif
7599bf9a700SWesley Yao 
7609bf9a700SWesley Yao 		adler_sum.a2 += dst_mem[i++];
7619bf9a700SWesley Yao 		adler_sum.b2 += adler_sum.a2;
7629bf9a700SWesley Yao 		adler_sum.a2 += dst_mem[i++];
7639bf9a700SWesley Yao 		adler_sum.b2 += adler_sum.a2;
7649bf9a700SWesley Yao #if defined(WARM_CPU)
7659bf9a700SWesley Yao 		c = c * d;
7669bf9a700SWesley Yao 		d = d + d;
7679bf9a700SWesley Yao #endif
7689bf9a700SWesley Yao 	}
7699bf9a700SWesley Yao 
7709bf9a700SWesley Yao #if defined(WARM_CPU)
7719bf9a700SWesley Yao 	d = a + b + c + d;
7729bf9a700SWesley Yao 	if (d == 1.0)
7739bf9a700SWesley Yao 		/* Reference the result so that it can't be discarded by the compiler. */
7749bf9a700SWesley Yao 		printf("This will probably never happen.\n");
7759bf9a700SWesley Yao #endif
7769bf9a700SWesley Yao 
7779bf9a700SWesley Yao 	if (adler_sum.a1 != src_pattern->adler_sum.a1 ||
7789bf9a700SWesley Yao 	    adler_sum.b1 != src_pattern->adler_sum.b1 ||
7799bf9a700SWesley Yao 	    adler_sum.a2 != src_pattern->adler_sum.a2 ||
7800ed3d443SWesley Yao 	    adler_sum.b2 != src_pattern->adler_sum.b2)
7810ed3d443SWesley Yao 		err = block_mis_search(dst_addr, src_pattern, "Inv", sat, cpu_id);
7829bf9a700SWesley Yao 
7839bf9a700SWesley Yao 	return err;
7849bf9a700SWesley Yao }
7859bf9a700SWesley Yao 
page_inv_up(void * src_addr,struct stressapptest_params * sat)7869bf9a700SWesley Yao static void page_inv_up(void *src_addr, struct stressapptest_params *sat)
7879bf9a700SWesley Yao {
7889bf9a700SWesley Yao 	void *dst_addr = src_addr;
7899bf9a700SWesley Yao 	uint data;
7909bf9a700SWesley Yao 	uint *dst_mem;
7919bf9a700SWesley Yao 
7929bf9a700SWesley Yao 	for (int i = 0; i < sat->block_num; i++) {
7939bf9a700SWesley Yao 		dst_mem = (uint *)dst_addr;
79432640b0aSWesley Yao 		for (int j = 0; j < sat->block_size_byte / sizeof(uint); j += 32) {
79532640b0aSWesley Yao 			for (int k = j; k < j + 32; k++) {
79632640b0aSWesley Yao 				data = dst_mem[k];
79732640b0aSWesley Yao 				dst_mem[k] = ~data;
79832640b0aSWesley Yao 			}
79932640b0aSWesley Yao 			flush_dcache_range((ulong)&dst_mem[j], (ulong)&dst_mem[j + 1]);
8009bf9a700SWesley Yao  		}
8019bf9a700SWesley Yao 		dst_addr += sat->block_size_byte;
8029bf9a700SWesley Yao 	}
8039bf9a700SWesley Yao }
8049bf9a700SWesley Yao 
page_inv_down(void * src_addr,struct stressapptest_params * sat)8059bf9a700SWesley Yao static void page_inv_down(void *src_addr, struct stressapptest_params *sat)
8069bf9a700SWesley Yao {
8079bf9a700SWesley Yao 	void *dst_addr = src_addr;
8089bf9a700SWesley Yao 	uint data;
8099bf9a700SWesley Yao 	uint *dst_mem;
8109bf9a700SWesley Yao 
8119bf9a700SWesley Yao 	dst_addr += sat->block_size_byte * (sat->block_num - 1);
8129bf9a700SWesley Yao 
8139bf9a700SWesley Yao 	for (int i = sat->block_num - 1; i >= 0; i--) {
8149bf9a700SWesley Yao 		dst_mem = (uint *)dst_addr;
81532640b0aSWesley Yao 		for (int j = sat->block_size_byte / sizeof(uint) - 32; j >= 0; j -= 32) {
81632640b0aSWesley Yao 			for (int k = j + 31; k >= j; k--) {
81732640b0aSWesley Yao 				data = dst_mem[k];
81832640b0aSWesley Yao 				dst_mem[k] = ~data;
81932640b0aSWesley Yao 			}
82032640b0aSWesley Yao 			flush_dcache_range((ulong)&dst_mem[j], (ulong)&dst_mem[j + 1]);
8219bf9a700SWesley Yao  		}
8229bf9a700SWesley Yao 		dst_addr -= sat->block_size_byte;
8239bf9a700SWesley Yao 	}
8249bf9a700SWesley Yao }
8259bf9a700SWesley Yao 
page_inv(struct stressapptest_params * sat,u8 cpu_id)8262d08ea87SWesley Yao static u32 page_inv(struct stressapptest_params *sat, u8 cpu_id)
8279bf9a700SWesley Yao {
8289bf9a700SWesley Yao 	u32 src;
8299bf9a700SWesley Yao 	void *dst_block_addr;
8309bf9a700SWesley Yao 	u32 err = 0;
8319bf9a700SWesley Yao 
8322d08ea87SWesley Yao 	src = page_rand_pick(page_list, 1, sat, cpu_id);	/* pick a valid page */
8339bf9a700SWesley Yao 	dst_block_addr = page_list[src].base_addr;
8349bf9a700SWesley Yao 
8359bf9a700SWesley Yao 	for (int i = 0; i < 4; i++) {
8369bf9a700SWesley Yao 		if (rand() % 2 == 0)
8379bf9a700SWesley Yao 			page_inv_up(page_list[src].base_addr, sat);
8389bf9a700SWesley Yao 		else
8399bf9a700SWesley Yao 			page_inv_down(page_list[src].base_addr, sat);
8409bf9a700SWesley Yao 	}
8419bf9a700SWesley Yao 
8429bf9a700SWesley Yao 	for (int i = 0; i < sat->block_num; i++) {
8432d08ea87SWesley Yao 		err += block_inv_check(dst_block_addr, page_list[src].pattern, sat, cpu_id);
8449bf9a700SWesley Yao 		dst_block_addr += sat->block_size_byte;
8459bf9a700SWesley Yao 	}
8469bf9a700SWesley Yao 
8479bf9a700SWesley Yao 	return err;
8489bf9a700SWesley Yao }
8499bf9a700SWesley Yao 
block_copy_check(void * dst_addr,struct adler_sum * adler_sum,struct pattern * src_pattern,struct stressapptest_params * sat,u8 cpu_id)8500ed3d443SWesley Yao static u32 block_copy_check(void *dst_addr, struct adler_sum *adler_sum,
8510ed3d443SWesley Yao 			    struct pattern *src_pattern, struct stressapptest_params *sat,
8520ed3d443SWesley Yao 			    u8 cpu_id)
8539bf9a700SWesley Yao {
8549bf9a700SWesley Yao 	u32 err = 0;
8559bf9a700SWesley Yao 
8569bf9a700SWesley Yao 	if (adler_sum->a1 != src_pattern->adler_sum.a1 ||
8579bf9a700SWesley Yao 	    adler_sum->b1 != src_pattern->adler_sum.b1 ||
8589bf9a700SWesley Yao 	    adler_sum->a2 != src_pattern->adler_sum.a2 ||
8590ed3d443SWesley Yao 	    adler_sum->b2 != src_pattern->adler_sum.b2)
8600ed3d443SWesley Yao 		err = block_mis_search(dst_addr, src_pattern, "Copy", sat, cpu_id);
8619bf9a700SWesley Yao 
8629bf9a700SWesley Yao 	return err;
8639bf9a700SWesley Yao }
8649bf9a700SWesley Yao 
block_copy(void * dst_addr,void * src_addr,struct pattern * src_pattern,struct stressapptest_params * sat,u8 cpu_id)8659bf9a700SWesley Yao static u32 block_copy(void *dst_addr, void *src_addr,
8669bf9a700SWesley Yao 		      struct pattern *src_pattern,
8672d08ea87SWesley Yao 		      struct stressapptest_params *sat, u8 cpu_id)
8689bf9a700SWesley Yao {
8699bf9a700SWesley Yao 	u64 *dst_mem;
8709bf9a700SWesley Yao 	u64 *src_mem;
8719bf9a700SWesley Yao 	u64 data;
8729bf9a700SWesley Yao 	int i = 0;
8739bf9a700SWesley Yao #if defined(WARM_CPU)
8749bf9a700SWesley Yao 	double a, b, c, d;
8759bf9a700SWesley Yao #endif
8769bf9a700SWesley Yao 
8779bf9a700SWesley Yao 	struct adler_sum adler_sum = {
8789bf9a700SWesley Yao 		1, 0, 1, 0
8799bf9a700SWesley Yao 	};
8809bf9a700SWesley Yao 
8819bf9a700SWesley Yao 	dst_mem = (u64 *)dst_addr;
8829bf9a700SWesley Yao 	src_mem = (u64 *)src_addr;
8839bf9a700SWesley Yao 
8849bf9a700SWesley Yao #if defined(WARM_CPU)
8859bf9a700SWesley Yao 	a = 2.0 * src_mem[0];
8869bf9a700SWesley Yao 	b = 5.0 * src_mem[0];
8879bf9a700SWesley Yao 	c = 7.0 * src_mem[0];
8889bf9a700SWesley Yao 	d = 9.0 * src_mem[0];
8899bf9a700SWesley Yao #endif
8909bf9a700SWesley Yao 
8919bf9a700SWesley Yao 	while (i < sat->block_size_byte / sizeof(u64)) {
8929bf9a700SWesley Yao 		data = src_mem[i];
8939bf9a700SWesley Yao 		adler_sum.a1 += data & 0xffffffff;
8949bf9a700SWesley Yao 		adler_sum.b1 += adler_sum.a1;
8959bf9a700SWesley Yao 		adler_sum.a1 += data >> 32;
8969bf9a700SWesley Yao 		adler_sum.b1 += adler_sum.a1;
8979bf9a700SWesley Yao 		dst_mem[i] = data;
8989bf9a700SWesley Yao 		i++;
8999bf9a700SWesley Yao 
9009bf9a700SWesley Yao #if defined(WARM_CPU)
9019bf9a700SWesley Yao 		a = a * b;
9029bf9a700SWesley Yao 		b = b + c;
9039bf9a700SWesley Yao #endif
9049bf9a700SWesley Yao 
9059bf9a700SWesley Yao 		data = src_mem[i];
9069bf9a700SWesley Yao 		adler_sum.a2 += data & 0xffffffff;
9079bf9a700SWesley Yao 		adler_sum.b2 += adler_sum.a2;
9089bf9a700SWesley Yao 		adler_sum.a2 += data >> 32;
9099bf9a700SWesley Yao 		adler_sum.b2 += adler_sum.a2;
9109bf9a700SWesley Yao 		dst_mem[i] = data;
9119bf9a700SWesley Yao 		i++;
9129bf9a700SWesley Yao 
9139bf9a700SWesley Yao #if defined(WARM_CPU)
9149bf9a700SWesley Yao 		c = c * d;
9159bf9a700SWesley Yao 		d = d + d;
9169bf9a700SWesley Yao #endif
9179bf9a700SWesley Yao 	}
9189bf9a700SWesley Yao 
9199bf9a700SWesley Yao #if defined(WARM_CPU)
9209bf9a700SWesley Yao 	d = a + b + c + d;
9219bf9a700SWesley Yao 	if (d == 1.0)
9229bf9a700SWesley Yao 		/* Reference the result so that it can't be discarded by the compiler. */
9239bf9a700SWesley Yao 		printf("This will probably never happen.\n");
9249bf9a700SWesley Yao #endif
9259bf9a700SWesley Yao 
9260ed3d443SWesley Yao 	return block_copy_check(dst_addr, &adler_sum, src_pattern, sat, cpu_id);
9279bf9a700SWesley Yao }
9289bf9a700SWesley Yao 
page_copy(struct stressapptest_params * sat,u8 cpu_id)9292d08ea87SWesley Yao static u32 page_copy(struct stressapptest_params *sat, u8 cpu_id)
9309bf9a700SWesley Yao {
9319bf9a700SWesley Yao 	u32 dst;
9329bf9a700SWesley Yao 	u32 src;
9339bf9a700SWesley Yao 	void *dst_block_addr;
9349bf9a700SWesley Yao 	void *src_block_addr;
9359bf9a700SWesley Yao 	u32 err = 0;
9369bf9a700SWesley Yao 
9372d08ea87SWesley Yao 	dst = page_rand_pick(page_list, 0, sat, cpu_id);	/* pick a empty page */
9389bf9a700SWesley Yao 	dst_block_addr = page_list[dst].base_addr;
9392d08ea87SWesley Yao 	src = page_rand_pick(page_list, 1, sat, cpu_id);	/* pick a valid page */
9409bf9a700SWesley Yao 	src_block_addr = page_list[src].base_addr;
9419bf9a700SWesley Yao 
9429bf9a700SWesley Yao 	for (int i = 0; i < sat->block_num; i++) {
9439bf9a700SWesley Yao 		err += block_copy(dst_block_addr, src_block_addr,
9442d08ea87SWesley Yao 				  page_list[src].pattern, sat, cpu_id);
9459bf9a700SWesley Yao 		dst_block_addr += sat->block_size_byte;
9469bf9a700SWesley Yao 		src_block_addr += sat->block_size_byte;
9479bf9a700SWesley Yao 	}
9489bf9a700SWesley Yao 
9499bf9a700SWesley Yao 	page_list[dst].pattern = page_list[src].pattern;
9509bf9a700SWesley Yao 	page_list[dst].valid = 1;
9519bf9a700SWesley Yao 	page_list[src].valid = 0;
95232640b0aSWesley Yao 	flush_dcache_range((ulong)&page_list[src], (ulong)&page_list[src + 1]);
95332640b0aSWesley Yao 	flush_dcache_range((ulong)&page_list[dst], (ulong)&page_list[dst + 1]);
9549bf9a700SWesley Yao 
9559bf9a700SWesley Yao 	return err;
9569bf9a700SWesley Yao }
9579bf9a700SWesley Yao 
secondary_main(void)9589bf9a700SWesley Yao void secondary_main(void)
9599bf9a700SWesley Yao {
9609bf9a700SWesley Yao #if (CPU_NUM_MAX > 1)
9619bf9a700SWesley Yao 	u8 cpu_id;
9629bf9a700SWesley Yao 	ulong test = 0;
9639bf9a700SWesley Yao 
9649bf9a700SWesley Yao #ifndef CONFIG_ARM64
9659bf9a700SWesley Yao 	asm volatile("mov r9, %0" : : "r" (__gd));	/* set r9 to gd addr */
9669bf9a700SWesley Yao #else
9679bf9a700SWesley Yao 	asm volatile("mov x18, %0" : : "r" (__gd));	/* set x18 to gd addr */
9689bf9a700SWesley Yao #endif
9699bf9a700SWesley Yao 	dcache_enable();
9709bf9a700SWesley Yao 	icache_enable();
9719bf9a700SWesley Yao 
9729bf9a700SWesley Yao 	udelay(100);
9739bf9a700SWesley Yao 
9749bf9a700SWesley Yao 	flush_dcache_all();
9752d08ea87SWesley Yao 
9769bf9a700SWesley Yao 	cpu_id = sat.cpu_num;
9779bf9a700SWesley Yao 	cpu_init_finish[cpu_id] = 1;
9789bf9a700SWesley Yao 	printf("CPU%d start OK.\n", cpu_id);
9799bf9a700SWesley Yao 
9809bf9a700SWesley Yao 	while (pattern_page_init_finish == 0) {
9819bf9a700SWesley Yao 		udelay(100);
9829bf9a700SWesley Yao 		flush_dcache_all();
9839bf9a700SWesley Yao 	}
9849bf9a700SWesley Yao 
9859bf9a700SWesley Yao 	while (1) {
9869bf9a700SWesley Yao 		udelay(100);
9879bf9a700SWesley Yao 		flush_dcache_all();
9889bf9a700SWesley Yao 		while (test < test_count) {
9899bf9a700SWesley Yao 			cpu_test_finish[cpu_id] = 0;
9909bf9a700SWesley Yao 			flush_dcache_all();
9919bf9a700SWesley Yao 			while (run_time_us() < test_time_us) {
9929bf9a700SWesley Yao 				if (rand() % 2 == 0)
9932d08ea87SWesley Yao 					cpu_copy_err[cpu_id] += page_copy(&sat, cpu_id);
9949bf9a700SWesley Yao 				else
9952d08ea87SWesley Yao 					cpu_inv_err[cpu_id] += page_inv(&sat, cpu_id);
9969bf9a700SWesley Yao 			}
9979bf9a700SWesley Yao 			test++;
9989bf9a700SWesley Yao 			cpu_test_finish[cpu_id] = 1;
99932640b0aSWesley Yao 			flush_dcache_range((ulong)&cpu_test_finish[cpu_id],
100032640b0aSWesley Yao 					   (ulong)&cpu_test_finish[cpu_id + 1]);
100132640b0aSWesley Yao 			flush_dcache_range((ulong)&cpu_copy_err[cpu_id],
100232640b0aSWesley Yao 					   (ulong)&cpu_copy_err[cpu_id + 1]);
100332640b0aSWesley Yao 			flush_dcache_range((ulong)&cpu_inv_err[cpu_id],
100432640b0aSWesley Yao 					   (ulong)&cpu_inv_err[cpu_id + 1]);
10059bf9a700SWesley Yao 		}
10069bf9a700SWesley Yao 	}
10079bf9a700SWesley Yao #else
10089bf9a700SWesley Yao 	return;
10099bf9a700SWesley Yao #endif
10109bf9a700SWesley Yao }
10119bf9a700SWesley Yao 
doing_stressapptest(void)10129bf9a700SWesley Yao static int doing_stressapptest(void)
10139bf9a700SWesley Yao {
10149bf9a700SWesley Yao 	int i;
10159bf9a700SWesley Yao 	u32 pre_10s;
10169bf9a700SWesley Yao 	u32 now_10s;
10179bf9a700SWesley Yao 
10189bf9a700SWesley Yao 	struct pattern pattern_list[PATTERN_LIST_SIZE];
10199bf9a700SWesley Yao 	void *page_info;
10209bf9a700SWesley Yao 
10219bf9a700SWesley Yao 	u32 all_copy_err = 0;
10229bf9a700SWesley Yao 	u32 all_inv_err = 0;
10239bf9a700SWesley Yao 	u32 cpu_no_response_err = 0;
10249bf9a700SWesley Yao 
10259bf9a700SWesley Yao 	int ret = CMD_RET_SUCCESS;
10269bf9a700SWesley Yao 
10279bf9a700SWesley Yao 	for (i = 0; i < CPU_NUM_MAX; i++) {
10289bf9a700SWesley Yao 		cpu_copy_err[i] = 0;
10299bf9a700SWesley Yao 		cpu_inv_err[i] = 0;
10309bf9a700SWesley Yao 		cpu_init_finish[i] = 0;
10319bf9a700SWesley Yao 		cpu_test_finish[i] = 0;
10329bf9a700SWesley Yao 	}
10339bf9a700SWesley Yao 	pattern_page_init_finish = 0;
10349bf9a700SWesley Yao 	print_mutex = 0;
10359bf9a700SWesley Yao 	asm volatile("clrex");
10369bf9a700SWesley Yao 
10379bf9a700SWesley Yao #if (CPU_NUM_MAX > 1)
10389bf9a700SWesley Yao 	if (test_count == 0) {
10399bf9a700SWesley Yao 		__gd = (ulong)gd;
10409bf9a700SWesley Yao 		asm volatile("mov %0, sp" : "=r" (__sp));
10419bf9a700SWesley Yao 		printf("CPU0 sp is at 0x%lx now.\n", __sp);
10429bf9a700SWesley Yao 		__sp &= ~(ulong)0xffff;
10439bf9a700SWesley Yao 		for (sat.cpu_num = 1; sat.cpu_num < CPU_NUM_MAX; sat.cpu_num++) {
10449bf9a700SWesley Yao 			__sp -= 0x10000;
10459bf9a700SWesley Yao 			flush_dcache_all();
10469bf9a700SWesley Yao 			if (psci_cpu_on(sat.cpu_num, (ulong)secondary_init) == 0) {
10479bf9a700SWesley Yao 				mdelay(10);
10489bf9a700SWesley Yao 				printf("Calling CPU%d, sp = 0x%lx\n", sat.cpu_num, __sp);
10499bf9a700SWesley Yao 			} else {
10509bf9a700SWesley Yao 				break;
10519bf9a700SWesley Yao 			}
10529bf9a700SWesley Yao 			while (cpu_init_finish[sat.cpu_num] == 0) {
10539bf9a700SWesley Yao 				udelay(1000);
10549bf9a700SWesley Yao 				flush_dcache_all();
10559bf9a700SWesley Yao 			}
10569bf9a700SWesley Yao 		}
10579bf9a700SWesley Yao 	}
10589bf9a700SWesley Yao #else
10599bf9a700SWesley Yao 	sat.cpu_num = 1;
10609bf9a700SWesley Yao #endif
10619bf9a700SWesley Yao 
10629c15e090SWesley Yao 	if (sat.total_test_size_mb == 0)
10639c15e090SWesley Yao 		sat.page_num = get_max_page_num(sat.page_size_byte);
10649c15e090SWesley Yao 	else
10659bf9a700SWesley Yao 		sat.page_num = (sat.total_test_size_mb << 20) / sat.page_size_byte;
10669bf9a700SWesley Yao 	sat.block_num = sat.page_size_byte / sat.block_size_byte;
10679bf9a700SWesley Yao 
10689bf9a700SWesley Yao 	udelay(100);
10699bf9a700SWesley Yao 
10709bf9a700SWesley Yao 	page_info = malloc(sizeof(struct page) * sat.page_num);
10719bf9a700SWesley Yao 	if (page_info == 0) {
10729bf9a700SWesley Yao 		printf("ERROR: StressAppTest fail to malloc.\n");
10739bf9a700SWesley Yao 		printf("Please try increasing CONFIG_SYS_MALLOC_LEN in include/configs/rxxxxx_common.h.\n");
10749bf9a700SWesley Yao 		ret = CMD_RET_FAILURE;
10759bf9a700SWesley Yao 		goto out;
10769bf9a700SWesley Yao 	}
10779bf9a700SWesley Yao 	page_list = (struct page *)page_info;
10789bf9a700SWesley Yao 
10799bf9a700SWesley Yao 	if (get_page_addr(page_list, &sat) < 0) {
10809bf9a700SWesley Yao 		ret = CMD_RET_FAILURE;
10819bf9a700SWesley Yao 		goto out;
10829bf9a700SWesley Yao 	}
10839bf9a700SWesley Yao 
10849bf9a700SWesley Yao 	pattern_list_init(pattern_list, &sat);
10859bf9a700SWesley Yao 	page_init(pattern_list, &sat);
10869bf9a700SWesley Yao 
10879bf9a700SWesley Yao #if (CPU_NUM_MAX > 1)
10889bf9a700SWesley Yao 	if (sat.cpu_num > 1) {
10899bf9a700SWesley Yao 		pattern_page_init_finish = 1;
10909bf9a700SWesley Yao 		test_count++;
10919bf9a700SWesley Yao 		flush_dcache_all();
10929bf9a700SWesley Yao 	}
10939bf9a700SWesley Yao #endif
10949bf9a700SWesley Yao 
10959bf9a700SWesley Yao 	pre_10s = (u32)(run_time_us() / 1000000 / 10);
10969bf9a700SWesley Yao 	lock_byte_mutex(&print_mutex);
10979bf9a700SWesley Yao 	print_time_stamp();
10989bf9a700SWesley Yao 	printf("Start StressAppTest in U-Boot:\n");
10999bf9a700SWesley Yao 	unlock_byte_mutex(&print_mutex);
11009bf9a700SWesley Yao 
11019bf9a700SWesley Yao 	while (run_time_us() < test_time_us) {
11029bf9a700SWesley Yao 		if (rand() % 2 == 0)
11032d08ea87SWesley Yao 			cpu_copy_err[0] += page_copy(&sat, 0);
11049bf9a700SWesley Yao 		else
11052d08ea87SWesley Yao 			cpu_inv_err[0] += page_inv(&sat, 0);
11069bf9a700SWesley Yao 
11079bf9a700SWesley Yao 		/* Print every 10 seconds */
11089bf9a700SWesley Yao 		now_10s = (u32)(run_time_us() / 1000000 / 10);
11099bf9a700SWesley Yao 		if (now_10s > pre_10s) {
11109bf9a700SWesley Yao 			pre_10s = now_10s;
11119bf9a700SWesley Yao 			lock_byte_mutex(&print_mutex);
11129bf9a700SWesley Yao 			print_time_stamp();
11139bf9a700SWesley Yao 			printf("Seconds remaining: %d\n", (u32)(test_time_us / 1000000 - now_10s * 10));
11149bf9a700SWesley Yao 			unlock_byte_mutex(&print_mutex);
11159bf9a700SWesley Yao 		}
11169bf9a700SWesley Yao 	}
11179bf9a700SWesley Yao 
11189bf9a700SWesley Yao #if (CPU_NUM_MAX > 1)
11199bf9a700SWesley Yao 	for (i = 1; i < sat.cpu_num; i++) {
11209bf9a700SWesley Yao 		while (cpu_test_finish[i] == 0) {
11219bf9a700SWesley Yao 			if ((u32)(run_time_us() / 1000000 / 10) > pre_10s + 6) {
11229bf9a700SWesley Yao 				/* wait for secondary CPU in 60s */
11239bf9a700SWesley Yao 				lock_byte_mutex(&print_mutex);
11249bf9a700SWesley Yao 				print_time_stamp();
11259bf9a700SWesley Yao 				printf("ERROR: Cannot wait for CPU%d to finish!\n", i);
11269bf9a700SWesley Yao 				unlock_byte_mutex(&print_mutex);
11279bf9a700SWesley Yao 				cpu_no_response_err++;
11289bf9a700SWesley Yao 				break;
11299bf9a700SWesley Yao 			}
11309bf9a700SWesley Yao 			mdelay(1);
113132640b0aSWesley Yao 			flush_dcache_range((ulong)&cpu_test_finish[i],
113232640b0aSWesley Yao 					   (ulong)&cpu_test_finish[i + 1]);
113332640b0aSWesley Yao 		}
113432640b0aSWesley Yao 	}
11359bf9a700SWesley Yao 	flush_dcache_all();
11369bf9a700SWesley Yao #endif
11379bf9a700SWesley Yao 
11389bf9a700SWesley Yao 	for (i = 0; i < sat.cpu_num; i++) {
11399bf9a700SWesley Yao 		all_copy_err += cpu_copy_err[i];
11409bf9a700SWesley Yao 		all_inv_err += cpu_inv_err[i];
11419bf9a700SWesley Yao 	}
11429bf9a700SWesley Yao 	print_time_stamp();
11439bf9a700SWesley Yao 	printf("StressAppTest Result: ");
11449bf9a700SWesley Yao 	if (all_copy_err == 0 && all_inv_err == 0 && cpu_no_response_err == 0)
11459bf9a700SWesley Yao 		printf("Pass.\n");
11469bf9a700SWesley Yao 	else
11479bf9a700SWesley Yao 		printf("FAIL!\nStressAppTest detects %d copy errors, %d inv errors.\n",
11489bf9a700SWesley Yao 		       all_copy_err, all_inv_err);
11499bf9a700SWesley Yao 
11509bf9a700SWesley Yao out:
11519bf9a700SWesley Yao 	free(page_info);
11529bf9a700SWesley Yao 
11539bf9a700SWesley Yao 	return ret;
11549bf9a700SWesley Yao }
11559bf9a700SWesley Yao 
do_stressapptest(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])11569bf9a700SWesley Yao static int do_stressapptest(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
11579bf9a700SWesley Yao {
11589bf9a700SWesley Yao 	ulong test_time_sec = 20;
11599bf9a700SWesley Yao 	ulong page_size_kb = 1024;
11609bf9a700SWesley Yao 
11619c15e090SWesley Yao 	sat.total_test_size_mb = 0;
11629bf9a700SWesley Yao 	sat.block_size_byte = 4096;
11632ac0a64aSWesley Yao 	sat.total_start_addr = 0x0;
11649bf9a700SWesley Yao 
11659bf9a700SWesley Yao 	printf("StressAppTest in U-Boot, " __version__ "\n");
11669bf9a700SWesley Yao 
11679bf9a700SWesley Yao 	if (argc > 1) {
11689bf9a700SWesley Yao 		if (strict_strtoul(argv[1], 0, &test_time_sec) < 0)
11699bf9a700SWesley Yao 			return CMD_RET_USAGE;
11709bf9a700SWesley Yao 		if (test_time_sec < 1)
11719bf9a700SWesley Yao 			test_time_sec = 20;
11729bf9a700SWesley Yao 	}
11739bf9a700SWesley Yao 	if (argc > 2) {
11749bf9a700SWesley Yao 		if (strict_strtoul(argv[2], 0, &sat.total_test_size_mb) < 0)
11759bf9a700SWesley Yao 			return CMD_RET_USAGE;
11769bf9a700SWesley Yao 		if (sat.total_test_size_mb < 1)
11779c15e090SWesley Yao 			sat.total_test_size_mb = 0;
11789bf9a700SWesley Yao 	}
11799bf9a700SWesley Yao 	if (argc > 3) {
11802ac0a64aSWesley Yao 		if (strict_strtoul(argv[3], 0, &sat.total_start_addr) < 0)
11812ac0a64aSWesley Yao 			return CMD_RET_USAGE;
11822ac0a64aSWesley Yao 		if (sat.total_start_addr < 0x1)
11832ac0a64aSWesley Yao 			sat.total_start_addr = 0x0;
11842ac0a64aSWesley Yao 	}
11852ac0a64aSWesley Yao 	if (argc > 4) {
11862ac0a64aSWesley Yao 		if (strict_strtoul(argv[4], 0, &page_size_kb) < 0)
11879bf9a700SWesley Yao 			return CMD_RET_USAGE;
11889bf9a700SWesley Yao 		if (page_size_kb < 1)
11899bf9a700SWesley Yao 			page_size_kb = 1024;
11909bf9a700SWesley Yao 	}
11919bf9a700SWesley Yao 
11929bf9a700SWesley Yao 	sat.page_size_byte = page_size_kb << 10;
11939bf9a700SWesley Yao 
11949bf9a700SWesley Yao 	start_time_us = get_time_us();
11959bf9a700SWesley Yao 	test_time_us = (u64)test_time_sec * 1000000;
11969bf9a700SWesley Yao 
11979bf9a700SWesley Yao 	/* Change rand seed. If not do this, rand() would be same after boot.*/
11989bf9a700SWesley Yao 	srand((unsigned int)(start_time_us & 0xffffffff));
11999bf9a700SWesley Yao 
12009bf9a700SWesley Yao 	return doing_stressapptest();
12019bf9a700SWesley Yao }
12029bf9a700SWesley Yao 
12032ac0a64aSWesley Yao U_BOOT_CMD(stressapptest,	5,	1,	do_stressapptest,
12042ac0a64aSWesley Yao 	   "StressAppTest for Rockchip\n",
12052ac0a64aSWesley Yao 	   "\narg1: test time in second, default value is 20s.\n"
12069c15e090SWesley Yao 	   "arg2: test size in MB, default value is all available space.\n"
12072ac0a64aSWesley Yao 	   "arg3: start addr for test.\n"
12082ac0a64aSWesley Yao 	   "arg4: test page size in kB, default value is 1024kB(1MB).\n"
12099bf9a700SWesley Yao 	   "example:\n"
12109c15e090SWesley Yao 	   "	stressapptest: test for 20s, test size is all available space, each page size is 1MB.\n"
12119bf9a700SWesley Yao 	   "	stressapptest 43200 64: test for 12h, test size is 64MB, each page size is 1MB (64 pages).\n"
12122ac0a64aSWesley Yao 	   "	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"
12132ac0a64aSWesley Yao 	   "	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"
12149bf9a700SWesley Yao );
1215