Merge branch 'master' of git://git.denx.de/u-boot-video
[platform/kernel/u-boot.git] / post / lib_ppc / 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 =
175     sizeof (cpu_post_load_table) / sizeof (struct cpu_post_load_s);
176
177 int cpu_post_test_load (void)
178 {
179     int ret = 0;
180     unsigned int i;
181     int flag = disable_interrupts();
182
183     for (i = 0; i < cpu_post_load_size && ret == 0; i++)
184     {
185         struct cpu_post_load_s *test = cpu_post_load_table + i;
186         uchar data[16] =
187         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
188         ulong base0 = (ulong) (data + 8);
189         ulong base = base0;
190         ulong value;
191
192         if (test->index)
193         {
194             ulong code[] =
195             {
196                 ASM_12(test->cmd, 5, 3, 4),
197                 ASM_BLR,
198             };
199
200             cpu_post_exec_22w (code, &base, test->offset, &value);
201         }
202         else
203         {
204             ulong code[] =
205             {
206                 ASM_11I(test->cmd, 4, 3, test->offset),
207                 ASM_BLR,
208             };
209
210             cpu_post_exec_21w (code, &base, &value);
211         }
212
213         if (ret == 0)
214         {
215            if (test->update)
216                ret = base == base0 + test->offset ? 0 : -1;
217            else
218                ret = base == base0 ? 0 : -1;
219         }
220
221         if (ret == 0)
222         {
223             switch (test->width)
224             {
225             case 1:
226                 ret = *(uchar *)(base0 + test->offset) == value ?
227                       0 : -1;
228                 break;
229             case 2:
230                 ret = *(ushort *)(base0 + test->offset) == value ?
231                       0 : -1;
232                 break;
233             case 3:
234                 ret = *(short *)(base0 + test->offset) == value ?
235                       0 : -1;
236                 break;
237             case 4:
238                 ret = *(ulong *)(base0 + test->offset) == value ?
239                       0 : -1;
240                 break;
241             }
242         }
243
244         if (ret != 0)
245         {
246             post_log ("Error at load test %d !\n", i);
247         }
248     }
249
250     if (flag)
251         enable_interrupts();
252
253     return ret;
254 }
255
256 #endif