Add missing CHANGELOG entry.
[oweals/u-boot.git] / post / cpu / 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 #ifdef CONFIG_POST
45
46 #include <post.h>
47 #include "cpu_asm.h"
48
49 #if CONFIG_POST & CFG_POST_CPU
50
51 extern void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3);
52 extern void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2);
53
54 static struct cpu_post_load_s
55 {
56     ulong cmd;
57     uint width;
58     int update;
59     int index;
60     ulong offset;
61 } cpu_post_load_table[] =
62 {
63     {
64         OP_LWZ,
65         4,
66         0,
67         0,
68         4
69     },
70     {
71         OP_LHA,
72         3,
73         0,
74         0,
75         2
76     },
77     {
78         OP_LHZ,
79         2,
80         0,
81         0,
82         2
83     },
84     {
85         OP_LBZ,
86         1,
87         0,
88         0,
89         1
90     },
91     {
92         OP_LWZU,
93         4,
94         1,
95         0,
96         4
97     },
98     {
99         OP_LHAU,
100         3,
101         1,
102         0,
103         2
104     },
105     {
106         OP_LHZU,
107         2,
108         1,
109         0,
110         2
111     },
112     {
113         OP_LBZU,
114         1,
115         1,
116         0,
117         1
118     },
119     {
120         OP_LWZX,
121         4,
122         0,
123         1,
124         4
125     },
126     {
127         OP_LHAX,
128         3,
129         0,
130         1,
131         2
132     },
133     {
134         OP_LHZX,
135         2,
136         0,
137         1,
138         2
139     },
140     {
141         OP_LBZX,
142         1,
143         0,
144         1,
145         1
146     },
147     {
148         OP_LWZUX,
149         4,
150         1,
151         1,
152         4
153     },
154     {
155         OP_LHAUX,
156         3,
157         1,
158         1,
159         2
160     },
161     {
162         OP_LHZUX,
163         2,
164         1,
165         1,
166         2
167     },
168     {
169         OP_LBZUX,
170         1,
171         1,
172         1,
173         1
174     },
175 };
176 static unsigned int cpu_post_load_size =
177     sizeof (cpu_post_load_table) / sizeof (struct cpu_post_load_s);
178
179 int cpu_post_test_load (void)
180 {
181     int ret = 0;
182     unsigned int i;
183
184     for (i = 0; i < cpu_post_load_size && ret == 0; i++)
185     {
186         struct cpu_post_load_s *test = cpu_post_load_table + i;
187         uchar data[16] =
188         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
189         ulong base0 = (ulong) (data + 8);
190         ulong base = base0;
191         ulong value;
192
193         if (test->index)
194         {
195             ulong code[] =
196             {
197                 ASM_12(test->cmd, 5, 3, 4),
198                 ASM_BLR,
199             };
200
201             cpu_post_exec_22w (code, &base, test->offset, &value);
202         }
203         else
204         {
205             ulong code[] =
206             {
207                 ASM_11I(test->cmd, 4, 3, test->offset),
208                 ASM_BLR,
209             };
210
211             cpu_post_exec_21w (code, &base, &value);
212         }
213
214         if (ret == 0)
215         {
216            if (test->update)
217                ret = base == base0 + test->offset ? 0 : -1;
218            else
219                ret = base == base0 ? 0 : -1;
220         }
221
222         if (ret == 0)
223         {
224             switch (test->width)
225             {
226             case 1:
227                 ret = *(uchar *)(base0 + test->offset) == value ?
228                       0 : -1;
229                 break;
230             case 2:
231                 ret = *(ushort *)(base0 + test->offset) == value ?
232                       0 : -1;
233                 break;
234             case 3:
235                 ret = *(short *)(base0 + test->offset) == value ?
236                       0 : -1;
237                 break;
238             case 4:
239                 ret = *(ulong *)(base0 + test->offset) == value ?
240                       0 : -1;
241                 break;
242             }
243         }
244
245         if (ret != 0)
246         {
247             post_log ("Error at load test %d !\n", i);
248         }
249     }
250
251     return ret;
252 }
253
254 #endif
255 #endif