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