1 /* 2 * (C) Copyright 2002 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 10 /* 11 * CPU test 12 * Condition register istructions: mtcr, mfcr, mcrxr, 13 * crand, crandc, cror, crorc, crxor, 14 * crnand, crnor, creqv, mcrf 15 * 16 * The mtcrf/mfcr instructions is tested by loading different 17 * values into the condition register (mtcrf), moving its value 18 * to a general-purpose register (mfcr) and comparing this value 19 * with the expected one. 20 * The mcrxr instruction is tested by loading a fixed value 21 * into the XER register (mtspr), moving XER value to the 22 * condition register (mcrxr), moving it to a general-purpose 23 * register (mfcr) and comparing the value of this register with 24 * the expected one. 25 * The rest of instructions is tested by loading a fixed 26 * value into the condition register (mtcrf), executing each 27 * instruction several times to modify all 4-bit condition 28 * fields, moving the value of the conditional register to a 29 * general-purpose register (mfcr) and comparing it with the 30 * expected one. 31 */ 32 33 #include <post.h> 34 #include "cpu_asm.h" 35 36 #if CONFIG_POST & CONFIG_SYS_POST_CPU 37 38 extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); 39 extern void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3); 40 41 static ulong cpu_post_cr_table1[] = 42 { 43 0xaaaaaaaa, 44 0x55555555, 45 }; 46 static unsigned int cpu_post_cr_size1 = ARRAY_SIZE(cpu_post_cr_table1); 47 48 static struct cpu_post_cr_s2 { 49 ulong xer; 50 ulong cr; 51 } cpu_post_cr_table2[] = 52 { 53 { 54 0xa0000000, 55 1 56 }, 57 { 58 0x40000000, 59 5 60 }, 61 }; 62 static unsigned int cpu_post_cr_size2 = ARRAY_SIZE(cpu_post_cr_table2); 63 64 static struct cpu_post_cr_s3 { 65 ulong cr; 66 ulong cs; 67 ulong cd; 68 ulong res; 69 } cpu_post_cr_table3[] = 70 { 71 { 72 0x01234567, 73 0, 74 4, 75 0x01230567 76 }, 77 { 78 0x01234567, 79 7, 80 0, 81 0x71234567 82 }, 83 }; 84 static unsigned int cpu_post_cr_size3 = ARRAY_SIZE(cpu_post_cr_table3); 85 86 static struct cpu_post_cr_s4 { 87 ulong cmd; 88 ulong cr; 89 ulong op1; 90 ulong op2; 91 ulong op3; 92 ulong res; 93 } cpu_post_cr_table4[] = 94 { 95 { 96 OP_CRAND, 97 0x0000ffff, 98 0, 99 16, 100 0, 101 0x0000ffff 102 }, 103 { 104 OP_CRAND, 105 0x0000ffff, 106 16, 107 17, 108 0, 109 0x8000ffff 110 }, 111 { 112 OP_CRANDC, 113 0x0000ffff, 114 0, 115 16, 116 0, 117 0x0000ffff 118 }, 119 { 120 OP_CRANDC, 121 0x0000ffff, 122 16, 123 0, 124 0, 125 0x8000ffff 126 }, 127 { 128 OP_CROR, 129 0x0000ffff, 130 0, 131 16, 132 0, 133 0x8000ffff 134 }, 135 { 136 OP_CROR, 137 0x0000ffff, 138 0, 139 1, 140 0, 141 0x0000ffff 142 }, 143 { 144 OP_CRORC, 145 0x0000ffff, 146 0, 147 16, 148 0, 149 0x0000ffff 150 }, 151 { 152 OP_CRORC, 153 0x0000ffff, 154 0, 155 0, 156 0, 157 0x8000ffff 158 }, 159 { 160 OP_CRXOR, 161 0x0000ffff, 162 0, 163 0, 164 0, 165 0x0000ffff 166 }, 167 { 168 OP_CRXOR, 169 0x0000ffff, 170 0, 171 16, 172 0, 173 0x8000ffff 174 }, 175 { 176 OP_CRNAND, 177 0x0000ffff, 178 0, 179 16, 180 0, 181 0x8000ffff 182 }, 183 { 184 OP_CRNAND, 185 0x0000ffff, 186 16, 187 17, 188 0, 189 0x0000ffff 190 }, 191 { 192 OP_CRNOR, 193 0x0000ffff, 194 0, 195 16, 196 0, 197 0x0000ffff 198 }, 199 { 200 OP_CRNOR, 201 0x0000ffff, 202 0, 203 1, 204 0, 205 0x8000ffff 206 }, 207 { 208 OP_CREQV, 209 0x0000ffff, 210 0, 211 0, 212 0, 213 0x8000ffff 214 }, 215 { 216 OP_CREQV, 217 0x0000ffff, 218 0, 219 16, 220 0, 221 0x0000ffff 222 }, 223 }; 224 static unsigned int cpu_post_cr_size4 = ARRAY_SIZE(cpu_post_cr_table4); 225 226 int cpu_post_test_cr (void) 227 { 228 int ret = 0; 229 unsigned int i; 230 unsigned long cr_sav; 231 int flag = disable_interrupts(); 232 233 asm ( "mfcr %0" : "=r" (cr_sav) : ); 234 235 for (i = 0; i < cpu_post_cr_size1 && ret == 0; i++) 236 { 237 ulong cr = cpu_post_cr_table1[i]; 238 ulong res; 239 240 unsigned long code[] = 241 { 242 ASM_MTCR(3), 243 ASM_MFCR(3), 244 ASM_BLR, 245 }; 246 247 cpu_post_exec_11 (code, &res, cr); 248 249 ret = res == cr ? 0 : -1; 250 251 if (ret != 0) 252 { 253 post_log ("Error at cr1 test %d !\n", i); 254 } 255 } 256 257 for (i = 0; i < cpu_post_cr_size2 && ret == 0; i++) 258 { 259 struct cpu_post_cr_s2 *test = cpu_post_cr_table2 + i; 260 ulong res; 261 ulong xer; 262 263 unsigned long code[] = 264 { 265 ASM_MTXER(3), 266 ASM_MCRXR(test->cr), 267 ASM_MFCR(3), 268 ASM_MFXER(4), 269 ASM_BLR, 270 }; 271 272 cpu_post_exec_21x (code, &res, &xer, test->xer); 273 274 ret = xer == 0 && ((res << (4 * test->cr)) & 0xe0000000) == test->xer ? 275 0 : -1; 276 277 if (ret != 0) 278 { 279 post_log ("Error at cr2 test %d !\n", i); 280 } 281 } 282 283 for (i = 0; i < cpu_post_cr_size3 && ret == 0; i++) 284 { 285 struct cpu_post_cr_s3 *test = cpu_post_cr_table3 + i; 286 ulong res; 287 288 unsigned long code[] = 289 { 290 ASM_MTCR(3), 291 ASM_MCRF(test->cd, test->cs), 292 ASM_MFCR(3), 293 ASM_BLR, 294 }; 295 296 cpu_post_exec_11 (code, &res, test->cr); 297 298 ret = res == test->res ? 0 : -1; 299 300 if (ret != 0) 301 { 302 post_log ("Error at cr3 test %d !\n", i); 303 } 304 } 305 306 for (i = 0; i < cpu_post_cr_size4 && ret == 0; i++) 307 { 308 struct cpu_post_cr_s4 *test = cpu_post_cr_table4 + i; 309 ulong res; 310 311 unsigned long code[] = 312 { 313 ASM_MTCR(3), 314 ASM_12F(test->cmd, test->op3, test->op1, test->op2), 315 ASM_MFCR(3), 316 ASM_BLR, 317 }; 318 319 cpu_post_exec_11 (code, &res, test->cr); 320 321 ret = res == test->res ? 0 : -1; 322 323 if (ret != 0) 324 { 325 post_log ("Error at cr4 test %d !\n", i); 326 } 327 } 328 329 asm ( "mtcr %0" : : "r" (cr_sav)); 330 331 if (flag) 332 enable_interrupts(); 333 334 return ret; 335 } 336 337 #endif 338