]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
ad5bb451 WD |
2 | /* |
3 | * (C) Copyright 2002 | |
4 | * Wolfgang Denk, DENX Software Engineering, [email protected]. | |
ad5bb451 WD |
5 | */ |
6 | ||
7 | #include <common.h> | |
8 | ||
9 | /* | |
10 | * CPU test | |
11 | * Branch instructions: b, bl, bc | |
12 | * | |
13 | * The first 2 instructions (b, bl) are verified by jumping | |
a6f70a3d | 14 | * to a fixed address and checking whether control was transferred |
ad5bb451 WD |
15 | * to that very point. For the bl instruction the value of the |
16 | * link register is checked as well (using mfspr). | |
17 | * To verify the bc instruction various combinations of the BI/BO | |
18 | * fields, the CTR and the condition register values are | |
19 | * checked. The list of such combinations is pre-built and | |
20 | * linked in U-Boot at build time. | |
21 | */ | |
22 | ||
ad5bb451 WD |
23 | #include <post.h> |
24 | #include "cpu_asm.h" | |
25 | ||
6d0f6bcf | 26 | #if CONFIG_POST & CONFIG_SYS_POST_CPU |
ad5bb451 WD |
27 | |
28 | extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); | |
29 | extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump, | |
30 | ulong cr); | |
31 | ||
32 | static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi, | |
a11e0696 | 33 | int pjump, int decr, int link, ulong pctr, ulong cr) |
ad5bb451 WD |
34 | { |
35 | int ret = 0; | |
36 | ulong lr = 0; | |
37 | ulong ctr = pctr; | |
38 | ulong jump; | |
39 | ||
40 | unsigned long code[] = | |
41 | { | |
42 | ASM_MTCR(6), | |
43 | ASM_MFLR(6), | |
44 | ASM_MTCTR(3), | |
45 | ASM_MTLR(4), | |
46 | ASM_LI(5, 1), | |
47 | ASM_3O(cmd, bo, bi, 8), | |
48 | ASM_LI(5, 0), | |
49 | ASM_MFCTR(3), | |
50 | ASM_MFLR(4), | |
51 | ASM_MTLR(6), | |
52 | ASM_BLR, | |
53 | }; | |
54 | ||
55 | cpu_post_exec_31 (code, &ctr, &lr, &jump, cr); | |
56 | ||
57 | if (ret == 0) | |
58 | ret = pjump == jump ? 0 : -1; | |
59 | if (ret == 0) | |
60 | { | |
a11e0696 | 61 | if (decr) |
ad5bb451 WD |
62 | ret = pctr == ctr + 1 ? 0 : -1; |
63 | else | |
64 | ret = pctr == ctr ? 0 : -1; | |
65 | } | |
66 | if (ret == 0) | |
67 | { | |
68 | if (link) | |
69 | ret = lr == (ulong) code + 24 ? 0 : -1; | |
70 | else | |
71 | ret = lr == 0 ? 0 : -1; | |
72 | } | |
73 | ||
74 | return ret; | |
75 | } | |
76 | ||
77 | int cpu_post_test_b (void) | |
78 | { | |
79 | int ret = 0; | |
80 | unsigned int i; | |
f2302d44 | 81 | int flag = disable_interrupts(); |
ad5bb451 WD |
82 | |
83 | if (ret == 0) | |
84 | { | |
85 | ulong code[] = | |
86 | { | |
87 | ASM_MFLR(4), | |
88 | ASM_MTLR(3), | |
89 | ASM_B(4), | |
90 | ASM_MFLR(3), | |
91 | ASM_MTLR(4), | |
92 | ASM_BLR, | |
93 | }; | |
94 | ulong res; | |
95 | ||
96 | cpu_post_exec_11 (code, &res, 0); | |
97 | ||
98 | ret = res == 0 ? 0 : -1; | |
99 | ||
100 | if (ret != 0) | |
101 | { | |
102 | post_log ("Error at b1 test !\n"); | |
103 | } | |
104 | } | |
105 | ||
106 | if (ret == 0) | |
107 | { | |
108 | ulong code[] = | |
109 | { | |
110 | ASM_MFLR(4), | |
111 | ASM_MTLR(3), | |
112 | ASM_BL(4), | |
113 | ASM_MFLR(3), | |
114 | ASM_MTLR(4), | |
115 | ASM_BLR, | |
116 | }; | |
117 | ulong res; | |
118 | ||
119 | cpu_post_exec_11 (code, &res, 0); | |
120 | ||
121 | ret = res == (ulong)code + 12 ? 0 : -1; | |
122 | ||
123 | if (ret != 0) | |
124 | { | |
125 | post_log ("Error at b2 test !\n"); | |
126 | } | |
127 | } | |
128 | ||
129 | if (ret == 0) | |
130 | { | |
131 | ulong cc, cd; | |
132 | int cond; | |
133 | ulong ctr; | |
134 | int link; | |
135 | ||
136 | i = 0; | |
137 | ||
138 | for (cc = 0; cc < 4 && ret == 0; cc++) | |
139 | { | |
140 | for (cd = 0; cd < 4 && ret == 0; cd++) | |
141 | { | |
142 | for (link = 0; link <= 1 && ret == 0; link++) | |
143 | { | |
144 | for (cond = 0; cond <= 1 && ret == 0; cond++) | |
145 | { | |
146 | for (ctr = 1; ctr <= 2 && ret == 0; ctr++) | |
147 | { | |
a11e0696 | 148 | int decr = cd < 2; |
ad5bb451 WD |
149 | int cr = cond ? 0x80000000 : 0x00000000; |
150 | int jumpc = cc >= 2 || | |
151 | (cc == 0 && !cond) || | |
152 | (cc == 1 && cond); | |
153 | int jumpd = cd >= 2 || | |
154 | (cd == 0 && ctr != 1) || | |
155 | (cd == 1 && ctr == 1); | |
156 | int jump = jumpc && jumpd; | |
157 | ||
158 | ret = cpu_post_test_bc (link ? OP_BCL : OP_BC, | |
a11e0696 | 159 | (cc << 3) + (cd << 1), 0, jump, decr, link, |
ad5bb451 WD |
160 | ctr, cr); |
161 | ||
162 | if (ret != 0) | |
163 | { | |
164 | post_log ("Error at b3 test %d !\n", i); | |
165 | } | |
166 | ||
167 | i++; | |
168 | } | |
169 | } | |
170 | } | |
171 | } | |
172 | } | |
173 | } | |
174 | ||
f2302d44 SR |
175 | if (flag) |
176 | enable_interrupts(); | |
177 | ||
ad5bb451 WD |
178 | return ret; |
179 | } | |
180 | ||
181 | #endif |