3fbd8babfa5685edcd594a9d5075c4fd7bfa12b9
[oweals/u-boot.git] / post / lib_powerpc / load.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  * Load instructions:           lbz(x)(u), lhz(x)(u), lha(x)(u), lwz(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 array contents, the value of the index
21  * register and the expected value of the destination register.
22  * After executing the instruction, the test verifies the
23  * value of the destination register and the value of the base
24  * register (it must change for "load 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_22w (ulong *code, ulong *op1, ulong op2, ulong *op3);
33 extern void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2);
34
35 static struct cpu_post_load_s
36 {
37     ulong cmd;
38     uint width;
39     int update;
40     int index;
41     ulong offset;
42 } cpu_post_load_table[] =
43 {
44     {
45         OP_LWZ,
46         4,
47         0,
48         0,
49         4
50     },
51     {
52         OP_LHA,
53         3,
54         0,
55         0,
56         2
57     },
58     {
59         OP_LHZ,
60         2,
61         0,
62         0,
63         2
64     },
65     {
66         OP_LBZ,
67         1,
68         0,
69         0,
70         1
71     },
72     {
73         OP_LWZU,
74         4,
75         1,
76         0,
77         4
78     },
79     {
80         OP_LHAU,
81         3,
82         1,
83         0,
84         2
85     },
86     {
87         OP_LHZU,
88         2,
89         1,
90         0,
91         2
92     },
93     {
94         OP_LBZU,
95         1,
96         1,
97         0,
98         1
99     },
100     {
101         OP_LWZX,
102         4,
103         0,
104         1,
105         4
106     },
107     {
108         OP_LHAX,
109         3,
110         0,
111         1,
112         2
113     },
114     {
115         OP_LHZX,
116         2,
117         0,
118         1,
119         2
120     },
121     {
122         OP_LBZX,
123         1,
124         0,
125         1,
126         1
127     },
128     {
129         OP_LWZUX,
130         4,
131         1,
132         1,
133         4
134     },
135     {
136         OP_LHAUX,
137         3,
138         1,
139         1,
140         2
141     },
142     {
143         OP_LHZUX,
144         2,
145         1,
146         1,
147         2
148     },
149     {
150         OP_LBZUX,
151         1,
152         1,
153         1,
154         1
155     },
156 };
157 static unsigned int cpu_post_load_size = ARRAY_SIZE(cpu_post_load_table);
158
159 int cpu_post_test_load (void)
160 {
161     int ret = 0;
162     unsigned int i;
163     int flag = disable_interrupts();
164
165     for (i = 0; i < cpu_post_load_size && ret == 0; i++)
166     {
167         struct cpu_post_load_s *test = cpu_post_load_table + i;
168         uchar data[16] =
169         { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
170         ulong base0 = (ulong) (data + 8);
171         ulong base = base0;
172         ulong value;
173
174         if (test->index)
175         {
176             ulong code[] =
177             {
178                 ASM_12(test->cmd, 5, 3, 4),
179                 ASM_BLR,
180             };
181
182             cpu_post_exec_22w (code, &base, test->offset, &value);
183         }
184         else
185         {
186             ulong code[] =
187             {
188                 ASM_11I(test->cmd, 4, 3, test->offset),
189                 ASM_BLR,
190             };
191
192             cpu_post_exec_21w (code, &base, &value);
193         }
194
195         if (ret == 0)
196         {
197            if (test->update)
198                ret = base == base0 + test->offset ? 0 : -1;
199            else
200                ret = base == base0 ? 0 : -1;
201         }
202
203         if (ret == 0)
204         {
205             switch (test->width)
206             {
207             case 1:
208                 ret = *(uchar *)(base0 + test->offset) == value ?
209                       0 : -1;
210                 break;
211             case 2:
212                 ret = *(ushort *)(base0 + test->offset) == value ?
213                       0 : -1;
214                 break;
215             case 3:
216                 ret = *(short *)(base0 + test->offset) == value ?
217                       0 : -1;
218                 break;
219             case 4:
220                 ret = *(ulong *)(base0 + test->offset) == value ?
221                       0 : -1;
222                 break;
223             }
224         }
225
226         if (ret != 0)
227         {
228             post_log ("Error at load test %d !\n", i);
229         }
230     }
231
232     if (flag)
233         enable_interrupts();
234
235     return ret;
236 }
237
238 #endif