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