]>
Commit | Line | Data |
---|---|---|
ad5bb451 WD |
1 | /* |
2 | * (C) Copyright 2002 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | #include <common.h> | |
25 | ||
26 | /* | |
27 | * CPU test | |
28 | * Branch instructions: b, bl, bc | |
29 | * | |
30 | * The first 2 instructions (b, bl) are verified by jumping | |
31 | * to a fixed address and checking whether control was transfered | |
32 | * to that very point. For the bl instruction the value of the | |
33 | * link register is checked as well (using mfspr). | |
34 | * To verify the bc instruction various combinations of the BI/BO | |
35 | * fields, the CTR and the condition register values are | |
36 | * checked. The list of such combinations is pre-built and | |
37 | * linked in U-Boot at build time. | |
38 | */ | |
39 | ||
ad5bb451 WD |
40 | #include <post.h> |
41 | #include "cpu_asm.h" | |
42 | ||
6d0f6bcf | 43 | #if CONFIG_POST & CONFIG_SYS_POST_CPU |
ad5bb451 WD |
44 | |
45 | extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); | |
46 | extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump, | |
47 | ulong cr); | |
48 | ||
49 | static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi, | |
a11e0696 | 50 | int pjump, int decr, int link, ulong pctr, ulong cr) |
ad5bb451 WD |
51 | { |
52 | int ret = 0; | |
53 | ulong lr = 0; | |
54 | ulong ctr = pctr; | |
55 | ulong jump; | |
56 | ||
57 | unsigned long code[] = | |
58 | { | |
59 | ASM_MTCR(6), | |
60 | ASM_MFLR(6), | |
61 | ASM_MTCTR(3), | |
62 | ASM_MTLR(4), | |
63 | ASM_LI(5, 1), | |
64 | ASM_3O(cmd, bo, bi, 8), | |
65 | ASM_LI(5, 0), | |
66 | ASM_MFCTR(3), | |
67 | ASM_MFLR(4), | |
68 | ASM_MTLR(6), | |
69 | ASM_BLR, | |
70 | }; | |
71 | ||
72 | cpu_post_exec_31 (code, &ctr, &lr, &jump, cr); | |
73 | ||
74 | if (ret == 0) | |
75 | ret = pjump == jump ? 0 : -1; | |
76 | if (ret == 0) | |
77 | { | |
a11e0696 | 78 | if (decr) |
ad5bb451 WD |
79 | ret = pctr == ctr + 1 ? 0 : -1; |
80 | else | |
81 | ret = pctr == ctr ? 0 : -1; | |
82 | } | |
83 | if (ret == 0) | |
84 | { | |
85 | if (link) | |
86 | ret = lr == (ulong) code + 24 ? 0 : -1; | |
87 | else | |
88 | ret = lr == 0 ? 0 : -1; | |
89 | } | |
90 | ||
91 | return ret; | |
92 | } | |
93 | ||
94 | int cpu_post_test_b (void) | |
95 | { | |
96 | int ret = 0; | |
97 | unsigned int i; | |
f2302d44 | 98 | int flag = disable_interrupts(); |
ad5bb451 WD |
99 | |
100 | if (ret == 0) | |
101 | { | |
102 | ulong code[] = | |
103 | { | |
104 | ASM_MFLR(4), | |
105 | ASM_MTLR(3), | |
106 | ASM_B(4), | |
107 | ASM_MFLR(3), | |
108 | ASM_MTLR(4), | |
109 | ASM_BLR, | |
110 | }; | |
111 | ulong res; | |
112 | ||
113 | cpu_post_exec_11 (code, &res, 0); | |
114 | ||
115 | ret = res == 0 ? 0 : -1; | |
116 | ||
117 | if (ret != 0) | |
118 | { | |
119 | post_log ("Error at b1 test !\n"); | |
120 | } | |
121 | } | |
122 | ||
123 | if (ret == 0) | |
124 | { | |
125 | ulong code[] = | |
126 | { | |
127 | ASM_MFLR(4), | |
128 | ASM_MTLR(3), | |
129 | ASM_BL(4), | |
130 | ASM_MFLR(3), | |
131 | ASM_MTLR(4), | |
132 | ASM_BLR, | |
133 | }; | |
134 | ulong res; | |
135 | ||
136 | cpu_post_exec_11 (code, &res, 0); | |
137 | ||
138 | ret = res == (ulong)code + 12 ? 0 : -1; | |
139 | ||
140 | if (ret != 0) | |
141 | { | |
142 | post_log ("Error at b2 test !\n"); | |
143 | } | |
144 | } | |
145 | ||
146 | if (ret == 0) | |
147 | { | |
148 | ulong cc, cd; | |
149 | int cond; | |
150 | ulong ctr; | |
151 | int link; | |
152 | ||
153 | i = 0; | |
154 | ||
155 | for (cc = 0; cc < 4 && ret == 0; cc++) | |
156 | { | |
157 | for (cd = 0; cd < 4 && ret == 0; cd++) | |
158 | { | |
159 | for (link = 0; link <= 1 && ret == 0; link++) | |
160 | { | |
161 | for (cond = 0; cond <= 1 && ret == 0; cond++) | |
162 | { | |
163 | for (ctr = 1; ctr <= 2 && ret == 0; ctr++) | |
164 | { | |
a11e0696 | 165 | int decr = cd < 2; |
ad5bb451 WD |
166 | int cr = cond ? 0x80000000 : 0x00000000; |
167 | int jumpc = cc >= 2 || | |
168 | (cc == 0 && !cond) || | |
169 | (cc == 1 && cond); | |
170 | int jumpd = cd >= 2 || | |
171 | (cd == 0 && ctr != 1) || | |
172 | (cd == 1 && ctr == 1); | |
173 | int jump = jumpc && jumpd; | |
174 | ||
175 | ret = cpu_post_test_bc (link ? OP_BCL : OP_BC, | |
a11e0696 | 176 | (cc << 3) + (cd << 1), 0, jump, decr, link, |
ad5bb451 WD |
177 | ctr, cr); |
178 | ||
179 | if (ret != 0) | |
180 | { | |
181 | post_log ("Error at b3 test %d !\n", i); | |
182 | } | |
183 | ||
184 | i++; | |
185 | } | |
186 | } | |
187 | } | |
188 | } | |
189 | } | |
190 | } | |
191 | ||
f2302d44 SR |
192 | if (flag) |
193 | enable_interrupts(); | |
194 | ||
ad5bb451 WD |
195 | return ret; |
196 | } | |
197 | ||
198 | #endif |