Merge branch 'master' of git://git.denx.de/u-boot-nios
[oweals/u-boot.git] / post / lib_powerpc / store.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  * Store instructions:          stb(x)(u), sth(x)(u), stw(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 value of the index register and
38  * the value of the source register. After executing the
39  * instruction, the test verifies the contents of the array
40  * and the value of the base register (it must change for "store
41  * 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_12w (ulong *code, ulong *op1, ulong op2, ulong op3);
50 extern void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2);
51
52 static struct cpu_post_store_s
53 {
54     ulong cmd;
55     uint width;
56     int update;
57     int index;
58     ulong offset;
59     ulong value;
60 } cpu_post_store_table[] =
61 {
62     {
63         OP_STW,
64         4,
65         0,
66         0,
67         -4,
68         0xff00ff00
69     },
70     {
71         OP_STH,
72         2,
73         0,
74         0,
75         -2,
76         0xff00
77     },
78     {
79         OP_STB,
80         1,
81         0,
82         0,
83         -1,
84         0xff
85     },
86     {
87         OP_STWU,
88         4,
89         1,
90         0,
91         -4,
92         0xff00ff00
93     },
94     {
95         OP_STHU,
96         2,
97         1,
98         0,
99         -2,
100         0xff00
101     },
102     {
103         OP_STBU,
104         1,
105         1,
106         0,
107         -1,
108         0xff
109     },
110     {
111         OP_STWX,
112         4,
113         0,
114         1,
115         -4,
116         0xff00ff00
117     },
118     {
119         OP_STHX,
120         2,
121         0,
122         1,
123         -2,
124         0xff00
125     },
126     {
127         OP_STBX,
128         1,
129         0,
130         1,
131         -1,
132         0xff
133     },
134     {
135         OP_STWUX,
136         4,
137         1,
138         1,
139         -4,
140         0xff00ff00
141     },
142     {
143         OP_STHUX,
144         2,
145         1,
146         1,
147         -2,
148         0xff00
149     },
150     {
151         OP_STBUX,
152         1,
153         1,
154         1,
155         -1,
156         0xff
157     },
158 };
159 static unsigned int cpu_post_store_size = ARRAY_SIZE(cpu_post_store_table);
160
161 int cpu_post_test_store (void)
162 {
163     int ret = 0;
164     unsigned int i;
165     int flag = disable_interrupts();
166
167     for (i = 0; i < cpu_post_store_size && ret == 0; i++)
168     {
169         struct cpu_post_store_s *test = cpu_post_store_table + i;
170         uchar data[16] =
171         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
172         ulong base0 = (ulong) (data + 8);
173         ulong base = base0;
174
175         if (test->index)
176         {
177             ulong code[] =
178             {
179                 ASM_12(test->cmd, 5, 3, 4),
180                 ASM_BLR,
181             };
182
183             cpu_post_exec_12w (code, &base, test->offset, test->value);
184         }
185         else
186         {
187             ulong code[] =
188             {
189                 ASM_11I(test->cmd, 4, 3, test->offset),
190                 ASM_BLR,
191             };
192
193             cpu_post_exec_11w (code, &base, test->value);
194         }
195
196         if (ret == 0)
197         {
198            if (test->update)
199                ret = base == base0 + test->offset ? 0 : -1;
200            else
201                ret = base == base0 ? 0 : -1;
202         }
203
204         if (ret == 0)
205         {
206             switch (test->width)
207             {
208             case 1:
209                 ret = *(uchar *)(base0 + test->offset) == test->value ?
210                       0 : -1;
211                 break;
212             case 2:
213                 ret = *(ushort *)(base0 + test->offset) == test->value ?
214                       0 : -1;
215                 break;
216             case 4:
217                 ret = *(ulong *)(base0 + test->offset) == test->value ?
218                       0 : -1;
219                 break;
220             }
221         }
222
223         if (ret != 0)
224         {
225             post_log ("Error at store test %d !\n", i);
226         }
227     }
228
229     if (flag)
230         enable_interrupts();
231
232     return ret;
233 }
234
235 #endif