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