Define ffs/fls for all architectures
[platform/kernel/u-boot.git] / post / lib_ppc / 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 =
160     sizeof (cpu_post_store_table) / sizeof (struct cpu_post_store_s);
161
162 int cpu_post_test_store (void)
163 {
164     int ret = 0;
165     unsigned int i;
166     int flag = disable_interrupts();
167
168     for (i = 0; i < cpu_post_store_size && ret == 0; i++)
169     {
170         struct cpu_post_store_s *test = cpu_post_store_table + i;
171         uchar data[16] =
172         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
173         ulong base0 = (ulong) (data + 8);
174         ulong base = base0;
175
176         if (test->index)
177         {
178             ulong code[] =
179             {
180                 ASM_12(test->cmd, 5, 3, 4),
181                 ASM_BLR,
182             };
183
184             cpu_post_exec_12w (code, &base, test->offset, test->value);
185         }
186         else
187         {
188             ulong code[] =
189             {
190                 ASM_11I(test->cmd, 4, 3, test->offset),
191                 ASM_BLR,
192             };
193
194             cpu_post_exec_11w (code, &base, test->value);
195         }
196
197         if (ret == 0)
198         {
199            if (test->update)
200                ret = base == base0 + test->offset ? 0 : -1;
201            else
202                ret = base == base0 ? 0 : -1;
203         }
204
205         if (ret == 0)
206         {
207             switch (test->width)
208             {
209             case 1:
210                 ret = *(uchar *)(base0 + test->offset) == test->value ?
211                       0 : -1;
212                 break;
213             case 2:
214                 ret = *(ushort *)(base0 + test->offset) == test->value ?
215                       0 : -1;
216                 break;
217             case 4:
218                 ret = *(ulong *)(base0 + test->offset) == test->value ?
219                       0 : -1;
220                 break;
221             }
222         }
223
224         if (ret != 0)
225         {
226             post_log ("Error at store test %d !\n", i);
227         }
228     }
229
230     if (flag)
231         enable_interrupts();
232
233     return ret;
234 }
235
236 #endif