1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2002
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 */
6
7 #include <common.h>
8
9 /*
10 * CPU test
11 * Store instructions: stb(x)(u), sth(x)(u), stw(x)(u)
12 *
13 * All operations are performed on a 16-byte array. The array
14 * is 4-byte aligned. The base register points to offset 8.
15 * The immediate offset (index register) ranges in [-8 ... +7].
16 * The test cases are composed so that they do not
17 * cause alignment exceptions.
18 * The test contains a pre-built table describing all test cases.
19 * The table entry contains:
20 * the instruction opcode, the value of the index register and
21 * the value of the source register. After executing the
22 * instruction, the test verifies the contents of the array
23 * and the value of the base register (it must change for "store
24 * with update" instructions).
25 */
26
27 #include <post.h>
28 #include "cpu_asm.h"
29
30 #if CONFIG_POST & CONFIG_SYS_POST_CPU
31
32 extern void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3);
33 extern void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2);
34
35 static struct cpu_post_store_s
36 {
37 ulong cmd;
38 uint width;
39 int update;
40 int index;
41 ulong offset;
42 ulong value;
43 } cpu_post_store_table[] =
44 {
45 {
46 OP_STW,
47 4,
48 0,
49 0,
50 -4,
51 0xff00ff00
52 },
53 {
54 OP_STH,
55 2,
56 0,
57 0,
58 -2,
59 0xff00
60 },
61 {
62 OP_STB,
63 1,
64 0,
65 0,
66 -1,
67 0xff
68 },
69 {
70 OP_STWU,
71 4,
72 1,
73 0,
74 -4,
75 0xff00ff00
76 },
77 {
78 OP_STHU,
79 2,
80 1,
81 0,
82 -2,
83 0xff00
84 },
85 {
86 OP_STBU,
87 1,
88 1,
89 0,
90 -1,
91 0xff
92 },
93 {
94 OP_STWX,
95 4,
96 0,
97 1,
98 -4,
99 0xff00ff00
100 },
101 {
102 OP_STHX,
103 2,
104 0,
105 1,
106 -2,
107 0xff00
108 },
109 {
110 OP_STBX,
111 1,
112 0,
113 1,
114 -1,
115 0xff
116 },
117 {
118 OP_STWUX,
119 4,
120 1,
121 1,
122 -4,
123 0xff00ff00
124 },
125 {
126 OP_STHUX,
127 2,
128 1,
129 1,
130 -2,
131 0xff00
132 },
133 {
134 OP_STBUX,
135 1,
136 1,
137 1,
138 -1,
139 0xff
140 },
141 };
142 static unsigned int cpu_post_store_size = ARRAY_SIZE(cpu_post_store_table);
143
cpu_post_test_store(void)144 int cpu_post_test_store (void)
145 {
146 int ret = 0;
147 unsigned int i;
148 int flag = disable_interrupts();
149
150 for (i = 0; i < cpu_post_store_size && ret == 0; i++)
151 {
152 struct cpu_post_store_s *test = cpu_post_store_table + i;
153 uchar data[16] =
154 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
155 ulong base0 = (ulong) (data + 8);
156 ulong base = base0;
157
158 if (test->index)
159 {
160 ulong code[] =
161 {
162 ASM_12(test->cmd, 5, 3, 4),
163 ASM_BLR,
164 };
165
166 cpu_post_exec_12w (code, &base, test->offset, test->value);
167 }
168 else
169 {
170 ulong code[] =
171 {
172 ASM_11I(test->cmd, 4, 3, test->offset),
173 ASM_BLR,
174 };
175
176 cpu_post_exec_11w (code, &base, test->value);
177 }
178
179 if (ret == 0)
180 {
181 if (test->update)
182 ret = base == base0 + test->offset ? 0 : -1;
183 else
184 ret = base == base0 ? 0 : -1;
185 }
186
187 if (ret == 0)
188 {
189 switch (test->width)
190 {
191 case 1:
192 ret = *(uchar *)(base0 + test->offset) == test->value ?
193 0 : -1;
194 break;
195 case 2:
196 ret = *(ushort *)(base0 + test->offset) == test->value ?
197 0 : -1;
198 break;
199 case 4:
200 ret = *(ulong *)(base0 + test->offset) == test->value ?
201 0 : -1;
202 break;
203 }
204 }
205
206 if (ret != 0)
207 {
208 post_log ("Error at store test %d !\n", i);
209 }
210 }
211
212 if (flag)
213 enable_interrupts();
214
215 return ret;
216 }
217
218 #endif
219