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