Merge branch 'master' of git://git.denx.de/u-boot-i2c
[oweals/u-boot.git] / post / lib_powerpc / store.c
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
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