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