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