xref: /openbmc/u-boot/post/lib_powerpc/threex.c (revision dd1033e4)
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  * Ternary instructions		instr rA,rS,rB
12  *
13  * Logic instructions:		or, orc, xor, nand, nor, eqv
14  * Shift instructions:		slw, srw, sraw
15  *
16  * The test contains a pre-built table of instructions, operands and
17  * expected results. For each table entry, the test will cyclically use
18  * different sets of operand registers and result registers.
19  */
20 
21 #include <post.h>
22 #include "cpu_asm.h"
23 
24 #if CONFIG_POST & CONFIG_SYS_POST_CPU
25 
26 extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
27     ulong op2);
28 extern ulong cpu_post_makecr (long v);
29 
30 static struct cpu_post_threex_s
31 {
32     ulong cmd;
33     ulong op1;
34     ulong op2;
35     ulong res;
36 } cpu_post_threex_table[] =
37 {
38     {
39 	OP_OR,
40 	0x1234,
41 	0x5678,
42 	0x1234 | 0x5678
43     },
44     {
45 	OP_ORC,
46 	0x1234,
47 	0x5678,
48 	0x1234 | ~0x5678
49     },
50     {
51 	OP_XOR,
52 	0x1234,
53 	0x5678,
54 	0x1234 ^ 0x5678
55     },
56     {
57 	OP_NAND,
58 	0x1234,
59 	0x5678,
60 	~(0x1234 & 0x5678)
61     },
62     {
63 	OP_NOR,
64 	0x1234,
65 	0x5678,
66 	~(0x1234 | 0x5678)
67     },
68     {
69 	OP_EQV,
70 	0x1234,
71 	0x5678,
72 	~(0x1234 ^ 0x5678)
73     },
74     {
75 	OP_SLW,
76 	0x80,
77 	16,
78 	0x800000
79     },
80     {
81 	OP_SLW,
82 	0x80,
83 	32,
84 	0
85     },
86     {
87 	OP_SRW,
88 	0x800000,
89 	16,
90 	0x80
91     },
92     {
93 	OP_SRW,
94 	0x800000,
95 	32,
96 	0
97     },
98     {
99 	OP_SRAW,
100 	0x80000000,
101 	3,
102 	0xf0000000
103     },
104     {
105 	OP_SRAW,
106 	0x8000,
107 	3,
108 	0x1000
109     },
110 };
111 static unsigned int cpu_post_threex_size = ARRAY_SIZE(cpu_post_threex_table);
112 
113 int cpu_post_test_threex (void)
114 {
115     int ret = 0;
116     unsigned int i, reg;
117     int flag = disable_interrupts();
118 
119     for (i = 0; i < cpu_post_threex_size && ret == 0; i++)
120     {
121 	struct cpu_post_threex_s *test = cpu_post_threex_table + i;
122 
123 	for (reg = 0; reg < 32 && ret == 0; reg++)
124 	{
125 	    unsigned int reg0 = (reg + 0) % 32;
126 	    unsigned int reg1 = (reg + 1) % 32;
127 	    unsigned int reg2 = (reg + 2) % 32;
128 	    unsigned int stk = reg < 16 ? 31 : 15;
129 	    unsigned long code[] =
130 	    {
131 		ASM_STW(stk, 1, -4),
132 		ASM_ADDI(stk, 1, -24),
133 		ASM_STW(3, stk, 12),
134 		ASM_STW(4, stk, 16),
135 		ASM_STW(reg0, stk, 8),
136 		ASM_STW(reg1, stk, 4),
137 		ASM_STW(reg2, stk, 0),
138 		ASM_LWZ(reg1, stk, 12),
139 		ASM_LWZ(reg0, stk, 16),
140 		ASM_12X(test->cmd, reg2, reg1, reg0),
141 		ASM_STW(reg2, stk, 12),
142 		ASM_LWZ(reg2, stk, 0),
143 		ASM_LWZ(reg1, stk, 4),
144 		ASM_LWZ(reg0, stk, 8),
145 		ASM_LWZ(3, stk, 12),
146 		ASM_ADDI(1, stk, 24),
147 		ASM_LWZ(stk, 1, -4),
148 		ASM_BLR,
149 	    };
150 	    unsigned long codecr[] =
151 	    {
152 		ASM_STW(stk, 1, -4),
153 		ASM_ADDI(stk, 1, -24),
154 		ASM_STW(3, stk, 12),
155 		ASM_STW(4, stk, 16),
156 		ASM_STW(reg0, stk, 8),
157 		ASM_STW(reg1, stk, 4),
158 		ASM_STW(reg2, stk, 0),
159 		ASM_LWZ(reg1, stk, 12),
160 		ASM_LWZ(reg0, stk, 16),
161 		ASM_12X(test->cmd, reg2, reg1, reg0) | BIT_C,
162 		ASM_STW(reg2, stk, 12),
163 		ASM_LWZ(reg2, stk, 0),
164 		ASM_LWZ(reg1, stk, 4),
165 		ASM_LWZ(reg0, stk, 8),
166 		ASM_LWZ(3, stk, 12),
167 		ASM_ADDI(1, stk, 24),
168 		ASM_LWZ(stk, 1, -4),
169 		ASM_BLR,
170 	    };
171 	    ulong res;
172 	    ulong cr;
173 
174 	    if (ret == 0)
175 	    {
176 		cr = 0;
177 		cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
178 
179 		ret = res == test->res && cr == 0 ? 0 : -1;
180 
181 		if (ret != 0)
182 		{
183 		    post_log ("Error at threex test %d !\n", i);
184 		}
185 	    }
186 
187 	    if (ret == 0)
188 	    {
189 		cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
190 
191 		ret = res == test->res &&
192 		      (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
193 
194 		if (ret != 0)
195 		{
196 		    post_log ("Error at threex test %d !\n", i);
197 		}
198 	    }
199 	}
200     }
201 
202     if (flag)
203 	enable_interrupts();
204 
205     return ret;
206 }
207 
208 #endif
209