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  * Condition register istructions:	mtcr, mfcr, mcrxr,
12  *					crand, crandc, cror, crorc, crxor,
13  *					crnand, crnor, creqv, mcrf
14  *
15  * The mtcrf/mfcr instructions is tested by loading different
16  * values into the condition register (mtcrf), moving its value
17  * to a general-purpose register (mfcr) and comparing this value
18  * with the expected one.
19  * The mcrxr instruction is tested by loading a fixed value
20  * into the XER register (mtspr), moving XER value to the
21  * condition register (mcrxr), moving it to a general-purpose
22  * register (mfcr) and comparing the value of this register with
23  * the expected one.
24  * The rest of instructions is tested by loading a fixed
25  * value into the condition register (mtcrf), executing each
26  * instruction several times to modify all 4-bit condition
27  * fields, moving the value of the conditional register to a
28  * general-purpose register (mfcr) and comparing it with the
29  * expected one.
30  */
31 
32 #include <post.h>
33 #include "cpu_asm.h"
34 
35 #if CONFIG_POST & CONFIG_SYS_POST_CPU
36 
37 extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
38 extern void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3);
39 
40 static ulong cpu_post_cr_table1[] =
41 {
42     0xaaaaaaaa,
43     0x55555555,
44 };
45 static unsigned int cpu_post_cr_size1 = ARRAY_SIZE(cpu_post_cr_table1);
46 
47 static struct cpu_post_cr_s2 {
48     ulong xer;
49     ulong cr;
50 } cpu_post_cr_table2[] =
51 {
52     {
53 	0xa0000000,
54 	1
55     },
56     {
57 	0x40000000,
58 	5
59     },
60 };
61 static unsigned int cpu_post_cr_size2 = ARRAY_SIZE(cpu_post_cr_table2);
62 
63 static struct cpu_post_cr_s3 {
64     ulong cr;
65     ulong cs;
66     ulong cd;
67     ulong res;
68 } cpu_post_cr_table3[] =
69 {
70     {
71 	0x01234567,
72 	0,
73 	4,
74 	0x01230567
75     },
76     {
77 	0x01234567,
78 	7,
79 	0,
80 	0x71234567
81     },
82 };
83 static unsigned int cpu_post_cr_size3 = ARRAY_SIZE(cpu_post_cr_table3);
84 
85 static struct cpu_post_cr_s4 {
86     ulong cmd;
87     ulong cr;
88     ulong op1;
89     ulong op2;
90     ulong op3;
91     ulong res;
92 } cpu_post_cr_table4[] =
93 {
94     {
95 	OP_CRAND,
96 	0x0000ffff,
97 	0,
98 	16,
99 	0,
100 	0x0000ffff
101     },
102     {
103 	OP_CRAND,
104 	0x0000ffff,
105 	16,
106 	17,
107 	0,
108 	0x8000ffff
109     },
110     {
111 	OP_CRANDC,
112 	0x0000ffff,
113 	0,
114 	16,
115 	0,
116 	0x0000ffff
117     },
118     {
119 	OP_CRANDC,
120 	0x0000ffff,
121 	16,
122 	0,
123 	0,
124 	0x8000ffff
125     },
126     {
127 	OP_CROR,
128 	0x0000ffff,
129 	0,
130 	16,
131 	0,
132 	0x8000ffff
133     },
134     {
135 	OP_CROR,
136 	0x0000ffff,
137 	0,
138 	1,
139 	0,
140 	0x0000ffff
141     },
142     {
143 	OP_CRORC,
144 	0x0000ffff,
145 	0,
146 	16,
147 	0,
148 	0x0000ffff
149     },
150     {
151 	OP_CRORC,
152 	0x0000ffff,
153 	0,
154 	0,
155 	0,
156 	0x8000ffff
157     },
158     {
159 	OP_CRXOR,
160 	0x0000ffff,
161 	0,
162 	0,
163 	0,
164 	0x0000ffff
165     },
166     {
167 	OP_CRXOR,
168 	0x0000ffff,
169 	0,
170 	16,
171 	0,
172 	0x8000ffff
173     },
174     {
175 	OP_CRNAND,
176 	0x0000ffff,
177 	0,
178 	16,
179 	0,
180 	0x8000ffff
181     },
182     {
183 	OP_CRNAND,
184 	0x0000ffff,
185 	16,
186 	17,
187 	0,
188 	0x0000ffff
189     },
190     {
191 	OP_CRNOR,
192 	0x0000ffff,
193 	0,
194 	16,
195 	0,
196 	0x0000ffff
197     },
198     {
199 	OP_CRNOR,
200 	0x0000ffff,
201 	0,
202 	1,
203 	0,
204 	0x8000ffff
205     },
206     {
207 	OP_CREQV,
208 	0x0000ffff,
209 	0,
210 	0,
211 	0,
212 	0x8000ffff
213     },
214     {
215 	OP_CREQV,
216 	0x0000ffff,
217 	0,
218 	16,
219 	0,
220 	0x0000ffff
221     },
222 };
223 static unsigned int cpu_post_cr_size4 = ARRAY_SIZE(cpu_post_cr_table4);
224 
cpu_post_test_cr(void)225 int cpu_post_test_cr (void)
226 {
227     int ret = 0;
228     unsigned int i;
229     unsigned long cr_sav;
230     int flag = disable_interrupts();
231 
232     asm ( "mfcr %0" : "=r" (cr_sav) : );
233 
234     for (i = 0; i < cpu_post_cr_size1 && ret == 0; i++)
235     {
236 	ulong cr = cpu_post_cr_table1[i];
237 	ulong res;
238 
239 	unsigned long code[] =
240 	{
241 	    ASM_MTCR(3),
242 	    ASM_MFCR(3),
243 	    ASM_BLR,
244 	};
245 
246 	cpu_post_exec_11 (code, &res, cr);
247 
248 	ret = res == cr ? 0 : -1;
249 
250 	if (ret != 0)
251 	{
252 	    post_log ("Error at cr1 test %d !\n", i);
253 	}
254     }
255 
256     for (i = 0; i < cpu_post_cr_size2 && ret == 0; i++)
257     {
258 	struct cpu_post_cr_s2 *test = cpu_post_cr_table2 + i;
259 	ulong res;
260 	ulong xer;
261 
262 	unsigned long code[] =
263 	{
264 	    ASM_MTXER(3),
265 	    ASM_MCRXR(test->cr),
266 	    ASM_MFCR(3),
267 	    ASM_MFXER(4),
268 	    ASM_BLR,
269 	};
270 
271 	cpu_post_exec_21x (code, &res, &xer, test->xer);
272 
273 	ret = xer == 0 && ((res << (4 * test->cr)) & 0xe0000000) == test->xer ?
274 	      0 : -1;
275 
276 	if (ret != 0)
277 	{
278 	    post_log ("Error at cr2 test %d !\n", i);
279 	}
280     }
281 
282     for (i = 0; i < cpu_post_cr_size3 && ret == 0; i++)
283     {
284 	struct cpu_post_cr_s3 *test = cpu_post_cr_table3 + i;
285 	ulong res;
286 
287 	unsigned long code[] =
288 	{
289 	    ASM_MTCR(3),
290 	    ASM_MCRF(test->cd, test->cs),
291 	    ASM_MFCR(3),
292 	    ASM_BLR,
293 	};
294 
295 	cpu_post_exec_11 (code, &res, test->cr);
296 
297 	ret = res == test->res ? 0 : -1;
298 
299 	if (ret != 0)
300 	{
301 	    post_log ("Error at cr3 test %d !\n", i);
302 	}
303     }
304 
305     for (i = 0; i < cpu_post_cr_size4 && ret == 0; i++)
306     {
307 	struct cpu_post_cr_s4 *test = cpu_post_cr_table4 + i;
308 	ulong res;
309 
310 	unsigned long code[] =
311 	{
312 	    ASM_MTCR(3),
313 	    ASM_12F(test->cmd, test->op3, test->op1, test->op2),
314 	    ASM_MFCR(3),
315 	    ASM_BLR,
316 	};
317 
318 	cpu_post_exec_11 (code, &res, test->cr);
319 
320 	ret = res == test->res ? 0 : -1;
321 
322 	if (ret != 0)
323 	{
324 	    post_log ("Error at cr4 test %d !\n", i);
325 	}
326     }
327 
328     asm ( "mtcr %0" : : "r" (cr_sav));
329 
330     if (flag)
331 	enable_interrupts();
332 
333     return ret;
334 }
335 
336 #endif
337