1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2002
4  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5  */
6 
7 #include <common.h>
8 
9 /*
10  * CPU test
11  * Store instructions:		stb(x)(u), sth(x)(u), stw(x)(u)
12  *
13  * All operations are performed on a 16-byte array. The array
14  * is 4-byte aligned. The base register points to offset 8.
15  * The immediate offset (index register) ranges in [-8 ... +7].
16  * The test cases are composed so that they do not
17  * cause alignment exceptions.
18  * The test contains a pre-built table describing all test cases.
19  * The table entry contains:
20  * the instruction opcode, the value of the index register and
21  * the value of the source register. After executing the
22  * instruction, the test verifies the contents of the array
23  * and the value of the base register (it must change for "store
24  * with update" instructions).
25  */
26 
27 #include <post.h>
28 #include "cpu_asm.h"
29 
30 #if CONFIG_POST & CONFIG_SYS_POST_CPU
31 
32 extern void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3);
33 extern void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2);
34 
35 static struct cpu_post_store_s
36 {
37     ulong cmd;
38     uint width;
39     int update;
40     int index;
41     ulong offset;
42     ulong value;
43 } cpu_post_store_table[] =
44 {
45     {
46 	OP_STW,
47 	4,
48 	0,
49 	0,
50 	-4,
51 	0xff00ff00
52     },
53     {
54 	OP_STH,
55 	2,
56 	0,
57 	0,
58 	-2,
59 	0xff00
60     },
61     {
62 	OP_STB,
63 	1,
64 	0,
65 	0,
66 	-1,
67 	0xff
68     },
69     {
70 	OP_STWU,
71 	4,
72 	1,
73 	0,
74 	-4,
75 	0xff00ff00
76     },
77     {
78 	OP_STHU,
79 	2,
80 	1,
81 	0,
82 	-2,
83 	0xff00
84     },
85     {
86 	OP_STBU,
87 	1,
88 	1,
89 	0,
90 	-1,
91 	0xff
92     },
93     {
94 	OP_STWX,
95 	4,
96 	0,
97 	1,
98 	-4,
99 	0xff00ff00
100     },
101     {
102 	OP_STHX,
103 	2,
104 	0,
105 	1,
106 	-2,
107 	0xff00
108     },
109     {
110 	OP_STBX,
111 	1,
112 	0,
113 	1,
114 	-1,
115 	0xff
116     },
117     {
118 	OP_STWUX,
119 	4,
120 	1,
121 	1,
122 	-4,
123 	0xff00ff00
124     },
125     {
126 	OP_STHUX,
127 	2,
128 	1,
129 	1,
130 	-2,
131 	0xff00
132     },
133     {
134 	OP_STBUX,
135 	1,
136 	1,
137 	1,
138 	-1,
139 	0xff
140     },
141 };
142 static unsigned int cpu_post_store_size = ARRAY_SIZE(cpu_post_store_table);
143 
cpu_post_test_store(void)144 int cpu_post_test_store (void)
145 {
146     int ret = 0;
147     unsigned int i;
148     int flag = disable_interrupts();
149 
150     for (i = 0; i < cpu_post_store_size && ret == 0; i++)
151     {
152 	struct cpu_post_store_s *test = cpu_post_store_table + i;
153 	uchar data[16] =
154 	{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
155 	ulong base0 = (ulong) (data + 8);
156 	ulong base = base0;
157 
158 	if (test->index)
159 	{
160 	    ulong code[] =
161 	    {
162 		ASM_12(test->cmd, 5, 3, 4),
163 		ASM_BLR,
164 	    };
165 
166 	    cpu_post_exec_12w (code, &base, test->offset, test->value);
167 	}
168 	else
169 	{
170 	    ulong code[] =
171 	    {
172 		ASM_11I(test->cmd, 4, 3, test->offset),
173 		ASM_BLR,
174 	    };
175 
176 	    cpu_post_exec_11w (code, &base, test->value);
177 	}
178 
179 	if (ret == 0)
180 	{
181 	   if (test->update)
182 	       ret = base == base0 + test->offset ? 0 : -1;
183 	   else
184 	       ret = base == base0 ? 0 : -1;
185 	}
186 
187 	if (ret == 0)
188 	{
189 	    switch (test->width)
190 	    {
191 	    case 1:
192 		ret = *(uchar *)(base0 + test->offset) == test->value ?
193 		      0 : -1;
194 		break;
195 	    case 2:
196 		ret = *(ushort *)(base0 + test->offset) == test->value ?
197 		      0 : -1;
198 		break;
199 	    case 4:
200 		ret = *(ulong *)(base0 + test->offset) == test->value ?
201 		      0 : -1;
202 		break;
203 	    }
204 	}
205 
206 	if (ret != 0)
207 	{
208 	    post_log ("Error at store test %d !\n", i);
209 	}
210     }
211 
212     if (flag)
213 	enable_interrupts();
214 
215     return ret;
216 }
217 
218 #endif
219