xref: /openbmc/u-boot/post/lib_powerpc/store.c (revision 4e3349b6)
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
236