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