]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - post/lib_powerpc/load.c
Merge branch 'next' of ../next
[karo-tx-uboot.git] / post / lib_powerpc / load.c
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