xref: /openbmc/u-boot/post/lib_powerpc/load.c (revision a71d45d7)
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  * Load instructions:		lbz(x)(u), lhz(x)(u), lha(x)(u), lwz(x)(u)
29  *
30  * All operations are performed on a 16-byte array. The array
31  * is 4-byte aligned. The base register points to offset 8.
32  * The immediate offset (index register) ranges in [-8 ... +7].
33  * The test cases are composed so that they do not
34  * cause alignment exceptions.
35  * The test contains a pre-built table describing all test cases.
36  * The table entry contains:
37  * the instruction opcode, the array contents, the value of the index
38  * register and the expected value of the destination register.
39  * After executing the instruction, the test verifies the
40  * value of the destination register and the value of the base
41  * register (it must change for "load with update" instructions).
42  */
43 
44 #include <post.h>
45 #include "cpu_asm.h"
46 
47 #if CONFIG_POST & CONFIG_SYS_POST_CPU
48 
49 extern void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3);
50 extern void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2);
51 
52 static struct cpu_post_load_s
53 {
54     ulong cmd;
55     uint width;
56     int update;
57     int index;
58     ulong offset;
59 } cpu_post_load_table[] =
60 {
61     {
62 	OP_LWZ,
63 	4,
64 	0,
65 	0,
66 	4
67     },
68     {
69 	OP_LHA,
70 	3,
71 	0,
72 	0,
73 	2
74     },
75     {
76 	OP_LHZ,
77 	2,
78 	0,
79 	0,
80 	2
81     },
82     {
83 	OP_LBZ,
84 	1,
85 	0,
86 	0,
87 	1
88     },
89     {
90 	OP_LWZU,
91 	4,
92 	1,
93 	0,
94 	4
95     },
96     {
97 	OP_LHAU,
98 	3,
99 	1,
100 	0,
101 	2
102     },
103     {
104 	OP_LHZU,
105 	2,
106 	1,
107 	0,
108 	2
109     },
110     {
111 	OP_LBZU,
112 	1,
113 	1,
114 	0,
115 	1
116     },
117     {
118 	OP_LWZX,
119 	4,
120 	0,
121 	1,
122 	4
123     },
124     {
125 	OP_LHAX,
126 	3,
127 	0,
128 	1,
129 	2
130     },
131     {
132 	OP_LHZX,
133 	2,
134 	0,
135 	1,
136 	2
137     },
138     {
139 	OP_LBZX,
140 	1,
141 	0,
142 	1,
143 	1
144     },
145     {
146 	OP_LWZUX,
147 	4,
148 	1,
149 	1,
150 	4
151     },
152     {
153 	OP_LHAUX,
154 	3,
155 	1,
156 	1,
157 	2
158     },
159     {
160 	OP_LHZUX,
161 	2,
162 	1,
163 	1,
164 	2
165     },
166     {
167 	OP_LBZUX,
168 	1,
169 	1,
170 	1,
171 	1
172     },
173 };
174 static unsigned int cpu_post_load_size = ARRAY_SIZE(cpu_post_load_table);
175 
176 int cpu_post_test_load (void)
177 {
178     int ret = 0;
179     unsigned int i;
180     int flag = disable_interrupts();
181 
182     for (i = 0; i < cpu_post_load_size && ret == 0; i++)
183     {
184 	struct cpu_post_load_s *test = cpu_post_load_table + i;
185 	uchar data[16] =
186 	{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
187 	ulong base0 = (ulong) (data + 8);
188 	ulong base = base0;
189 	ulong value;
190 
191 	if (test->index)
192 	{
193 	    ulong code[] =
194 	    {
195 		ASM_12(test->cmd, 5, 3, 4),
196 		ASM_BLR,
197 	    };
198 
199 	    cpu_post_exec_22w (code, &base, test->offset, &value);
200 	}
201 	else
202 	{
203 	    ulong code[] =
204 	    {
205 		ASM_11I(test->cmd, 4, 3, test->offset),
206 		ASM_BLR,
207 	    };
208 
209 	    cpu_post_exec_21w (code, &base, &value);
210 	}
211 
212 	if (ret == 0)
213 	{
214 	   if (test->update)
215 	       ret = base == base0 + test->offset ? 0 : -1;
216 	   else
217 	       ret = base == base0 ? 0 : -1;
218 	}
219 
220 	if (ret == 0)
221 	{
222 	    switch (test->width)
223 	    {
224 	    case 1:
225 		ret = *(uchar *)(base0 + test->offset) == value ?
226 		      0 : -1;
227 		break;
228 	    case 2:
229 		ret = *(ushort *)(base0 + test->offset) == value ?
230 		      0 : -1;
231 		break;
232 	    case 3:
233 		ret = *(short *)(base0 + test->offset) == value ?
234 		      0 : -1;
235 		break;
236 	    case 4:
237 		ret = *(ulong *)(base0 + test->offset) == value ?
238 		      0 : -1;
239 		break;
240 	    }
241 	}
242 
243 	if (ret != 0)
244 	{
245 	    post_log ("Error at load test %d !\n", i);
246 	}
247     }
248 
249     if (flag)
250 	enable_interrupts();
251 
252     return ret;
253 }
254 
255 #endif
256