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